[OLINGO-1003] server batch handling corrections

- binary content in bodies
- absolute-path URIs
- HTTP headers with allowed non-letter characters

Signed-off-by: Christian Amend <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/14278ac1
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/14278ac1
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/14278ac1

Branch: refs/heads/master
Commit: 14278ac189aad2513632b7f4ec519b2197717469
Parents: 20a0070
Author: Klaus Straubinger <[email protected]>
Authored: Thu Sep 15 13:59:50 2016 +0200
Committer: Christian Amend <[email protected]>
Committed: Thu Sep 15 14:09:34 2016 +0200

----------------------------------------------------------------------
 .../fit/tecsvc/client/BatchClientITCase.java    |  346 +-
 .../batch/BatchDeserializerException.java       |    4 +-
 .../deserializer/batch/BatchLineReader.java     |   46 +-
 .../deserializer/batch/BatchParserCommon.java   |   15 +-
 .../batch/BatchRequestTransformator.java        |   64 +-
 .../batch/BatchTransformatorCommon.java         |   35 +-
 .../batch/HttpRequestStatusLine.java            |   13 +-
 .../server-core-exceptions-i18n.properties      |    2 +-
 .../deserializer/batch/BatchLineReaderTest.java |  100 +-
 .../batch/BatchParserCommonTest.java            |   66 +
 .../batch/BatchRequestParserTest.java           | 1401 ++-
 .../batch/HttpRequestStatusLineTest.java        |   63 +-
 .../serializer/BatchResponseSerializerTest.java |  308 +-
 .../src/test/resources/batchLarge.batch         | 8857 +++++++++++++-----
 .../src/test/resources/batchWithPost.batch      |   39 -
 15 files changed, 7866 insertions(+), 3493 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
index 913d9f9..a03d3c7 100644
--- 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
+++ 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java
@@ -23,11 +23,12 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayInputStream;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.Iterator;
 
 import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
 import org.apache.olingo.client.api.communication.request.batch.BatchManager;
 import 
org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest;
 import 
org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
@@ -37,6 +38,8 @@ import 
org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateR
 import org.apache.olingo.client.api.communication.request.cud.UpdateType;
 import 
org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
 import 
org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import 
org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import 
org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityCreateRequest;
 import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
 import 
org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
 import 
org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
@@ -45,10 +48,8 @@ import 
org.apache.olingo.client.api.communication.response.ODataRetrieveResponse
 import org.apache.olingo.client.api.domain.ClientEntity;
 import org.apache.olingo.client.api.domain.ClientEntitySet;
 import org.apache.olingo.client.api.domain.ClientObjectFactory;
+import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.http.HttpClientException;
-import org.apache.olingo.client.api.uri.URIBuilder;
-import 
org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.PreferenceName;
@@ -90,11 +91,9 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     // Try to create entity, with invalid type
     ClientObjectFactory factory = getFactory();
     final ClientEntity entity = factory.newEntity(ES_NOT_AVAILABLE);
-    entity.getProperties().add(factory.newPrimitiveProperty(PROPERTY_STRING, 
factory
-            .newPrimitiveValueBuilder()
-            .buildString("1")));
-    final ODataBatchRequest batchRequest = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-    final BatchManager payloadManager = batchRequest.payloadManager();
+    entity.getProperties().add(
+        factory.newPrimitiveProperty(PROPERTY_STRING, 
factory.newPrimitiveValueBuilder().buildString("1")));
+    BatchManager payloadManager = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI).payloadManager();
     final ODataChangeset changeset = payloadManager.addChangeset();
     final URI targetURI = getClient().newURIBuilder(SERVICE_URI)
         .appendEntitySetSegment(ES_NOT_AVAILABLE_NAME)
@@ -124,10 +123,10 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
   @Test
   public void emptyBatchRequest() {
     // create your request
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-    final ODataBatchResponse response = payload.getResponse();
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    final ODataBatchResponse response = request.payloadManager().getResponse();
+    saveCookieHeader(response);
 
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
     assertEquals("Accepted", response.getStatusMessage());
@@ -137,16 +136,15 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
   }
 
   @Test
-  public void getBatchRequestWithRelativeUris() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-
-    // create new request
-    appendGetRequest(payload, "ESAllPrim", 32767, true);
+  public void getBatchRequestWithRelativeUris() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    payload.addRequest(createGetRequest("ESAllPrim", 32767, true));
 
     // Fetch result
     final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
 
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
     assertEquals("Accepted", response.getStatusMessage());
@@ -160,24 +158,25 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     ODataResponse oDataResponse = item.next();
     assertNotNull(oDataResponse);
     assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
-    assertEquals(1, oDataResponse.getHeader("OData-Version").size());
-    assertEquals("4.0", oDataResponse.getHeader("OData-Version").toArray()[0]);
-    assertEquals(1, oDataResponse.getHeader("Content-Length").size());
-    assertEquals("605", 
oDataResponse.getHeader("Content-Length").toArray()[0]);
-    assertEquals(ContentType.JSON.toContentTypeString(), 
oDataResponse.getContentType());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
+    assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
+    assertEquals(isJson() ? "605" : "2246", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertContentType(oDataResponse.getContentType());
   }
 
   @Test
-  public void getBatchRequest() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
+  public void getBatchRequest() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
 
     // create new request
-    appendGetRequest(payload, "ESAllPrim", 32767, false);
+    payload.addRequest(createGetRequest("ESAllPrim", 32767, false));
 
     // Fetch result
     final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
 
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
     assertEquals("Accepted", response.getStatusMessage());
@@ -191,25 +190,93 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     ODataResponse oDataResponse = item.next();
     assertNotNull(oDataResponse);
     assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
-    assertEquals(1, oDataResponse.getHeader("OData-Version").size());
-    assertEquals("4.0", oDataResponse.getHeader("OData-Version").toArray()[0]);
-    assertEquals(1, oDataResponse.getHeader("Content-Length").size());
-    assertEquals("605", 
oDataResponse.getHeader("Content-Length").toArray()[0]);
-    assertEquals(ContentType.JSON.toContentTypeString(), 
oDataResponse.getContentType());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
+    assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
+    assertEquals(isJson() ? "605" : "2246", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertContentType(oDataResponse.getContentType());
   }
 
   @Test
-  public void errorWithoutContinueOnErrorPreferHeader() throws 
URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+  public void binaryContent() throws Exception {
+    BatchManager payload = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI).payloadManager();
+    ODataMediaEntityCreateRequest<ClientEntity> request = 
getClient().getCUDRequestFactory()
+        .getMediaEntityCreateRequest(
+            
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESMedia").build(),
+            new ByteArrayInputStream(new byte[] { -42, 0, 1 }));
+    
request.setContentType(ContentType.APPLICATION_OCTET_STREAM.toContentTypeString());
+    request.addCustomHeader("Custom-Header-0123456789", "!!!");
+    payload.addRequest(request);
+
+    
payload.addRequest(getClient().getRetrieveRequestFactory().getMediaRequest(URI.create(
+        "ESMedia(5)/$value")));
 
