Sfoglia il codice sorgente

Initial import of the www branch

Jachym Cepicky 13 anni fa
parent
commit
a6b5a8824c

+ 130 - 0
Makefile

@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Proxy4OWS.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Proxy4OWS.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/Proxy4OWS"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Proxy4OWS"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	make -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

+ 0 - 411
OWS.py

@@ -1,411 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-import urlparse
-import urllib
-from lxml import objectify
-try:
-    from lxml import etree
-except:
-    from xml.etree import ElementTree as etree
-
-import os,sys
-import tempfile
-import logging
-import ConfigParser
-import md5
-import mapscript
-from string import Template
-from osgeo import osr
-from osgeo import ogr
-import OWSExceptions
-from owslib import crs as CRS
-import shutil
-
-class OWS:
-
-    capabilities = None
-    url = None
-    requestUrl = None
-    mapobj = None
-    qstring = None
-    owsns11 = "http://www.opengis.net/ows/1.1"
-    owsns = "http://www.opengis.net/ows"
-    cachedir = None
-    mapfileName = "mapfile.map"
-    config = None
-    parsedUrl = None
-    service = None
-    mapfilename = None
-
-    def __init__(self,url=None,qstring=None,configFile=None):
-        self.requestUrl = url
-        configFiles = [ os.path.join(os.path.dirname(__file__),"config.cfg") ]
-
-        if sys.platform == "win32":
-            pass # TODO Default conf. file on windows platform
-        elif sys.platform == "linux2":
-            configFiles.append("/etc/owsviewer.cfg")
-
-        if configFile:
-            configFiles.append(configFile)
-
-        self.config = ConfigParser.ConfigParser()
-        self.config.read(configFiles)
-
-        logging.debug("Creating cachedir for %s in %s" % (self.url,self.config.get("Proxy4OWS","cachedir")))
-        logging.debug("%s initialized"%self.service)
-
-        if url:
-            self.url = url
-            logging.debug("OWS.py::__init__()::url: '%s'" % url)
-            self.__getCapabilities()
-        if qstring:
-            self.qstring = qstring
-
-
-    def __getCapabilities(self):
-        self.__getCacheDir()
-        logging.debug("OWS.py::__getCapabilities::self.url: '%s'" % self.url)
-        self.parsedUrl = urlparse.urlparse(self.url)
-
-        if self.service == "WFS":
-            from owslib.wfs import WebFeatureService
-            # FIXME Make default version configurable
-            try:
-                self.capabilities = WebFeatureService(url=self.url,version="1.0.0")
-            except:
-                self.capabilities = WebFeatureService(url=self.url,version="1.1.0")
-
-        elif self.service == "WCS":
-            from owslib.wcs import WebCoverageService
-            self.capabilities = WebCoverageService(url=self.url,version="1.0.0")
-
-    def getParams(self):
-        params =  urlparse.parse_qs(self.qstring)
-
-        if not "VERSION" in params.keys() and "version" in params.keys():
-            params["VERSION"] = params.pop("version")
-        if not "LAYERS" in params.keys() and "layers" in params.keys():
-            params["LAYERS"] = params.pop("layers")
-        if not "FORMAT" in params.keys() and "format" in params.keys():
-            params["FORMAT"] = params.pop("format")
-        if not "STYLES" in params.keys() and "styles" in params.keys():
-            params["STYLES"] = params.pop("styles")
-        else:
-            params["STYLES"] = ['']
-        if not "TRANSPARENT" in params.keys() and "transparent" in params.keys():
-            params["TRANSPARENT"] = params.pop("transparent")
-        return params
-
-    def getOnlineResource(self,onlineresource,mapfilename=None):
-        o = urlparse.urlparse(onlineresource)
-        params = urlparse.parse_qs(o.query,keep_blank_values=True)
-        params["owsUrl"] = self.url
-        params["owsService"] = self.service
-        params["map"] = self.getMapfileLocation(mapfilename)
-
-        location = urlparse.urlunparse((o[0],o[1],o[2],o[3],urllib.urlencode(params,True),o[5]))
-        logging.debug("Setting OnlineResource to %s"% location)
-        return location
-
-    def getMapfileLocation(self,mapfilename=None):
-
-        # save the map if possible
-        if mapfilename:
-            mapfilename.replace("..","") # remove potential path change
-
-            # mapfile must end with .map and cachedir must be at the
-            # beginning of the mapfile name
-            if mapfilename.endswith(".map") and \
-               mapfilename.find(self.cachedir) == 0:
-                    return mapfilename
-                    
-            else:
-                # do not save anything
-                return
-        # save to new location otherwice
-        else:
-            return os.path.join(self.cachedir,self.mapfileName)
-
-    def __getCacheDir(self):
-        
-        dirname = os.path.join(self.config.get("Proxy4OWS","cachedir"),
-                                "%s-%s" % (self.service, md5.new(self.url).hexdigest()))
-
-        self.cachedir = dirname
-
-        # get existing cache dir
-        if not os.path.isdir(dirname):
-            os.mkdir(dirname)
-            logging.debug("Cachedir %s created" % dirname)
-            os.chmod(dirname,  0777)
-            open(os.path.join(self.cachedir,"url.txt"),"w").write(self.url)
-        else:
-            logging.debug("Cachedir %s found" % dirname)
-
-
-        return self.cachedir
-
-    def dispatch(self):
-        """Dispatch given request
-        """
-        request = mapscript.OWSRequest()
-        request.loadParams()
-        mapobj = None
-
-        self.request=request.getValueByName("REQUEST")
-
-        # if no 'map' parameter in URL, create new mapfile
-        if not request.getValueByName("map"):
-            logging.debug("Creating new mapfile")
-            mapobj = self.makeMap()
-        else:
-            # there is 'map' parameter in URL and the file exists, load it
-            logging.debug("Using existing mapfile %s" % request.getValueByName("map"))
-            if os.path.isfile(request.getValueByName("map")):
-                mapobj = mapscript.mapObj(request.getValueByName("map"))
-            # there is 'map' parameter in URL BUT the file does not exist:
-            # create
-            else:
-                mapobj = self.makeMap(request.getValueByName("map"))
-
-        # WFS Filter encoding, if available
-        if request.getValueByName("fes"):
-            self.setFilter(mapobj,request)
-
-        # mapobj.getLayerByName(request.getValueByName("layers")).metadata.get("wfs_filter")
-        # here is still fine, but it fails on dispatch:
-        res = mapobj.OWSDispatch(request)
-        if mapscript.MS_DONE == res:
-            raise OWSExceptions.NoValidRequest("No valid OWS Request")
-        elif mapscript.MS_FAILURE == res:
-            pass
-            #raise OWSExceptions.RequestFailed("Request failed")
-
-    def getMapObj(self,mapfilename=None):
-
-
-        if self.url is not None and self.capabilities is None:
-            self.__getCapabilities()
-
-        # nothing has changed in the capabilities document since last
-        # request ?
-        if os.path.exists(os.path.join(self.cachedir,"capabilities.xml")) and\
-            "_capabilities" in dir(self.capabilities):
-            oldCapsFile = open(os.path.join(self.cachedir,"capabilities.xml"))
-            oldCaps = oldCapsFile.read()
-            oldCapsFile.close()
-            # the capabilities document is up-to-date, load existing
-            # mapfile
-            newXml = etree.tostring(self.capabilities._capabilities)
-            if md5.new(oldCaps).hexdigest() == md5.new(newXml).hexdigest():
-                newCapsFile = open(os.path.join(self.cachedir,"capabilities.xml"),"w")
-                newCapsFile.write(newXml)
-                mapfilename = self.getMapfileLocation()
-                if os.path.exists(mapfilename):
-                    logging.debug("Capabilities unchanged, using existing mapfile %s" % self.getMapfileLocation())
-                    return mapscript.mapObj(mapfilename)
-                
-
-        # finally
-
-        # clear existing cached files
-        logging.debug("Cached capabilities document is outdated, creating new one")
-        shutil.rmtree(self.cachedir)
-        # reate new one
-        self.__getCacheDir()
-        return self._createNewMapObj(mapfilename)
-
-
-    def _createNewMapObj(self,mapfilename=None):
-
-        mapobj = mapscript.mapObj()
-
-        mapobj.setMetaData("wms_onlineresource",self.getOnlineResource(self.config.get("MapServer","onlineresource"),mapfilename))
-
-        logging.debug("Setting SRS to %s"%self.config.get("MapServer","srs"))
-        mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
-
-        mapobj.setProjection("init=epsg:4326")
-        mapobj.setSize(500,500)
-        mapobj.setExtent(-180,-90,90,180)
-        mapobj.shapepath = self.cachedir
-        mapobj.setMetaData("wms_encoding","utf-8")
-
-        errfile = self.config.get("MapServer","errorfile")
-        logging.debug("Setting ERRORFILE to %s"%errfile)
-        if not os.path.exists(errfile) and errfile != "stderr":
-            tmp = open(errfile,"w")
-            tmp.close()
-
-        # file
-        if os.access(errfile, os.W_OK):
-            mapobj.setConfigOption("MS_ERRORFILE",errfile)
-        # stderr
-        elif errfile == "stderr":
-            mapobj.setConfigOption("MS_ERRORFILE",errfile)
-        # no error file set
-        else:
-            logging.warning("Cannot set ERRORFILE to %s: %s " % (errfile,"Write access denided"))
-
-        logging.debug("Setting IMAGEPATH to %s"%self.config.get("MapServer","imagepath"))
-        mapobj.web.imagepath=self.config.get("MapServer","imagepath")
-
-        mapobj.setMetaData("ows_enable_request","*")
-
-        return mapobj
-
-    def saveMapfile(self,mapobj,mapfilename):
-
-        self.mapfilename = self.getMapfileLocation(mapfilename)
-        if self.mapfilename:
-
-            # save mapfile ONLY if GetCapabilities requested - it makes no
-            # sense for other cases
-            logging.info("Saving mapfile to %s" %  self.mapfilename)
-            mapobj.save(self.mapfilename)
-
-            # cache capabilities document
-            if "_capabilities" in dir(self.capabilities):
-                logging.info("Saving service Capabilities to %s" % os.path.join(self.cachedir,"capabilities.xml"))
-                open(os.path.join(self.cachedir,"capabilities.xml"),"w").write(etree.tostring(self.capabilities._capabilities))
-
-        else:
-            logging.info("Mapfile NOT saved")
-
-        return self.mapfilename
-
-    def getLayerUrl(self):
-
-        layerurl = self.url
-
-        if self.url.find("?") > -1:
-            if not self.url.endswith("?") and\
-                not self.url.endswith("&"):
-                layerurl += "&"
-        else:
-            layerurl += "?"
-
-        return layerurl
-
-    def createLayerDefinitionFile(self, name,
-            templatefile,time="",target=None):
-
-            layerurl = self.getLayerUrl()
-            defFileName = None
-            if target:
-                defFileName = target
-            else:
-                defFileName = os.path.join(self.cachedir,'%s.%s'%(name,self.service.lower()))
-            if time:
-                time = "<DefaultTime>"+time+"</DefaultTime>"
-
-            if not os.path.isfile(defFileName):
-                open(defFileName,'w').write(
-                        Template(open(templatefile).read()).substitute( 
-                                dict(url= layerurl,
-                                    name=name,time=time,extras="&BAND=1,2,3")))
-                                # FIXME always takes band 1,2,3 ^^
-
-                logging.debug("Created %s layer definition file" % defFileName)
-            else:
-                logging.debug("Using existing layer definition file %s" % defFileName)
-
-            return defFileName
-
-    def getLayerExtent(self,layer,crs=None):
-        """Get extent of layer in form of minx, miny, maxx,maxy
-        
-        :returns: [minx, miny, maxx, maxy]
-        """
-
-        bbox = None
-        if layer.boundingBoxWGS84:
-
-            dest = osr.SpatialReference()
-            dest.ImportFromEPSG(crs.code)
-
-            source = osr.SpatialReference()
-            source.ImportFromEPSG(4326)
-
-            bbox = []
-
-            # TODO rewrite this using ogr CoordinateTransformation
-            # http://www.gdal.org/ogr/osr_tutorial.html
-            # WELL: it does NOT seem to be THAT better
-            geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[0],layer.boundingBoxWGS84[1]),source)
-            geom.TransformTo(dest)
-            bbox.append(geom.GetX())
-            bbox.append(geom.GetY())
-
-            geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[2],layer.boundingBoxWGS84[3]),source)
-            geom.TransformTo(dest)
-            bbox.append(geom.GetX())
-            bbox.append(geom.GetY())
-
-            logging.debug("Setting extent for layer <%s> to %s" %\
-                    (layer.id,bbox))
-        return bbox
-
-    def setFilter(self,mapobj,request):
-        """ Set WFS filter encoding 
-        """
-        # get the layer
-        layerobj = mapobj.getLayerByName(request.getValueByName("layers"))
-
-        # get the filter
-        fes = request.getValueByName("fes")
-        logging.debug("FES received from HSLayers: %s" % fes)
-
-        # cut off the opening and closing <Filter> tag
-        # - this is needed for mapserver
-        #root = etree.XML(fes)
-        #msFilter = ""
-        #for child in root:
-        #    msFilter += etree.tostring(child)
-        #logging.debug("Setting the filter %s" % msFilter)
-
-        # set the filter
-        layerobj.setMetaData("wfs_filter",fes)
-        #layerobj.setMetaData("wfs_filter",msFilter)
-
-        # save the mapfile - debugging
-        mapobj.save("mapfile.fes")
-
-
-def getService(configFile=None):
-
-    qstring = os.environ["QUERY_STRING"]
-    params = urlparse.parse_qs(qstring)
-
-    for p in params:
-        if p.lower() == "owsurl":
-            v = params[p]
-            del params[p]
-            params["owsUrl"] = v
-
-        if p.lower() == "owsservice":
-            v = params[p]
-            del params[p]
-            params["owsService"] = v
-
-    
-    if "owsUrl" in params.keys() and\
-        "owsService" in params.keys():
-        owsUrl = urllib.unquote(params["owsUrl"][0])
-
-        if params["owsService"][0].lower() == "wfs":
-            from wfs import WFS
-            logging.debug("OWS.py::getService()::owsUrl: '%s'" % owsUrl)
-            return WFS(owsUrl,qstring,configFile = configFile )
-        elif params["owsService"][0].lower() == "wcs":
-            from wcs import WCS
-            return WCS(owsUrl,qstring, configFile = configFile)
-        elif params["owsService"][0].lower() == "wms":
-            from wms import WMS
-            return WMS(owsUrl,qstring, configFile = configFile)
-    else:
-        raise OWSExceptions.MissingParameterValue("""owsUrl or owsService""")
-    
-

