/** * Constructor - create a JRON RPC proxy based on the full pathname of * an SMD file * * @param string $target Target URI * @param string $base_path_for_relative_paths Base path * @param string $binding_config Config */ public function __construct($target, $base_path_for_relative_paths, $binding_config) { SCA::$logger->log('Entering'); $this->smd_file_name = SCA_Helper::constructAbsoluteTarget($target, $base_path_for_relative_paths); $this->jsonrpc_client = new SCA_JsonRpcClient($this->smd_file_name); SCA::$logger->log('Exiting'); }
/** * 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'); $class_name = SCA_Helper::guessClassName($calling_component_filename); $wsdl_filename = str_replace('.php', '.wsdl', $calling_component_filename); if (!file_exists($wsdl_filename)) { file_put_contents($wsdl_filename, SCA_Bindings_Soap_ServiceDescriptionGenerator::generateDocumentLiteralWrappedWsdl($service_description)); } $handler = new SCA_Bindings_soap_Mapper("SoapServer"); try { SCA::$logger->log("Wsdl Type = {$wsdl_filename}"); $handler->setWSDLTypes($wsdl_filename); } catch (SCA_RuntimeException $wsdlerror) { echo $wsdlerror->exceptionString() . "\n"; } if (SCA_Helper::wsdlWasGeneratedForAnScaComponent($wsdl_filename)) { $options = $service_description->binding_config; $options['typemap'] = $handler->getTypeMap(); $server = new SoapServer($wsdl_filename, $options); } else { $server = new SoapServer($wsdl_filename, $service_description->binding_config); } $class_name = SCA_Helper::guessClassName($calling_component_filename); $service_wrapper = new SCA_Bindings_Soap_Wrapper($class_name, $handler); $server->setObject($service_wrapper); global $HTTP_RAW_POST_DATA; $server->handle($HTTP_RAW_POST_DATA); }
/** * 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"); SCA::$logger->log("_handleXmlRpcRequest - {$calling_component_filename}\n"); try { $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_proxy = new SCA_Bindings_Xmlrpc_Wrapper($instance, $class_name, $wsdl_filename); // create the xmlrpc server that will process the input message // and generate the result message $xmlrpc_server = new SCA_Bindings_Xmlrpc_Server($service_proxy); // handle the current request $xmlrpc_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 XML infrastructure // classes where XMLRPC info can be read over remote connections. We // still want to send a sensible error back to the client $response = "{\"error\":\"" . $ex->getMessage(); $response = $response . "\",\"version\":\"1.0\"}"; // some debugging //file_put_contents("xmlrpc_messages.txt", //"Response at XMLRPC server = " . $response . "\n", //FILE_APPEND); header('Content-type: text/xml'); echo $response; } 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'); $class_name = SCA_Helper::guessClassName($calling_component_filename); $service_wrapper = new SCA_Bindings_restresource_Wrapper($class_name); $server = new SCA_Bindings_restresource_Server($service_wrapper); $server->handle(); }
/** * Create the service wrapper for an SCA Component. In the event that the * mapping of the SCA Component methods the base_class and xmldas types are * set to null. * * @param string $class_name Class name */ public function __construct($class_name) { //TODO: get rid of the wsdl filename here SCA::$logger->log("Entering constructor"); SCA::$logger->log("class_name = {$class_name}"); $this->class_name = $class_name; $this->class_instance = SCA::createInstance($class_name); SCA::fillInReferences($this->class_instance); //need an xmldas //want to have the xsds in here. do xmldas only here then do add types. $this->xml_das = SCA_Helper::getXmldas($class_name, ""); SCA::$logger->log("Exiting Constructor"); }
/** * Create the service wrapper for an SCA Component. In the event that the * mapping of the SCA Component methods the base_class and xmldas types are * set to null. * * @param string $class_name Class name */ public function __construct($class_name) { //TODO: get rid of the wsdl filename here SCA::$logger->log("Entering constructor"); SCA::$logger->log("class_name = {$class_name}"); $this->class_name = $class_name; $this->class_instance = SCA::createInstance($class_name); SCA::fillInReferences($this->class_instance); // Get an xmldas to handle the SDOs passing in and // out of the wrapped service. This call creates the das // and adds all of the service types to it. $this->xml_das = SCA_Helper::getXmldas($class_name, ""); SCA::$logger->log("Exiting Constructor"); }
public function testElementsComeOutInTheRightNamespace() { $location_of_sca_class = SCA_Helper::getFileContainingClass("SCA"); $sca_dir = dirname($location_of_sca_class); $location_of_atom_xsd = $sca_dir . "/Bindings/atom/Atom1.0.xsd"; $xmldas = SDO_DAS_XML::create($location_of_atom_xsd); $document = $xmldas->createDocument('http://www.w3.org/2005/Atom', 'entry'); $entry = $document->getRootDataObject(); $author = $entry->createDataObject('author'); $author->name[] = "Caroline Maynard"; $xml = $xmldas->saveString($document, 2); $this->assertContains("<tns:author>", $xml); $this->assertContains("<tns:name>", $xml); }
/** * Once the proxy has been constructed the runtime passes in * the information associated with the reference that the proxy * represents * * @param SCA_ReferenceType $reference_type Reference type * * @return null */ public function addReferenceType(SCA_ReferenceType $reference_type) { $this->reference_type = $reference_type; // If there are type descriptions create and XML DAS and add them if (count($reference_type->getTypes()) > 0) { // Some XSD types are specified with the reference // annotation so use these XSDs to build the XML DAS $this->xml_das = $reference_type->getXmlDas(); // get the list of types that have been loaded into // the XML DAS $this->type_list = SCA_Helper::getAllXmlDasTypes($this->xml_das); } else { // No XSDs are specified so we assume that only simple type // parameters will be used. } }
/** * 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"); SCA::$logger->log("calling from {$calling_component_filename}"); //var_dump($service_description); // Guess a queue name if (!isset($service_description->binding_config['destination'])) { $service_description->binding_config['destination'] = 'queue://' . $service_description->class_name; SCA::$logger->log("Target queue not specified, SCA will use class name as default queue name"); } //Generate a Message Provider Description file. $mpd_filename = str_replace('.php', '.msd', $calling_component_filename); if (!file_exists($mpd_filename)) { file_put_contents($mpd_filename, SCA_Bindings_message_ServiceDescriptionGenerator::generateMSD($service_description)); } /*do we use WSDL schema?*/ if (isset($service_description->binding_config['wsdl']) && $service_description->binding_config['wsdl'] == 'disabled') { /*No!*/ $mapper = null; } else { /*Yes, then we'll also need a wsdl file, this is generated by the ServiceDescriptionGenerator class of the soap binding*/ $wsdl_filename = str_replace('.php', '.wsdl', $calling_component_filename); if (!file_exists($wsdl_filename)) { file_put_contents($wsdl_filename, SCA_Bindings_soap_ServiceDescriptionGenerator::generateDocumentLiteralWrappedWsdl($service_description)); } $mapper = new SCA_Bindings_message_Mapper(); try { SCA::$logger->log("Wsdl Type = {$wsdl_filename}"); $mapper->setWSDLTypes($wsdl_filename); } catch (SCA_RuntimeException $wsdlerror) { echo $wsdlerror->exceptionString() . "\n"; } } $class_name = SCA_Helper::guessClassName($calling_component_filename); //create a wapper $service_wrapper = new SCA_Bindings_message_Wrapper($class_name, $service_description, $mapper); // create the message listener $listener = new SCA_Bindings_message_SAMClient($service_wrapper); $msd_config = SCA_Bindings_message_ServiceDescriptionGenerator::parseBindingConfig($service_description->binding_config); $listener->config($msd_config); $listener->start(); echo ">> Test END <<"; SCA::$logger->log("exiting"); return; }
/** * Is service request? * * @param string $calling_component_filename Filename * * @return bool */ public function isServiceRequest($calling_component_filename) { SCA_Helper::checkSoapExtensionLoaded(); if (isset($_SERVER['HTTP_HOST'])) { if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] == '/RPC2') { return false; // looks like it is XmlRpc, not SOAP } $p1 = realpath($calling_component_filename); $p2 = realpath($_SERVER['SCRIPT_FILENAME']); if ($p1 == $p2 && (strpos($_SERVER['CONTENT_TYPE'], 'text/xml') !== false || strpos($_SERVER['CONTENT_TYPE'], 'soap') !== false)) { return true; } } } return false; }
/** * Proxy constructor * * @param string $target Target URI * @param string $base_path_for_relative_paths Base path * @param string $binding_config Config */ public function __construct($target, $base_path_for_relative_paths, $binding_config) { SCA::$logger->log('Entering'); if (!SCA_Bindings_ebaysoap_Proxy::dependenciesLoaded()) { SCA::$logger->log('eBay soap binding requires the openssl extension, but it is not loaded.'); throw new SCA_RuntimeException('eBay soap binding requires the openssl extension, but it is not loaded.'); } $binding_config = SCA_Helper::mergeBindingIniAndConfig($binding_config, $base_path_for_relative_paths); // Check that all the required configuration has been provided if (!key_exists('siteid', $binding_config) || empty($binding_config['siteid'])) { SCA::$logger->log('eBay soap binding configuration missing: siteid.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: siteid.'); } if (!key_exists('version', $binding_config) || empty($binding_config['version'])) { SCA::$logger->log('eBay soap binding configuration missing: version.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: version.'); } if (!key_exists('authtoken', $binding_config) || empty($binding_config['authtoken'])) { SCA::$logger->log('eBay soap binding configuration missing: authtoken.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: authtoken.'); } if (!key_exists('routing', $binding_config) || empty($binding_config['routing'])) { SCA::$logger->log('eBay soap binding configuration missing: routing.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: routing.'); } if (!key_exists('appid', $binding_config) || empty($binding_config['appid'])) { SCA::$logger->log('eBay soap binding configuration missing: appid.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: appid.'); } if (!key_exists('devid', $binding_config) || empty($binding_config['devid'])) { SCA::$logger->log('eBay soap binding configuration missing: devid.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: devid.'); } if (!key_exists('authcert', $binding_config) || empty($binding_config['authcert'])) { SCA::$logger->log('eBay soap binding configuration missing: authcert.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: authcert.'); } if (!key_exists('location', $binding_config) || empty($binding_config['location'])) { SCA::$logger->log('eBay soap binding configuration missing: location.'); throw new SCA_RuntimeException('eBay soap binding configuration missing: location.'); } parent::__construct($target, $base_path_for_relative_paths, $binding_config); SCA::$logger->log('Leaving'); }
/** * 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; }
/** * Create the service wrapper for a SCA Component. In the event that the mapping * of the SCA Component methods the base_class and xmldas types are set to * null. * * @param string $class_name * @param string $wsdl_filename */ public function __construct($instance, $class_name, $wsdl_filename) { SCA::$logger->log("Entering"); $this->class_name = $class_name; $this->instance_of_the_base_class = $instance; SCA::fillInReferences($this->instance_of_the_base_class); // create a JSON DAS and populate it with the valid types // that this service can create. Not strinctly required // for json encoding but the JSON Server uses this // DAS for decoding $xsds = SCA_Helper::getAllXsds($class_name); $this->json_das = new SDO_DAS_Json(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $class_name); $this->json_das->addTypesXsdFile($xsd); } } }
/** * Constructor */ public function __construct($path_to_msd, $immediate_caller_directory, $binding_config) { SCA::$logger->log('entering'); //check if SAM extensions is loaded if (!in_array('sam', get_loaded_extensions())) { throw new SCA_RuntimeException("The SAM extension must be loaded"); } if ($binding_config === null) { $binding_config = array(); } $binding_config['msd'] = $path_to_msd; /*parse MSD file */ $msd_config = SCA_Bindings_message_ServiceDescriptionGenerator::parseBindingConfig($binding_config); if (isset($msd_config->responseTimeout)) { $this->waitResponseTimeout = $msd_config->responseTimeout; } if (!isset($msd_config->wsdl)) { throw new SCA_RuntimeException("Path to WSDL file is required to the binding configuration,\n or the 'wsdl' property should be stated as 'disabled' explicitly."); } else { /*check if wsdl is disabled, if not the wsdl schema will be loaded */ if ($msd_config->wsdl != 'disabled') { $path_to_wsdl = SCA_Helper::constructAbsoluteTarget($msd_config->wsdl, $immediate_caller_directory); SCA::$logger->log('The proxy will use wsdl file :' . $path_to_wsdl); $this->mapper = new SCA_Bindings_message_Mapper(); try { $this->mapper->setWSDLTypes($path_to_wsdl); //$xmldas = $this->mapper->getXmlDas(); } catch (SCA_RuntimeException $se) { if (substr($path_to_wsdl, 0, 5) == 'http:' && strpos($se->getMessage(), 'SDO_Exception') !== false && strpos($se->getMessage(), 'Unable to parse') !== false && strpos($se->getMessage(), 'Document is empty') !== false) { throw new SCA_RuntimeException('A call to SCA specified a URL: ' . $path_to_wsdl . " The document returned was empty. One explanation for this may be apache bug 39662. See http://issues.apache.org/bugzilla/show_bug.cgi?id=36692. You may need to obtain the WSDL in a browser and save it as a local file."); } throw $se; } } } /*create and config a SAM client*/ $this->ms_client = new SCA_Bindings_message_SAMClient($this); $this->ms_client->config($msd_config); SCA::$logger->log('SAM is ready'); }
/** * Create the service wrapper for a SCA Component. * * @param object $instance Instance * @param string $class_name Class * @param string $wsdl_filename WSDL */ public function __construct($instance, $class_name, $wsdl_filename) { SCA::$logger->log("Wrapper {$class_name}"); $this->class_name = $class_name; $this->instance_of_the_base_class = $instance; SCA::fillInReferences($this->instance_of_the_base_class); $this->annotations = new SCA_AnnotationReader($this->instance_of_the_base_class); // create an XML-RPC DAS and populate it with the valid types // that this service can create. $xsds = SCA_Helper::getAllXsds($class_name); $this->xmlrpc_das = new SCA_Bindings_Xmlrpc_DAS(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $class_name); $this->xmlrpc_das->addTypesXsdFile($xsd); } } $this->xmlrpc_server = xmlrpc_server_create(); $service_description = $this->annotations->reflectService(); $serviceDescGen = new SCA_Bindings_Xmlrpc_ServiceDescriptionGenerator(); $serviceDescGen->addIntrospectionData($this->xmlrpc_server, $service_description, $this->method_aliases, $this->xmlrpc_das); }
/** * Create data pnkect * * @param string $namespace_uri Namespace URI * @param string $type_name Type name * * @return mixed */ public function createDataObject($namespace_uri, $type_name) { try { return SCA_Helper::createDataObject($namespace_uri, $type_name, $this->component_class_name); } catch (Exception $e) { throw new SCA_RuntimeException($e->getMessage()); } // following return logically unecessary but keeps the ZS code // analyzer happy return null; }
/** * Here is where we turn the list of positional parameters into a * single array of name parameters e.g. 'IBM' into array('ticker'=>'IBM') * This is the opposite of what we do in the ServiceWrapper * * We have to find the names to be given to each parameter * which we currently do by creating an SDO document and an SDO within it * then assigning the parameters one by one to the properties of the data object * * There is an inherent assumption that as we iterate through the * properties of the object we will get them in the same order as the * wsdl, and that this order is in turn the same as the order of the * parameters in the call. This relies on the user to put the @param * annotations in the right order in the annotations. * * @param string $method_name Method name * @param array $arguments Arguments * * @return mixed */ public function __call($method_name, $arguments) { SCA::$logger->log("Entering"); SCA::$logger->log("method name = {$method_name}"); if (SCA_Helper::wsdlWasGeneratedForAnScaComponent($this->wsdl_file_name)) { $return = null; $operation_sdo = null; /* Break out of the 'call' in the event of an SDO problem */ try { $operation_sdo = $this->_getSoapOperationSdo($method_name, $arguments); } catch (SDO_Exception $sdoe) { throw new SCA_RuntimeException($sdoe->getMessage()); } $operation_array = array($operation_sdo); $return = $this->_passTheCallToTheSoapClient($method_name, $operation_array); return $return[$method_name . 'Return']; } else { return $this->_passTheCallToTheSoapClient($method_name, $arguments); } }
/** * Generate method and type information to add introspection data. * The information required is generated from annotations. * All methods are registered with the server, and introspection data * is added to the server. * * @param resource $xmlrpc_server XML RPC server * @param array $service_description Description * @param array &$method_aliases Aliases * @param object $xmlrpc_das Unknown * * @return string Method description */ public function addIntrospectionData($xmlrpc_server, $service_description, &$method_aliases, $xmlrpc_das = null) { if ($xmlrpc_das == null) { $xsds = SCA_Helper::getAllXsds($service_description->class_name); $xmlrpc_das = new SCA_Bindings_Xmlrpc_DAS(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $service_description->class_name); $xmlrpc_das->addTypesXsdFile($xsd); } } } $type_list = array(); $methodDesc = <<<END <?xml version='1.0'?> <introspection version='1.0'> <methodList> END; foreach ($service_description->operations as $methodName => $methodInfo) { $methodParams = ""; $methodReturn = ""; if (array_key_exists("name", $methodInfo) && array_key_exists("name", $methodInfo["name"]) && $methodInfo["name"]["name"] != null && strlen($methodInfo["name"]["name"]) > 0) { $xmlrpcMethodName = $methodInfo["name"]["name"]; $method_aliases[$xmlrpcMethodName] = $methodName; } else { $xmlrpcMethodName = $methodName; } xmlrpc_server_register_method($xmlrpc_server, $xmlrpcMethodName, $methodName); if (array_key_exists("parameters", $methodInfo) && $methodInfo["parameters"] != null) { foreach ($methodInfo["parameters"] as $param) { $paramName = $param["name"]; if (array_key_exists('objectType', $param)) { $paramType = $param["objectType"]; $this->generateType($param["namespace"], $param["objectType"], $type_list, $xmlrpc_das); } else { $paramType = $this->sdoTypeToXmlRpcType($param["type"]); } $methodParams = $methodParams . <<<END <value type='{$paramType}' desc='{$paramName}'> </value> END; } } if (array_key_exists("return", $methodInfo) && $methodInfo["return"] != null) { foreach ($methodInfo["return"] as $ret) { if (array_key_exists('objectType', $ret)) { $retType = $ret["objectType"]; $this->generateType($ret["namespace"], $ret["objectType"], $type_list, $xmlrpc_das); } else { $retType = $this->sdoTypeToXmlRpcType($ret["type"]); } $methodReturn = $methodReturn . <<<END <value type='{$retType}' desc='return'> </value> END; } } $methodDesc = $methodDesc . <<<END <methodDescription name='{$xmlrpcMethodName}'> <author></author> <purpose></purpose> <version></version> <signatures> <signature> <params> {$methodParams} </params> <returns> {$methodReturn} </returns> </signature> </signatures> </methodDescription> END; } $methodDesc = $methodDesc . "</methodList>\n"; if (count($type_list) > 0) { $methodDesc = $methodDesc . "<typeList>\n"; foreach ($type_list as $type) { $methodDesc = $methodDesc . <<<END <typeDescription name='{$type->name}' basetype='struct' desc='{$type->name}'> END; foreach ($type->typedef->properties as $prop) { $methodDesc = $methodDesc . <<<END <value type='{$prop->type}' name='{$prop->name}'></value> END; } $methodDesc = $methodDesc . <<<END </typeDescription> END; } $methodDesc = $methodDesc . "</typeList>\n"; } $methodDesc = $methodDesc . "</introspection>\n"; $descArray = xmlrpc_parse_method_descriptions($methodDesc); xmlrpc_server_add_introspection_data($xmlrpc_server, $descArray); }
/** * Am repeating this code here (it's in the previous method also) * as we are seeing a number of different combinitations of * creating and XMLDAS based on the \@type annotations in the * \@Service comment or in the \@Reference comment * * TODO - create a more complete model of the service in memory * so that we can pick bits from it rather than having to * rescan the class and regen it every time we need a bit * * @param string $class_name Class name * @param mixed $xsds XSDs * * @return SDO_DAS_XML */ public static function getXmldasFormXsdArray($class_name, $xsds) { $xmldas = SDO_DAS_XML::create(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $class_name); $xmldas->addTypes($xsd); } } return $xmldas; }
public function testDeleteRequestAndResponse() { //DELETE requests are translated to 'delete()' calls $_SERVER['REQUEST_METHOD'] = 'DELETE'; $_SERVER['PATH_INFO'] = 'TEST_ID'; //set up the service wrapper and atom server $file_name = dirname(__FILE__) . '/ComponentDeleteReturnTrueResponse.php'; include $file_name; $class_name = SCA_Helper::guessClassName($file_name); $sw = new SCA_ServiceWrapperAtom($class_name); $as = new SCA_AtomServer($sw); $input = dirname(__FILE__) . '/AtomInputFile3.txt'; $as->setInputStream($input); //Not expecting a body $as->handle(); $this->assertContains("HTTP/1.1 200 OK", $this->http_header_catcher->headers); }
/** * TODO - We need to think about where to put this method * * @param SCA_ReferenceType $reference_type Reference Type * * @return null */ public function addReferenceType(SCA_ReferenceType $reference_type) { SCA::$logger->log("Entering"); $this->reference_type = $reference_type; // Add type descriptions to the XML DAS. We use XSDs if they // are prvoided. if (count($reference_type->getTypes()) > 0) { // Some XSD types are specified with the reference // annotation so use these XSDs to build the XMLDAS $this->xmldas = $reference_type->getXmlDas(); // get the list of types that have been loaded into // the XMLDAS in this case $this->type_list = SCA_Helper::getAllXmlDasTypes($this->xmldas); } else { //TODO: This is where we end up if we don't specify @types on a client side atom component with an @reference! //TODO: refactor this and check routes to this part of the code result in proper response $this->xmldas = SDO_DAS_XML::create(dirname(__FILE__) . '/Atom1.0.xsd'); } }
/** * get all of the existing resources. * * @return an SDO representing the collection */ public function enumerate() { SCA::$logger->log("Entering enumerate()"); $handle = curl_init($this->target_url); curl_setopt($handle, CURLOPT_HEADER, false); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_HTTPGET, true); $headers = array("User-Agent: SCA", "Content-Type: text/plain;", "Accept: text/xml"); curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($handle); $response_http_code = curl_getinfo($handle, CURLINFO_HTTP_CODE); curl_close($handle); $response_exception = $this->buildResponseException($response_http_code, '200'); if ($response_exception != null) { throw $response_exception; } else { //convert the result into an sdo. $sdo = SCA_Helper::xmlToSdo($this->xml_das, $result); return $sdo; } }
/** * This function can be called directly by a php script to dispatch a request to * an SCA service. You only need to use this operation when you organize your * code so that the service implementation (and SCA/SCA.php include) are included * by in a script that is just a wrapper script and is not acting as a client for * the service. This can happen if you want keep php files that define service * outside of the htdocs directory * * @param string $class_name The class_name that implements the target service * * @return void */ public static function dispatch($class_name) { $file_name = SCA_Helper::getFileContainingClass($class_name); $_SERVER['SCRIPT_FILENAME'] = $file_name; SCA::initComponent($file_name); }
/** * Start/Restart the logger * * @return null */ public function startLog() { if ($this->run == SCA_LOGGER_START) { // we are already started; this is a second // or subsequent call to startLog() - do nothing return; } $dirpath = SCA_Helper::getTempDir() . '/log'; $file = 'SCA'; $command = SCA_LOGGER_UPDATE; if ($dirpath !== null) { $this->dirpath = $dirpath; if (!file_exists($dirpath)) { mkdir($dirpath); } } if ($file !== null) { $this->file = $file; } $this->logfile = "{$this->dirpath}/{$this->file}.{$this->extn}"; // turn on if you cannot remember where the log is written to //trigger_error("SCA logging started; logging to $this->logfile"); date_default_timezone_set('UTC'); /* Delete an existing file, or get the last message index */ if ($command == SCA_LOGGER_DELETE) { $this->deleteLogFile(); } else { $this->msgIndex = 1; } $this->run = SCA_LOGGER_START; }
public function __construct() { $tmpdir = SCA_Helper::getTempDir(); $this->loginfo = array($tmpdir . '/log', 'SCAUnitTest'); $this->loglocn = $tmpdir . '/log/SCAUnitTest.log'; }
public function getJsonDas($xsds, $class_name) { $json_das = new SDO_DAS_Json(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $class_name); $json_das->addTypesXsdFile($xsd); } } return $json_das; }
/** * 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; }
/** * Get XML DAS for Atom * * @param string $class_name Class name * @param string $namespace_uri Namespace * * @todo refactor this back into getXmldas - should just be able to load the atom schema if the namespace and type are http://www.w3.org/2005/Atom and entryType. This needs some thought though as the namespace could change, and someone else might use the type name entryType in a non-atom schema * * @return XML_DAS */ public static function getXmldasForAtom($class_name, $namespace_uri) { SCA::$logger->log("Entering"); $xmldas = SDO_DAS_XML::create(dirname(__FILE__) . '/Atom1.0.xsd'); // expect to find xsds along with the SCA code - automatically loads xhtml1.xsd and xml.xsd as part of this. // TODO examine this code again // one might imagine that what is wanted is a map: // array(namespace => Set Of xsd) // but this is not what we have // Code Analyser correctly picks up a number // of strangenesses $xsds = SCA_Helper::getAllXsds($class_name); //$atomhelperlog->log("SCA_ServiceWrapperAtom::getXmldasForAtom() Just tried to find xsds in the component: ". print_r($xsds, true) ." \n"); //$xmldas = SDO_DAS_XML::create(); foreach ($xsds as $index => $xsds) { list($namespace, $xsdfile) = $xsds; if (SCA_Helper::isARelativePath($xsdfile)) { $xsd = SCA_Helper::constructAbsolutePath($xsdfile, $class_name); $xmldas->addTypes($xsd); } } // $atomhelperlog->log("SCA_ServiceWrapperAtom::getXmldasForAtom() xmldas after adding other types from the class:: $xmldas \n"); SCA::$logger->log("Exiting"); return $xmldas; }
/** * Constructor for simpledb Proxy * Use the values from the configuration file provided to create a PDO for the database * Query the database to obtain column metadata and primary key * * @param string $target Target * @param string $immediate_caller_directory Directory * @param string $binding_config Config */ public function __construct($target, $immediate_caller_directory, $binding_config) { SCA::$logger->log('Entering constructor'); try { $this->table = $target; $this->config = SCA_Helper::mergeBindingIniAndConfig($binding_config, $immediate_caller_directory); if (array_key_exists('username', $this->config)) { $username = $this->config['username']; } else { $username = null; } if (array_key_exists('password', $this->config)) { $password = $this->config['password']; } else { $password = null; } if (array_key_exists('namespace', $this->config)) { $this->namespace = $this->config['namespace']; } if (array_key_exists('case', $this->config)) { $this->case = $this->config['case']; } else { $this->case = 'lower'; } if (!array_key_exists('dsn', $this->config)) { throw new SCA_RuntimeException("Data source name should be specified"); } $tableName = $this->table; // Special processing for IBM databases: // IBM table names can contain schema name as prefix // Column metadata returned by pdo_ibm does not specify the primary key // Hence primary key for IBM databases has to be obtained using // db2_primary_key. if (strpos($this->config["dsn"], "ibm:") === 0 || strpos($this->config["dsn"], "IBM:") === 0) { $this->isIBM = true; // Table could be of format schemaName.tableName $schemaName = null; if (($pos = strrpos($tableName, '.')) !== false) { $schemaName = substr($tableName, 0, $pos); $tableName = substr($tableName, $pos + 1); } // DSN for IBM databases can be a database name or a connection string // Both can be passed onto db2_connect. Remove the dsn prefix if specified $database = substr($this->config["dsn"], 4); if (strpos($database, "dsn=") === 0 || strpos($database, "DSN=") === 0) { $database = substr($database, 4); } // Need to make sure the name is in DB2 uppercase style $db2TableName = strtoupper($tableName); $conn = db2_connect($database, $username, $password); $stmt = db2_primary_keys($conn, null, $schemaName, $db2TableName); $keys = db2_fetch_array($stmt); if (count($keys) > 3) { $this->primary_key = $keys[3]; } else { throw new SCA_RuntimeException("Table '{$tableName}' does not appear to have a primary key."); } } $this->table_name = $this->_getName($tableName); if ($username != null) { $this->pdo = new PDO($this->config["dsn"], $username, $password, $this->config); } else { $this->pdo = new PDO($this->config["dsn"]); } $this->pdo_driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME); $stmt = $this->pdo->prepare('SELECT * FROM ' . $this->table); if (!$stmt->execute()) { throw new SCA_RuntimeException(self::_getPDOError($stmt, "select")); } $columns = array(); for ($i = 0; $i < $stmt->columnCount(); $i++) { $meta = $stmt->getColumnMeta($i); $name = $this->_getName($meta["name"]); if (in_array("primary_key", $meta["flags"], true)) { $this->primary_key = $name; } $columns[] = $name; } //$pk = $this->_getName($this->primary_key); SCA::$logger->log("Table {$tableName} PrimaryKey {$this->primary_key}"); /* $metadata = array( 'name' => $this->table_name, 'columns' => $columns, 'PK' => $pk ); */ $this->datafactory = SDO_DAS_DataFactory::getDataFactory(); // Define the model on the data factory (from the database) $this->datafactory->addType(SCA_Bindings_simpledb_Proxy::ROOT_NS, SCA_Bindings_simpledb_Proxy::ROOT_TYPE); $this->datafactory->addType($this->namespace, $this->table_name); foreach ($columns as $name) { $this->datafactory->addPropertyToType($this->namespace, $this->table_name, $name, 'commonj.sdo', 'String'); } $this->datafactory->addPropertyToType(SCA_Bindings_simpledb_Proxy::ROOT_NS, SCA_Bindings_simpledb_Proxy::ROOT_TYPE, $this->table_name, $this->namespace, $this->table_name, array('many' => true)); } catch (Exception $e) { throw new SCA_RuntimeException($e->getMessage()); } SCA::$logger->log("Exiting constructor"); }
/** * Handle * * @param string $calling_component_filename Filename * * @return null */ public function handle($calling_component_filename) { SCA::$logger->log("Entering"); $actions = array('POST' => array('create', 1), 'GET' => array('retrieve', 1), 'PUT' => array('update', 2), 'DELETE' => array('delete', 1)); if (array_key_exists($_SERVER['REQUEST_METHOD'], $actions)) { $methodWithNumberOfParams = $actions[$_SERVER['REQUEST_METHOD']]; $method = $methodWithNumberOfParams[0]; } else { //TODO find out correct response header("HTTP/1.1 404 "); echo $_SERVER['REQUEST_METHOD'] . " Not Supported."; return; } //*handle situations where we have the id in the url.*/ /** These look like the variables to use: [REQUEST_URI] => /Samples/RSS/Contact.php/12 [SCRIPT_NAME] => /Samples/RSS/Contact.php [PATH_INFO] => /12 */ /* * Note, if the PATH_INFO is not working, and you are using Apache 2.0, * check the AcceptPathInfo directive for php files. * See http://httpd.apache.org/docs/2.0/mod/core.html#acceptpathinfo */ //Set $id - works for non-selector style, but not for selector style. if (isset($_SERVER['PATH_INFO'])) { $param = $_SERVER['PATH_INFO']; //test different length of param //$param = "/344656"; //TODO: is there a case where there will not be a slash in [PATH_INFO]? //strip slash $lengthOfParam = strlen($param); $id = substr($param, 1, $lengthOfParam); } else { if (isset($_GET['id'])) { $id = $_GET['id']; //left so that our rewrite test still works } else { $id = null; } } try { //always give the component an sdo, but handle sdo or xml back from it. if ($method === 'create') { SCA::$logger->log("{$method} == create"); // Can only do GET (retrieve) on RSS // return http method not allowed status header("HTTP/1.1 405"); } else { if ($method === 'retrieve') { $call_response = null; try { if ($id === null) { $method = 'enumerate'; } SCA::$logger->log("Calling {$method} on the RSS service wrapper, passing in the id {$id}"); $class_name = SCA_Helper::guessClassName($calling_component_filename); $service_component = SCA::createInstance($class_name); SCA::fillInReferences($service_component); $call_response = call_user_func_array(array(&$service_component, $method), $id); SCA::$logger->log("Response from calling the method {$method} is: {$call_response}"); //TODO: make sure these tests reflect the correct return values. if ($call_response !== null) { $response_xml; // Handle the different types of response (SDO, PHP Class, Raw XML) if ($call_response instanceof SDO_DataObjectImpl) { //if the thing received is an sdo... //convert it to xml $response_xml = SCA_Bindings_Rss_RssDas::toXml($call_response); } else { if ($call_response instanceof Channel) { // TODO: write the mapping from php classes to XML... SCA::$logger->log("TODO: write the mapping from php rss classes to xml."); $response_xml = null; } else { if (is_string($call_response)) { $response_xml = $call_response; } } } header("HTTP/1.1 200"); header("Content-Type: application/xml"); echo $response_xml; } else { SCA::$logger->log("Caught call_response is null exception in RSSServer"); //TODO find out the right response header("HTTP/1.1 500"); //echo "The requested resource <em>$id</em> does not exist on this database"; } } catch (SCA_ServiceUnavailableException $ex) { header("HTTP/1.1 503"); } catch (SCA_ConflictException $ex) { header("HTTP/1.1 409"); } catch (SCA_AuthenticationException $ex) { header("HTTP/1.1 407"); } catch (SCA_BadRequestException $ex) { header("HTTP/1.1 400"); } catch (SCA_InternalServerErrorException $ex) { SCA::$logger->log("Caught SCA_InternalServerErrorException in RSSServer"); header("HTTP/1.1 500"); } catch (SCA_MethodNotAllowedException $ex) { //note - this one is more likely to be thrown by the server code than the component code. header("HTTP/1.1 405"); } catch (SCA_UnauthorizedException $ex) { header("HTTP/1.1 401"); } catch (SCA_RuntimeException $ex) { SCA::$logger->log("Caught SCA_RuntimeException in RSSServer\n"); header("HTTP/1.1 500"); } catch (Exception $ex) { SCA::$logger->log("Caught an exception in RSSServer: " . $ex->getMessage() . "\n"); $call_response['error'] = $ex->getMessage(); //TODO find out the right response header("HTTP/1.1 500"); } } else { if ($method === 'update') { // Can only do GET (retrieve) on RSS // return http method not allowed status header("HTTP/1.1 405"); } else { if ($method === 'delete') { // Can only do GET (retrieve) on RSS // return http method not allowed status header("HTTP/1.1 405"); } } } } } catch (SCA_MethodNotAllowedException $ex) { //catch problem finding the method encountered by the service wrapper. header("HTTP/1.1 405"); } catch (SCA_RuntimeException $ex) { //TODO: output exceptions correctly. header("HTTP/1.1 500"); } return; }