You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by jh...@apache.org on 2013/08/23 16:29:05 UTC
[4/4] git commit: Batch Support, Validation in Deserialization
Batch Support, Validation in Deserialization
Change-Id: Ic263de081d06b71d395804b75a36c6e4b525d386
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/commit/45c27419
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/45c27419
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/45c27419
Branch: refs/heads/master
Commit: 45c27419cfcf1024d8e57100e7408276a932598c
Parents: a133661
Author: Jens Huesken <jh...@apache.org>
Authored: Fri Aug 23 16:27:58 2013 +0200
Committer: Jens Huesken <jh...@apache.org>
Committed: Fri Aug 23 16:27:58 2013 +0200
----------------------------------------------------------------------
.../olingo/odata2/api/batch/BatchException.java | 8 +-
.../olingo/odata2/api/batch/BatchHandler.java | 6 +-
.../olingo/odata2/api/batch/BatchPart.java | 43 --
.../odata2/api/batch/BatchRequestPart.java | 42 ++
.../odata2/api/client/batch/BatchChangeSet.java | 61 +++
.../api/client/batch/BatchChangeSetPart.java | 110 +++++
.../odata2/api/client/batch/BatchPart.java | 27 ++
.../odata2/api/client/batch/BatchQueryPart.java | 97 +++++
.../api/client/batch/BatchSingleResponse.java | 65 +++
.../olingo/odata2/api/ep/EntityProvider.java | 74 +++-
.../api/ep/EntityProviderReadProperties.java | 29 +-
.../olingo/odata2/api/rt/RuntimeDelegate.java | 21 +
.../odata2/core/batch/BatchChangeSetImpl.java | 49 +++
.../core/batch/BatchChangeSetPartImpl.java | 116 +++++
.../odata2/core/batch/BatchConstants.java | 36 --
.../odata2/core/batch/BatchHandlerImpl.java | 20 +-
.../olingo/odata2/core/batch/BatchHelper.java | 51 +++
.../olingo/odata2/core/batch/BatchPartImpl.java | 58 ---
.../odata2/core/batch/BatchQueryPartImpl.java | 102 +++++
.../odata2/core/batch/BatchRequestParser.java | 294 +++++++------
.../odata2/core/batch/BatchRequestPartImpl.java | 58 +++
.../odata2/core/batch/BatchRequestWriter.java | 120 ++++++
.../odata2/core/batch/BatchResponseParser.java | 354 +++++++++++++++
.../odata2/core/batch/BatchResponseWriter.java | 80 ++--
.../core/batch/BatchSingleResponseImpl.java | 90 ++++
.../olingo/odata2/core/commons/Encoder.java | 1 -
.../olingo/odata2/core/edm/EdmBinary.java | 2 +-
.../olingo/odata2/core/edm/EdmDateTime.java | 2 +-
.../apache/olingo/odata2/core/edm/EdmTime.java | 15 +-
.../odata2/core/edm/parser/EdmParser.java | 11 +-
.../odata2/core/ep/JsonEntityProvider.java | 9 +-
.../odata2/core/ep/ProviderFacadeImpl.java | 22 +-
.../core/ep/aggregator/EntityPropertyInfo.java | 20 +-
.../core/ep/consumer/JsonEntityConsumer.java | 4 +-
.../core/ep/consumer/JsonEntryConsumer.java | 4 +-
.../core/ep/consumer/JsonPropertyConsumer.java | 3 +
.../core/ep/consumer/XmlEntityConsumer.java | 6 +-
.../core/ep/consumer/XmlEntryConsumer.java | 35 +-
.../core/ep/consumer/XmlPropertyConsumer.java | 65 ++-
.../processor/ODataSingleProcessorService.java | 3 +-
.../odata2/core/rt/RuntimeDelegateImpl.java | 25 ++
odata-core/src/main/resources/i18n.properties | 4 +-
.../core/batch/BatchRequestParserTest.java | 427 ++++++++++---------
.../core/batch/BatchRequestWriterTest.java | 236 ++++++++++
.../core/batch/BatchResponseParserTest.java | 280 ++++++++++++
.../core/batch/BatchResponseWriterTest.java | 4 +-
.../odata2/core/edm/parser/EdmParserTest.java | 11 +-
.../core/ep/AbstractXmlProducerTestHelper.java | 3 +
.../core/ep/consumer/JsonEntryConsumerTest.java | 46 +-
.../ep/consumer/JsonPropertyConsumerTest.java | 152 ++++---
.../core/ep/consumer/XmlEntityConsumerTest.java | 123 +++---
.../core/ep/consumer/XmlLinkConsumerTest.java | 7 +
.../ep/consumer/XmlPropertyConsumerTest.java | 181 +++++---
.../ODataSingleProcessorServiceTest.java | 2 +-
.../uri/expression/TestAbapCompatibility.java | 3 +-
.../uri/expression/TestParserExceptions.java | 10 +-
.../src/test/resources/batchResponse.batch | 39 ++
.../olingo/odata2/fit/basic/BasicBatchTest.java | 9 +-
.../odata2/fit/client/ClientBatchTest.java | 235 ++++++++++
.../apache/olingo/odata2/fit/ref/BatchTest.java | 2 +-
.../odata2/fit/ref/EntryJsonChangeTest.java | 29 +-
.../fit/ref/EntryJsonCreateInlineTest.java | 2 +
.../odata2/fit/ref/EntryXmlChangeTest.java | 53 ++-
.../odata2/ref/edm/ScenarioEdmProvider.java | 2 +-
.../odata2/ref/processor/ListsProcessor.java | 29 +-
.../odata2/testutil/helper/StringHelper.java | 11 +-
.../olingo/odata2/testutil/mock/EdmMock.java | 1 +
.../olingo/odata2/testutil/mock/TecEdmInfo.java | 5 +-
.../mock/TechnicalScenarioEdmProvider.java | 47 +-
69 files changed, 3295 insertions(+), 896 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
index bbed22b..f5582d6 100644
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
@@ -49,7 +49,7 @@ public class BatchException extends ODataMessageException {
/** INVALID_QUERY_PARAMETER requires no content value */
public static final MessageReference INVALID_QUERY_PARAMETER = createMessageReference(BatchException.class, "INVALID_QUERY_PARAMETER");
- /** INVALID_URI requires no content value */
+ /** INVALID_URI requires 1 content value('line number') */
public static final MessageReference INVALID_URI = createMessageReference(BatchException.class, "INVALID_URI");
/** INVALID_BOUNDARY requires 1 content value('line number') */
@@ -91,9 +91,15 @@ public class BatchException extends ODataMessageException {
/** INVALID_REQUEST_LINE requires 2 content value ('request line', 'line number') */
public static final MessageReference INVALID_REQUEST_LINE = createMessageReference(BatchException.class, "INVALID_REQUEST_LINE");
+ /** INVALID_STATUS_LINE requires 2 content value ('status line', 'line number') */
+ public static final MessageReference INVALID_STATUS_LINE = createMessageReference(BatchException.class, "INVALID_STATUS_LINE");
+
/** TRUNCETED_BODY requires 1 content value ('line number') */
public static final MessageReference TRUNCATED_BODY = createMessageReference(BatchException.class, "TRUNCATED_BODY");
+ /** UNSUPPORTED_ABSOLUTE_PATH requires 1 content value ('line number') */
+ public static final MessageReference UNSUPPORTED_ABSOLUTE_PATH = createMessageReference(BatchException.class, "UNSUPPORTED_ABSOLUTE_PATH");
+
public BatchException(final MessageReference messageReference) {
super(messageReference);
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
index 23584f3..1748e3e 100644
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
@@ -27,12 +27,12 @@ import org.apache.olingo.odata2.api.processor.ODataResponse;
*/
public interface BatchHandler {
/**
- * <p>Handles the {@link BatchPart} in a way that it results in a corresponding {@link BatchResponsePart}.</p>
- * @param batchPart the incoming batchPart
+ * <p>Handles the {@link BatchRequestPart} in a way that it results in a corresponding {@link BatchResponsePart}.</p>
+ * @param batchRequestPart the incoming MIME part
* @return the corresponding result
* @throws ODataException
*/
- public BatchResponsePart handleBatchPart(BatchPart batchPart) throws ODataException;
+ public BatchResponsePart handleBatchPart(BatchRequestPart batchRequestPart) throws ODataException;
/**
* <p>Delegates a handling of the request {@link ODataRequest} to the request handler and provides ODataResponse {@link ODataResponse}.</p>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
deleted file mode 100644
index b7d8539..0000000
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.api.batch;
-
-import java.util.List;
-
-import org.apache.olingo.odata2.api.processor.ODataRequest;
-
-/**
- * A BatchPart
- * <p> BatchPart represents a distinct MIME part of a Batch Request body. It can be ChangeSet or Query Operation
- *
- */
-public interface BatchPart {
-
- /**
- * Get the info if a BatchPart is a ChangeSet
- * @return true or false
- */
- public boolean isChangeSet();
-
- /**
- * Get requests. If a BatchPart is a Query Operation, the list contains one request.
- * @return a list of {@link ODataRequest}
- */
- public List<ODataRequest> getRequests();
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchRequestPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchRequestPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchRequestPart.java
new file mode 100644
index 0000000..a12f774
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchRequestPart.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.odata2.api.batch;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+
+/**
+ * A BatchPart
+ * <p> BatchPart represents a distinct MIME part of a Batch Request body. It can be ChangeSet or Query Operation
+ */
+public interface BatchRequestPart {
+
+ /**
+ * Get the info if a BatchPart is a ChangeSet
+ * @return true or false
+ */
+ public boolean isChangeSet();
+
+ /**
+ * Get requests. If a BatchPart is a Query Operation, the list contains one request.
+ * @return a list of {@link ODataRequest}
+ */
+ public List<ODataRequest> getRequests();
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSet.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSet.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSet.java
new file mode 100644
index 0000000..13f7df0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSet.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.odata2.api.client.batch;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * A BatchChangeSet
+ * <p> BatchChangeSet represents a Change Set, that consists of change requests
+ */
+public abstract class BatchChangeSet implements BatchPart {
+
+ /**
+ * Add a new change request to the ChangeSet
+ * @param BatchChangeSetPart {@link BatchChangeSetPart}
+ */
+ public abstract void add(BatchChangeSetPart request);
+
+ /**
+ * Get change requests
+ * @return a list of {@link BatchChangeSetPart}
+ */
+ public abstract List<BatchChangeSetPart> getChangeSetParts();
+
+ /**
+ * Get new builder instance
+ * @return {@link BatchChangeSetBuilder}
+ */
+ public static BatchChangeSetBuilder newBuilder() {
+ return BatchChangeSetBuilder.newInstance();
+ }
+
+ public static abstract class BatchChangeSetBuilder {
+
+ protected BatchChangeSetBuilder() {}
+
+ private static BatchChangeSetBuilder newInstance() {
+ return RuntimeDelegate.createBatchChangeSetBuilder();
+ }
+
+ public abstract BatchChangeSet build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSetPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSetPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSetPart.java
new file mode 100644
index 0000000..ba59edc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchChangeSetPart.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * 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.odata2.api.client.batch;
+
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * A BatchChangeSetPart
+ * <p> BatchChangeSetPart represents a change request within a Change Set
+ */
+public abstract class BatchChangeSetPart {
+
+ public abstract Map<String, String> getHeaders();
+
+ public abstract String getBody();
+
+ public abstract String getUri();
+
+ public abstract String getMethod();
+
+ public abstract String getContentId();
+
+ /**
+ * @param headers
+ * @return a new builder object
+ */
+ public static BatchChangeSetPartBuilder headers(final Map<String, String> headers) {
+ return newBuilder().headers(headers);
+ }
+
+ /**
+ * @param body a change request body
+ * @return a new builder object
+ */
+ public static BatchChangeSetPartBuilder body(final String body) {
+ return newBuilder().body(body);
+ }
+
+ /**
+ * @param uri should not be null
+ * @return a new builder object
+ */
+ public static BatchChangeSetPartBuilder uri(final String uri) {
+ return newBuilder().uri(uri);
+ }
+
+ /**
+ * @param method MUST be the PUT, POST, MERGE, DELETE or PATCH method
+ * @return a new builder object
+ */
+ public static BatchChangeSetPartBuilder method(final String method) {
+ return newBuilder().method(method);
+ }
+
+ /**
+ * @param contentId can be used to identify the different request within a the batch
+ * @return a new builder object
+ */
+ public static BatchChangeSetPartBuilder contentId(final String contentId) {
+ return newBuilder().contentId(contentId);
+ }
+
+ /**
+ * @return returns a new builder object
+ */
+ public static BatchChangeSetPartBuilder newBuilder() {
+ return BatchChangeSetPartBuilder.newInstance();
+ }
+
+ public static abstract class BatchChangeSetPartBuilder {
+
+ protected BatchChangeSetPartBuilder() {}
+
+ private static BatchChangeSetPartBuilder newInstance() {
+ return RuntimeDelegate.createBatchChangeSetPartBuilder();
+ }
+
+ public abstract BatchChangeSetPart build();
+
+ public abstract BatchChangeSetPartBuilder headers(Map<String, String> headers);
+
+ public abstract BatchChangeSetPartBuilder body(String body);
+
+ public abstract BatchChangeSetPartBuilder uri(String uri);
+
+ public abstract BatchChangeSetPartBuilder method(String method);
+
+ public abstract BatchChangeSetPartBuilder contentId(String contentId);
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchPart.java
new file mode 100644
index 0000000..6c6c7f0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchPart.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.odata2.api.client.batch;
+
+/**
+ * A BatchPartRequest
+ * <p> BatchPartRequest represents a distinct part of a Batch Request body. It can be a ChangeSet or Query Operation.
+ */
+public interface BatchPart {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchQueryPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchQueryPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchQueryPart.java
new file mode 100644
index 0000000..42bd28d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchQueryPart.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.odata2.api.client.batch;
+
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * A BatchQueryPart
+ * <p>BatchQueryPart represents a single retrieve request
+ */
+public abstract class BatchQueryPart implements BatchPart {
+
+ public abstract Map<String, String> getHeaders();
+
+ public abstract String getUri();
+
+ public abstract String getMethod();
+
+ public abstract String getContentId();
+
+ /**
+ * @param headers
+ * @return a new builder object
+ */
+ public static BatchQueryPartBuilder headers(final Map<String, String> headers) {
+ return newBuilder().headers(headers);
+ }
+
+ /**
+ * @param uri should not be null
+ * @return a new builder object
+ */
+ public static BatchQueryPartBuilder uri(final String uri) {
+ return newBuilder().uri(uri);
+ }
+
+ /**
+ * @param method MUST be the HTTP GET method
+ * @return a new builder object
+ */
+ public static BatchQueryPartBuilder method(final String method) {
+ return newBuilder().method(method);
+ }
+
+ /**
+ * @param contentId can be used to identify the different request within a the batch
+ * @return a new builder object
+ */
+ public static BatchQueryPartBuilder contentId(final String contentId) {
+ return newBuilder().contentId(contentId);
+ }
+
+ /**
+ * @return returns a new builder object
+ */
+ public static BatchQueryPartBuilder newBuilder() {
+ return BatchQueryPartBuilder.newInstance();
+ }
+
+ public static abstract class BatchQueryPartBuilder {
+
+ protected BatchQueryPartBuilder() {}
+
+ private static BatchQueryPartBuilder newInstance() {
+ return RuntimeDelegate.createBatchQueryPartBuilder();
+ }
+
+ public abstract BatchQueryPart build();
+
+ public abstract BatchQueryPartBuilder headers(Map<String, String> headers);
+
+ public abstract BatchQueryPartBuilder uri(String uri);
+
+ public abstract BatchQueryPartBuilder method(String method);
+
+ public abstract BatchQueryPartBuilder contentId(String contentId);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchSingleResponse.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchSingleResponse.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchSingleResponse.java
new file mode 100644
index 0000000..4d99c7d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/client/batch/BatchSingleResponse.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.odata2.api.client.batch;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+* A BatchSingleResponse
+* <p> BatchSingleResponse represents a single response of a Batch Response body. It can be a response to a change request of ChangeSet or a response to a retrieve request
+*/
+public interface BatchSingleResponse {
+ /**
+ * @return a result code of the attempt to understand and satisfy the request
+ */
+ public String getStatusCode();
+
+ /**
+ * @return a short textual description of the status code
+ */
+ public String getStatusInfo();
+
+ /**
+ * @return a value of the Content-Id header
+ */
+ public String getContentId();
+
+ /**
+ * @return a body part of a response message
+ */
+ public String getBody();
+
+ /**
+ * @return all available headers
+ */
+ public Map<String, String> getHeaders();
+
+ /**
+ * @param name HTTP response header name
+ * @return a header value or null if not set
+ */
+ public String getHeader(final String name);
+
+ /**
+ * @return a set of all available header names
+ */
+ public Set<String> getHeaderNames();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
index 97cc26a..cb876aa 100644
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
@@ -23,8 +23,10 @@ import java.util.List;
import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchRequestPart;
import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
@@ -220,13 +222,18 @@ public final class EntityProvider {
ODataFeed readFeed(String contentType, EdmEntitySet entitySet, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
/**
- * Read (de-serialize) data from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
- * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide this data as {@link ODataEntry}.
- *
- * @param contentType format of content in the given input stream.
- * @param entitySet entity data model for entity set to be read
- * @param content data in form of an {@link InputStream} which contains the data in specified format
- * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}.
+ * Reads (de-serializes) data from <code>content</code> (as {@link InputStream})
+ * in specified format (given as <code>contentType</code>) based on
+ * <code>entity data model</code> (given as {@link EdmEntitySet})
+ * and provides this data as {@link ODataEntry}.
+ * Does not return complete entry data but only data present in the
+ * de-serialized content.
+ * @param contentType format of content in the given input stream
+ * @param entitySet entity data model for entity set to be read
+ * @param content data in form of an {@link InputStream} which
+ * contains the data in specified format
+ * @param properties additional properties necessary for reading
+ * content from {@link InputStream} into {@link Map}.
* @return entry as {@link ODataEntry}
* @throws EntityProviderException if reading of data (de-serialization) fails
*/
@@ -331,7 +338,7 @@ public final class EntityProvider {
* @return list of {@link BatchPart}
* @throws BatchException if parsing fails
*/
- List<BatchPart> parseBatchRequest(String contentType, InputStream content, EntityProviderBatchProperties properties) throws BatchException;
+ List<BatchRequestPart> parseBatchRequest(String contentType, InputStream content, EntityProviderBatchProperties properties) throws BatchException;
/**
* Write responses of Batch Response Parts in Batch Response as {@link ODataResponse}.
@@ -342,6 +349,26 @@ public final class EntityProvider {
* @throws BatchException
*/
ODataResponse writeBatchResponse(List<BatchResponsePart> batchResponseParts) throws BatchException;
+
+ /**
+ * Create Batch Request body as InputStream.
+ *
+ * @param batchParts a list of BatchPartRequests {@link BatchPart}
+ * @param boundary
+ * @return Batch Request as InputStream
+ */
+ InputStream writeBatchRequest(List<BatchPart> batchParts, String boundary);
+
+ /**
+ * Parse Batch Response body (as {@link InputStream}) and provide a list of single responses as {@link BatchSingleResponse}
+ *
+ * @param content response body
+ * @param contentType format of content in the given input stream (incl. boundary parameter)
+ * @return list of {@link BatchSingleResponse}
+ * @throws BatchException
+ */
+ List<BatchSingleResponse> parseBatchResponse(String contentType, InputStream content) throws BatchException;
+
}
/**
@@ -671,15 +698,15 @@ public final class EntityProvider {
}
/**
- * Parse Batch Request body <code>inputStream</code> (as {@link InputStream}) and provide a list of Batch Parts as {@link BatchPart}
+ * Parse Batch Request body <code>inputStream</code> (as {@link InputStream}) and provide a list of Batch Request parts as {@link BatchRequestPart}
*
* @param contentType format of content in the given input stream
* @param content request body
* @param properties additional properties necessary for parsing. Must not be null.
- * @return list of {@link BatchPart}
+ * @return list of {@link BatchRequestPart}
* @throws BatchException if parsing fails
*/
- public static List<BatchPart> parseBatchRequest(final String contentType, final InputStream content, final EntityProviderBatchProperties properties) throws BatchException {
+ public static List<BatchRequestPart> parseBatchRequest(final String contentType, final InputStream content, final EntityProviderBatchProperties properties) throws BatchException {
return createEntityProvider().parseBatchRequest(contentType, content, properties);
}
@@ -695,4 +722,27 @@ public final class EntityProvider {
return createEntityProvider().writeBatchResponse(batchResponseParts);
}
+ /**
+ * Create Batch Request body as InputStream.
+ *
+ * @param batchParts a list of BatchPartRequests {@link BatchPart}
+ * @param boundary
+ * @return Batch Request as InputStream
+ */
+ public static InputStream writeBatchRequest(final List<BatchPart> batchParts, final String boundary) {
+ return createEntityProvider().writeBatchRequest(batchParts, boundary);
+ }
+
+ /**
+ * Parse Batch Response body (as {@link InputStream}) and provide a list of single responses as {@link BatchSingleResponse}
+ *
+ * @param content response body
+ * @param contentType format of content in the given input stream (inclusive boundary parameter)
+ * @return list of {@link BatchSingleResponse}
+ * @throws BatchException
+ */
+ public static List<BatchSingleResponse> parseBatchResponse(final InputStream content, final String contentType) throws BatchException {
+ return createEntityProvider().parseBatchResponse(contentType, content);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
index f64aa93..97e4002 100644
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
@@ -25,28 +25,28 @@ import java.util.Map;
import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
/**
- * The {@link EntityProviderReadProperties} contains all necessary settings to read an entity with the {@link EntityProvider}.
- *
- * The main settings are
+ * <p>The {@link EntityProviderReadProperties} contains all necessary settings
+ * to read an entity with the {@link EntityProvider}.</p>
+ * <p>The main settings are
* <ul>
* <li>the <code>mergeSemantic</code></li>
* <li>the <code>callback for inlined navigation properties</code></li>
* <li>and the <code>type mappings</code></li>
* </ul>
- *
+ * </p>
*
*/
public class EntityProviderReadProperties {
/** Callback which is necessary if entity contains inlined navigation properties. */
private OnReadInlineContent callback;
/**
- * if merge is <code>true</code> the input content is in context of an <b>merge</b> (e.g. MERGE, PATCH) read request,
- * otherwise if <code>false</code> it is an <b>none merge</b> (e.g. CREATE) read request
+ * if merge is <code>true</code> the input content is in context of a <b>merge</b> (e.g. MERGE, PATCH) read request,
+ * otherwise if <code>false</code> it is a <b>non-merge</b> (e.g. CREATE) read request
*/
private boolean merge;
/**
- * typeMappings contains mappings from <code>edm property name</code> to <code>java class</code> which should be used
- * for a type mapping during read of content. If according <code>edm property</code> can not be read
+ * typeMappings contains mappings from <code>edm property name</code> to <code>java class</code> which should be used
+ * for a type mapping during reading of content. If according <code>edm property</code> can not be read
* into given <code>java class</code> an {@link EntityProviderException} is thrown.
* Supported mappings are documented in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType}.
*/
@@ -78,6 +78,14 @@ public class EntityProviderReadProperties {
return callback;
}
+ /**
+ * <p>Gets the merge semantics.</p>
+ * <p>Merge semantics is set if the input content has to be treated in the context
+ * of a request to merge incoming data with existing data (e.g., indicated by the
+ * HTTP verbs <code>MERGE</code> or <code>PATCH</code> in a server application).
+ * Otherwise the request, even if not all data are supplied, is supposed to
+ * overwrite the existing entity completely.</p>
+ */
public boolean getMergeSemantic() {
return merge;
}
@@ -97,6 +105,11 @@ public class EntityProviderReadProperties {
addTypeMappings(propertiesFrom.typeMappings);
}
+ /**
+ * Sets the merge semantics.
+ * @param mergeSemantic whether merge semantics is requested
+ * @see EntityProviderReadProperties#getMergeSemantic()
+ */
public EntityProviderReadPropertiesBuilder mergeSemantic(final boolean mergeSemantic) {
properties.merge = mergeSemantic;
return this;
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
index 6590bc5..88c87cd 100644
--- a/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
@@ -22,6 +22,9 @@ import java.io.InputStream;
import org.apache.olingo.odata2.api.ODataService;
import org.apache.olingo.odata2.api.batch.BatchResponsePart.BatchResponsePartBuilder;
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSet.BatchChangeSetBuilder;
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart.BatchChangeSetPartBuilder;
+import org.apache.olingo.odata2.api.client.batch.BatchQueryPart.BatchQueryPartBuilder;
import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
@@ -96,6 +99,12 @@ public abstract class RuntimeDelegate {
protected abstract ODataRequestBuilder createODataRequestBuilder();
+ protected abstract BatchChangeSetBuilder createBatchChangeSetBuilder();
+
+ protected abstract BatchQueryPartBuilder createBatchQueryRequestBuilder();
+
+ protected abstract BatchChangeSetPartBuilder createBatchChangeSetRequest();
+
}
/**
@@ -185,4 +194,16 @@ public abstract class RuntimeDelegate {
public static ODataRequestBuilder createODataRequestBuilder() {
return RuntimeDelegate.getInstance().createODataRequestBuilder();
}
+
+ public static BatchChangeSetBuilder createBatchChangeSetBuilder() {
+ return RuntimeDelegate.getInstance().createBatchChangeSetBuilder();
+ }
+
+ public static BatchQueryPartBuilder createBatchQueryPartBuilder() {
+ return RuntimeDelegate.getInstance().createBatchQueryRequestBuilder();
+ }
+
+ public static BatchChangeSetPartBuilder createBatchChangeSetPartBuilder() {
+ return RuntimeDelegate.getInstance().createBatchChangeSetRequest();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetImpl.java
new file mode 100644
index 0000000..2db859c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetImpl.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.odata2.core.batch;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSet;
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart;
+
+public class BatchChangeSetImpl extends BatchChangeSet {
+ private List<BatchChangeSetPart> requests = new ArrayList<BatchChangeSetPart>();
+
+ @Override
+ public void add(final BatchChangeSetPart request) {
+ requests.add(request);
+ }
+
+ @Override
+ public List<BatchChangeSetPart> getChangeSetParts() {
+ return Collections.unmodifiableList(requests);
+ }
+
+ public class BatchChangeSetBuilderImpl extends BatchChangeSetBuilder {
+
+ @Override
+ public BatchChangeSet build() {
+ return BatchChangeSetImpl.this;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetPartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetPartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetPartImpl.java
new file mode 100644
index 0000000..9546017
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchChangeSetPartImpl.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.odata2.core.batch;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart;
+
+public class BatchChangeSetPartImpl extends BatchChangeSetPart {
+ private String method;
+ private Map<String, String> headers = new HashMap<String, String>();
+ private String body;
+ private String uri;
+ public String contentId;
+ private static final String CHANGE_METHODS = "(PUT|POST|DELETE|MERGE|PATCH)";
+
+ @Override
+ public Map<String, String> getHeaders() {
+ return Collections.unmodifiableMap(headers);
+ }
+
+ @Override
+ public String getBody() {
+ return body;
+ }
+
+ @Override
+ public String getMethod() {
+ return method;
+ }
+
+ @Override
+ public String getUri() {
+ return uri;
+ }
+
+ @Override
+ public String getContentId() {
+ return contentId;
+ }
+
+ public class BatchChangeSetRequestBuilderImpl extends BatchChangeSetPartBuilder {
+ private String method;
+ private Map<String, String> headers = new HashMap<String, String>();
+ private String body;
+ private String uri;
+ private String contentId;
+
+ @Override
+ public BatchChangeSetPart build() {
+ if (method == null || uri == null) {
+ throw new IllegalArgumentException();
+ }
+ BatchChangeSetPartImpl.this.method = method;
+ BatchChangeSetPartImpl.this.headers = headers;
+ BatchChangeSetPartImpl.this.body = body;
+ BatchChangeSetPartImpl.this.uri = uri;
+ BatchChangeSetPartImpl.this.contentId = contentId;
+ return BatchChangeSetPartImpl.this;
+ }
+
+ @Override
+ public BatchChangeSetPartBuilder headers(final Map<String, String> headers) {
+ this.headers = headers;
+ return this;
+ }
+
+ @Override
+ public BatchChangeSetPartBuilder body(final String body) {
+ this.body = body;
+ return this;
+ }
+
+ @Override
+ public BatchChangeSetPartBuilder uri(final String uri) {
+ this.uri = uri;
+ return this;
+ }
+
+ @Override
+ public BatchChangeSetPartBuilder method(final String method) {
+ if (method != null && method.matches(CHANGE_METHODS)) {
+ this.method = method;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ return this;
+ }
+
+ @Override
+ public BatchChangeSetPartBuilder contentId(final String contentId) {
+ this.contentId = contentId;
+ return this;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
deleted file mode 100644
index 052365d..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-public class BatchConstants {
-
- public static final String HTTP_APPLICATION_HTTP = "application/http";
-
- public static final String MULTIPART_MIXED = "multipart/mixed";
-
- public static final String BINARY_ENCODING = "binary";
-
- public static final String HTTP_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
-
- public static final String HTTP_CONTENT_ID = "Content-Id";
-
- public static final String MIME_HEADER_CONTENT_ID = "MimeHeader-ContentId";
-
- public static final String REQUEST_HEADER_CONTENT_ID = "RequestHeader-ContentId";
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
index 22dfd70..8869a33 100644
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
@@ -29,7 +29,7 @@ import java.util.Map;
import org.apache.olingo.odata2.api.ODataService;
import org.apache.olingo.odata2.api.ODataServiceFactory;
import org.apache.olingo.odata2.api.batch.BatchHandler;
-import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchRequestPart;
import org.apache.olingo.odata2.api.batch.BatchResponsePart;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
@@ -55,7 +55,7 @@ public class BatchHandlerImpl implements BatchHandler {
}
@Override
- public BatchResponsePart handleBatchPart(final BatchPart batchPart) throws ODataException {
+ public BatchResponsePart handleBatchPart(final BatchRequestPart batchPart) throws ODataException {
if (batchPart.isChangeSet()) {
List<ODataRequest> changeSetRequests = batchPart.getRequests();
contentIdMap = new HashMap<String, String>();
@@ -66,8 +66,8 @@ public class BatchHandlerImpl implements BatchHandler {
}
ODataRequest request = batchPart.getRequests().get(0);
ODataRequestHandler handler = createHandler(request);
- String mimeHeaderContentId = request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
- String requestHeaderContentId = request.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ String mimeHeaderContentId = request.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ String requestHeaderContentId = request.getRequestHeaderValue(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
ODataResponse response = setContentIdHeader(handler.handle(request), mimeHeaderContentId, requestHeaderContentId);
List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
responses.add(response);
@@ -78,8 +78,8 @@ public class BatchHandlerImpl implements BatchHandler {
@Override
public ODataResponse handleRequest(final ODataRequest suppliedRequest) throws ODataException {
ODataRequest request;
- String mimeHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
- String requestHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ String mimeHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ String requestHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
List<PathSegment> odataSegments = suppliedRequest.getPathInfo().getODataSegments();
if (!odataSegments.isEmpty() && odataSegments.get(0).getPath().matches("\\$.*")) {
@@ -142,12 +142,12 @@ public class BatchHandlerImpl implements BatchHandler {
private ODataResponse setContentIdHeader(final ODataResponse response, final String mimeHeaderContentId, final String requestHeaderContentId) {
ODataResponse modifiedResponse;
if (requestHeaderContentId != null && mimeHeaderContentId != null) {
- modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId)
- .header(BatchConstants.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
+ modifiedResponse = ODataResponse.fromResponse(response).header(BatchHelper.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId)
+ .header(BatchHelper.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
} else if (requestHeaderContentId != null) {
- modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId).build();
+ modifiedResponse = ODataResponse.fromResponse(response).header(BatchHelper.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId).build();
} else if (mimeHeaderContentId != null) {
- modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
+ modifiedResponse = ODataResponse.fromResponse(response).header(BatchHelper.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
} else {
return response;
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHelper.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHelper.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHelper.java
new file mode 100644
index 0000000..38d02ae
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHelper.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.odata2.core.batch;
+
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+public class BatchHelper {
+
+ public static final String BINARY_ENCODING = "binary";
+
+ public static final String DEFAULT_ENCODING = "utf-8";
+
+ public static final String HTTP_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+
+ public static final String HTTP_CONTENT_ID = "Content-Id";
+
+ public static final String MIME_HEADER_CONTENT_ID = "MimeHeader-ContentId";
+
+ public static final String REQUEST_HEADER_CONTENT_ID = "RequestHeader-ContentId";
+
+ protected static String generateBoundary(final String value) {
+ return value + "_" + UUID.randomUUID().toString();
+ }
+
+ protected static byte[] getBytes(final String body) {
+ try {
+ return body.getBytes(DEFAULT_ENCODING);
+ } catch (UnsupportedEncodingException e) {
+ throw new ODataRuntimeException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
deleted file mode 100644
index 665b01b..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.olingo.odata2.api.batch.BatchPart;
-import org.apache.olingo.odata2.api.processor.ODataRequest;
-
-public class BatchPartImpl implements BatchPart {
-
- private List<ODataRequest> requests = new ArrayList<ODataRequest>();
- private boolean isChangeSet;
-
- public BatchPartImpl() {}
-
- public BatchPartImpl(final boolean isChangeSet, final List<ODataRequest> requests) {
- this.isChangeSet = isChangeSet;
- this.requests = requests;
- }
-
- @Override
- public boolean isChangeSet() {
- return isChangeSet;
- }
-
- public void setChangeSet(final boolean isChangeSet) {
- this.isChangeSet = isChangeSet;
- }
-
- @Override
- public List<ODataRequest> getRequests() {
- return Collections.unmodifiableList(requests);
- }
-
- public void setRequests(final List<ODataRequest> requests) {
- this.requests = requests;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchQueryPartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchQueryPartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchQueryPartImpl.java
new file mode 100644
index 0000000..e22a3b3
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchQueryPartImpl.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.odata2.core.batch;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.client.batch.BatchQueryPart;
+
+public class BatchQueryPartImpl extends BatchQueryPart {
+ private String method;
+ private Map<String, String> headers = new HashMap<String, String>();
+ private String uri;
+ private String contentId;
+ private static final String GET = "GET";
+
+ @Override
+ public Map<String, String> getHeaders() {
+ return Collections.unmodifiableMap(headers);
+ }
+
+ @Override
+ public String getMethod() {
+ return method;
+ }
+
+ @Override
+ public String getUri() {
+ return uri;
+ }
+
+ @Override
+ public String getContentId() {
+ return contentId;
+ }
+
+ public class BatchQueryRequestBuilderImpl extends BatchQueryPartBuilder {
+ private String method;
+ private Map<String, String> headers = new HashMap<String, String>();
+ private String uri;
+ private String contentId;
+
+ @Override
+ public BatchQueryPart build() {
+ if (method == null || uri == null) {
+ throw new IllegalArgumentException();
+ }
+ BatchQueryPartImpl.this.method = method;
+ BatchQueryPartImpl.this.headers = headers;
+ BatchQueryPartImpl.this.uri = uri;
+ BatchQueryPartImpl.this.contentId = contentId;
+ return BatchQueryPartImpl.this;
+ }
+
+ @Override
+ public BatchQueryPartBuilder headers(final Map<String, String> headers) {
+ this.headers = headers;
+ return this;
+ }
+
+ @Override
+ public BatchQueryPartBuilder uri(final String uri) {
+ this.uri = uri;
+ return this;
+ }
+
+ @Override
+ public BatchQueryPartBuilder method(final String method) {
+ if (method != null && method.matches(GET)) {
+ this.method = method;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ return this;
+ }
+
+ @Override
+ public BatchQueryPartBuilder contentId(final String contentId) {
+ this.contentId = contentId;
+ return this;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
index 4c0ae32..e37d572 100644
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
@@ -21,10 +21,10 @@ package org.apache.olingo.odata2.core.batch;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -37,11 +37,13 @@ import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchRequestPart;
+import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataRequest.ODataRequestBuilder;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.api.uri.PathSegment;
import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
@@ -64,7 +66,7 @@ public class BatchRequestParser {
private static final Pattern REG_EX_ANY_BOUNDARY_STRING = Pattern.compile("--" + ANY_CHARACTERS + REG_EX_ZERO_OR_MORE_WHITESPACES);
private static final Pattern REG_EX_REQUEST_LINE = Pattern.compile("(GET|POST|PUT|DELETE|MERGE|PATCH)\\s(.*)\\s?" + REG_EX_VERSION + REG_EX_ZERO_OR_MORE_WHITESPACES);
private static final Pattern REG_EX_BOUNDARY_PARAMETER = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE + "boundary=(\".*\"|.*)" + REG_EX_ZERO_OR_MORE_WHITESPACES);
- private static final Pattern REG_EX_CONTENT_TYPE = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE + BatchConstants.MULTIPART_MIXED);
+ private static final Pattern REG_EX_CONTENT_TYPE = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE + HttpContentType.MULTIPART_MIXED);
private static final Pattern REG_EX_QUERY_PARAMETER = Pattern.compile("((?:\\$|)[^=]+)=([^=]+)");
private static final String REG_EX_BOUNDARY = "([a-zA-Z0-9_\\-\\.'\\+]{1,70})|\"([a-zA-Z0-9_\\-\\.'\\+\\s\\(\\),/:=\\?]{1,69}[a-zA-Z0-9_\\-\\.'\\+\\(\\),/:=\\?])\""; // See RFC 2046
@@ -74,19 +76,21 @@ public class BatchRequestParser {
private String boundary;
private String currentMimeHeaderContentId;
private int currentLineNumber = 0;
- private static Set<String> HTTP_CHANGESET_METHODS;
- private static Set<String> HTTP_BATCH_METHODS;
+ private final static Set<String> HTTP_CHANGESET_METHODS;
+ private final static Set<String> HTTP_BATCH_METHODS;
static {
- HTTP_CHANGESET_METHODS = new HashSet<String>();
- HTTP_CHANGESET_METHODS.add("POST");
- HTTP_CHANGESET_METHODS.add("PUT");
- HTTP_CHANGESET_METHODS.add("DELETE");
- HTTP_CHANGESET_METHODS.add("MERGE");
- HTTP_CHANGESET_METHODS.add("PATCH");
-
- HTTP_BATCH_METHODS = new HashSet<String>();
- HTTP_BATCH_METHODS.add("GET");
+ HashSet<String> httpChangesetMethods = new HashSet<String>();
+ httpChangesetMethods.add("POST");
+ httpChangesetMethods.add("PUT");
+ httpChangesetMethods.add("DELETE");
+ httpChangesetMethods.add("MERGE");
+ httpChangesetMethods.add("PATCH");
+ HTTP_CHANGESET_METHODS = Collections.unmodifiableSet(httpChangesetMethods);
+
+ HashSet<String> httpBatchMethods = new HashSet<String>();
+ httpBatchMethods.add("GET");
+ HTTP_BATCH_METHODS = Collections.unmodifiableSet(httpBatchMethods);
}
public BatchRequestParser(final String contentType, final EntityProviderBatchProperties properties) {
@@ -94,10 +98,10 @@ public class BatchRequestParser {
batchRequestPathInfo = properties.getPathInfo();
}
- public List<BatchPart> parse(final InputStream in) throws BatchException {
- Scanner scanner = new Scanner(in, "UTF-8").useDelimiter(LF);
+ public List<BatchRequestPart> parse(final InputStream in) throws BatchException {
+ Scanner scanner = new Scanner(in, BatchHelper.DEFAULT_ENCODING).useDelimiter(LF);
baseUri = getBaseUri();
- List<BatchPart> requestList;
+ List<BatchRequestPart> requestList;
try {
requestList = parseBatchRequest(scanner);
} finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
@@ -111,12 +115,12 @@ public class BatchRequestParser {
return requestList;
}
- private List<BatchPart> parseBatchRequest(final Scanner scanner) throws BatchException {
- List<BatchPart> requests = new LinkedList<BatchPart>();
+ private List<BatchRequestPart> parseBatchRequest(final Scanner scanner) throws BatchException {
+ List<BatchRequestPart> requests = new LinkedList<BatchRequestPart>();
if (contentTypeMime != null) {
boundary = getBoundary(contentTypeMime);
parsePreamble(scanner);
- String closeDelimiter = "--" + boundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES;
+ final String closeDelimiter = "--" + boundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES;
while (scanner.hasNext() && !scanner.hasNext(closeDelimiter)) {
requests.add(parseMultipart(scanner, boundary, false));
parseNewLine(scanner);
@@ -131,7 +135,6 @@ public class BatchRequestParser {
throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
}
return requests;
-
}
//The method parses additional information prior to the first boundary delimiter line
@@ -142,37 +145,37 @@ public class BatchRequestParser {
}
}
- private BatchPart parseMultipart(final Scanner scanner, final String boundary, final boolean isChangeSet) throws BatchException {
+ private BatchRequestPart parseMultipart(final Scanner scanner, final String boundary, final boolean isChangeSet) throws BatchException {
Map<String, String> mimeHeaders = new HashMap<String, String>();
- BatchPart multipart = null;
+ BatchRequestPart multipart = null;
List<ODataRequest> requests = new ArrayList<ODataRequest>();
if (scanner.hasNext("--" + boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
scanner.next();
currentLineNumber++;
mimeHeaders = parseHeaders(scanner);
- currentMimeHeaderContentId = mimeHeaders.get(BatchConstants.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ currentMimeHeaderContentId = mimeHeaders.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
String contentType = mimeHeaders.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
if (contentType == null) {
throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
}
if (isChangeSet) {
- if (BatchConstants.HTTP_APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
- validateEncoding(mimeHeaders.get(BatchConstants.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
+ if (HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
+ validateEncoding(mimeHeaders.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
parseNewLine(scanner);// mandatory
requests.add(parseRequest(scanner, isChangeSet));
- multipart = new BatchPartImpl(false, requests);
+ multipart = new BatchRequestPartImpl(false, requests);
} else {
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.HTTP_APPLICATION_HTTP));
+ throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.APPLICATION_HTTP));
}
} else {
- if (BatchConstants.HTTP_APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
- validateEncoding(mimeHeaders.get(BatchConstants.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
+ if (HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
+ validateEncoding(mimeHeaders.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
parseNewLine(scanner);// mandatory
requests.add(parseRequest(scanner, isChangeSet));
- multipart = new BatchPartImpl(false, requests);
- } else if (contentType.matches(REG_EX_OPTIONAL_WHITESPACE + BatchConstants.MULTIPART_MIXED + ANY_CHARACTERS)) {
+ multipart = new BatchRequestPartImpl(false, requests);
+ } else if (contentType.matches(REG_EX_OPTIONAL_WHITESPACE + HttpContentType.MULTIPART_MIXED + ANY_CHARACTERS)) {
String changeSetBoundary = getBoundary(contentType);
if (boundary.equals(changeSetBoundary)) {
throw new BatchException(BatchException.INVALID_CHANGESET_BOUNDARY.addContent(currentLineNumber));
@@ -181,16 +184,14 @@ public class BatchRequestParser {
parseNewLine(scanner);// mandatory
Pattern changeSetCloseDelimiter = Pattern.compile("--" + changeSetBoundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES);
while (!scanner.hasNext(changeSetCloseDelimiter)) {
- BatchPart part = parseMultipart(scanner, changeSetBoundary, true);
- if (part.getRequests().size() == 1) {
- changeSetRequests.add(part.getRequests().get(0));
- }
+ BatchRequestPart part = parseMultipart(scanner, changeSetBoundary, true);
+ changeSetRequests.addAll(part.getRequests());
}
scanner.next(changeSetCloseDelimiter);
currentLineNumber++;
- multipart = new BatchPartImpl(true, changeSetRequests);
+ multipart = new BatchRequestPartImpl(true, changeSetRequests);
} else {
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.MULTIPART_MIXED + " or " + BatchConstants.HTTP_APPLICATION_HTTP));
+ throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED + " or " + HttpContentType.APPLICATION_HTTP));
}
}
} else if (scanner.hasNext(boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
@@ -208,60 +209,62 @@ public class BatchRequestParser {
}
private ODataRequest parseRequest(final Scanner scanner, final boolean isChangeSet) throws BatchException {
- try {
- ODataRequest request;
- if (scanner.hasNext(REG_EX_REQUEST_LINE)) {
- scanner.next(REG_EX_REQUEST_LINE);
- currentLineNumber++;
- String method = null;
- String uri = null;
- MatchResult result = scanner.match();
- if (result.groupCount() == 2) {
- method = result.group(1);
- uri = result.group(2).trim();
- } else {
- currentLineNumber++;
- throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(scanner.next()).addContent(currentLineNumber));
- }
- PathInfo pathInfo = parseRequestUri(uri);
- Map<String, String> queryParameters = parseQueryParameters(uri);
- if (isChangeSet) {
- if (!HTTP_CHANGESET_METHODS.contains(method)) {
- throw new BatchException(BatchException.INVALID_CHANGESET_METHOD.addContent(currentLineNumber));
- }
- } else if (!HTTP_BATCH_METHODS.contains(method)) {
- throw new BatchException(BatchException.INVALID_QUERY_OPERATION_METHOD.addContent(currentLineNumber));
- }
- ODataHttpMethod httpMethod = ODataHttpMethod.valueOf(method);
- Map<String, List<String>> headers = parseRequestHeaders(scanner);
- if (currentMimeHeaderContentId != null) {
- List<String> headerList = new ArrayList<String>();
- headerList.add(currentMimeHeaderContentId);
- headers.put(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
- }
-
- String contentType = getContentTypeHeader(headers);
- List<String> acceptHeaders = getAcceptHeader(headers);
- List<Locale> acceptLanguages = getAcceptLanguageHeader(headers);
- parseNewLine(scanner);
- InputStream body;
- body = new ByteArrayInputStream("".getBytes("UTF-8"));
- if (isChangeSet) {
- body = parseBody(scanner);
- }
- if (contentType != null) {
- request = ODataRequest.method(httpMethod).queryParameters(queryParameters).requestHeaders(headers).pathInfo(pathInfo).acceptableLanguages(acceptLanguages).contentType(contentType).body(body).acceptHeaders(acceptHeaders).build();
- } else {
- request = ODataRequest.method(httpMethod).queryParameters(queryParameters).requestHeaders(headers).pathInfo(pathInfo).acceptableLanguages(acceptLanguages).body(body).acceptHeaders(acceptHeaders).build();
- }
+ if (scanner.hasNext(REG_EX_REQUEST_LINE)) {
+ scanner.next(REG_EX_REQUEST_LINE);
+ currentLineNumber++;
+ final String method;
+ final String uri;
+ MatchResult result = scanner.match();
+ if (result.groupCount() == 2) {
+ method = result.group(1);
+ uri = result.group(2).trim();
} else {
currentLineNumber++;
throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(scanner.next()).addContent(currentLineNumber));
}
- return request;
- } catch (UnsupportedEncodingException e) {
- throw new ODataRuntimeException(e);
+ PathInfo pathInfo = parseRequestUri(uri);
+ Map<String, String> queryParameters = parseQueryParameters(uri);
+ if (isChangeSet) {
+ if (!HTTP_CHANGESET_METHODS.contains(method)) {
+ throw new BatchException(BatchException.INVALID_CHANGESET_METHOD.addContent(currentLineNumber));
+ }
+ } else if (!HTTP_BATCH_METHODS.contains(method)) {
+ throw new BatchException(BatchException.INVALID_QUERY_OPERATION_METHOD.addContent(currentLineNumber));
+ }
+ ODataHttpMethod httpMethod = ODataHttpMethod.valueOf(method);
+ Map<String, List<String>> headers = parseRequestHeaders(scanner);
+ if (currentMimeHeaderContentId != null) {
+ List<String> headerList = new ArrayList<String>();
+ headerList.add(currentMimeHeaderContentId);
+ headers.put(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
+ }
+
+ String contentType = getContentTypeHeader(headers);
+ List<String> acceptHeaders = getAcceptHeader(headers);
+ List<Locale> acceptLanguages = getAcceptLanguageHeader(headers);
+ parseNewLine(scanner);
+ InputStream body = new ByteArrayInputStream(new byte[0]);
+ if (isChangeSet) {
+ body = parseBody(scanner);
+ }
+
+ ODataRequestBuilder requestBuilder = ODataRequest.method(httpMethod)
+ .queryParameters(queryParameters)
+ .requestHeaders(headers)
+ .pathInfo(pathInfo)
+ .acceptableLanguages(acceptLanguages)
+ .body(body)
+ .acceptHeaders(acceptHeaders);
+
+ if (contentType != null) {
+ requestBuilder = requestBuilder.contentType(contentType);
+ }
+ return requestBuilder.build();
+ } else {
+ currentLineNumber++;
+ throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(scanner.next()).addContent(currentLineNumber));
}
+
}
private Map<String, List<String>> parseRequestHeaders(final Scanner scanner) throws BatchException {
@@ -280,7 +283,7 @@ public class BatchRequestParser {
} else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerName)) {
List<String> acceptLanguageHeaders = parseAcceptableLanguages(headerValue);
headers.put(headerName, acceptLanguageHeaders);
- } else if (!BatchConstants.HTTP_CONTENT_ID.equalsIgnoreCase(headerName)) {
+ } else if (!BatchHelper.HTTP_CONTENT_ID.equalsIgnoreCase(headerName)) {
if (headers.containsKey(headerName)) {
headers.get(headerName).add(headerValue);
} else {
@@ -291,7 +294,7 @@ public class BatchRequestParser {
} else {
List<String> headerList = new ArrayList<String>();
headerList.add(headerValue);
- headers.put(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
+ headers.put(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
}
}
} else {
@@ -306,40 +309,65 @@ public class BatchRequestParser {
PathInfoImpl pathInfo = new PathInfoImpl();
pathInfo.setServiceRoot(batchRequestPathInfo.getServiceRoot());
pathInfo.setPrecedingPathSegment(batchRequestPathInfo.getPrecedingSegments());
- Scanner uriScanner = new Scanner(uri);
- Pattern regexRequestUri = Pattern.compile("(?:" + baseUri + ")?/?([^?]+)(\\?.*)?");
- if (uriScanner.hasNext(regexRequestUri)) {
- uriScanner.next(regexRequestUri);
- MatchResult result = uriScanner.match();
- if (result.groupCount() == 2) {
- String odataPathSegmentsAsString = result.group(1);
- String queryParametersAsString = result.group(2) != null ? result.group(2) : "";
- pathInfo.setODataPathSegment(parseODataPathSegments(odataPathSegmentsAsString));
- try {
- if (!odataPathSegmentsAsString.startsWith("$")) {
- String requestUri = baseUri + "/" + odataPathSegmentsAsString + queryParametersAsString;
- pathInfo.setRequestUri(new URI(requestUri));
+ final String odataPathSegmentsAsString;
+ final String queryParametersAsString;
+ try {
+ Scanner uriScanner = new Scanner(uri).useDelimiter(LF);
+ URI uriObject = new URI(uri);
+ if (uriObject.isAbsolute()) {
+ Pattern regexRequestUri = Pattern.compile(baseUri + "/([^/][^?]*)(\\?.*)?");
+ if (uriScanner.hasNext(regexRequestUri)) {
+ uriScanner.next(regexRequestUri);
+ MatchResult result = uriScanner.match();
+ if (result.groupCount() == 2) {
+ odataPathSegmentsAsString = result.group(1);
+ queryParametersAsString = result.group(2) != null ? result.group(2) : "";
+ } else {
+ uriScanner.close();
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber));
}
- } catch (URISyntaxException e) {
+ } else {
uriScanner.close();
- throw new BatchException(BatchException.INVALID_URI, e);
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber));
}
} else {
- uriScanner.close();
- throw new BatchException(BatchException.INVALID_URI);
+ Pattern regexRequestUri = Pattern.compile("([^/][^?]*)(\\?.*)?");
+ if (uriScanner.hasNext(regexRequestUri)) {
+ uriScanner.next(regexRequestUri);
+ MatchResult result = uriScanner.match();
+ if (result.groupCount() == 2) {
+ odataPathSegmentsAsString = result.group(1);
+ queryParametersAsString = result.group(2) != null ? result.group(2) : "";
+ } else {
+ uriScanner.close();
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber));
+ }
+ } else if (uriScanner.hasNext("/(.*)")) {
+ uriScanner.close();
+ throw new BatchException(BatchException.UNSUPPORTED_ABSOLUTE_PATH.addContent(currentLineNumber));
+ } else {
+ uriScanner.close();
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber));
+ }
+
}
- } else {
uriScanner.close();
- throw new BatchException(BatchException.INVALID_URI);
+ pathInfo.setODataPathSegment(parseODataPathSegments(odataPathSegmentsAsString));
+ if (!odataPathSegmentsAsString.startsWith("$")) {
+ String requestUri = baseUri + "/" + odataPathSegmentsAsString + queryParametersAsString;
+ pathInfo.setRequestUri(new URI(requestUri));
+ }
+ return pathInfo;
+ } catch (URISyntaxException e) {
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber), e);
}
- uriScanner.close();
- return pathInfo;
+
}
private Map<String, String> parseQueryParameters(final String uri) throws BatchException {
- Scanner uriScanner = new Scanner(uri);
+ Scanner uriScanner = new Scanner(uri).useDelimiter("\n");
Map<String, String> queryParametersMap = new HashMap<String, String>();
- Pattern regex = Pattern.compile("(?:" + baseUri + ")?/?" + "[^?]+" + "\\?(.*)");
+ Pattern regex = Pattern.compile("(?:" + baseUri + "/)?" + "[^?]+" + "\\?(.*)");
if (uriScanner.hasNext(regex)) {
uriScanner.next(regex);
MatchResult uriResult = uriScanner.match();
@@ -362,7 +390,7 @@ public class BatchRequestParser {
} else {
uriScanner.close();
- throw new BatchException(BatchException.INVALID_URI);
+ throw new BatchException(BatchException.INVALID_URI.addContent(currentLineNumber));
}
}
uriScanner.close();
@@ -388,30 +416,28 @@ public class BatchRequestParser {
}
private InputStream parseBody(final Scanner scanner) {
- try {
- String body = null;
- InputStream requestBody;
- while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
- if (!scanner.hasNext(REG_EX_ZERO_OR_MORE_WHITESPACES)) {
- if (body == null) {
- body = scanner.next();
- } else {
- body = body + LF + scanner.next();
- }
+ StringBuilder body = null;
+ final InputStream requestBody;
+
+ while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
+ if (!scanner.hasNext(REG_EX_ZERO_OR_MORE_WHITESPACES)) {
+ if (body == null) {
+ body = new StringBuilder(scanner.next());
} else {
- scanner.next();
+ body.append(LF).append(scanner.next());
}
- currentLineNumber++;
- }
- if (body != null) {
- requestBody = new ByteArrayInputStream(body.getBytes("UTF-8"));
} else {
- requestBody = new ByteArrayInputStream("".getBytes("UTF-8"));
+ scanner.next();
}
- return requestBody;
- } catch (UnsupportedEncodingException e) {
- throw new ODataRuntimeException(e);
+ currentLineNumber++;
+ }
+
+ if (body != null) {
+ requestBody = new ByteArrayInputStream(BatchHelper.getBytes(body.toString()));
+ } else {
+ requestBody = new ByteArrayInputStream(new byte[0]);
}
+ return requestBody;
}
private String getBoundary(final String contentType) throws BatchException {
@@ -420,7 +446,7 @@ public class BatchRequestParser {
contentTypeScanner.next(REG_EX_CONTENT_TYPE);
} else {
contentTypeScanner.close();
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.MULTIPART_MIXED));
+ throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED));
}
if (contentTypeScanner.hasNext(REG_EX_BOUNDARY_PARAMETER)) {
contentTypeScanner.next(REG_EX_BOUNDARY_PARAMETER);
@@ -438,7 +464,7 @@ public class BatchRequestParser {
}
private void validateEncoding(final String encoding) throws BatchException {
- if (!BatchConstants.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
+ if (!BatchHelper.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
}
}