+ 0 - 24
OWSExceptions.py

@@ -1,24 +0,0 @@
-class OWSException(Exception):
-    pass
-
-class WMSException(OWSException):
-    def toXml(self):
-        print  """Content-type: text/xml\n"""
-
-        print """<?xml version="1.0" ?>
-        <ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc"
-            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-            xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd">
-        <ServiceException code="%s" locator="%s"><![CDATA[
-        %s
-        ]]></ServiceException>
-        </ServiceExceptionReport>""" % \
-                (self.__class__.__name__,self.message,self.args)
-
-class MissingParameterValue(WMSException):
-    pass
-
-class RequestFailed(WMSException):
-    pass
-class NoValidRequest(WMSException):
-    pass

+ 12 - 0
README

@@ -0,0 +1,12 @@
+Proxy4OWS www pages
+###################
+
+- edit source files
+
+- run make::
+
+    make dirhtml
+
+- rsync::
+    
+    rsync  --delete-excluded build/dirhtml/ proxy4ows.org:/data/www/proxy4ows.org/htdocs/

+ 0 - 1
__init__.py

@@ -1 +0,0 @@
-__all__ = [ "OWS","wcs","wfs","wms","OWSException"]

+ 0 - 13
config.cfg-template

@@ -1,13 +0,0 @@
-[Proxy4OWS]
-cachedir=/tmp/
-logging=DEBUG
-owslib=/home/jachym/usr/src/owslib/OWSLib/
-
-[MapServer]
-name=proxy4ows
-tempdir=/tmp/
-errorfile=stderr
-imagepath=/tmp/mapserv/
-onlineresource=http://localhost/cgi-bin/proxy4ows.cgi
-srs=EPSG:4326 EPSG:102067 EPSG:900913 EPSG:3035 EPSG:3857 EPSG:900913
-

+ 170 - 0
make.bat

@@ -0,0 +1,170 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Proxy4OWS.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Proxy4OWS.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

+ 0 - 19
proxy4ows.cgi-template

@@ -1,19 +0,0 @@
-#!/usr/bin/python
-
-#debugger
-#import rpdb2; rpdb2.start_embedded_debugger("lucerna")
-
-# import sys
-# sys.path.append("/path/to/proxy4ows/")
-
-import OWS
-import logging
-import OWSExceptions
-
-logging.basicConfig(level=logging.DEBUG)
-
-try:
-    service = OWS.getService(configFile = "config.cfg")
-    service.dispatch()
-except OWSExceptions.OWSException,e:
-    e.toXml()

BIN
source/_templates/proxy4ows/.layout.html.swp


+ 102 - 0
source/_templates/proxy4ows/layout.html

