[OLINGO-507] nearly complete server dispatching

Change-Id: I4c337f5e8f9b3caeaa14fc658464baa3f4bf1df8

Signed-off-by: Christian Amend <chrisam@apache.org>
This commit is contained in:
Klaus Straubinger 2014-12-19 16:31:14 +01:00 committed by Christian Amend
parent 574a65037a
commit 883c89c140
6 changed files with 296 additions and 53 deletions

View File

@ -18,7 +18,6 @@
*/ */
package org.apache.olingo.server.api.processor; package org.apache.olingo.server.api.processor;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.ODataResponse;
@ -36,11 +35,9 @@ public interface CountPrimitiveCollectionProcessor extends Processor {
* @param request OData request object containing raw HTTP information. * @param request OData request object containing raw HTTP information.
* @param response OData response object for collecting response data * @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI * @param uriInfo information of a parsed OData URI
* @param responseFormat requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure * @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed * @throws SerializerException if serialization failed
*/ */
void countPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, void countPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo)
ContentType responseFormat)
throws ODataApplicationException, SerializerException; throws ODataApplicationException, SerializerException;
} }

View File

@ -45,33 +45,27 @@ public interface ReferenceProcessor extends Processor {
/** /**
* Creates entity reference in the persistence and puts content, status, and Location into the response. * Creates entity reference in the persistence and puts content, status, and Location into the response.
* @param request OData request object containing raw HTTP information * @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data * @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI * @param uriInfo information of a parsed OData URI
* @param requestFormat content type of body sent with request * @param requestFormat content type of body sent with request
* @param responseFormat requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure * @throws ODataApplicationException if the service implementation encounters a failure
* @throws DeserializerException if de-serialization failed * @throws DeserializerException if de-serialization failed
* @throws SerializerException if serialization failed
*/ */
void createReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, void createReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat)
ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException;
throws ODataApplicationException, DeserializerException, SerializerException;
/** /**
* Update entity reference in the persistence and puts content, status, and Location into the response. * Update entity reference in the persistence and puts content, status, and Location into the response.
* @param request OData request object containing raw HTTP information * @param request OData request object containing raw HTTP information
* @param response OData response object for collecting response data * @param response OData response object for collecting response data
* @param uriInfo information of a parsed OData URI * @param uriInfo information of a parsed OData URI
* @param requestFormat content type of body sent with request * @param requestFormat content type of body sent with request
* @param responseFormat requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure * @throws ODataApplicationException if the service implementation encounters a failure
* @throws DeserializerException if de-serialization failed * @throws DeserializerException if de-serialization failed
* @throws SerializerException if serialization failed
*/ */
void updateReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, void updateReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat)
ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException;
throws ODataApplicationException, DeserializerException, SerializerException;
/** /**
* Deletes reference to an entity from persistence and puts the status into the response. * Deletes reference to an entity from persistence and puts the status into the response.

View File

@ -138,4 +138,17 @@ public class ContentNegotiator {
} }
return null; return null;
} }
public static void checkSupport(final ContentType contentType,
final CustomContentTypeSupport customContentTypeSupport, final RepresentationType representationType)
throws ContentNegotiatorException {
for (final ContentType supportedContentType :
getSupportedContentTypes(customContentTypeSupport, representationType)) {
if (AcceptType.fromContentType(supportedContentType).get(0).matches(contentType)) {
return;
}
}
throw new ContentNegotiatorException("unsupported content type: " + contentType,
ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentType.toContentTypeString());
}
} }

View File

@ -41,7 +41,9 @@ import org.apache.olingo.server.api.deserializer.DeserializerException;
import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor; import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor; import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor; import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.CountPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.DefaultProcessor; import org.apache.olingo.server.api.processor.DefaultProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.processor.EntityProcessor;
@ -52,6 +54,8 @@ import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor; import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.PrimitiveValueProcessor; import org.apache.olingo.server.api.processor.PrimitiveValueProcessor;
import org.apache.olingo.server.api.processor.Processor; import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
import org.apache.olingo.server.api.processor.ReferenceProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.serializer.CustomContentTypeSupport; import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
import org.apache.olingo.server.api.serializer.RepresentationType; import org.apache.olingo.server.api.serializer.RepresentationType;
@ -61,6 +65,7 @@ import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet; import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.core.batchhandler.BatchHandler; import org.apache.olingo.server.core.batchhandler.BatchHandler;
import org.apache.olingo.server.core.uri.parser.Parser; import org.apache.olingo.server.core.uri.parser.Parser;
@ -143,7 +148,7 @@ public class ODataHandler {
switch (uriInfo.getKind()) { switch (uriInfo.getKind()) {
case metadata: case metadata:
if (method.equals(HttpMethod.GET)) { if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.METADATA); request, customContentTypeSupport, RepresentationType.METADATA);
selectProcessor(MetadataProcessor.class) selectProcessor(MetadataProcessor.class)
@ -154,7 +159,7 @@ public class ODataHandler {
} }
break; break;
case service: case service:
if (method.equals(HttpMethod.GET)) { if (method == HttpMethod.GET) {
if ("".equals(request.getRawODataPath())) { if ("".equals(request.getRawODataPath())) {
selectProcessor(RedirectProcessor.class).redirect(request, response); selectProcessor(RedirectProcessor.class).redirect(request, response);
} else { } else {
@ -173,11 +178,14 @@ public class ODataHandler {
handleResourceDispatching(request, response); handleResourceDispatching(request, response);
break; break;
case batch: case batch:
final BatchProcessor bp = selectProcessor(BatchProcessor.class); if (method == HttpMethod.POST) {
final BatchHandler handler = new BatchHandler(this, bp); final BatchProcessor bp = selectProcessor(BatchProcessor.class);
final BatchHandler handler = new BatchHandler(this, bp);
handler.process(request, response, true); handler.process(request, response, true);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
break; break;
default: default:
throw new ODataHandlerException("not implemented", throw new ODataHandlerException("not implemented",
@ -230,6 +238,7 @@ public class ODataHandler {
.createMediaEntity(request, response, uriInfo, requestFormat, responseFormat); .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
} else { } else {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.ENTITY);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY); request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(EntityProcessor.class) selectProcessor(EntityProcessor.class)
@ -247,8 +256,12 @@ public class ODataHandler {
selectProcessor(EntityProcessor.class) selectProcessor(EntityProcessor.class)
.readEntity(request, response, uriInfo, requestedContentType); .readEntity(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented", final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.ENTITY);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(EntityProcessor.class)
.updateEntity(request, response, uriInfo, requestFormat, responseFormat);
} else if (method == HttpMethod.DELETE) { } else if (method == HttpMethod.DELETE) {
selectProcessor(isMedia(lastPathSegment) ? MediaEntityProcessor.class : EntityProcessor.class) selectProcessor(isMedia(lastPathSegment) ? MediaEntityProcessor.class : EntityProcessor.class)
.deleteEntity(request, response, uriInfo); .deleteEntity(request, response, uriInfo);
@ -265,10 +278,12 @@ public class ODataHandler {
if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) { if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) {
selectProcessor(CountEntityCollectionProcessor.class) selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo); .countEntityCollection(request, response, uriInfo);
} else if (resource instanceof UriResourcePrimitiveProperty) {
selectProcessor(CountPrimitiveCollectionProcessor.class)
.countPrimitiveCollection(request, response, uriInfo);
} else { } else {
throw new ODataHandlerException( selectProcessor(CountComplexCollectionProcessor.class)
"Count of collections of primitive-type or complex-type instances is not implemented.", .countComplexCollection(request, response, uriInfo);
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
} }
} else { } else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.", throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
@ -291,8 +306,17 @@ public class ODataHandler {
.readPrimitiveCollection(request, response, uriInfo, requestedContentType); .readPrimitiveCollection(request, response, uriInfo, requestedContentType);
} }
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented", final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, representationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class)
.updatePrimitive(request, response, uriInfo, requestFormat, responseFormat);
} else {
selectProcessor(PrimitiveCollectionProcessor.class)
.updatePrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat);
}
} else if (method == HttpMethod.DELETE) { } else if (method == HttpMethod.DELETE) {
if (representationType == RepresentationType.PRIMITIVE) { if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class) selectProcessor(PrimitiveProcessor.class)
@ -322,8 +346,17 @@ public class ODataHandler {
.readComplexCollection(request, response, uriInfo, requestedContentType); .readComplexCollection(request, response, uriInfo, requestedContentType);
} }
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented", final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, complexRepresentationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, complexRepresentationType);
if (complexRepresentationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class)
.updateComplex(request, response, uriInfo, requestFormat, responseFormat);
} else {
selectProcessor(ComplexCollectionProcessor.class)
.updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat);
}
} else if (method == HttpMethod.DELETE) { } else if (method == HttpMethod.DELETE) {
if (complexRepresentationType == RepresentationType.COMPLEX) { if (complexRepresentationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class) selectProcessor(ComplexProcessor.class)
@ -341,19 +374,23 @@ public class ODataHandler {
case value: case value:
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceProperty) { if (resource instanceof UriResourceProperty) {
final RepresentationType valueRepresentationType =
(EdmPrimitiveType) ((UriResourceProperty) resource).getType() ==
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
RepresentationType.BINARY : RepresentationType.VALUE;
if (method == HttpMethod.GET) { if (method == HttpMethod.GET) {
final RepresentationType valueRepresentationType =
(EdmPrimitiveType) ((UriResourceProperty) resource).getType() ==
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
RepresentationType.BINARY : RepresentationType.VALUE;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, valueRepresentationType); request, customContentTypeSupport, valueRepresentationType);
selectProcessor(PrimitiveValueProcessor.class) selectProcessor(PrimitiveValueProcessor.class)
.readPrimitiveValue(request, response, uriInfo, requestedContentType); .readPrimitiveValue(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT) { } else if (method == HttpMethod.PUT) {
throw new ODataHandlerException("not implemented", final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, valueRepresentationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, valueRepresentationType);
selectProcessor(PrimitiveValueProcessor.class)
.updatePrimitive(request, response, uriInfo, requestFormat, responseFormat);
} else if (method == HttpMethod.DELETE) { } else if (method == HttpMethod.DELETE) {
selectProcessor(PrimitiveValueProcessor.class) selectProcessor(PrimitiveValueProcessor.class)
.deletePrimitive(request, response, uriInfo); .deletePrimitive(request, response, uriInfo);
@ -383,6 +420,43 @@ public class ODataHandler {
} }
break; break;
case ref:
if (((UriResourcePartTyped) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).isCollection()) {
if (method == HttpMethod.GET) {
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.COLLECTION_REFERENCE);
selectProcessor(ReferenceCollectionProcessor.class)
.readReferenceCollection(request, response, uriInfo, responseFormat);
} else if (method == HttpMethod.POST) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.REFERENCE);
selectProcessor(ReferenceProcessor.class)
.createReference(request, response, uriInfo, requestFormat);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
} else {
if (method == HttpMethod.GET) {
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.REFERENCE);
selectProcessor(ReferenceProcessor.class)
.readReference(request, response, uriInfo, responseFormat);
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.REFERENCE);
selectProcessor(ReferenceProcessor.class)
.updateReference(request, response, uriInfo, requestFormat);
} else if (method == HttpMethod.DELETE) {
selectProcessor(ReferenceProcessor.class)
.deleteReference(request, response, uriInfo);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
break;
default: default:
throw new ODataHandlerException("not implemented", throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);

View File

@ -30,7 +30,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataRequest;
@ -142,6 +144,31 @@ public class ContentNegotiatorTest {
} }
} }
@Test
public void checkSupport() throws Exception {
ContentNegotiator.checkSupport(ODataFormat.JSON.getContentType(ODataServiceVersion.V40), null,
RepresentationType.ENTITY);
ContentNegotiator.checkSupport(ContentType.TEXT_PLAIN, null, RepresentationType.VALUE);
try {
ContentNegotiator.checkSupport(ContentType.APPLICATION_SVG_XML, null, RepresentationType.ENTITY);
fail("Exception expected.");
} catch (final ContentNegotiatorException e) {
assertEquals(ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, e.getMessageKey());
}
ContentNegotiator.checkSupport(ContentType.create("a/b"), createCustomContentTypeSupport("a/b"),
RepresentationType.ENTITY);
ContentNegotiator.checkSupport(ContentType.create("a/b", "c=d"), createCustomContentTypeSupport("a/b"),
RepresentationType.ENTITY);
try {
ContentNegotiator.checkSupport(ContentType.create("a/b"), createCustomContentTypeSupport("a/b;c=d"),
RepresentationType.ENTITY);
fail("Exception expected.");
} catch (final ContentNegotiatorException e) {
assertEquals(ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, e.getMessageKey());
}
}
private void testContentNegotiation(final String[] useCase, final RepresentationType representationType) private void testContentNegotiation(final String[] useCase, final RepresentationType representationType)
throws ContentNegotiatorException { throws ContentNegotiatorException {
@ -156,13 +183,8 @@ public class ContentNegotiatorTest {
request.addHeader(HttpHeader.ACCEPT, Arrays.asList(useCase[2])); request.addHeader(HttpHeader.ACCEPT, Arrays.asList(useCase[2]));
} }
CustomContentTypeSupport customContentTypeSupport = null; final CustomContentTypeSupport customContentTypeSupport = useCase[3] == null ? null :
if (useCase[3] != null) { createCustomContentTypeSupport(useCase[3]);
customContentTypeSupport = mock(CustomContentTypeSupport.class);
when(customContentTypeSupport.modifySupportedContentTypes(
anyListOf(ContentType.class), any(RepresentationType.class)))
.thenReturn(createCustomContentTypes(useCase[3]));
}
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation( final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(
formatOption, request, customContentTypeSupport, representationType); formatOption, request, customContentTypeSupport, representationType);
@ -173,7 +195,7 @@ public class ContentNegotiatorTest {
} }
} }
private List<ContentType> createCustomContentTypes(final String contentTypeString) { private CustomContentTypeSupport createCustomContentTypeSupport(final String contentTypeString) {
final String[] contentTypes = contentTypeString.split(","); final String[] contentTypes = contentTypeString.split(",");
List<ContentType> types = new ArrayList<ContentType>(); List<ContentType> types = new ArrayList<ContentType>();
@ -181,6 +203,10 @@ public class ContentNegotiatorTest {
types.add(ContentType.create(contentTypes[i])); types.add(ContentType.create(contentTypes[i]));
} }
return types; CustomContentTypeSupport customContentTypeSupport = mock(CustomContentTypeSupport.class);
when(customContentTypeSupport.modifySupportedContentTypes(
anyListOf(ContentType.class), any(RepresentationType.class)))
.thenReturn(types);
return customContentTypeSupport;
} }
} }

View File

@ -25,6 +25,7 @@ import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import java.util.Collections; import java.util.Collections;
@ -35,6 +36,7 @@ import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.commons.api.http.HttpMethod;
@ -47,9 +49,12 @@ import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edm.provider.EdmProvider; import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.edm.provider.EntitySet; import org.apache.olingo.server.api.edm.provider.EntitySet;
import org.apache.olingo.server.api.edmx.EdmxReference; import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor; import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor; import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor; import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.CountPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.MediaEntityProcessor; import org.apache.olingo.server.api.processor.MediaEntityProcessor;
@ -58,6 +63,8 @@ import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor; import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.PrimitiveValueProcessor; import org.apache.olingo.server.api.processor.PrimitiveValueProcessor;
import org.apache.olingo.server.api.processor.Processor; import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
import org.apache.olingo.server.api.processor.ReferenceProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
@ -219,6 +226,20 @@ public class ODataHandlerTest {
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode()); assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
} }
@Test
public void dispatchBatch() throws Exception {
final String uri = "$batch";
final BatchProcessor processor = mock(BatchProcessor.class);
dispatch(HttpMethod.POST, uri, processor);
// TODO: Verify that batch processing has been called.
dispatchMethodNotAllowed(HttpMethod.GET, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test @Test
public void dispatchEntitySet() throws Exception { public void dispatchEntitySet() throws Exception {
final String uri = "ESAllPrim"; final String uri = "ESAllPrim";
@ -266,6 +287,16 @@ public class ODataHandlerTest {
verify(processor).readEntity( verify(processor).readEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteEntity(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deleteEntity(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -317,6 +348,16 @@ public class ODataHandlerTest {
verify(processor).readPrimitive( verify(processor).readPrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -332,10 +373,17 @@ public class ODataHandlerTest {
verify(processor).readPrimitiveValue(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), verify(processor).readPrimitiveValue(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class)); any(ContentType.class));
dispatch(HttpMethod.PUT, uri, null, HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString(),
processor);
verify(processor).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor); dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
} }
@Test @Test
@ -347,12 +395,31 @@ public class ODataHandlerTest {
verify(processor).readPrimitiveCollection( verify(processor).readPrimitiveCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updatePrimitiveCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitiveCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deletePrimitiveCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor); dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
} }
@Test
public void dispatchPrimitiveCollectionPropertyCount() throws Exception {
final String uri = "ESMixPrimCollComp(7)/CollPropertyString/$count";
final CountPrimitiveCollectionProcessor processor = mock(CountPrimitiveCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).countPrimitiveCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test @Test
public void dispatchComplexProperty() throws Exception { public void dispatchComplexProperty() throws Exception {
final String uri = "ESMixPrimCollComp(7)/PropertyComp"; final String uri = "ESMixPrimCollComp(7)/PropertyComp";
@ -362,6 +429,16 @@ public class ODataHandlerTest {
verify(processor).readComplex( verify(processor).readComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteComplex(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deleteComplex(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -377,12 +454,72 @@ public class ODataHandlerTest {
verify(processor).readComplexCollection( verify(processor).readComplexCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateComplexCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor); dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteComplexCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); verify(processor).deleteComplexCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor); dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
} }
@Test
public void dispatchComplexCollectionPropertyCount() throws Exception {
final String uri = "ESMixPrimCollComp(7)/CollPropertyComp/$count";
final CountComplexCollectionProcessor processor = mock(CountComplexCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).countComplexCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test
public void dispatchReference() throws Exception {
final String uri = "ESAllPrim(0)/NavPropertyETTwoPrimOne/$ref";
final ReferenceProcessor processor = mock(ReferenceProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).readReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatch(HttpMethod.POST, uri.replace("One", "Many"), processor);
verify(processor).createReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
}
@Test
public void dispatchReferenceCollection() throws Exception {
final String uri = "ESAllPrim(0)/NavPropertyETTwoPrimMany/$ref";
final ReferenceCollectionProcessor processor = mock(ReferenceCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).readReferenceCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
private ODataResponse dispatch(final HttpMethod method, final String path, final String query, private ODataResponse dispatch(final HttpMethod method, final String path, final String query,
final String headerName, final String headerValue, final Processor processor) { final String headerName, final String headerValue, final Processor processor) {
ODataRequest request = new ODataRequest(); ODataRequest request = new ODataRequest();
@ -397,6 +534,8 @@ public class ODataHandlerTest {
if (headerName != null) { if (headerName != null) {
request.addHeader(headerName, Collections.singletonList(headerValue)); request.addHeader(headerName, Collections.singletonList(headerValue));
} }
request.addHeader(HttpHeader.CONTENT_TYPE, Collections.singletonList(
ODataFormat.JSON.getContentType(ODataServiceVersion.V40).toContentTypeString()));
final OData odata = OData.newInstance(); final OData odata = OData.newInstance();
final ServiceMetadata metadata = odata.createServiceMetadata( final ServiceMetadata metadata = odata.createServiceMetadata(