Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

"""
***************************************************************************
__init__.py
OutputString.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Tim Sutton
Email : tim at linfiniti dot com
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
Expand All @@ -17,22 +17,18 @@
***************************************************************************
"""

__author__ = 'Tim Sutton'
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Tim Sutton'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

def name():
return "SEXTANTE example provider"
def description():
return "An example plugin that adds algorithms to SEXTANTE. Mainly created to guide developers in the process of creating plugins that add new capabilities to SEXTANTE"
def version():
return "Version 1.0"
def icon():
return "icon.png"
def qgisMinimumVersion():
return "1.0"
def classFactory(iface):
from sextanteexampleprovider.SextanteExampleProviderPlugin import SextanteExampleProviderPlugin
return SextanteExampleProviderPlugin()
from sextante.outputs.Output import Output

class OutputString(Output):

def __init__(self, name="", description=""):
self.name = name
self.description = description
self.value = None
self.hidden = True
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class PymorphAlgorithmProvider(AlgorithmProvider):

def __init__(self):
AlgorithmProvider.__init__(self)
#self.readAlgNames()
self.activate = False
self.createAlgsList()

def scriptsFolder(self):
Expand Down
4 changes: 3 additions & 1 deletion python/plugins/sextante/r/EditRScriptDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@ def editHelp(self):

def saveAlgorithm(self):
if self.filename is None:
self.filename = QtGui.QFileDialog.getSaveFileName(self, "Save Script", RUtils.RScriptsFolder(), "SEXTANTE R script (*.rsx)")
self.filename = QtGui.QFileDialog.getSaveFileName(self, "Save Script", RUtils.RScriptsFolder(), "SEXTANTE R script (*.rsx)")

if self.filename:
if not self.filename.endswith(".rsx"):
self.filename += ".rsx"
text = str(self.text.toPlainText())
if self.alg is not None:
self.alg.script = text
Expand Down
2 changes: 2 additions & 0 deletions python/plugins/sextante/script/EditScriptDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ def saveAlgorithm(self):
self.filename = QtGui.QFileDialog.getSaveFileName(self, "Save Script", ScriptUtils.scriptsFolder(), "Python scripts (*.py)")

if self.filename:
if not self.filename.endswith(".py"):
self.filename += ".py"
text = str(self.text.toPlainText())
if self.alg is not None:
self.alg.script = text
Expand Down
61 changes: 61 additions & 0 deletions python/plugins/sextante/servertools/CreateMosaicDatastore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#===============================================================================
# # -*- coding: utf-8 -*-
#
# """
# ***************************************************************************
# CreateMosaicDatastore.py
# ---------------------
# Date : October 2012
# Copyright : (C) 2012 by Victor Olaya
# Email : volayaf at gmail dot com
# ***************************************************************************
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation; either version 2 of the License, or *
# * (at your option) any later version. *
# * *
# ***************************************************************************
# """
# from sextante.core.LayerExporter import LayerExporter
# from sextante.parameters.ParameterString import ParameterString
# from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm
#
# __author__ = 'Victor Olaya'
# __date__ = 'October 2012'
# __copyright__ = '(C) 2012, Victor Olaya'
# # This will get replaced with a git SHA1 when you do a git archive
# __revision__ = '$Format:%H$'
#
# from qgis.core import *
# from sextante.parameters.ParameterVector import ParameterVector
# from sextante.core.QGisLayers import QGisLayers
# import os
#
# class CreateMosaicDatastore(GeoServerToolsAlgorithm):
#
# INPUT = "INPUT"
# WORKSPACE = "WORKSPACE"
#
# def processAlgorithm(self, progress):
# self.createCatalog()
# input = self.getParameterValue(self.INPUT)
# workspaceName = self.getParameterValue(self.WORKSPACE)
# connection = {
# 'shp': basepathname + '.shp',
# 'shx': basepathname + '.shx',
# 'dbf': basepathname + '.dbf',
# 'prj': basepathname + '.prj'
# }
#
# workspace = self.catalog.get_workspace(workspaceName)
# self.catalog.create_featurestore(basefilename, connection, workspace)
#
#
# def defineCharacteristics(self):
# self.addcaddBaseParameters()
# self.name = "Import into GeoServer"
# self.group = "GeoServer management tools"
# self.addParameter(ParameterVector(self.INPUT, "Layer to import", ParameterVector.VECTOR_TYPE_ANY))
# self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))
#===============================================================================
56 changes: 56 additions & 0 deletions python/plugins/sextante/servertools/CreateWorkspace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
CreateWorkspace.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm
from sextante.outputs.OutputString import OutputString

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import os
from qgis.core import *
from PyQt4 import QtGui
from sextante.parameters.ParameterString import ParameterString

class CreateWorkspace(GeoServerToolsAlgorithm):

WORKSPACE = "WORKSPACE"
WORKSPACEURI = "WORKSPACEURI"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/geoserver.png")

def processAlgorithm(self, progress):
self.createCatalog()
workspaceName = self.getParameterValue(self.WORKSPACE)
workspaceUri = self.getParameterValue(self.WORKSPACEURI)
self.catalog.create_workspace(workspaceName, workspaceUri)


