/**
  * Write in specific format 
  * 
  * @param DataService        &$dataService        Dataservice
  * @param RequestDescription &$requestDescription Request description object
  * @param Object             &$odataModelInstance OData model instance
  * @param String             $responseContentType Content type of the response
  * @param String             $responseFormat      Output format
  * 
  * @return nothing
  */
 public static function write(DataService &$dataService, RequestDescription &$requestDescription, &$odataModelInstance, $responseContentType, $responseFormat)
 {
     $responseBody = null;
     $dataServiceVersion = $requestDescription->getResponseDataServiceVersion();
     if ($responseFormat == ResponseFormat::METADATA_DOCUMENT) {
         // /$metadata
         $writer = new MetadataWriter($dataService->getMetadataQueryProviderWrapper());
         $responseBody = $writer->writeMetadata();
         $dataServiceVersion = $writer->getDataServiceVersion();
     } else {
         if ($responseFormat == ResponseFormat::TEXT) {
             // /Customer('ALFKI')/CompanyName/$value
             // /Customers/$count
             $responseBody = utf8_encode($requestDescription->getTargetResult());
         } else {
             if ($responseFormat == ResponseFormat::BINARY) {
                 // Binary property or media resource
                 $targetKind = $requestDescription->getTargetKind();
                 if ($targetKind == RequestTargetKind::MEDIA_RESOURCE) {
                     $eTag = $dataService->getStreamProvider()->getStreamETag($requestDescription->getTargetResult(), $requestDescription->getResourceStreamInfo());
                     $dataService->getHost()->setResponseETag($eTag);
                     $responseBody = $dataService->getStreamProvider()->getReadStream($requestDescription->getTargetResult(), $requestDescription->getResourceStreamInfo());
                 } else {
                     $responseBody = $requestDescription->getTargetResult();
                 }
                 if (is_null($responseContentType)) {
                     $responseContentType = ODataConstants::MIME_APPLICATION_OCTETSTREAM;
                 }
             } else {
                 $writer = null;
                 $absoluteServiceUri = $dataService->getHost()->getAbsoluteServiceUri()->getUrlAsString();
                 if ($responseFormat == ResponseFormat::ATOM || $responseFormat == ResponseFormat::PLAIN_XML) {
                     if (is_null($odataModelInstance)) {
                         $writer = new \ODataProducer\Writers\ServiceDocument\Atom\ServiceDocumentWriter($dataService->getMetadataQueryProviderWrapper(), $absoluteServiceUri);
                     } else {
                         $isPostV1 = $requestDescription->getResponseDataServiceVersion()->compare(new Version(1, 0)) == 1;
                         $writer = new ODataWriter($absoluteServiceUri, $isPostV1, 'atom');
                     }
                 } else {
                     if ($responseFormat == ResponseFormat::JSON) {
                         if (is_null($odataModelInstance)) {
                             $writer = new \ODataProducer\Writers\ServiceDocument\Json\ServiceDocumentWriter($dataService->getMetadataQueryProviderWrapper(), $absoluteServiceUri);
                         } else {
                             $isPostV1 = $requestDescription->getResponseDataServiceVersion()->compare(new Version(1, 0)) == 1;
                             $writer = new ODataWriter($absoluteServiceUri, $isPostV1, 'json');
                         }
                     }
                 }
                 $responseBody = $writer->writeRequest($odataModelInstance);
             }
         }
     }
     $dataService->getHost()->setResponseStatusCode(HttpStatus::CODE_OK);
     $dataService->getHost()->setResponseContentType($responseContentType);
     $dataService->getHost()->setResponseVersion($dataServiceVersion->toString() . ';');
     $dataService->getHost()->setResponseCacheControl(ODataConstants::HTTPRESPONSE_HEADER_CACHECONTROL_NOCACHE);
     $dataService->getHost()->getWebOperationContext()->outgoingResponse()->setStream($responseBody);
 }
 /**
  * Process the given request Uri and creates an instance of 
  * RequestDescription from the processed uri.
  * 
  * @param Url         &$absoluteRequestUri The absolute request uri.
  * @param DataService &$dataService        Reference to the data service
  *                                         instance.
  * 
  * @return RequestDescription
  * 
  * @throws ODataException If any exception occurs while processing the segments
  *                        or incase of any version incompatibility.
  */
 public static function process(Url &$absoluteRequestUri, DataService &$dataService)
 {
     $absoluteRequestUri = $dataService->getHost()->getAbsoluteRequestUri();
     $absoluteServiceUri = $dataService->getHost()->getAbsoluteServiceUri();
     $requestUriSegments = array_slice($absoluteRequestUri->getSegments(), $absoluteServiceUri->getSegmentCount());
     $segmentDescriptors = null;
     try {
         $segmentDescriptors = SegmentParser::parseRequestUriSegements($requestUriSegments, $dataService->getMetadataQueryProviderWrapper(), true);
     } catch (ODataException $odataException) {
         throw $odataException;
     }
     $requestDescription = new RequestDescription($segmentDescriptors, $absoluteRequestUri);
     $requestTargetKind = $requestDescription->getTargetKind();
     if ($requestTargetKind != RequestTargetKind::METADATA && $requestTargetKind != RequestTargetKind::BATCH && $requestTargetKind != RequestTargetKind::SERVICE_DIRECTORY) {
         if ($requestTargetKind != RequestTargetKind::PRIMITIVE_VALUE && $requestTargetKind != RequestTargetKind::MEDIA_RESOURCE) {
             $requestDescription->setContainerName($requestDescription->getIdentifier());
         } else {
             // http://odata/NW.svc/Orders/$count
             // http://odata/NW.svc/Orders(123)/Customer/CustomerID/$value
             // http://odata/NW.svc/Employees(1)/$value
             // http://odata/NW.svc/Employees(1)/ThumbNail_48X48/$value
             $requestDescription->setContainerName($segmentDescriptors[count($segmentDescriptors) - 2]->getIdentifier());
         }
         if ($requestDescription->getIdentifier() === ODataConstants::URI_COUNT_SEGMENT) {
             if (!$dataService->getServiceConfiguration()->getAcceptCountRequests()) {
                 ODataException::createBadRequestError(Messages::dataServiceConfigurationCountNotAccepted());
             }
             $requestDescription->setRequestCountOption(RequestCountOption::VALUE_ONLY);
             // use of $count requires request DataServiceVersion
             // and MaxDataServiceVersion
             // greater than or equal to 2.0
             $requestDescription->raiseResponseVersion(2, 0, $dataService);
             $requestDescription->raiseMinimumVersionRequirement(2, 0, $dataService);
         } else {
             if ($requestDescription->isNamedStream()) {
                 $requestDescription->raiseMinimumVersionRequirement(3, 0, $dataService);
             } else {
                 if ($requestDescription->getTargetKind() == RequestTargetKind::RESOURCE) {
                     if (!$requestDescription->isLinkUri()) {
                         $resourceSetWrapper = $requestDescription->getTargetResourceSetWrapper();
                         //assert($resourceSetWrapper != null)
                         $hasNamedStream = $resourceSetWrapper->hasNamedStreams($dataService->getMetadataQueryProviderWrapper());
                         $hasBagProperty = $resourceSetWrapper->hasBagProperty($dataService->getMetadataQueryProviderWrapper());
                         if ($hasNamedStream || $hasBagProperty) {
                             $requestDescription->raiseResponseVersion(3, 0, $dataService);
                         }
                     }
                 } else {
                     if ($requestDescription->getTargetKind() == RequestTargetKind::BAG) {
                         $requestDescription->raiseResponseVersion(3, 0, $dataService);
                     }
                 }
             }
         }
     }
     return $requestDescription;
 }
