Repository: olingo-odata4 Updated Branches: refs/heads/master 34f082560 -> d19afa013
[OLINGO-350] Status code handling and refactoring Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/5c0b34a9 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/5c0b34a9 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/5c0b34a9 Branch: refs/heads/master Commit: 5c0b34a92d67f7f4f3846a1bdd2ad76e70cd0f6b Parents: 34f0825 Author: Christian Amend <[email protected]> Authored: Fri Aug 1 16:20:55 2014 +0200 Committer: Christian Amend <[email protected]> Committed: Wed Aug 6 17:10:15 2014 +0200 ---------------------------------------------------------------------- .../server/api/ODataTranslatedException.java | 6 - .../api/processor/CollectionProcessor.java | 40 ------- .../server/api/processor/DefaultProcessor.java | 4 +- .../processor/EntityCollectionProcessor.java | 40 +++++++ .../src/main/resources/i18n.properties | 7 +- .../olingo/server/core/ContentNegotiator.java | 35 +++--- .../server/core/ContentNegotiatorException.java | 45 +++++++ .../apache/olingo/server/core/ODataHandler.java | 120 +++++++++++-------- .../server/core/ContentNegotiatorTest.java | 41 +++---- .../server/core/ODataHttpHandlerImplTest.java | 6 - .../tecsvc/processor/TechnicalProcessor.java | 4 +- .../olingo/server/core/ODataHandlerTest.java | 49 ++++++++ 12 files changed, 249 insertions(+), 148 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java index b703f93..1dbb810 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java @@ -45,12 +45,6 @@ public class ODataTranslatedException extends ODataException { PROCESSOR_NOT_IMPLEMENTED, FUNCTIONALITY_NOT_IMPLEMENTED, ODATA_VERSION_NOT_SUPPORTED, - /** parameters: HTTP header name, HTTP header value */ - WRONG_CHARSET_IN_HEADER, - /** parameter: list of content-type ranges */ - UNSUPPORTED_CONTENT_TYPES, - /** parameter: content type */ - UNSUPPORTED_CONTENT_TYPE } private MessageKey messageKey; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java deleted file mode 100644 index d61734c..0000000 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.olingo.server.api.processor; - -import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.server.api.ODataRequest; -import org.apache.olingo.server.api.ODataResponse; -import org.apache.olingo.server.api.uri.UriInfo; - -/** - * Processor interface for handling collections of entities (collections, EntitySets or feeds). - */ -public interface CollectionProcessor extends Processor { - - /** - * Read entities data from persistency and puts serialized content and status into the response. - * @param request - OData request object containing raw http information. - * @param response - OData response object for collecting response data - * @param uriInfo - information of a parsed OData uri - * @param requestedContentType - requested content type after content negotiation - */ - void readCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType); - -} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java index 028bf6b..359136b 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java @@ -87,7 +87,9 @@ public class DefaultProcessor implements MetadataProcessor, ServiceDocumentProce } catch (Exception e) { // This should never happen but to be sure we have this catch here to prevent sending a stacktrace to a client. String responseContent = - "An unexpected exception occoured during error processing with message: \"" + e.getMessage() + "\""; + "{\"error\":{\"code\":null,\"message\":\"An unexpected exception occoured during " + + "error processing with message: " + + e.getMessage() + "\"}}"; response.setContent(new ByteArrayInputStream(responseContent.getBytes())); response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.APPLICATION_JSON.toContentTypeString()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java new file mode 100644 index 0000000..0e58c96 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling collections of entities (collections, EntitySets or feeds). + */ +public interface EntityCollectionProcessor extends Processor { + + /** + * Read entities data from persistency and puts serialized content and status into the response. + * @param request - OData request object containing raw http information. + * @param response - OData response object for collecting response data + * @param uriInfo - information of a parsed OData uri + * @param requestedContentType - requested content type after content negotiation + */ + void readCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType); + +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/resources/i18n.properties ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/resources/i18n.properties b/lib/server-api/src/main/resources/i18n.properties index 3efb829..7a7fbe9 100644 --- a/lib/server-api/src/main/resources/i18n.properties +++ b/lib/server-api/src/main/resources/i18n.properties @@ -23,9 +23,10 @@ ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED=Invalid HTTP method given: ODataTranslatedException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered. ODataTranslatedException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet). ODataTranslatedException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported. -ODataTranslatedException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with value '%2$s' contains an invalid character-set specification. -ODataTranslatedException.UNSUPPORTED_CONTENT_TYPES=The content-type range '%1$s' is not supported. -ODataTranslatedException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported. +ContentNegotiatorException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with value '%2$s' contains an invalid character-set specification. +ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPES=The content-type range '%1$s' is not supported. +ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported. +ContentNegotiatorException.UNSUPPORTED_FORMAT_OPTION=The $format option '%1$s' is not supported. ODataSerializerException.NOT_IMPLEMENTED=The requested serialization method has not been implemented yet. ODataSerializerException.UNSUPPORTED_FORMAT=The format '%1$s' is not supported. http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java index 2bdadd8..e762464 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java @@ -18,28 +18,23 @@ */ package org.apache.olingo.server.core; +import java.util.ArrayList; +import java.util.List; + import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.format.AcceptType; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.server.api.ODataRequest; -import org.apache.olingo.server.api.ODataTranslatedException; import org.apache.olingo.server.api.processor.CustomContentTypeSupportProcessor; import org.apache.olingo.server.api.processor.FormatContentTypeMapping; import org.apache.olingo.server.api.processor.MetadataProcessor; import org.apache.olingo.server.api.processor.Processor; import org.apache.olingo.server.api.uri.queryoption.FormatOption; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; public class ContentNegotiator { - private final static Logger LOG = LoggerFactory.getLogger(ContentNegotiator.class); - private ContentNegotiator() {} private static List<FormatContentTypeMapping> @@ -71,7 +66,7 @@ public class ContentNegotiator { } public static ContentType doContentNegotiation(final FormatOption formatOption, final ODataRequest request, - final Processor processor, final Class<? extends Processor> processorClass) throws ODataTranslatedException { + final Processor processor, final Class<? extends Processor> processorClass) throws ContentNegotiatorException { ContentType requestedContentType = null; List<FormatContentTypeMapping> supportedContentTypes = getSupportedContentTypes(processor, processorClass); @@ -81,7 +76,6 @@ public class ContentNegotiator { boolean supported = false; if (formatOption != null) { - if ("json".equalsIgnoreCase(formatOption.getText().trim())) { requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40); for (FormatContentTypeMapping entry : supportedContentTypes) { @@ -107,6 +101,10 @@ public class ContentNegotiator { } } } + if (!supported) { + throw new ContentNegotiatorException("Unsupported $format = " + formatOption.getText(), + ContentNegotiatorException.MessageKeys.UNSUPPORTED_FORMAT_OPTION, formatOption.getText()); + } } else if (acceptHeaderValue != null) { List<AcceptType> acceptedContentTypes = AcceptType.create(acceptHeaderValue); @@ -119,8 +117,8 @@ public class ContentNegotiator { if ("utf8".equalsIgnoreCase(value) || "utf-8".equalsIgnoreCase(value)) { ct = ContentType.create(ct, ContentType.PARAMETER_CHARSET_UTF8); } else { - throw new ODataTranslatedException("charset in accept header not supported: " + acceptHeaderValue, - ODataTranslatedException.MessageKeys.WRONG_CHARSET_IN_HEADER, HttpHeader.ACCEPT, acceptHeaderValue); + throw new ContentNegotiatorException("charset in accept header not supported: " + acceptHeaderValue, + ContentNegotiatorException.MessageKeys.WRONG_CHARSET_IN_HEADER, HttpHeader.ACCEPT, acceptHeaderValue); } } @@ -135,13 +133,12 @@ public class ContentNegotiator { } } - if (requestedContentType == null) { - throw new ODataTranslatedException( + if (!supported) { + throw new ContentNegotiatorException( "unsupported accept content type: " + acceptedContentTypes + " != " + supportedContentTypes, - ODataTranslatedException.MessageKeys.UNSUPPORTED_CONTENT_TYPES, acceptedContentTypes.toString()); + ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPES, acceptedContentTypes.toString()); } } else { - if (processorClass == MetadataProcessor.class) { requestedContentType = ContentType.APPLICATION_XML; } else { @@ -157,13 +154,11 @@ public class ContentNegotiator { } if (!supported) { - throw new ODataTranslatedException( + throw new ContentNegotiatorException( "unsupported accept content type: " + requestedContentType + " != " + supportedContentTypes, - ODataTranslatedException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, requestedContentType.toContentTypeString()); + ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, requestedContentType.toContentTypeString()); } - LOG.debug("requested content type: " + requestedContentType); - return requestedContentType; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java new file mode 100644 index 0000000..6e0d823 --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.server.core; + +import org.apache.olingo.server.api.ODataTranslatedException; + +public class ContentNegotiatorException extends ODataTranslatedException { + private static final long serialVersionUID = -8112658467394158700L; + + public static enum MessageKeys implements MessageKey { + /** parameters: HTTP header name, HTTP header value */ + WRONG_CHARSET_IN_HEADER, + /** parameter: list of content-type ranges */ + UNSUPPORTED_CONTENT_TYPES, + /** parameter: content type */ + UNSUPPORTED_CONTENT_TYPE, + /** parameter: format string */ + UNSUPPORTED_FORMAT_OPTION + } + + public ContentNegotiatorException(String developmentMessage, MessageKey messageKey, String... parameters) { + super(developmentMessage, messageKey, parameters); + } + + public ContentNegotiatorException(String developmentMessage, Throwable cause, MessageKey messageKey, + String... parameters) { + super(developmentMessage, cause, messageKey, parameters); + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java index 9c6bf3e..f364a22 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.format.ContentType; @@ -36,7 +35,7 @@ import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.ODataTranslatedException; -import org.apache.olingo.server.api.processor.CollectionProcessor; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.DefaultProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.processor.ExceptionProcessor; @@ -48,6 +47,8 @@ import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.core.uri.parser.Parser; +import org.apache.olingo.server.core.uri.parser.UriParserException; +import org.apache.olingo.server.core.uri.validator.UriValidationException; import org.apache.olingo.server.core.uri.validator.UriValidator; public class ODataHandler { @@ -69,46 +70,17 @@ public class ODataHandler { ContentType requestedContentType = null; ODataResponse response = new ODataResponse(); try { - validateODataVersion(request, response); - Parser parser = new Parser(); - String odUri = - request.getRawODataPath() + (request.getRawQueryPath() == null ? "" : "?" + request.getRawQueryPath()); - UriInfo uriInfo = parser.parseUri(odUri, edm); + processInternal(request, requestedContentType, response); - UriValidator validator = new UriValidator(); - validator.validate(uriInfo, request.getMethod()); + } catch (UriParserException e) { - switch (uriInfo.getKind()) { - case metadata: - MetadataProcessor mp = selectProcessor(MetadataProcessor.class, response); - - requestedContentType = - ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, mp, MetadataProcessor.class); - - mp.readMetadata(request, response, uriInfo, requestedContentType); - break; - case service: - if ("".equals(request.getRawODataPath())) { - RedirectProcessor rdp = selectProcessor(RedirectProcessor.class, response); - rdp.redirect(request, response); - } else { - ServiceDocumentProcessor sdp = selectProcessor(ServiceDocumentProcessor.class, response); - - requestedContentType = - ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, sdp, - ServiceDocumentProcessor.class); - - sdp.readServiceDocument(request, response, uriInfo, requestedContentType); - } - break; - case resource: - handleResourceDispatching(request, response, uriInfo); - break; - default: - throw new ODataTranslatedException("not implemented", - ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); - } + } catch (ContentNegotiatorException e) { + Locale requestedLocale = null; + ODataServerError serverError = + ODataExceptionHelper.createServerErrorObject(e, HttpStatusCode.NOT_ACCEPTABLE.getStatusCode(), + requestedLocale); + handleException(request, response, serverError, requestedContentType); } catch (ODataTranslatedException e) { Locale requestedLocale = null; ODataServerError serverError = @@ -124,6 +96,53 @@ public class ODataHandler { return response; } + private void processInternal(final ODataRequest request, ContentType requestedContentType, + final ODataResponse response) + throws ODataTranslatedException, UriParserException, UriValidationException, ContentNegotiatorException, + ODataApplicationException { + validateODataVersion(request, response); + + Parser parser = new Parser(); + String odUri = + request.getRawODataPath() + (request.getRawQueryPath() == null ? "" : "?" + request.getRawQueryPath()); + UriInfo uriInfo = parser.parseUri(odUri, edm); + + UriValidator validator = new UriValidator(); + validator.validate(uriInfo, request.getMethod()); + + switch (uriInfo.getKind()) { + case metadata: + MetadataProcessor mp = selectProcessor(MetadataProcessor.class, response); + + requestedContentType = + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, mp, MetadataProcessor.class); + + mp.readMetadata(request, response, uriInfo, requestedContentType); + break; + case service: + if ("".equals(request.getRawODataPath())) { + RedirectProcessor rdp = selectProcessor(RedirectProcessor.class, response); + rdp.redirect(request, response); + } else { + ServiceDocumentProcessor sdp = selectProcessor(ServiceDocumentProcessor.class, response); + + requestedContentType = + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, sdp, + ServiceDocumentProcessor.class); + + sdp.readServiceDocument(request, response, uriInfo, requestedContentType); + } + break; + case resource: + handleResourceDispatching(request, response, uriInfo); + break; + default: + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); + throw new ODataTranslatedException("not implemented", + ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + } + private void handleException(ODataRequest request, ODataResponse response, ODataServerError serverError, ContentType requestedContentType) { ExceptionProcessor exceptionProcessor; @@ -132,10 +151,10 @@ public class ODataHandler { } catch (ODataTranslatedException e) { exceptionProcessor = new DefaultProcessor(); } - if (requestedContentType == null) { - requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40); - } - exceptionProcessor.processException(request, response, serverError, requestedContentType); + if (requestedContentType == null) { + requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40); + } + exceptionProcessor.processException(request, response, serverError, requestedContentType); } private void handleResourceDispatching(final ODataRequest request, final ODataResponse response, @@ -148,13 +167,15 @@ public class ODataHandler { case entitySet: if (((UriResourcePartTyped) lastPathSegment).isCollection()) { if (request.getMethod().equals(HttpMethod.GET)) { - CollectionProcessor cp = selectProcessor(CollectionProcessor.class, response); + EntityCollectionProcessor cp = selectProcessor(EntityCollectionProcessor.class, response); requestedContentType = - ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, CollectionProcessor.class); + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, + EntityCollectionProcessor.class); cp.readCollection(request, response, uriInfo, requestedContentType); } else { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); throw new ODataTranslatedException("not implemented", ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } @@ -167,6 +188,7 @@ public class ODataHandler { ep.readEntity(request, response, uriInfo, requestedContentType); } else { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); throw new ODataTranslatedException("not implemented", ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } @@ -175,13 +197,15 @@ public class ODataHandler { case navigationProperty: if (((UriResourceNavigation) lastPathSegment).isCollection()) { if (request.getMethod().equals(HttpMethod.GET)) { - CollectionProcessor cp = selectProcessor(CollectionProcessor.class, response); + EntityCollectionProcessor cp = selectProcessor(EntityCollectionProcessor.class, response); requestedContentType = - ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, CollectionProcessor.class); + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, + EntityCollectionProcessor.class); cp.readCollection(request, response, uriInfo, requestedContentType); } else { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); throw new ODataTranslatedException("not implemented", ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } @@ -194,12 +218,14 @@ public class ODataHandler { ep.readEntity(request, response, uriInfo, requestedContentType); } else { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); throw new ODataTranslatedException("not implemented", ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } } break; default: + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); throw new ODataTranslatedException("not implemented", ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java index ca78ba0..f858aa0 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java @@ -18,6 +18,17 @@ */ package org.apache.olingo.server.core; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpHeader; @@ -25,8 +36,7 @@ import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; -import org.apache.olingo.server.api.ODataTranslatedException; -import org.apache.olingo.server.api.processor.CollectionProcessor; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.CustomContentTypeSupportProcessor; import org.apache.olingo.server.api.processor.FormatContentTypeMapping; import org.apache.olingo.server.api.processor.MetadataProcessor; @@ -35,19 +45,6 @@ import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.queryoption.FormatOption; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class ContentNegotiatorTest { @@ -103,8 +100,6 @@ public class ContentNegotiatorTest { //CHECKSTYLE:ON //@formatter:on - private final static Logger LOG = LoggerFactory.getLogger(ContentNegotiatorTest.class); - @Test public void testServiceDocumentSingleCase() throws Exception { String[] useCase = { ACCEPT_CASE_MIN_UTF8, null, ACCEPT_CASE_MIN_UTF8, null, null }; @@ -139,17 +134,17 @@ public class ContentNegotiatorTest { try { testContentNegotiation(useCase, MetadataProcessor.class); fail("Exeption expected!"); - } catch (Exception e) { + } catch (ContentNegotiatorException e) { + }catch (Exception e) { + e.printStackTrace(); + fail("Wrong Exception: " + e.getClass().getName()); } } } public void testContentNegotiation(final String[] useCase, final Class<? extends Processor> processorClass) - throws ODataTranslatedException { - - LOG.debug(Arrays.asList(useCase).toString()); - + throws Exception { ODataRequest request = new ODataRequest(); request.setMethod(HttpMethod.GET); request.setRawODataPath("/" + (useCase[1] == null ? "" : "?$format=" + useCase[1])); @@ -194,7 +189,7 @@ public class ContentNegotiatorTest { } private class ProcessorStub implements ServiceDocumentProcessor, MetadataProcessor, - CollectionProcessor, + EntityCollectionProcessor, CustomContentTypeSupportProcessor { List<FormatContentTypeMapping> customMapping; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java index 03fc0ea..a81af68 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java @@ -29,13 +29,9 @@ import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataTranslatedException; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class ODataHttpHandlerImplTest { - private final Logger LOG = LoggerFactory.getLogger(ODataHttpHandlerImplTest.class); - @Test public void extractMethod() throws Exception { String[][] mm = { @@ -149,8 +145,6 @@ public class ODataHttpHandlerImplTest { String requestUri = p[1] + p[2] + p[3] + p[4]; String queryString = p[5].isEmpty() ? null : p[5]; - LOG.debug(requestUrl + (queryString == null ? "" : "?" + queryString)); - when(hr.getRequestURL()).thenReturn(new StringBuffer(requestUrl)); when(hr.getRequestURI()).thenReturn(requestUri); when(hr.getQueryString()).thenReturn(queryString); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java index d079dd0..3ea7b1e 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java @@ -31,7 +31,7 @@ import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.ODataTranslatedException; -import org.apache.olingo.server.api.processor.CollectionProcessor; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.uri.UriInfo; @@ -42,7 +42,7 @@ import org.apache.olingo.server.tecsvc.data.DataProvider; import java.util.List; -public class TechnicalProcessor implements CollectionProcessor, EntityProcessor { +public class TechnicalProcessor implements EntityCollectionProcessor, EntityProcessor { private OData odata; private Edm edm; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index efd0e65..5eaff89 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -21,22 +21,28 @@ package org.apache.olingo.server.core; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import java.util.Arrays; +import java.util.Locale; import org.apache.commons.io.IOUtils; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; +import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.processor.MetadataProcessor; import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; +import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Before; import org.junit.Test; @@ -187,4 +193,47 @@ public class ODataHandlerTest { assertEquals(400, response.getStatusCode()); } + @Test + public void testContentNegotiationSupported() { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("$metadata"); + request.setRawQueryPath("$format=xml"); + + ODataResponse response = handler.process(request); + assertNotNull(response); + assertEquals(200, response.getStatusCode()); + } + + @Test + public void testContentNegotiationNotSupported() { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("$metadata"); + request.setRawQueryPath("$format=notSupported"); + + ODataResponse response = handler.process(request); + assertNotNull(response); + assertEquals(406, response.getStatusCode()); + } + + @Test + public void testWithApplicationExceptionInProcessor() throws Exception { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("$metadata"); + + MetadataProcessor metadataProcessor = mock(MetadataProcessor.class); + doThrow(new ODataApplicationException("msg", 412, Locale.ENGLISH)).when(metadataProcessor).readMetadata( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + handler.register(metadataProcessor); + + ODataResponse response = handler.process(request); + assertNotNull(response); + assertEquals(412, response.getStatusCode()); + } }