def defineCharacteristics(self):
self.addBaseParameters()
self.name = "Create workspace"
self.group = "GeoServer management tools"
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))
self.addParameter(ParameterString(self.WORKSPACEURI, "Workspace URI"))
self.addOutput(OutputString(self.WORKSPACE, "Workspace"))


56 changes: 56 additions & 0 deletions python/plugins/sextante/servertools/DeleteDatastore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
DeleteDatastore.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import os
from qgis.core import *
from PyQt4 import QtGui
from sextante.parameters.ParameterString import ParameterString

class DeleteDatastore(GeoServerToolsAlgorithm):

DATASTORE = "DATASTORE"
WORKSPACE = "WORKSPACE"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/geoserver.png")

def processAlgorithm(self, progress):
self.createCatalog()
datastoreName = self.getParameterValue(self.DATASTORE)
workspaceName = self.getParameterValue(self.WORKSPACE)
ds = self.catalog.get_store(datastoreName, workspaceName)
self.catalog.delete(ds, recurse=True)


def defineCharacteristics(self):
self.addBaseParameters()
self.name = "Delete datastore"
self.group = "GeoServer management tools"
self.addParameter(ParameterString(self.DATASTORE, "Datastore name"))
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))



53 changes: 53 additions & 0 deletions python/plugins/sextante/servertools/DeleteWorkspace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
DeleteWorkspace.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import os
from qgis.core import *
from PyQt4 import QtGui
from sextante.parameters.ParameterString import ParameterString

class DeleteWorkspace(GeoServerToolsAlgorithm):

WORKSPACE = "WORKSPACE"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/geoserver.png")

def processAlgorithm(self, progress):
self.createCatalog()
workspaceName = self.getParameterValue(self.WORKSPACE)
ws = self.catalog.get_workspace(workspaceName)
self.catalog.delete(ws)


def defineCharacteristics(self):
self.addBaseParameters()
self.name = "Delete workspace"
self.group = "GeoServer management tools"
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))



52 changes: 52 additions & 0 deletions python/plugins/sextante/servertools/GeoServerToolsAlgorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
GeoserverToolsAlgorithm.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.parameters.ParameterString import ParameterString
from sextante.servertools.geoserver.catalog import Catalog

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import os
from PyQt4 import QtGui
from sextante.core.GeoAlgorithm import GeoAlgorithm

class GeoServerToolsAlgorithm(GeoAlgorithm):

URL = "URL"
USER = "USER"
PASSWORD = "PASSWORD"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/geoserver.png")

def addBaseParameters(self):
self.addParameter(ParameterString(self.URL, "URL", "http://localhost:8080/geoserver/rest"))
self.addParameter(ParameterString(self.USER, "User", "admin"))
self.addParameter(ParameterString(self.PASSWORD, "Password", "geoserver"))

def createCatalog(self):
url = self.getParameterValue(self.URL)
user = self.getParameterValue(self.USER)
password = self.getParameterValue(self.PASSWORD)
self.catalog = Catalog(url, user, password)


Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
GeoServerToolsAlgorithmProvider.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.servertools.CreateWorkspace import CreateWorkspace
from sextante.servertools.ImportVectorIntoGeoServer import ImportVectorIntoGeoServer
from sextante.servertools.ImportRasterIntoGeoServer import ImportRasterIntoGeoServer
from sextante.servertools.DeleteWorkspace import DeleteWorkspace
from sextante.servertools.DeleteDatastore import DeleteDatastore

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from sextante.core.AlgorithmProvider import AlgorithmProvider
from PyQt4 import QtGui
import os

class GeoServerToolsAlgorithmProvider(AlgorithmProvider):

def __init__(self):
AlgorithmProvider.__init__(self)
self.alglist = [ImportVectorIntoGeoServer(), ImportRasterIntoGeoServer(),
CreateWorkspace(), DeleteWorkspace(), DeleteDatastore()]#, CreateMosaicGeoserver(), StyleGeoserverLayer(), TruncateSeedGWC()]

def initializeSettings(self):
AlgorithmProvider.initializeSettings(self)


def unload(self):
AlgorithmProvider.unload(self)


def getName(self):
return "geoserver"

def getDescription(self):
return "Geoserver management tools"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/geoserver.png")

def _loadAlgorithms(self):
self.algs = self.alglist

def supportsNonFileBasedOutput(self):
return True
62 changes: 62 additions & 0 deletions python/plugins/sextante/servertools/ImportRasterIntoGeoServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
ImportVectorIntoGeoServer.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.core.LayerExporter import LayerExporter
from sextante.parameters.ParameterString import ParameterString
from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm
from sextante.parameters.ParameterRaster import ParameterRaster

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from qgis.core import *

class ImportRasterIntoGeoServer(GeoServerToolsAlgorithm):

INPUT = "INPUT"
WORKSPACE = "WORKSPACE"
NAME = "NAME"


def exportRasterLayer(self, inputFilename):
return inputFilename