-    final BatchManager payload = request.payloadManager();
+    final ODataBatchResponse response = payload.getResponse();
+    assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
 
-    appendGetRequest(payload, "ESAllPrim", 32767, false); // Without error
-    appendGetRequest(payload, "ESAllPrim", 42, false); // Error ( Key does not 
exist )
-    appendGetRequest(payload, "ESAllPrim", 0, false); // Without error
+    Iterator<ODataBatchResponseItem> iter = response.getBody();
+    assertTrue(iter.hasNext());
+    ODataBatchResponseItem item = iter.next();
+    assertFalse(item.isChangeset());
+
+    ODataResponse oDataResponse = item.next();
+    assertNotNull(oDataResponse);
+    assertEquals(HttpStatusCode.CREATED.getStatusCode(), 
oDataResponse.getStatusCode());
+    assertFalse(item.hasNext());
+
+    assertTrue(iter.hasNext());
+    oDataResponse = iter.next().next();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
+    assertEquals(ContentType.APPLICATION_OCTET_STREAM.toContentTypeString(), 
oDataResponse.getContentType());
+    // TODO: Correct the client code so that the following content 
verification can be enabled.
+//    InputStream rawResponse = oDataResponse.getRawResponse();
+//    assertEquals(-42, (byte) rawResponse.read());
+//    assertEquals(0, rawResponse.read());
+//    assertEquals(1, rawResponse.read());
+//    assertEquals(-1, rawResponse.read());
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void absolutePath() {
+    BatchManager payload = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI).payloadManager();
+    final URI uri = URI.create(
+        
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESTwoPrim").appendKeySegment(32767).build()
+            .getRawPath());
+    ODataPropertyRequest<ClientProperty> request = 
getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(uri);
+    setCookieHeader(request);
+    request.addCustomHeader("Custom-Header-0123456789", "!!!");
+    payload.addRequest(request);
+
+    final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
+
+    Iterator<ODataBatchResponseItem> iter = response.getBody();
+    assertTrue(iter.hasNext());
+    ODataBatchResponseItem item = iter.next();
+    assertFalse(item.isChangeset());
+
+    ODataResponse oDataResponse = item.next();
+    assertNotNull(oDataResponse);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
+    assertFalse(item.hasNext());
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void errorWithoutContinueOnErrorPreferHeader() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    payload.addRequest(createGetRequest("ESAllPrim", 32767, false)); // 
Without error
+    payload.addRequest(createGetRequest("ESAllPrim", 42, false)); // Error ( 
Key does not exist )
+    payload.addRequest(createGetRequest("ESAllPrim", 0, false)); // Without 
error
 
     // Fetch result
     final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
 
     final Iterator<ODataBatchResponseItem> iter = response.getBody();
@@ -222,11 +289,11 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     ODataResponse oDataResponse = item.next();
     assertNotNull(oDataResponse);
     assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
-    assertEquals(1, oDataResponse.getHeader("OData-Version").size());
-    assertEquals("4.0", oDataResponse.getHeader("OData-Version").toArray()[0]);
-    assertEquals(1, oDataResponse.getHeader("Content-Length").size());
-    assertEquals("605", 
oDataResponse.getHeader("Content-Length").toArray()[0]);
-    assertEquals(ContentType.JSON.toContentTypeString(), 
oDataResponse.getContentType());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
+    assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
+    assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
+    assertEquals(isJson() ? "605" : "2246", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertContentType(oDataResponse.getContentType());
 
     // Check second get request
     assertTrue(iter.hasNext());
@@ -242,17 +309,18 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
   }
 
   @Test
-  public void invalidAbsoluteUri() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-    final URI uri = new URI(SERVICE_URI + "../ESAllPrim(32767)");
-    final ODataEntityRequest<ClientEntity> queryReq = 
getClient().getRetrieveRequestFactory().getEntityRequest(uri);
-    queryReq.setFormat(ContentType.JSON);
+  public void invalidAbsoluteUri() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    ODataEntityRequest<ClientEntity> queryReq = 
getClient().getRetrieveRequestFactory().getEntityRequest(URI.create(
+        SERVICE_URI + "../ESAllPrim(32767)"));
+    queryReq.setFormat(getContentType());
     payload.addRequest(queryReq);
 
     // Fetch result
     final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
 
     final Iterator<ODataBatchResponseItem> bodyIterator = response.getBody();
@@ -265,48 +333,54 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), 
oDataResponse.getStatusCode());
   }
 
-  @Test(expected = HttpClientException.class)
-  public void invalidHost() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-    final URI uri = new URI("http://otherhost/odata/ESAllPrim(32767)");
-    final ODataEntityRequest<ClientEntity> queryReq = 
getClient().getRetrieveRequestFactory().getEntityRequest(uri);
-    queryReq.setFormat(ContentType.JSON);
-    payload.addRequest(queryReq);
-
-    // Fetch result
-    payload.getResponse();
+  @Test
+  public void invalidHost() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    
payload.addRequest(getClient().getRetrieveRequestFactory().getEntityRequest(URI.create(
+        "http://otherhost/odata/ESAllPrim(32767)")));
+
+    try {
+      payload.getResponse();
+    } catch (final HttpClientException e) {
+      assertTrue(e.getCause().getCause() instanceof ODataClientErrorException);
+      assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(),
+          ((ODataClientErrorException) 
e.getCause().getCause()).getStatusLine().getStatusCode());
+    }
   }
 
-  @Test(expected = HttpClientException.class)
-  public void invalidAbsoluteRequest() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-    final URI uri = new URI("/ESAllPrim(32767)");
-    final ODataEntityRequest<ClientEntity> queryReq = 
getClient().getRetrieveRequestFactory().getEntityRequest(uri);
-    queryReq.setFormat(ContentType.JSON);
-    payload.addRequest(queryReq);
-
-    // Fetch result
-    payload.getResponse();
+  @Test
+  public void invalidAbsoluteRequest() {
+    ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    
payload.addRequest(getClient().getRetrieveRequestFactory().getEntityRequest(URI.create(
+        "/ESAllPrim(32767)")));
+
+    try {
+      payload.getResponse();
+    } catch (final HttpClientException e) {
+      assertTrue(e.getCause().getCause() instanceof ODataClientErrorException);
+      assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(),
+          ((ODataClientErrorException) 
e.getCause().getCause()).getStatusLine().getStatusCode());
+    }
   }
 
   @Test
-  public void errorWithContinueOnErrorPreferHeader() throws Exception {
+  public void errorWithContinueOnErrorPreferHeader() {
     ODataClient client = getClient();
     client.getConfiguration().setContinueOnError(true);
-    final ODataBatchRequest request = 
client.getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-
-    final BatchManager payload = request.payloadManager();
-
-    appendGetRequest(payload, "ESAllPrim", 32767, false); // Without error
-    appendGetRequest(payload, "ESAllPrim", 42, false); // Error ( Key does not 
exist )
-    appendGetRequest(payload, "ESAllPrim", 0, false); // Without error
+    ODataBatchRequest request = 
client.getBatchRequestFactory().getBatchRequest(SERVICE_URI);
+    setCookieHeader(request);
+    BatchManager payload = request.payloadManager();
+    payload.addRequest(createGetRequest("ESAllPrim", 32767, false)); // 
Without error
+    payload.addRequest(createGetRequest("ESAllPrim", 42, false)); // Error ( 
Key does not exist )
+    payload.addRequest(createGetRequest("ESAllPrim", 0, false)); // Without 
error
 
     // Fetch result
     final ODataBatchResponse response = payload.getResponse();
