[OLINGO-698] technical service supports preferences, part 2

Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
Klaus Straubinger 2015-06-17 09:59:23 +02:00 committed by Christian Amend
parent 0938f1179d
commit afda326d75
6 changed files with 64 additions and 213 deletions

View File

@ -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());

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);