From afda326d7538ddb970fd4237321d1c420b8ac31b Mon Sep 17 00:00:00 2001 From: Klaus Straubinger Date: Wed, 17 Jun 2015 09:59:23 +0200 Subject: [PATCH] [OLINGO-698] technical service supports preferences, part 2 Signed-off-by: Christian Amend --- .../fit/tecsvc/client/BatchClientITCase.java | 64 ++++----- .../deserializer/batch/ODataResponsePart.java | 29 ++-- .../core/batchhandler/BatchPartHandler.java | 14 +- .../apache/olingo/server/tecsvc/Encoder.java | 132 ------------------ .../processor/TechnicalBatchProcessor.java | 26 ++-- .../options/ServerSidePagingHandler.java | 12 +- 6 files changed, 64 insertions(+), 213 deletions(-) delete mode 100644 lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/Encoder.java diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java index 72a4ef394..e56165dbf 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java @@ -60,7 +60,6 @@ import org.junit.Before; import org.junit.Test; public class BatchClientITCase extends AbstractTestITCase { - private final static String ACCEPT = ContentType.APPLICATION_OCTET_STREAM.toContentTypeString(); private static final String SERVICE_URI = TecSvcConst.BASE_URI; private static final String SERVICE_NAMESPACE = "olingo.odata.test1"; private static final String ES_NOT_AVAILABLE_NAME = "ESNotAvailable"; @@ -70,6 +69,7 @@ public class BatchClientITCase extends AbstractTestITCase { @Before public void setup() { + client.getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM); client.getConfiguration().setContinueOnError(false); } @@ -98,7 +98,6 @@ public class BatchClientITCase extends AbstractTestITCase { entity.getProperties().add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder() .buildString("1"))); final ODataBatchRequest batchRequest = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - batchRequest.setAccept(ACCEPT); final BatchManager payloadManager = batchRequest.payloadManager(); final ODataChangeset changeset = payloadManager.addChangeset(); final URI targetURI = client.newURIBuilder(SERVICE_URI) @@ -130,12 +129,11 @@ public class BatchClientITCase extends AbstractTestITCase { public void emptyBatchRequest() { // create your request final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); assertEquals("Accepted", response.getStatusMessage()); final Iterator iter = response.getBody(); @@ -145,7 +143,6 @@ public class BatchClientITCase extends AbstractTestITCase { @Test public void getBatchRequestWithRelativeUris() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); @@ -155,7 +152,7 @@ public class BatchClientITCase extends AbstractTestITCase { // Fetch result final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); assertEquals("Accepted", response.getStatusMessage()); final Iterator iter = response.getBody(); @@ -177,7 +174,6 @@ public class BatchClientITCase extends AbstractTestITCase { @Test public void getBatchRequest() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); @@ -187,7 +183,7 @@ public class BatchClientITCase extends AbstractTestITCase { // Fetch result final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); assertEquals("Accepted", response.getStatusMessage()); final Iterator iter = response.getBody(); @@ -209,7 +205,6 @@ public class BatchClientITCase extends AbstractTestITCase { @Test public void testErrorWithoutContinueOnErrorPreferHeader() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); @@ -219,7 +214,7 @@ public class BatchClientITCase extends AbstractTestITCase { // Fetch result final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); final Iterator iter = response.getBody(); @@ -253,7 +248,6 @@ public class BatchClientITCase extends AbstractTestITCase { @Test public void testInvalidAbsoluteUri() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); final URI uri = new URI(SERVICE_URI + "/../ESAllPrim(32767)"); @@ -263,7 +257,7 @@ public class BatchClientITCase extends AbstractTestITCase { // Fetch result final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); final Iterator bodyIterator = response.getBody(); assertTrue(bodyIterator.hasNext()); @@ -272,13 +266,12 @@ public class BatchClientITCase extends AbstractTestITCase { assertFalse(item.isChangeset()); final ODataResponse oDataResponse = item.next(); - assertEquals(400, oDataResponse.getStatusCode()); + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), oDataResponse.getStatusCode()); } @Test(expected = HttpClientException.class) public void testInvalidHost() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); final URI uri = new URI("http://otherhost/odata/ESAllPrim(32767)"); @@ -293,7 +286,6 @@ public class BatchClientITCase extends AbstractTestITCase { @Test(expected = HttpClientException.class) public void testInvalidAbsoluteRequest() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); final URI uri = new URI("/ESAllPrim(32767)"); @@ -306,10 +298,9 @@ public class BatchClientITCase extends AbstractTestITCase { } @Test - public void testErrorWithContinueOnErrorPreferHeader() throws URISyntaxException { + public void errorWithContinueOnErrorPreferHeader() throws Exception { client.getConfiguration().setContinueOnError(true); final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); @@ -319,7 +310,8 @@ public class BatchClientITCase extends AbstractTestITCase { // Fetch result final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); + assertEquals("odata.continue-on-error", response.getHeader(HttpHeader.PREFERENCE_APPLIED).iterator().next()); final Iterator bodyIterator = response.getBody(); @@ -331,10 +323,10 @@ public class BatchClientITCase extends AbstractTestITCase { ODataResponse oDataResonse = item.next(); assertNotNull(oDataResonse); assertEquals(HttpStatusCode.OK.getStatusCode(), oDataResonse.getStatusCode()); - assertEquals(1, oDataResonse.getHeader("OData-Version").size()); - assertEquals("4.0", oDataResonse.getHeader("OData-Version").toArray()[0]); - assertEquals(1, oDataResonse.getHeader("Content-Length").size()); - assertEquals("605", oDataResonse.getHeader("Content-Length").toArray()[0]); + assertEquals(1, oDataResonse.getHeader(HttpHeader.ODATA_VERSION).size()); + assertEquals("4.0", oDataResonse.getHeader(HttpHeader.ODATA_VERSION).toArray()[0]); + assertEquals(1, oDataResonse.getHeader(HttpHeader.CONTENT_LENGTH).size()); + assertEquals("605", oDataResonse.getHeader(HttpHeader.CONTENT_LENGTH).toArray()[0]); assertEquals("application/json;odata.metadata=minimal", oDataResonse.getContentType()); // Check second get request @@ -354,20 +346,18 @@ public class BatchClientITCase extends AbstractTestITCase { oDataResonse = item.next(); assertNotNull(oDataResonse); assertEquals(HttpStatusCode.OK.getStatusCode(), oDataResonse.getStatusCode()); - assertEquals(1, oDataResonse.getHeader("OData-Version").size()); - assertEquals("4.0", oDataResonse.getHeader("OData-Version").toArray()[0]); - assertEquals(1, oDataResonse.getHeader("Content-Length").size()); - assertEquals("513", oDataResonse.getHeader("Content-Length").toArray()[0]); + assertEquals(1, oDataResonse.getHeader(HttpHeader.ODATA_VERSION).size()); + assertEquals("4.0", oDataResonse.getHeader(HttpHeader.ODATA_VERSION).toArray()[0]); + assertEquals(1, oDataResonse.getHeader(HttpHeader.CONTENT_LENGTH).size()); + assertEquals("513", oDataResonse.getHeader(HttpHeader.CONTENT_LENGTH).toArray()[0]); assertEquals("application/json;odata.metadata=minimal", oDataResonse.getContentType()); } @Test - @SuppressWarnings("unchecked") public void changesetWithReferences() throws EdmPrimitiveTypeException, URISyntaxException { // create your request final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); final ClientObjectFactory of = client.getObjectFactory(); - request.setAccept(ACCEPT); final BatchManager streamManager = request.payloadManager(); final ODataChangeset changeset = streamManager.addChangeset(); @@ -421,7 +411,7 @@ public class BatchClientITCase extends AbstractTestITCase { ODataResponse res = chgitem.next(); assertEquals(HttpStatusCode.CREATED.getStatusCode(), res.getStatusCode()); assertTrue(res instanceof ODataEntityCreateResponse); - final ODataEntityCreateResponse createResponse = ((ODataEntityCreateResponse) res); + final ODataEntityCreateResponse createResponse = ((ODataEntityCreateResponse) res); res = chgitem.next(); assertEquals(HttpStatusCode.OK.getStatusCode(), res.getStatusCode()); @@ -442,11 +432,9 @@ public class BatchClientITCase extends AbstractTestITCase { } @Test - @SuppressWarnings("unchecked") public void changesetBatchRequest() throws URISyntaxException { final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(SERVICE_URI); final ClientObjectFactory of = client.getObjectFactory(); - request.setAccept(ACCEPT); final BatchManager payload = request.payloadManager(); // ----------------------------- @@ -530,7 +518,7 @@ public class BatchClientITCase extends AbstractTestITCase { // - Fetch result // ----------------------------- final ODataBatchResponse response = payload.getResponse(); - assertEquals(202, response.getStatusCode()); + assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), response.getStatusCode()); final Iterator bodyIterator = response.getBody(); // Check first get request @@ -540,7 +528,9 @@ public class BatchClientITCase extends AbstractTestITCase { assertTrue(item.hasNext()); final ODataResponse response0 = item.next(); assertTrue(response0 instanceof ODataRetrieveResponse); - assertEquals(34, ((ODataRetrieveResponse) response0).getBody() + @SuppressWarnings("unchecked") + ODataRetrieveResponse retrieveResponse = (ODataRetrieveResponse) response0; + assertEquals(34, retrieveResponse.getBody() .getProperty("PropertyDecimal") .getPrimitiveValue() .toValue()); @@ -555,7 +545,7 @@ public class BatchClientITCase extends AbstractTestITCase { final ODataResponse response1 = item.next(); assertEquals(HttpStatusCode.CREATED.getStatusCode(), response1.getStatusCode()); assertTrue(response1 instanceof ODataEntityCreateResponse); - assertEquals(3.1415, ((ODataEntityCreateResponse) response1).getBody().getProperty("PropertyDouble") + assertEquals(3.1415, ((ODataEntityCreateResponse) response1).getBody().getProperty("PropertyDouble") .getPrimitiveValue() .toValue()); // Update @@ -569,7 +559,7 @@ public class BatchClientITCase extends AbstractTestITCase { final ODataResponse response3 = item.next(); assertEquals(HttpStatusCode.CREATED.getStatusCode(), response3.getStatusCode()); assertTrue(response3 instanceof ODataEntityUpdateResponse); - assertEquals(3.1415, ((ODataEntityUpdateResponse) response3).getBody().getProperty("PropertyDouble") + assertEquals(3.1415, ((ODataEntityUpdateResponse) response3).getBody().getProperty("PropertyDouble") .getPrimitiveValue() .toValue()); @@ -580,7 +570,9 @@ public class BatchClientITCase extends AbstractTestITCase { assertTrue(item.hasNext()); final ODataResponse response4 = item.next(); assertTrue(response4 instanceof ODataRetrieveResponse); - assertEquals(3.1415, ((ODataRetrieveResponse) response4).getBody() + @SuppressWarnings("unchecked") + final ODataRetrieveResponse retrieveResponse2 = (ODataRetrieveResponse) response4; + assertEquals(3.1415, retrieveResponse2.getBody() .getProperty("PropertyDouble") .getPrimitiveValue() .toValue()); diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/ODataResponsePart.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/ODataResponsePart.java index 56c0084ce..8b0bd5225 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/ODataResponsePart.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/ODataResponsePart.java @@ -24,23 +24,23 @@ import java.util.List; import org.apache.olingo.server.api.ODataResponse; /** - * An ODataResponsePart represents a collections of ODataResponses. + * An ODataResponsePart represents a collection of ODataResponses. * A list of ODataResponseParts can be combined by the BatchSerializer to a single * OData batch response. */ public class ODataResponsePart { - private List responses; - private boolean isChangeSet; + private final List responses; + private final boolean isChangeSet; /** * Creates a new ODataResponsePart. * - * An ODataResponsePart represents a collections of ODataResponses. + * An ODataResponsePart represents a collection of ODataResponses. * A list of ODataResponseParts can be combined by the BatchSerializer to a single * OData batch response. * * @param responses A list of {@link ODataResponse} - * @param isChangeSet True this ODataResponsePart represents a change set, otherwise false + * @param isChangeSet whether this ODataResponsePart represents a change set */ public ODataResponsePart(final List responses, final boolean isChangeSet) { this.responses = responses; @@ -50,12 +50,12 @@ public class ODataResponsePart { /** * Creates a new ODataResponsePart. * - * An ODataResponsePart represents a collections of ODataResponses. + * An ODataResponsePart represents a collection of ODataResponses. * A list of ODataResponseParts can be combined by the BatchSerializer to a single * OData batch response. * * @param response A single {@link ODataResponse} - * @param isChangeSet True this ODataResponsePart represents a change set, otherwise false + * @param isChangeSet whether this ODataResponsePart represents a change set */ public ODataResponsePart(final ODataResponse response, final boolean isChangeSet) { responses = Arrays.asList(response); @@ -63,21 +63,18 @@ public class ODataResponsePart { } /** - * Returns true if the current instance represents a change set. - * - * @return true or false + * Returns a collection of ODataResponses. + * Each collection contains at least one {@link ODataResponse}. + * If this instance represents a change set, there may be many ODataResponses. + * @return a list of {@link ODataResponse} */ public List getResponses() { return responses; } /** - * Returns a collection of ODataResponses. - * Each collections contains at least one {@link ODataResponse}. - * - * If this instance represents a change set, there are may many ODataResponses - * - * @return a list of {@link ODataResponse} + * Returns true if the current instance represents a change set. + * @return true or false */ public boolean isChangeSet() { return isChangeSet; diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchPartHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchPartHandler.java index c3cf73aa0..de1dcb1d0 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchPartHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/batchhandler/BatchPartHandler.java @@ -34,14 +34,14 @@ import org.apache.olingo.server.core.deserializer.batch.BatchParserCommon; public class BatchPartHandler { private final ODataHandler oDataHandler; private final BatchProcessor batchProcessor; - private final BatchFacade batchFascade; + private final BatchFacade batchFacade; private final BatchReferenceRewriter rewriter; public BatchPartHandler(final ODataHandler oDataHandler, final BatchProcessor processor, - final BatchFacade batchFascade) { + final BatchFacade batchFacade) { this.oDataHandler = oDataHandler; batchProcessor = processor; - this.batchFascade = batchFascade; + this.batchFacade = batchFacade; rewriter = new BatchReferenceRewriter(); } @@ -49,8 +49,8 @@ public class BatchPartHandler { return handle(request, true); } - public ODataResponsePart handleBatchRequest(final BatchRequestPart request) throws ODataApplicationException, - ODataLibraryException { + public ODataResponsePart handleBatchRequest(final BatchRequestPart request) + throws ODataApplicationException, ODataLibraryException { if (request.isChangeSet()) { return handleChangeSet(request); } else { @@ -62,7 +62,7 @@ public class BatchPartHandler { public ODataResponse handle(final ODataRequest request, final boolean isChangeSet) throws BatchDeserializerException { - final ODataResponse response; + ODataResponse response; if (isChangeSet) { rewriter.replaceReference(request); @@ -85,7 +85,7 @@ public class BatchPartHandler { private ODataResponsePart handleChangeSet(final BatchRequestPart request) throws ODataApplicationException, ODataLibraryException { - return batchProcessor.processChangeSet(batchFascade, request.getRequests()); + return batchProcessor.processChangeSet(batchFacade, request.getRequests()); } } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/Encoder.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/Encoder.java deleted file mode 100644 index 33956b5a2..000000000 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/Encoder.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ******************************************************************************/ -package org.apache.olingo.server.tecsvc; - -import java.io.UnsupportedEncodingException; - -/** - * Encodes a Java String (in its internal UTF-16 encoding) into its - * percent-encoded UTF-8 representation according to - * RFC 3986 - * (with consideration of its predecessor RFC 2396). - * - */ -public class Encoder { - - // TODO: Should we really copy this class? - - /** - * Encodes a Java String (in its internal UTF-16 encoding) into its - * percent-encoded UTF-8 representation according to - * RFC 3986, - * suitable for parts of an OData path segment. - * @param value the Java String - * @return the encoded String - */ - public static String encode(final String value) { - return encoder.encodeInternal(value); - } - - // OData has special handling for "'", so we allow that to remain unencoded. - // Other sub-delims not used neither by JAX-RS nor by OData could be added - // if the encoding is considered to be too aggressive. - // RFC 3986 would also allow the gen-delims ":" and "@" to appear literally - // in path-segment parts. - private static final String ODATA_UNENCODED = "'"; - - // Character classes from RFC 3986 - private final static String UNRESERVED = "-._~"; // + ALPHA + DIGIT - // RFC 3986 says: "For consistency, URI producers and normalizers should - // use uppercase hexadecimal digits for all percent-encodings." - private final static String[] hex = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0A", - "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18", "%19", "%1A", - "%1B", "%1C", "%1D", "%1E", "%1F", "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", "%28", "%29", "%2A", - "%2B", "%2C", "%2D", "%2E", "%2F", "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", "%38", "%39", "%3A", - "%3B", "%3C", "%3D", "%3E", "%3F", "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", "%48", "%49", "%4A", - "%4B", "%4C", "%4D", "%4E", "%4F", "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", "%58", "%59", "%5A", - "%5B", "%5C", "%5D", "%5E", "%5F", "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", "%68", "%69", "%6A", - "%6B", "%6C", "%6D", "%6E", "%6F", "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", "%78", "%79", "%7A", - "%7B", "%7C", "%7D", "%7E", "%7F", "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", "%88", - "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F", "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", "%98", - "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F", "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", "%A8", - "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7", "%B8", - "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF", "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7", "%C8", - "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", "%D8", - "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF", "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7", "%E8", - "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF", "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", "%F8", - "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF" }; - - private static final Encoder encoder = new Encoder(ODATA_UNENCODED); - - /** characters to remain unencoded in addition to {@link #UNRESERVED} */ - private final String unencoded; - - private Encoder(final String unencoded) { - this.unencoded = unencoded == null ? "" : unencoded; - } - - /** - *

Returns the percent-encoded UTF-8 representation of a String.

- *

In order to avoid producing percent-encoded CESU-8 (as described in - * the Unicode Consortium's - * Technical Report #26), this is done in two steps: - *

    - *
  1. Re-encode the characters from their Java-internal UTF-16 representations - * into their UTF-8 representations.
  2. - *
  3. Percent-encode each of the bytes in the UTF-8 representation. - * This is possible on byte level because all characters that do not have - * a %xx representation are represented in one byte in UTF-8.
  4. - *

- * @param input input String - * @return encoded representation - */ - private String encodeInternal(final String input) { - StringBuilder resultStr = new StringBuilder(); - - try { - for (byte utf8Byte : input.getBytes("UTF-8")) { - final char character = (char) utf8Byte; - if (isUnreserved(character)) { - resultStr.append(character); - } else if (isUnencoded(character)) { - resultStr.append(character); - } else if (utf8Byte >= 0) { - resultStr.append(hex[utf8Byte]); - } else { - // case UTF-8 continuation byte - resultStr.append(hex[256 + utf8Byte]); // index adjusted for the usage of signed bytes - } - } - } catch (final UnsupportedEncodingException e) { // should never happen; UTF-8 is always there - return null; - } - return resultStr.toString(); - } - - private static boolean isUnreserved(final char character) { - return 'A' <= character && character <= 'Z' // case A..Z - || 'a' <= character && character <= 'z' // case a..z - || '0' <= character && character <= '9' // case 0..9 - || UNRESERVED.indexOf(character) >= 0; - } - - private boolean isUnencoded(final char character) { - return unencoded.indexOf(character) >= 0; - } -} diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalBatchProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalBatchProcessor.java index b96ab827e..fbdeb908c 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalBatchProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalBatchProcessor.java @@ -34,11 +34,11 @@ import org.apache.olingo.server.api.batch.BatchFacade; import org.apache.olingo.server.api.deserializer.batch.BatchOptions; import org.apache.olingo.server.api.deserializer.batch.BatchRequestPart; import org.apache.olingo.server.api.deserializer.batch.ODataResponsePart; +import org.apache.olingo.server.api.prefer.PreferencesApplied; import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.tecsvc.data.DataProvider; public class TechnicalBatchProcessor extends TechnicalProcessor implements BatchProcessor { - private static final String PREFERENCE_CONTINUE_ON_ERROR = "odata.continue-on-error"; public TechnicalBatchProcessor(final DataProvider dataProvider) { super(dataProvider); @@ -47,7 +47,8 @@ public class TechnicalBatchProcessor extends TechnicalProcessor implements Batch @Override public void processBatch(final BatchFacade facade, final ODataRequest request, final ODataResponse response) throws ODataApplicationException, ODataLibraryException { - boolean continueOnError = isContinueOnError(request); + final boolean continueOnError = + odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).hasContinueOnError(); final String boundary = facade.extractBoundaryFromContentType(request.getHeader(HttpHeader.CONTENT_TYPE)); final BatchOptions options = BatchOptions.with() @@ -59,15 +60,15 @@ public class TechnicalBatchProcessor extends TechnicalProcessor implements Batch for (BatchRequestPart part : parts) { final ODataResponsePart responsePart = facade.handleBatchRequest(part); - responseParts.add(responsePart); // Also add failed responses + responseParts.add(responsePart); // Also add failed responses. final int statusCode = responsePart.getResponses().get(0).getStatusCode(); if ((statusCode >= 400 && statusCode <= 600) && !continueOnError) { - // Perform some additions actions + // Perform some additional actions. // ... - break; // Stop processing, but serialize all recent requests + break; // Stop processing, but serialize responses to all recent requests. } } @@ -77,19 +78,10 @@ public class TechnicalBatchProcessor extends TechnicalProcessor implements Batch response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.MULTIPART_MIXED + ";boundary=" + responseBoundary); response.setContent(responseContent); response.setStatusCode(HttpStatusCode.ACCEPTED.getStatusCode()); - } - - private boolean isContinueOnError(final ODataRequest request) { - final List preferValues = request.getHeaders(HttpHeader.PREFER); - - if (preferValues != null) { - for (final String preference : preferValues) { - if (PREFERENCE_CONTINUE_ON_ERROR.equals(preference)) { - return true; - } - } + if (continueOnError) { + response.setHeader(HttpHeader.PREFERENCE_APPLIED, + PreferencesApplied.with().continueOnError().build().toString()); } - return false; } @Override diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java index 71496fd64..ad8b7dd44 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java @@ -28,7 +28,6 @@ import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.uri.queryoption.SkipTokenOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind; -import org.apache.olingo.server.tecsvc.Encoder; public class ServerSidePagingHandler { private static final int MAX_PAGE_SIZE = 10; @@ -45,7 +44,7 @@ public class ServerSidePagingHandler { * @param rawRequestUri the request URI (used to construct the next link) * @param preferredPageSize the client's preference for page size * @return the chosen page size (or null if no paging has been done); - * could be used in the Preference-Applied HTTP header + * could be used in the Preference-Applied HTTP header * @throws ODataApplicationException */ public static Integer applyServerSidePaging(final SkipTokenOption skipTokenOption, EntityCollection entityCollection, @@ -74,7 +73,7 @@ public class ServerSidePagingHandler { return null; } - private static URI createNextLink(final String rawRequestUri, final Integer page, final int pageSize) + private static URI createNextLink(final String rawRequestUri, final int page, final int pageSize) throws ODataApplicationException { // Remove a maybe existing skiptoken, making sure that the query part is not empty. String nextlink = rawRequestUri.contains("?") ? @@ -85,9 +84,12 @@ public class ServerSidePagingHandler { nextlink += nextlink.contains("?") ? '&' : '?'; // Append the new skiptoken. + nextlink += SystemQueryOptionKind.SKIPTOKEN.toString().replace("$", "%24") // poor man's percent encoding + + '=' + + page + "%2A" + pageSize; // "%2A" is a percent-encoded asterisk + try { - return new URI(nextlink + Encoder.encode(SystemQueryOptionKind.SKIPTOKEN.toString()) + '=' - + Encoder.encode(page.toString() + '*' + pageSize)); + return new URI(nextlink); } catch (final URISyntaxException e) { throw new ODataApplicationException("Exception while constructing next link", HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, e);