def processAlgorithm(self, progress):
self.createCatalog()
inputFilename = self.getParameterValue(self.INPUT)
name = self.getParameterValue(self.NAME)
workspaceName = self.getParameterValue(self.WORKSPACE)
filename = self.exportRasterLayer(inputFilename)
workspace = self.catalog.get_workspace(workspaceName)
ds = self.catalog.create_coveragestore2(name, workspace)
ds.data_url = "file:" + filename;
self.catalog.save(ds)


def defineCharacteristics(self):
self.addBaseParameters()
self.name = "Import raster into GeoServer"
self.group = "GeoServer management tools"
self.addParameter(ParameterRaster(self.INPUT, "Layer to import"))
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))
self.addParameter(ParameterString(self.NAME, "Store name"))

64 changes: 64 additions & 0 deletions python/plugins/sextante/servertools/ImportVectorIntoGeoServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
ImportVectorIntoGeoServer.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from sextante.core.LayerExporter import LayerExporter
from sextante.parameters.ParameterString import ParameterString
from sextante.servertools.GeoServerToolsAlgorithm import GeoServerToolsAlgorithm

__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from qgis.core import *
from sextante.parameters.ParameterVector import ParameterVector
from sextante.core.QGisLayers import QGisLayers
import os

class ImportVectorIntoGeoServer(GeoServerToolsAlgorithm):

INPUT = "INPUT"
WORKSPACE = "WORKSPACE"

def processAlgorithm(self, progress):
self.createCatalog()
inputFilename = self.getParameterValue(self.INPUT)
layer = QGisLayers.getObjectFromUri(inputFilename)
workspaceName = self.getParameterValue(self.WORKSPACE)
filename = LayerExporter.exportVectorLayer(layer)
basefilename = os.path.basename(filename)
basepathname = os.path.dirname(filename) + os.sep + basefilename[:basefilename.find('.')]
connection = {
'shp': basepathname + '.shp',
'shx': basepathname + '.shx',
'dbf': basepathname + '.dbf',
'prj': basepathname + '.prj'
}

workspace = self.catalog.get_workspace(workspaceName)
self.catalog.create_featurestore(basefilename, connection, workspace)


def defineCharacteristics(self):
self.addBaseParameters()
self.name = "Import vector into GeoServer"
self.group = "GeoServer management tools"
self.addParameter(ParameterVector(self.INPUT, "Layer to import", ParameterVector.VECTOR_TYPE_ANY))
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))

Empty file.
Empty file.
504 changes: 504 additions & 0 deletions python/plugins/sextante/servertools/geoserver/catalog.py

Large diffs are not rendered by default.

132 changes: 132 additions & 0 deletions python/plugins/sextante/servertools/geoserver/layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from sextante.servertools.geoserver.support import ResourceInfo, xml_property, write_bool, url
from sextante.servertools.geoserver.style import Style

class _attribution(object):
def __init__(self, title, width, height):
self.title = title
self.width = width
self.height = height

def _read_attribution(node):
title = node.find("title")
width = node.find("logoWidth")
height = node.find("logoHeight")

if title is not None:
title = title.text
if width is not None:
width = width.text
if height is not None:
height = height.text

return _attribution(title, width, height)

def _write_attribution(builder, attr):
builder.start("attribution", dict())
if attr.title is not None:
builder.start("title", dict())
builder.data(attr.title)
builder.end("title")
if attr.width is not None:
builder.start("logoWidth", dict())
builder.data(attr.width)
builder.end("logoWidth")
if attr.height is not None:
builder.start("logoHeight", dict())
builder.data(attr.height)
builder.end("logoHeight")
builder.end("attribution")

def _write_default_style(builder, name):
builder.start("defaultStyle", dict())
if name is not None:
builder.start("name", dict())
builder.data(name)
builder.end("name")
builder.end("defaultStyle")


def _write_alternate_styles(builder, styles):
builder.start("styles", dict())
for s in styles:
builder.start("style", dict())
builder.start("name", dict())
builder.data(s.name)
builder.end("name")
builder.end("style")
builder.end("styles")


class Layer(ResourceInfo):
def __init__(self, catalog, name):
super(Layer, self).__init__()
self.catalog = catalog
self.name = name

resource_type = "layer"
save_method = "PUT"

@property
def href(self):
return url(self.catalog.service_url, ["layers", self.name + ".xml"])

@property
def resource(self):
if self.dom is None:
self.fetch()
name = self.dom.find("resource/name").text
return self.catalog.get_resource(name)

def _get_default_style(self):
if 'default_style' in self.dirty:
return self.dirty['default_style']
if self.dom is None:
self.fetch()
name = self.dom.find("defaultStyle/name")
# aborted data uploads can result in no default style
if name is not None:
return self.catalog.get_style(name.text)
else:
return None

def _set_default_style(self, style):
if isinstance(style, Style):
style = style.name
self.dirty["default_style"] = style

def _get_alternate_styles(self):
if "alternate_styles" in self.dirty:
return self.dirty["alternate_styles"]
if self.dom is None:
self.fetch()
styles = self.dom.findall("styles/style/name")
return [Style(self.catalog, s.text) for s in styles]

