[OLINGO-698] technical service supports preferences, part 2
Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
parent
0938f1179d
commit
afda326d75
|
@ -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<ODataBatchResponseItem> 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<ODataBatchResponseItem> 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<ODataBatchResponseItem> 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<ODataBatchResponseItem> 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<ODataBatchResponseItem> 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<ODataBatchResponseItem> 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<ClientEntity> createResponse = ((ODataEntityCreateResponse<ClientEntity>) 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<ODataBatchResponseItem> 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<ClientEntity>) response0).getBody()
|
||||
@SuppressWarnings("unchecked")
|
||||
ODataRetrieveResponse<ClientEntity> retrieveResponse = (ODataRetrieveResponse<ClientEntity>) 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<ClientEntity>) 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<ClientEntity>) 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<ClientEntity>) response4).getBody()
|
||||
@SuppressWarnings("unchecked")
|
||||
final ODataRetrieveResponse<ClientEntity> retrieveResponse2 = (ODataRetrieveResponse<ClientEntity>) response4;
|
||||
assertEquals(3.1415, retrieveResponse2.getBody()
|
||||
.getProperty("PropertyDouble")
|
||||
.getPrimitiveValue()
|
||||
.toValue());
|
||||
|
|
|
@ -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<ODataResponse> responses;
|
||||
private boolean isChangeSet;
|
||||
private final List<ODataResponse> 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<ODataResponse> 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<ODataResponse> 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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
|
||||
* (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
|
||||
* <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>,
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the percent-encoded UTF-8 representation of a String.</p>
|
||||
* <p>In order to avoid producing percent-encoded CESU-8 (as described in
|
||||
* the Unicode Consortium's <a href="http://www.unicode.org/reports/tr26/">
|
||||
* Technical Report #26</a>), this is done in two steps:
|
||||
* <ol>
|
||||
* <li>Re-encode the characters from their Java-internal UTF-16 representations
|
||||
* into their UTF-8 representations.</li>
|
||||
* <li>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 <code>%xx</code> representation are represented in one byte in UTF-8.</li>
|
||||
* </ol></p>
|
||||
* @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;
|
||||
}
|
||||
}
|
|
@ -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<String> 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
|
||||
|
|
|
@ -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 <code>null</code> 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);
|
||||
|
|
Loading…
Reference in New Issue