Esempio n. 1
0
    def dispatchRequest (self, environ, start_response):
        """Read in request data, and return a (content-type, response string) tuple. May
           raise an exception, which should be returned as a 500 error to the user."""
        
        dd = cgi.parse(None, environ)
        params = {}
        post_data = None
        accepts = None
        request_method = environ['REQUEST_METHOD']
        #if request_method in ['GET','OPTIONS']:
            #for k in dd.keys():
                #params[k.lower()] = dd[k][0]
        #elif request_method in ['POST']:    
            #buf = environ['wsgi.input'].read()
            #post_data = urllib.unquote_plus(buf)
        for k in dd.keys():
            params[k.lower()] = dd[k][0]
        buf = environ['wsgi.input'].read()
        post_data = urllib.unquote_plus(buf)
            
        #CESIUM_ACCESS_CONTROL_ALLOW_HEADERS = ',' + str(self.config['wfs']['cesium_access_control_allow_headers'])
        #for i in range()
        response_code = "200 OK"
        host = environ['SERVER_NAME']
        path_info = environ['PATH_INFO']
        request = None
        content_types = {
          'application/vnd.google-earth.kml+xml': 'KML',
          'application/json': 'GeoJSON',
          'text/javascript': 'GeoJSON',
          'application/rss+xml': 'GeoRSS',
          'text/html': 'HTML',
          'osm': 'OSM',
          'gml': 'WFS',
          'wfs': 'WFS',
          'kml': 'KML',
          'json': 'GeoJSON',
          'georss': 'GeoRSS',
          'atom': 'GeoRSS',
          'html': 'HTML',
          'geojson':'GeoJSON',
          'shp': 'SHP',
          'csv': 'CSV',
          'gpx': 'GPX',
          'ov2': 'OV2',
          'sqlite': 'SQLite',
          'dxf' : 'DXF'
        }
        
        exceptionReport = ExceptionReport()
        
        path = path_info.split("/")
        
        found = False
        
        format = None
        
        if params.has_key("format"):
            format = params['format']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True
        
        if not found and len(path) > 1:
            path_pieces = path[-1].split(".")
            if len(path_pieces) > 1:
                format = path_pieces[-1]
                if format.lower() in content_types:
                    format = content_types[format.lower()]
                    found = True
        
        if not found and not params.has_key("service") and post_data:
            try:
                dom = etree.XML(post_data)
                params['service'] = dom.get('service')
            except etree.ParseError: pass

        if not found and not params.has_key("version") and post_data:
            try:
                dom = etree.XML(post_data)
                params['version'] = dom.get('version')
            except etree.ParseError: pass
            
        if not found and not params.has_key("typename") and post_data:
            try:
                dom = etree.XML(post_data)
                for key, value in cgi.parse_qsl(post_data, keep_blank_values=True):
                    if key.lower() == 'typename':
                        params['typename'] = value
            except etree.ParseError: pass

        if not found and params.has_key("service"):
            format = params['service']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True
        
        if not found and accepts:
            if accepts.lower() in content_types:
                format = content_types[accepts.lower()]
                found = True
        
        if not found and not format:
            if self.metadata.has_key("default_service"):
                format = self.metadata['default_service']
            else:    
                format = "WFS"
        
                
        #===============================================================================
        # (reflection) dynamic load of format class e.g. WFS, KML, etc.
        # for supported format see package 'Service'
        #       -----------           -------
        #       | Request | <|------- | WFS |
        #       -----------           -------
        #===============================================================================
        service_module = __import__("FeatureServer.Service.%s" % format, globals(), locals(), format)
        service = getattr(service_module, format)
        request = service(self)
        
        response = []
        mime =  'text/xml;charset=' + ENCODING
        try:
            request.parse(params, path_info, host, post_data, request_method)
            
            # short circuit datasource where the first action is a metadata request. 
            if len(request.actions) and request.actions[0].method == "metadata":
                mime, msg = request.encode_metadata(request.actions[0])
                start_response(response_code, [('Content-Type', mime),('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type'), ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
                return [msg]

            # short circuit datasource where a OGC WFS request is set
            # processing by service
            if len(request.actions) > 0 and hasattr(request.actions[0], 'request') and request.actions[0].request is not None:
                version = '1.0.0'
                if hasattr(request.actions[0], 'version') and len(request.actions[0].version) > 0:
                    version = request.actions[0].version
                
                if request.actions[0].request.lower() == "getcapabilities":
                    s = getattr(request, request.actions[0].request.lower())(version)
                    start_response(response_code, [('Content-Length', str(len(s[1]))),('Content-Type', mime), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type' ), ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
                    return [s[1]]
                elif request.actions[0].request.lower() == "describefeaturetype":
                    s = getattr(request, request.actions[0].request.lower())(version)
                    start_response(response_code, [('Content-Length', str(len(s[1]))),('Content-Type', mime), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type'), ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
                    return [s[1]]

            datasource = self.datasources[request.actions[0].layer]

            if request_method != "GET" and hasattr(datasource, 'processes'):
                raise Exception("You can't post data to a processed layer.")

        
            try:
                datasource.begin()

                if len(request.actions) > 0 and hasattr(request.actions[0], 'request') and request.actions[0].request is not None:
                    if request.actions[0].request.lower() == "getfeature":
                        ''' '''

                try:
                    transactionResponse = TransactionResponse()
                    transactionResponse.setSummary(TransactionSummary())
                    
                    for action in request.actions:
                        method = getattr(datasource, action.method)
                        try:
                            result = method(action)
                            if isinstance(result, ActionResult):
                                transactionResponse.addResult(result)
                            elif result is not None:
                                response += result
                        except InvalidValueException as e:
                            exceptionReport.add(e)
    
                        datasource.commit()
                except:
                    datasource.rollback()
                    raise

                if hasattr(datasource, 'processes'):
                    for process in datasource.processes.split(","):
                        if not self.processes.has_key(process):
                            raise Exception("Process %s configured incorrectly. Possible processes: \n\n%s" % (process, ",".join(self.processes.keys() )))
                        response = self.processes[process].dispatch(features=response, params=params)
                if transactionResponse.summary.totalDeleted > 0 or transactionResponse.summary.totalInserted > 0 or transactionResponse.summary.totalUpdated > 0 or transactionResponse.summary.totalReplaced > 0:
                    response = transactionResponse

            except ConnectionException as e:
                exceptionReport.add(e)
    
        except LayerNotFoundException as e:
            exceptionReport.add(e)

        if len(exceptionReport) > 0:
            if self.metadata.has_key("default_exception"):
                service_module = __import__("Service.%s" % self.metadata['default_exception'], globals(), locals(), self.metadata['default_exception'])
                service = getattr(service_module, self.metadata['default_exception'])
                default_exception = service(self)
                
                if hasattr(default_exception, "default_exception"):
                    mime, data, headers, encoding = default_exception.encode_exception_report(exceptionReport)
                else:
                    raise Exception("Defined service of key 'default_exception' does not support encoding exception reports. Please use a supported service or disable this key.")
            else:
                # check if service supports exception encoding
                if hasattr(request, "encode_exception_report"):
                    mime, data, headers, encoding = request.encode_exception_report(exceptionReport)
                else:
                    # get default service and instantiate
                    service_module = __import__("Service.%s" % self.metadata['default_service'], globals(), locals(), self.metadata['default_service'])
                    service = getattr(service_module, self.metadata['default_service'])
                    default_service = service(self)
                
                    if hasattr(default_service, "encode_exception_report"):
                        mime, data, headers, encoding = default_service.encode_exception_report(exceptionReport)
                    else:
                        # load WFS for exception handling
                        from FeatureServer.Service.WFS import WFS
                        wfs_service = WFS(self)
                        mime, data, headers, encoding = wfs_service.encode_exception_report(exceptionReport)

        
        else:
            mime, data, headers, encoding = request.encode(response)
        mime = 'text/xml; subtype=gml/3.1.1'
        #mime = 'text/xml; subtype=gml/2.1.2'
        start_response(response_code, [('Server', 'ogc_server'), ('Content-Length', str(len(enc(data)))),('Content-Type', mime), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type'), ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
        #print(data)
        return [enc(data)]
Esempio n. 2
0
    def dispatchRequest(self,
                        base_path="",
                        path_info="/",
                        params={},
                        request_method="GET",
                        post_data=None,
                        accepts=""):
        """Read in request data, and return a (content-type, response string) tuple. May
           raise an exception, which should be returned as a 500 error to the user."""
        response_code = "200 OK"
        host = base_path
        request = None
        content_types = {
            'application/vnd.google-earth.kml+xml': 'KML',
            'application/json': 'GeoJSON',
            'text/javascript': 'GeoJSON',
            'application/rss+xml': 'GeoRSS',
            'text/html': 'HTML',
            'osm': 'OSM',
            'gml': 'WFS',
            'wfs': 'WFS',
            'kml': 'KML',
            'json': 'GeoJSON',
            'georss': 'GeoRSS',
            'atom': 'GeoRSS',
            'html': 'HTML',
            'geojson': 'GeoJSON',
            'shp': 'SHP',
            'csv': 'CSV',
            'gpx': 'GPX',
            'ov2': 'OV2',
            'sqlite': 'SQLite',
            'dxf': 'DXF'
        }

        exceptionReport = ExceptionReport()

        path = path_info.split("/")

        found = False

        format = ""

        if params.has_key("format"):
            format = params['format']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True

        if not found and len(path) > 1:
            path_pieces = path[-1].split(".")
            if len(path_pieces) > 1:
                format = path_pieces[-1]
                if format.lower() in content_types:
                    format = content_types[format.lower()]
                    found = True

        if not found and not params.has_key("service") and post_data:
            try:
                dom = etree.XML(post_data)
                params['service'] = dom.get('service')
            except etree.ParseError:
                pass

        if not found and not params.has_key("version") and post_data:
            try:
                dom = etree.XML(post_data)
                params['version'] = dom.get('version')
            except etree.ParseError:
                pass

        if not found and not params.has_key("typename") and post_data:
            try:
                dom = etree.XML(post_data)
                for key, value in cgimod.parse_qsl(post_data,
                                                   keep_blank_values=True):
                    if key.lower() == 'typename':
                        params['typename'] = value
            except etree.ParseError:
                pass

        if not found and params.has_key("service"):
            format = params['service']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True

        if not found and accepts:
            if accepts.lower() in content_types:
                format = content_types[accepts.lower()]
                found = True

        if not found and not format:
            if self.metadata.has_key("default_service"):
                format = self.metadata['default_service']
            else:
                format = "WFS"

        #===============================================================================
        # (reflection) dynamic load of format class e.g. WFS, KML, etc.
        # for supported format see package 'Service'
        #       -----------           -------
        #       | Request | <|------- | WFS |
        #       -----------           -------
        #===============================================================================
        service_module = __import__("Service.%s" % format, globals(), locals(),
                                    format)
        service = getattr(service_module, format)
        request = service(self)

        response = []

        try:
            request.parse(params, path_info, host, post_data, request_method)

            # short circuit datasource where the first action is a metadata request.
            if len(request.actions
                   ) and request.actions[0].method == "metadata":
                return request.encode_metadata(request.actions[0])

            # short circuit datasource where a OGC WFS request is set
            # processing by service
            if len(request.actions) > 0 and hasattr(
                    request.actions[0],
                    'request') and request.actions[0].request is not None:
                version = '1.0.0'
                if hasattr(request.actions[0],
                           'version') and len(request.actions[0].version) > 0:
                    version = request.actions[0].version

                if request.actions[0].request.lower() == "getcapabilities":
                    return getattr(request,
                                   request.actions[0].request.lower())(version)
                elif request.actions[0].request.lower(
                ) == "describefeaturetype":
                    return getattr(request,
                                   request.actions[0].request.lower())(version)

            datasource = self.datasources[request.datasources[0]]

            if request_method != "GET" and hasattr(datasource, 'processes'):
                raise Exception("You can't post data to a processed layer.")

            try:
                datasource.begin()

                if len(request.actions) > 0 and hasattr(
                        request.actions[0],
                        'request') and request.actions[0].request is not None:
                    if request.actions[0].request.lower() == "getfeature":
                        ''' '''

                try:
                    transactionResponse = TransactionResponse()
                    transactionResponse.setSummary(TransactionSummary())

                    for action in request.actions:
                        method = getattr(datasource, action.method)
                        try:
                            result = method(action)
                            if isinstance(result, ActionResult):
                                transactionResponse.addResult(result)
                            elif result is not None:
                                response += result
                        except InvalidValueException as e:
                            exceptionReport.add(e)

                        datasource.commit()
                except:
                    datasource.rollback()
                    raise

                if hasattr(datasource, 'processes'):
                    for process in datasource.processes.split(","):
                        if not self.processes.has_key(process):
                            raise Exception(
                                "Process %s configured incorrectly. Possible processes: \n\n%s"
                                % (process, ",".join(self.processes.keys())))
                        response = self.processes[process].dispatch(
                            features=response, params=params)
                if transactionResponse.summary.totalDeleted > 0 or transactionResponse.summary.totalInserted > 0 or transactionResponse.summary.totalUpdated > 0 or transactionResponse.summary.totalReplaced > 0:
                    response = transactionResponse

            except ConnectionException as e:
                exceptionReport.add(e)

        except LayerNotFoundException as e:
            exceptionReport.add(e)

        if len(exceptionReport) > 0:
            if self.metadata.has_key("default_exception"):
                service_module = __import__(
                    "Service.%s" % self.metadata['default_exception'],
                    globals(), locals(), self.metadata['default_exception'])
                service = getattr(service_module,
                                  self.metadata['default_exception'])
                default_exception = service(self)

                if hasattr(default_exception, "default_exception"):
                    mime, data, headers, encoding = default_exception.encode_exception_report(
                        exceptionReport)
                else:
                    raise Exception(
                        "Defined service of key 'default_exception' does not support encoding exception reports. Please use a supported service or disable this key."
                    )
            else:
                # check if service supports exception encoding
                if hasattr(request, "encode_exception_report"):
                    mime, data, headers, encoding = request.encode_exception_report(
                        exceptionReport)
                else:
                    # get default service and instantiate
                    service_module = __import__(
                        "Service.%s" % self.metadata['default_service'],
                        globals(), locals(), self.metadata['default_service'])
                    service = getattr(service_module,
                                      self.metadata['default_service'])
                    default_service = service(self)

                    if hasattr(default_service, "encode_exception_report"):
                        mime, data, headers, encoding = default_service.encode_exception_report(
                            exceptionReport)
                    else:
                        # load WFS for exception handling
                        from FeatureServer.Service.WFS import WFS
                        wfs_service = WFS(self)
                        mime, data, headers, encoding = wfs_service.encode_exception_report(
                            exceptionReport)

        else:
            mime, data, headers, encoding = request.encode(response)

        return Response(data=data,
                        content_type=mime,
                        headers=headers,
                        status_code=response_code,
                        encoding=encoding)
Esempio n. 3
0
    def dispatchRequest (self, base_path="", path_info="/", params={}, request_method = "GET", post_data = None,  accepts = ""):
        """Read in request data, and return a (content-type, response string) tuple. May
           raise an exception, which should be returned as a 500 error to the user."""
        response_code = "200 OK"
        host = base_path
        request = None
        content_types = {
          'application/vnd.google-earth.kml+xml': 'KML',
          'application/json': 'GeoJSON',
          'text/javascript': 'GeoJSON',
          'application/rss+xml': 'GeoRSS',
          'text/html': 'HTML',
          'osm': 'OSM',
          'gml': 'WFS',
          'wfs': 'WFS',
          'wkt': 'WKT',
          'kml': 'KML',
          'json': 'GeoJSON',
          'georss': 'GeoRSS',
          'atom': 'GeoRSS',
          'html': 'HTML',
          'geojson':'GeoJSON',
          'shp': 'SHP',
          'csv': 'CSV',
          'gpx': 'GPX',
          'ov2': 'OV2',
          'sqlite': 'SQLite',
          'dxf' : 'DXF'
        }
        
        exceptionReport = ExceptionReport()
        
        path = path_info.split("/")
        
        found = False
        
        format = ""
        
        # support legacy format parameter
        if params.has_key("format"):
            format = params['format']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True
        
        if not found and len(path) > 1:
            path_pieces = path[-1].split(".")
            if len(path_pieces) > 1:
                format = path_pieces[-1]
                if format.lower() in content_types:
                    format = content_types[format.lower()]
                    found = True
        
        if not found and not params.has_key("service") and post_data:
            try:
                dom = etree.XML(post_data)
                params['service'] = dom.get('service')
            except etree.ParseError: pass

        if not found and not params.has_key("version") and post_data:
            try:
                dom = etree.XML(post_data)
                params['version'] = dom.get('version')
            except etree.ParseError: pass
            
        if not found and not params.has_key("typename") and post_data:
            try:
                dom = etree.XML(post_data)
                for key, value in cgimod.parse_qsl(post_data, keep_blank_values=True):
                    if key.lower() == 'typename':
                        params['typename'] = value
            except etree.ParseError: pass

        if not found and params.has_key("service"):
            format = params['service']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True
        
        if not found and accepts:
            if accepts.lower() in content_types:
                format = content_types[accepts.lower()]
                found = True
        
        if not found and not format:
            if self.metadata.has_key("default_service"):
                format = self.metadata['default_service']
            else:    
                format = "WFS"
        
                
        #===============================================================================
        # (reflection) dynamic load of format class e.g. WFS, KML, etc.
        # for supported format see package 'Service'
        #       -----------           -------
        #       | Request | <|------- | WFS |
        #       -----------           -------
        #===============================================================================
        service_module = __import__("Service.%s" % format, globals(), locals(), format)
        service = getattr(service_module, format)
        request = service(self)
        
        response = []
        
        try:
            request.parse(params, path_info, host, post_data, request_method)
            
            # short circuit datasource where the first action is a metadata request. 
            if len(request.actions) and request.actions[0].method == "metadata": 
                return request.encode_metadata(request.actions[0])

            # short circuit datasource where a OGC WFS request is set
            # processing by service
            if len(request.actions) > 0 and hasattr(request.actions[0], 'request') and request.actions[0].request is not None:
                version = '1.0.0'
                if hasattr(request.actions[0], 'version') and len(request.actions[0].version) > 0:
                    version = request.actions[0].version
                
                if request.actions[0].request.lower() == "getcapabilities":
                    return getattr(request, request.actions[0].request.lower())(version)
                elif request.actions[0].request.lower() == "describefeaturetype":
                    return getattr(request, request.actions[0].request.lower())(version)

            # now what if we have multiple data sources?
            datasource = self.datasources[request.datasources[0]]

            if request_method != "GET" and hasattr(datasource, 'processes'):
                raise Exception("You can't post data to a processed layer.")
        
            try:
                datasource.begin()

                if len(request.actions) > 0 and hasattr(request.actions[0], 'request') and request.actions[0].request is not None:
                    if request.actions[0].request.lower() == "getfeature":
                        ''' '''

                try:
                    transactionResponse = TransactionResponse()
                    transactionResponse.setSummary(TransactionSummary())
                    
                    for action in request.actions:
                        method = getattr(datasource, action.method)
                        try:
                            result = method(action)
                            if isinstance(result, ActionResult):
                                transactionResponse.addResult(result)
                            elif result is not None:
                                response += result
                        except InvalidValueException as e:
                            exceptionReport.add(e)
    
                        datasource.commit()
                except:
                    datasource.rollback()
                    raise

                if hasattr(datasource, 'processes'):
                    for process in datasource.processes.split(","):
                        if not self.processes.has_key(process):
                            raise Exception("Process %s configured incorrectly. Possible processes: \n\n%s" % (process, ",".join(self.processes.keys() )))
                        response = self.processes[process].dispatch(features=response, params=params)
                if transactionResponse.summary.totalDeleted > 0 or transactionResponse.summary.totalInserted > 0 or transactionResponse.summary.totalUpdated > 0 or transactionResponse.summary.totalReplaced > 0:
                    response = transactionResponse

            except ConnectionException as e:
                exceptionReport.add(e)
    
        except LayerNotFoundException as e:
            exceptionReport.add(e)

        if len(exceptionReport) > 0:
            if self.metadata.has_key("default_exception"):
                service_module = __import__("Service.%s" % self.metadata['default_exception'], globals(), locals(), self.metadata['default_exception'])
                service = getattr(service_module, self.metadata['default_exception'])
                default_exception = service(self)
                
                if hasattr(default_exception, "default_exception"):
                    mime, data, headers, encoding = default_exception.encode_exception_report(exceptionReport)
                else:
                    raise Exception("Defined service of key 'default_exception' does not support encoding exception reports. Please use a supported service or disable this key.")
            else:
                # check if service supports exception encoding
                if hasattr(request, "encode_exception_report"):
                    mime, data, headers, encoding = request.encode_exception_report(exceptionReport)
                else:
                    # get default service and instantiate
                    service_module = __import__("Service.%s" % self.metadata['default_service'], globals(), locals(), self.metadata['default_service'])
                    service = getattr(service_module, self.metadata['default_service'])
                    default_service = service(self)
                
                    if hasattr(default_service, "encode_exception_report"):
                        mime, data, headers, encoding = default_service.encode_exception_report(exceptionReport)
                    else:
                        # load WFS for exception handling
                        from FeatureServer.Service.WFS import WFS
                        wfs_service = WFS(self)
                        mime, data, headers, encoding = wfs_service.encode_exception_report(exceptionReport)

        
        else:
            mime, data, headers, encoding = request.encode(response)

        return Response(data=data, content_type=mime, headers=headers, status_code=response_code, encoding=encoding)     
Esempio n. 4
0
    def dispatchRequest(self, environ, start_response):
        """Read in request data, and return a (content-type, response string) tuple. May
           raise an exception, which should be returned as a 500 error to the user."""

        dd = cgi.parse(None, environ)
        params = {}
        post_data = None
        accepts = None
        request_method = environ['REQUEST_METHOD']
        #if request_method in ['GET','OPTIONS']:
        #for k in dd.keys():
        #params[k.lower()] = dd[k][0]
        #elif request_method in ['POST']:
        #buf = environ['wsgi.input'].read()
        #post_data = urllib.unquote_plus(buf)
        for k in dd.keys():
            params[k.lower()] = dd[k][0]
        buf = environ['wsgi.input'].read()
        post_data = urllib.unquote_plus(buf)

        #CESIUM_ACCESS_CONTROL_ALLOW_HEADERS = ',' + str(self.config['wfs']['cesium_access_control_allow_headers'])
        #for i in range()
        response_code = "200 OK"
        host = environ['SERVER_NAME']
        path_info = environ['PATH_INFO']
        request = None
        content_types = {
            'application/vnd.google-earth.kml+xml': 'KML',
            'application/json': 'GeoJSON',
            'text/javascript': 'GeoJSON',
            'application/rss+xml': 'GeoRSS',
            'text/html': 'HTML',
            'osm': 'OSM',
            'gml': 'WFS',
            'wfs': 'WFS',
            'kml': 'KML',
            'json': 'GeoJSON',
            'georss': 'GeoRSS',
            'atom': 'GeoRSS',
            'html': 'HTML',
            'geojson': 'GeoJSON',
            'shp': 'SHP',
            'csv': 'CSV',
            'gpx': 'GPX',
            'ov2': 'OV2',
            'sqlite': 'SQLite',
            'dxf': 'DXF'
        }

        exceptionReport = ExceptionReport()

        path = path_info.split("/")

        found = False

        format = None

        if params.has_key("format"):
            format = params['format']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True

        if not found and len(path) > 1:
            path_pieces = path[-1].split(".")
            if len(path_pieces) > 1:
                format = path_pieces[-1]
                if format.lower() in content_types:
                    format = content_types[format.lower()]
                    found = True

        if not found and not params.has_key("service") and post_data:
            try:
                dom = etree.XML(post_data)
                params['service'] = dom.get('service')
            except etree.ParseError:
                pass

        if not found and not params.has_key("version") and post_data:
            try:
                dom = etree.XML(post_data)
                params['version'] = dom.get('version')
            except etree.ParseError:
                pass

        if not found and not params.has_key("typename") and post_data:
            try:
                dom = etree.XML(post_data)
                for key, value in cgi.parse_qsl(post_data,
                                                keep_blank_values=True):
                    if key.lower() == 'typename':
                        params['typename'] = value
            except etree.ParseError:
                pass

        if not found and params.has_key("service"):
            format = params['service']
            if format.lower() in content_types:
                format = content_types[format.lower()]
                found = True

        if not found and accepts:
            if accepts.lower() in content_types:
                format = content_types[accepts.lower()]
                found = True

        if not found and not format:
            if self.metadata.has_key("default_service"):
                format = self.metadata['default_service']
            else:
                format = "WFS"

        #===============================================================================
        # (reflection) dynamic load of format class e.g. WFS, KML, etc.
        # for supported format see package 'Service'
        #       -----------           -------
        #       | Request | <|------- | WFS |
        #       -----------           -------
        #===============================================================================
        service_module = __import__("FeatureServer.Service.%s" % format,
                                    globals(), locals(), format)
        service = getattr(service_module, format)
        request = service(self)

        response = []
        mime = 'text/xml;charset=' + ENCODING
        try:
            request.parse(params, path_info, host, post_data, request_method)

            # short circuit datasource where the first action is a metadata request.
            if len(request.actions
                   ) and request.actions[0].method == "metadata":
                mime, msg = request.encode_metadata(request.actions[0])
                start_response(
                    response_code,
                    [('Content-Type', mime),
                     ('Access-Control-Allow-Origin', '*'),
                     ('Access-Control-Allow-Headers',
                      'X-Requested-With,Content-Type'),
                     ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
                return [msg]

            # short circuit datasource where a OGC WFS request is set
            # processing by service
            if len(request.actions) > 0 and hasattr(
                    request.actions[0],
                    'request') and request.actions[0].request is not None:
                version = '1.0.0'
                if hasattr(request.actions[0],
                           'version') and len(request.actions[0].version) > 0:
                    version = request.actions[0].version

                if request.actions[0].request.lower() == "getcapabilities":
                    s = getattr(request,
                                request.actions[0].request.lower())(version)
                    start_response(response_code, [
                        ('Content-Length', str(len(s[1]))),
                        ('Content-Type', mime),
                        ('Access-Control-Allow-Origin', '*'),
                        ('Access-Control-Allow-Headers',
                         'X-Requested-With,Content-Type'),
                        ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
                    ])
                    return [s[1]]
                elif request.actions[0].request.lower(
                ) == "describefeaturetype":
                    s = getattr(request,
                                request.actions[0].request.lower())(version)
                    start_response(response_code, [
                        ('Content-Length', str(len(s[1]))),
                        ('Content-Type', mime),
                        ('Access-Control-Allow-Origin', '*'),
                        ('Access-Control-Allow-Headers',
                         'X-Requested-With,Content-Type'),
                        ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
                    ])
                    return [s[1]]

            datasource = self.datasources[request.actions[0].layer]

            if request_method != "GET" and hasattr(datasource, 'processes'):
                raise Exception("You can't post data to a processed layer.")

            try:
                datasource.begin()

                if len(request.actions) > 0 and hasattr(
                        request.actions[0],
                        'request') and request.actions[0].request is not None:
                    if request.actions[0].request.lower() == "getfeature":
                        ''' '''

                try:
                    transactionResponse = TransactionResponse()
                    transactionResponse.setSummary(TransactionSummary())

                    for action in request.actions:
                        method = getattr(datasource, action.method)
                        try:
                            result = method(action)
                            if isinstance(result, ActionResult):
                                transactionResponse.addResult(result)
                            elif result is not None:
                                response += result
                        except InvalidValueException as e:
                            exceptionReport.add(e)

                        datasource.commit()
                except:
                    datasource.rollback()
                    raise

                if hasattr(datasource, 'processes'):
                    for process in datasource.processes.split(","):
                        if not self.processes.has_key(process):
                            raise Exception(
                                "Process %s configured incorrectly. Possible processes: \n\n%s"
                                % (process, ",".join(self.processes.keys())))
                        response = self.processes[process].dispatch(
                            features=response, params=params)
                if transactionResponse.summary.totalDeleted > 0 or transactionResponse.summary.totalInserted > 0 or transactionResponse.summary.totalUpdated > 0 or transactionResponse.summary.totalReplaced > 0:
                    response = transactionResponse

            except ConnectionException as e:
                exceptionReport.add(e)

        except LayerNotFoundException as e:
            exceptionReport.add(e)

        if len(exceptionReport) > 0:
            if self.metadata.has_key("default_exception"):
                service_module = __import__(
                    "Service.%s" % self.metadata['default_exception'],
                    globals(), locals(), self.metadata['default_exception'])
                service = getattr(service_module,
                                  self.metadata['default_exception'])
                default_exception = service(self)

                if hasattr(default_exception, "default_exception"):
                    mime, data, headers, encoding = default_exception.encode_exception_report(
                        exceptionReport)
                else:
                    raise Exception(
                        "Defined service of key 'default_exception' does not support encoding exception reports. Please use a supported service or disable this key."
                    )
            else:
                # check if service supports exception encoding
                if hasattr(request, "encode_exception_report"):
                    mime, data, headers, encoding = request.encode_exception_report(
                        exceptionReport)
                else:
                    # get default service and instantiate
                    service_module = __import__(
                        "Service.%s" % self.metadata['default_service'],
                        globals(), locals(), self.metadata['default_service'])
                    service = getattr(service_module,
                                      self.metadata['default_service'])
                    default_service = service(self)

                    if hasattr(default_service, "encode_exception_report"):
                        mime, data, headers, encoding = default_service.encode_exception_report(
                            exceptionReport)
                    else:
                        # load WFS for exception handling
                        from FeatureServer.Service.WFS import WFS
                        wfs_service = WFS(self)
                        mime, data, headers, encoding = wfs_service.encode_exception_report(
                            exceptionReport)

        else:
            mime, data, headers, encoding = request.encode(response)
        mime = 'text/xml; subtype=gml/3.1.1'
        #mime = 'text/xml; subtype=gml/2.1.2'
        start_response(
            response_code,
            [('Server', 'ogc_server'), ('Content-Length', str(len(enc(data)))),
             ('Content-Type', mime), ('Access-Control-Allow-Origin', '*'),
             ('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type'),
             ('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')])
        #print(data)
        return [enc(data)]