def _set_alternate_styles(self, styles):
self.dirty["alternate_styles"] = styles

default_style = property(_get_default_style, _set_default_style)
styles = property(_get_alternate_styles, _set_alternate_styles)

attribution_object = xml_property("attribution", _read_attribution)
enabled = xml_property("enabled", lambda x: x.text == "true")

def _get_attr_text(self):
return self.attribution_object.title

def _set_attr_text(self, text):
self.dirty["attribution"] = _attribution(
text,
self.attribution_object.width,
self.attribution_object.height
)
assert self.attribution_object.title == text

attribution = property(_get_attr_text, _set_attr_text)

writers = dict(
attribution = _write_attribution,
enabled = write_bool("enabled"),
default_style = _write_default_style,
alternate_styles = _write_alternate_styles
)
84 changes: 84 additions & 0 deletions python/plugins/sextante/servertools/geoserver/layergroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from sextante.servertools.geoserver.support import ResourceInfo, bbox, write_bbox, \
write_string, xml_property, url

def _maybe_text(n):
if n is None:
return None
else:
return n.text

def _layer_list(node):
if node is not None:
return [_maybe_text(n.find("name")) for n in node.findall("layer")]

def _style_list(node):
if node is not None:
return [_maybe_text(n.find("name")) for n in node.findall("style")]

def _write_layers(builder, layers):
builder.start("layers", dict())
for l in layers:
builder.start("layer", dict())
if l is not None:
builder.start("name", dict())
builder.data(l)
builder.end("name")
builder.end("layer")
builder.end("layers")

def _write_styles(builder, styles):
builder.start("styles", dict())
for s in styles:
builder.start("style", dict())
if s is not None:
builder.start("name", dict())
builder.data(s)
builder.end("name")
builder.end("style")
builder.end("styles")

class LayerGroup(ResourceInfo):
"""
Represents a layer group in geoserver
"""

resource_type = "layerGroup"
save_method = "PUT"

def __init__(self, catalog, name):
super(LayerGroup, self).__init__()

assert isinstance(name, basestring)

self.catalog = catalog
self.name = name

@property
def href(self):
return url(self.catalog.service_url, ["layergroups", self.name + ".xml"])

styles = xml_property("styles", _style_list)
layers = xml_property("layers", _layer_list)
bounds = xml_property("bounds", bbox)

writers = dict(
name = write_string("name"),
styles = _write_styles,
layers = _write_layers,
bounds = write_bbox("bounds")
)

def __str__(self):
return "<LayerGroup %s>" % self.name

__repr__ = __str__

class UnsavedLayerGroup(LayerGroup):
save_method = "POST"
def __init__(self, catalog, name, layers, styles, bounds):
super(UnsavedLayerGroup, self).__init__(catalog, name)
self.dirty.update(name = name, layers = layers, styles = styles, bounds = bounds)

@property
def href(self):
return "%s/layergroups?name=%s" % (self.catalog.service_url, self.name)
Empty file.
176 changes: 176 additions & 0 deletions python/plugins/sextante/servertools/geoserver/resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
from sextante.servertools.geoserver.support import ResourceInfo, xml_property, write_string, bbox, \
write_bbox, string_list, write_string_list, attribute_list, write_bool, url

def md_link(node):
"""Extract a metadata link tuple from an xml node"""
mimetype = node.find("type")
mdtype = node.find("metadataType")
content = node.find("content")
if None in [mimetype, mdtype, content]:
return None
else:
return (mimetype.text, mdtype.text, content.text)

def metadata_link_list(node):
if node is not None:
return [md_link(n) for n in node.findall("metadataLink")]

def write_metadata_link_list(name):
def write(builder, md_links):
builder.start(name, dict())
for (mime, md_type, content_url) in md_links:
builder.start("metadataLink", dict())
builder.start("type", dict())
builder.data(mime)
builder.end("type")
builder.start("metadataType", dict())
builder.data(md_type)
builder.end("metadataType")
builder.start("content", dict())
builder.data(content_url)
builder.end("content")
builder.end("metadataLink")
builder.end("metadataLinks")
return write

def featuretype_from_index(catalog, workspace, store, node):
name = node.find("name")
return FeatureType(catalog, workspace, store, name.text)

def coverage_from_index(catalog, workspace, store, node):
name = node.find("name")
return Coverage(catalog, workspace, store, name.text)

class FeatureType(ResourceInfo):
resource_type = "featureType"
save_method = "PUT"

def __init__(self, catalog, workspace, store, name):
super(FeatureType, self).__init__()

assert isinstance(store, ResourceInfo)
assert isinstance(name, basestring)

self.catalog = catalog
self.workspace = workspace
self.store = store
self.name = name

@property
def href(self):
return url(self.catalog.service_url,
["workspaces", self.workspace.name,
"datastores", self.store.name,
"featuretypes", self.name + ".xml"])

title = xml_property("title")
abstract = xml_property("abstract")
enabled = xml_property("enabled")
native_bbox = xml_property("nativeBoundingBox", bbox)
latlon_bbox = xml_property("latLonBoundingBox", bbox)
projection = xml_property("srs")
projection_policy = xml_property("projectionPolicy")
keywords = xml_property("keywords", string_list)
attributes = xml_property("attributes", attribute_list)
metadata_links = xml_property("metadataLinks", metadata_link_list)

