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 10:39:22 UTC
[4/5] olingo-odata4 git commit: [OLINGO-729] Merge branch 'master'
into OLINGO-729_BatchDeSerializer
[OLINGO-729] Merge branch 'master' into OLINGO-729_BatchDeSerializer
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/594ad4ab
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/594ad4ab
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/594ad4ab
Branch: refs/heads/OLINGO-729_BatchDeSerializer
Commit: 594ad4ab45b6e4d2033361d16931a66a77aa0918
Parents: 3c591da 4baaf0d
Author: Michael Bolz <mi...@sap.com>
Authored: Fri Jul 10 08:19:25 2015 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Fri Jul 10 09:24:45 2015 +0200
----------------------------------------------------------------------
.../apache/olingo/fit/v4/BatchTestITCase.java | 2 -
.../org/apache/olingo/server/api/OData.java | 9 ++
.../olingo/server/api/ODataHttpHandler.java | 7 ++
.../server/api/debug/DebugResponseHelper.java | 38 ++++++
.../olingo/server/api/debug/DebugSupport.java | 49 ++++++++
.../server/api/debug/DefaultDebugSupport.java | 52 ++++++++
.../server/core/ODataHttpHandlerImpl.java | 33 ++++-
.../apache/olingo/server/core/ODataImpl.java | 9 ++
.../core/debug/DebugResponseHelperImpl.java | 33 +++++
.../deserializer/batch/BatchLineReader.java | 50 +++++---
.../serializer/BatchResponseSerializer.java | 3 +-
.../serializer/json/ODataJsonSerializer.java | 1 -
.../deserializer/batch/BatchLineReaderTest.java | 92 +++++++++++---
.../serializer/BatchResponseSerializerTest.java | 60 ++++++++-
.../olingo/server/tecsvc/TechnicalServlet.java | 5 +
pom.xml | 1 +
.../myservice/mynamespace/data/Storage.java | 92 +++++++-------
.../mynamespace/service/DemoEdmProvider.java | 43 +++----
.../service/DemoEntityCollectionProcessor.java | 47 ++++---
.../service/DemoEntityProcessor.java | 64 ++++------
.../service/DemoPrimitiveProcessor.java | 42 +++----
.../java/myservice/mynamespace/util/Util.java | 126 ++++++++++---------
.../myservice/mynamespace/web/DemoServlet.java | 17 ++-
23 files changed, 600 insertions(+), 275 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/594ad4ab/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReader.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReader.java
index d96a5f5,0000000..150d318
mode 100644,000000..100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReader.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReader.java
@@@ -1,275 -1,0 +1,295 @@@
+/*
+ * 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.deserializer.batch;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
++/**
++ * Read batch content and split it into lines.
++ * This class is not thread safe.
++ */
+public class BatchLineReader {
- private static final byte CR = '\r';
- private static final byte LF = '\n';
++ private static final byte CR_BYTE = '\r';
++ private static final byte LF_BYTE = '\n';
+ private static final int EOF = -1;
+ private static final int BUFFER_SIZE = 8192;
+ private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+ private static final Charset CS_ISO_8859_1 = Charset.forName("iso-8859-1");
- public static final String BOUNDARY = "boundary";
- public static final String DOUBLE_DASH = "--";
- public static final String CRLF = "\r\n";
++ private static final String BOUNDARY = "boundary";
++ private static final String DOUBLE_DASH = "--";
++ private static final String CR = "\r";
++ private static final String LF = "\n";
++ private static final String CRLF = "\r\n";
++ // length of the Content-Type Header field including the ':'
++ // "Content-Type:" => 13
++ private static final int CONTENT_TYPE_LENGTH = 13;
++
++ private final ReadState readState = new ReadState();
+ private Charset currentCharset = DEFAULT_CHARSET;
+ private String currentBoundary = null;
- private ReadState readState = new ReadState();
+ private InputStream reader;
+ private byte[] buffer;
+ private int offset = 0;
+ private int limit = 0;
+
+ public BatchLineReader(final InputStream reader) {
+ this(reader, BUFFER_SIZE);
+ }
+
+ public BatchLineReader(final InputStream reader, final int bufferSize) {
+ if (bufferSize <= 0) {
+ throw new IllegalArgumentException("Buffer size must be greater than zero.");
+ }
+
+ this.reader = reader;
+ buffer = new byte[bufferSize];
+ }
+
+ public void close() throws IOException {
+ reader.close();
+ }
+
+ public List<String> toList() throws IOException {
+ final List<String> result = new ArrayList<String>();
+ String currentLine = readLine();
+ if(currentLine != null) {
+ currentBoundary = currentLine.trim();
+ result.add(currentLine);
+
+ while ((currentLine = readLine()) != null) {
+ result.add(currentLine);
+ }
+ }
+ return result;
+ }
+
+ public List<Line> toLineList() throws IOException {
+ final List<Line> result = new ArrayList<Line>();
+ String currentLine = readLine();
+ if(currentLine != null) {
+ currentBoundary = currentLine.trim();
+ int counter = 1;
+ result.add(new Line(currentLine, counter++));
+
+ while ((currentLine = readLine()) != null) {
+ result.add(new Line(currentLine, counter++));
+ }
+ }
+
+ return result;
+ }
+
+ int read(final byte[] byteBuffer, final int bufferOffset, final int length) throws IOException {
+ if ((bufferOffset + length) > byteBuffer.length) {
+ throw new IndexOutOfBoundsException("Buffer is too small");
+ }
+
+ if (length < 0 || bufferOffset < 0) {
- throw new IndexOutOfBoundsException("Offset and length must be grater than zero");
++ throw new IndexOutOfBoundsException("Offset and length must be greater than zero");
+ }
+
+ // Check if buffer is filled. Return if EOF is reached
+ // Is buffer refill required
+ if (limit == offset || isEOF()) {
+ fillBuffer();
+
+ if (isEOF()) {
+ return EOF;
+ }
+ }
+
+ int bytesRead = 0;
+ int bytesToRead = length;
+ int currentOutputOffset = bufferOffset;
+
+ while (bytesToRead != 0) {
+ // Is buffer refill required?
+ if (limit == offset) {
+ fillBuffer();
+
+ if (isEOF()) {
+ bytesToRead = 0;
+ }
+ }
+
+ if (bytesToRead > 0) {
+ int readByte = Math.min(limit - offset, bytesToRead);
+ bytesRead += readByte;
+ bytesToRead -= readByte;
+
+ for (int i = 0; i < readByte; i++) {
+ byteBuffer[currentOutputOffset++] = buffer[offset++];
+ }
+ }
+ }
+
+ return bytesRead;
+ }
+
+ private void updateCurrentCharset(String currentLine) {
- // TODO: mibo: Improve this method
+ if(currentLine != null) {
+ if(currentLine.startsWith(HttpHeader.CONTENT_TYPE)) {
- currentLine = currentLine.substring(13, currentLine.length() - 2).trim();
- ContentType ct = ContentType.parse(currentLine);
++ ContentType ct = parseContentType(currentLine);
+ if (ct != null) {
+ String charsetString = ct.getParameter(ContentType.PARAMETER_CHARSET);
+ if (charsetString != null) {
+ currentCharset = Charset.forName(charsetString);
+ } else {
+ currentCharset = DEFAULT_CHARSET;
+ }
+ // boundary
+ String boundary = ct.getParameter(BOUNDARY);
+ if (boundary != null) {
+ currentBoundary = DOUBLE_DASH + boundary;
+ }
+ }
- } else if(CRLF.equals(currentLine)) {
++ } else if(isLinebreak(currentLine)) {
+ readState.foundLinebreak();
+ } else if(isBoundary(currentLine)) {
+ readState.foundBoundary();
+ }
+ }
+ }
+
++ private ContentType parseContentType(String currentLine) {
++ currentLine = currentLine.substring(CONTENT_TYPE_LENGTH, currentLine.length()).trim();
++ return ContentType.parse(currentLine);
++ }
++
++ private boolean isLinebreak(String currentLine) {
++ if(currentLine.length() > 2) {
++ return false;
++ }
++ return CR.equals(currentLine) || LF.equals(currentLine) || CRLF.equals(currentLine);
++ }
++
+ private boolean isBoundary(String currentLine) {
+ if((currentBoundary + CRLF).equals(currentLine)) {
+ return true;
+ } else if((currentBoundary + DOUBLE_DASH + CRLF).equals(currentLine)) {
+ return true;
+ }
+ return false;
+ }
+
+ String readLine() throws IOException {
+ if (limit == EOF) {
+ return null;
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
+ boolean foundLineEnd = false; // EOF will be considered as line ending
+
+ while (!foundLineEnd) {
+ // Is buffer refill required?
+ if (limit == offset) {
+ if (fillBuffer() == EOF) {
+ foundLineEnd = true;
+ }
+ }
+
+ if (!foundLineEnd) {
+ byte currentChar = this.buffer[offset++];
+ if(!buffer.hasRemaining()) {
+ buffer.flip();
+ ByteBuffer tmp = ByteBuffer.allocate(buffer.limit() *2);
+ tmp.put(buffer);
+ buffer = tmp;
+ }
+ buffer.put(currentChar);
+
- if (currentChar == LF) {
++ if (currentChar == LF_BYTE) {
+ foundLineEnd = true;
- } else if (currentChar == CR) {
++ } else if (currentChar == CR_BYTE) {
+ foundLineEnd = true;
+
+ // Check next char. Consume \n if available
+ // Is buffer refill required?
+ if (limit == offset) {
+ fillBuffer();
+ }
+
+ // Check if there is at least one character
- if (limit != EOF && this.buffer[offset] == LF) {
- buffer.put(LF);
++ if (limit != EOF && this.buffer[offset] == LF_BYTE) {
++ buffer.put(LF_BYTE);
+ offset++;
+ }
+ }
+ }
+ }
+
+ if(buffer.position() == 0) {
+ return null;
+ } else {
+ String currentLine;
+ if(readState.isReadBody()) {
+ currentLine = new String(buffer.array(), 0, buffer.position(), getCurrentCharset());
+ } else {
+ currentLine = new String(buffer.array(), 0, buffer.position(), CS_ISO_8859_1);
+ }
+ updateCurrentCharset(currentLine);
+ return currentLine;
+ }
+ }
+
+ private boolean isEOF() {
+ return limit == EOF;
+ }
+
+ private int fillBuffer() throws IOException {
+ limit = reader.read(buffer, 0, buffer.length);
+ offset = 0;
+
+ return limit;
+ }
+
+ private Charset getCurrentCharset() {
+ return currentCharset;
+ }
+
+ /**
+ * Read state indicator (whether currently the <code>body</code> or <code>header</code> part is read).
+ */
+ private class ReadState {
+ private int state = 0;
+
+ public void foundLinebreak() {
+ state++;
+ }
+ public void foundBoundary() {
+ state = 0;
+ }
+ public boolean isReadBody() {
+ return state >= 2;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(state);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/594ad4ab/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/BatchResponseSerializer.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/BatchResponseSerializer.java
index 377c5e1,577f083..21474dd
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/BatchResponseSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/BatchResponseSerializer.java
@@@ -22,12 -22,6 +22,11 @@@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
- import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@@ -165,93 -182,4 +164,93 @@@ public class BatchResponseSerializer
private String generateBoundary(final String value) {
return value + "_" + UUID.randomUUID().toString();
}
-}
+
+ /**
+ * Builder class to create the body and the header.
+ */
+ private class BodyBuilder {
+ private final Charset CHARSET_ISO_8859_1 = Charset.forName("iso-8859-1");
+ private ByteBuffer buffer = ByteBuffer.allocate(8192);
+ private boolean isClosed = false;
+
+ public byte[] getContent() {
+ isClosed = true;
+ byte[] tmp = new byte[buffer.position()];
+ buffer.flip();
+ buffer.get(tmp, 0, buffer.limit());
+ return tmp;
+ }
+
+ public BodyBuilder append(String string) {
+ byte [] b = string.getBytes(CHARSET_ISO_8859_1);
+ put(b);
+ return this;
+ }
+
+ private void put(byte[] b) {
+ if(isClosed) {
+ throw new RuntimeException("BodyBuilder is closed.");
+ }
+ if(buffer.remaining() < b.length) {
+ buffer.flip();
- ByteBuffer tmp = ByteBuffer.allocate(buffer.limit() *2);
++ ByteBuffer tmp = ByteBuffer.allocate(b.length + BUFFER_SIZE);
+ tmp.put(buffer);
+ buffer = tmp;
+ }
+ buffer.put(b);
+ }
+
+ public BodyBuilder append(int statusCode) {
+ return append(String.valueOf(statusCode));
+ }
+
+ public BodyBuilder append(Body body) {
+ put(body.getContent());
+ return this;
+ }
+
+ public String toString() {
+ return new String(buffer.array(), 0, buffer.position());
+ }
+ }
+
+ /**
+ * Body part which is read and stored as bytes (no charset conversion).
+ */
+ private class Body {
+ private final byte[] content;
+
+ public Body(ODataResponse response) {
+ this.content = getBody(response);
+ }
+
+ public int getLength() {
+ return content.length;
+ }
+
+ public byte[] getContent() {
+ return content;
+ }
+
+ private byte[] getBody(final ODataResponse response) {
+ if (response == null || response.getContent() == null) {
+ return new byte[0];
+ }
+
+ try {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ByteBuffer inBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+ ReadableByteChannel ic = Channels.newChannel(response.getContent());
+ WritableByteChannel oc = Channels.newChannel(output);
+ while (ic.read(inBuffer) > 0) {
+ inBuffer.flip();
+ oc.write(inBuffer);
+ inBuffer.rewind();
+ }
+ return output.toByteArray();
+ } catch (IOException e) {
+ throw new ODataRuntimeException("Error on reading request content");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/594ad4ab/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReaderTest.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReaderTest.java
index 3d2507c,0000000..afb51f0
mode 100644,000000..100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReaderTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReaderTest.java
@@@ -1,280 -1,0 +1,342 @@@
+/*
+ * 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.deserializer.batch;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
++import java.io.ByteArrayOutputStream;
++import java.io.IOException;
++import java.io.InputStream;
++import java.nio.ByteBuffer;
++import java.nio.channels.Channels;
++import java.nio.channels.ReadableByteChannel;
++import java.nio.channels.WritableByteChannel;
++import java.nio.charset.Charset;
+import java.util.List;
+
++import org.apache.commons.io.IOUtils;
++import org.apache.commons.lang3.StringUtils;
++import org.apache.olingo.commons.api.ODataRuntimeException;
++import org.apache.olingo.server.api.ODataResponse;
+import org.junit.Test;
+
+public class BatchLineReaderTest {
+
+ private static final String TEXT_COMBINED = "Test\r" +
+ "Test2\r\n" +
+ "Test3\n" +
+ "Test4\r" +
+ "\r" +
+ "\r\n" +
+ "\r\n" +
+ "Test5\n" +
+ "Test6\r\n" +
+ "Test7\n" +
+ "\n";
+
+ private static final String TEXT_EMPTY = "";
++ private static final String LF = "\n";
+
+ @Test
+ public void testSimpleText() throws Exception {
+ final String TEXT = "Test";
+ BatchLineReader reader = create(TEXT);
+
+ assertEquals(TEXT, reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testNoText() throws Exception {
+ final String TEXT = "";
+ BatchLineReader reader = create(TEXT);
+
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testNoBytes() throws Exception {
+ BatchLineReader reader =
+ new BatchLineReader(new ByteArrayInputStream(new byte[0]));
+
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testCRLF() throws Exception {
+ final String TEXT = "Test\r\n" +
+ "Test2";
+
+ BatchLineReader reader = create(TEXT);
+
+ assertEquals("Test\r\n", reader.readLine());
+ assertEquals("Test2", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testLF() throws Exception {
+ final String TEXT = "Test\n" +
+ "Test2";
+
+ BatchLineReader reader = create(TEXT);
+
+ assertEquals("Test\n", reader.readLine());
+ assertEquals("Test2", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testCR() throws Exception {
+ final String TEXT = "Test\r" +
+ "Test2";
+
+ BatchLineReader reader = create(TEXT);
+
+ assertEquals("Test\r", reader.readLine());
+ assertEquals("Test2", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testCombined() throws Exception {
+ BatchLineReader reader = create(TEXT_COMBINED);
+
+ assertEquals("Test\r", reader.readLine());
+ assertEquals("Test2\r\n", reader.readLine());
+ assertEquals("Test3\n", reader.readLine());
+ assertEquals("Test4\r", reader.readLine());
+ assertEquals("\r", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("Test5\n", reader.readLine());
+ assertEquals("Test6\r\n", reader.readLine());
+ assertEquals("Test7\n", reader.readLine());
+ assertEquals("\n", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testCombinedBufferSizeTwo() throws Exception {
+ BatchLineReader reader = create(TEXT_COMBINED, 2);
+
+ assertEquals("Test\r", reader.readLine());
+ assertEquals("Test2\r\n", reader.readLine());
+ assertEquals("Test3\n", reader.readLine());
+ assertEquals("Test4\r", reader.readLine());
+ assertEquals("\r", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("Test5\n", reader.readLine());
+ assertEquals("Test6\r\n", reader.readLine());
+ assertEquals("Test7\n", reader.readLine());
+ assertEquals("\n", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testCombinedBufferSizeOne() throws Exception {
+ final String TEXT = "Test\r" +
+ "Test2\r\n" +
+ "Test3\n" +
+ "Test4\r" +
+ "\r" +
+ "\r\n" +
+ "\r\n" +
+ "Test5\n" +
+ "Test6\r\n" +
+ "Test7\n" +
+ "\r\n";
+
+ BatchLineReader reader = create(TEXT, 1);
+
+ assertEquals("Test\r", reader.readLine());
+ assertEquals("Test2\r\n", reader.readLine());
+ assertEquals("Test3\n", reader.readLine());
+ assertEquals("Test4\r", reader.readLine());
+ assertEquals("\r", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertEquals("Test5\n", reader.readLine());
+ assertEquals("Test6\r\n", reader.readLine());
+ assertEquals("Test7\n", reader.readLine());
+ assertEquals("\r\n", reader.readLine());
+ assertNull(reader.readLine());
+ assertNull(reader.readLine());
+
+ reader.close();
+ }
+
+ @Test
+ public void testDoubleLF() throws Exception {
+ final String TEXT = "Test\r" +
+ "\r";
+
+ BatchLineReader reader = create(TEXT, 1);
+
+ assertEquals("Test\r", reader.readLine());
+ assertEquals("\r", reader.readLine());
+ reader.close();
+ }
+
+ @Test
+ public void testReadMoreBufferCapacityThanCharacterAvailable() throws Exception {
+ final String TEXT = "Foo";
+ byte[] buffer = new byte[20];
+
+ BatchLineReader reader = create(TEXT);
+ assertEquals(3, reader.read(buffer, 0, 20));
+ assertEquals(-1, reader.read(buffer, 0, 20));
+ reader.close();
+
+ BatchLineReader readerBufferOne = create(TEXT, 1);
+ assertEquals(3, readerBufferOne.read(buffer, 0, 20));
+ assertEquals(-1, readerBufferOne.read(buffer, 0, 20));
+ readerBufferOne.close();
+ }
+
+ @Test
+ public void testLineEqualsAndHashCode() {
+ Line l1 = new Line("The first line", 1);
+ Line l2 = new Line("The first line", 1);
+ Line l3 = new Line("The second line", 2);
+
+ assertEquals(l1, l2);
+ assertFalse(l1.equals(l3));
+ assertTrue(l1.hashCode() != l3.hashCode());
+ }
+
- // @Test(expected = IllegalArgumentException.class)
- // public void testSkipNegative() throws Exception {
- // BufferedReaderIncludingLineEndings reader = create("123");
- // reader.skip(-1);
- // }
-
- @Test(expected = IllegalArgumentException.class)
- public void testFailBufferSizeZero() throws Exception {
- BatchLineReader reader = create(TEXT_EMPTY, 0);
- reader.close();
- }
++ @Test
++ public void testToList() throws Exception {
++ BatchLineReader reader = create(TEXT_COMBINED);
++ List<String> stringList = reader.toList();
+
- @Test(expected = IllegalArgumentException.class)
- public void testFailBufferSizeNegative() throws Exception {
- BatchLineReader reader = create(TEXT_EMPTY, -1);
++ assertEquals(11, stringList.size());
++ assertEquals("Test\r", stringList.get(0));
++ assertEquals("Test2\r\n", stringList.get(1));
++ assertEquals("Test3\n", stringList.get(2));
++ assertEquals("Test4\r", stringList.get(3));
++ assertEquals("\r", stringList.get(4));
++ assertEquals("\r\n", stringList.get(5));
++ assertEquals("\r\n", stringList.get(6));
++ assertEquals("Test5\n", stringList.get(7));
++ assertEquals("Test6\r\n", stringList.get(8));
++ assertEquals("Test7\n", stringList.get(9));
++ assertEquals("\n", stringList.get(10));
+ reader.close();
+ }
+
+ @Test
- public void testToList() throws Exception {
++ public void testToLineList() throws Exception {
+ BatchLineReader reader = create(TEXT_COMBINED);
+ List<Line> stringList = reader.toLineList();
+
+ assertEquals(11, stringList.size());
+ assertEquals("Test\r", stringList.get(0).toString());
+ assertEquals("Test2\r\n", stringList.get(1).toString());
+ assertEquals("Test3\n", stringList.get(2).toString());
+ assertEquals("Test4\r", stringList.get(3).toString());
+ assertEquals("\r", stringList.get(4).toString());
+ assertEquals("\r\n", stringList.get(5).toString());
+ assertEquals("\r\n", stringList.get(6).toString());
+ assertEquals("Test5\n", stringList.get(7).toString());
+ assertEquals("Test6\r\n", stringList.get(8).toString());
+ assertEquals("Test7\n", stringList.get(9).toString());
+ assertEquals("\n", stringList.get(10).toString());
+ reader.close();
+ }
+
++ @Test
++ public void testBatchContent() throws Exception {
++ String batchContent = getFileContent("/batchLarge.batch", "utf-8");
++ BatchLineReader reader = create(batchContent);
++
++ List<String> lines = reader.toList();
++ assertEquals(2422, lines.size());
++ assertEquals("--batch_8194-cf13-1f56\n", lines.get(0));
++ assertEquals(" <d:City m:type=\"RefScenario.c_City\">\n", lines.get(1402));
++ assertEquals("\n", lines.get(1903));
++ assertEquals("--batch_8194-cf13-1f56--", lines.get(2421));
++ }
++
++ private String getFileContent(String fileName, String charset) throws IOException {
++ byte[] content = getFileContent(fileName);
++ return new String(content, Charset.forName(charset));
++ }
++
++ private byte[] getFileContent(String fileName) throws IOException {
++ final InputStream input = ClassLoader.class.getResourceAsStream(fileName);
++ if (input == null) {
++ throw new IOException("Requested file '" + fileName + "' was not found.");
++ }
++ ByteArrayOutputStream output = new ByteArrayOutputStream();
++ ByteBuffer inBuffer = ByteBuffer.allocate(8192);
++ ReadableByteChannel ic = Channels.newChannel(input);
++ WritableByteChannel oc = Channels.newChannel(output);
++ while (ic.read(inBuffer) > 0) {
++ inBuffer.flip();
++ oc.write(inBuffer);
++ inBuffer.rewind();
++ }
++ return output.toByteArray();
++ }
++
++ @Test(expected = IllegalArgumentException.class)
++ public void testFailBufferSizeZero() throws Exception {
++ BatchLineReader reader = create(TEXT_EMPTY, 0);
++ reader.close();
++ }
++
++ @Test(expected = IllegalArgumentException.class)
++ public void testFailBufferSizeNegative() throws Exception {
++ BatchLineReader reader = create(TEXT_EMPTY, -1);
++ reader.close();
++ }
++
+ private BatchLineReader create(final String inputString) throws Exception {
+ return new BatchLineReader(new ByteArrayInputStream(inputString
+ .getBytes("UTF-8")));
+ }
+
+ private BatchLineReader create(final String inputString, final int bufferSize) throws Exception {
+ return new BatchLineReader(new ByteArrayInputStream(inputString
+ .getBytes("UTF-8")), bufferSize);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/594ad4ab/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/BatchResponseSerializerTest.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/BatchResponseSerializerTest.java
index f73479b,c5d0653..9570d35
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/BatchResponseSerializerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/BatchResponseSerializerTest.java
@@@ -22,11 -22,10 +22,12 @@@ import static org.junit.Assert.assertEq
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayInputStream;
import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
++import java.util.Random;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
@@@ -96,219 -93,7 +97,219 @@@ public class BatchResponseSerializerTes
assertEquals(CRLF, body.get(line++));
assertEquals(CRLF, body.get(line++));
assertTrue(body.get(line++).contains("--changeset_"));
- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
+ }
+
+ @Test
+ public void testBatchResponseUmlautsUtf8() throws Exception {
+ final List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE,
+ ContentType.APPLICATION_JSON.toContentTypeString() + "; charset=UTF-8");
+ response.setContent(IOUtils.toInputStream("Wälter Winter" + CRLF));
+
+ List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+ responses.add(response);
+ parts.add(new ODataResponsePart(responses, false));
+
+ ODataResponse changeSetResponse = new ODataResponse();
+ changeSetResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+ changeSetResponse.setHeader(HttpHeader.CONTENT_ID, "1");
+ responses = new ArrayList<ODataResponse>(1);
+ responses.add(changeSetResponse);
+ parts.add(new ODataResponsePart(responses, true));
+
+ BatchResponseSerializer serializer = new BatchResponseSerializer();
+ final InputStream content = serializer.serialize(parts, BOUNDARY);
+ assertNotNull(content);
+ final BatchLineReader reader =
+ new BatchLineReader(content);
+ final List<String> body = reader.toList();
+ reader.close();
+
+ int line = 0;
+ assertEquals(24, body.size());
assertTrue(body.get(line++).contains("--batch_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
+ assertEquals("Content-Type: application/json; charset=UTF-8" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 16" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("Wälter Winter" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--batch_"));
+ assertTrue(body.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals("Content-ID: 1" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 204 No Content" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 0" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
+ }
+
+ @Test
+ public void testBatchResponseUmlautsUtf8BodyIsoHeader() throws Exception {
+ final List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE,
+ ContentType.APPLICATION_JSON.toContentTypeString() + "; charset=UTF-8");
+ response.setContent(IOUtils.toInputStream("Wälter Winter" + CRLF));
+
+ List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+ responses.add(response);
+ parts.add(new ODataResponsePart(responses, false));
+
+ ODataResponse changeSetResponse = new ODataResponse();
+ changeSetResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+ changeSetResponse.setHeader(HttpHeader.CONTENT_ID, "1");
+
+ byte[] umlauts = "äüö".getBytes(CS_ISO_8859_1);
+ changeSetResponse.setHeader("Custom-Header", new String(umlauts, CS_ISO_8859_1));
+ responses = new ArrayList<ODataResponse>(1);
+ responses.add(changeSetResponse);
+ parts.add(new ODataResponsePart(responses, true));
+
+ BatchResponseSerializer serializer = new BatchResponseSerializer();
+ final InputStream content = serializer.serialize(parts, BOUNDARY);
+ assertNotNull(content);
+ final BatchLineReader reader =
+ new BatchLineReader(content);
+ final List<String> body = reader.toList();
+ reader.close();
+
+ int line = 0;
+ assertEquals(25, body.size());
+ assertTrue(body.get(line++).contains("--batch_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
+ assertEquals("Content-Type: application/json; charset=UTF-8" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 16" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("Wälter Winter" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--batch_"));
+ assertTrue(body.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals("Content-ID: 1" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 204 No Content" + CRLF, body.get(line++));
+ assertEquals("Custom-Header: äüö" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 0" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
+ }
+
+ @Test
+ public void testBatchResponseUmlautsUtf8BodyAndHeader() throws Exception {
+ final List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE,
+ ContentType.APPLICATION_JSON.toContentTypeString() + "; charset=UTF-8");
+ response.setContent(IOUtils.toInputStream("Wälter Winter" + CRLF));
+
+ List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+ responses.add(response);
+ parts.add(new ODataResponsePart(responses, false));
+
+ ODataResponse changeSetResponse = new ODataResponse();
+ changeSetResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+ changeSetResponse.setHeader(HttpHeader.CONTENT_ID, "1");
+
+// byte[] umlauts = "äüö".getBytes(CS_UTF_8);
+// changeSetResponse.setHeader("Custom-Header", new String(umlauts, CS_UTF_8));
+ changeSetResponse.setHeader("Custom-Header", "äüö");
+ responses = new ArrayList<ODataResponse>(1);
+ responses.add(changeSetResponse);
+ parts.add(new ODataResponsePart(responses, true));
+
+ BatchResponseSerializer serializer = new BatchResponseSerializer();
+ final InputStream content = serializer.serialize(parts, BOUNDARY);
+ assertNotNull(content);
+ final BatchLineReader reader =
+ new BatchLineReader(content);
+ final List<String> body = reader.toList();
+ reader.close();
+
+ assertEquals(25, body.size());
+ // TODO: check: with latest change in BatchResponseSerializer is not possible
+ // to set header values with UTF-8 (only iso-8859-1)
+// assertEquals("Custom-Header: äüö" + CRLF, body.get(19));
+ assertEquals("Custom-Header: äüö" + CRLF, body.get(19));
+ }
+
+ @Test
+ public void testBatchResponseUmlautsIso() throws Exception {
+ final List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
+ ODataResponse response = new ODataResponse();
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE,
+ ContentType.APPLICATION_JSON.toContentTypeString() + "; charset=iso-8859-1");
+ byte[] payload = ("Wälter Winter" + CRLF).getBytes("iso-8859-1");
+ response.setContent(new ByteArrayInputStream(payload));
+
+ List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+ responses.add(response);
+ parts.add(new ODataResponsePart(responses, false));
+
+ ODataResponse changeSetResponse = new ODataResponse();
+ changeSetResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+ changeSetResponse.setHeader(HttpHeader.CONTENT_ID, "1");
+ responses = new ArrayList<ODataResponse>(1);
+ responses.add(changeSetResponse);
+ parts.add(new ODataResponsePart(responses, true));
+
+ BatchResponseSerializer serializer = new BatchResponseSerializer();
+ final InputStream content = serializer.serialize(parts, BOUNDARY);
+ assertNotNull(content);
+ final BatchLineReader reader =
+ new BatchLineReader(content);
+ final List<String> body = reader.toList();
+ reader.close();
+
+ int line = 0;
+ assertEquals(24, body.size());
+ assertTrue(body.get(line++).contains("--batch_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
+ assertEquals("Content-Type: application/json; charset=iso-8859-1" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 15" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("Wälter Winter" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--batch_"));
+ assertTrue(body.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
+ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
+ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
+ assertEquals("Content-ID: 1" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals("HTTP/1.1 204 No Content" + CRLF, body.get(line++));
+ assertEquals("Content-Length: 0" + CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertEquals(CRLF, body.get(line++));
+ assertTrue(body.get(line++).contains("--changeset_"));
- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
}
@Test
@@@ -362,7 -147,7 +363,7 @@@
assertEquals(CRLF, body.get(line++));
assertEquals(CRLF, body.get(line++));
assertTrue(body.get(line++).contains("--changeset_"));
-- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
}
@Test
@@@ -397,7 -182,7 +398,54 @@@
assertEquals("Content-Length: 13" + CRLF, body.get(line++));
assertEquals(CRLF, body.get(line++));
assertEquals("Walter Winter" + CRLF, body.get(line++));
++ assertTrue(body.get(line).contains("--batch_"));
++ }
++
++ @Test
++ public void testResponseVeryLargeHeader() throws Exception {
++ List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
++ ODataResponse response = new ODataResponse();
++ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
++ response.setHeader(HttpHeader.CONTENT_TYPE, "application/json");
++ final String chValue = generateTestData(20000);
++ response.setHeader("Custom-Header", chValue);
++ response.setContent(IOUtils.toInputStream("Walter Winter"));
++
++ List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
++ responses.add(response);
++ parts.add(new ODataResponsePart(responses, false));
++
++ final BatchResponseSerializer serializer = new BatchResponseSerializer();
++ final InputStream content = serializer.serialize(parts, BOUNDARY);
++
++ assertNotNull(content);
++ final BatchLineReader reader =
++ new BatchLineReader(content);
++ final List<String> body = reader.toList();
++ reader.close();
++
++ int line = 0;
++ assertEquals(11, body.size());
assertTrue(body.get(line++).contains("--batch_"));
++ assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
++ assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
++ assertEquals(CRLF, body.get(line++));
++ assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
++ assertEquals("Custom-Header: " + chValue + CRLF, body.get(line++));
++ assertEquals("Content-Type: application/json" + CRLF, body.get(line++));
++ assertEquals("Content-Length: 13" + CRLF, body.get(line++));
++ assertEquals(CRLF, body.get(line++));
++ assertEquals("Walter Winter" + CRLF, body.get(line++));
++ assertTrue(body.get(line).contains("--batch_"));
++ }
++
++ private String generateTestData(int amount) {
++ StringBuilder sb = new StringBuilder();
++ Random r = new Random();
++ for (int j = 0; j < amount; j++) {
++ sb.append((char)(65 + r.nextInt(25)));
++ }
++ return sb.toString();
}
@Test
@@@ -436,6 -221,6 +484,6 @@@
assertEquals(CRLF, body.get(line++));
assertEquals(CRLF, body.get(line++));
assertTrue(body.get(line++).contains("--changeset_"));
-- assertTrue(body.get(line++).contains("--batch_"));
++ assertTrue(body.get(line).contains("--batch_"));
}
}