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 2015/07/10 15:17:54 UTC
[03/11] olingo-odata4 git commit: [OLINGO-708] Added
AsyncResponseSerializer
[OLINGO-708] Added AsyncResponseSerializer
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/03bf387b
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/03bf387b
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/03bf387b
Branch: refs/heads/master
Commit: 03bf387b24e6c390945a9a748d96c34674555dde
Parents: 06d508d
Author: mibo <mi...@apache.org>
Authored: Sat Jun 27 11:45:48 2015 +0200
Committer: mibo <mi...@apache.org>
Committed: Sat Jun 27 11:45:48 2015 +0200
----------------------------------------------------------------------
.../serializer/BatchSerializerException.java | 2 +-
.../api/serializer/FixedFormatSerializer.java | 8 ++
.../api/serializer/SerializerException.java | 2 +-
.../serializer/AsyncResponseSerializer.java | 102 +++++++++++++++++++
.../serializer/FixedFormatSerializerImpl.java | 7 ++
.../serializer/AsyncResponseSerializerTest.java | 78 ++++++++++++++
.../olingo/server/tecsvc/TechnicalServlet.java | 6 --
.../tecsvc/async/TechnicalAsyncService.java | 65 ++++++++----
.../async/TechnicalStatusMonitorServlet.java | 2 +-
9 files changed, 244 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BatchSerializerException.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BatchSerializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BatchSerializerException.java
index fa193e9..fe37950 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BatchSerializerException.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BatchSerializerException.java
@@ -23,7 +23,7 @@ public class BatchSerializerException extends SerializerException {
private static final long serialVersionUID = 2634433974342796905L;
- public static enum MessageKeys implements MessageKey {
+ public enum MessageKeys implements MessageKey {
MISSING_CONTENT_ID;
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/FixedFormatSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/FixedFormatSerializer.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/FixedFormatSerializer.java
index d15d5ce..42b6efd 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/FixedFormatSerializer.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/FixedFormatSerializer.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.List;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.deserializer.batch.ODataResponsePart;
/** OData serializer for fixed output formats. */
@@ -55,4 +56,11 @@ public interface FixedFormatSerializer {
* @return response as an input stream
*/
InputStream batchResponse(List<ODataResponsePart> batchResponses, String boundary) throws BatchSerializerException;
+
+ /**
+ * Serializes a ODataResponse into an async response.
+ * @param odataResponse the response parts
+ * @return response as an input stream
+ */
+ InputStream asyncResponse(ODataResponse odataResponse) throws SerializerException;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java
index 8a65976..4e1a035 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java
@@ -26,7 +26,7 @@ public class SerializerException extends ODataLibraryException {
private static final long serialVersionUID = 5358683245923127425L;
/** Keys for exception texts in the resource bundle. */
- public static enum MessageKeys implements MessageKey {
+ public enum MessageKeys implements MessageKey {
NOT_IMPLEMENTED,
/** parameter: format */
UNSUPPORTED_FORMAT,
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializer.java
new file mode 100644
index 0000000..472f073
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializer.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.serializer;
+
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.Map;
+
+public class AsyncResponseSerializer {
+ private static final int BUFFER_SIZE = 4096;
+ private static final String COLON = ":";
+ private static final String SP = " ";
+ private static final String CRLF = "\r\n";
+ public static final String HEADER_CHARSET_NAME = "ISO-8859-1";
+ public static final String HTTP_VERSION = "HTTP/1.1";
+
+ public InputStream serialize(final ODataResponse response) throws SerializerException {
+ try {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ appendStatusLine(response, buffer);
+ appendResponseHeader(response, buffer);
+ append(CRLF, buffer);
+ appendBody(response, buffer);
+
+ buffer.flush();
+ return new ByteArrayInputStream(buffer.toByteArray(), 0, buffer.size());
+ } catch (IOException e) {
+ throw new SerializerException("Exception occurred during serialization of asynchronous response.",
+ e, SerializerException.MessageKeys.IO_EXCEPTION);
+ }
+ }
+
+ private void appendResponseHeader(final ODataResponse response,
+ final ByteArrayOutputStream buffer) throws IOException {
+ final Map<String, String> header = response.getHeaders();
+
+ for (final String key: header.keySet()) {
+ appendHeader(key, header.get(key), buffer);
+ }
+ }
+
+ private void appendHeader(final String name, final String value, final ByteArrayOutputStream buffer)
+ throws IOException {
+ append(name + COLON + SP + value + CRLF, buffer);
+ }
+
+ private void appendStatusLine(final ODataResponse response, final ByteArrayOutputStream buffer)
+ throws IOException {
+ HttpStatusCode status = HttpStatusCode.fromStatusCode(response.getStatusCode());
+ append(HTTP_VERSION + SP + response.getStatusCode() + SP + status + CRLF, buffer);
+ }
+
+ private void appendBody(ODataResponse response, ByteArrayOutputStream buffer) throws IOException {
+ InputStream input = response.getContent();
+ if (input != null) {
+ ByteBuffer inBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+ ReadableByteChannel ic = Channels.newChannel(input);
+ WritableByteChannel oc = Channels.newChannel(buffer);
+ while (ic.read(inBuffer) > 0) {
+ inBuffer.flip();
+ oc.write(inBuffer);
+ inBuffer.rewind();
+ }
+ }
+ }
+
+ private void append(final String value, final ByteArrayOutputStream buffer) throws IOException {
+ try {
+ buffer.write(value.getBytes(HEADER_CHARSET_NAME));
+ } catch (UnsupportedEncodingException e) {
+ throw new IOException("Default header charset with name '" + HEADER_CHARSET_NAME +
+ "' is not available.", e);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/FixedFormatSerializerImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/FixedFormatSerializerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/FixedFormatSerializerImpl.java
index dd15973..0a401b2 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/FixedFormatSerializerImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/FixedFormatSerializerImpl.java
@@ -25,6 +25,7 @@ import java.util.List;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.deserializer.batch.ODataResponsePart;
import org.apache.olingo.server.api.serializer.BatchSerializerException;
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
@@ -60,6 +61,12 @@ public class FixedFormatSerializerImpl implements FixedFormatSerializer {
}
}
+ @Override
+ public InputStream asyncResponse(ODataResponse odataResponse) throws SerializerException {
+ AsyncResponseSerializer serializer = new AsyncResponseSerializer();
+ return serializer.serialize(odataResponse);
+ }
+
// TODO: Signature refactoring for writeBatchResponse
@Override
public InputStream batchResponse(final List<ODataResponsePart> batchResponses, final String boundary)
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializerTest.java
new file mode 100644
index 0000000..aee42dd
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/AsyncResponseSerializerTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.core.serializer;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataResponse;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+
+public class AsyncResponseSerializerTest {
+ private static final String CRLF = "\r\n";
+
+ @Test
+ public void testSimpleResponse() throws Exception {
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.APPLICATION_JSON.toContentTypeString());
+
+ response.setContent(IOUtils.toInputStream("Walter Winter" + CRLF));
+
+ AsyncResponseSerializer serializer = new AsyncResponseSerializer();
+ InputStream in = serializer.serialize(response);
+ String result = IOUtils.toString(in);
+ assertEquals("HTTP/1.1 200 OK" + CRLF +
+ "Content-Type: application/json" + CRLF + CRLF +
+ "Walter Winter" + CRLF, result);
+ }
+
+ @Test
+ public void testBiggerResponse() throws Exception {
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.ACCEPTED.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.APPLICATION_JSON.toContentTypeString());
+
+ String testData = testData(20000);
+ response.setContent(IOUtils.toInputStream(testData));
+
+ AsyncResponseSerializer serializer = new AsyncResponseSerializer();
+ InputStream in = serializer.serialize(response);
+ String result = IOUtils.toString(in);
+ assertEquals("HTTP/1.1 202 Accepted" + CRLF +
+ "Content-Type: application/json" + CRLF + CRLF +
+ testData, result);
+ }
+
+ private String testData(int amount) {
+ StringBuilder result = new StringBuilder();
+ Random r = new Random();
+ for (int i = 0; i < amount; i++) {
+ result.append((char)(r.nextInt(26) + 'a'));
+ }
+
+ return result.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
index c88e0e7..09e8682 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
@@ -64,12 +64,6 @@ public class TechnicalServlet extends HttpServlet {
protected void service(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
try {
- if(TechnicalAsyncService.getInstance().isStatusMonitorResource(request)) {
- TechnicalAsyncService asyncService = TechnicalAsyncService.getInstance();
- asyncService.handle(request, response);
- return;
- }
-
OData odata = OData.newInstance();
EdmxReference reference = new EdmxReference(URI.create("../v4.0/cs02/vocabularies/Org.OData.Core.V1.xml"));
reference.addInclude(new EdmxReferenceInclude("Org.OData.Core.V1", "Core"));
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalAsyncService.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalAsyncService.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalAsyncService.java
index 26d426b..2b752f0 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalAsyncService.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalAsyncService.java
@@ -33,13 +33,16 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.olingo.commons.api.ODataRuntimeException;
+import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.processor.Processor;
+import org.apache.olingo.server.api.serializer.SerializerException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -90,7 +93,7 @@ public class TechnicalAsyncService {
return location;
}
- public void handle(HttpServletRequest request, HttpServletResponse response) {
+ public void handle(HttpServletRequest request, HttpServletResponse response) throws SerializerException, IOException {
String location = getAsyncLocation(request);
AsyncRunner runner = LOCATION_2_ASYNC_RUNNER.get(location);
@@ -99,7 +102,7 @@ public class TechnicalAsyncService {
} else {
if(runner.isFinished()) {
ODataResponse wrapResult = runner.getDispatched().getProcessResponse();
- convertToHttp(response, wrapResult);
+ wrapToAsyncHttpResponse(wrapResult, response);
LOCATION_2_ASYNC_RUNNER.remove(location);
} else {
response.setStatus(HttpStatusCode.ACCEPTED.getStatusCode());
@@ -110,11 +113,19 @@ public class TechnicalAsyncService {
}
}
+ private static void writeToResponse(HttpServletResponse response, InputStream input) throws IOException {
+ copy(input, response.getOutputStream());
+ }
+
private void writeToResponse(HttpServletResponse response, String content) {
+ writeToResponse(response, content.getBytes());
+ }
+
+ private static void writeToResponse(HttpServletResponse response, byte[] content) {
OutputStream output = null;
try {
output = response.getOutputStream();
- output.write(content.getBytes());
+ output.write(content);
} catch (IOException e) {
throw new ODataRuntimeException(e);
} finally {
@@ -122,32 +133,48 @@ public class TechnicalAsyncService {
}
}
- static void convertToHttp(final HttpServletResponse response, final ODataResponse odResponse) {
+ static void wrapToAsyncHttpResponse(final ODataResponse odResponse, final HttpServletResponse response)
+ throws SerializerException, IOException {
+ OData odata = OData.newInstance();
+ InputStream odResponseStream = odata.createFixedFormatSerializer().asyncResponse(odResponse);
+
+ response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.APPLICATION_HTTP.toContentTypeString());
+ response.setHeader(HttpHeader.CONTENT_ENCODING, "binary");
+ response.setStatus(HttpStatusCode.OK.getStatusCode());
+
+ writeToResponse(response, odResponseStream);
+ }
+
+ static void writeHttpResponse(final ODataResponse odResponse, final HttpServletResponse response) throws IOException {
response.setStatus(odResponse.getStatusCode());
for (Map.Entry<String, String> entry : odResponse.getHeaders().entrySet()) {
response.setHeader(entry.getKey(), entry.getValue());
}
- InputStream input = odResponse.getContent();
- if (input != null) {
- OutputStream output = null;
- try {
- output = response.getOutputStream();
- byte[] buffer = new byte[1024];
- int n;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- }
- } catch (IOException e) {
- throw new ODataRuntimeException(e);
- } finally {
- closeStream(output);
- closeStream(input);
+ copy(odResponse.getContent(), response.getOutputStream());
+ }
+
+ static void copy(final InputStream input, final OutputStream output) {
+ if(output == null || input == null) {
+ return;
+ }
+
+ try {
+ byte[] buffer = new byte[1024];
+ int n;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
}
+ } catch (IOException e) {
+ throw new ODataRuntimeException(e);
+ } finally {
+ closeStream(output);
+ closeStream(input);
}
}
+
private static void closeStream(final Closeable closeable) {
if (closeable != null) {
try {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/03bf387b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalStatusMonitorServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalStatusMonitorServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalStatusMonitorServlet.java
index 262ad65..8fd22cf 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalStatusMonitorServlet.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/async/TechnicalStatusMonitorServlet.java
@@ -59,7 +59,7 @@ public class TechnicalStatusMonitorServlet extends HttpServlet {
TechnicalAsyncService asyncService = TechnicalAsyncService.getInstance();
asyncService.handle(request, response);
}
- } catch (final RuntimeException e) {
+ } catch (final Exception e) {
LOG.error("Server Error", e);
throw new ServletException(e);
}