writers = dict(
title = write_string("title"),
abstract = write_string("abstract"),
enabled = write_bool("enabled"),
nativeBoundingBox = write_bbox("nativeBoundingBox"),
latLonBoundingBox = write_bbox("latLonBoundingBox"),
srs = write_string("srs"),
projectionPolicy = write_string("projectionPolicy"),
keywords = write_string_list("keywords"),
metadataLinks = write_metadata_link_list("metadataLinks")
)

class CoverageDimension(object):
def __init__(self, name, description, dimension_range):
self.name = name
self.description = description
self.dimension_range = dimension_range

def coverage_dimension(node):
name = node.find("name")
name = name.text if name is not None else None
description = node.find("description")
description = description.text if description is not None else None
range_min = node.find("range/min")
range_max = node.find("range/max")
dimension_range = None
if None not in [min, max]:
dimension_range = float(range_min.text), float(range_max.text)
if None not in [name, description]:
return CoverageDimension(name, description, dimension_range)
else:
return None # should we bomb out more spectacularly here?

def coverage_dimension_xml(builder, dimension):
builder.start("coverageDimension", dict())
builder.start("name", dict())
builder.data(dimension.name)
builder.end("name")

builder.start("description", dict())
builder.data(dimension.description)
builder.end("description")

if dimension.range is not None:
builder.start("range", dict())
builder.start("min", dict())
builder.data(str(dimension.range[0]))
builder.end("min")
builder.start("max", dict())
builder.data(str(dimension.range[1]))
builder.end("max")
builder.end("range")

builder.end("coverageDimension")

class Coverage(ResourceInfo):
def __init__(self, catalog, workspace, store, name):
super(Coverage, self).__init__()
self.catalog = catalog
self.workspace = workspace
self.store = store
self.name = name

@property
def href(self):
return url(self.catalog.service_url,
["workspaces", self.workspace.name,
"coveragestores", self.store.name,
"coverages", self.name + ".xml"])

resource_type = "coverage"
save_method = "PUT"

title = xml_property("title")
abstract = xml_property("abstract")
enabled = xml_property("enabled")
native_bbox = xml_property("nativeBoundingBox", bbox)
latlon_bbox = xml_property("latLonBoundingBox", bbox)
projection = xml_property("srs")
projection_policy = xml_property("projectionPolicy")
keywords = xml_property("keywords", string_list)
request_srs_list = xml_property("requestSRS", string_list)
response_srs_list = xml_property("responseSRS", string_list)
supported_formats = xml_property("supportedFormats", string_list)
metadata_links = xml_property("metadataLinks", metadata_link_list)

writers = dict(
title = write_string("title"),
abstract = write_string("abstract"),
enabled = write_bool("enabled"),
nativeBoundingBox = write_bbox("nativeBoundingBox"),
latLonBoundingBox = write_bbox("latLonBoundingBox"),
srs = write_string("srs"),
projection_policy = write_string("projectionPolicy"),
keywords = write_string_list("keywords"),
metadataLinks = write_metadata_link_list("metadataLinks"),
requestSRS = write_string_list("requestSRS"),
responseSRS = write_string_list("responseSRS"),
supportedFormats = write_string_list("supportedFormats")
)
117 changes: 117 additions & 0 deletions python/plugins/sextante/servertools/geoserver/store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import sextante.servertools.geoserver.workspace as ws

This comment has been minimized.

Copy link
@slarosa

slarosa Nov 5, 2012

Member

This should be changed to:

from sextante.servertools.geoserver import workspace as ws

otherwise the import throws an error

This comment has been minimized.

Copy link
@volaya

volaya Nov 5, 2012

Author Contributor

Any idea why that happens?

I do not have that error, and that code belongs to the gsconfig.py library, which is used in GeoNode like that. I'd prefer no to change this code, since it is not my own code, so as to make changing to a new version easier by just using the original code. Any suggestions?thanks!

This comment has been minimized.

Copy link
@slarosa

slarosa Nov 6, 2012

Member

Rigth now, no idea !
I get this:

    import sextante.servertools.geoserver.workspace as ws
AttributeError: 'module' object has no attribute 'geoserver'
from sextante.servertools.geoserver.resource import featuretype_from_index, coverage_from_index
from sextante.servertools.geoserver.support import ResourceInfo, xml_property, key_value_pairs, \
write_bool, write_dict, write_string, url

def datastore_from_index(catalog, workspace, node):
name = node.find("name")
return DataStore(catalog, workspace, name.text)

def coveragestore_from_index(catalog, workspace, node):
name = node.find("name")
return CoverageStore(catalog, workspace, name.text)

class DataStore(ResourceInfo):
resource_type = "dataStore"
save_method = "PUT"

def __init__(self, catalog, workspace, name):
super(DataStore, self).__init__()

assert isinstance(workspace, ws.Workspace)
assert isinstance(name, basestring)
self.catalog = catalog
self.workspace = workspace
self.name = name

