[OLINGO-507] Split 'handleResourceDispatching' into several smaller methods

This commit is contained in:
Michael Bolz 2015-01-08 14:22:19 +01:00
parent 883c89c140
commit 6b0d6d2544
6 changed files with 375 additions and 269 deletions

View File

@ -34,11 +34,14 @@ import java.util.List;
import org.apache.olingo.client.api.CommonODataClient; import org.apache.olingo.client.api.CommonODataClient;
import org.apache.olingo.client.api.communication.ODataClientErrorException; import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.ODataServerErrorException;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest; import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataServiceDocumentRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataServiceDocumentRequest;
import org.apache.olingo.client.api.communication.request.retrieve.XMLMetadataRequest; import org.apache.olingo.client.api.communication.request.retrieve.XMLMetadataRequest;
import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.client.api.edm.xml.v4.Reference; import org.apache.olingo.client.api.edm.xml.v4.Reference;
@ -52,9 +55,11 @@ import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
import org.apache.olingo.commons.api.domain.v4.ODataProperty; import org.apache.olingo.commons.api.domain.v4.ODataProperty;
import org.apache.olingo.commons.api.domain.v4.ODataValue; import org.apache.olingo.commons.api.domain.v4.ODataValue;
import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
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.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.commons.core.domain.v4.ODataEntityImpl;
import org.apache.olingo.fit.AbstractBaseTestITCase; import org.apache.olingo.fit.AbstractBaseTestITCase;
import org.apache.olingo.fit.tecsvc.TecSvcConst; import org.apache.olingo.fit.tecsvc.TecSvcConst;
import org.junit.Test; import org.junit.Test;
@ -188,6 +193,42 @@ public class BasicITCase extends AbstractBaseTestITCase {
assertEquals(30112, iterator.next().asPrimitive().toValue()); assertEquals(30112, iterator.next().asPrimitive().toValue());
} }
/**
* Actual an create request for an entity will lead to an "501 - Not Implemented" response
* and hence to an ODataServerErrorException
*/
@Test(expected = ODataServerErrorException.class)
public void createEntity() throws IOException {
final ODataEntityRequest<ODataEntity> request = getClient().getRetrieveRequestFactory()
.getEntityRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESCollAllPrim").appendKeySegment(1).build());
assertNotNull(request);
final ODataRetrieveResponse<ODataEntity> response = request.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
final ODataEntity entity = response.getBody();
assertNotNull(entity);
final ODataEntityCreateRequest<ODataEntity> createRequest = getClient().getCUDRequestFactory()
.getEntityCreateRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESCollAllPrim").build(), entity);
assertNotNull(createRequest);
ODataEntityCreateResponse<ODataEntity> createResponse = createRequest.execute();
final ODataEntity createdEntity = createResponse.getBody();
assertNotNull(createdEntity);
final ODataProperty property = createdEntity.getProperty("CollPropertyInt16");
assertNotNull(property);
assertNotNull(property.getCollectionValue());
assertEquals(3, property.getCollectionValue().size());
Iterator<ODataValue> iterator = property.getCollectionValue().iterator();
assertEquals(1000, iterator.next().asPrimitive().toValue());
assertEquals(2000, iterator.next().asPrimitive().toValue());
assertEquals(30112, iterator.next().asPrimitive().toValue());
}
@Override @Override
protected CommonODataClient<?> getClient() { protected CommonODataClient<?> getClient() {
ODataClient odata = ODataClientFactory.getV4(); ODataClient odata = ODataClientFactory.getV4();

View File

@ -151,4 +151,17 @@ public class ContentNegotiator {
throw new ContentNegotiatorException("unsupported content type: " + contentType, throw new ContentNegotiatorException("unsupported content type: " + contentType,
ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentType.toContentTypeString()); ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentType.toContentTypeString());
} }
public static boolean isSupported(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 true;
}
}
return false;
}
} }

View File