Beispiel #3
0
 /**
  * Checks whether client request contains any odata query options.
  * 
  * @return void
  * 
  * @throws ODataException Throws bad request error if client request 
  *                        includes any odata query option.
  */
 private function _checkForEmptyQueryArguments()
 {
     $dataServiceHost = $this->_dataService->getHost();
     if (!is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_FILTER)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_EXPAND)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_INLINECOUNT)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_ORDERBY)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_SELECT)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_SKIP)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_SKIPTOKEN)) || !is_null($dataServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_TOP))) {
         ODataException::createBadRequestError(Messages::queryProcessorNoQueryOptionsApplicable());
     }
 }
 /**
  * Builds the string corresponding to query parameters for top level results 
  * (result set identified by the resource path) to be put in next page link.
  * 
  * @return string/NULL string representing the query parameters in the URI 
  *                     query parameter format, NULL if there 
  *                     is no query parameters
  *                     required for the next link of top level result set.
  */
 protected function getNextPageLinkQueryParametersForRootResourceSet()
 {
     $queryParameterString = null;
     foreach (array(ODataConstants::HTTPQUERY_STRING_FILTER, ODataConstants::HTTPQUERY_STRING_EXPAND, ODataConstants::HTTPQUERY_STRING_ORDERBY, ODataConstants::HTTPQUERY_STRING_INLINECOUNT, ODataConstants::HTTPQUERY_STRING_SELECT) as $queryOption) {
         $value = $this->dataService->getHost()->getQueryStringItem($queryOption);
         if (!is_null($value)) {
             if (!is_null($queryParameterString)) {
                 $queryParameterString = $queryParameterString . '&';
             }
             $queryParameterString .= $queryOption . '=' . $value;
         }
     }
     $topCountValue = $this->requestDescription->getTopOptionCount();
     if (!is_null($topCountValue)) {
         $remainingCount = $topCountValue - $this->requestDescription->getTopCount();
         if (!is_null($queryParameterString)) {
             $queryParameterString .= '&';
         }
         $queryParameterString .= ODataConstants::HTTPQUERY_STRING_TOP . '=' . $remainingCount;
     }
     if (!is_null($queryParameterString)) {
         $queryParameterString .= '&';
     }
     return $queryParameterString;
 }