@property
def href(self):
return url(self.catalog.service_url,
["workspaces", self.workspace.name, "datastores", self.name + ".xml"])

enabled = xml_property("enabled", lambda x: x.text == "true")
name = xml_property("name")
connection_parameters = xml_property("connectionParameters", key_value_pairs)

writers = dict(enabled = write_bool("enabled"),
name = write_string("name"),
connectionParameters = write_dict("connectionParameters"))


def get_resources(self):
res_url = url(self.catalog.service_url,
["workspaces", self.workspace.name, "datastores", self.name, "featuretypes.xml"])
xml = self.catalog.get_xml(res_url)
def ft_from_node(node):
return featuretype_from_index(self.catalog, self.workspace, self, node)

return [ft_from_node(node) for node in xml.findall("featureType")]

class UnsavedDataStore(DataStore):
save_method = "POST"

def __init__(self, catalog, name, workspace):
super(UnsavedDataStore, self).__init__(catalog, workspace, name)
self.dirty.update(dict(
name=name, enabled=True, connectionParameters=dict()))

@property
def href(self):
path = [ "workspaces",
self.workspace.name, "datastores"]
query = dict(name=self.name)
return url(self.catalog.service_url, path, query)

class CoverageStore(ResourceInfo):
resource_type = 'coverageStore'
save_method = "PUT"

def __init__(self, catalog, workspace, name):
super(CoverageStore, self).__init__()

assert isinstance(workspace, ws.Workspace)
assert isinstance(name, basestring)

self.catalog = catalog
self.workspace = workspace
self.name = name

@property
def href(self):
return url(self.catalog.service_url,
["workspaces", self.workspace.name, "coveragestores", self.name + ".xml"])

enabled = xml_property("enabled", lambda x: x.text == "true")
name = xml_property("name")
url = xml_property("url")
type = xml_property("type")

writers = dict(enabled = write_bool("enabled"),
name = write_string("name"),
url = write_string("url"),
type = write_string("type"))


def get_resources(self):
res_url = url(self.catalog.service_url,
["workspaces", self.workspace.name, "coveragestores", self.name, "coverages.xml"])

xml = self.catalog.get_xml(res_url)

def cov_from_node(node):
return coverage_from_index(self.catalog, self.workspace, self, node)

return [cov_from_node(node) for node in xml.findall("coverage")]

class UnsavedCoverageStore(CoverageStore):
save_method = "POST"

def __init__(self, catalog, name, workspace):
super(UnsavedCoverageStore, self).__init__(catalog, workspace, name)
self.dirty.update(name=name, enabled = True, type="GeoTIFF",
url = "file:data/")

@property
def href(self):
return url(self.catalog.service_url,
["workspaces", self.workspace.name, "coveragestores"], dict(name=self.name))
46 changes: 46 additions & 0 deletions python/plugins/sextante/servertools/geoserver/style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from sextante.servertools.geoserver.support import ResourceInfo, url, xml_property

class Style(ResourceInfo):
def __init__(self, catalog, name):
super(Style, self).__init__()
assert isinstance(name, basestring)

self.catalog = catalog
self.name = name
self._sld_dom = None

@property
def href(self):
return url(self.catalog.service_url, ["styles", self.name + ".xml"])

def body_href(self):
return url(self.catalog.service_url, ["styles", self.name + ".sld"])

filename = xml_property("filename")

def _get_sld_dom(self):
if self._sld_dom is None:
self._sld_dom = self.catalog.get_xml(self.body_href())
return self._sld_dom

@property
def sld_title(self):
user_style = self._get_sld_dom().find("{http://www.opengis.net/sld}NamedLayer/{http://www.opengis.net/sld}UserStyle")
title_node = user_style.find("{http://www.opengis.net/sld}Title")
return title_node.text if title_node is not None else None

@property
def sld_name(self):
user_style = self._get_sld_dom().find("{http://www.opengis.net/sld}NamedLayer/{http://www.opengis.net/sld}UserStyle")
name_node = user_style.find("{http://www.opengis.net/sld}Name")
return name_node.text if name_node is not None else None

@property
def sld_body(self):
content = self.catalog.http.request(self.body_href())[1]
return content

def update_body(self, body):
headers = { "Content-Type": "application/vnd.ogc.sld+xml" }
self.catalog.http.request(
self.body_href(), "PUT", body, headers)
218 changes: 218 additions & 0 deletions python/plugins/sextante/servertools/geoserver/support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import logging
from xml.etree.ElementTree import TreeBuilder, tostring
import urllib
import urlparse
from zipfile import ZipFile
from sextante.core.SextanteUtils import SextanteUtils


logger = logging.getLogger("gsconfig.support")

FORCE_DECLARED = "FORCE_DECLARED"
## The projection handling policy for layers that should use coordinates
## directly while reporting the configured projection to clients. This should be
## used when projection information is missing from the underlying datastore.


FORCE_NATIVE = "FORCE_NATIVE"
## The projection handling policy for layers that should use the projection
## information from the underlying storage mechanism directly, and ignore the
## projection setting.

