瀏覽代碼

added OwsException; added test parse xml request

Piotr Labudda 8 年之前
父節點
當前提交
e53f3f97e9
共有 5 個文件被更改,包括 197 次插入20 次删除
  1. 60 0
      SE/se-lib/Api/OwsException.php
  2. 3 0
      SE/se-lib/Api/Wps.php
  3. 16 0
      SE/se-lib/Api/WpsHelper.php
  4. 24 20
      SE/se-lib/Api/WpsV1/Server.php
  5. 94 0
      SE/se-lib/Api/WpsV1/ServerBase.php

+ 60 - 0
SE/se-lib/Api/OwsException.php

@@ -0,0 +1,60 @@
+<?php
+
+// @usage: throw new Api_OwsException("Access Denied to Create field '{$fieldName}' in object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingFieldPermCreate', 'request');
+
+// example:
+// <ows:ExceptionReport
+//	 xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/ows/1.1 https://demo.boundlessgeo.com/geoserver/schemas/ows/1.1.0/owsAll.xsd">
+//	 <ows:Exception exceptionCode="MissingParameterValue" locator="request">
+//		 <ows:ExceptionText>Could not determine geoserver request from http request org.geoserver.platform.AdvancedDispatchFilter$AdvancedDispatchHttpRequest@4183f02c</ows:ExceptionText>
+//	 </ows:Exception>
+// </ows:ExceptionReport>
+
+class Api_OwsException extends Exception {
+
+	public $wfsCode = '';
+	public $wfsLocator = '';
+
+	public function __construct($message, $code = 0, Exception $previous = null, $wfsCode = '', $wfsLocator = '') {
+		$this->wfsCode = $wfsCode;
+		$this->wfsLocator = $wfsLocator;
+		parent::__construct($message, $code, $previous);
+	}
+
+	public function generateResponseXml() {
+		$xmlWriter = new XMLWriter();
+		if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
+		// $xmlWriter->openUri('php://output');
+		$xmlWriter->openMemory();
+		$xmlWriter->setIndent(true);
+		$xmlWriter->startDocument('1.0','UTF-8');
+		$xmlWriter->startElement('ows:ExceptionReport');
+		{
+			$xmlWriter->writeAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
+			$xmlWriter->writeAttribute('xmlns:ows', 'http://www.opengis.net/ows/1.1');
+			$xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+			$xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.opengis.net/ows/1.1 https://demo.boundlessgeo.com/geoserver/schemas/ows/1.1.0/owsAll.xsd');
+			$xmlWriter->writeAttribute('version', '1.1.0');
+			$xmlWriter->startElement('ows:Exception');
+			{
+				if ($this->wfsCode) $xmlWriter->writeAttribute('exceptionCode', $this->wfsCode);
+				if ($this->wfsLocator) $xmlWriter->writeAttribute('locator', $this->wfsLocator);
+				$xmlWriter->startElement('ows:ExceptionText');
+				{
+					$xmlWriter->text($this->message);
+				}
+				$xmlWriter->endElement();// ows:ExceptionText
+			}
+			$xmlWriter->endElement();// ows:Exception
+		}
+		$xmlWriter->endElement();// ows:ExceptionReport
+		$xmlWriter->endDocument();
+		return $xmlWriter->outputMemory(true);
+	}
+
+	public function sendResponseXml() {
+		header('Content-type: application/xml');
+		echo $this->generateResponseXml();
+	}
+
+}

+ 3 - 0
SE/se-lib/Api/Wps.php