Beispiel #5
0
 /**
  * Common function to handle exceptions in the data service.
  * 
  * @param Exception   $exception    exception occured
  * @param DataService &$dataService dataservice
  * 
  * @return nothing
  */
 public static function handleException($exception, DataService &$dataService)
 {
     $acceptTypesText = $dataService->getHost()->getRequestAccept();
     $responseContentType = null;
     try {
         $responseContentType = HttpProcessUtility::selectMimeType($acceptTypesText, array(ODataConstants::MIME_APPLICATION_XML, ODataConstants::MIME_APPLICATION_JSON));
     } catch (HttpHeaderFailure $exception) {
         $exception = new ODataException($exception->getMessage(), $exception->getStatusCode());
     } catch (\Exception $exception) {
         // Never come here
     }
     if (is_null($responseContentType)) {
         $responseContentType = ODataConstants::MIME_APPLICATION_XML;
     }
     if (!$exception instanceof ODataException) {
         $exception = new ODataException($exception->getMessage(), HttpStatus::CODE_INTERNAL_SERVER_ERROR);
     }
     $dataService->getHost()->setResponseVersion(ODataConstants::DATASERVICEVERSION_1_DOT_0 . ';');
     // At this point all kind of exceptions will be converted
     //to 'ODataException'
     if ($exception->getStatusCode() == HttpStatus::CODE_NOT_MODIFIED) {
         $dataService->getHost()->setResponseStatusCode(HttpStatus::CODE_NOT_MODIFIED);
     } else {
         $dataService->getHost()->setResponseStatusCode($exception->getStatusCode());
         $dataService->getHost()->setResponseContentType($responseContentType);
         $responseBody = null;
         if (strcasecmp($responseContentType, ODataConstants::MIME_APPLICATION_XML) == 0) {
             $responseBody = AtomODataWriter::serializeException($exception, true);
         } else {
             $responseBody = JsonODataWriter::serializeException($exception, true);
         }
         $dataService->getHost()->getWebOperationContext()->outgoingResponse()->setStream($responseBody);
     }
 }
 /**
  * Pushes a segment for the current navigation property being written out.
  * Note: Refer 'ObjectModelSerializerNotes.txt' for more details about
  * 'Segment Stack' and this method.
  * Note: Calls to this method should be balanced with calls to popSegment.
  *
  * @param ResourceProperty &$resourceProperty Current navigation property 
  *                                            being written out
  *
  * @return true if a segment was pushed, false otherwise
  *
  * @throws InvalidOperationException If this function invoked with non-navigation
  *                                   property instance.
  */
 private function _pushSegmentForNavigationProperty(ResourceProperty &$resourceProperty)
 {
     if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
         $this->assert(!empty($this->_segmentNames), '!is_empty($this->_segmentNames');
         $currentResourceSetWrapper = $this->_getCurrentResourceSetWrapper();
         $currentResourceType = $currentResourceSetWrapper->getResourceType();
         $currentResourceSetWrapper = $this->_dataService->getMetadataQueryProviderWrapper()->getResourceSetWrapperForNavigationProperty($currentResourceSetWrapper, $currentResourceType, $resourceProperty);
         $this->assert(!is_null($currentResourceSetWrapper), '!null($currentResourceSetWrapper)');
         return $this->_pushSegment($resourceProperty->getName(), $currentResourceSetWrapper);
     } else {
         throw new InvalidOperationException('pushSegmentForNavigationProperty should not be called with non-entity type');
     }
 }
 /**
  * Gets the response format for the requested resource.
  * 
  * @param RequestDescription &$requestDescription  The request submitted by 
  *                                                 client and it's execution 
  *                                                 result.
  * @param UriProcessor       &$uriProcessor        The reference to the 
  *                                                 UriProcessor.
  * @param DataService        &$dataService         Reference to the data 
  *                                                 service instance
  * @param string             &$responseContentType On Return, this will hold
  * the response content-type, a null value means the requested resource
  * is named stream and IDSSP2::getStreamContentType returned null.
  * 
  * @return ResponseFormat The format in which response needs to be serialized.
  * 
  * @throws ODataException, HttpHeaderFailure
  */
 public static function getResponseFormat(RequestDescription &$requestDescription, UriProcessor &$uriProcessor, DataService &$dataService, &$responseContentType)
 {
     // The Accept request-header field specifies media types which are
     // acceptable for the response
     $requestAcceptText = $dataService->getHost()->getRequestAccept();
     $responseFormat = ResponseFormat::UNSUPPORTED;
     $requestTargetKind = $requestDescription->getTargetKind();
     if ($requestDescription->isLinkUri()) {
         $requestTargetKind = RequestTargetKind::LINK;
     }
     if ($requestTargetKind == RequestTargetKind::METADATA) {
         $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML));
         if (!is_null($responseContentType)) {
             $responseFormat = ResponseFormat::METADATA_DOCUMENT;
         }
     } else {
         if ($requestTargetKind == RequestTargetKind::SERVICE_DIRECTORY) {
             $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML, ODataConstants::MIME_APPLICATION_ATOMSERVICE, ODataConstants::MIME_APPLICATION_JSON));
             if (!is_null($responseContentType)) {
                 $responseFormat = self::_getContentFormat($responseContentType);
             }
         } else {
             if ($requestTargetKind == RequestTargetKind::PRIMITIVE_VALUE) {
                 $supportedResponseMimeTypes = array(ODataConstants::MIME_TEXTPLAIN);
                 $responseFormat = ResponseFormat::TEXT;
                 if ($requestDescription->getIdentifier() != '$count') {
                     $projectedProperty = $requestDescription->getProjectedProperty();
                     self::assert(!is_null($projectedProperty), '!is_null($projectedProperty)');
                     $type = $projectedProperty->getInstanceType();
                     self::assert(!is_null($type) && array_search('ODataProducer\\Providers\\Metadata\\Type\\IType', class_implements($type)) !== false, '!is_null($type) && array_search(\'ODataProducer\\Providers\\Metadata\\Type\\IType\', class_implements($type)) !== false');
                     if ($type instanceof Binary) {
                         $supportedResponseMimeTypes = array(ODataConstants::MIME_APPLICATION_OCTETSTREAM);
                         $responseFormat = ResponseFormat::BINARY;
                     }
                 }
                 $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, $supportedResponseMimeTypes);
                 if (is_null($responseContentType)) {
                     $responseFormat = ResponseFormat::UNSUPPORTED;
                 }
             } else {
                 if ($requestTargetKind == RequestTargetKind::PRIMITIVE || $requestTargetKind == RequestTargetKind::COMPLEX_OBJECT || $requestTargetKind == RequestTargetKind::BAG || $requestTargetKind == RequestTargetKind::LINK) {
                     $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML, ODataConstants::MIME_TEXTXML, ODataConstants::MIME_APPLICATION_JSON));
                     if (!is_null($responseContentType)) {
                         $responseFormat = self::_getContentFormat($responseContentType);
                     }
                 } else {
                     if ($requestTargetKind == RequestTargetKind::RESOURCE) {
                         $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_ATOM, ODataConstants::MIME_APPLICATION_JSON));
                         if (!is_null($responseContentType)) {
                             $responseFormat = self::_getContentFormat($responseContentType);
                         }
                     } else {
                         if ($requestTargetKind == RequestTargetKind::MEDIA_RESOURCE) {
                             $responseFormat = ResponseFormat::BINARY;
                             if ($requestDescription->isNamedStream() || $requestDescription->getTargetResourceType()->isMediaLinkEntry()) {
                                 $streamInfo = $requestDescription->getResourceStreamInfo();
                                 //Execute the query as we need media resource instance for
                                 //further processing
                                 $uriProcessor->execute();
                                 $requestDescription->setExecuted();
                                 // DSSW::getStreamContentType can throw error in 2 cases
                                 // 1. If the required stream implementation not found
                                 // 2. If IDSSP::getStreamContentType returns NULL for MLE
                                 $contentType = $dataService->getStreamProvider()->getStreamContentType($requestDescription->getTargetResult(), $streamInfo);
                                 if (!is_null($contentType)) {
                                     $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array($contentType));
                                     if (is_null($responseContentType)) {
                                         $responseFormat = ResponseFormat::UNSUPPORTED;
                                     }
                                 } else {
                                     // For NamedStream StreamWrapper::getStreamContentType
                                     // can return NULL if the requested named stream has not
                                     // yet been uploaded. But for an MLE if
                                     // IDSSP::getStreamContentType
                                     // returns NULL then StreamWrapper will throw error
                                     $responseContentType = null;
                                 }
                             } else {
                                 ODataException::createBadRequestError(Messages::badRequestInvalidUriForMediaResource($dataService->getHost()->getAbsoluteRequestUri()->getUrlAsString()));
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($responseFormat == ResponseFormat::UNSUPPORTED) {
         throw new ODataException(Messages::dataServiceExceptionUnsupportedMediaType(), 415);
     }
     return $responseFormat;
 }
 /**
  * This function is used to perform following checking (validation)
  * for capability negotiation.
  *  (1) Check client request's 'DataServiceVersion' header value is 
  *      less than or equal to the minimum version required to intercept
  *      the response
  *  (2) Check client request's 'MaxDataServiceVersion' header value is
  *      less than or equal to the version of protocol required to generate
  *      the response
  *  (3) Check the configured maximum protocol version is less than or equal 
  *      to the version of protocol required to generate the response
  *  In addition to these checking, this function is also responsible for
  *  initializing the properties respresenting 'DataServiceVersion' and
  *  'MaxDataServiceVersion'.
  *  
  * @param RequestDescription $requestDescription The request description object
  * @param DataService        $dataService        The Service to check
  * 
  * @return void
  * 
  * @throws ODataException If any of the above 3 check fails.
  */
 public static function checkVersion(RequestDescription $requestDescription, DataService $dataService)
 {
     if (is_null($requestDescription->_requestDataServiceVersion)) {
         $version = $dataService->getHost()->getRequestVersion();
         //'DataServiceVersion' header not present in the request, so use
         //default value as the maximum version number that the server can
         //interpret.
         if (is_null($version)) {
             $knownVersions = $requestDescription::getKnownDataServiceVersions();
             $version = $knownVersions[count($knownVersions) - 1];
         } else {
             $version = $requestDescription::_validateAndGetVersion($version, ODataConstants::ODATAVERSIONHEADER);
         }
         $requestDescription->_requestDataServiceVersion = $version;
     }
     if (is_null($requestDescription->_requestMaxDataServiceVersion)) {
         $version = $dataService->getHost()->getRequestMaxVersion();
         //'MaxDataServiceVersion' header not present in the request, so use
         //default value as the maximum version number that the server can
         //interpret.
         if (is_null($version)) {
             $knownVersions = $requestDescription::getKnownDataServiceVersions();
             $version = $knownVersions[count($knownVersions) - 1];
         } else {
             $version = $requestDescription::_validateAndGetVersion($version, ODataConstants::ODATAMAXVERSIONHEADER);
         }
         $requestDescription->_requestMaxDataServiceVersion = $version;
     }
     if ($requestDescription->_requestDataServiceVersion->compare($requestDescription->_minimumRequiredClientVersion) < 0) {
         ODataException::createBadRequestError(Messages::requestDescriptionDataServiceVersionTooLow($requestDescription->_requestDataServiceVersion->toString(), $requestDescription->_minimumRequiredClientVersion->toString()));
     }
     if ($requestDescription->_requestMaxDataServiceVersion->compare($requestDescription->_responseDataServiceVersion) < 0) {
         ODataException::createBadRequestError(Messages::requestDescriptionDataServiceVersionTooLow($requestDescription->_requestMaxDataServiceVersion->toString(), $requestDescription->_responseDataServiceVersion->toString()));
     }
     $configuration = $dataService->getServiceConfiguration();
     $maxConfiguredProtocolVersion = $configuration->getMaxDataServiceVersionObject();
     if ($maxConfiguredProtocolVersion->compare($requestDescription->_responseDataServiceVersion) < 0) {
         ODataException::createBadRequestError(Messages::requestDescriptionResponseVersionIsBiggerThanProtocolVersion($requestDescription->_responseDataServiceVersion->toString(), $maxConfiguredProtocolVersion->toString()));
     }
 }
 /**
  * Check whether implementor modified content type or etag header
  * if so throw InvalidOperationException.
  * 
  * @param string $methodName NAme of the method
  * 
  * @return void
  * 
  * @throws InvalidOperationException
  */
 private function _verifyContentTypeOrETagModified($methodName)
 {
     if ($this->_responseContentType !== $this->_dataService->getHost()->getResponseContentType() || $this->_responseETag !== $this->_dataService->getHost()->getResponseETag()) {
         throw new InvalidOperationException(Messages::dataServiceStreamProviderWrapperMustNotSetContentTypeAndEtag($methodName));
     }
 }