@ -30,6 +30,7 @@ public class ContentNegotiatorException extends ODataTranslatedException {
UNSUPPORTED_CONTENT_TYPES, UNSUPPORTED_CONTENT_TYPES,
/** parameter: content type */ /** parameter: content type */
UNSUPPORTED_CONTENT_TYPE, UNSUPPORTED_CONTENT_TYPE,
/** no parameter */
NO_CONTENT_TYPE_SUPPORTED, NO_CONTENT_TYPE_SUPPORTED,
/** parameter: format string */ /** parameter: format string */
UNSUPPORTED_FORMAT_OPTION; UNSUPPORTED_FORMAT_OPTION;

View File

@ -22,7 +22,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
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;
@ -136,64 +135,70 @@ public class ODataHandler {
} }
private void processInternal(final ODataRequest request, final ODataResponse response) private void processInternal(final ODataRequest request, final ODataResponse response)
throws ODataHandlerException, UriParserException, UriValidationException, ContentNegotiatorException, throws ODataHandlerException, UriParserException, UriValidationException, ContentNegotiatorException,
ODataApplicationException, SerializerException, DeserializerException { ODataApplicationException, SerializerException, DeserializerException {
validateODataVersion(request, response); validateODataVersion(request, response);
uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null, uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null,
serviceMetadata.getEdm()); serviceMetadata.getEdm());
final HttpMethod method = request.getMethod(); final HttpMethod method = request.getMethod();
new UriValidator().validate(uriInfo, method); new UriValidator().validate(uriInfo, method);
switch (uriInfo.getKind()) { switch (uriInfo.getKind()) {
case metadata: case metadata:
if (method == HttpMethod.GET) { if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.METADATA);
selectProcessor(MetadataProcessor.class)
.readMetadata(request, response, uriInfo, requestedContentType);
} else {
throw new ODataHandlerException("HttpMethod " + method + " not allowed for metadata document",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
break;
case service:
if (method == HttpMethod.GET) {
if ("".equals(request.getRawODataPath())) {
selectProcessor(RedirectProcessor.class).redirect(request, response);
} else {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.SERVICE); request, customContentTypeSupport, RepresentationType.METADATA);
selectProcessor(MetadataProcessor.class)
selectProcessor(ServiceDocumentProcessor.class) .readMetadata(request, response, uriInfo, requestedContentType);
.readServiceDocument(request, response, uriInfo, requestedContentType); } else {
throw new ODataHandlerException("HttpMethod " + method + " not allowed for metadata document",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
} }
} else { break;
throw new ODataHandlerException("HttpMethod " + method + " not allowed for service document",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); case service:
} if (method == HttpMethod.GET) {
break; if ("".equals(request.getRawODataPath())) {
case resource: selectProcessor(RedirectProcessor.class).redirect(request, response);
handleResourceDispatching(request, response); } else {
break; final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
case batch: request, customContentTypeSupport, RepresentationType.SERVICE);
if (method == HttpMethod.POST) {
final BatchProcessor bp = selectProcessor(BatchProcessor.class); selectProcessor(ServiceDocumentProcessor.class)
final BatchHandler handler = new BatchHandler(this, bp); .readServiceDocument(request, response, uriInfo, requestedContentType);
handler.process(request, response, true); }
} else { } else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.", throw new ODataHandlerException("HttpMethod " + method + " not allowed for service document",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
} }
break; break;
default:
throw new ODataHandlerException("not implemented", case resource:
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); handleResourceDispatching(request, response);
break;
case batch:
if (method == HttpMethod.POST) {
final BatchProcessor bp = selectProcessor(BatchProcessor.class);
final BatchHandler handler = new BatchHandler(this, bp);
handler.process(request, response, true);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
break;
default:
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
} }
} }
public void handleException(ODataRequest request, ODataResponse response, ODataServerError serverError) { public void handleException(final ODataRequest request, final ODataResponse response,
final ODataServerError serverError) {
ErrorProcessor exceptionProcessor; ErrorProcessor exceptionProcessor;
try { try {
exceptionProcessor = selectProcessor(ErrorProcessor.class); exceptionProcessor = selectProcessor(ErrorProcessor.class);
@ -204,8 +209,8 @@ public class ODataHandler {
ContentType requestedContentType; ContentType requestedContentType;
try { try {
requestedContentType = ContentNegotiator.doContentNegotiation( requestedContentType = ContentNegotiator.doContentNegotiation(
uriInfo == null ? null : uriInfo.getFormatOption(), request, customContentTypeSupport, uriInfo == null ? null : uriInfo.getFormatOption(), request, customContentTypeSupport,
RepresentationType.ERROR); RepresentationType.ERROR);
} catch (final ContentNegotiatorException e) { } catch (final ContentNegotiatorException e) {
requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40); requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
} }
@ -213,274 +218,318 @@ public class ODataHandler {
} }
private void handleResourceDispatching(final ODataRequest request, final ODataResponse response) private void handleResourceDispatching(final ODataRequest request, final ODataResponse response)
throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException, throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException,
SerializerException, DeserializerException { SerializerException, DeserializerException {
final HttpMethod method = request.getMethod(); final HttpMethod method = request.getMethod();
final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1; final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
final UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex); final UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
switch (lastPathSegment.getKind()) { switch (lastPathSegment.getKind()) {
case entitySet: case entitySet:
case navigationProperty: case navigationProperty:
if (((UriResourcePartTyped) lastPathSegment).isCollection()) { handleEntityDispatching(request, response, method, (UriResourcePartTyped) lastPathSegment);
if (method == HttpMethod.GET) { break;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY);
selectProcessor(EntityCollectionProcessor.class) case count:
.readEntityCollection(request, response, uriInfo, requestedContentType); handleCountDispatching(request, response, method, lastPathSegmentIndex);
} else if (method == HttpMethod.POST) { break;
if (isMedia(lastPathSegment)) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(MediaEntityProcessor.class)
.createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
} else {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.ENTITY);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(EntityProcessor.class)
.createEntity(request, response, uriInfo, requestFormat, responseFormat);
}
} 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 requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(EntityProcessor.class) case primitiveProperty:
.readEntity(request, response, uriInfo, requestedContentType); handlePrimitivePropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment);
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { break;
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
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) {
selectProcessor(isMedia(lastPathSegment) ? MediaEntityProcessor.class : EntityProcessor.class)
.deleteEntity(request, response, uriInfo);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
break;
case count: case complexProperty:
handleComplexPropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment);
break;
case value:
handleValueDispatching(request, response, method, lastPathSegmentIndex);
break;
case ref:
handleReferenceDispatching(request, response, method, lastPathSegmentIndex);
break;
default:
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
}
private void handleReferenceDispatching(final ODataRequest request, final ODataResponse response,
final HttpMethod method, final int lastPathSegmentIndex)
throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException,
DeserializerException {
if (((UriResourcePartTyped) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).isCollection()) {
if (method == HttpMethod.GET) { if (method == HttpMethod.GET) {
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) {
selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo);
} else if (resource instanceof UriResourcePrimitiveProperty) {
selectProcessor(CountPrimitiveCollectionProcessor.class)
.countPrimitiveCollection(request, response, uriInfo);
} else {
selectProcessor(CountComplexCollectionProcessor.class)
.countComplexCollection(request, response, uriInfo);
}
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
break;
case primitiveProperty:
final UriResourceProperty propertyResource = (UriResourceProperty) lastPathSegment;
final RepresentationType representationType = propertyResource.isCollection() ?
RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE;
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class)
.readPrimitive(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(PrimitiveCollectionProcessor.class)
.readPrimitiveCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, representationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType); request, customContentTypeSupport, RepresentationType.COLLECTION_REFERENCE);
if (representationType == RepresentationType.PRIMITIVE) { selectProcessor(ReferenceCollectionProcessor.class)
selectProcessor(PrimitiveProcessor.class) .readReferenceCollection(request, response, uriInfo, responseFormat);
.updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); } else if (method == HttpMethod.POST) {
} else { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
selectProcessor(PrimitiveCollectionProcessor.class) checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE);
.updatePrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); selectProcessor(ReferenceProcessor.class)
} .createReference(request, response, uriInfo, requestFormat);
} else if (method == HttpMethod.DELETE) {
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class)
.deletePrimitive(request, response, uriInfo);
} else {
selectProcessor(PrimitiveCollectionProcessor.class)
.deletePrimitiveCollection(request, response, uriInfo);
}
} else { } else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.", throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
} }
break; } else {
case complexProperty:
final UriResourceProperty complexPropertyResource = (UriResourceProperty) lastPathSegment;
final RepresentationType complexRepresentationType = complexPropertyResource.isCollection() ?
RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX;
if (method == HttpMethod.GET) { if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, complexRepresentationType); request, customContentTypeSupport, RepresentationType.REFERENCE);
if (complexRepresentationType == RepresentationType.COMPLEX) { selectProcessor(ReferenceProcessor.class).readReference(request, response, uriInfo, responseFormat);
selectProcessor(ComplexProcessor.class)
.readComplex(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(ComplexCollectionProcessor.class)
.readComplexCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, complexRepresentationType); checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), selectProcessor(ReferenceProcessor.class)
request, customContentTypeSupport, complexRepresentationType); .updateReference(request, response, uriInfo, requestFormat);
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) { selectProcessor(ReferenceProcessor.class)
selectProcessor(ComplexProcessor.class) .deleteReference(request, response, uriInfo);
.deleteComplex(request, response, uriInfo);
} else {
selectProcessor(ComplexCollectionProcessor.class)
.deleteComplexCollection(request, response, uriInfo);
}
} else { } else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.", throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
} }
break; }
}
case value: private void handleValueDispatching(final ODataRequest request, final ODataResponse response,
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); final HttpMethod method, final int lastPathSegmentIndex)
if (resource instanceof UriResourceProperty) { throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException,
final RepresentationType valueRepresentationType = DeserializerException {
(EdmPrimitiveType) ((UriResourceProperty) resource).getType() == final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ? if (resource instanceof UriResourceProperty) {
RepresentationType.BINARY : RepresentationType.VALUE; final RepresentationType valueRepresentationType =
if (method == HttpMethod.GET) { ((UriResourceProperty) resource).getType() ==
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
request, customContentTypeSupport, valueRepresentationType); RepresentationType.BINARY : RepresentationType.VALUE;
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
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) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, valueRepresentationType); checkContentTypeSupport(requestFormat, valueRepresentationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, valueRepresentationType); request, customContentTypeSupport, valueRepresentationType);
selectProcessor(PrimitiveValueProcessor.class) selectProcessor(PrimitiveValueProcessor.class)
.updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); .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);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
} else { } else {
if (method == HttpMethod.GET) { throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
request, customContentTypeSupport, RepresentationType.MEDIA); }
selectProcessor(MediaEntityProcessor.class) } else {
.readMediaEntity(request, response, uriInfo, requestedContentType); if (method == HttpMethod.GET) {
} else if (method == HttpMethod.PUT) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.MEDIA);
selectProcessor(MediaEntityProcessor.class)
.readMediaEntity(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(MediaEntityProcessor.class)
.updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
} else if (method == HttpMethod.DELETE) {
selectProcessor(MediaEntityProcessor.class).deleteEntity(request, response, uriInfo);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
}
private void handleComplexPropertyDispatching(final ODataRequest request, final ODataResponse response,
final HttpMethod method,
final UriResourceProperty complexPropertyResource)
throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException,
DeserializerException {
final RepresentationType complexRepresentationType = complexPropertyResource.isCollection() ?
RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX;
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, complexRepresentationType);
if (complexRepresentationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class)
.readComplex(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(ComplexCollectionProcessor.class)
.readComplexCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, 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) {
if (complexRepresentationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class).deleteComplex(request, response, uriInfo);
} else {
selectProcessor(ComplexCollectionProcessor.class).deleteComplexCollection(request, response, uriInfo);
}
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
private void handlePrimitivePropertyDispatching(final ODataRequest request, final ODataResponse response,
final HttpMethod method, final UriResourceProperty propertyResource)
throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException,
DeserializerException {
final RepresentationType representationType = propertyResource.isCollection() ?
RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE;
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, representationType);
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class).readPrimitive(request, response, uriInfo, requestedContentType);
} else {
selectProcessor(PrimitiveCollectionProcessor.class)
.readPrimitiveCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, 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) {
if (representationType == RepresentationType.PRIMITIVE) {
selectProcessor(PrimitiveProcessor.class).deletePrimitive(request, response, uriInfo);
} else {
selectProcessor(PrimitiveCollectionProcessor.class).deletePrimitiveCollection(request, response, uriInfo);
}
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
private void handleCountDispatching(final ODataRequest request, final ODataResponse response,
final HttpMethod method, final int lastPathSegmentIndex)
throws ODataApplicationException, SerializerException, ODataHandlerException {
if (method == HttpMethod.GET) {
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) {
selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo);
} else if (resource instanceof UriResourcePrimitiveProperty) {
selectProcessor(CountPrimitiveCollectionProcessor.class)
.countPrimitiveCollection(request, response, uriInfo);
} else {
selectProcessor(CountComplexCollectionProcessor.class)
.countComplexCollection(request, response, uriInfo);
}
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
private void handleEntityDispatching(final ODataRequest request, final ODataResponse response,
final HttpMethod method,
final UriResourcePartTyped uriResourcePart)
throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException,
DeserializerException {
if (uriResourcePart.isCollection()) {
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY);
selectProcessor(EntityCollectionProcessor.class)
.readEntityCollection(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.POST) {
if (isMedia(uriResourcePart)) {
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY); request, customContentTypeSupport, RepresentationType.ENTITY);
selectProcessor(MediaEntityProcessor.class) selectProcessor(MediaEntityProcessor.class)
.updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat); .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat);
} else if (method == HttpMethod.DELETE) {
selectProcessor(MediaEntityProcessor.class)
.deleteEntity(request, response, uriInfo);
} else { } else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
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)); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.REFERENCE); checkContentTypeSupport(requestFormat, RepresentationType.ENTITY);
selectProcessor(ReferenceProcessor.class) final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
.createReference(request, response, uriInfo, requestFormat); request, customContentTypeSupport, RepresentationType.ENTITY);
} else { selectProcessor(EntityProcessor.class)
throw new ODataHandlerException("HTTP method " + method + " is not allowed.", .createEntity(request, response, uriInfo, requestFormat, responseFormat);
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
} }
} else { } else {
if (method == HttpMethod.GET) { throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
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; } else {
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.ENTITY);
default: selectProcessor(EntityProcessor.class).readEntity(request, response, uriInfo, requestedContentType);
throw new ODataHandlerException("not implemented", } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, 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) {
selectProcessor(isMedia(uriResourcePart) ? MediaEntityProcessor.class : EntityProcessor.class)
.deleteEntity(request, response, uriInfo);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
}
}
}
private void checkContentTypeSupport(ContentType requestFormat, RepresentationType representationType)
throws ODataHandlerException, ContentNegotiatorException {
if (!ContentNegotiator.isSupported(requestFormat, customContentTypeSupport, representationType)) {
final String contentTypeString = requestFormat.toContentTypeString();
throw new ODataHandlerException("ContentType " + contentTypeString + " is not supported.",
ODataHandlerException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentTypeString);
} }
} }
private void validateODataVersion(final ODataRequest request, final ODataResponse response) private void validateODataVersion(final ODataRequest request, final ODataResponse response)
throws ODataHandlerException { throws ODataHandlerException {
final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION); final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION);
response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString()); response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString());
if (maxVersion != null) { if (maxVersion != null) {
if (ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) { if (ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) {
throw new ODataHandlerException("ODataVersion not supported: " + maxVersion, throw new ODataHandlerException("ODataVersion not supported: " + maxVersion,
ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED, maxVersion); ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED, maxVersion);
} }
} }
} }
private boolean isMedia(final UriResource pathSegment) { private boolean isMedia(final UriResource pathSegment) {
return pathSegment instanceof UriResourceEntitySet return pathSegment instanceof UriResourceEntitySet
&& ((UriResourceEntitySet) pathSegment).getEntityType().hasStream() && ((UriResourceEntitySet) pathSegment).getEntityType().hasStream()
|| pathSegment instanceof UriResourceNavigation || pathSegment instanceof UriResourceNavigation
&& ((EdmEntityType) ((UriResourceNavigation) pathSegment).getType()).hasStream(); && ((EdmEntityType) ((UriResourceNavigation) pathSegment).getType()).hasStream();
} }
private <T extends Processor> T selectProcessor(final Class<T> cls) throws ODataHandlerException { private <T extends Processor> T selectProcessor(final Class<T> cls) throws ODataHandlerException {
@ -491,7 +540,7 @@ public class ODataHandler {
} }
} }
throw new ODataHandlerException("Processor: " + cls.getSimpleName() + " not registered.", throw new ODataHandlerException("Processor: " + cls.getSimpleName() + " not registered.",
ODataHandlerException.MessageKeys.PROCESSOR_NOT_IMPLEMENTED, cls.getSimpleName()); ODataHandlerException.MessageKeys.PROCESSOR_NOT_IMPLEMENTED, cls.getSimpleName());
} }
public void register(final Processor processor) { public void register(final Processor processor) {

View File

@ -29,7 +29,8 @@ public class ODataHandlerException extends ODataTranslatedException {
/** parameter: HTTP method */ INVALID_HTTP_METHOD, /** parameter: HTTP method */ INVALID_HTTP_METHOD,
/** parameter: HTTP method */ HTTP_METHOD_NOT_ALLOWED, /** parameter: HTTP method */ HTTP_METHOD_NOT_ALLOWED,
/** parameter: processor interface */ PROCESSOR_NOT_IMPLEMENTED, /** parameter: processor interface */ PROCESSOR_NOT_IMPLEMENTED,
FUNCTIONALITY_NOT_IMPLEMENTED, /** no parameter */ FUNCTIONALITY_NOT_IMPLEMENTED,
/** parameter: content type */ UNSUPPORTED_CONTENT_TYPE,
/** parameter: version */ ODATA_VERSION_NOT_SUPPORTED; /** parameter: version */ ODATA_VERSION_NOT_SUPPORTED;
@Override @Override

View File

@ -24,6 +24,7 @@ ODataHandlerException.HTTP_METHOD_NOT_ALLOWED=HTTP method '%1$s' not allowed for
ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered. ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered.
ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet). ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet).
ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported. ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported.
ODataHandlerException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported for this request.
UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the last segment. UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the last segment.
UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined. UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined.