You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2013/09/24 14:42:49 UTC
[22/51] [partial] Refactored project structure
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseParser.java
deleted file mode 100644
index 84b90b0..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseParser.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.regex.MatchResult;
-import java.util.regex.Pattern;
-
-import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
-import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-
-public class BatchResponseParser {
-
- private static final String LF = "\n";
- private static final String REG_EX_OPTIONAL_WHITESPACE = "\\s?";
- private static final String REG_EX_ZERO_OR_MORE_WHITESPACES = "\\s*";
- private static final String ANY_CHARACTERS = ".*";
-
- private static final Pattern REG_EX_BLANK_LINE = Pattern.compile("(|" + REG_EX_ZERO_OR_MORE_WHITESPACES + ")");
- private static final Pattern REG_EX_HEADER = Pattern.compile("([a-zA-Z\\-]+):" + REG_EX_OPTIONAL_WHITESPACE + "(.*)"
- + REG_EX_ZERO_OR_MORE_WHITESPACES);
- private static final Pattern REG_EX_VERSION = Pattern.compile("(?:HTTP/[0-9]\\.[0-9])");
- private static final Pattern REG_EX_ANY_BOUNDARY_STRING = Pattern.compile("--" + ANY_CHARACTERS
- + REG_EX_ZERO_OR_MORE_WHITESPACES);
- private static final Pattern REG_EX_STATUS_LINE = Pattern.compile(REG_EX_VERSION + "\\s" + "([0-9]{3})\\s([\\S ]+)"
- + REG_EX_ZERO_OR_MORE_WHITESPACES);
- private static final Pattern REG_EX_BOUNDARY_PARAMETER = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE
- + "boundary=(\".*\"|.*)" + REG_EX_ZERO_OR_MORE_WHITESPACES);
- private static final Pattern REG_EX_CONTENT_TYPE = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE
- + HttpContentType.MULTIPART_MIXED);
-
- private static final String REG_EX_BOUNDARY =
- "([a-zA-Z0-9_\\-\\.'\\+]{1,70})|\"([a-zA-Z0-9_\\-\\.'\\+ \\(\\)" +
- ",/:=\\?]{1,69}[a-zA-Z0-9_\\-\\.'\\+\\(\\),/:=\\?])\""; // See RFC 2046
-
- private String contentTypeMime;
- private String boundary;
- private String currentContentId;
- private int currentLineNumber = 0;
-
- public BatchResponseParser(final String contentType) {
- contentTypeMime = contentType;
- }
-
- public List<BatchSingleResponse> parse(final InputStream in) throws BatchException {
- Scanner scanner = new Scanner(in, BatchHelper.DEFAULT_ENCODING).useDelimiter(LF);
- List<BatchSingleResponse> responseList;
- try {
- responseList = Collections.unmodifiableList(parseBatchResponse(scanner));
- } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
- scanner.close();
- try {
- in.close();
- } catch (IOException e) {
- throw new ODataRuntimeException(e);
- }
- }
- return responseList;
- }
-
- private List<BatchSingleResponse> parseBatchResponse(final Scanner scanner) throws BatchException {
- List<BatchSingleResponse> responses = new ArrayList<BatchSingleResponse>();
- if (contentTypeMime != null) {
- boundary = getBoundary(contentTypeMime);
- parsePreamble(scanner);
- final String closeDelimiter = "--" + boundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES;
- while (scanner.hasNext() && !scanner.hasNext(closeDelimiter)) {
- responses.addAll(parseMultipart(scanner, boundary, false));
- }
- if (scanner.hasNext(closeDelimiter)) {
- scanner.next(closeDelimiter);
- currentLineNumber++;
- } else {
- throw new BatchException(BatchException.MISSING_CLOSE_DELIMITER.addContent(currentLineNumber));
- }
- } else {
- throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
- }
- return responses;
-
- }
-
- // The method parses additional information prior to the first boundary delimiter line
- private void parsePreamble(final Scanner scanner) {
- while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
- scanner.next();
- currentLineNumber++;
- }
- }
-
- private List<BatchSingleResponse> parseMultipart(final Scanner scanner, final String boundary,
- final boolean isChangeSet) throws BatchException {
- Map<String, String> mimeHeaders = new HashMap<String, String>();
- List<BatchSingleResponse> responses = new ArrayList<BatchSingleResponse>();
- if (scanner.hasNext("--" + boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
- scanner.next();
- currentLineNumber++;
- mimeHeaders = parseMimeHeaders(scanner);
- currentContentId = mimeHeaders.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
-
- final String contentType = mimeHeaders.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
- if (contentType == null) {
- throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
- }
- if (isChangeSet) {
- if (HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
- validateEncoding(mimeHeaders.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
- parseNewLine(scanner);// mandatory
- BatchSingleResponseImpl response = parseResponse(scanner, isChangeSet);
- responses.add(response);
- } else {
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.APPLICATION_HTTP));
- }
- } else {
- if (HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
- validateEncoding(mimeHeaders.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
- parseNewLine(scanner);// mandatory
- BatchSingleResponseImpl response = parseResponse(scanner, isChangeSet);
- responses.add(response);
- } else if (contentType.matches(REG_EX_OPTIONAL_WHITESPACE + HttpContentType.MULTIPART_MIXED + ANY_CHARACTERS)) {
- String changeSetBoundary = getBoundary(contentType);
- if (boundary.equals(changeSetBoundary)) {
- throw new BatchException(BatchException.INVALID_CHANGESET_BOUNDARY.addContent(currentLineNumber));
- }
- parseNewLine(scanner);// mandatory
- Pattern changeSetCloseDelimiter =
- Pattern.compile("--" + changeSetBoundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES);
- while (!scanner.hasNext(changeSetCloseDelimiter)) {
- responses.addAll(parseMultipart(scanner, changeSetBoundary, true));
- }
- scanner.next(changeSetCloseDelimiter);
- currentLineNumber++;
- parseNewLine(scanner);
- } else {
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED
- + " or " + HttpContentType.APPLICATION_HTTP));
- }
- }
- } else if (scanner.hasNext(boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
- currentLineNumber++;
- throw new BatchException(BatchException.INVALID_BOUNDARY_DELIMITER.addContent(currentLineNumber));
- } else if (scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
- currentLineNumber++;
- throw new BatchException(BatchException.NO_MATCH_WITH_BOUNDARY_STRING.addContent(boundary).addContent(
- currentLineNumber));
- } else {
- currentLineNumber++;
- throw new BatchException(BatchException.MISSING_BOUNDARY_DELIMITER.addContent(currentLineNumber));
- }
- return responses;
-
- }
-
- private BatchSingleResponseImpl parseResponse(final Scanner scanner, final boolean isChangeSet)
- throws BatchException {
- BatchSingleResponseImpl response = new BatchSingleResponseImpl();
- if (scanner.hasNext(REG_EX_STATUS_LINE)) {
- scanner.next(REG_EX_STATUS_LINE);
- currentLineNumber++;
- final String statusCode;
- final String statusInfo;
- MatchResult result = scanner.match();
- if (result.groupCount() == 2) {
- statusCode = result.group(1);
- statusInfo = result.group(2);
- } else {
- currentLineNumber++;
- throw new BatchException(BatchException.INVALID_STATUS_LINE.addContent(scanner.next()).addContent(
- currentLineNumber));
- }
-
- Map<String, String> headers = parseResponseHeaders(scanner);
- parseNewLine(scanner);
- String contentLengthHeader = getHeaderValue(headers, HttpHeaders.CONTENT_LENGTH);
- String body =
- (contentLengthHeader != null) ? parseBody(scanner, Integer.parseInt(contentLengthHeader))
- : parseBody(scanner);
- response.setStatusCode(statusCode);
- response.setStatusInfo(statusInfo);
- response.setHeaders(headers);
- response.setContentId(currentContentId);
- response.setBody(body);
- } else {
- currentLineNumber++;
- throw new BatchException(BatchException.INVALID_STATUS_LINE.addContent(scanner.next()).addContent(
- currentLineNumber));
- }
- return response;
- }
-
- private void validateEncoding(final String encoding) throws BatchException {
- if (!BatchHelper.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
- throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
- }
- }
-
- private Map<String, String> parseMimeHeaders(final Scanner scanner) throws BatchException {
- Map<String, String> headers = new HashMap<String, String>();
- while (scanner.hasNext() && !(scanner.hasNext(REG_EX_BLANK_LINE))) {
- if (scanner.hasNext(REG_EX_HEADER)) {
- scanner.next(REG_EX_HEADER);
- currentLineNumber++;
- MatchResult result = scanner.match();
- if (result.groupCount() == 2) {
- String headerName = result.group(1).trim().toLowerCase(Locale.ENGLISH);
- String headerValue = result.group(2).trim();
- headers.put(headerName, headerValue);
- }
- } else {
- throw new BatchException(BatchException.INVALID_HEADER.addContent(scanner.next()));
- }
- }
- return headers;
- }
-
- private Map<String, String> parseResponseHeaders(final Scanner scanner) throws BatchException {
- Map<String, String> headers = new HashMap<String, String>();
- while (scanner.hasNext() && !scanner.hasNext(REG_EX_BLANK_LINE)) {
- if (scanner.hasNext(REG_EX_HEADER)) {
- scanner.next(REG_EX_HEADER);
- currentLineNumber++;
- MatchResult result = scanner.match();
- if (result.groupCount() == 2) {
- String headerName = result.group(1).trim();
- String headerValue = result.group(2).trim();
- if (BatchHelper.HTTP_CONTENT_ID.equalsIgnoreCase(headerName)) {
- if (currentContentId == null) {
- currentContentId = headerValue;
- }
- } else {
- headers.put(headerName, headerValue);
- }
- }
- } else {
- currentLineNumber++;
- throw new BatchException(BatchException.INVALID_HEADER.addContent(scanner.next())
- .addContent(currentLineNumber));
- }
- }
- return headers;
- }
-
- private String getHeaderValue(final Map<String, String> headers, final String headerName) {
- for (Map.Entry<String, String> header : headers.entrySet()) {
- if (headerName.equalsIgnoreCase(header.getKey())) {
- return header.getValue();
- }
- }
- return null;
- }
-
- private String parseBody(final Scanner scanner) {
- StringBuilder body = null;
- while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
- if (!scanner.hasNext(REG_EX_ZERO_OR_MORE_WHITESPACES)) {
- if (body == null) {
- body = new StringBuilder(scanner.next());
- } else {
- body.append(LF).append(scanner.next());
- }
- } else {
- scanner.next();
- }
- currentLineNumber++;
- }
- String responseBody = body != null ? body.toString() : null;
- return responseBody;
- }
-
- private String parseBody(final Scanner scanner, final int contentLength) {
- StringBuilder body = null;
- int length = 0;
- while (scanner.hasNext() && length < contentLength) {
- if (!scanner.hasNext(REG_EX_ZERO_OR_MORE_WHITESPACES)) {
- String nextLine = scanner.next();
- length += BatchHelper.getBytes(nextLine).length;
- if (body == null) {
- body = new StringBuilder(nextLine);
- } else {
- body.append(LF).append(nextLine);
- }
- } else {
- scanner.next();
- }
- currentLineNumber++;
- if (scanner.hasNext() && scanner.hasNext(REG_EX_BLANK_LINE)) {
- scanner.next();
- currentLineNumber++;
- }
- }
- String responseBody = body != null ? body.toString() : null;
- return responseBody;
- }
-
- private String getBoundary(final String contentType) throws BatchException {
- Scanner contentTypeScanner = new Scanner(contentType).useDelimiter(";\\s?");
- if (contentTypeScanner.hasNext(REG_EX_CONTENT_TYPE)) {
- contentTypeScanner.next(REG_EX_CONTENT_TYPE);
- } else {
- contentTypeScanner.close();
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED));
- }
- if (contentTypeScanner.hasNext(REG_EX_BOUNDARY_PARAMETER)) {
- contentTypeScanner.next(REG_EX_BOUNDARY_PARAMETER);
- MatchResult result = contentTypeScanner.match();
- contentTypeScanner.close();
- if (result.groupCount() == 1 && result.group(1).trim().matches(REG_EX_BOUNDARY)) {
- return trimQuota(result.group(1).trim());
- } else {
- throw new BatchException(BatchException.INVALID_BOUNDARY);
- }
- } else {
- contentTypeScanner.close();
- throw new BatchException(BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE);
- }
- }
-
- private void parseNewLine(final Scanner scanner) throws BatchException {
- if (scanner.hasNext() && scanner.hasNext(REG_EX_BLANK_LINE)) {
- scanner.next();
- currentLineNumber++;
- } else {
- currentLineNumber++;
- if (scanner.hasNext()) {
- throw new BatchException(BatchException.MISSING_BLANK_LINE.addContent(scanner.next()).addContent(
- currentLineNumber));
- } else {
- throw new BatchException(BatchException.TRUNCATED_BODY.addContent(currentLineNumber));
-
- }
- }
- }
-
- private String trimQuota(String boundary) {
- if (boundary.matches("\".*\"")) {
- boundary = boundary.replace("\"", "");
- }
- boundary = boundary.replaceAll("\\)", "\\\\)");
- boundary = boundary.replaceAll("\\(", "\\\\(");
- boundary = boundary.replaceAll("\\?", "\\\\?");
- boundary = boundary.replaceAll("\\+", "\\\\+");
- return boundary;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
deleted file mode 100644
index 3d6e6db..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-import java.util.List;
-
-import org.apache.olingo.odata2.api.batch.BatchResponsePart;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-
-public class BatchResponsePartImpl extends BatchResponsePart {
- private List<ODataResponse> responses;
- private boolean isChangeSet;
-
- @Override
- public List<ODataResponse> getResponses() {
- return responses;
- }
-
- @Override
- public boolean isChangeSet() {
- return isChangeSet;
- }
-
- public class BatchResponsePartBuilderImpl extends BatchResponsePartBuilder {
- private List<ODataResponse> responses;
- private boolean isChangeSet;
-
- @Override
- public BatchResponsePart build() {
- BatchResponsePartImpl.this.responses = responses;
- BatchResponsePartImpl.this.isChangeSet = isChangeSet;
- return BatchResponsePartImpl.this;
- }
-
- @Override
- public BatchResponsePartBuilder responses(final List<ODataResponse> responses) {
- this.responses = responses;
- return this;
- }
-
- @Override
- public BatchResponsePartBuilder changeSet(final boolean isChangeSet) {
- this.isChangeSet = isChangeSet;
- return this;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
deleted file mode 100644
index be189d3..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.batch.BatchResponsePart;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
-import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
-import org.apache.olingo.odata2.api.exception.ODataMessageException;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-
-public class BatchResponseWriter {
- private static final String COLON = ":";
- private static final String SP = " ";
- private static final String LF = "\r\n";
- private ResponseWriter writer = new ResponseWriter();
-
- public ODataResponse writeResponse(final List<BatchResponsePart> batchResponseParts) throws BatchException {
- String boundary = BatchHelper.generateBoundary("batch");
- appendResponsePart(batchResponseParts, boundary);
- String batchResponseBody = writer.toString();
- return ODataResponse.entity(batchResponseBody).status(HttpStatusCodes.ACCEPTED)
- .header(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + "; boundary=" + boundary)
- .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(writer.length()))
- .build();
- }
-
- private void appendChangeSet(final BatchResponsePart batchResponsePart) throws BatchException {
- String boundary = BatchHelper.generateBoundary("changeset");
- writer.append(HttpHeaders.CONTENT_TYPE).append(COLON).append(SP)
- .append("multipart/mixed; boundary=" + boundary).append(LF).append(LF);
- for (ODataResponse response : batchResponsePart.getResponses()) {
- writer.append("--").append(boundary).append(LF);
- appendResponsePartBody(response);
- }
- writer.append("--").append(boundary).append("--").append(LF).append(LF);
- }
-
- private void appendResponsePart(final List<BatchResponsePart> batchResponseParts, final String boundary)
- throws BatchException {
- for (BatchResponsePart batchResponsePart : batchResponseParts) {
- writer.append("--").append(boundary).append(LF);
- if (batchResponsePart.isChangeSet()) {
- appendChangeSet(batchResponsePart);
- } else {
- ODataResponse response = batchResponsePart.getResponses().get(0);
- appendResponsePartBody(response);
- }
- }
- writer.append("--").append(boundary).append("--");
- }
-
- private void appendResponsePartBody(final ODataResponse response) throws BatchException {
- writer.append(HttpHeaders.CONTENT_TYPE).append(COLON).append(SP)
- .append(HttpContentType.APPLICATION_HTTP).append(LF);
- writer.append(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING).append(COLON).append(SP)
- .append(BatchHelper.BINARY_ENCODING).append(LF);
- if (response.getHeader(BatchHelper.MIME_HEADER_CONTENT_ID) != null) {
- writer.append(BatchHelper.HTTP_CONTENT_ID).append(COLON).append(SP)
- .append(response.getHeader(BatchHelper.MIME_HEADER_CONTENT_ID)).append(LF);
- }
- writer.append(LF);
- writer.append("HTTP/1.1").append(SP).append(String.valueOf(response.getStatus().getStatusCode())).append(SP)
- .append(response.getStatus().getInfo()).append(LF);
- appendHeader(response);
- if (!HttpStatusCodes.NO_CONTENT.equals(response.getStatus())) {
- String body;
- if (response.getEntity() instanceof InputStream) {
- InputStream in = (InputStream) response.getEntity();
- body = readBody(in);
- } else {
- body = response.getEntity().toString();
- }
- writer.append(HttpHeaders.CONTENT_LENGTH).append(COLON).append(SP)
- .append(String.valueOf(BatchHelper.getBytes(body).length)).append(LF).append(LF);
- writer.append(body);
- }
- writer.append(LF).append(LF);
- }
-
- private void appendHeader(final ODataResponse response) {
- for (String name : response.getHeaderNames()) {
- if (!BatchHelper.MIME_HEADER_CONTENT_ID.equalsIgnoreCase(name)
- && !BatchHelper.REQUEST_HEADER_CONTENT_ID.equalsIgnoreCase(name)) {
- writer.append(name).append(COLON).append(SP).append(response.getHeader(name)).append(LF);
- } else if (BatchHelper.REQUEST_HEADER_CONTENT_ID.equalsIgnoreCase(name)) {
- writer.append(BatchHelper.HTTP_CONTENT_ID).append(COLON).append(SP)
- .append(response.getHeader(name)).append(LF);
- }
- }
- }
-
- private String readBody(final InputStream in) throws BatchException {
- byte[] tmp = new byte[2048];
- int count;
- BatchException cachedException = null;
- StringBuffer b = new StringBuffer();
- try {
- count = in.read(tmp);
- while (count >= 0) {
- b.append(new String(tmp, 0, count, BatchHelper.DEFAULT_ENCODING));
- count = in.read(tmp);
- }
- } catch (IOException e) {
- cachedException = new BatchException(ODataMessageException.COMMON, e);
- throw cachedException;
- } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
- try {
- in.close();
- } catch (IOException e) {
- if (cachedException != null) {
- throw cachedException;
- }
- }
- }
- return b.toString();
- }
-
- private static class ResponseWriter {
- private StringBuilder sb = new StringBuilder();
- private int length = 0;
-
- public ResponseWriter append(final String content) {
- length += BatchHelper.getBytes(content).length;
- sb.append(content);
- return this;
- }
-
- public int length() {
- return length;
- }
-
- @Override
- public String toString() {
- return sb.toString();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchSingleResponseImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchSingleResponseImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchSingleResponseImpl.java
deleted file mode 100644
index 85c09ca..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchSingleResponseImpl.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
-
-public class BatchSingleResponseImpl implements BatchSingleResponse {
-
- private String statusCode;
- private String statusInfo;
- private String body;
- private Map<String, String> headers = new HashMap<String, String>();
- private String contentId;
-
- @Override
- public String getStatusCode() {
- return statusCode;
- }
-
- @Override
- public String getStatusInfo() {
- return statusInfo;
- }
-
- @Override
- public String getBody() {
- return body;
- }
-
- @Override
- public Map<String, String> getHeaders() {
- return headers;
- }
-
- @Override
- public String getContentId() {
- return contentId;
- }
-
- @Override
- public String getHeader(final String name) {
- return headers.get(name);
- }
-
- @Override
- public Set<String> getHeaderNames() {
- return headers.keySet();
- }
-
- public void setStatusCode(final String statusCode) {
- this.statusCode = statusCode;
- }
-
- public void setStatusInfo(final String statusInfo) {
- this.statusInfo = statusInfo;
- }
-
- public void setBody(final String body) {
- this.body = body;
- }
-
- public void setHeaders(final Map<String, String> headers) {
- this.headers = headers;
- }
-
- public void setContentId(final String contentId) {
- this.contentId = contentId;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
deleted file mode 100644
index 6a797ad..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
+++ /dev/null
@@ -1,933 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.commons;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-/**
- * Internally used {@link ContentType} for OData library.
- *
- * For more details on format and content of a {@link ContentType} see
- * <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7
- * (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html)</code>.
- * <pre>
- * <code>
- * media-type = type "/" subtype *( ";" parameter )
- * type = token
- * subtype = token
- * </code>
- * </pre>
- *
- * Especially for <code>Accept</code> Header as defined in
- * <code>RFC 2616 chapter 14.1 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)</code>:
- * <pre>
- * <code>
- * Accept = "Accept" ":"
- * #( media-range [ accept-params ] )
- * media-range = ( "* /*"
- * | ( type "/" "*" )
- * | ( type "/" subtype )
- * ) *( ";" parameter )
- * accept-params = ";" "q" "=" qvalue *( accept-extension )
- * accept-extension = ";" token [ "=" ( token | quoted-string ) ]
- * </code>
- * </pre>
- *
- * Especially for <code>Content-Type</code> Header as defined in
- * <code>RFC 2616 chapter 14.7 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)</code>:
- * <pre>
- * <code>
- * Content-Type = "Content-Type" ":" media-type
- * </code>
- * </pre>
- *
- * Once created a {@link ContentType} is <b>IMMUTABLE</b>.
- *
- *
- */
-public class ContentType {
-
- public enum ODataFormat {
- ATOM, XML, JSON, MIME, CUSTOM
- }
-
- private static final Set<String> KNOWN_MIME_TYPES = new HashSet<String>();
- static {
- KNOWN_MIME_TYPES.add("audio");
- KNOWN_MIME_TYPES.add("image");
- KNOWN_MIME_TYPES.add("video");
- KNOWN_MIME_TYPES.add("multipart");
- KNOWN_MIME_TYPES.add("text");
- }
-
- private static final Comparator<String> Q_PARAMETER_COMPARATOR = new Comparator<String>() {
- @Override
- public int compare(final String o1, final String o2) {
- Float f1 = parseQParameterValue(o1);
- Float f2 = parseQParameterValue(o2);
- return f2.compareTo(f1);
- }
- };
-
- private static final char WHITESPACE_CHAR = ' ';
- private static final String PARAMETER_SEPARATOR = ";";
- private static final String PARAMETER_KEY_VALUE_SEPARATOR = "=";
- private static final String TYPE_SUBTYPE_SEPARATOR = "/";
- private static final String MEDIA_TYPE_WILDCARD = "*";
- private static final String VERBOSE = "verbose";
-
- public static final String PARAMETER_CHARSET = "charset";
- public static final String PARAMETER_ODATA = "odata";
- public static final String PARAMETER_Q = "q";
- public static final String PARAMETER_TYPE = "type";
- public static final String CHARSET_UTF_8 = "utf-8";
-
- private static final Pattern Q_PARAMETER_VALUE_PATTERN = Pattern.compile("1|0|1\\.0{1,3}|0\\.\\d{1,3}");
-
- public static final ContentType WILDCARD = new ContentType(MEDIA_TYPE_WILDCARD, MEDIA_TYPE_WILDCARD);
-
- public static final ContentType APPLICATION_XML = new ContentType("application", "xml", ODataFormat.XML);
- public static final ContentType APPLICATION_XML_CS_UTF_8 = ContentType.create(APPLICATION_XML, PARAMETER_CHARSET,
- CHARSET_UTF_8);
- public static final ContentType APPLICATION_ATOM_XML = new ContentType("application", "atom+xml", ODataFormat.ATOM);
- public static final ContentType APPLICATION_ATOM_XML_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML,
- PARAMETER_CHARSET, CHARSET_UTF_8);
- public static final ContentType APPLICATION_ATOM_XML_ENTRY = new ContentType("application", "atom+xml",
- ODataFormat.ATOM, parameterMap(PARAMETER_TYPE, "entry"));
- public static final ContentType APPLICATION_ATOM_XML_ENTRY_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML_ENTRY,
- PARAMETER_CHARSET, CHARSET_UTF_8);
- public static final ContentType APPLICATION_ATOM_XML_FEED = new ContentType("application", "atom+xml",
- ODataFormat.ATOM, parameterMap(PARAMETER_TYPE, "feed"));
- public static final ContentType APPLICATION_ATOM_XML_FEED_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML_FEED,
- PARAMETER_CHARSET, CHARSET_UTF_8);
- public static final ContentType APPLICATION_ATOM_SVC =
- new ContentType("application", "atomsvc+xml", ODataFormat.ATOM);
- public static final ContentType APPLICATION_ATOM_SVC_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_SVC,
- PARAMETER_CHARSET, CHARSET_UTF_8);
- public static final ContentType APPLICATION_JSON = new ContentType("application", "json", ODataFormat.JSON);
- public static final ContentType APPLICATION_JSON_ODATA_VERBOSE = ContentType.create(APPLICATION_JSON,
- PARAMETER_ODATA, VERBOSE);
- public static final ContentType APPLICATION_JSON_CS_UTF_8 = ContentType.create(APPLICATION_JSON, PARAMETER_CHARSET,
- CHARSET_UTF_8);
- public static final ContentType APPLICATION_OCTET_STREAM = new ContentType("application", "octet-stream");
- public static final ContentType TEXT_PLAIN = new ContentType("text", "plain");
- public static final ContentType TEXT_PLAIN_CS_UTF_8 = ContentType
- .create(TEXT_PLAIN, PARAMETER_CHARSET, CHARSET_UTF_8);
- public static final ContentType MULTIPART_MIXED = new ContentType("multipart", "mixed");
-
- private final String type;
- private final String subtype;
- private final Map<String, String> parameters;
- private final ODataFormat odataFormat;
-
- private ContentType(final String type) {
- if (type == null) {
- throw new IllegalArgumentException("Type parameter MUST NOT be null.");
- }
- odataFormat = ODataFormat.CUSTOM;
- this.type = validateType(type);
- subtype = null;
- parameters = Collections.emptyMap();
- }
-
- private ContentType(final String type, final String subtype) {
- this(type, subtype, ODataFormat.CUSTOM, null);
- }
-
- private ContentType(final String type, final String subtype, final ODataFormat odataFormat) {
- this(type, subtype, odataFormat, null);
- }
-
- private ContentType(final String type, final String subtype, final ODataFormat odataFormat,
- final Map<String, String> parameters) {
- if ((type == null || MEDIA_TYPE_WILDCARD.equals(type)) && !MEDIA_TYPE_WILDCARD.equals(subtype)) {
- throw new IllegalArgumentException("Illegal combination of WILDCARD type with NONE WILDCARD subtype.");
- }
- this.odataFormat = odataFormat;
- this.type = validateType(type);
- this.subtype = validateType(subtype);
-
- if (parameters == null) {
- this.parameters = Collections.emptyMap();
- } else {
- this.parameters = new TreeMap<String, String>(new Comparator<String>() {
- @Override
- public int compare(final String o1, final String o2) {
- return o1.compareToIgnoreCase(o2);
- }
- });
- this.parameters.putAll(parameters);
- this.parameters.remove(PARAMETER_Q);
- }
- }
-
- private String validateType(final String type) {
- if (type == null || type.isEmpty()) {
- return MEDIA_TYPE_WILDCARD;
- }
- int len = type.length();
- for (int i = 0; i < len; i++) {
- if (type.charAt(i) == WHITESPACE_CHAR) {
- throw new IllegalArgumentException("Illegal whitespace found for type '" + type + "'.");
- }
- }
- return type;
- }
-
- /**
- * Validates if given <code>format</code> is parseable and can be used as input for {@link #create(String)} method.
- * @param format to be validated string
- * @return <code>true</code> if format is parseable otherwise <code>false</code>
- */
- public static boolean isParseable(final String format) {
- try {
- return ContentType.create(format) != null;
- } catch (IllegalArgumentException e) {
- return false;
- }
- }
-
- /**
- * Validates if given <code>format</code> is parseable and can be used as input for {@link #create(String)} method.
- * @param format to be validated string
- * @return <code>true</code> if format is parseable otherwise <code>false</code>
- */
- public static boolean isParseableAsCustom(final String format) {
- try {
- return ContentType.create(format) != null;
- } catch (IllegalArgumentException e) {
- return false;
- }
- }
-
- /**
- * Creates a content type from type and subtype
- * @param type
- * @param subtype
- * @return a new <code>ContentType</code> object
- */
- public static ContentType create(final String type, final String subtype) {
- return new ContentType(type, subtype, mapToODataFormat(type, subtype), null);
- }
-
- /**
- *
- * @param type
- * @param subtype
- * @param parameters
- * @return a new <code>ContentType</code> object
- */
- public static ContentType create(final String type, final String subtype, final Map<String, String> parameters) {
- return new ContentType(type, subtype, mapToODataFormat(type, subtype), parameters);
- }
-
- /**
- *
- * @param contentType
- * @param parameterKey
- * @param parameterValue
- * @return a new <code>ContentType</code> object
- */
- public static ContentType
- create(final ContentType contentType, final String parameterKey, final String parameterValue) {
- ContentType ct =
- new ContentType(contentType.type, contentType.subtype, contentType.odataFormat, contentType.parameters);
- ct.parameters.put(parameterKey, parameterValue);
- return ct;
- }
-
- /**
- * Create a {@link ContentType} based on given input string (<code>format</code>).
- *
- * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
- * This format is used as
- * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
- * and
- * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>
- *
- * @param format a string in format as defined in <code>RFC 2616 section 3.7</code>
- * @return a new <code>ContentType</code> object
- * @throws IllegalArgumentException if input string is not parseable
- */
- public static ContentType create(final String format) {
- if (format == null) {
- throw new IllegalArgumentException("Parameter format MUST NOT be NULL.");
- }
-
- // split 'types' and 'parameters'
- String[] typesAndParameters = format.split(PARAMETER_SEPARATOR, 2);
- String types = typesAndParameters[0];
- String parameters = (typesAndParameters.length > 1 ? typesAndParameters[1] : null);
- //
- Map<String, String> parametersMap = parseParameters(parameters);
- //
- if (types.contains(TYPE_SUBTYPE_SEPARATOR)) {
- String[] tokens = types.split(TYPE_SUBTYPE_SEPARATOR);
- if (tokens.length == 2) {
- if (tokens[0] == null || tokens[0].isEmpty()) {
- throw new IllegalArgumentException("No type found in format '" + format + "'.");
- } else if (tokens[1] == null || tokens[1].isEmpty()) {
- throw new IllegalArgumentException("No subtype found in format '" + format + "'.");
- } else {
- return create(tokens[0], tokens[1], parametersMap);
- }
- } else {
- throw new IllegalArgumentException("Too many '" + TYPE_SUBTYPE_SEPARATOR + "' in format '" + format + "'.");
- }
- } else if (MEDIA_TYPE_WILDCARD.equals(types)) {
- return ContentType.WILDCARD;
- } else {
- throw new IllegalArgumentException("No separator '" + TYPE_SUBTYPE_SEPARATOR + "' was found in format '" + format
- + "'.");
- }
- }
-
- /**
- * Create a {@link ContentType} based on given input string (<code>format</code>).
- *
- * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
- * and {@link ContentType} with {@link ODataFormat#CUSTOM}.
- *
- * The <code>Media Type</code> format can be used as
- * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
- * and
- * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>.
- * The {@link ContentType} with {@link ODataFormat#CUSTOM} can only be used as <code>$format</code> system query
- * option
- * (as defined
- * http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/#47_Format_System_Query_Option_format).
- *
- * @param format a string in format as defined in <code>RFC 2616 section 3.7</code>
- * @return a new <code>ContentType</code> object
- * @throws IllegalArgumentException if input string is not parseable
- */
- public static ContentType createAsCustom(final String format) {
- ContentType parsedContentType = parse(format);
- if (parsedContentType == null) {
- return new ContentType(format);
- }
- return parsedContentType;
- }
-
- /**
- * Create a list of {@link ContentType} based on given input strings (<code>contentTypes</code>).
- *
- * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
- * This format is used as
- * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
- * and
- * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>.
- * <p>
- * If one of the given strings can not be parsed an exception is thrown (hence no list is returned with the parseable
- * strings).
- * </p>
- *
- * @param contentTypeStrings a list of strings in format as defined in <code>RFC 2616 section 3.7</code>
- * @return a list of new <code>ContentType</code> object
- * @throws IllegalArgumentException if one of the given input string is not parseable this exceptions is thrown
- */
- public static List<ContentType> create(final List<String> contentTypeStrings) {
- List<ContentType> contentTypes = new ArrayList<ContentType>(contentTypeStrings.size());
- for (String contentTypeString : contentTypeStrings) {
- contentTypes.add(create(contentTypeString));
- }
- return contentTypes;
- }
-
- /**
- * Create a list of {@link ContentType} based on given input strings (<code>contentTypes</code>).
- *
- * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
- * and {@link ContentType} with {@link ODataFormat#CUSTOM}.
- *
- * The <code>Media Type</code> format can be used as
- * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
- * and
- * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>.
- * The {@link ContentType} with {@link ODataFormat#CUSTOM} can only be used as <code>$format</code> system query
- * option
- * (as defined
- * http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/#47_Format_System_Query_Option_format).
- *
- * @param contentTypeStrings a list of strings in format as defined in <code>RFC 2616 section 3.7</code> or
- * as defined
- * http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/#47_Format_System_Query_Option_format
- * @return a list of new <code>ContentType</code> object
- * @throws IllegalArgumentException if one of the given input string is not parseable this exceptions is thrown
- */
- public static List<ContentType> createAsCustom(final List<String> contentTypeStrings) {
- List<ContentType> contentTypes = new ArrayList<ContentType>(contentTypeStrings.size());
- for (String contentTypeString : contentTypeStrings) {
- contentTypes.add(createAsCustom(contentTypeString));
- }
- return contentTypes;
- }
-
- /**
- * Parses the given input string (<code>format</code>) and returns created {@link ContentType} if input was valid or
- * return <code>NULL</code> if
- * input was not parseable.
- *
- * For the definition of the supported format see {@link #create(String)}.
- *
- * @param format a string in format as defined in <code>RFC 2616 section 3.7</code>
- * @return a new <code>ContentType</code> object
- */
- public static ContentType parse(final String format) {
- try {
- return ContentType.create(format);
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
-
- /**
- * Sort given list (which must contains content type formated string) for their {@value #PARAMETER_Q} value
- * as defined in <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">RFC 2616 section 4.1</a> and
- * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9">RFC 2616 Section 3.9</a>.
- *
- * <b>Attention:</b> For invalid values a {@value #PARAMETER_Q} value from <code>-1</code> is used for sorting.
- *
- * @param toSort list which is sorted and hence re-arranged
- */
- public static void sortForQParameter(final List<String> toSort) {
- Collections.sort(toSort, ContentType.Q_PARAMETER_COMPARATOR);
- }
-
- /**
- * Map combination of type/subtype to corresponding {@link ODataFormat}.
- *
- * @param type type which is used for mapping
- * @param subtype subtype which is used for mapping
- * @return corresponding {@link ODataFormat} or {@link ODataFormat#CUSTOM} if none specific format is available.
- */
- private static ODataFormat mapToODataFormat(final String type, final String subtype) {
- ODataFormat odataFormat = ODataFormat.CUSTOM;
- if (type.contains("application")) {
- if (subtype.contains("atom")) {
- odataFormat = ODataFormat.ATOM;
- } else if (subtype.contains("xml")) {
- odataFormat = ODataFormat.XML;
- } else if (subtype.contains("json")) {
- odataFormat = ODataFormat.JSON;
- }
- } else if (KNOWN_MIME_TYPES.contains(type)) {
- odataFormat = ODataFormat.MIME;
- }
- return odataFormat;
- }
-
- /**
- * Maps content of array into map.
- * Therefore it must be an combination of <code>key</code> followed by the <code>value</code> in the array.
- *
- * @param content content which is added to {@link Map}.
- * @return a new <code>ContentType</code> object
- */
- private static Map<String, String> parameterMap(final String... content) {
- Map<String, String> map = new HashMap<String, String>();
- for (int i = 0; i < content.length - 1; i += 2) {
- String key = content[i];
- String value = content[i + 1];
- map.put(key, value);
- }
- return map;
- }
-
- /**
- * Valid input are <code>;</code> separated <code>key=value</code> pairs
- * without spaces between key and value.
- * <b>Attention:</b> <code>q</code> parameter is validated but not added to result map
- *
- * <p>
- * See RFC 2616:
- * The type, subtype, and parameter attribute names are case-insensitive.
- * Parameter values might or might not be case-sensitive, depending on the
- * semantics of the parameter name. <b>Linear white space (LWS) MUST NOT be used
- * between the type and subtype, nor between an attribute and its value</b>.
- * </p>
- *
- * @param parameters
- * @return Map with keys mapped to values
- */
- private static Map<String, String> parseParameters(final String parameters) {
- Map<String, String> parameterMap = new HashMap<String, String>();
- if (parameters != null) {
- String[] splittedParameters = parameters.split(PARAMETER_SEPARATOR);
- for (String parameter : splittedParameters) {
- String[] keyValue = parameter.split(PARAMETER_KEY_VALUE_SEPARATOR);
- String key = keyValue[0].trim().toLowerCase(Locale.ENGLISH);
- String value = keyValue.length > 1 ? keyValue[1] : null;
- if (value != null && isLws(value.charAt(0))) {
- throw new IllegalArgumentException("Value of parameter '" + key + "' starts with a LWS ('" + parameters
- + "').");
- }
- if (PARAMETER_Q.equals(key.toLowerCase(Locale.US))) {
- // q parameter is only validated but not added
- if (!Q_PARAMETER_VALUE_PATTERN.matcher(value).matches()) {
- throw new IllegalArgumentException("Value of 'q' parameter is not valid (q='" + value + "').");
- }
- } else {
- parameterMap.put(key, value);
- }
- }
- }
- return parameterMap;
- }
-
- /**
- * Parse value of {@value #PARAMETER_Q} <code>parameter</code> out of content type/parameters.
- * If no {@value #PARAMETER_Q} <code>parameter</code> is in <code>content type/parameters</code> parameter found
- * <code>1</code> is returned.
- * If {@value #PARAMETER_Q} <code>parameter</code> is invalid <code>-1</code> is returned.
- *
- * @param contentType parameter which is parsed for {@value #PARAMETER_Q} <code>parameter</code> value
- * @return value of {@value #PARAMETER_Q} <code>parameter</code> or <code>1</code> or <code>-1</code>
- */
- private static Float parseQParameterValue(final String contentType) {
- if (contentType != null) {
- String[] splittedParameters = contentType.split(PARAMETER_SEPARATOR);
- for (String parameter : splittedParameters) {
- String[] keyValue = parameter.split(PARAMETER_KEY_VALUE_SEPARATOR);
- String key = keyValue[0].trim().toLowerCase(Locale.ENGLISH);
- if (PARAMETER_Q.equalsIgnoreCase(key)) {
- String value = keyValue.length > 1 ? keyValue[1] : null;
- if (Q_PARAMETER_VALUE_PATTERN.matcher(value).matches()) {
- return Float.valueOf(value);
- }
- return Float.valueOf(-1);
- }
- }
- }
- return Float.valueOf(1);
- }
-
- /**
- * Check if parameter with key value is a allowed parameter.
- *
- * @param key
- * @return
- */
- private static boolean isParameterAllowed(final String key) {
- return key != null && !PARAMETER_Q.equals(key.toLowerCase(Locale.US));
- }
-
- /**
- * Validate if given character is a linear whitepace (includes <code>horizontal-tab, linefeed, carriage return and
- * space</code>).
- *
- * @param character to be checked
- * @return <code>true</code> if character is a LWS, otherwise <code>false</code>.
- */
- private static boolean isLws(final char character) {
- switch (character) {
- case 9: // HT = <US-ASCII HT, horizontal-tab (9)>
- case 10: // LF = <US-ASCII LF, linefeed (10)>
- case 13: // CR = <US-ASCII CR, carriage return (13)>
- case 32: // SP = <US-ASCII SP, space (32)>
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Ensure that charset parameter ({@link #PARAMETER_CHARSET}) is set on returned content type
- * if this {@link ContentType} is a <code>odata text related</code> content type (@see
- * {@link #isContentTypeODataTextRelated()}).
- * If <code>this</code> {@link ContentType} has no charset parameter set a new {@link ContentType} with given
- * <code>defaultCharset</code> is created.
- * Otherwise if charset parameter is already set nothing is done.
- *
- * @param defaultCharset
- * @return ContentType
- */
- public ContentType receiveWithCharsetParameter(final String defaultCharset) {
- if (isContentTypeODataTextRelated()) {
- if (!parameters.containsKey(ContentType.PARAMETER_CHARSET)) {
- return ContentType.create(this, ContentType.PARAMETER_CHARSET, defaultCharset);
- }
- }
- return this;
- }
-
- /**
- *
- * @return <code>true</code> if this {@link ContentType} is text related (in the view of OData)
- */
- public boolean isContentTypeODataTextRelated() {
- return (ContentType.TEXT_PLAIN.equals(this)
- || (getODataFormat() == ODataFormat.XML)
- || (getODataFormat() == ODataFormat.ATOM)
- || (getODataFormat() == ODataFormat.JSON));
- }
-
- public String getType() {
- return type;
- }
-
- public String getSubtype() {
- return subtype;
- }
-
- /**
- *
- * @return parameters of this {@link ContentType} as unmodifiable map.
- */
- public Map<String, String> getParameters() {
- return Collections.unmodifiableMap(parameters);
- }
-
- @Override
- public int hashCode() {
- return 1;
- }
-
- /**
- * {@link ContentType}s are equal
- * <ul>
- * <li>if <code>type</code>, <code>subtype</code> and all <code>parameters</code> have the same value.</li>
- * <li>if <code>type</code> and/or <code>subtype</code> is set to "*" (in such a case the <code>parameters</code> are
- * ignored).</li>
- * </ul>
- *
- * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code>.
- */
- @Override
- public boolean equals(final Object obj) {
- // NULL validation is done in method 'isEqualWithoutParameters(obj)'
- Boolean compatible = isEqualWithoutParameters(obj);
-
- if (compatible == null) {
- ContentType other = (ContentType) obj;
-
- // parameter checks
- if (parameters == null) {
- if (other.parameters != null) {
- return false;
- }
- } else if (parameters.size() == other.parameters.size()) {
- Iterator<Entry<String, String>> entries = parameters.entrySet().iterator();
- Iterator<Entry<String, String>> otherEntries = other.parameters.entrySet().iterator();
- while (entries.hasNext()) {
- Entry<String, String> e = entries.next();
- Entry<String, String> oe = otherEntries.next();
-
- if (!areEqual(e.getKey(), oe.getKey())) {
- return false;
- }
- if (!areEqual(e.getValue(), oe.getValue())) {
- return false;
- }
- }
- } else {
- return false;
- }
- return true;
- } else {
- // all tests run
- return compatible.booleanValue();
- }
- }
-
- /**
- * {@link ContentType}s are <b>compatible</b>
- * <ul>
- * <li>if <code>type</code>, <code>subtype</code> have the same value.</li>
- * <li>if <code>type</code> and/or <code>subtype</code> is set to "*"</li>
- * </ul>
- * The set <code>parameters</code> are <b>always</b> ignored (for compare with parameters see {@link #equals(Object)}
- * ).
- *
- * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code>.
- */
- public boolean isCompatible(final ContentType obj) {
- Boolean compatible = isEqualWithoutParameters(obj);
- if (compatible == null) {
- return true;
- }
- return compatible.booleanValue();
- }
-
- /**
- * Check equal without parameters.
- * It is possible that no decision about <code>equal/none equal</code> can be determined a <code>NULL</code> is
- * returned.
- *
- * @param obj to checked object
- * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code>
- * or <code>NULL</code> if no decision about <code>equal/none equal</code> could be determined.
- */
- private Boolean isEqualWithoutParameters(final Object obj) {
- // basic checks
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
-
- ContentType other = (ContentType) obj;
-
- // subtype checks
- if (subtype == null) {
- if (other.subtype != null) {
- return false;
- }
- } else if (!subtype.equals(other.subtype)) {
- if (other.subtype == null) {
- return false;
- } else if (!subtype.equals(MEDIA_TYPE_WILDCARD) && !other.subtype.equals(MEDIA_TYPE_WILDCARD)) {
- return false;
- }
- }
-
- // type checks
- if (type == null) {
- if (other.type != null) {
- return false;
- }
- } else if (!type.equals(other.type)) {
- if (!type.equals(MEDIA_TYPE_WILDCARD) && !other.type.equals(MEDIA_TYPE_WILDCARD)) {
- return false;
- }
- }
-
- // if wildcards are set, content types are defined as 'equal'
- if (countWildcards() > 0 || other.countWildcards() > 0) {
- return true;
- }
-
- return null;
- }
-
- /**
- * Check whether both string are equal ignoring the case of the strings.
- *
- * @param first first string
- * @param second second string
- * @return <code>true</code> if both strings are equal (by ignoring the case), otherwise <code>false</code> is
- * returned
- */
- private static boolean areEqual(final String first, final String second) {
- if (first == null) {
- if (second != null) {
- return false;
- }
- } else if (!first.equalsIgnoreCase(second)) {
- return false;
- }
- return true;
- }
-
- /**
- * Get {@link ContentType} as string as defined in RFC 2616 (http://www.ietf.org/rfc/rfc2616.txt - chapter 14.17:
- * Content-Type)
- *
- * @return string representation of <code>ContentType</code> object
- */
- public String toContentTypeString() {
- StringBuilder sb = new StringBuilder();
-
- if (odataFormat == ODataFormat.CUSTOM && subtype == null) {
- sb.append(type);
- } else {
- sb.append(type).append(TYPE_SUBTYPE_SEPARATOR).append(subtype);
- }
-
- for (String key : parameters.keySet()) {
- if (isParameterAllowed(key)) {
- String value = parameters.get(key);
- sb.append(";").append(key).append("=").append(value);
- }
- }
- return sb.toString();
- }
-
- @Override
- public String toString() {
- return toContentTypeString();
- }
-
- public ODataFormat getODataFormat() {
- return odataFormat;
- }
-
- /**
- * Find best match between this {@link ContentType} and the {@link ContentType} in the list.
- * If a match (this {@link ContentType} is equal to a {@link ContentType} in list) is found either this or the
- * {@link ContentType} from the list is returned based on which {@link ContentType} has less "**" characters set
- * (checked with {@link #compareWildcardCounts(ContentType)}.
- * If no match (none {@link ContentType} in list is equal to this {@link ContentType}) is found <code>NULL</code> is
- * returned.
- *
- * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
- * @return best matched content type in list or <code>NULL</code> if none content type match to this content type
- * instance
- */
- public ContentType match(final List<ContentType> toMatchContentTypes) {
- for (ContentType supportedContentType : toMatchContentTypes) {
- if (equals(supportedContentType)) {
- if (compareWildcardCounts(supportedContentType) < 0) {
- return this;
- } else {
- return supportedContentType;
- }
- }
- }
- return null;
- }
-
- /**
- * Find best match between this {@link ContentType} and the {@link ContentType} in the list ignoring all set
- * parameters.
- * If a match (this {@link ContentType} is equal to a {@link ContentType} in list) is found either this or the
- * {@link ContentType} from the list is returned based on which {@link ContentType} has less "**" characters set
- * (checked with {@link #compareWildcardCounts(ContentType)}.
- * If no match (none {@link ContentType} in list is equal to this {@link ContentType}) is found <code>NULL</code> is
- * returned.
- *
- * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
- * @return best matched content type in list or <code>NULL</code> if none content type match to this content type
- * instance
- */
- public ContentType matchCompatible(final List<ContentType> toMatchContentTypes) {
- for (ContentType supportedContentType : toMatchContentTypes) {
- if (isCompatible(supportedContentType)) {
- if (compareWildcardCounts(supportedContentType) < 0) {
- return this;
- } else {
- return supportedContentType;
- }
- }
- }
- return null;
- }
-
- /**
- * Check if a valid compatible match for this {@link ContentType} exists in given list.
- * Compatible in this case means that <b>all set parameters are ignored</b>.
- * For more detail what a valid match is see {@link #matchCompatible(List)}.
- *
- * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
- * @return <code>true</code> if a compatible content type was found in given list
- * or <code>false</code> if none compatible content type match was found
- */
- public boolean hasCompatible(final List<ContentType> toMatchContentTypes) {
- return matchCompatible(toMatchContentTypes) != null;
- }
-
- /**
- * Check if a valid match for this {@link ContentType} exists in given list.
- * For more detail what a valid match is see {@link #match(List)}.
- *
- * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
- * @return <code>true</code> if a matching content type was found in given list
- * or <code>false</code> if none matching content type match was found
- */
- public boolean hasMatch(final List<ContentType> toMatchContentTypes) {
- return match(toMatchContentTypes) != null;
- }
-
- /**
- * Compare wildcards counts/weights of both {@link ContentType}.
- *
- * The smaller {@link ContentType} has lesser weighted wildcards then the bigger {@link ContentType}.
- * As result this method returns this object weighted wildcards minus the given parameter object weighted wildcards.
- *
- * A type wildcard is weighted with <code>2</code> and a subtype wildcard is weighted with <code>1</code>.
- *
- * @param otherContentType {@link ContentType} to be compared to
- * @return this object weighted wildcards minus the given parameter object weighted wildcards.
- */
- public int compareWildcardCounts(final ContentType otherContentType) {
- return countWildcards() - otherContentType.countWildcards();
- }
-
- private int countWildcards() {
- int count = 0;
- if (MEDIA_TYPE_WILDCARD.equals(type)) {
- count += 2;
- }
- if (MEDIA_TYPE_WILDCARD.equals(subtype)) {
- count++;
- }
- return count;
- }
-
- /**
- *
- * @return <code>true</code> if <code>type</code> or <code>subtype</code> of this instance is a "*".
- */
- public boolean hasWildcard() {
- return (MEDIA_TYPE_WILDCARD.equals(type) || MEDIA_TYPE_WILDCARD.equals(subtype));
- }
-
- /**
- *
- * @return <code>true</code> if both <code>type</code> and <code>subtype</code> of this instance are a "*".
- */
- public boolean isWildcard() {
- return (MEDIA_TYPE_WILDCARD.equals(type) && MEDIA_TYPE_WILDCARD.equals(subtype));
- }
-
- public static List<ContentType> convert(final List<String> types) {
- List<ContentType> results = new ArrayList<ContentType>();
- for (String contentType : types) {
- results.add(ContentType.create(contentType));
- }
- return results;
- }
-
- /**
- * Check if a valid match for given content type formated string (<code>toMatch</code>) exists in given list.
- * Therefore the given content type formated string (<code>toMatch</code>) is converted into a {@link ContentType}
- * with a simple {@link #create(String)} call (during which an exception can occur).
- *
- * For more detail in general see {@link #hasMatch(List)} and for what a valid match is see {@link #match(List)}.
- *
- * @param toMatch content type formated string (<code>toMatch</code>) for which is checked if a match exists in given
- * list
- * @param matchExamples list of {@link ContentType}s which are matches against content type formated string
- * (<code>toMatch</code>)
- * @return <code>true</code> if a matching content type was found in given list
- * or <code>false</code> if none matching content type match was found
- */
- public static boolean match(final String toMatch, final ContentType... matchExamples) {
- ContentType toMatchContentType = ContentType.create(toMatch);
-
- return toMatchContentType.hasMatch(Arrays.asList(matchExamples));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
deleted file mode 100644
index c725a2f..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.commons;
-
-import java.io.UnsupportedEncodingException;
-
-/**
- * Decodes a Java String containing a percent-encoded UTF-8 String value
- * into a Java String (in its internal UTF-16 encoding).
- *
- */
-public class Decoder {
-
- /**
- * Decodes a percent-encoded UTF-8 String value into a Java String
- * (in its internal UTF-16 encoding).
- * @param value the encoded String
- * @return the Java String
- * @throws IllegalArgumentException if value contains characters not representing UTF-8 bytes
- * or ends with an unfinished percent-encoded character
- * @throws NumberFormatException if the two characters after a percent character
- * are not hexadecimal digits
- */
- public static String decode(final String value) throws IllegalArgumentException, NumberFormatException {
- if (value == null) {
- return value;
- }
-
- // Use a tiny finite-state machine to handle decoding on byte level.
- // There are only three states:
- // -2: normal bytes
- // -1: a byte representing the percent character has been read
- // >= 0: a byte representing the first half-byte of a percent-encoded byte has been read
- // The variable holding the state is also used to store the value of the first half-byte.
- byte[] result = new byte[value.length()];
- int position = 0;
- byte encodedPart = -2;
- for (final char c : value.toCharArray()) {
- if (c <= Byte.MAX_VALUE) {
- if (c == '%') {
- if (encodedPart == -2) {
- encodedPart = -1;
- } else {
- throw new IllegalArgumentException();
- }
- } else if (encodedPart == -1) {
- encodedPart = (byte) c;
- } else if (encodedPart >= 0) {
- final int i = Integer.parseInt(String.valueOf(new char[] { (char) encodedPart, c }), 16);
- if (i >= 0) {
- result[position++] = (byte) i;
- } else {
- throw new NumberFormatException();
- }
- encodedPart = -2;
- } else {
- result[position++] = (byte) c;
- }
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- if (encodedPart >= 0) {
- throw new IllegalArgumentException();
- }
-
- try {
- return new String(result, 0, position, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
deleted file mode 100644
index aceb6cf..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.commons;
-
-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 {
-
- /**
- * 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;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
deleted file mode 100644
index bb04303..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.debug;
-
-import java.io.IOException;
-
-import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
-
-/**
- *
- */
-public interface DebugInfo {
-
- /**
- * Gets the name of this debug information part, useful as title.
- * @return the name
- */
- public String getName();
-
- /**
- * Appends the content of this debug information part
- * to the given JSON stream writer.
- * @param jsonStreamWriter a JSON stream writer
- */
- public void appendJson(JsonStreamWriter jsonStreamWriter) throws IOException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
deleted file mode 100644
index 8b68337..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.debug;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
-import org.apache.olingo.odata2.api.ep.EntityProviderException;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-import org.apache.olingo.odata2.core.ep.BasicEntityProvider;
-import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
-
-/**
- *
- */
-public class DebugInfoBody implements DebugInfo {
-
- private final ODataResponse response;
-
- public DebugInfoBody(final ODataResponse response) {
- this.response = response;
- }
-
- @Override
- public String getName() {
- return "Body";
- }
-
- @Override
- public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
- final String contentType = response.getContentHeader();
- if (contentType.startsWith("image/")) {
- if (response.getEntity() instanceof InputStream) {
- jsonStreamWriter.stringValueRaw(Base64.encodeBase64String(getBinaryFromInputStream((InputStream) response
- .getEntity())));
- } else if (response.getEntity() instanceof String) {
- jsonStreamWriter.stringValueRaw(getContentString());
- } else {
- throw new ClassCastException("Unsupported content entity class: " + response.getEntity().getClass().getName());
- }
- } else if (contentType.startsWith(HttpContentType.APPLICATION_JSON)) {
- jsonStreamWriter.unquotedValue(getContentString());
- } else {
- jsonStreamWriter.stringValue(getContentString());
- }
- }
-
- private String getContentString() {
- String content;
- if (response.getEntity() instanceof String) {
- content = (String) response.getEntity();
- } else if (response.getEntity() instanceof InputStream) {
- content = getStringFromInputStream((InputStream) response.getEntity());
- } else {
- throw new ClassCastException("Unsupported content entity class: " + response.getEntity().getClass().getName());
- }
- return content;
- }
-
- private static byte[] getBinaryFromInputStream(final InputStream inputStream) {
- try {
- return new BasicEntityProvider().readBinary(inputStream);
- } catch (final EntityProviderException e) {
- return null;
- }
- }
-
- private static String getStringFromInputStream(final InputStream inputStream) {
- try {
- return new BasicEntityProvider().readText(inputStream);
- } catch (final EntityProviderException e) {
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/57599da6/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
deleted file mode 100644
index c84f51f..0000000
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.debug;
-
-import java.io.IOException;
-import java.util.Locale;
-
-import org.apache.olingo.odata2.api.exception.ODataMessageException;
-import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
-import org.apache.olingo.odata2.core.exception.MessageService;
-
-/**
- *
- */
-public class DebugInfoException implements DebugInfo {
-
- private final Exception exception;
- private final Locale locale;
-
- public DebugInfoException(final Exception exception, final Locale locale) {
- this.exception = exception;
- this.locale = locale;
- }
-
- @Override
- public String getName() {
- return "Stacktrace";
- }
-
- @Override
- public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
- jsonStreamWriter.beginObject()
- .name("exceptions")
- .beginArray();
- Throwable throwable = exception;
- while (throwable != null) {
- jsonStreamWriter.beginObject()
- .namedStringValueRaw("class", throwable.getClass().getCanonicalName()).separator()
- .namedStringValue(
- "message",
- throwable instanceof ODataMessageException ?
- MessageService.getMessage(locale, ((ODataMessageException) throwable).getMessageReference())
- .getText() :
- throwable.getLocalizedMessage())
- .separator();
-
- jsonStreamWriter.name("invocation");
- appendJsonStackTraceElement(jsonStreamWriter, throwable.getStackTrace()[0]);
-
- jsonStreamWriter.endObject();
- throwable = throwable.getCause();
- if (throwable != null) {
- jsonStreamWriter.separator();
- }
- }
- jsonStreamWriter.endArray();
- jsonStreamWriter.separator();
-
- jsonStreamWriter.name("stacktrace")
- .beginArray();
- boolean first = true;
- for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
- if (!first) {
- jsonStreamWriter.separator();
- }
- first = false;
- appendJsonStackTraceElement(jsonStreamWriter, stackTraceElement);
- }
- jsonStreamWriter.endArray();
- jsonStreamWriter.endObject();
- }
-
- private static void appendJsonStackTraceElement(final JsonStreamWriter jsonStreamWriter,
- final StackTraceElement stackTraceElement) throws IOException {
- jsonStreamWriter.beginObject()
- .namedStringValueRaw("class", stackTraceElement.getClassName()).separator()
- .namedStringValueRaw("method", stackTraceElement.getMethodName()).separator()
- .name("line").unquotedValue(Integer.toString(stackTraceElement.getLineNumber()))
- .endObject();
- }
-}