@@ -0,0 +1,102 @@
+{#
+    agogo/layout.html
+    ~~~~~~~~~~~~~~~~~
+
+    Sphinx layout template for the agogo theme, originally written
+    by Andi Albrecht.
+
+    :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+#}
+{% extends "basic/layout.html" %}
+
+{% block header %}
+    <div class="header-wrapper">
+      <div class="header">
+        {%- if logo %}
+          <p class="logo"><a href="{{ pathto(master_doc) }}">
+            <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+          </a></p>
+        {%- endif %}
+        {%- block headertitle %}
+        <h1><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></h1>
+        {%- endblock %}
+        <div class="rel">
+          {%- for rellink in rellinks|reverse %}
+          <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+             {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+          {%- if not loop.last %}{{ reldelim2 }}{% endif %}
+          {%- endfor %}
+        </div>
+       </div>
+    </div>
+{% endblock %}
+
+{% block content %}
+    <div class="content-wrapper">
+      <div class="content">
+        <div class="document">
+          {%- block document %}
+            {{ super() }}
+          {%- endblock %}
+        </div>
+        <div class="sidebar">
+           <div class="navigation">
+               <ul>
+                   <li><a href="/about/">About</a></li>
+                   <li><a href="/download/">Download</a></li>
+                   <li><a href="/license/">License</a></li>
+                   <li><a href="/development/">Development</a></li>
+                   <li><a href="/contributors/">Contributors</a></li>
+               </ul>
+           </div>
+          {%- block sidebartoc %}
+          {%- if toctree() %}
+          <h3>{{ _('Table Of Contents') }}</h3>
+          {{ toctree() }}
+          {% endif %}
+          {%- endblock %}
+          {%- block sidebarsearch %}
+          <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3>
+          <form class="search" action="{{ pathto('search') }}" method="get">
+            <input type="text" name="q" size="18" />
+            <input type="submit" value="{{ _('Go') }}" />
+            <input type="hidden" name="check_keywords" value="yes" />
+            <input type="hidden" name="area" value="default" />
+          </form>
+          <p class="searchtip" style="font-size: 90%">
+            {{ _('Enter search terms or a module, class or function name.') }}
+          </p>
+          {%- endblock %}
+        </div>
+        <div class="clearer"></div>
+      </div>
+    </div>
+{% endblock %}
+
+{% block footer %}
+    <div class="footer-wrapper">
+      <div class="footer">
+        <div class="left">
+          {%- for rellink in rellinks|reverse %}
+          <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+             {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+          {%- if not loop.last %}{{ reldelim2 }}{% endif %}
+          {%- endfor %}
+          {%- if show_source and has_source and sourcename %}
+            <br/>
+            <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+               rel="nofollow">{{ _('Show Source') }}</a>
+          {%- endif %}
+        </div>
+
+        <div class="right">
+          {{ super() }}
+        </div>
+        <div class="clearer"></div>
+      </div>
+    </div>
+{% endblock %}
+
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}

+ 452 - 0
source/_templates/proxy4ows/static/agogo.css_t

@@ -0,0 +1,452 @@
+/*
+ * agogo.css_t
+ * ~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- agogo theme.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+* {
+  margin: 0px;
+  padding: 0px;
+}
+
+body {
+  font-family: {{ theme_bodyfont }};
+  line-height: 1.4em;
+  color: black;
+  background-color: {{ theme_bgcolor }};
+}
+
+
+/* Page layout */
+
+div.header, div.content, div.footer {
+  width: {{ theme_pagewidth }};
+  margin-left: auto;
+  margin-right: auto;
+}
+
+div.header-wrapper {
+  background: {{ theme_headerbg }};
+  border-bottom: 3px solid #2e3436;
+}
+
+
+/* Default body styles */
+a {
+  color: {{ theme_linkcolor }};
+}
+
+div.bodywrapper a, div.footer a {
+  text-decoration: underline;
+}
+
+.clearer {
+  clear: both;
+}
+
+.left {
+  float: left;
+}
+
+.right {
+  float: right;
+}
+
+.line-block {
+    display: block;
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+
+.line-block .line-block {
+    margin-top: 0;
+    margin-bottom: 0;
+    margin-left: 1.5em;
+}
+
+h1, h2, h3, h4 {
+  font-family: {{ theme_headerfont }};
+  font-weight: normal;
+  color: {{ theme_headercolor2 }};
+  margin-bottom: .8em;
+}
+
+h1 {
+  color: {{ theme_headercolor1 }};
+}
+
+h2 {
+  padding-bottom: .5em;
+  border-bottom: 1px solid {{ theme_headercolor2 }};
+}
+
+a.headerlink {
+  visibility: hidden;
+  color: #dddddd;
+  padding-left: .3em;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+  visibility: visible;
+}
+
+img {
+  border: 0;
+}
+
+div.admonition {
+  margin-top: 10px;
+  margin-bottom: 10px;
+  padding: 2px 7px 1px 7px;
+  border-left: 0.2em solid black;
+}
+
+p.admonition-title {
+  margin: 0px 10px 5px 0px;
+  font-weight: bold;
+}
+
+dt:target, .highlighted {
+  background-color: #fbe54e;
+}
+
+/* Header */
+
+div.header {
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+
+div.header h1 {
+  font-family: {{ theme_headerfont }};
+  font-weight: normal;
+  font-size: 180%;
+  letter-spacing: .08em;
+}
+
+div.header h1 a {
+  color: white;
+}
+
+div.header div.rel {
+  margin-top: 1em;
+}
+
+div.header div.rel a {
+  color: {{ theme_headerlinkcolor }};
+  letter-spacing: .1em;
+  text-transform: uppercase;
+}
+
+p.logo {
+    float: right;
+}
+
+img.logo {
+    border: 0;
+}
+
+
+/* Content */
+div.content-wrapper {
+  background-color: white;
+  padding-top: 20px;
+  padding-bottom: 20px;
+}
+
+div.document {
+  width: {{ theme_documentwidth }};
+  float: left;
+}
+
+div.body {
+  padding-right: 2em;
+  text-align: {{ theme_textalign }};
+}
+
+div.document ul {
+  margin: 1.5em;
+  list-style-type: square;
+}
+
+div.document dd {
+  margin-left: 1.2em;
+  margin-top: .4em;
+  margin-bottom: 1em;
+}
+
+div.document .section {
+  margin-top: 1.7em;
+}
+div.document .section:first-child {
+  margin-top: 0px;
+}
+
+div.document div.highlight {
+  padding: 3px;
+  background-color: #eeeeec;
+  border-top: 2px solid #dddddd;
+  border-bottom: 2px solid #dddddd;
+  margin-top: .8em;
+  margin-bottom: .8em;
+}
+
+div.document h2 {
+  margin-top: .7em;
+}
+
+div.document p {
+  margin-bottom: .5em;
+}
+
+div.document li.toctree-l1 {
+  margin-bottom: 1em;
+}
+
+div.document .descname {
+  font-weight: bold;
+}
+
+div.document .docutils.literal {
+  background-color: #eeeeec;
+  padding: 1px;
+}
+
+div.document .docutils.xref.literal {
+  background-color: transparent;
+  padding: 0px;
+}
+
+div.document blockquote {
+  margin: 1em;
+}
+
+div.document ol {
+  margin: 1.5em;
+}
+
+
+/* Sidebar */
+
+div.sidebar {
+  width: {{ theme_sidebarwidth }};
+  float: right;
+  font-size: .9em;
+}
+
+div.sidebar a, div.header a {
+  text-decoration: none;
+}
+
+div.sidebar a:hover, div.header a:hover {
+  text-decoration: underline;
+}
+
+div.sidebar h3 {
+  color: #2e3436;
+  text-transform: uppercase;
+  font-size: 130%;
+  letter-spacing: .1em;
+}
+
+div.sidebar ul {
+  list-style-type: none;
+}
+
+div.sidebar li.toctree-l1 a {
+  display: block;
+  padding: 1px;
+  border: 1px solid #dddddd;
+  background-color: #eeeeec;
+  margin-bottom: .4em;
+  padding-left: 3px;
+  color: #2e3436;
+}
+
+div.sidebar li.toctree-l2 a {
+  background-color: transparent;
+  border: none;
+  margin-left: 1em;
+  border-bottom: 1px solid #dddddd;
+}
+
+div.sidebar li.toctree-l3 a {
+  background-color: transparent;
+  border: none;
+  margin-left: 2em;
+  border-bottom: 1px solid #dddddd;
+}
+
+div.sidebar li.toctree-l2:last-child a {
+  border-bottom: none;
+}
+
+div.sidebar li.toctree-l1.current a {
+  border-right: 5px solid {{ theme_headerlinkcolor }};
+}
+
+div.sidebar li.toctree-l1.current li.toctree-l2 a {
+  border-right: none;
+}
+
+
+/* Footer */
+
+div.footer-wrapper {
+  background: {{ theme_footerbg }};
+  border-top: 4px solid #babdb6;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  min-height: 80px;
+}
+
+div.footer, div.footer a {
+  color: #888a85;
+}
+
+div.footer .right {
+  text-align: right;
+}
+
+div.footer .left {
+  text-transform: uppercase;
+}
+
+
+/* Styles copied from basic theme */
+
+img.align-left, .figure.align-left, object.align-left {
+    clear: left;
+    float: left;
+    margin-right: 1em;
+}
+
+img.align-right, .figure.align-right, object.align-right {
+    clear: right;
+    float: right;
+    margin-left: 1em;
+}
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+    text-align: left;
+}
+
+.align-center {
+    clear: both;
+    text-align: center;
+}
+
+.align-right {
+    text-align: right;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+/* -- viewcode extension ---------------------------------------------------- */
+
+.viewcode-link {
+    float: right;
+}
+
+.viewcode-back {
+    float: right;
+    font-family:: {{ theme_bodyfont }};
+}
+
+div.viewcode-block:target {
+    margin: -1px -3px;
+    padding: 0 3px;
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}

BIN
source/_templates/proxy4ows/static/bgfooter.png


BIN
source/_templates/proxy4ows/static/bgtop.png


+ 19 - 0
source/_templates/proxy4ows/theme.conf

@@ -0,0 +1,19 @@
+[theme]
+inherit = basic
+stylesheet = agogo.css
+pygments_style = tango
+
+[options]
+bodyfont = "Verdana", Arial, sans-serif
+headerfont = "Georgia", "Times New Roman", serif
+pagewidth = 70em
+documentwidth = 50em
+sidebarwidth = 20em
+bgcolor = #eeeeec
+headerbg = url(bgtop.png) top left repeat-x
+footerbg = url(bgfooter.png) top left repeat-x
+linkcolor = #ce5c00
+headercolor1 = #204a87
+headercolor2 = #3465a4
+headerlinkcolor = #fcaf3e
+textalign = justify

+ 233 - 0
source/about.rst

@@ -0,0 +1,233 @@
+About Proxy4OWS
+###############
+
+*Proxy4OWS is Open Source server
+program, which enables to visualize and work with large vector data and
+raster data in the web environment. It basically transforms OGC Web Feature
+Service and OGC Web Coverage service to OGC Web Mapping service calls. It
+can be also used for transformation of the original data into
+server-unsupported coordinate reference system, including OGC WMS*
+
+The problem of displaying large GIS datasets
+============================================
+When working with large vector datasets, we are usually facing limits of
+nowadays browsers. Google Maps [#]_ for example are limiting number of
+displaying vector features to 1000. In OpenLayers [#]_, no limit for number
+of features is used, but displaying e.g. cadastral map makes browsers often
+freeze. Advantage of working with vector data directly is (among others),
+direct possibility of vector data editing, more interactive way of user
+experience, speed (when dealing with reasonable amount of data).
+
+
+While vector data can be displayed using todays technologies, some popular
+raster data formats, such as GeoTIFF, can be not. According to W3C [#]_,
+only few formats for raster data are supported, none of them is really used
+or usable in GIS, usually because of compression method, they are using. In
+the internet, raster graphics format are focusing on possibly low amount of
+data transfered from the server to the client, while loosing the accuracy
+of the data being transfered. In GIS, we are focusing on data quality,
+regardless on file size.
+
+Raster and vector data are usually distributed using OGC OWS standards.
+Vector and raster data are distributed via OGC Web Feature and Raster
+Service respectively. Both services are offering list of datasets and
+metadata.
+
+Another problem might occur, when some OGC Web Mapping Service does not
+offer coordinate reference system, in which the web mapping application is
+configured. Some middle-ware have to be setuped between the map application
+and the server, which will transform the images from server coordinate
+reference system to the one, accepted by the client.
+
+
+Proxy4OWS 
+=========
+Proxy4OWS is server script, which is between the client mapping application
+and OGC OWS server (WCS, WFS or WMS). It is transforming OGC WMS request
+types from the client, into WCS or WFS requests, so that the target server
+can accept them. On the way back, it downloads the data distributed by the
+server (raster or vector), creates image and sends it back to the client.
+
+Features
+--------
+It also transforms GetCapabilities request-response pair, so that the
+(WMS) client can deal with it.
+
+As result, data are processed on the server, into the form, common
+web browser mapping application are able to display without big demands on
+system resources.
+
+.. figure:: imgs/owsproxy_sequence_diagram.png
+    
+    HSlayers.Layer.WCS and WFS are derived from Layer WMS. As proxy
+    between the client (the map) and the WFS|WCS server, Proxy4OWS is
+    placed. Proxy4OWS transforms WMS requests comming from the client
+    into WFS|WCS calls and also responses are transformed to WMS
+    responses or images, displayable in the web browser.
+
+Proxy4OWS also can deal with OGC WMS service in the way, that it is
+transforming the coordinate reference system of the original service into
+the client-preferred one in the case, server does not support coordinate
+system of the client. The resulting image is usually a bit distorted, yet
+displayable. 
+
+
+Technology
+----------
+Proxy4OWS is written in Python programming language. Following libraries are
+used:
+
+MapServer [#]_
+    MapServer is the core of Proxy4OWS. Proxy4OWS generates the Map object
+    configration and after that dispatch method of MapServer is used, which
+    will deal with the request, download all necessary data from servers
+    and generate resulting image.
+
+    From the client-point of view, it is used for working with vector data
+    directlya (deals as OGC WFS client).
+    
+GDAL/OGR [#]_
+    GDAL is used for reading OGC WFS and OGC WCS service metadata, so that
+    the WMS response from Proxy4OWS to the client, has all necessary
+    informations.
+
+    While for OGC WFS service, MapServer directly is acting as client, OGC
+    WCS is configured as GDAL data source.
+
+    Also for WMS transformation service, WMS interface of GDAL is used,
+    because of, it is able to deal with tiled requests, preserving the
+    large dataset exceptions issue.
+
+OWSLib [#]_
+    OWSLib is Python library, which acts as OWS client. With help of
+    OWSLib, metadata of particular target services are being collected
+    easy.
+
+Architecture
+------------
+Once again: Proxy4OWS acts as WMS server to the client and acts as WFS, WCS
+or even WMS client to the target server.
+
+GetCapabilities
+    When GetCapabilities request arrives from the client, Proxy4OWS
+    Checks for existing cached directory with mapfile, creates new, if not existing
+    
+GetMap
+    When GetMap request arrives, image is generated based on previously
+    generated mapfile, using `OWSDispatch` method. At this point, WFS
+    filter is applied, if target server is WFS.
+
+In both cases, Proxy4OWS is looking for existing MapServer MapFile (it
+creates one, if it does not exist) and let MapServer do the work. Proxy4OWS
+is takes care about proper MapFile configuration.
+
+.. figure:: imgs/getcapabilities.png
+    
+    When WMS GetCapabilities request arrives, Proxy4OWS generates MapFile
+    with list of layers, corresponding to either feature types (WFS) or
+    coverages (WCS) of the target service. For configuring the MapFile
+    properly, GDAL, OGR and OWSLib libraries are used. 
+
+    WFS Layers are configured, using MapServer as WFS Client, while WCS
+    layers are using GDAL as WCS Client.
+
+    Then MapFile is generated, `OWSDispatch` method is called and
+    Capabilities response does arrive.
+    
+.. figure:: imgs/getmap.png
+
+    When WMS GetMap request arrives, Proxy4OWS find existing MapFile
+    (creates new, if it does not exist) and performs `OWSDispatch` function
+    of MapServer, which generates the output image and sends it back to the
+    server.
+
+Invocation
+----------
+Proxy4OWS is originally designed as WMS server. But it can also be used as
+WFS or WCS server, so that it can only transform original data into
+coordinate system unsupported by the target server.
+
+Therefore, the client can use basically any type of OWS request using
+proper parameters. In addition to this, two more parameters will have to be
+appended to the request URL:
+
+    * `owsservice` says, what is the target server service type (WCS, WFS
+      or WMS)
+    * `owsurl` is the URL of original server
+
+.. figure:: imgs/crwfs.png
+
+    Image based on OGC WFS service, as result of following WMS GetMap
+    request. Note `owsurl` and `owsservice` parameters in the URL:
+
+    `http://localhost/cgi-bin/owsproxy.cgi?map=/var/www/localhost/htdocs/tmp/WFS-8066ca5a58f48c499f919d45529596c0xeWyOF/mapfile.map&owsService=WFS&owsUrl=http://bnhelp.cz/ows/crwfs&LAYERS=kraje&TRANSPARENT=TRUE&FORMAT=image/png&EXCEPTIONS=XML&VERSION=1.3.0&INFO_FORMAT=application/vnd.ogc.gml&CRS=EPSG:3035&SERVICE=WMS&REQUEST=GetMap&STYLES=&BBOX=2844318.7336584,4288032.8774186,3211207.4244274,5053560.2418116&WIDTH=1085&HEIGHT=520 <http://localhost/cgi-bin/owsproxy.cgi?map=/var/www/localhost/htdocs/tmp/WFS-8066ca5a58f48c499f919d45529596c0xeWyOF/mapfile.map&owsService=WFS&owsUrl=http://bnhelp.cz/ows/crwfs&LAYERS=kraje&TRANSPARENT=TRUE&FORMAT=image/png&EXCEPTIONS=XML&VERSION=1.3.0&INFO_FORMAT=application/vnd.ogc.gml&CRS=EPSG:3035&SERVICE=WMS&REQUEST=GetMap&STYLES=&BBOX=2844318.7336584,4288032.8774186,3211207.4244274,5053560.2418116&WIDTH=1085&HEIGHT=520>`_
+
+
+WMS Transformation
+------------------
+Implementation of transformation of OGC WMS services is done in little bit
+different way. Since it is assumed, that Capabilities document is already
+parsed, it is expecting GetMap request from the client to Proxy4OWS
+directly. The GetMap request is expected to have - next to original WMS paramters -  also
+three add-on options:
+
+    * owsService - this is going to be WMS
+    * owsUrl - URL of the original service, which is expecting to handle
+      the GetMap request
+    * fromCRS - CRS of the original coordinate system, from which shall the
+      result of GetMap be transformed to.
+
+The MapServer's mapfile is generated on-the-fly. Only one layer is attached
+to the mapfile - layer of type WMS. MapServer then formulates the necessary
+request, fetches the data from remote server and provides image
+transformation on them. Result is always little bit distorted, because the
+resolution is not always fine enough, but the it can be used and displayed
+in the mapping application.
+
+.. figure:: imgs/wms_sequence.png
+
+   WMS Sequence diagram. 
+    
+
+.. figure:: imgs/wms_transformace.png
+
+   WMS transformation result - left map coordinate system, right -
+   transformed result from EPSG:4326 source.
+
+Thanks to Proxy4OWS, we can now display seam-less data from several WMS
+resources, which do not support coordinate system of the map, displayed in
+user's browser.
+
+Further development
+===================
+Currently, when full featured Capabilities response is send back from the
+server to the client, for some servers, with hight amount of data, this
+takes long time. 
+
+For WFS for example, GetCapabilities, DescribeFeatureType and sometimes
+even GetFeature requests are to be called, before all necessary metadata
+are filled to MapFile. This certainly makes the Capabilities response come
+back after long time. In the future, we would like to eliminate this,
+calls, so that only smallest amount of requests (GetCapabilities) would
+have to be requested, and WMS Capabilities response could be returned
+possibly fast. Of course, when users chooses the particular layer to be
+displayed, additional non-standard call would have to be done, for getting
+addition attributes, so that the client has all necessary informations
+(which can be normally taken from Capabilities document).
+
+Also now, virtually no configuration caching is created. For each
+GetCapabilities request, new temporary MapFile configuration is setuped.
+Proper way would be to use already existing MapFile for particular service,
+if already generated and evaluate the difference between cashed version and
+potentially upgraded service.
+
+Proxy4OWS is not cashing any data. It would be the option for further
+investigation, if it would make sense, to pre-cache some original data at
+Proxy4OWS side, and make the performance higher.
+
+.. [#] http://code.google.com/intl/cs-CZ/apis/kml/documentation/mapsSupport.html
+.. [#] http://openlayers.org
+.. [#] http://www.w3.org/Graphics/
+.. [#] http://mapserver.org
+.. [#] http://gdal.org
+.. [#] http://sourceforge.net/apps/trac/owslib/wiki

+ 220 - 0
source/conf.py

@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+#
+# Proxy4OWS documentation build configuration file, created by
+# sphinx-quickstart on Sat Mar 17 00:01:04 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Proxy4OWS'
+copyright = u'2012, CCSS, HS-RS'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'proxy4ows'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ['_templates']
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "Proxy4OWS"
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = "logo.png"
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Proxy4OWSdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'Proxy4OWS.tex', u'Proxy4OWS Documentation',
+   u'CCSS, HS-RS', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'proxy4ows', u'Proxy4OWS Documentation',
+     [u'CCSS, HS-RS'], 1)
+]
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}

+ 38 - 0
source/contributors.rst

@@ -0,0 +1,38 @@
+Proxy4OWS Contributors
+######################
+
+Persons
+=======
+Following persons have contributed to Proxy4OWS's code and are helping with
+the development:
+
+Jachym Cepicky
+    * Coder, Code designer
+    
+Michal Sredl
+    * Coder, Tester
+
+Premysl Vohnout
+    * System administration, testing
+
+Organizations
+=============
+Following organizations have founded development of Proxy4OWS.
+
+CCSS 
+    * Czech Center for Science and Sociaty
+    * http://ccss.cz
+    
+HS-RS 
+    * Help Service - Remote Sensing
+    * http://bnhelp.cz
+
+Projects
+========
+Proxy4OWS was founded among other also thanks to following projects:
+
+Briseide
+    * http://briseide.eu
+
+enviroGRIDS
+    * http://envirogrids.net/

+ 23 - 0
source/development.rst

@@ -0,0 +1,23 @@
+Proxy4OWS Development
+#####################
+
+`Visit Proxy4OWS's development site <http://redmine.ccss.cz/projects/owsproxy>`_ 
+
+Proxy4OWS is developed using `Python <http://python.org>`_. Following
+projects are used in Proxy4OWS code base:
+
+MapServer
+    * http://mapserver.org
+    * Core of Proxy4OWS
+    * Acts as WFS and WMS client
+    * Acts as Proxy4OWS back-end server
+
+GDAL
+    * http://gdal.org
+    * Acts WCS client
+    * Data parsing
+
+OWSLib
+    * http://sourceforge.net/apps/trac/owslib/
+    * Data parsing
+

+ 6 - 0
source/download.rst

@@ -0,0 +1,6 @@
+Download Proxy4OWS
+##################
+
+Proxy4OWS id available via `GIT <http://git-scm.com/>`_::
+
+   git clone git://git.ccss.cz/hsrs/owsproxy.git proxy4ows

BIN
source/imgs/crwfs.png


BIN
source/imgs/getcapabilities.png


BIN
source/imgs/getmap.png


BIN
source/imgs/logo.png


BIN
source/imgs/owsproxy_sequence_diagram.png


+ 0 - 0
init.txt → source/imgs/proxy4ows.zargo~


BIN
source/imgs/wms_sequence.png


BIN
source/imgs/wms_transformace.png


+ 14 - 0
source/index.rst

@@ -0,0 +1,14 @@
+.. Proxy4OWS documentation master file, created by
+   sphinx-quickstart on Sat Mar 17 00:01:04 2012.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Proxy4OWS
+=========
+Proxy4OWS is Open Source server program, which enables to visualize and
+work with large vector data and raster data in the web environment. It
+basically transforms OGC Web Feature Service and OGC Web Coverage service
+to OGC Web Mapping service calls. It can be also used for transformation of
+the original data into server-unsupported coordinate reference system,
+including OGC WMS.
+

+ 4 - 0
source/license.rst

@@ -0,0 +1,4 @@
+Proxy4OWS License
+#################
+
+TO BE FILLED

+ 233 - 0
source/owsproxy.rst

@@ -0,0 +1,233 @@
+Proxy4OWS
+#########
+
+*Proxy4OWS [http://redmine.ccss.cz/projects/owsproxy] is Open Source server
+program, which enables to visualize and work with large vector data and
+raster data in the web environment. It basically transforms OGC Web Feature
+Service and OGC Web Coverage service to OGC Web Mapping service calls. It
+can be also used for transformation of the original data into
+server-unsupported coordinate reference system, including OGC WMS*
+
+The problem of displaying large GIS datasets
+============================================
+When working with large vector datasets, we are usually facing limits of
+nowadays browsers. Google Maps [#]_ for example are limiting number of
+displaying vector features to 1000. In OpenLayers [#]_, no limit for number
+of features is used, but displaying e.g. cadastral map makes browsers often
+freeze. Advantage of working with vector data directly is (among others),
+direct possibility of vector data editing, more interactive way of user
+experience, speed (when dealing with reasonable amount of data).
+
+
+While vector data can be displayed using todays technologies, some popular
+raster data formats, such as GeoTIFF, can be not. According to W3C [#]_,
+only few formats for raster data are supported, none of them is really used
+or usable in GIS, usually because of compression method, they are using. In
+the internet, raster graphics format are focusing on possibly low amount of
+data transfered from the server to the client, while loosing the accuracy
+of the data being transfered. In GIS, we are focusing on data quality,
+regardless on file size.
+
+Raster and vector data are usually distributed using OGC OWS standards.
+Vector and raster data are distributed via OGC Web Feature and Raster
+Service respectively. Both services are offering list of datasets and
+metadata.
+
+Another problem might occur, when some OGC Web Mapping Service does not
+offer coordinate reference system, in which the web mapping application is
+configured. Some middle-ware have to be setuped between the map application
+and the server, which will transform the images from server coordinate
+reference system to the one, accepted by the client.
+
+
+Proxy4OWS 
+=========
+Proxy4OWS is server script, which is between the client mapping application
+and OGC OWS server (WCS, WFS or WMS). It is transforming OGC WMS request
+types from the client, into WCS or WFS requests, so that the target server
+can accept them. On the way back, it downloads the data distributed by the
+server (raster or vector), creates image and sends it back to the client.
+
+Features
+--------
+It also transforms GetCapabilities request-response pair, so that the
+(WMS) client can deal with it.
+
+As result, data are processed on the server, into the form, common
+web browser mapping application are able to display without big demands on
+system resources.
+
+.. figure:: imgs/owsproxy_sequence_diagram.png
+    
+    HSlayers.Layer.WCS and WFS are derived from Layer WMS. As proxy
+    between the client (the map) and the WFS|WCS server, Proxy4OWS is
+    placed. Proxy4OWS transforms WMS requests comming from the client
+    into WFS|WCS calls and also responses are transformed to WMS
+    responses or images, displayable in the web browser.
+
+Proxy4OWS also can deal with OGC WMS service in the way, that it is
+transforming the coordinate reference system of the original service into
+the client-preferred one in the case, server does not support coordinate
+system of the client. The resulting image is usually a bit distorted, yet
+displayable. 
+
+
+Technology
+----------
+Proxy4OWS is written in Python programming language. Following libraries are
+used:
+
+MapServer [#]_
+    MapServer is the core of Proxy4OWS. Proxy4OWS generates the Map object
+    configration and after that dispatch method of MapServer is used, which
+    will deal with the request, download all necessary data from servers
+    and generate resulting image.
+
+    From the client-point of view, it is used for working with vector data
+    directlya (deals as OGC WFS client).
+    
+GDAL/OGR [#]_
+    GDAL is used for reading OGC WFS and OGC WCS service metadata, so that
+    the WMS response from Proxy4OWS to the client, has all necessary
+    informations.
+
+    While for OGC WFS service, MapServer directly is acting as client, OGC
+    WCS is configured as GDAL data source.
+
+    Also for WMS transformation service, WMS interface of GDAL is used,
+    because of, it is able to deal with tiled requests, preserving the
+    large dataset exceptions issue.
+
+OWSLib [#]_
+    OWSLib is Python library, which acts as OWS client. With help of
+    OWSLib, metadata of particular target services are being collected
+    easy.
+
+Architecture
+------------
+Once again: Proxy4OWS acts as WMS server to the client and acts as WFS, WCS
+or even WMS client to the target server.
+
+GetCapabilities
+    When GetCapabilities request arrives from the client, Proxy4OWS
+    Checks for existing cached directory with mapfile, creates new, if not existing
+    
+GetMap
+    When GetMap request arrives, image is generated based on previously
+    generated mapfile, using `OWSDispatch` method. At this point, WFS
+    filter is applied, if target server is WFS.
+
+In both cases, Proxy4OWS is looking for existing MapServer MapFile (it
+creates one, if it does not exist) and let MapServer do the work. Proxy4OWS
+is takes care about proper MapFile configuration.
+
+.. figure:: imgs/getcapabilities.png
+    
+    When WMS GetCapabilities request arrives, Proxy4OWS generates MapFile
+    with list of layers, corresponding to either feature types (WFS) or
+    coverages (WCS) of the target service. For configuring the MapFile
+    properly, GDAL, OGR and OWSLib libraries are used. 
+
+    WFS Layers are configured, using MapServer as WFS Client, while WCS
+    layers are using GDAL as WCS Client.
+
+    Then MapFile is generated, `OWSDispatch` method is called and
+    Capabilities response does arrive.
+    
+.. figure:: imgs/getmap.png
+
+    When WMS GetMap request arrives, Proxy4OWS find existing MapFile
+    (creates new, if it does not exist) and performs `OWSDispatch` function
+    of MapServer, which generates the output image and sends it back to the
+    server.
+
+Invocation
+----------
+Proxy4OWS is originally designed as WMS server. But it can also be used as
+WFS or WCS server, so that it can only transform original data into
+coordinate system unsupported by the target server.
+
+Therefore, the client can use basically any type of OWS request using
+proper parameters. In addition to this, two more parameters will have to be
+appended to the request URL:
+
+    * `owsservice` says, what is the target server service type (WCS, WFS
+      or WMS)
+    * `owsurl` is the URL of original server
+
+.. figure:: imgs/crwfs.png
+
+    Image based on OGC WFS service, as result of following WMS GetMap
+    request. Note `owsurl` and `owsservice` parameters in the URL:
+
+    `http://localhost/cgi-bin/owsproxy.cgi?map=/var/www/localhost/htdocs/tmp/WFS-8066ca5a58f48c499f919d45529596c0xeWyOF/mapfile.map&owsService=WFS&owsUrl=http://bnhelp.cz/ows/crwfs&LAYERS=kraje&TRANSPARENT=TRUE&FORMAT=image/png&EXCEPTIONS=XML&VERSION=1.3.0&INFO_FORMAT=application/vnd.ogc.gml&CRS=EPSG:3035&SERVICE=WMS&REQUEST=GetMap&STYLES=&BBOX=2844318.7336584,4288032.8774186,3211207.4244274,5053560.2418116&WIDTH=1085&HEIGHT=520 <http://localhost/cgi-bin/owsproxy.cgi?map=/var/www/localhost/htdocs/tmp/WFS-8066ca5a58f48c499f919d45529596c0xeWyOF/mapfile.map&owsService=WFS&owsUrl=http://bnhelp.cz/ows/crwfs&LAYERS=kraje&TRANSPARENT=TRUE&FORMAT=image/png&EXCEPTIONS=XML&VERSION=1.3.0&INFO_FORMAT=application/vnd.ogc.gml&CRS=EPSG:3035&SERVICE=WMS&REQUEST=GetMap&STYLES=&BBOX=2844318.7336584,4288032.8774186,3211207.4244274,5053560.2418116&WIDTH=1085&HEIGHT=520>`_
+
+
+WMS Transformation
+------------------
+Implementation of transformation of OGC WMS services is done in little bit
+different way. Since it is assumed, that Capabilities document is already
+parsed, it is expecting GetMap request from the client to Proxy4OWS
+directly. The GetMap request is expected to have - next to original WMS paramters -  also
+three add-on options:
+
+    * owsService - this is going to be WMS
+    * owsUrl - URL of the original service, which is expecting to handle
+      the GetMap request
+    * fromCRS - CRS of the original coordinate system, from which shall the
+      result of GetMap be transformed to.
+
+The MapServer's mapfile is generated on-the-fly. Only one layer is attached
+to the mapfile - layer of type WMS. MapServer then formulates the necessary
+request, fetches the data from remote server and provides image
+transformation on them. Result is always little bit distorted, because the
+resolution is not always fine enough, but the it can be used and displayed
+in the mapping application.
+
+.. figure:: imgs/wms_sequence.png
+
+   WMS Sequence diagram. 
+    
+
+.. figure:: imgs/wms_transformace.png
+
+   WMS transformation result - left map coordinate system, right -
+   transformed result from EPSG:4326 source.
+
+Thanks to Proxy4OWS, we can now display seam-less data from several WMS
+resources, which do not support coordinate system of the map, displayed in
+user's browser.
+
+Further development
+===================
+Currently, when full featured Capabilities response is send back from the
+server to the client, for some servers, with hight amount of data, this
+takes long time. 
+
+For WFS for example, GetCapabilities, DescribeFeatureType and sometimes
+even GetFeature requests are to be called, before all necessary metadata
+are filled to MapFile. This certainly makes the Capabilities response come
+back after long time. In the future, we would like to eliminate this,
+calls, so that only smallest amount of requests (GetCapabilities) would
+have to be requested, and WMS Capabilities response could be returned
+possibly fast. Of course, when users chooses the particular layer to be
+displayed, additional non-standard call would have to be done, for getting
+addition attributes, so that the client has all necessary informations
+(which can be normally taken from Capabilities document).
+
+Also now, virtually no configuration caching is created. For each
+GetCapabilities request, new temporary MapFile configuration is setuped.
+Proper way would be to use already existing MapFile for particular service,
+if already generated and evaluate the difference between cashed version and
+potentially upgraded service.
+
+Proxy4OWS is not cashing any data. It would be the option for further
+investigation, if it would make sense, to pre-cache some original data at
+Proxy4OWS side, and make the performance higher.
+
+.. [#] http://code.google.com/intl/cs-CZ/apis/kml/documentation/mapsSupport.html
+.. [#] http://openlayers.org
+.. [#] http://www.w3.org/Graphics/
+.. [#] http://mapserver.org
+.. [#] http://gdal.org
+.. [#] http://sourceforge.net/apps/trac/owslib/wiki

BIN
tests/mapfiles/dem.tif


+ 0 - 29
tests/mapfiles/linie.gml

@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<ogr:FeatureCollection
-     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-     xsi:schemaLocation="http://ogr.maptools.org/ linie.xsd"
-     xmlns:ogr="http://ogr.maptools.org/"
-     xmlns:gml="http://www.opengis.net/gml">
-  <gml:boundedBy>
-    <gml:Box>
-      <gml:coord><gml:X>12.73534180854241</gml:X><gml:Y>48.15241851478495</gml:Y></gml:coord>
-      <gml:coord><gml:X>18.61281586021506</gml:X><gml:Y>51.4318325306153</gml:Y></gml:coord>
-    </gml:Box>
-  </gml:boundedBy>
-                           
-  <gml:featureMember>
-    <ogr:line fid="F0">
-      <ogr:geometryProperty><gml:LineString><gml:coordinates>13.282972110215054,51.329947823327359 12.748077396953406,50.763214139038233 12.735341808542413,48.992967349910394 13.416695788530467,48.324348958333331 14.301819183094386,49.075748674581838 14.257244623655914,50.801420904271204 13.276604316009559,51.323580029121864 13.276604316009559,51.323580029121864</gml:coordinates></gml:LineString></ogr:geometryProperty>
-    </ogr:line>
-  </gml:featureMember>
-  <gml:featureMember>
-    <ogr:line fid="F1">
-      <ogr:geometryProperty><gml:LineString><gml:coordinates>14.671151247013142,51.380890176971327 15.619952583632021,48.152418514784948 16.040227001194744,51.304476646505378 16.435030241935486,48.196993074223414 17.14185539874552,51.310844440710873 17.135487604540025,51.304476646505378</gml:coordinates></gml:LineString></ogr:geometryProperty>
-    </ogr:line>
-  </gml:featureMember>
-  <gml:featureMember>
-    <ogr:line fid="F2">
-      <ogr:geometryProperty><gml:LineString><gml:coordinates>18.612815860215058,51.100707231929512 18.103392323775392,51.431832530615296 17.31378584229391,50.833259875298687 18.421782034050182,49.349563825418159 17.912358497610516,48.40076248879928 17.065441868279571,49.056645291965353 17.065441868279571,49.056645291965353</gml:coordinates></gml:LineString></ogr:geometryProperty>
-    </ogr:line>
-  </gml:featureMember>
-</ogr:FeatureCollection>

+ 0 - 76
tests/mapfiles/ows.map

@@ -1,76 +0,0 @@
-MAP
-NAME "OWS Server"
-STATUS ON
-SIZE 250 250
-EXTENT -180 -90 180 90
-SHAPEPATH "./"
-IMAGECOLOR 255 255 255
-CONFIG "MS_ERRORFILE" "stderr"
-DEBUG 5
-
-WEB
-  IMAGEPATH "tmp/" 
-  IMAGEURL "/tmp/"
-  METADATA
-    "wfs_title"            "OWS Server"  ## REQUIRED
-    "ows_enable_request" "*"
-    "ows_updatesequence" "2011-29-05T00:24:00"
-    "ows_srs"               "EPSG:4326 EPSG:3035"  ## Recommended
-    "ows_abstract"      "OWS Server for Proxy4OWS testing purposes"
-  END
-END
-
-PROJECTION
-  "init=epsg:4326"
-END
-
-LAYER
-  NAME "line"
-  METADATA
-    "wfs_title"             "Line" ##REQUIRED
-    "wfs_srs"               "EPSG:4326" ## REQUIRED
-    "gml_include_items"     "all" ## Optional (serves all attributes for layer)
-    #"ows_feature_id"         "gml_id" ## REQUIRED
-    "wfs_abstract"         "My abstract"
-  END
-  TYPE LINE
-  STATUS ON
-  CONNECTIONTYPE OGR
-  CONNECTION "linie.gml"
-  PROJECTION
-    "init=epsg:4326"
-  END
-  EXTENT 12.735342 48.152419 18.612816 51.431833
-  DUMP TRUE           ## REQUIRED
-  CLASS
-    NAME "Linie"
-    STYLE
-      COLOR 0 155 0
-      OUTLINECOLOR 120 120 120
-    END
-    TEMPLATE "foo.html"
-  END
-END # Layer
-
-LAYER
-    NAME "dem"
-    TYPE RASTER
-    DATA "dem.tif"
-    PROJECTION
-        "init=epsg:4326"
-    END
-    STATUS ON
-    DEBUG ON
-    METADATA
-        "wms_name"            "dem"
-        "wms_title"            "CR dem"
-        "wms_server_version"  "1.1.1"
-        "wms_format"          "image/png"
-        "wcs_label"           "Elevation/Bathymetry"  ### required
-        "wcs_rangeset_name"   "Range 1"               ### required to support DescribeCoverage request
-        "wcs_rangeset_label"  "My Label"              ### required to support DescribeCoverage request
-        "wcs_abstract"         "My abstract"
-    END
-END
-
-END # Map File

+ 0 - 2
tests/test.cfg-default

@@ -1,2 +0,0 @@
-[OWSServer]
-owsserver=http://localhost/cgi-bin/mapserv

+ 0 - 94
tests/test_ows.py

@@ -1,94 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-# 
-#
-
-import unittest
-import logging
-import os,sys
-from ConfigParser import ConfigParser
-import urllib
-import urlparse
-from owslib import crs
-
-OWSVIEWER_DIR=os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
-sys.path.append(OWSVIEWER_DIR)
-
-from OWS import *
-
-class TestOWS(unittest.TestCase):
-    """Base class for OWS services (WFS, WCS)
-    """
-
-    owsUrl = None
-    config = None
-    service = None
-
-
-    def setUp(self):
-
-        # set logging
-        logging.basicConfig(level=logging.DEBUG)
-        
-        # mapfile for original services
-        mapfile = os.path.join(OWSVIEWER_DIR,"tests","mapfiles","ows.map")
-        self.config = ConfigParser.ConfigParser()
-        self.config.read(os.path.join(OWSVIEWER_DIR,"tests","test.cfg"))
-        self.owsUrl = self._getURLWithMap(mapfile)
-
-        os.environ.update({"QUERY_STRING":
-                "owsService=%s&owsUrl=%s"%(self.service,urllib.quote(self.owsUrl))})
-
-        self.service = getService()
-
-    def test_bbox(self):
-        """test if corect bounding box for layer will be used"""
-        
-        initExtent = [15, 50, 16, 51]
-        class ContentsMetadata:
-            boundingBoxWGS84 = initExtent
-            id = "Temporary test layer"
-        wcsLayer = ContentsMetadata()
-        ows = OWS()
-        extent = ows.getLayerExtent(wcsLayer,crs.Crs("EPSG:4326"))
-        self.assertAlmostEqual(extent[0], initExtent[0])
-        self.assertAlmostEqual(extent[1], initExtent[1])
-        self.assertAlmostEqual(extent[2], initExtent[2])
-        self.assertAlmostEqual(extent[3], initExtent[3])
-
-        extent = ows.getLayerExtent(wcsLayer,crs.Crs("EPSG:32633"))
-        self.assertAlmostEqual(extent[0], 500000.00, 0)
-        self.assertAlmostEqual(extent[1], 5538630.70, 0)
-        self.assertAlmostEqual(extent[2], 570168.86, 0)
-        self.assertAlmostEqual(extent[3], 5650300.79, 0)
-
-        
-        
-
-
-
-    def _getURLWithMap(self,mapfile):
-
-        # create URL which will produce WCS and WFS services for testing
-        # purposes
-        owsUrl = urlparse.urlparse(self.config.get("OWSServer","owsserver"))
-        owsParams = urlparse.parse_qs(owsUrl[4])
-        owsParams["map"] = mapfile
-
-        return urlparse.urlunparse((owsUrl[0],owsUrl[1],owsUrl[2], owsUrl[3],
-                                     urllib.unquote(urllib.urlencode(owsParams,True)),owsUrl[5]))
-
-    def _getWMSCapabilities(self):
-        # download the WMS Capabilities
-        url = self._getURLWithMap(self.service.mapfilename)
-        url = urlparse.urlparse(url)
-        params = urlparse.parse_qs(url[4])
-        params["REQUEST"] = "GetCapabilities"
-        params["SERVICE"] = "WMS"
-        params = urllib.unquote(urllib.urlencode(params,True))
-        attrs = (url[0],url[1],url[2],url[3],params,url[5])
-        logging.debug("GetCapabilities URL: " + urlparse.urlunparse(attrs))
-        resp = objectify.parse(urllib.urlopen(urlparse.urlunparse(attrs)))
-        return resp.getroot()
-

+ 0 - 30
tests/test_wcs.py

@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-import unittest
-from test_ows import TestOWS
-
-from OWS import *
-import wcs
-
-class TestWCS(TestOWS):
-
-    config = None
-    service = "WCS"
-
-    def test_getservice(self):
-
-        self.assertTrue(isinstance(self.service, wcs.WCS))
-        
-        mapObj = self.service.makeMap()
-
-        self.assertTrue(isinstance(mapObj, mapscript.mapObj))
-        self.assertEquals(mapObj.numlayers,1)
-
-        self.capabilities = self._getWMSCapabilities()
-        self.assertEquals(self.capabilities.Capability.tag,"{http://www.opengis.net/wms}Capability")
-        self.assertEquals(self.capabilities.Capability.Layer.Layer.Name.text, "dem")
-        self.assertEquals(self.capabilities.Capability.Layer.Layer.Abstract.text, "My abstract")
-
-if __name__ == "__main__":
-    unittest.main()

+ 0 - 46
tests/test_wfs.py

@@ -1,46 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-import os
-from test_ows import *
-
-import wfs
-import unittest
-import urllib
-import urlparse
-import mapscript
-from lxml import objectify
-from osgeo import ogr
-
-class TestWFS(TestOWS):
-
-    service = "WFS"
-
-    def test_getmapobj(self):
-
-        self.assertTrue(isinstance(self.service, wfs.WFS))
-        
-        mapObj = self.service.makeMap()
-
-        self.assertTrue(isinstance(mapObj, mapscript.mapObj))
-        self.assertEquals(mapObj.numlayers,1)
-        
-        layer = mapObj.getLayer(0)
-        self.assertEquals(layer.type,mapscript.MS_LAYER_LINE)
-
-        self.capabilities = self._getWMSCapabilities()
-        # test the wms capabilities document
-        self.assertEquals(self.capabilities.Capability.tag,"{http://www.opengis.net/wms}Capability")
-        self.assertEquals(self.capabilities.Capability.Layer.Layer.Name.text, "line")
-        self.assertEquals(self.capabilities.Capability.Layer.Layer.Abstract.text, "My abstract")
-        # test the wfs extent 
-        ds = ogr.Open(self.service.layerDefFile)
-        lineLayer = ds.GetLayer()
-        self.service.capabilities.attrib["version"] = "1.1.0"
-        self.assertEquals((48.152419, 12.735342, 51.431833, 18.612816),self.service.getLayerExtent(lineLayer))
-        self.service.capabilities.attrib["version"] = "1.0.0"
-        self.assertEquals((12.735342,48.152419,18.612816,51.431833),self.service.getLayerExtent(lineLayer))
-        self.service.capabilities.attrib["version"] = "1.1.0"
-
-if __name__ == "__main__":
-    unittest.main()

+ 0 - 169
wcs/__init__.py

@@ -1,169 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-from OWS import OWS
-import mapscript
-from osgeo import gdal
-from osgeo import ogr
-from osgeo import osr
-import os
-import logging
-import re
-
-class WCS(OWS):
-
-    service = "WCS"
-    request = '' # GetCapabilies, ...
-    parser = None
-    version = None
-
-    def __init__(self,url=None,qstring=None,configFile=None):
-        OWS.__init__(self,url,qstring,configFile)
-
-    def makeMap(self,mapfilename=None):
-        """Create mapscript.mapObj"""
-
-        lyrobj = None
-
-        self.version = self.capabilities.version
-
-        mapobj = self.getMapObj(mapfilename)
-    
-        # mapobjects exists, do not do any new layers
-        if mapobj.numlayers:
-            return mapobj
-
-        #
-        # for each layer from the WCS Capabilities file, transform it to
-        # mapscript.layerObj
-        #
-        for name in self.capabilities.contents:
-            layer = self.capabilities.contents[name]
-            logging.debug("Creating layer %s" % name)
-
-            # create layer definition file
-            # see http://www.gdal.org/frmt_wcs.html
-            layerDefFile = self.createLayerDefinitionFile(name,
-                    os.path.join( os.path.dirname(__file__), "templates",'wcs.xml'))
-
-            # create the layer
-            ds = gdal.Open(layerDefFile)
-
-            try:
-                lyrobj = mapscript.layerObj(mapobj)
-                lyrobj.name = name
-                lyrobj.data = layerDefFile
-                if layer.title:
-                    lyrobj.title = layer.title
-                    lyrobj.setMetaData("wms_title",layer.title)
-                #if "{%s}%s" % (self.owsns11,"Abstract") in layer:
-                #    lyrobj.setMetaData("ows_abstract",  layer["{%s}%s" % (self.owsns11,"Abstract")].text)
-                lyrobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
-                extent = None
-                # processing
-                if layer.crsOptions:
-                    lyrobj.setProjection(layer.crsOptions[0].getcode())
-                    extent = self.getLayerExtent(layer,layer.crsOptions[0])
-                elif  layer.supportedCRS:
-                    lyrobj.setProjection(layer.supportedCRS[0].getcode())
-                    extent = self.getLayerExtent(layer,layer.supportedCRS[0])
-                else:
-                    sr = osr.SpatialReference()
-                    sr.ImportFromWkt(ds.GetProjection())
-                    if sr.AutoIdentifyEPSG() == 0:
-                        epsg = "{code}:{value}".format(code=sr.GetAuthorityName("PROJCS"),value=sr.GetAuthorityCode("PROJCS"))
-                        extent = self.getLayerExtent(layer,epsg)
-                        lyrobj.setProjection(epsg)
-                    else:
-                        extent = self.getLayerExtent(layer,wkt=ds.GetProjection())
-                        lyrobj.setProjection(sr.ExportToProj4())
-                lyrobj.setMetaData("wms_extent","%s %s %s %s" % \
-                        (extent[0],extent[1],extent[2],extent[3]))
-                lyrobj.type = mapscript.MS_LAYER_RASTER
-                lyrobj.dump = mapscript.MS_TRUE
-                lyrobj.template = "foo"
-                
-                # bands
-                if layer.axisDescriptions:
-                    self._addBandsMetadata(layer, lyrobj)
-                if ds:
-                    self.getTime(ds,lyrobj)
-                cls = mapscript.classObj(lyrobj)
-                mapscript.styleObj(cls)
-            except Exception,e:
-                mapobj.removeLayer(lyrobj.index)
-                logging.warning("Layer %s: %s, skipping." %\
-                                (name,e.message))
-
-        self.saveMapfile(mapobj,mapfilename)
-        return mapobj
-
-    def getTime(self,ds,lyrobj):
-        """Generate time index file, set approripate layer metadata"""
-
-        # make time index file
-        drv = ogr.GetDriverByName("ESRI Shapefile")
-        tindex = '%s.%s.%s'%(lyrobj.name,self.service.lower(),"tindex")
-        logging.info("Creating time index definition file %s.shp in %s" % (tindex,self.cachedir))
-        tds = drv.CreateDataSource(os.path.join(self.cachedir,tindex))
-        lyr = tds.CreateLayer(tindex)
-        tile_field = ogr.FieldDefn("location", ogr.OFTString )
-        tile_field.SetWidth( 256 )
-        lyr.CreateField(tile_field)
-
-        time_field = ogr.FieldDefn("time", ogr.OFTString )
-        time_field.SetWidth( 256 )
-        lyr.CreateField(time_field)
-
-        timeMetadata = ""
-        for sds in ds.GetSubDatasets():
-            if sds[0].find('time') > -1:
-                # crate mapfile metadata
-                sdsname = sds[0].split(",")[0]
-                sdsvalue = re.findall(r'".*"',sdsname)[0].replace('"',"")
-                timeMetadata = timeMetadata+","+sdsvalue
-
-                # create OGR tindex vector feature
-                feature = ogr.Feature(lyr.GetLayerDefn())
-
-                # feature geometry
-                geotransform = ds.GetGeoTransform()
-                w = ds.RasterXSize
-                h = ds.RasterYSize
-                bbox = {"minx":geotransform[0],"miny":geotransform[5]*h+geotransform[3],"maxx":geotransform[1]*w+geotransform[0],"maxy":geotransform[3]}
-                poly = ogr.CreateGeometryFromWkt("""POLYGON((%(minx)s %(miny)s, %(maxx)s %(miny)s, %(maxx)s %(maxy)s, %(minx)s %(maxy)s, %(minx)s %(miny)s))""" % bbox)
-                feature.SetGeometry(poly)
-
-                # set time attribute
-                feature.SetField("time","%s" % (sdsvalue))
-                feature.SetField("location",sds[0])
-                lyr.CreateFeature(feature)
-
-        if timeMetadata.endswith(","):
-            timeMetadata = re.sub(r",$","",timeMetadata)
-        if timeMetadata.startswith(","):
-            timeMetadata = re.sub(r"^,","",timeMetadata)
-
-        if timeMetadata:
-            logging.info("Setting %s to %s layer" % (timeMetadata, lyrobj.name))
-
-            lyrobj.setMetaData("wms_timeextent", timeMetadata) 
-            lyrobj.setMetaData("wms_timeitem", "time") 
-
-            # NOTE: lyrobj.data will not be the wcs definition file
-            # anymore, BUT the time index shapefile
-            logging.info("Setting layer data to %s" %
-                    (os.path.join(tindex,tindex+".shp")))
-            lyrobj.data = None
-            lyrobj.tileindex = os.path.join(tindex,tindex+".shp")
-        else:
-            logging.info("No time subset found")
-
-    def _addBandsMetadata(self, layer, lyrobj):
-        """Adds wmcs_band* metadata to the lyrobj"""
-
-        for i in layer.axisDescriptions:
-            if i.name.lower() == "bands":
-                lyrobj.setMetaData("wcs_bandcount",str(len(i.values)))
-                lyrobj.setMetaData("wcs_rangeset_axes",str(i.name))
-                lyrobj.setMetaData("wcs_rangeset_name",str(i.name))

+ 0 - 7
wcs/templates/wcs.xml

@@ -1,7 +0,0 @@
-<WCS_GDAL>
-  <ServiceURL>$url</ServiceURL>
-  <CoverageName>$name</CoverageName>
-  <Timeout>5000</Timeout>
-  <GetCoverageExtras>$extras</GetCoverageExtras>
-  $time
-</WCS_GDAL>

+ 0 - 187
wfs/__init__.py

@@ -1,187 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-from OWS import OWS
-import mapscript
-import cgi
-from lxml import objectify
-import urllib
-import urlparse
-import logging
-from osgeo import ogr
-import pyproj
-import os
-import re
-
-class WFS(OWS):
-
-    service = "WFS"
-    wfsns = "http://www.opengis.net/wfs"
-    layerDefFile = None
-    lyrobj = None
-
-    def __init__(self,url=None,qstring=None,configFile=None):
-        OWS.__init__(self,url,qstring,configFile)
-
-    def makeMap(self,mapfilename=None):
-
-        mapobj = self.getMapObj(mapfilename)
-
-        # mapobjects exists, do not do any new layers
-        if mapobj.numlayers:
-            return mapobj
-
-        self.layerDefFile = self.createLayerDefinitionFile("wfs",
-                os.path.join( os.path.dirname(__file__), "templates",'wfs.xml'))
-
-        ds = ogr.Open(self.layerDefFile)
-
-        self.setMapName(mapobj)
-
-        logging.debug(self.capabilities.contents)
-
-        srss = []
-
-        for name in self.capabilities.contents:
-                
-            mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
-            mapobj.setMetaData("wfs_srs",self.config.get("MapServer","srs"))
-            layer = self.capabilities.contents[name]
-
-            logging.debug("Creating layer %s" % name)
-
-            srss = srss+filter(lambda y: not y in srss,layer.crsOptions)
-
-            lyrobj = mapscript.layerObj(mapobj)
-            #lyrobj.name = name.replace(":","_")
-            lyrobj.name = name
-            lyrobj.title = layer.title
-            if layer.title:
-                lyrobj.setMetaData("wms_title",layer.title)
-                lyrobj.setMetaData("wfs_title",layer.title)
-            #if layer.abstract:
-            #    lyrobj.setMetaData("ows_abstract",  layer.abstract)
-            lyrobj.setMetaData("wfs_typename", name)
-            logging.debug("WFS version %s",self.capabilities.version)
-            lyrobj.setMetaData("wfs_version",self.capabilities.version)
-            lyrobj.setMetaData("gml_include_items","all")
-            lyrobj.setMetaData("wfs_request_method","GET")
-            lyrobj.setConnectionType(mapscript.MS_WFS,'')
-            lyrobj.connection = self.getLayerUrl()
-            lyrobj.data = re.sub(r".*:","",name)
-            if ds:
-                ogrLayer = ds.GetLayerByName(name)
-                extent = self.getLayerExtent(layer,layer.crsOptions[0])
-                if extent:
-                    lyrobj.setMetaData("wms_extent","%s %s %s %s" % \
-                            (extent[0],extent[1],extent[2],extent[3]))
-                    lyrobj.setMetaData("wfs_extent","%s %s %s %s" % \
-                            (extent[0],extent[1],extent[2],extent[3]))
-                lyrobj.type = self._getLayerType(ogrLayer)
-            else:
-                mapobj.removeLayer(mapobj.numlayers-1)
-                logging.debug("No ogrDataSource found")
-                continue
-
-            #lyrobj.setProjection(self.__getLayerCrs(layer.crsOptions))
-            lyrobj.setProjection(layer.crsOptions[0].getcode())
-
-            lyrobj.dump = mapscript.MS_TRUE 
-            lyrobj.template = "foo"
-            cls = mapscript.classObj(lyrobj)
-            style = mapscript.styleObj(cls)
-            style.outlinecolor=mapscript.colorObj(134,81,0)
-            style.color=mapscript.colorObj(238,153,0)
-            style.size=5
-            style.width=5
-
-        ## overwrite already set SRSs
-        #if len(srss) > 0:
-        #    logging.debug("Overwriting SRS option")
-        #    mapobj.setMetaData("wms_srs"," ".join(srss))
-
-        self.saveMapfile(mapobj,mapfilename)
-        return mapobj
-    
-    def getGeomName(self,geomname):
-
-        if geomname.find("LINE") > -1:
-            return mapscript.MS_LAYER_LINE
-        elif geomname.find("POLYGON") > -1:
-            return mapscript.MS_LAYER_POLYGON
-        else:
-            return mapscript.MS_LAYER_POINT
-
-    def setMapName(self,mapobj):
-        mapobj.name = self.config.get("MapServer","name")
-
-        if self.capabilities.identification.title:
-            mapobj.setMetaData("wms_title",self.capabilities.identification.title)
-            mapobj.setMetaData("wfs_title",self.capabilities.identification.title)
-        if self.capabilities.identification.abstract:
-            mapobj.setMetaData("wms_abstract",self.capabilities.identification.abstract)
-            mapobj.setMetaData("wfs_abstract",self.capabilities.identification.abstract)
-
-    def _getLayerType(self,layer):
-        """Returns MS layer type based on ogr.Layer.GetGeomType
-
-        with ogr:
-
-            wkbGeometryCollection = 7
-            wkbGeometryCollection25D = -2147483641
-            wkbLineString = 2
-            wkbLineString25D = -2147483646
-            wkbLinearRing = 101
-            wkbMultiLineString = 5
-            wkbMultiLineString25D = -2147483643
-            wkbMultiPoint = 4
-            wkbMultiPoint25D = -2147483644
-            wkbMultiPolygon = 6
-            wkbMultiPolygon25D = -2147483642
-            wkbNDR = 1
-            wkbNone = 100
-            wkbPoint = 1
-            wkbPoint25D = -2147483647
-            wkbPolygon = 3
-            wkbPolygon25D = -2147483645
-            wkbUnknown = 0
-        """
-
-        geomType = layer.GetGeomType()
-        if geomType == 0: # unknown
-            # brutal force way
-            f = layer.GetNextFeature()
-            if f:
-                gr = f.GetGeometryRef()
-                geomType = gr.GetGeometryType()
-
-        if geomType in [ogr.wkbPolygon,
-                        ogr.wkbMultiPolygon,
-                        ogr.wkbLinearRing]:
-               return mapscript.MS_LAYER_POLYGON
-        elif geomType in [ogr.wkbLineString,
-                          ogr.wkbMultiLineString]:
-               return mapscript.MS_LAYER_LINE
-        else:
-               return mapscript.MS_LAYER_POINT
-
-    def __getLayerCrs(self,crss):
-        """
-        Returns bests (non-degree) coordinate system of the layer, which is
-        available.
-
-        Ofcourse, sometimes, there is no other option, there EPSG:4326, but
-        take somethign else, if you can
-        """
-        for crs in crss:
-            try:
-                proj = pyproj.Proj("+init=%s"%crs)
-                if proj.is_latlon():
-                    continue
-                else:
-                    return crs
-            except:
-                pass
-        return crss[0]
-
-

+ 0 - 3
wfs/templates/wfs.xml

@@ -1,3 +0,0 @@
-<OGRWFSDataSource>
-  <URL>$url</URL>
-</OGRWFSDataSource>

+ 0 - 116
wms/__init__.py

@@ -1,116 +0,0 @@
-#!/usr/bin/env python
-# coding=utf-8
-
-from OWS import OWS
-import mapscript
-from osgeo import gdal
-from osgeo import ogr
-from osgeo import osr
-import os
-import logging
-import re
-
-class WMS(OWS):
-
-    service = "WMS"
-    request = '' # GetCapabilies, ...
-    parser = None
-    version = None
-
-    def __init__(self,url=None,qstring=None,configFile=None):
-        OWS.__init__(self,url,qstring,configFile)
-
-    def makeMap(self,mapfilename=None):
-        """Create mapscript.mapObj"""
-
-        mapobj = self.getMapObj(mapfilename)
-
-
-        params = self.getParams()
-
-
-        self.version = params["VERSION"][0]
-
-        # create layer
-        logging.debug("Creating layer %s" % params["LAYERS"][0]) 
-        lyrobj = mapscript.layerObj(mapobj)
-        lyrobj.name = params["LAYERS"][0]
-        lyrobj.type = mapscript.MS_LAYER_RASTER
-        lyrobj.connection = params["OWSURL"][0]
-        lyrobj.status = mapscript.MS_DEFAULT
-        lyrobj.setConnectionType(mapscript.MS_WMS,None)
-        lyrobj.setMetaData("wms_srs",params["FROMCRS"][0])
-        lyrobj.setMetaData("wms_name",params["LAYERS"][0])
-        lyrobj.setMetaData("wms_server_version",params["VERSION"][0])
-	if params["VERSION"][0] == "1.3.0":
-		lyrobj.setMetaData("wms_server_version","1.1.1")
-        lyrobj.setMetaData("wms_exceptions_format",params["EXCEPTIONS"][0])
-        lyrobj.setMetaData("wms_formatlist",params["FORMAT"][0])
-        lyrobj.setMetaData("wms_style",params["STYLES"][0])
-        lyrobj.setMetaData("wms_transparent",params["TRANSPARENT"][0])
-        lyrobj.setMetaData("gml_include_items","all")
-        lyrobj.template = "foo"
-
-        self.saveMapfile(mapobj,mapfilename)
-        return mapobj
-
-    def getTime(self,ds,lyrobj):
-        """Generate time index file, set approripate layer metadata"""
-
-        # make time index file
-        drv = ogr.GetDriverByName("ESRI Shapefile")
-        tindex = '%s.%s.%s'%(lyrobj.name,self.service.lower(),"tindex")
-        logging.info("Creating time index definition file %s.shp in %s" % (tindex,self.cachedir))
-        tds = drv.CreateDataSource(os.path.join(self.cachedir,tindex))
-        lyr = tds.CreateLayer(tindex)
-        tile_field = ogr.FieldDefn("location", ogr.OFTString )
-        tile_field.SetWidth( 256 )
-        lyr.CreateField(tile_field)
-
-        time_field = ogr.FieldDefn("time", ogr.OFTString )
-        time_field.SetWidth( 256 )
-        lyr.CreateField(time_field)
-
-        timeMetadata = ""
-        for sds in ds.GetSubDatasets():
-            if sds[0].find('time') > -1:
-                # crate mapfile metadata
-                sdsname = sds[0].split(",")[0]
-                sdsvalue = re.findall(r'".*"',sdsname)[0].replace('"',"")
-                timeMetadata = timeMetadata+","+sdsvalue
-
-                # create OGR tindex vector feature
-                feature = ogr.Feature(lyr.GetLayerDefn())
-
-                # feature geometry
-                geotransform = ds.GetGeoTransform()
-                w = ds.RasterXSize
-                h = ds.RasterYSize
-                bbox = {"minx":geotransform[0],"miny":geotransform[5]*h+geotransform[3],"maxx":geotransform[1]*w+geotransform[0],"maxy":geotransform[3]}
-                poly = ogr.CreateGeometryFromWkt("""POLYGON((%(minx)s %(miny)s, %(maxx)s %(miny)s, %(maxx)s %(maxy)s, %(minx)s %(maxy)s, %(minx)s %(miny)s))""" % bbox)
-                feature.SetGeometry(poly)
-
-                # set time attribute
-                feature.SetField("time","%s" % (sdsvalue))
-                feature.SetField("location",sds[0])
-                lyr.CreateFeature(feature)
-
-        if timeMetadata.endswith(","):
-            timeMetadata = re.sub(r",$","",timeMetadata)
-        if timeMetadata.startswith(","):
-            timeMetadata = re.sub(r"^,","",timeMetadata)
-
-        if timeMetadata:
-            logging.info("Setting %s to %s layer" % (timeMetadata, lyrobj.name))
-
-            lyrobj.setMetaData("wms_timeextent", timeMetadata) 
-            lyrobj.setMetaData("wms_timeitem", "time") 
-
-            # NOTE: lyrobj.data will not be the wcs definition file
-            # anymore, BUT the time index shapefile
-            logging.info("Setting layer data to %s" %
-                    (os.path.join(tindex,tindex+".shp")))
-            lyrobj.data = None
-            lyrobj.tileindex = os.path.join(tindex,tindex+".shp")
-        else:
-            logging.info("No time subset found")