/** * Generate * * @param string $service_description Service Description * * @return null */ public function generate($service_description) { SCA::$logger->log("Entering"); try { $smd_str = SCA_GenerateSmd::generateSmd($service_description); SCA::sendHttpHeader('Content-type: text/plain'); echo $smd_str; } catch (SCA_RuntimeException $se) { echo $se->exceptionString() . "\n"; } catch (SDO_DAS_XML_FileException $e) { throw new SCA_RuntimeException("{$e->getMessage()} in {$e->getFile()}"); } return; }
/** * Handle * * @param string $calling_component_filename Filename * @param string $service_description Service description * * @return mixed */ public function handle($calling_component_filename, $service_description) { SCA::$logger->log("Entering"); try { $smd_filename = str_replace('.php', '.smd', $calling_component_filename); if (!file_exists($smd_filename)) { file_put_contents($smd_filename, SCA_GenerateSmd::generateSmd($service_description)); // ,self::generateSMD($calling_component_filename) // ); } $wsdl_filename = null; // create a wrapper, which in turn creates a service // instance and fills in all of the references $class_name = SCA_Helper::guessClassName($calling_component_filename); $instance = SCA::createInstance($class_name); $service_wrapper = new SCA_ServiceWrapperJson($instance, $class_name, $wsdl_filename); // create the jsonrpc server that will process the input message // and generate the result message $jsonrpc_server = new SCA_JsonRpcServer($service_wrapper); $jsonrpc_server->handle(); } catch (Exception $ex) { // A catch all exception just in case something drastic goes wrong // This can often be the case in constructors of the JSON infsatructure // classes where SMD files can be read over remote connections. We // still want to send a sensible error back to the client // TODO extend the JSON service to expose this kind of function // through public methods $response = "{\"id\":\""; $response = $response . SCA_JsonRpcServer::getRequest()->id; $response = $response . "\",\"error\":\"" . $ex->getMessage(); $response = $response . "\",\"version\":\"1.0\"}"; // TODO what to do about id? We can catch errors before the // input is parsed // some debugging // file_put_contents("json_messages.txt", // "Response at JSONRPC server = " . $response . "\n", // FILE_APPEND); header('Content-type: application/json-rpc'); echo $response; } return; }
/** * Filter the service desrciption (which is derived * from the annotations in the service class) to produce * a "Simple Method Description" object for use by * JSON-RPC (well the DOJO flavour of it anyhow) */ public static function generateSmd($service_desc) { // an array of types used to ensure that complex // type descriptions are only written out once // this is separate from the smd object that is // being built up so that it doesn't get written // out to JSON at the end $type_array = array(); // construct an XMLDAS base on the XSDs in the // service description // // TODO - this xmldas could be provided as part of the // service description. I would like to see a class // hierarchy in PHP that holds the service // description and can be cached if necessary self::$xmldas = SCA_Helper::getXmldasFormXsdArray($service_desc->class_name, $service_desc->xsd_types); // work out what the hostname is so that the // url can be constructed $http_host = null; if (isset($_SERVER['HTTP_HOST'])) { $http_host = $_SERVER['HTTP_HOST']; } else { $http_host = "localhost"; } $smd = new stdClass(); $smd->SMDVersion = ".1"; $smd->serviceType = "JSON-RPC"; $smd->serviceURL = str_replace(' ', '%20', "http://" . $http_host . $_SERVER['SCRIPT_NAME']); $smd->methods = array(); foreach ($service_desc->operations as $operation_name => $operation) { $method = new stdClass(); $method->name = $operation_name; $method->parameters = array(); $smd->methods[] = $method; if (array_key_exists("parameters", $operation) && $operation["parameters"]) { // create the method parameters entries foreach ($operation["parameters"] as $parameter) { $param = new stdClass(); $param->name = $parameter["name"]; if (array_key_exists('objectType', $parameter)) { $param->type = $parameter["objectType"]; self::generateSmdType($smd, $parameter["objectType"], $parameter["namespace"], $type_array); // add the type info to the smd } else { $param->type = $parameter["type"]; } $method->parameters[] = $param; } } if (array_key_exists("return", $operation) && $operation["return"]) { // create the method return type entries foreach ($operation["return"] as $return) { $rtn = new stdClass(); if (array_key_exists('objectType', $return)) { $rtn->type = $return["objectType"]; self::generateSmdType($smd, $return["objectType"], $return["namespace"], $type_array); // add the type info to the smd } else { $rtn->type = $return["type"]; } $method->return = $rtn; } } } // turn the smd into JSON format $str = json_encode($smd); // TODO - hack to remove the encoded /s from the encoded string $str = str_replace("\\/", "/", $str); return $str; }