@@ -69,6 +69,9 @@ class Api_Wps extends ApiRouteBase {// TODO: extends Api_WfsBase which extends A
 			$wfsServer->setBaseUri($this->_apiBaseUri);
 			$wfsServer->run($request);
 			exit;// TODO:? return $document;
+		} catch (Api_OwsException $e) {
+			DBG::logAuth($e);
+			$e->sendResponseXml();
 		} catch (Api_WfsException $e) {
 			DBG::logAuth($e);
 			$e->sendResponseXml();

+ 16 - 0
SE/se-lib/Api/WpsHelper.php

@@ -1,6 +1,7 @@
 <?php
 
 Lib::loadClass('Type_WpsProcess');
+Lib::loadClass('Api_OwsException');
 
 class Api_WpsHelper {
 
@@ -73,4 +74,19 @@ class Api_WpsHelper {
 		return $defaultWpsProcessList;
 	}
 
+	static function validateProcessArgs($wpsProcess, $args) {
+		foreach ($wpsProcess->dataInputs as $input) {
+			$identifier = $input->identifier;
+			// TODO: required? minOccurs > 0
+			if ($input->minOccurs > 0 && empty($args[ $identifier ])) throw new Api_OwsException("Missing value for '{$identifier}'", 501, null, 'MissingParameterValue', 'request');
+			$totalValues = count($args[ $identifier ]);
+			if ($totalValues > 1) {
+				if ( 'unbounded' !== $input->maxOccurs && $totalValues > $input->maxOccurs ) {
+					throw new Api_OwsException("Too many values for '{$identifier}'", 501, null, 'TooManyParameterValues', 'request');
+				}
+			}
+			// TODO: validate values with type definition - _xsdType
+		}
+	}
+
 }

+ 24 - 20
SE/se-lib/Api/WpsV1/Server.php

@@ -23,11 +23,11 @@ class Api_WpsV1_Server extends Api_WpsV1_ServerBase {
 
 	public function run(Type_ApiRequest $request) {
 		$document = '';
-		if ('WPS' != V::geti('service', '', $request->query)) {
-			throw new Api_WfsException("Only WPS Service is allowed");
-		}
 		$req = V::geti('request', '', $request->query);
 		if (!empty($req)) {
+			if ('WPS' != V::geti('service', '', $request->query)) {
+				throw new Api_WfsException("Only WPS Service is allowed");
+			}
 			$methodName = "{$req}Action";
 			if (!method_exists($this, $methodName)) {
 				throw new Api_WfsException("Not Implemented " . htmlspecialchars($req), 501);
@@ -54,27 +54,31 @@ class Api_WpsV1_Server extends Api_WpsV1_ServerBase {
 		}
 	}
 
-	public function parseXMLRequest() {
+	function parseXMLRequest() {
 		$data = array();
+		$tags = [];
 		$reqContent = Request::getRequestBody();
-		if (empty($reqContent)) {
-			throw new Exception("Empty request");
-		}
-		$parserXml = xml_parser_create();
-		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
-		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
-		if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) {
-			throw new Exception("Error parsing xml");
-		}
-		xml_parser_free($parserXml);
-		if (empty($tags)) {
-			throw new Exception("Empty structure from request");
-		}
+		if (empty($reqContent)) throw new Exception("Empty request");
 
-		$rootTagName = V::get('tag', '', $tags[0]);
-		if ('Transaction' == $rootTagName) return $this->_parseTransactionXmlStruct($reqContent, $tags);
+		Lib::loadClass('XML');
+		$xml = XML::xmlToArray($reqContent);
+		if (empty($xml)) throw new Exception("Error structure from request");
 
-		throw new Api_WfsException("Not implemented '{$rootTagName}' #L." . __LINE__, 501);
+		$rootTagName = $xml[0];
+		switch ($rootTagName) {
+			case 'wps:Execute': return $this->_runExecute($xml);
+			default: throw new Api_WfsException("Not implemented WPS xml request '{$rootTagName}'" . __LINE__, 501);
+		}
+	}
+	function _runExecute($xml) {
+		$funInfo = self::_parseExecuteXmlArray($xml);
+		print_r($funInfo);
+		$identifier = V::get('identifier', '', $funInfo);
+		$args = V::get('args', [], $funInfo, 'array');
+		if (empty($identifier)) throw new Exception("Parse xml request error - missing identifier");
+		Lib::loadClass('Api_WpsHelper');
+		$wpsProcess = Api_WpsHelper::getUserWpsProcess($identifier);
+		Api_WpsHelper::validateProcessArgs($wpsProcess, $args);
 	}
 
 	function describeProcessAction() {

+ 94 - 0
SE/se-lib/Api/WpsV1/ServerBase.php

@@ -95,6 +95,100 @@ class Api_WpsV1_ServerBase {
 		return $usrObjList;
 	}
 
+	static function convertWpsExecuteDataInputsXmlArrayToArgs($tagDataInputs) {
+		if (empty($tagDataInputs)) throw new Exception("Missing wps:DataInputs");
+		if (empty($tagDataInputs[2])) throw new Exception("Missing wps:DataInputs child nodes");
+		$tagsInput = array_filter($tagDataInputs[2], function ($tag) {
+			return ( 'wps:Input' === $tag[0] );
+		});
+		if (empty($tagsInput)) throw new Exception("Missing wps:DataInputs child nodes");
+
+		$args = [];
+		foreach ($tagsInput as $tagInput) {
+			list($key, $value) = self::convertWpsExecuteInputXmlArrayToArg($tagInput);
+			$args[ $key ][] = $value;
+		}
+		// echo "\$tagDataInputs[2]:"; print_r($tagDataInputs[2]);
+		// echo "\$tagsInput:"; print_r($tagsInput);
+		return $args;
+	}
+	static function convertWpsExecuteInputXmlArrayToArg($tagInput) {
+		if (empty($tagInput)) throw new Exception("Missing wps:Input");
+		if (empty($tagInput[2])) throw new Exception("Missing wps:Input child nodes");
+		$tagsIdentifier = array_filter($tagInput[2], function ($tag) {
+			return ( 'ows:Identifier' === $tag[0] );
+		});
+		$tagIdentifier = reset($tagsIdentifier);
+		$identifier = (!empty($tagIdentifier[2][0])) ? $tagIdentifier[2][0] : null;
+		if (empty($identifier)) throw new Exception("Missing wps:Input/ows:Identifier");
+
+		$tagsData = array_filter($tagInput[2], function ($tag) {
+			return ( 'wps:Data' === $tag[0] );
+		});
+		$tagData = reset($tagsData);
+		if (empty($tagData)) throw new Exception("Missing wps:Input/wps:Data");
+
+		$data = self::convertWpsExecuteInputDataXmlArrayToValue($tagData);
+
+		return [ $identifier, $data ];
+	}
+	static function convertWpsExecuteInputDataXmlArrayToValue($tagData) {
+		$firstChild = (!empty($tagData[2])) ? reset($tagData[2]) : null;
+		if (empty($firstChild)) throw new Exception("Missing wps:Input/wps:Data child nodes");
+		if ('wps:LiteralData' !== $firstChild[0]) throw new Exception("Missing wps:Input/wps:Data/wps:LiteralData");
+		$value = (!empty($firstChild[2][0])) ? $firstChild[2][0] : null;
+		if (empty($value)) throw new Exception("Missing wps:Input/wps:Data/wps:LiteralData value");
+		return $value;
+	}
+	static function _parseExecuteXmlArray($xml) {
+		// <wps:Execute xmlns:wps="http://www.opengis.net/wps/1.0.0" version="1.0.0" service="WPS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd">
+		//   <ows:Identifier xmlns:ows="http://www.opengis.net/ows/1.1">p5:selectFeature</ows:Identifier>
+		//   <wps:DataInputs>
+		//     <wps:Input>
+		//       <ows:Identifier xmlns:ows="http://www.opengis.net/ows/1.1">typeName</ows:Identifier>
+		//       <wps:Data><wps:LiteralData>default_db/TEST_PERMS/TestPermsAnt</wps:LiteralData></wps:Data>
+		//     </wps:Input>
+		//     <wps:Input>
+		//       <ows:Identifier xmlns:ows="http://www.opengis.net/ows/1.1">primaryKey</ows:Identifier>
+		//       <wps:Data><wps:LiteralData>97</wps:LiteralData></wps:Data>
+		//     </wps:Input>
+		//   </wps:DataInputs>
+		//   <wps:ResponseForm/>
+		// </wps:Execute>
+		if (empty($xml[2])) throw new Exception("Parse WPS Execute error - empty 'wps:Execute' tag");
+		$childTags = array_map(function ($child) {
+			return $child[0];
+		}, $xml[2]);
+		// echo "\$childTags:"; print_r($childTags);
+		// [0] => ows:Identifier
+		// [1] => wps:DataInputs
+		// [2] => wps:ResponseForm
+		$childListIdentifier = array_filter($xml[2], function ($child) {
+			return ( 'ows:Identifier' === $child[0] );
+		});
+		// echo "\$childIdentifier:"; print_r($childIdentifier);
+		$childIdentifier = (!empty($childListIdentifier)) ? reset($childListIdentifier) : [];
+		$identifier = (!empty($childIdentifier[2])) ? reset($childIdentifier[2]) : null;
+		$childListDataInputs = array_filter($xml[2], function ($child) {
+			return ( 'wps:DataInputs' === $child[0] );
+		});
+		$childDataInputs = (!empty($childListDataInputs)) ? reset($childListDataInputs) : [];
+		$args = self::convertWpsExecuteDataInputsXmlArrayToArgs($childDataInputs);
+		// echo "\$tagsInput:"; print_r($tagsInput);
+		// echo "\$args:"; print_r($args);
+		// TODO: response format
+		// $childResponseForm = array_filter($xml[2], function ($child) {
+		// 	return ( 'wps:ResponseForm' === $child[0] );
+		// });
+		// // echo "\$childResponseForm:"; print_r($childResponseForm);
+
+		return [
+			'identifier' => $identifier,
+			'args' => $args,
+			'responseFormat' => '', // TODO: ...
+		];
+	}
+
 	public function _parseTransactionXmlStruct($requestXml, $requestXmlTags) {
 		$DBG = V::get('DBG_XML', 0, $_GET, 'int');// TODO: Profiler
 		$rootTagName = V::get('tag', '', $requestXmlTags[0]);