+    saveCookieHeader(response);
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
     assertEquals(PreferenceName.CONTINUE_ON_ERROR.getName(),
         response.getHeader(HttpHeader.PREFERENCE_APPLIED).iterator().next());
@@ -322,10 +396,10 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     assertNotNull(oDataResponse);
     assertEquals(HttpStatusCode.OK.getStatusCode(), 
oDataResponse.getStatusCode());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
-    assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).toArray()[0]);
+    assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals("605", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).toArray()[0]);
-    assertEquals(ContentType.JSON.toContentTypeString(), 
oDataResponse.getContentType());
+    assertEquals(isJson() ? "605" : "2246", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertContentType(oDataResponse.getContentType());
 
     // Check second get request
     assertTrue(bodyIterator.hasNext());
@@ -347,17 +421,15 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size());
     assertEquals("4.0", 
oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next());
     assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size());
-    assertEquals("517", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
-    assertEquals(ContentType.JSON.toContentTypeString(), 
oDataResponse.getContentType());
+    assertEquals(isJson() ? "517" : "2138", 
oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next());
+    assertContentType(oDataResponse.getContentType());
   }
 
   @Test
-  public void changesetWithReferences() throws EdmPrimitiveTypeException, 
URISyntaxException {
-    // create your request
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-    final BatchManager streamManager = request.payloadManager();
+  public void changesetWithReferences() {
+    BatchManager payload = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI).payloadManager();
 
-    final ODataChangeset changeset = streamManager.addChangeset();
+    final ODataChangeset changeset = payload.addChangeset();
     final ClientEntity entityESAllPrim = getFactory().newEntity(new 
FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
 
     
entityESAllPrim.getProperties().add(getFactory().newPrimitiveProperty("PropertyDouble",
@@ -369,12 +441,12 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
             .appendKeySegment(-365)
             .build()));
 
-    final URIBuilder uriBuilder = 
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim");
+    final URI uri = 
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").build();
 
     // add create request
     final ODataEntityCreateRequest<ClientEntity> createReq =
-        
getClient().getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), 
entityESAllPrim);
-    createReq.setFormat(ContentType.JSON);
+        getClient().getCUDRequestFactory().getEntityCreateRequest(uri, 
entityESAllPrim);
+    createReq.setFormat(getContentType());
     changeset.addRequest(createReq);
 
     // retrieve request reference
@@ -387,11 +459,11 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
 
     final ODataEntityUpdateRequest<ClientEntity> updateReq = 
getClient().getCUDRequestFactory().getEntityUpdateRequest(
         URI.create("$" + createRequestRef), UpdateType.PATCH, entityUpdate);
-    updateReq.setFormat(ContentType.JSON);
+    updateReq.setFormat(getContentType());
 
     changeset.addRequest(updateReq);
 
-    final ODataBatchResponse response = streamManager.getResponse();
+    final ODataBatchResponse response = payload.getResponse();
     assertEquals(HttpStatusCode.ACCEPTED.getStatusCode(), 
response.getStatusCode());
     final String cookie = 
response.getHeader(HttpHeader.SET_COOKIE).iterator().next();
 
@@ -399,25 +471,23 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     final Iterator<ODataBatchResponseItem> bodyIterator = response.getBody();
     final ODataBatchResponseItem item = bodyIterator.next();
 
-    assertTrue(item instanceof ODataChangesetResponseItem);
-    final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) 
item;
-    assertTrue(chgitem.hasNext());
-    ODataResponse res = chgitem.next();
+    assertTrue(item.hasNext());
+    ODataResponse res = item.next();
     assertEquals(HttpStatusCode.CREATED.getStatusCode(), res.getStatusCode());
     assertTrue(res instanceof ODataEntityCreateResponse);
     final ODataEntityCreateResponse<?> createResponse = 
((ODataEntityCreateResponse<?>) res);
 
-    res = chgitem.next();
+    res = item.next();
     assertEquals(HttpStatusCode.OK.getStatusCode(), res.getStatusCode());
     assertTrue(res instanceof ODataEntityUpdateResponse);
 
     final ODataEntitySetRequest<ClientEntitySet> req = 
getClient().getRetrieveRequestFactory().getEntitySetRequest(
-        new 
URI(createResponse.getHeader(HttpHeader.LOCATION).iterator().next() + 
"/NavPropertyETTwoPrimMany"));
-    req.setFormat(ContentType.JSON);
+        
URI.create(createResponse.getHeader(HttpHeader.LOCATION).iterator().next() + 
"/NavPropertyETTwoPrimMany"));
+    req.setFormat(getContentType());
     req.addCustomHeader(HttpHeader.COOKIE, cookie);
     final ODataRetrieveResponse<ClientEntitySet> getResponse = req.execute();
 
-    assertEquals(32767, getResponse.getBody()
+    assertShortOrInt(32767, getResponse.getBody()
         .getEntities()
         .get(0)
         .getProperty("PropertyInt16")
@@ -426,24 +496,22 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
   }
 
   @Test
-  public void changesetBatchRequest() throws URISyntaxException {
-    final ODataBatchRequest request = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI);
-    final BatchManager payload = request.payloadManager();
+  public void changesetBatchRequest() {
+    BatchManager payload = 
getClient().getBatchRequestFactory().getBatchRequest(SERVICE_URI).payloadManager();
     // -----------------------------
     // - Append get request
     // -----------------------------
-    appendGetRequest(payload, "ESAllPrim", 32767, false); // Without error
+    payload.addRequest(createGetRequest("ESAllPrim", 32767, false));
 
     // -----------------------------
     // - Append change set
     // -----------------------------
     final ODataChangeset changeset = payload.addChangeset();
 
-    // ------------------------
+    // -----------------------------
     // POST request (Insert)
-    URIBuilder targetURI =
-        
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim");
-    URI editLink = targetURI.build();
+    // -----------------------------
+    URI targetURI = 
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").build();
 
     ClientObjectFactory factory = getFactory();
     ClientEntity postEntity = factory.newEntity(new 
FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
@@ -457,34 +525,32 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
             factory.newPrimitiveValueBuilder().buildDouble(3.1415)));
 
     final ODataEntityCreateRequest<ClientEntity> createRequest =
-        getClient().getCUDRequestFactory().getEntityCreateRequest(editLink, 
postEntity);
-    createRequest.setFormat(ContentType.JSON);
+        getClient().getCUDRequestFactory().getEntityCreateRequest(targetURI, 
postEntity);
+    createRequest.setFormat(getContentType());
 
     changeset.addRequest(createRequest);
 
-    // ------------------------
+    // -----------------------------
     // Patch request (Update)
-    targetURI = 
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(0);
-    editLink = targetURI.build();
-
+    // -----------------------------
     ClientEntity patchEntity = factory.newEntity(new 
FullQualifiedName(SERVICE_NAMESPACE, "ETAllPrim"));
-    patchEntity.setEditLink(editLink);
+    patchEntity.setEditLink(
+        
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(0).build());
 
     
patchEntity.getProperties().add(factory.newPrimitiveProperty("PropertyDouble",
             factory.newPrimitiveValueBuilder().buildDouble(3.1415)));
 
     ODataEntityUpdateRequest<ClientEntity> changeReq =
         
getClient().getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, 
patchEntity);
-    changeReq.setFormat(ContentType.JSON);
+    changeReq.setFormat(getContentType());
     changeset.addRequest(changeReq);
 
