| 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")) | ||
| #=============================================================================== |
| 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")) | ||
|
|
||
|
|
| 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")) | ||
|
|
||
|
|
||
|
|
| 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")) | ||
|
|
||
|
|
||
|
|
| 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 |
| 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")) | ||
|
|
| 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")) | ||
|
|
| 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 | ||
| ) |
| 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) |
| 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") | ||
| ) |
| 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.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
volaya
Author
Contributor
|
||
| 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)) | ||
| 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) |
| 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") | ||
|
|
| 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']) |
| 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) |
| 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() | ||
|
|
||
|
|
This should be changed to:
otherwise the import throws an error