From 15bd15267a36ab2318e0824f6fcbb06f3d7a3351 Mon Sep 17 00:00:00 2001 From: Christian Holzer Date: Tue, 28 Oct 2014 16:55:57 +0100 Subject: [PATCH] Tech Servlet Signed-off-by: Christian Amend --- .../server/api}/batch/BatchException.java | 4 +- .../server/api/batch/BatchOperation.java | 36 +++++ .../server/api/processor/BatchProcessor.java | 31 ++++ .../olingo/server/core/ODataHandler.java | 12 +- .../batch/handler/BatchChangeSetSorter.java | 145 ++++++++++++++++++ .../core/batch/handler/BatchHandler.java | 68 ++++++++ .../batch/handler/BatchOperationImpl.java | 74 +++++++++ .../core/batch/handler/BatchPartHandler.java | 66 ++++++++ .../batch/handler/ODataResponsePartImpl.java | 44 ++++++ .../core/batch/parser/BatchBodyPart.java | 2 +- .../core/batch/parser/BatchChangeSetPart.java | 2 +- .../server/core/batch/parser/BatchParser.java | 2 +- .../core/batch/parser/BatchParserCommon.java | 5 +- .../batch/parser/BatchQueryOperation.java | 2 +- .../BatchRequestTransformator.java | 8 +- .../transformator/BatchTransformator.java | 2 +- .../BatchTransformatorCommon.java | 4 +- .../batch/writer/BatchResponseWriter.java | 4 +- .../core/batch/BatchRequestParserTest.java | 3 +- .../batch/parser/BatchParserCommonTest.java | 2 +- .../batch/writer/BatchResponseWriterTest.java | 2 +- .../tecsvc/processor/TechnicalProcessor.java | 39 ++++- 22 files changed, 535 insertions(+), 22 deletions(-) rename lib/{server-core/src/main/java/org/apache/olingo/server/core => server-api/src/main/java/org/apache/olingo/server/api}/batch/BatchException.java (94%) create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchOperation.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/BatchProcessor.java create mode 100644 lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchChangeSetSorter.java create mode 100644 lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchHandler.java create mode 100644 lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchOperationImpl.java create mode 100644 lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchPartHandler.java create mode 100644 lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/ODataResponsePartImpl.java diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/BatchException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchException.java similarity index 94% rename from lib/server-core/src/main/java/org/apache/olingo/server/core/batch/BatchException.java rename to lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchException.java index aafe1413a..8da47a8fb 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/BatchException.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchException.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.core.batch; +package org.apache.olingo.server.api.batch; import org.apache.olingo.server.api.ODataTranslatedException; @@ -40,7 +40,7 @@ public class BatchException extends ODataTranslatedException { MISSING_CONTENT_ID, MISSING_CONTENT_TRANSFER_ENCODING, MISSING_CONTENT_TYPE, - MISSING_MANDATORY_HEADER, FORBIDDEN_HEADER; + MISSING_MANDATORY_HEADER, FORBIDDEN_HEADER, INVALID_CONTENT_ID; @Override public String getKey() { diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchOperation.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchOperation.java new file mode 100644 index 000000000..8e438cfa3 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/BatchOperation.java @@ -0,0 +1,36 @@ +/* + * 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.batch; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; + +public interface BatchOperation { + public List parseBatchRequest(InputStream in) throws BatchException; + + public ODataResponse handleODataRequest(ODataRequest request); + + public ODataResponsePart handleBatchRequest(BatchRequestPart request); + + public void writeResponseParts(List batchResponses, ODataResponse response) throws BatchException, + IOException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/BatchProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/BatchProcessor.java new file mode 100644 index 000000000..5a9518d94 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/BatchProcessor.java @@ -0,0 +1,31 @@ +/* + * 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 java.util.List; + +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchOperation; + +public interface BatchProcessor extends Processor { + void executeBatch(BatchOperation operation, ODataRequest requst, ODataResponse response); + + List executeChangeSet(BatchOperation operation, List requests); +} 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 a13ef6fd5..48d75ded4 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 @@ -35,6 +35,8 @@ 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.ServiceMetadata; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.api.processor.DefaultProcessor; import org.apache.olingo.server.api.processor.EntitySetProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; @@ -52,6 +54,7 @@ import org.apache.olingo.server.api.uri.UriResourceKind; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.api.uri.UriResourceProperty; +import org.apache.olingo.server.core.batch.handler.BatchHandler; 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.parser.UriParserSemanticException; @@ -115,7 +118,7 @@ public class ODataHandler { private void processInternal(final ODataRequest request, final ODataResponse response) throws ODataHandlerException, UriParserException, UriValidationException, ContentNegotiatorException, - ODataApplicationException, SerializerException { + ODataApplicationException, SerializerException, BatchException { validateODataVersion(request, response); uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null, @@ -157,6 +160,13 @@ public class ODataHandler { break; case resource: handleResourceDispatching(request, response); + break; + case batch: + BatchProcessor bp = selectProcessor(BatchProcessor.class); + + final BatchHandler handler = new BatchHandler(this, request, bp, true); + handler.process(response); + break; default: throw new ODataHandlerException("not implemented", diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchChangeSetSorter.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchChangeSetSorter.java new file mode 100644 index 000000000..c348512a0 --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchChangeSetSorter.java @@ -0,0 +1,145 @@ +/* + * 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.batch.handler; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; +import org.apache.olingo.server.core.batch.parser.BatchParserCommon; + +public class BatchChangeSetSorter { + private static final String REG_EX_REFERENCE = "\\$(.*)(/.*)?"; + + final List orderdList = new ArrayList(); + + private static Pattern referencePattern = Pattern.compile(REG_EX_REFERENCE); + private Set knownContentId = new HashSet(); + private Map> requestContentIdMapping = new HashMap>(); + + public BatchChangeSetSorter(List requests) throws BatchException { + sort(requests); + } + + public List getOrderdRequests() { + return orderdList; + } + + private List sort(final List requests) throws BatchException { + extractUrlContentId(requests); + orderdList.addAll(getRequestsWithoutReferences()); + + boolean areRequestsProcessed = true; + while (requestsToProcessAvailable() && areRequestsProcessed) { + areRequestsProcessed = processRemainingRequests(orderdList); + } + + if (requestsToProcessAvailable()) { + throw new BatchException("Invalid content id", MessageKeys.INVALID_CONTENT_ID, 0); + } + + return orderdList; + } + + private boolean requestsToProcessAvailable() { + return requestContentIdMapping.keySet().size() != 0; + } + + private boolean processRemainingRequests(List orderdList) { + final List addedRequests = getRemainingRequestsWithKownContentId(); + addRequestsToKnownContentIds(addedRequests); + orderdList.addAll(addedRequests); + + return addedRequests.size() != 0; + } + + private List getRemainingRequestsWithKownContentId() { + List result = new ArrayList(); + + for (String contextId : knownContentId) { + List processedRequests = requestContentIdMapping.get(contextId); + if (processedRequests != null && processedRequests.size() != 0) { + result.addAll(processedRequests); + requestContentIdMapping.remove(contextId); + } + } + + return result; + } + + private List getRequestsWithoutReferences() { + final List requestsWithoutReference = requestContentIdMapping.get(null); + requestContentIdMapping.remove(null); + + addRequestsToKnownContentIds(requestsWithoutReference); + return requestsWithoutReference; + } + + private void addRequestsToKnownContentIds(List requestsWithoutReference) { + for (ODataRequest request : requestsWithoutReference) { + final String contentId = getContentIdFromHeader(request); + if (contentId != null) { + knownContentId.add(contentId); + } + } + } + + private String getContentIdFromHeader(ODataRequest request) { + return request.getHeader(BatchParserCommon.HTTP_CONTENT_ID); + } + + private void extractUrlContentId(List requests) { + for (ODataRequest request : requests) { + final String reference = getReferenceInURI(request); + addRequestToMapping(reference, request); + } + } + + private void addRequestToMapping(final String reference, final ODataRequest request) { + List requestList = requestContentIdMapping.get(reference); + requestList = (requestList == null) ? new ArrayList() : requestList; + + requestList.add(request); + requestContentIdMapping.put(reference, requestList); + } + + public static String getReferenceInURI(ODataRequest request) { + Matcher matcher = referencePattern.matcher(removeFollingPathSegments(request.getRawODataPath())); + return (matcher.matches()) ? matcher.group(1) : null; + } + + private static String removeFollingPathSegments(String rawODataPath) { + final int indexOfSlash = rawODataPath.indexOf("/"); + return (indexOfSlash != -1) ? rawODataPath.substring(0, indexOfSlash) : rawODataPath; + } + + public static void replaceContentIdReference(ODataRequest request, String contentId, String resourceUri) { + final String newUri = request.getRawODataPath().replace("$" + contentId, resourceUri); + request.setRawODataPath(newUri); + request.setRawRequestUri(request.getRawBaseUri() + "/" + newUri); + } +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchHandler.java new file mode 100644 index 000000000..01a149e6e --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchHandler.java @@ -0,0 +1,68 @@ +/* + * 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.batch.handler; + +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpMethod; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchOperation; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; +import org.apache.olingo.server.api.processor.BatchProcessor; +import org.apache.olingo.server.core.ODataHandler; +import org.apache.olingo.server.core.batch.parser.BatchParserCommon; + +public class BatchHandler { + private final BatchOperation operation; + private final BatchProcessor batchProcessor; + private ODataRequest request; + + public BatchHandler(final ODataHandler oDataHandler, final ODataRequest request, final BatchProcessor batchProcessor, + final boolean isStrict) { + + this.request = request; + this.batchProcessor = batchProcessor; + operation = new BatchOperationImpl(oDataHandler, request, batchProcessor, isStrict); + } + + public void process(ODataResponse response) throws BatchException { + validateRequest(); + batchProcessor.executeBatch(operation, request, response); + } + + private void validateRequest() throws BatchException { + validateHttpMethod(); + validateContentType(); + } + + private void validateContentType() throws BatchException { + final String contentType = request.getHeader(HttpHeader.CONTENT_TYPE); + + if(contentType == null || !BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches()) { + throw new BatchException("Invalid content type", MessageKeys.INVALID_CONTENT_TYPE, 0); + } + } + + private void validateHttpMethod() throws BatchException { + if(request.getMethod() != HttpMethod.POST) { + throw new BatchException("Invalid HTTP method", MessageKeys.INVALID_METHOD, 0); + } + } +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchOperationImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchOperationImpl.java new file mode 100644 index 000000000..bc148f00b --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchOperationImpl.java @@ -0,0 +1,74 @@ +/* + * 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.batch.handler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchOperation; +import org.apache.olingo.server.api.batch.BatchRequestPart; +import org.apache.olingo.server.api.batch.ODataResponsePart; +import org.apache.olingo.server.api.processor.BatchProcessor; +import org.apache.olingo.server.core.ODataHandler; +import org.apache.olingo.server.core.batch.parser.BatchParser; +import org.apache.olingo.server.core.batch.writer.BatchResponseWriter; + +public class BatchOperationImpl implements BatchOperation { + private final BatchPartHandler partHandler; + private final BatchResponseWriter writer; + private final BatchParser parser; + + public BatchOperationImpl(ODataHandler oDataHandler, ODataRequest request, BatchProcessor batchProcessor, + final boolean isStrict) { + partHandler = new BatchPartHandler(oDataHandler, batchProcessor, this); + writer = new BatchResponseWriter(); + parser = new BatchParser(getContentType(request), request.getRawBaseUri(), + request.getRawServiceResolutionUri(), isStrict); + } + + @Override + public List parseBatchRequest(InputStream in) throws BatchException { + return parser.parseBatchRequest(in); + } + + @Override + public ODataResponse handleODataRequest(ODataRequest request) { + return partHandler.handleODataRequest(request); + } + + @Override + public ODataResponsePart handleBatchRequest(BatchRequestPart request) { + return partHandler.handleBatchRequest(request); + } + + @Override + public void writeResponseParts(List batchResponses, ODataResponse response) throws BatchException, + IOException { + writer.toODataResponse(batchResponses, response); + } + + private String getContentType(ODataRequest request) { + return request.getHeader(HttpHeader.CONTENT_TYPE); + } +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchPartHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchPartHandler.java new file mode 100644 index 000000000..a78d5859d --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/BatchPartHandler.java @@ -0,0 +1,66 @@ +/* + * 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.batch.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchOperation; +import org.apache.olingo.server.api.batch.BatchRequestPart; +import org.apache.olingo.server.api.batch.ODataResponsePart; +import org.apache.olingo.server.api.processor.BatchProcessor; +import org.apache.olingo.server.core.ODataHandler; +import org.apache.olingo.server.core.batch.parser.BatchParserCommon; + +public class BatchPartHandler { + + private ODataHandler oDataHandler; + private BatchProcessor batchProcessor; + private BatchOperation batchOperation; + + public BatchPartHandler(final ODataHandler oDataHandler, final BatchProcessor processor, + final BatchOperation batchOperation) { + this.oDataHandler = oDataHandler; + this.batchProcessor = processor; + this.batchOperation = batchOperation; + } + + public ODataResponse handleODataRequest(ODataRequest request) { + final ODataResponse response = oDataHandler.process(request); + response.setHeader(BatchParserCommon.HTTP_CONTENT_ID, request.getHeader(BatchParserCommon.HTTP_CONTENT_ID)); + + return response; + } + + public ODataResponsePart handleBatchRequest(BatchRequestPart request) { + final List responses = new ArrayList(); + + if (request.isChangeSet()) { + responses.addAll(batchProcessor.executeChangeSet(batchOperation, request.getRequests())); + return new ODataResponsePartImpl(responses, true); + } else { + responses.add(handleODataRequest(request.getRequests().get(0))); + return new ODataResponsePartImpl(responses, false); + } + } + +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/ODataResponsePartImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/ODataResponsePartImpl.java new file mode 100644 index 000000000..da52a372f --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/handler/ODataResponsePartImpl.java @@ -0,0 +1,44 @@ +/* + * 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.batch.handler; + +import java.util.List; + +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.ODataResponsePart; + +public class ODataResponsePartImpl implements ODataResponsePart { + private List responses; + private boolean isChangeSet; + + public ODataResponsePartImpl(List responses, boolean isChangeSet) { + this.responses = responses; + this.isChangeSet = isChangeSet; + } + + @Override + public List getResponses() { + return responses; + } + + @Override + public boolean isChangeSet() { + return isChangeSet; + } +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchBodyPart.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchBodyPart.java index c2d2e0fde..2b937830e 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchBodyPart.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchBodyPart.java @@ -22,7 +22,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.olingo.commons.api.http.HttpHeader; -import org.apache.olingo.server.core.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; public class BatchBodyPart implements BatchPart { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchChangeSetPart.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchChangeSetPart.java index 1d0bd6f79..aaa266048 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchChangeSetPart.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchChangeSetPart.java @@ -20,7 +20,7 @@ package org.apache.olingo.server.core.batch.parser; import java.util.List; -import org.apache.olingo.server.core.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; public class BatchChangeSetPart extends BatchQueryOperation { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParser.java index 37b1a9cde..75c008477 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParser.java @@ -25,9 +25,9 @@ import java.util.LinkedList; import java.util.List; import org.apache.olingo.commons.api.ODataRuntimeException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.BatchParserResult; import org.apache.olingo.server.api.batch.BatchRequestPart; -import org.apache.olingo.server.core.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; import org.apache.olingo.server.core.batch.transformator.BatchRequestTransformator; diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParserCommon.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParserCommon.java index e2dc5e520..43a09b683 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParserCommon.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchParserCommon.java @@ -29,7 +29,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.olingo.commons.api.http.HttpContentType; -import org.apache.olingo.server.core.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; public class BatchParserCommon { @@ -186,7 +186,8 @@ public class BatchParserCommon { } public static void consumeBlankLine(final List remainingMessage, final boolean isStrict) throws BatchException { - if (remainingMessage.size() > 0 && remainingMessage.get(0).toString().matches("\\s*\r\n\\s*")) { + //TODO is \r\n to strict? + if (remainingMessage.size() > 0 && remainingMessage.get(0).toString().matches("\\s*(\r\n|\n)\\s*")) { remainingMessage.remove(0); } else { if (isStrict) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchQueryOperation.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchQueryOperation.java index 5ff7faf96..6a5309ebf 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchQueryOperation.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/parser/BatchQueryOperation.java @@ -20,7 +20,7 @@ package org.apache.olingo.server.core.batch.parser; import java.util.List; -import org.apache.olingo.server.core.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; public class BatchQueryOperation implements BatchPart { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchRequestTransformator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchRequestTransformator.java index 02c811897..94d522616 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchRequestTransformator.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchRequestTransformator.java @@ -27,9 +27,9 @@ import java.util.List; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.BatchParserResult; -import org.apache.olingo.server.core.batch.BatchException; -import org.apache.olingo.server.core.batch.BatchException.MessageKeys; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; import org.apache.olingo.server.core.batch.parser.BatchBodyPart; import org.apache.olingo.server.core.batch.parser.BatchChangeSetPart; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; @@ -84,10 +84,10 @@ public class BatchRequestTransformator implements BatchTransformator { final HeaderField contentIdRequest = getContentId(request); if (contentIdChangeRequestPart == null && contentIdRequest == null) { - throw new BatchException("Missing content type", MessageKeys.MISSING_CONTENT_ID, changeRequestPart.getHeaders() + throw new BatchException("Missing content id", MessageKeys.MISSING_CONTENT_ID, changeRequestPart.getHeaders() .getLineNumber()); } else if (contentIdChangeRequestPart != null) { - request.getHeaders().replaceHeaderField(contentIdChangeRequestPart); + request.getHeaders().replaceHeaderField(contentIdChangeRequestPart); } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformator.java index becb6c765..286c0cc34 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformator.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformator.java @@ -20,8 +20,8 @@ package org.apache.olingo.server.core.batch.transformator; import java.util.List; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.BatchParserResult; -import org.apache.olingo.server.core.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BatchBodyPart; public interface BatchTransformator { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformatorCommon.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformatorCommon.java index a351cca7c..c9da563ef 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformatorCommon.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/transformator/BatchTransformatorCommon.java @@ -28,8 +28,8 @@ import java.util.regex.Pattern; 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.server.core.batch.BatchException; -import org.apache.olingo.server.core.batch.BatchException.MessageKeys; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; import org.apache.olingo.server.core.batch.parser.Header; diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriter.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriter.java index a0637477e..812ea8b0d 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriter.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriter.java @@ -31,9 +31,9 @@ import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.ODataResponsePart; -import org.apache.olingo.server.core.batch.BatchException; -import org.apache.olingo.server.core.batch.BatchException.MessageKeys; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/BatchRequestParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/BatchRequestParserTest.java index 1d68307a4..c9778e385 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/BatchRequestParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/BatchRequestParserTest.java @@ -33,8 +33,9 @@ import java.util.List; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.BatchRequestPart; -import org.apache.olingo.server.core.batch.BatchException.MessageKeys; +import org.apache.olingo.server.api.batch.BatchException.MessageKeys; import org.apache.olingo.server.core.batch.parser.BatchParser; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; import org.junit.Test; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java index 6fb079670..e3a1acceb 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java @@ -24,7 +24,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.olingo.commons.api.http.HttpHeader; -import org.apache.olingo.server.core.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line; import org.apache.olingo.server.core.batch.parser.Header; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java index ec45a22ba..b7169b9c2 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java @@ -30,8 +30,8 @@ import java.util.List; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.batch.BatchException; import org.apache.olingo.server.api.batch.ODataResponsePart; -import org.apache.olingo.server.core.batch.BatchException; import org.apache.olingo.server.core.batch.StringUtil; import org.apache.olingo.server.core.batch.parser.BatchParserCommon; import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings; 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 d88a02f91..b59c92edf 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 @@ -19,11 +19,14 @@ package org.apache.olingo.server.tecsvc.processor; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Locale; +import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.data.Entity; @@ -46,6 +49,11 @@ 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.ServiceMetadata; +import org.apache.olingo.server.api.batch.BatchException; +import org.apache.olingo.server.api.batch.BatchOperation; +import org.apache.olingo.server.api.batch.BatchRequestPart; +import org.apache.olingo.server.api.batch.ODataResponsePart; +import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.processor.EntitySetProcessor; import org.apache.olingo.server.api.processor.PropertyProcessor; @@ -66,7 +74,7 @@ import org.apache.olingo.server.tecsvc.data.DataProvider; /** * Technical Processor which provides currently implemented processor functionality. */ -public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor { +public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor, BatchProcessor { private OData odata; private DataProvider dataProvider; @@ -326,4 +334,33 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, } } } + + @Override + public void executeBatch(BatchOperation operation, ODataRequest requst, ODataResponse response) { + try { + final List parts = operation.parseBatchRequest(requst.getBody()); + final List responseParts = new ArrayList(); + + for(BatchRequestPart part : parts) { + responseParts.add(operation.handleBatchRequest(part)); + } + + operation.writeResponseParts(responseParts, response); + } catch (BatchException e) { + throw new ODataRuntimeException(e); + } catch (IOException e) { + throw new ODataRuntimeException(e); + } + } + + @Override + public List executeChangeSet(BatchOperation operation, List requests) { + List responses = new ArrayList(); + + for(ODataRequest request : requests) { + responses.add(operation.handleODataRequest(request)); + } + + return responses; + } }