-    // ------------------------
+    // -----------------------------
     // Patch request (Upsert)
-    targetURI = 
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(15);
-    editLink = targetURI.build();
-
+    // -----------------------------
     patchEntity = factory.newEntity(new FullQualifiedName(SERVICE_NAMESPACE, 
"ETAllPrim"));
-    patchEntity.setEditLink(editLink);
+    patchEntity.setEditLink(
+        
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").appendKeySegment(15).build());
 
     
patchEntity.getProperties().add(factory.newPrimitiveProperty("PropertyDouble",
             factory.newPrimitiveValueBuilder().buildDouble(3.1415)));
@@ -496,13 +562,13 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
             .build()));
 
     changeReq = 
getClient().getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, 
patchEntity);
-    changeReq.setFormat(ContentType.JSON);
+    changeReq.setFormat(getContentType());
     changeset.addRequest(changeReq);
 
     // -----------------------------
     // - Append get request
     // -----------------------------
-    appendGetRequest(payload, "ESAllPrim", 0, false); // Without error
+    payload.addRequest(createGetRequest("ESAllPrim", 0, false));
 
     // -----------------------------
     // - Fetch result
@@ -520,7 +586,7 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
     assertTrue(response0 instanceof ODataRetrieveResponse);
     @SuppressWarnings("unchecked")
     ODataRetrieveResponse<ClientEntity> retrieveResponse = 
(ODataRetrieveResponse<ClientEntity>) response0;
-    assertEquals(34, retrieveResponse.getBody()
+    assertShortOrInt(34, retrieveResponse.getBody()
         .getProperty("PropertyDecimal")
         .getPrimitiveValue()
         .toValue());
@@ -568,15 +634,15 @@ public class BatchClientITCase extends 
AbstractParamTecSvcITCase {
         .toValue());
   }
 