REPROJECT = "REPROJECT"
## The projection handling policy for layers that should use the projection
## information from the underlying storage mechanism to reproject to the
## configured projection.

def url(base, seg, query=None):
"""
Create a URL from a list of path segments and an optional dict of query
parameters.
"""

seg = (urllib.quote(s.strip('/')) for s in seg)
if query is None or len(query) == 0:
query_string = ''
else:
query_string = "?" + urllib.urlencode(query)
path = '/'.join(seg) + query_string
adjusted_base = base.rstrip('/') + '/'
return urlparse.urljoin(adjusted_base, path)

def xml_property(path, converter = lambda x: x.text):
def getter(self):
if path in self.dirty:
return self.dirty[path]
else:
if self.dom is None:
self.fetch()
node = self.dom.find(path)
return converter(self.dom.find(path)) if node is not None else None

def setter(self, value):
self.dirty[path] = value

def delete(self):
self.dirty[path] = None

return property(getter, setter, delete)

def bbox(node):
if node is not None:
minx = node.find("minx")
maxx = node.find("maxx")
miny = node.find("miny")
maxy = node.find("maxy")
crs = node.find("crs")
crs = crs.text if crs is not None else None

if (None not in [minx, maxx, miny, maxy]):
return (minx.text, maxx.text, miny.text, maxy.text, crs)
else:
return None
else:
return None

def string_list(node):
if node is not None:
return [n.text for n in node.findall("string")]

def attribute_list(node):
if node is not None:
return [n.text for n in node.findall("attribute/name")]

def key_value_pairs(node):
if node is not None:
return dict((entry.attrib['key'], entry.text) for entry in node.findall("entry"))

def write_string(name):
def write(builder, value):
builder.start(name, dict())
if (value is not None):
builder.data(value)
builder.end(name)
return write

def write_bool(name):
def write(builder, b):
builder.start(name, dict())
builder.data("true" if b else "false")
builder.end(name)
return write

def write_bbox(name):
def write(builder, b):
builder.start(name, dict())
bbox_xml(builder, b)
builder.end(name)
return write

def write_string_list(name):
def write(builder, words):
builder.start(name, dict())
for w in words:
builder.start("string", dict())
builder.data(w)
builder.end("string")
builder.end(name)
return write

def write_dict(name):
def write(builder, pairs):
builder.start(name, dict())
for k, v in pairs.iteritems():
builder.start("entry", dict(key=k))
builder.data(v)
builder.end("entry")
builder.end(name)
return write

class ResourceInfo(object):
def __init__(self):
self.dom = None
self.dirty = dict()

def fetch(self):
self.dom = self.catalog.get_xml(self.href)

def clear(self):
self.dirty = dict()

def refresh(self):
self.clear()
self.fetch()

def serialize(self, builder):
# GeoServer will disable the resource if we omit the <enabled> tag,
# so force it into the dirty dict before writing
if hasattr(self, "enabled"):
self.dirty['enabled'] = self.enabled

for k, writer in self.writers.items():
if k in self.dirty:
writer(builder, self.dirty[k])

def message(self):
builder = TreeBuilder()
builder.start(self.resource_type, dict())
self.serialize(builder)
builder.end(self.resource_type)
msg = tostring(builder.close())
return msg

def prepare_upload_bundle(name, data):
"""GeoServer's REST API uses ZIP archives as containers for file formats such
as Shapefile and WorldImage which include several 'boxcar' files alongside
the main data. In such archives, GeoServer assumes that all of the relevant
files will have the same base name and appropriate extensions, and live in
the root of the ZIP archive. This method produces a zip file that matches
these expectations, based on a basename, and a dict of extensions to paths or
file-like objects. The client code is responsible for deleting the zip
archive when it's done."""
#we ut the zip file in the sextante temp dir, so it is deleted at the end.
f = SextanteUtils.getTempFilename('zip')
zip_file = ZipFile(f, 'w')
for ext, stream in data.iteritems():
fname = "%s.%s" % (name, ext)
if (isinstance(stream, basestring)):
zip_file.write(stream, fname)
else:
zip_file.writestr(fname, stream.read())
zip_file.close()
return f

def atom_link(node):
if 'href' in node.attrib:
return node.attrib['href']
else:
l = node.find("{http://www.w3.org/2005/Atom}link")
return l.get('href')

def atom_link_xml(builder, href):
builder.start("atom:link", {
'rel': 'alternate',
'href': href,
'type': 'application/xml',
'xmlns:atom': 'http://www.w3.org/2005/Atom'
})
builder.end("atom:link")

def bbox_xml(builder, box):
minx, maxx, miny, maxy, crs = box
builder.start("minx", dict())
builder.data(minx)
builder.end("minx")
builder.start("maxx", dict())
builder.data(maxx)
builder.end("maxx")
builder.start("miny", dict())
builder.data(miny)
builder.end("miny")
builder.start("maxy", dict())
builder.data(maxy)
builder.end("maxy")
if crs is not None:
builder.start("crs", {"class": "projected"})
builder.data(crs)
builder.end("crs")

5 changes: 5 additions & 0 deletions python/plugins/sextante/servertools/geoserver/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# shapefile_and_friends = None
# shapefile_plus_sidecars = shapefile_and_friends("test/data/states")

def shapefile_and_friends(path):
return dict((ext, path + "." + ext) for ext in ['shx', 'shp', 'dbf', 'prj'])
33 changes: 33 additions & 0 deletions python/plugins/sextante/servertools/geoserver/workspace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from sextante.servertools.geoserver.support import xml_property, write_bool, ResourceInfo, url

def workspace_from_index(catalog, node):
name = node.find("name")
return Workspace(catalog, name.text)

class Workspace(ResourceInfo):
resource_type = "workspace"

def __init__(self, catalog, name):
super(Workspace, self).__init__()
self.catalog = catalog
self.name = name

@property
def href(self):
return url(self.catalog.service_url, ["workspaces", self.name + ".xml"])

@property
def coveragestore_url(self):
return url(self.catalog.service_url, ["workspaces", self.name, "coveragestores.xml"])

@property
def datastore_url(self):
return url(self.catalog.service_url, ["workspaces", self.name, "datastores.xml"])

enabled = xml_property("enabled", lambda x: x.lower() == 'true')
writers = dict(
enabled = write_bool("enabled")
)

def __repr__(self):
return "%s @ %s" % (self.name, self.href)
1,675 changes: 1,675 additions & 0 deletions python/plugins/sextante/servertools/httplib2/__init__.py

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions python/plugins/sextante/servertools/httplib2/iri2uri.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""
iri2uri
Converts an IRI to a URI.
"""
__author__ = "Joe Gregorio (joe@bitworking.org)"
__copyright__ = "Copyright 2006, Joe Gregorio"
__contributors__ = []
__version__ = "1.0.0"
__license__ = "MIT"
__history__ = """
"""

import urlparse


# Convert an IRI to a URI following the rules in RFC 3987
#
# The characters we need to enocde and escape are defined in the spec:
#
# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
# / %xD0000-DFFFD / %xE1000-EFFFD

escape_range = [
(0xA0, 0xD7FF ),
(0xE000, 0xF8FF ),
(0xF900, 0xFDCF ),
(0xFDF0, 0xFFEF),
(0x10000, 0x1FFFD ),
(0x20000, 0x2FFFD ),
(0x30000, 0x3FFFD),
(0x40000, 0x4FFFD ),
(0x50000, 0x5FFFD ),
(0x60000, 0x6FFFD),
(0x70000, 0x7FFFD ),
(0x80000, 0x8FFFD ),
(0x90000, 0x9FFFD),
(0xA0000, 0xAFFFD ),
(0xB0000, 0xBFFFD ),
(0xC0000, 0xCFFFD),
(0xD0000, 0xDFFFD ),
(0xE1000, 0xEFFFD),
(0xF0000, 0xFFFFD ),
(0x100000, 0x10FFFD)
]

def encode(c):
retval = c
i = ord(c)
for low, high in escape_range:
if i < low:
break
if i >= low and i <= high:
retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')])
break
return retval


def iri2uri(uri):
"""Convert an IRI to a URI. Note that IRIs must be
passed in a unicode strings. That is, do not utf-8 encode
the IRI before passing it into the function."""
if isinstance(uri ,unicode):
(scheme, authority, path, query, fragment) = urlparse.urlsplit(uri)
authority = authority.encode('idna')
# For each character in 'ucschar' or 'iprivate'
# 1. encode as utf-8
# 2. then %-encode each octet of that utf-8
uri = urlparse.urlunsplit((scheme, authority, path, query, fragment))
uri = "".join([encode(c) for c in uri])
return uri

if __name__ == "__main__":
import unittest

class Test(unittest.TestCase):

def test_uris(self):
"""Test that URIs are invariant under the transformation."""
invariant = [
u"ftp://ftp.is.co.za/rfc/rfc1808.txt",
u"http://www.ietf.org/rfc/rfc2396.txt",
u"ldap://[2001:db8::7]/c=GB?objectClass?one",
u"mailto:John.Doe@example.com",
u"news:comp.infosystems.www.servers.unix",
u"tel:+1-816-555-1212",
u"telnet://192.0.2.16:80/",
u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ]
for uri in invariant:
self.assertEqual(uri, iri2uri(uri))

def test_iri(self):
""" Test that the right type of escaping is done for each part of the URI."""
self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}"))
self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}"))
self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}"))
self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}"))
self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))
self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")))
self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8')))

unittest.main()


438 changes: 438 additions & 0 deletions python/plugins/sextante/servertools/httplib2/socks.py

Large diffs are not rendered by default.

104 changes: 0 additions & 104 deletions python/plugins/sextanteexampleprovider/ExampleAlgorithm.py

This file was deleted.

78 changes: 0 additions & 78 deletions python/plugins/sextanteexampleprovider/ExampleAlgorithmProvider.py

This file was deleted.

This file was deleted.

11 changes: 0 additions & 11 deletions python/plugins/sextanteexampleprovider/metadata.txt

This file was deleted.