-  private void appendGetRequest(final BatchManager manager, final String 
segment, final Object key,
-      final boolean isRelative)
-      throws URISyntaxException {
-    final URIBuilder targetURI = getClient().newURIBuilder(SERVICE_URI);
-    targetURI.appendEntitySetSegment(segment).appendKeySegment(key);
-    final URI uri = (isRelative) ? new 
URI(SERVICE_URI).relativize(targetURI.build()) : targetURI.build();
+  private ODataEntityRequest<ClientEntity> createGetRequest(final String 
segment, final Object key,
+      final boolean isRelative) {
+    final URI targetURI = getClient().newURIBuilder(SERVICE_URI)
+        .appendEntitySetSegment(segment).appendKeySegment(key)
+        .build();
+    final URI uri = isRelative ? URI.create(SERVICE_URI).relativize(targetURI) 
: targetURI;
 
     ODataEntityRequest<ClientEntity> queryReq = 
getClient().getRetrieveRequestFactory().getEntityRequest(uri);
-    queryReq.setFormat(ContentType.JSON);
-    manager.addRequest(queryReq);
+    queryReq.setAccept(getContentType().toContentTypeString());
+    return queryReq;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/BatchDeserializerException.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/BatchDeserializerException.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/BatchDeserializerException.java
index 6420ba6..24e2572 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/BatchDeserializerException.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/batch/BatchDeserializerException.java
@@ -39,6 +39,8 @@ public class BatchDeserializerException extends 
DeserializerException {
     /** parameter: line */
     INVALID_CONTENT_ID,
     /** parameter: line */
+    INVALID_HOST,
+    /** parameter: line */
     INVALID_HTTP_VERSION,
     /** parameter: line */
     INVALID_METHOD,
@@ -55,8 +57,6 @@ public class BatchDeserializerException extends 
DeserializerException {
     /** parameter: line */
     MISSING_CONTENT_ID,
     /** parameter: line */
-    MISSING_CONTENT_TRANSFER_ENCODING,
-    /** parameter: line */
     MISSING_CONTENT_TYPE,
     /** parameter: line */
     MISSING_MANDATORY_HEADER,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReader.java
----------------------------------------------------------------------
diff --git 
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
index c209ade..15d7672 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
@@ -33,8 +33,7 @@ public class BatchLineReader {
   private static final byte LF = '\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");
+  private static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
   public static final String BOUNDARY = "boundary";
   public static final String DOUBLE_DASH = "--";
   public static final String CRLF = "\r\n";
@@ -96,18 +95,17 @@ public class BatchLineReader {
   private void updateCurrentCharset(final String currentLine) {
     if (currentLine != null) {
       if (currentLine.startsWith(HttpHeader.CONTENT_TYPE)) {
-        //13 is content-type.length() + 1 for header value
-        String clValue = currentLine.substring(13, currentLine.length() - 
2).trim();
-        ContentType ct = ContentType.parse(clValue);
-        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);
+        final ContentType contentType = ContentType.parse(
+            currentLine.substring(HttpHeader.CONTENT_TYPE.length() + 1, 
currentLine.length() - 2).trim());
+        if (contentType != null) {
+          final String charsetString = 
contentType.getParameter(ContentType.PARAMETER_CHARSET);
+          currentCharset = charsetString == null ?
+              contentType.isCompatible(ContentType.APPLICATION_JSON) || 
contentType.getSubtype().contains("xml") ?
+                  Charset.forName("UTF-8") :
+                  DEFAULT_CHARSET :
+              Charset.forName(charsetString);
+
+          final String boundary = contentType.getParameter(BOUNDARY);
           if (boundary != null) {
             currentBoundary = DOUBLE_DASH + boundary;
           }
@@ -121,12 +119,8 @@ public class BatchLineReader {
   }
 
   private boolean isBoundary(final String currentLine) {
-    if ((currentBoundary + CRLF).equals(currentLine)) {
-      return true;
-    } else if ((currentBoundary + DOUBLE_DASH + CRLF).equals(currentLine)) {
-      return true;
-    }
-    return false;
+    return (currentBoundary + CRLF).equals(currentLine)
+        || (currentBoundary + DOUBLE_DASH + CRLF).equals(currentLine);
   }
 
   String readLine() throws IOException {
@@ -177,12 +171,8 @@ public class BatchLineReader {
     if (innerBuffer.position() == 0) {
       return null;
     } else {
-      String currentLine;
-      if (readState.isReadBody()) {
-        currentLine = new String(innerBuffer.array(), 0, 
innerBuffer.position(), getCurrentCharset());
-      } else {
-        currentLine = new String(innerBuffer.array(), 0, 
innerBuffer.position(), CS_ISO_8859_1);
-      }
+      final String currentLine = new String(innerBuffer.array(), 0, 
innerBuffer.position(),
+          readState.isReadBody() ? currentCharset : DEFAULT_CHARSET);
       updateCurrentCharset(currentLine);
       return currentLine;
     }
@@ -195,10 +185,6 @@ public class BatchLineReader {
     return limit;
   }
 
-  private Charset getCurrentCharset() {
-    return currentCharset;
-  }
-
   /**
    * Read state indicator (whether currently the <code>body</code> or 
<code>header</code> part is read).
    */

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommon.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommon.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommon.java
index c9ae89e..d1f4392 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommon.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommon.java
@@ -64,14 +64,14 @@ public class BatchParserCommon {
 
   public static String getBoundary(final String contentType, final int line) 
throws BatchDeserializerException {
     final ContentType type = parseContentType(contentType, 
ContentType.MULTIPART_MIXED, line);
-    String boundary = type.getParameter(BOUNDARY);
+    final String boundary = type.getParameter(BOUNDARY);
     if (boundary == null) {
       throw new BatchDeserializerException("Missing boundary.",
           BatchDeserializerException.MessageKeys.MISSING_BOUNDARY_DELIMITER, 
Integer.toString(line));
     }
-    boundary = boundary.trim();
-    if (PATTERN_BOUNDARY.matcher(boundary).matches()) {
-      return trimQuotes(boundary);
+    final Matcher matcher = PATTERN_BOUNDARY.matcher(boundary);
+    if (matcher.matches()) {
+      return matcher.group(1) == null ? matcher.group(2) : matcher.group(1);
     } else {
       throw new BatchDeserializerException("Invalid boundary format",
           BatchDeserializerException.MessageKeys.INVALID_BOUNDARY, 
Integer.toString(line));
@@ -111,13 +111,6 @@ public class BatchParserCommon {
     }
   }
 
-  private static String trimQuotes(final String boundary) {
-    if (boundary != null && boundary.length() >= 2 && 
boundary.startsWith("\"") && boundary.endsWith("\"")) {
-      return boundary.substring(1, boundary.length() - 1);
-    }
-    return boundary;
-  }
-
   public static List<List<Line>> splitMessageByBoundary(final List<Line> 
message, final String boundary)
       throws BatchDeserializerException {
     final List<List<Line>> messageParts = new LinkedList<List<Line>>();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestTransformator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestTransformator.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestTransformator.java
index b9174c9..006032b 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestTransformator.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestTransformator.java
@@ -34,7 +34,6 @@ import 
org.apache.olingo.server.api.deserializer.batch.BatchDeserializerExceptio
 import org.apache.olingo.server.api.deserializer.batch.BatchRequestPart;
 
 public class BatchRequestTransformator {
-  private static final Charset DEFAULT_CHARSET = Charset.forName("utf-8");
   private final String baseUri;
   private final String rawServiceResolutionUri;
 
@@ -47,7 +46,7 @@ public class BatchRequestTransformator {
     final List<ODataRequest> requests = new LinkedList<ODataRequest>();
     final List<BatchRequestPart> resultList = new 
ArrayList<BatchRequestPart>();
 
-    validateBodyPartHeader(bodyPart);
+    validateHeaders(bodyPart.getHeaders(), bodyPart.isChangeSet());
 
     for (BatchQueryOperation queryOperation : bodyPart.getRequests()) {
       requests.add(processQueryOperation(bodyPart, baseUri, queryOperation));
@@ -62,7 +61,7 @@ public class BatchRequestTransformator {
     if (bodyPart.isChangeSet()) {
       BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSetPart) 
queryOperation).getRequest();
       handleContentId(queryOperation, encapsulatedQueryOperation);
-      validateHeader(queryOperation, true);
+      validateHeaders(queryOperation.getHeaders(), false);
 
       return createRequest(encapsulatedQueryOperation, baseUri, 
bodyPart.isChangeSet());
     } else {
@@ -99,20 +98,20 @@ public class BatchRequestTransformator {
   }
 
   private ODataRequest createRequest(final BatchQueryOperation operation, 
final String baseUri,
-      final boolean isChangeSet)
-          throws BatchDeserializerException {
+      final boolean isChangeSet) throws BatchDeserializerException {
     final HttpRequestStatusLine statusLine =
         new HttpRequestStatusLine(operation.getHttpStatusLine(), baseUri, 
rawServiceResolutionUri);
     statusLine.validateHttpMethod(isChangeSet);
+    BatchTransformatorCommon.validateHost(operation.getHeaders(), baseUri);
 
     validateBody(statusLine, operation);
     Charset charset = getCharset(operation);
-    InputStream bodyStrean = getBodyStream(operation, statusLine, charset);
+    InputStream bodyStream = getBodyStream(operation, statusLine, charset);
 
     validateForbiddenHeader(operation);
 
     final ODataRequest request = new ODataRequest();
-    request.setBody(bodyStrean);
+    request.setBody(bodyStream);
     request.setMethod(statusLine.getMethod());
     request.setRawBaseUri(statusLine.getRawBaseUri());
     request.setRawODataPath(statusLine.getRawODataPath());
@@ -128,24 +127,25 @@ public class BatchRequestTransformator {
   }
 
   private Charset getCharset(final BatchQueryOperation operation) {
-    String ct = operation.getHeaders().getHeader(HttpHeader.CONTENT_TYPE);
-    if (ct != null) {
-      ContentType contentType = ContentType.parse(ct);
-      if (contentType != null) {
-        String charsetValue = 
contentType.getParameter(ContentType.PARAMETER_CHARSET);
-        if (charsetValue != null) {
-          return Charset.forName(charsetValue);
+    final ContentType contentType = 
ContentType.parse(operation.getHeaders().getHeader(HttpHeader.CONTENT_TYPE));
+    if (contentType != null) {
+      final String charsetValue = 
contentType.getParameter(ContentType.PARAMETER_CHARSET);
+      if (charsetValue == null) {
+        if (contentType.isCompatible(ContentType.APPLICATION_JSON) || 
contentType.getSubtype().contains("xml")) {
+          return Charset.forName("UTF-8");
         }
+      } else {
+        return Charset.forName(charsetValue);
       }
     }
-    return DEFAULT_CHARSET;
+    return Charset.forName("ISO-8859-1");
   }
 
   private void validateForbiddenHeader(final BatchQueryOperation operation) 
throws BatchDeserializerException {
     final Header header = operation.getHeaders();
 
-    if (header.exists(HttpHeader.AUTHORIZATION) || 
header.exists(HttpHeader.EXPECT)
-        || header.exists(HttpHeader.FROM) || 
header.exists(HttpHeader.MAX_FORWARDS)
+    if (header.exists(HttpHeader.WWW_AUTHENTICATE) || 
header.exists(HttpHeader.AUTHORIZATION)
+        || header.exists(HttpHeader.EXPECT) || header.exists(HttpHeader.FROM) 
|| header.exists(HttpHeader.MAX_FORWARDS)
         || header.exists(HttpHeader.RANGE) || header.exists(HttpHeader.TE)) {
       throw new BatchDeserializerException("Forbidden header", 
MessageKeys.FORBIDDEN_HEADER,
           Integer.toString(header.getLineNumber()));
@@ -153,8 +153,7 @@ public class BatchRequestTransformator {
   }
 
   private InputStream getBodyStream(final BatchQueryOperation operation, final 
HttpRequestStatusLine statusLine,
-      final Charset charset)
-          throws BatchDeserializerException {
+      final Charset charset) throws BatchDeserializerException {
     if (statusLine.getMethod().equals(HttpMethod.GET)) {
       return new ByteArrayInputStream(new byte[0]);
     } else {
@@ -170,34 +169,23 @@ public class BatchRequestTransformator {
 
   private void validateBody(final HttpRequestStatusLine statusLine, final 
BatchQueryOperation operation)
       throws BatchDeserializerException {
-    if (statusLine.getMethod().equals(HttpMethod.GET) && 
isUnvalidGetRequestBody(operation)) {
+    if (statusLine.getMethod().equals(HttpMethod.GET) && 
isInvalidGetRequestBody(operation)) {
       throw new BatchDeserializerException("Invalid request line", 
MessageKeys.INVALID_CONTENT,
           Integer.toString(statusLine.getLineNumber()));
     }
   }
 
-  private boolean isUnvalidGetRequestBody(final BatchQueryOperation operation) 
{
-    return (operation.getBody().size() > 1)
-        || (operation.getBody().size() == 1 && 
!"".equals(operation.getBody().get(0).toString().trim()));
+  private boolean isInvalidGetRequestBody(final BatchQueryOperation operation) 
{
+    return operation.getBody().size() > 1
+        || operation.getBody().size() == 1 && 
!operation.getBody().get(0).toString().trim().isEmpty();
   }
 
-  private void validateHeader(final BatchPart bodyPart, final boolean 
isChangeSet) throws BatchDeserializerException {
-    final Header headers = bodyPart.getHeaders();
-
-    BatchTransformatorCommon.validateContentType(headers, 
ContentType.APPLICATION_HTTP);
+  private void validateHeaders(final Header headers, final boolean 
isChangeSet) throws BatchDeserializerException {
     if (isChangeSet) {
-      BatchTransformatorCommon.validateContentTransferEncoding(headers);
-    }
-  }
-
-  private void validateBodyPartHeader(final BatchBodyPart bodyPart) throws 
BatchDeserializerException {
-    final Header header = bodyPart.getHeaders();
-
-    if (bodyPart.isChangeSet()) {
-      BatchTransformatorCommon.validateContentType(header, 
ContentType.MULTIPART_MIXED);
+      BatchTransformatorCommon.validateContentType(headers, 
ContentType.MULTIPART_MIXED);
     } else {
-      BatchTransformatorCommon.validateContentTransferEncoding(header);
-      BatchTransformatorCommon.validateContentType(header, 
ContentType.APPLICATION_HTTP);
+      BatchTransformatorCommon.validateContentTransferEncoding(headers);
+      BatchTransformatorCommon.validateContentType(headers, 
ContentType.APPLICATION_HTTP);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchTransformatorCommon.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchTransformatorCommon.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchTransformatorCommon.java
index d319f86..8b8e1d9 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchTransformatorCommon.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/BatchTransformatorCommon.java
@@ -18,6 +18,7 @@
  */
 package org.apache.olingo.server.core.deserializer.batch;
 
+import java.net.URI;
 import java.util.List;
 
 import org.apache.olingo.commons.api.format.ContentType;
@@ -47,23 +48,11 @@ public class BatchTransformatorCommon {
 
     if (contentTransferField != null) {
       final List<String> contentTransferValues = 
contentTransferField.getValues();
-      if (contentTransferValues.size() == 1) {
-        String encoding = contentTransferValues.get(0);
-
-        if (!BatchParserCommon.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
-          throw new BatchDeserializerException("Invalid content transfer 
encoding",
-              MessageKeys.INVALID_CONTENT_TRANSFER_ENCODING,
-              Integer.toString(headers.getLineNumber()));
-        }
-      } else {
+      if (contentTransferValues.size() > 1
+          || 
!BatchParserCommon.BINARY_ENCODING.equalsIgnoreCase(contentTransferValues.get(0)))
 {
         throw new BatchDeserializerException("Invalid 
Content-Transfer-Encoding header",
-            MessageKeys.INVALID_CONTENT_TRANSFER_ENCODING,
-            Integer.toString(headers.getLineNumber()));
+            MessageKeys.INVALID_CONTENT_TRANSFER_ENCODING, 
Integer.toString(headers.getLineNumber()));
       }
-    } else {
-      throw new BatchDeserializerException("Missing mandatory content transfer 
encoding",
-          MessageKeys.MISSING_CONTENT_TRANSFER_ENCODING,
-          Integer.toString(headers.getLineNumber()));
     }
   }
 
@@ -71,10 +60,8 @@ public class BatchTransformatorCommon {
     final HeaderField contentLengthField = 
headers.getHeaderField(HttpHeader.CONTENT_LENGTH);
 
     if (contentLengthField != null && contentLengthField.getValues().size() == 
1) {
-      final List<String> contentLengthValues = contentLengthField.getValues();
-
       try {
-        int contentLength = Integer.parseInt(contentLengthValues.get(0));
+        final int contentLength = 
Integer.parseInt(contentLengthField.getValues().get(0));
 
         if (contentLength < 0) {
           throw new BatchDeserializerException("Invalid content length", 
MessageKeys.INVALID_CONTENT_LENGTH,
@@ -90,4 +77,16 @@ public class BatchTransformatorCommon {
 
     return -1;
   }
+
+  public static void validateHost(final Header headers, final String baseUri) 
throws BatchDeserializerException {
+    final HeaderField hostField = headers.getHeaderField(HttpHeader.HOST);
+
+    if (hostField != null) {
+      if (hostField.getValues().size() > 1
+          || 
!URI.create(baseUri).getAuthority().equalsIgnoreCase(hostField.getValues().get(0).trim()))
 {
+        throw new BatchDeserializerException("Invalid Host header",
+            MessageKeys.INVALID_HOST, 
Integer.toString(headers.getLineNumber()));
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java
index 38773de..f2d1178 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java
@@ -33,8 +33,8 @@ import 
org.apache.olingo.server.api.deserializer.batch.BatchDeserializerExceptio
 public class HttpRequestStatusLine {
   private static final Pattern PATTERN_RELATIVE_URI = 
Pattern.compile("([^/][^?]*)(?:\\?(.*))?");
 
-  private static final Set<String> HTTP_CHANGE_SET_METHODS = new 
HashSet<String>(Arrays.asList(new String[] { "POST",
-      "PUT", "DELETE", "PATCH" }));
+  private static final Set<HttpMethod> HTTP_CHANGE_SET_METHODS = new 
HashSet<HttpMethod>(Arrays.asList(
+      new HttpMethod[] { HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, 
HttpMethod.PATCH }));
   private static final String HTTP_VERSION = "HTTP/1.1";
 
   final private Line statusLine;
@@ -78,7 +78,12 @@ public class HttpRequestStatusLine {
       if (uri.isAbsolute()) {
         parseAbsoluteUri(rawUri, baseUri);
       } else {
-        parseRelativeUri(rawUri);
+        final URI base = URI.create(baseUri);
+        if (rawUri.startsWith(base.getRawPath())) {
+          
parseRelativeUri(removeLeadingSlash(rawUri.substring(base.getRawPath().length())));
+        } else {
+          parseRelativeUri(rawUri);
+        }
       }
     } catch (final URISyntaxException e) {
       throw new BatchDeserializerException("Malformed uri", e, 
MessageKeys.INVALID_URI,
@@ -143,7 +148,7 @@ public class HttpRequestStatusLine {
   }
 
   public void validateHttpMethod(final boolean isChangeSet) throws 
BatchDeserializerException {
-    if (isChangeSet && 
!HTTP_CHANGE_SET_METHODS.contains(getMethod().toString())) {
+    if (isChangeSet && !HTTP_CHANGE_SET_METHODS.contains(getMethod())) {
       throw new BatchDeserializerException("Invalid change set method", 
MessageKeys.INVALID_CHANGESET_METHOD,
           Integer.toString(statusLine.getLineNumber()));
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties 
b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index afe5535..831fe37 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -147,6 +147,7 @@ 
BatchDeserializerException.INVALID_CONTENT_TRANSFER_ENCODING=The Content-Transfe
 BatchDeserializerException.INVALID_CONTENT_TYPE=Invalid Content-Type HTTP 
header at line '%1$s'.
 BatchDeserializerException.UNEXPECTED_CONTENT_TYPE=Content-Type at line '%1$s' 
should be '%2$s' but is '%3$s'.
 BatchDeserializerException.INVALID_CONTENT_ID=Invalid Content-ID HTTP header 
at line '%1$s'.
+BatchDeserializerException.INVALID_HOST=Invalid Host HTTP header at line 
'%1$s'.
 BatchDeserializerException.INVALID_HTTP_VERSION=The HTTP version must be 
HTTP/1.1 at line '%1$s'.
 BatchDeserializerException.INVALID_METHOD=Invalid HTTP method at line '%1$s'.
 BatchDeserializerException.INVALID_STATUS_LINE=Invalid HTTP status line at 
line '%1$s'.
@@ -156,7 +157,6 @@ BatchDeserializerException.MISSING_BLANK_LINE=Missing blank 
line at line '%1$s'.
 BatchDeserializerException.MISSING_BOUNDARY_DELIMITER=Missing boundary 
delimiter at line '%1$s'.
 BatchDeserializerException.MISSING_CLOSE_DELIMITER=Missing close delimiter at 
line '%1$s'.
 BatchDeserializerException.MISSING_CONTENT_ID=Missing content-id at line 
'%1$s'.
-BatchDeserializerException.MISSING_CONTENT_TRANSFER_ENCODING=Missing content 
transfer encoding at line '%1$s'.
 BatchDeserializerException.MISSING_CONTENT_TYPE=Missing content-type at line 
'%1$s'.
 BatchDeserializerException.MISSING_MANDATORY_HEADER=Missing mandatory header 
at line '%1$s'.
 BatchDeserializerException.INVALID_BASE_URI=The base URI does not match the 
service base URI at line '%1$s'.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchLineReaderTest.java
----------------------------------------------------------------------
diff --git 
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
index ea202db..810c743 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
@@ -18,12 +18,15 @@
  */
 package org.apache.olingo.server.core.deserializer.batch;
 
+import static org.junit.Assert.assertArrayEquals;
 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.IOException;
+import java.nio.charset.Charset;
 import java.util.List;
 
 import org.junit.Test;
@@ -45,7 +48,7 @@ public class BatchLineReaderTest {
   private static final String TEXT_EMPTY = "";
 
   @Test
-  public void testSimpleText() throws Exception {
+  public void simpleText() throws Exception {
     final String TEXT = "Test";
     BatchLineReader reader = create(TEXT);
 
@@ -56,9 +59,8 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testNoText() throws Exception {
-    final String TEXT = "";
-    BatchLineReader reader = create(TEXT);
+  public void noText() throws Exception {
+    BatchLineReader reader = create(TEXT_EMPTY);
 
     assertNull(reader.readLine());
     assertNull(reader.readLine());
@@ -66,9 +68,8 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testNoBytes() throws Exception {
-    BatchLineReader reader =
-        new BatchLineReader(new ByteArrayInputStream(new byte[0]));
+  public void noBytes() throws Exception {
+    BatchLineReader reader = new BatchLineReader(new ByteArrayInputStream(new 
byte[0]));
 
     assertNull(reader.readLine());
     assertNull(reader.readLine());
@@ -76,7 +77,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testCRLF() throws Exception {
+  public void CRLF() throws Exception {
     final String TEXT = "Test\r\n" +
         "Test2";
 
@@ -90,7 +91,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testLF() throws Exception {
+  public void LF() throws Exception {
     final String TEXT = "Test\n" +
         "Test2";
 
@@ -104,7 +105,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testCR() throws Exception {
+  public void CR() throws Exception {
     final String TEXT = "Test\r" +
         "Test2";
 
@@ -118,7 +119,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testCombined() throws Exception {
+  public void combined() throws Exception {
     BatchLineReader reader = create(TEXT_COMBINED);
 
     assertEquals("Test\r", reader.readLine());
@@ -138,7 +139,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testCombinedBufferSizeTwo() throws Exception {
+  public void combinedBufferSizeTwo() throws Exception {
     BatchLineReader reader = create(TEXT_COMBINED, 2);
 
     assertEquals("Test\r", reader.readLine());
@@ -158,20 +159,8 @@ public class BatchLineReaderTest {
   }
 
   @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);
+  public void combinedBufferSizeOne() throws Exception {
+    BatchLineReader reader = create(TEXT_COMBINED, 1);
 
     assertEquals("Test\r", reader.readLine());
     assertEquals("Test2\r\n", reader.readLine());
@@ -183,7 +172,7 @@ public class BatchLineReaderTest {
     assertEquals("Test5\n", reader.readLine());
     assertEquals("Test6\r\n", reader.readLine());
     assertEquals("Test7\n", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
+    assertEquals("\n", reader.readLine());
     assertNull(reader.readLine());
     assertNull(reader.readLine());
 
@@ -191,7 +180,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testDoubleLF() throws Exception {
+  public void doubleCR() throws Exception {
     final String TEXT = "Test\r" +
         "\r";
 
@@ -203,7 +192,7 @@ public class BatchLineReaderTest {
   }
 
   @Test
-  public void testLineEqualsAndHashCode() {
+  public void lineEqualsAndHashCode() {
     Line l1 = new Line("The first line", 1);
     Line l2 = new Line("The first line", 1);
     Line l3 = new Line("The second line", 2);
@@ -214,19 +203,19 @@ public class BatchLineReaderTest {
   }
 
   @Test(expected = IllegalArgumentException.class)
-  public void testFailBufferSizeZero() throws Exception {
+  public void failBufferSizeZero() throws Exception {
     BatchLineReader reader = create(TEXT_EMPTY, 0);
     reader.close();
   }
 
   @Test(expected = IllegalArgumentException.class)
-  public void testFailBufferSizeNegative() throws Exception {
+  public void failBufferSizeNegative() throws Exception {
     BatchLineReader reader = create(TEXT_EMPTY, -1);
     reader.close();
   }
 
   @Test
-  public void testToList() throws Exception {
+  public void toList() throws Exception {
     BatchLineReader reader = create(TEXT_COMBINED);
     List<Line> stringList = reader.toLineList();
 
@@ -245,13 +234,48 @@ public class BatchLineReaderTest {
     reader.close();
   }
 
-  private BatchLineReader create(final String inputString) throws Exception {
-    return new BatchLineReader(new ByteArrayInputStream(inputString
-        .getBytes("UTF-8")));
+  @Test
+  public void specialCharacters() throws Exception {
+    final String text = "\r\n"
+        + "Content-Type: text/plain; charset=UTF-8\r\n"
+        + "\r\n"
+        + "ä€\r\n"
+        + "\uFDFC\r\n"  // RIAL SIGN
+        // Unicode characters outside the Basic Multilingual Plane are stored
+        // in a Java String in two surrogate characters.
+        + String.valueOf(Character.toChars(0x1F603));
+    BatchLineReader reader = create(text);
+    reader.readLine();
+    reader.readLine();
+    reader.readLine();
+    assertEquals("ä€\r\n", reader.readLine());
+    assertEquals("\uFDFC\r\n", reader.readLine());
+    assertEquals(String.valueOf(Character.toChars(0x1F603)), 
reader.readLine());
+    assertNull(reader.readLine());
+    reader.close();
+  }
+
+  @Test
+  public void rawBytes() throws Exception {
+    byte[] content = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE + 1];
+    // binary content, not a valid UTF-8 representation of a string
+    for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+      content[i - Byte.MIN_VALUE] = (byte) i;
+    }
+    BatchLineReader reader = new BatchLineReader(new 
ByteArrayInputStream(content));
+    final String contentString = reader.readLine()  // initial part up to '\n'
+        + reader.readLine()  // second part from '\n' to '\r'
+        + reader.readLine();  // the rest
+    assertArrayEquals(content, 
contentString.getBytes(Charset.forName("ISO-8859-1")));
+    assertNull(reader.readLine());
+    reader.close();
+  }
+
+  private BatchLineReader create(final String inputString) throws IOException {
+    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);
+  private BatchLineReader create(final String inputString, final int 
bufferSize) throws IOException {
+    return new BatchLineReader(new 
ByteArrayInputStream(inputString.getBytes("UTF-8")), bufferSize);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/14278ac1/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java
 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java
index 6c27b19..95afe12 100644
--- 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java
+++ 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java
@@ -27,11 +27,14 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.olingo.commons.api.http.HttpHeader;
+import 
org.apache.olingo.server.api.deserializer.batch.BatchDeserializerException;
+import org.junit.Assert;
 import org.junit.Test;
 
 public class BatchParserCommonTest {
 
   private static final String CRLF = "\r\n";
+  private static final String MULTIPART_MIXED = "multipart/mixed";
 
   @Test
   public void multipleHeaders() throws Exception {
@@ -161,6 +164,60 @@ public class BatchParserCommonTest {
   }
 
   @Test
+  public void boundaryParameter() throws Exception {
+    final String boundary = "boundary";
+    final String contentType = MULTIPART_MIXED + "; boundary=" + boundary + "  
";
+    Assert.assertEquals(boundary, BatchParserCommon.getBoundary(contentType, 
0));
+  }
+
+  @Test
+  public void boundaryParameterWithQuotes() throws Exception {
+    final String boundary = "batch_1.2+34:2j)0?";
+    final String contentType = MULTIPART_MIXED + "; boundary=\"" + boundary + 
"\"";
+    Assert.assertEquals(boundary, BatchParserCommon.getBoundary(contentType, 
0));
+  }
+
+  @Test
+  public void boundaryParameterWithSpaces() throws Exception {
+    final String boundary = "        boundary";
+    final String contentType = MULTIPART_MIXED + "; boundary=\"" + boundary + 
"\"  ";
+    Assert.assertEquals(boundary, BatchParserCommon.getBoundary(contentType, 
0));
+  }
+
+  @Test
+  public void invalidContentType() throws Exception {
+    invalidBoundary("multipart;boundary=BOUNDARY", 
BatchDeserializerException.MessageKeys.INVALID_CONTENT_TYPE);
+  }
+
+  @Test
+  public void contentTypeCharset() throws Exception {
+    final String contentType = MULTIPART_MIXED + "; charset=UTF-8;boundary=" + 
BatchParserCommon.BOUNDARY;
+    final String boundary = BatchParserCommon.getBoundary(contentType, 0);
+    Assert.assertEquals(BatchParserCommon.BOUNDARY, boundary);
+  }
+
+  @Test
+  public void withoutBoundaryParameter() throws Exception {
+    invalidBoundary(MULTIPART_MIXED, 
BatchDeserializerException.MessageKeys.MISSING_BOUNDARY_DELIMITER);
+  }
+
+  @Test
+  public void boundaryParameterWithoutQuote() throws Exception {
+    invalidBoundary(MULTIPART_MIXED + ";boundary=batch_1740-bb:84-2f7f",
+        BatchDeserializerException.MessageKeys.INVALID_BOUNDARY);
+  }
+
+  @Test
+  public void boundaryEmpty() throws Exception {
+    invalidBoundary(MULTIPART_MIXED + ";boundary=\"\"", 
BatchDeserializerException.MessageKeys.INVALID_BOUNDARY);
+  }
+
+  @Test
+  public void boundarySpace() throws Exception {
+    invalidBoundary(MULTIPART_MIXED + ";boundary=\" \"", 
BatchDeserializerException.MessageKeys.INVALID_BOUNDARY);
+  }
+
+  @Test
   public void removeEndingCRLF() {
     String line = "Test" + CRLF;
     assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line, 
1)).toString());
@@ -219,4 +276,13 @@ public class BatchParserCommonTest {
 
     return lineList;
   }
+
+  private void invalidBoundary(final String contentType, final 
BatchDeserializerException.MessageKeys messageKey) {
+    try {
+      BatchParserCommon.getBoundary(contentType, 0);
+      Assert.fail("Expected exception not thrown.");
+    } catch (final BatchDeserializerException e) {
+      Assert.assertEquals(messageKey, e.getMessageKey());
+    }
+  }
 }

Reply via email to