You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/10/09 17:06:12 UTC

[05/19] git commit: Code Review - Bug fix and refactoring

Code Review - Bug fix and refactoring

Signed-off-by: Christian Amend <ch...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/1f90b733
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/1f90b733
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/1f90b733

Branch: refs/heads/master
Commit: 1f90b733a25a41c43f93ceb0f78369e6c27ef753
Parents: ffb21db
Author: Christian Holzer <c....@sap.com>
Authored: Thu Oct 2 19:12:38 2014 +0200
Committer: Christian Amend <ch...@apache.org>
Committed: Mon Oct 6 13:54:37 2014 +0200

----------------------------------------------------------------------
 .../olingo/odata2/core/batch/AcceptParser.java  |  64 +++++--
 .../odata2/core/batch/v2/BatchBodyPart.java     |  27 +--
 .../odata2/core/batch/v2/BatchChangeSet.java    |  55 ------
 .../core/batch/v2/BatchChangeSetPart.java       |  55 ++++++
 .../odata2/core/batch/v2/BatchParser.java       |   2 +-
 .../odata2/core/batch/v2/BatchParserCommon.java | 122 +++++++------
 .../core/batch/v2/BatchQueryOperation.java      |  10 +-
 .../batch/v2/BatchRequestTransformator.java     |  16 +-
 .../batch/v2/BatchResponseTransformator.java    |  13 +-
 .../core/batch/v2/BatchTransformatorCommon.java |  24 +--
 .../odata2/core/batch/AcceptParserTest.java     |  77 +++++---
 .../core/batch/BatchParserCommonTest.java       | 182 +++++++++++++++----
 .../core/batch/BatchRequestParserTest.java      | 124 +++++++++----
 .../batch/BatchTransformatorCommonTest.java     |  12 +-
 14 files changed, 516 insertions(+), 267 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
index 946fccf..48bfb1b 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
@@ -6,9 +6,9 @@
  * 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
@@ -20,6 +20,7 @@ package org.apache.olingo.odata2.core.batch;
 
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Scanner;
@@ -30,10 +31,11 @@ import java.util.regex.Pattern;
 import org.apache.olingo.odata2.api.batch.BatchException;
 
 /**
- *  
+ *
  */
 public class AcceptParser {
 
+  private static final String COMMA = ",";
   private static final String BAD_REQUEST = "400";
   private static final String ALL = "*";
   private static final String REG_EX_QUALITY_FACTOR = "q=((?:1\\.0{0,3})|(?:0\\.[0-9]{0,2}[1-9]))";
@@ -48,10 +50,15 @@ public class AcceptParser {
 
   private static final double QUALITY_PARAM_FACTOR = 0.001;
 
-  public static List<String> parseAcceptHeaders(final String headerValue) throws BatchException {
-    TreeSet<Accept> acceptTree = getAcceptTree();
-    List<String> acceptHeaders = new ArrayList<String>();
-    Scanner acceptHeaderScanner = new Scanner(headerValue);
+  private List<String> acceptHeaderValues = new ArrayList<String>();
+  private List<String> acceptLanguageHeaderValues = new ArrayList<String>();
+
+  public List<String> parseAcceptHeaders() throws BatchException {
+    final String headerValue = concatenateHeaderLines(acceptHeaderValues);
+    final TreeSet<Accept> acceptTree = getAcceptTree();
+    final List<String> acceptHeaders = new ArrayList<String>();
+    final Scanner acceptHeaderScanner = new Scanner(headerValue);
+
     acceptHeaderScanner.useDelimiter(",\\s?");
     while (acceptHeaderScanner.hasNext()) {
       if (acceptHeaderScanner.hasNext(REG_EX_ACCEPT_WITH_Q_FACTOR)) {
@@ -75,18 +82,21 @@ public class AcceptParser {
       }
     }
     for (Accept accept : acceptTree) {
-      acceptHeaders.add(accept.getValue());
+      if (!acceptHeaders.contains(accept.getValue())) {
+        acceptHeaders.add(accept.getValue());
+      }
     }
     acceptHeaderScanner.close();
     return acceptHeaders;
   }
 
-  private static double getQualityFactor(final String acceptHeaderValue, double qualityFactor) {
+  private double getQualityFactor(final String acceptHeaderValue, double qualityFactor) {
     int paramNumber = 0;
     double typeFactor = 0.0;
     double subtypeFactor = 0.0;
     String[] mediaRange = acceptHeaderValue.split("(?=[^;]+);");
     String[] mediaTypes = mediaRange[0].split("/");
+
     if (mediaTypes.length == 2) {
       String type = mediaTypes[0];
       String subtype = mediaTypes[1];
@@ -101,13 +111,15 @@ public class AcceptParser {
       String[] parameters = mediaRange[1].split(";\\s?");
       paramNumber = parameters.length;
     }
+
     qualityFactor = qualityFactor + paramNumber * QUALITY_PARAM_FACTOR + typeFactor + subtypeFactor;
     return qualityFactor;
   }
 
-  public static List<String> parseAcceptableLanguages(final String headerValue) throws BatchException {
-    List<String> acceptLanguages = new LinkedList<String>();
-    TreeSet<Accept> acceptTree = getAcceptTree();
+  public List<String> parseAcceptableLanguages() throws BatchException {
+    final String headerValue = concatenateHeaderLines(acceptLanguageHeaderValues);
+    final List<String> acceptLanguages = new LinkedList<String>();
+    final TreeSet<Accept> acceptTree = getAcceptTree();
     Scanner acceptLanguageScanner = new Scanner(headerValue);
     acceptLanguageScanner.useDelimiter(",\\s?");
 
@@ -132,13 +144,37 @@ public class AcceptParser {
       }
     }
     for (Accept accept : acceptTree) {
-      acceptLanguages.add(accept.getValue());
+      if (!acceptLanguages.contains(accept.getValue())) {
+        acceptLanguages.add(accept.getValue());
+      }
     }
     acceptLanguageScanner.close();
     return acceptLanguages;
   }
 
-  private static TreeSet<Accept> getAcceptTree() {
+  private String concatenateHeaderLines(final List<String> headerValues) {
+    final StringBuilder builder = new StringBuilder();
+    final Iterator<String> iter = headerValues.iterator();
+
+    while (iter.hasNext()) {
+      builder.append(iter.next());
+      if (iter.hasNext()) {
+        builder.append(COMMA);
+      }
+    }
+
+    return builder.toString();
+  }
+
+  public void addAcceptHeaderValue(final String headerValue) {
+    acceptHeaderValues.add(headerValue);
+  }
+
+  public void addAcceptLanguageHeaderValue(final String headerValue) {
+    acceptLanguageHeaderValues.add(headerValue);
+  }
+
+  private TreeSet<Accept> getAcceptTree() {
     TreeSet<Accept> treeSet = new TreeSet<Accept>(new Comparator<Accept>() {
       @Override
       public int compare(final Accept o1, final Accept o2) {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
index e355f84..4edcf45 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
@@ -24,18 +24,16 @@ import java.util.Locale;
 import java.util.Map;
 
 import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
 import org.apache.olingo.odata2.api.commons.HttpHeaders;
 import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
 
 public class BatchBodyPart implements BatchPart {
-  final private Map<String, HeaderField> headers;
   final private String boundary;
-  final private boolean isChangeSet;
   final private boolean isStrict;
-  final private List<String> body;
-  private boolean isParsed = false;
+  final List<String> remainingMessage = new LinkedList<String>();
+
+  private Map<String, HeaderField> headers;
+  private boolean isChangeSet;
   private List<BatchQueryOperation> requests;
 
   public BatchBodyPart(final List<String> bodyPartMessage, final String boundary, final boolean isStrict)
@@ -43,19 +41,14 @@ public class BatchBodyPart implements BatchPart {
     this.boundary = boundary;
     this.isStrict = isStrict;
 
-    List<String> remainingMessage = new LinkedList<String>();
     remainingMessage.addAll(bodyPartMessage);
+  }
 
+  public BatchBodyPart parse() throws BatchException {
     headers = BatchParserCommon.consumeHeaders(remainingMessage);
     BatchParserCommon.consumeBlankLine(remainingMessage, isStrict);
     isChangeSet = isChangeSet(headers);
-    body = remainingMessage;
-  }
-
-  public BatchBodyPart parse(final int contentLength) throws BatchException {
-    List<String> remainingMessage = BatchParserCommon.trimStringListToLength(body, contentLength);
     requests = consumeRequest(remainingMessage);
-    isParsed = true;
 
     return this;
   }
@@ -78,7 +71,7 @@ public class BatchBodyPart implements BatchPart {
   }
 
   private boolean isContentTypeMultiPartMixed(final String contentType) {
-    return contentType.contains(HttpContentType.MULTIPART_MIXED);
+    return BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches();
   }
 
   private List<BatchQueryOperation> consumeRequest(final List<String> remainingMessage) throws BatchException {
@@ -95,7 +88,7 @@ public class BatchBodyPart implements BatchPart {
     final List<BatchQueryOperation> requestList = new LinkedList<BatchQueryOperation>();
 
     for (List<String> changeRequest : changeRequests) {
-      requestList.add(new BatchChangeSet(changeRequest, isStrict).parse());
+      requestList.add(new BatchChangeSetPart(changeRequest, isStrict).parse());
     }
 
     return requestList;
@@ -146,10 +139,6 @@ public class BatchBodyPart implements BatchPart {
   }
 
   public List<BatchQueryOperation> getRequests() {
-    if (!isParsed) {
-      throw new ODataRuntimeException("Batch part must be parsed first");
-    }
-
     return requests;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
deleted file mode 100644
index 5331ff8..0000000
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch.v2;
-
-import java.util.List;
-
-import org.apache.olingo.odata2.api.batch.BatchException;
-
-public class BatchChangeSet extends BatchQueryOperation {
-  private BatchQueryOperation request;
-
-  public BatchChangeSet(final List<String> message, final boolean isStrict) throws BatchException {
-    super(message, isStrict);
-  }
-
-  @Override
-  public BatchChangeSet parse() throws BatchException {
-    headers = BatchParserCommon.consumeHeaders(message);
-    BatchParserCommon.consumeBlankLine(message, isStrict);
-
-    request = new BatchQueryOperation(message, isStrict).parse();
-
-    return this;
-  }
-
-  public BatchQueryOperation getRequest() {
-    return request;
-  }
-
-  @Override
-  public List<String> getBody() {
-    return request.getBody();
-  }
-
-  @Override
-  public String getHttpMethod() {
-    return request.getHttpMethod();
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
new file mode 100644
index 0000000..746c368
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch.v2;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+
+public class BatchChangeSetPart extends BatchQueryOperation {
+  private BatchQueryOperation request;
+
+  public BatchChangeSetPart(final List<String> message, final boolean isStrict) throws BatchException {
+    super(message, isStrict);
+  }
+
+  @Override
+  public BatchChangeSetPart parse() throws BatchException {
+    headers = BatchParserCommon.consumeHeaders(message);
+    BatchParserCommon.consumeBlankLine(message, isStrict);
+
+    request = new BatchQueryOperation(message, isStrict).parse();
+
+    return this;
+  }
+
+  public BatchQueryOperation getRequest() {
+    return request;
+  }
+
+  @Override
+  public List<String> getBody() {
+    return request.getBody();
+  }
+
+  @Override
+  public String getHttpStatusLine() {
+    return request.getHttpStatusLine();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
index b64453b..6fb7dbd 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
@@ -83,7 +83,7 @@ public class BatchParser {
     final List<List<String>> bodyPartStrings = splitBodyParts(in, boundary);
 
     for (List<String> bodyPartString : bodyPartStrings) {
-      BatchBodyPart bodyPart = new BatchBodyPart(bodyPartString, boundary, isStrict);
+      BatchBodyPart bodyPart = new BatchBodyPart(bodyPartString, boundary, isStrict).parse();
       resultList.addAll(transformator.transform(bodyPart, batchRequestPathInfo, baseUri));
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
index 51314dd..8b7f62a 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
@@ -44,32 +44,23 @@ import org.apache.olingo.odata2.core.batch.AcceptParser;
 import org.apache.olingo.odata2.core.commons.Decoder;
 
 public class BatchParserCommon {
-  private static final String BOUNDARY_IDENTIFIER = "boundary=";
   private static final String REG_EX_BOUNDARY =
       "([a-zA-Z0-9_\\-\\.'\\+]{1,70})|\"([a-zA-Z0-9_\\-\\.'\\+\\s\\" +
           "(\\),/:=\\?]{1,69}[a-zA-Z0-9_\\-\\.'\\+\\(\\),/:=\\?])\""; // See RFC 2046
 
-  private static final Pattern REG_EX_HEADER = Pattern.compile("([a-zA-Z\\-]+):\\s?(.*)\\s*");
+  private static final String REX_EX_MULTIPART_BOUNDARY = "multipart/mixed;\\s*boundary=(.+)";
+  private static final String REG_EX_APPLICATION_HTTP = "application/http";
+  public static final Pattern PATTERN_MULTIPART_BOUNDARY = Pattern.compile(REX_EX_MULTIPART_BOUNDARY,
+      Pattern.CASE_INSENSITIVE);
+  public static final Pattern PATTERN_HEADER_LINE = Pattern.compile("([a-zA-Z\\-]+):\\s?(.*)\\s*");
+  public static final Pattern PATTERN_CONTENT_TYPE_APPLICATION_HTTP = Pattern.compile(REG_EX_APPLICATION_HTTP,
+      Pattern.CASE_INSENSITIVE);
 
-  public static List<String> trimStringListToLength(final List<String> list, final int length) {
-    final Iterator<String> iter = list.iterator();
-    final List<String> result = new ArrayList<String>();
-    boolean isEndReached = false;
-    int currentLength = 0;
-
-    while (!isEndReached && iter.hasNext()) {
-      String currentLine = iter.next();
-
-      if (currentLength + currentLine.length() <= length) {
-        result.add(currentLine);
-        currentLength += currentLine.length();
-      } else {
-        result.add(currentLine.substring(0, length - currentLength));
-        isEndReached = true;
-      }
-    }
+  public static String trimStringListToStringLength(final List<String> list, final int length) {
+    final String message = stringListToString(list);
+    final int lastIndex = Math.min(length, message.length());
 
-    return result;
+    return (lastIndex > 0) ? message.substring(0, lastIndex) : "";
   }
 
   public static String stringListToString(final List<String> list) {
@@ -82,13 +73,21 @@ public class BatchParserCommon {
     return builder.toString();
   }
 
-  public static InputStream convertMessageToInputStream(final List<String> message, final int contentLength)
+  public static InputStream convertMessageToInputStream(final List<String> messageList, final int contentLength)
       throws BatchException {
-    List<String> shortenedMessage = BatchParserCommon.trimStringListToLength(message, contentLength);
+    final String message = trimStringListToStringLength(messageList, contentLength);
 
-    return new ByteArrayInputStream(BatchParserCommon.stringListToString(shortenedMessage).getBytes());
+    return new ByteArrayInputStream(message.getBytes());
   }
 
+  public static InputStream convertMessageToInputStream(final List<String> messageList)
+      throws BatchException {
+    final String message = stringListToString(messageList);
+
+    return new ByteArrayInputStream(message.getBytes());
+  }
+
+  // TODO Splitten von InputStream, sodass nur eine Iteration erfolgen muss
   static List<List<String>> splitMessageByBoundary(final List<String> message, final String boundary)
       throws BatchException {
     final List<List<String>> messageParts = new LinkedList<List<String>>();
@@ -149,15 +148,16 @@ public class BatchParserCommon {
     }
   }
 
-  static Map<String, HeaderField> consumeHeaders(final List<String> remainingMessage) throws BatchException {
+  public static Map<String, HeaderField> consumeHeaders(final List<String> remainingMessage) throws BatchException {
     final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
     boolean isHeader = true;
+    final Iterator<String> iter = remainingMessage.iterator();
+    final AcceptParser acceptParser = new AcceptParser();
     String currentLine;
-    Iterator<String> iter = remainingMessage.iterator();
 
     while (iter.hasNext() && isHeader) {
       currentLine = iter.next();
-      Matcher headerMatcher = REG_EX_HEADER.matcher(currentLine);
+      Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine);
 
       if (headerMatcher.matches() && headerMatcher.groupCount() == 2) {
         iter.remove();
@@ -167,38 +167,55 @@ public class BatchParserCommon {
         String headerValue = headerMatcher.group(2).trim();
 
         if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerNameLowerCase)) {
-          List<String> acceptHeaders = AcceptParser.parseAcceptHeaders(headerValue);
-          headers.put(headerNameLowerCase, new HeaderField(headerName, acceptHeaders));
+          acceptParser.addAcceptHeaderValue(headerValue);
         } else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerNameLowerCase)) {
-          List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages(headerValue);
-          headers.put(headerNameLowerCase, new HeaderField(headerName, acceptLanguageHeaders));
+          acceptParser.addAcceptLanguageHeaderValue(headerValue);
         } else {
-          HeaderField headerField = headers.get(headerNameLowerCase);
-          headerField = headerField == null ? new HeaderField(headerName) : headerField;
-          headers.put(headerNameLowerCase, headerField);
-          headerField.getValues().add(headerValue);
+          addHeaderValue(headers, headerName, headerNameLowerCase, headerValue);
         }
       } else {
         isHeader = false;
       }
     }
 
+    final List<String> acceptHeader = acceptParser.parseAcceptHeaders();
+    headers.put(HttpHeaders.ACCEPT.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT, acceptHeader));
+
+    final List<String> acceptLanguageHeader = acceptParser.parseAcceptableLanguages();
+    headers.put(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT_LANGUAGE,
+        acceptLanguageHeader));
+
     return Collections.unmodifiableMap(headers);
   }
 
-  static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict) throws BatchException {
-    if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).trim())) {
-      remainingMessage.remove(0);
-    } else {
-      if (isStrict) {
-        throw new BatchException(BatchException.MISSING_BLANK_LINE);
+  private static void addHeaderValue(final Map<String, HeaderField> headers, final String headerName,
+      final String headerNameLowerCase, final String headerValue) {
+    HeaderField headerField = headers.get(headerNameLowerCase);
+    headerField = headerField == null ? new HeaderField(headerName) : headerField;
+    headers.put(headerNameLowerCase, headerField);
+
+    for (final String singleValue : splitHeaderValuesByComma(headerValue)) {
+      if (!headerField.getValues().contains(singleValue)) {
+        headerField.getValues().add(singleValue);
       }
     }
   }
 
-  static void consumeLastBlankLine(final List<String> message, final boolean isStrict) throws BatchException {
-    if (message.size() > 0 && "".equals(message.get(message.size() - 1).trim())) {
-      message.remove(message.size() - 1);
+  private static List<String> splitHeaderValuesByComma(final String headerValue) {
+    final List<String> singleValues = new ArrayList<String>();
+
+    String[] parts = headerValue.split(",");
+    for (final String value : parts) {
+      singleValues.add(value.trim());
+    }
+
+    return singleValues;
+  }
+
+  public static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict)
+      throws BatchException {
+    if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).trim())) {
+      remainingMessage.remove(0);
     } else {
       if (isStrict) {
         throw new BatchException(BatchException.MISSING_BLANK_LINE);
@@ -206,25 +223,22 @@ public class BatchParserCommon {
     }
   }
 
-  static String getBoundary(final String contentType) throws BatchException {
-    if (contentType.contains(HttpContentType.MULTIPART_MIXED)) {
-      String[] parts = contentType.split(BOUNDARY_IDENTIFIER);
+  public static String getBoundary(final String contentType) throws BatchException {
+    final Matcher boundaryMatcher = PATTERN_MULTIPART_BOUNDARY.matcher(contentType);
 
-      if (parts.length == 2) {
-        if (parts[1].matches(REG_EX_BOUNDARY)) {
-          return trimQuota(parts[1].trim());
-        } else {
-          throw new BatchException(BatchException.INVALID_BOUNDARY);
-        }
+    if (boundaryMatcher.matches()) {
+      final String boundary = boundaryMatcher.group(1);
+      if (boundary.matches(REG_EX_BOUNDARY)) {
+        return trimQuota(boundary);
       } else {
-        throw new BatchException(BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE);
+        throw new BatchException(BatchException.INVALID_BOUNDARY);
       }
     } else {
       throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED));
     }
   }
 
-  static Map<String, List<String>> parseQueryParameter(final String httpRequest) {
+  public static Map<String, List<String>> parseQueryParameter(final String httpRequest) {
     Map<String, List<String>> queryParameter = new HashMap<String, List<String>>();
 
     String[] requestParts = httpRequest.split(" ");

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
index 179fffb..5176bb8 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
@@ -27,7 +27,7 @@ import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
 public class BatchQueryOperation implements BatchPart {
 
   protected final boolean isStrict;
-  protected String httpMethod;
+  protected String httpStatusLine;
   protected Map<String, HeaderField> headers;
   protected List<String> body;
   protected int bodySize;
@@ -39,7 +39,7 @@ public class BatchQueryOperation implements BatchPart {
   }
 
   public BatchQueryOperation parse() throws BatchException {
-    httpMethod = consumeHttpMethod(message);
+    httpStatusLine = consumeHttpStatusLine(message);
     headers = BatchParserCommon.consumeHeaders(message);
     BatchParserCommon.consumeBlankLine(message, isStrict);
     body = message;
@@ -47,7 +47,7 @@ public class BatchQueryOperation implements BatchPart {
     return this;
   }
 
-  protected String consumeHttpMethod(final List<String> message) throws BatchException {
+  protected String consumeHttpStatusLine(final List<String> message) throws BatchException {
     if (message.size() > 0 && !message.get(0).trim().equals("")) {
       String method = message.get(0);
       message.remove(0);
@@ -58,8 +58,8 @@ public class BatchQueryOperation implements BatchPart {
     }
   }
 
-  public String getHttpMethod() {
-    return httpMethod;
+  public String getHttpStatusLine() {
+    return httpStatusLine;
   }
 
   public List<String> getBody() {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
index 3626686..5169575 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
@@ -55,7 +55,6 @@ public class BatchRequestTransformator implements BatchTransformator {
     final List<ODataRequest> requests = new LinkedList<ODataRequest>();
     final List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
 
-    BatchTransformatorCommon.parsePartSyntax(bodyPart);
     validateBodyPartHeaders(bodyPart);
 
     for (BatchQueryOperation queryOperation : bodyPart.getRequests()) {
@@ -77,7 +76,7 @@ public class BatchRequestTransformator implements BatchTransformator {
       final String baseUri, final BatchQueryOperation queryOperation) throws BatchException {
 
     if (bodyPart.isChangeSet()) {
-      BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSet) queryOperation).getRequest();
+      BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSetPart) queryOperation).getRequest();
       Map<String, HeaderField> headers = transformHeader(encapsulatedQueryOperation, queryOperation);
       validateChangeSetMultipartMimeHeaders(queryOperation, encapsulatedQueryOperation);
 
@@ -98,7 +97,7 @@ public class BatchRequestTransformator implements BatchTransformator {
   private ODataRequest createRequest(final BatchQueryOperation operation, final Map<String, HeaderField> headers,
       final PathInfo pathInfo, final String baseUri, final boolean isChangeSet) throws BatchException {
 
-    ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpMethod());
+    ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpStatusLine());
     validateHttpMethod(httpMethod, isChangeSet);
     validateBody(httpMethod, operation);
     InputStream bodyStrean = getBodyStream(operation, headers, httpMethod);
@@ -106,10 +105,10 @@ public class BatchRequestTransformator implements BatchTransformator {
     ODataRequestBuilder requestBuilder = ODataRequest.method(httpMethod)
         .acceptableLanguages(getAcceptLanguageHeaders(headers))
         .acceptHeaders(getAcceptHeaders(headers))
-        .allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpMethod()))
+        .allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpStatusLine()))
         .body(bodyStrean)
         .requestHeaders(BatchParserCommon.headerFieldMapToMultiMap(headers))
-        .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpMethod(), pathInfo, baseUri));
+        .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpStatusLine(), pathInfo, baseUri));
 
     addContentTypeHeader(requestBuilder, headers);
 
@@ -135,9 +134,12 @@ public class BatchRequestTransformator implements BatchTransformator {
       return new ByteArrayInputStream(new byte[0]);
     } else {
       int contentLength = BatchTransformatorCommon.getContentLength(headers);
-      contentLength = (contentLength >= 0) ? contentLength : Integer.MAX_VALUE;
 
-      return BatchParserCommon.convertMessageToInputStream(operation.getBody(), contentLength);
+      if (contentLength == -1) {
+        return BatchParserCommon.convertMessageToInputStream(operation.getBody());
+      } else {
+        return BatchParserCommon.convertMessageToInputStream(operation.getBody(), contentLength);
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
index 88f5064..d82d09e 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
@@ -51,7 +51,6 @@ public class BatchResponseTransformator implements BatchTransformator {
 
     List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
 
-    BatchTransformatorCommon.parsePartSyntax(bodyPart);
     BatchTransformatorCommon.validateContentType(bodyPart.getHeaders());
 
     resultList.addAll(handleBodyPart(bodyPart));
@@ -64,7 +63,7 @@ public class BatchResponseTransformator implements BatchTransformator {
 
     if (bodyPart.isChangeSet()) {
       for (BatchQueryOperation operation : bodyPart.getRequests()) {
-        bodyPartResult.add(transformChangeSet((BatchChangeSet) operation));
+        bodyPartResult.add(transformChangeSet((BatchChangeSetPart) operation));
       }
     } else {
       bodyPartResult.add(transformQueryOperation(bodyPart.getRequests().get(0), getContentId(bodyPart.getHeaders())));
@@ -73,7 +72,7 @@ public class BatchResponseTransformator implements BatchTransformator {
     return bodyPartResult;
   }
 
-  private BatchSingleResponse transformChangeSet(final BatchChangeSet changeSet) throws BatchException {
+  private BatchSingleResponse transformChangeSet(final BatchChangeSetPart changeSet) throws BatchException {
     BatchTransformatorCommon.validateContentTransferEncoding(changeSet.getHeaders(), true);
 
     return transformQueryOperation(changeSet.getRequest(), getContentId(changeSet.getHeaders()));
@@ -84,8 +83,8 @@ public class BatchResponseTransformator implements BatchTransformator {
     BatchSingleResponseImpl response = new BatchSingleResponseImpl();
     response.setContentId(contentId);
     response.setHeaders(BatchParserCommon.headerFieldMapToSingleMap(operation.getHeaders()));
-    response.setStatusCode(getStatusCode(operation.httpMethod));
-    response.setStatusInfo(getStatusInfo(operation.getHttpMethod()));
+    response.setStatusCode(getStatusCode(operation.httpStatusLine));
+    response.setStatusInfo(getStatusInfo(operation.getHttpStatusLine()));
     response.setBody(getBody(operation));
 
     return response;
@@ -105,8 +104,8 @@ public class BatchResponseTransformator implements BatchTransformator {
 
   private String getBody(final BatchQueryOperation operation) throws BatchException {
     int contentLength = BatchTransformatorCommon.getContentLength(operation.getHeaders());
-    List<String> body = BatchParserCommon.trimStringListToLength(operation.getBody(), contentLength);
-    return BatchParserCommon.stringListToString(body);
+
+    return BatchParserCommon.trimStringListToStringLength(operation.getBody(), contentLength);
   }
 
   private String getStatusCode(final String httpMethod) throws BatchException {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
index 2098708..c9c8e0f 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
@@ -12,20 +12,16 @@ import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
 public class BatchTransformatorCommon {
 
   public static void validateContentType(final Map<String, HeaderField> headers) throws BatchException {
-    if (headers.containsKey(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH))) {
-      HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
-
+    final HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
+    if (contentTypeField != null) {
       if (contentTypeField.getValues().size() == 1) {
-        String contentType = contentTypeField.getValues().get(0);
-
-        if (!(HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)
-        || contentType.contains(HttpContentType.MULTIPART_MIXED))) {
+        final String contentType = contentTypeField.getValues().get(0);
 
+        if (!BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches()
+            && !BatchParserCommon.PATTERN_CONTENT_TYPE_APPLICATION_HTTP.matcher(contentType).matches()) {
           throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED
               + " or " + HttpContentType.APPLICATION_HTTP));
         }
-      } else if (contentTypeField.getValues().size() == 0) {
-        throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
       } else {
         throw new BatchException(BatchException.INVALID_HEADER);
       }
@@ -34,7 +30,8 @@ public class BatchTransformatorCommon {
     }
   }
 
-  public static void validateContentTransferEncoding(final Map<String, HeaderField> headers, boolean isChangeRequest)
+  public static void validateContentTransferEncoding(final Map<String, HeaderField> headers,
+      final boolean isChangeRequest)
       throws BatchException {
     if (headers.containsKey(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH))) {
       HeaderField encodingField = headers.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH));
@@ -57,11 +54,6 @@ public class BatchTransformatorCommon {
     }
   }
 
-  public static void parsePartSyntax(final BatchBodyPart bodyPart) throws BatchException {
-    int contentLength = BatchTransformatorCommon.getContentLength(bodyPart.getHeaders());
-    bodyPart.parse(contentLength);
-  }
-
   public static int getContentLength(final Map<String, HeaderField> headers) throws BatchException {
 
     if (headers.containsKey(HttpHeaders.CONTENT_LENGTH.toLowerCase(Locale.ENGLISH))) {
@@ -79,6 +71,6 @@ public class BatchTransformatorCommon {
       }
     }
 
-    return Integer.MAX_VALUE;
+    return -1;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
index a3c0512..b7d7fac 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
@@ -31,8 +31,10 @@ public class AcceptParserTest {
 
   @Test
   public void testAcceptHeader() throws BatchException {
-    List<String> acceptHeaders =
-        AcceptParser.parseAcceptHeaders("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+    
     assertNotNull(acceptHeaders);
     assertEquals(4, acceptHeaders.size());
     assertEquals("text/html", acceptHeaders.get(0));
@@ -43,48 +45,58 @@ public class AcceptParserTest {
 
   @Test
   public void testAcceptHeaderWithParameter() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;odata=verbose;q=1.0, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/json;odata=verbose;q=1.0, */*;q=0.1");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+    
     assertNotNull(acceptHeaders);
     assertEquals(2, acceptHeaders.size());
     assertEquals("application/json;odata=verbose", acceptHeaders.get(0));
-    ;
     assertEquals("*/*", acceptHeaders.get(1));
   }
 
   @Test
   public void testAcceptHeaderWithParameterAndLws() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;  odata=verbose;q=1.0, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/json;  odata=verbose;q=1.0, */*;q=0.1");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+
     assertNotNull(acceptHeaders);
     assertEquals(2, acceptHeaders.size());
     assertEquals("application/json;  odata=verbose", acceptHeaders.get(0));
-    ;
     assertEquals("*/*", acceptHeaders.get(1));
   }
 
   @Test
   public void testAcceptHeaderWithTabulator() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;\todata=verbose;q=1.0, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/json;\todata=verbose;q=1.0, */*;q=0.1");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+    
     assertNotNull(acceptHeaders);
     assertEquals(2, acceptHeaders.size());
     assertEquals("application/json;" + TAB + "odata=verbose", acceptHeaders.get(0));
-    ;
     assertEquals("*/*", acceptHeaders.get(1));
   }
 
   @Test
   public void testAcceptHeaderWithTwoParameters() throws BatchException {
-    List<String> acceptHeaders =
-        AcceptParser.parseAcceptHeaders("application/xml;another=test ; param=alskdf, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/xml;another=test ; param=alskdf, */*;q=0.1");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+
     assertNotNull(acceptHeaders);
     assertEquals(2, acceptHeaders.size());
     assertEquals("application/xml;another=test ; param=alskdf", acceptHeaders.get(0));
-    ;
     assertEquals("*/*", acceptHeaders.get(1));
   }
 
   @Test
   public void testAcceptHeader2() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("text/html;level=1, application/*, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("text/html;level=1, application/*, */*;q=0.1");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+
     assertNotNull(acceptHeaders);
     assertEquals(3, acceptHeaders.size());
     assertEquals("text/html;level=1", acceptHeaders.get(0));
@@ -94,7 +106,10 @@ public class AcceptParserTest {
 
   @Test
   public void testMoreSpecificMediaType() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, application/xml");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/*, application/xml");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+    
     assertNotNull(acceptHeaders);
     assertEquals(2, acceptHeaders.size());
     assertEquals("application/xml", acceptHeaders.get(0));
@@ -103,28 +118,40 @@ public class AcceptParserTest {
 
   @Test
   public void testQualityParameter() throws BatchException {
-    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, */*; q=0.012");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("application/*, */*; q=0.012");
+    List<String> acceptHeaders = parser.parseAcceptHeaders();
+    
     assertNotNull(acceptHeaders);
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidAcceptHeader() throws BatchException {
-    AcceptParser.parseAcceptHeaders("appi cation/*, */*;q=0.1");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("appi cation/*, */*;q=0.1");
+    parser.parseAcceptHeaders();
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidQualityParameter() throws BatchException {
-    AcceptParser.parseAcceptHeaders("appication/*, */*;q=0,9");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("appication/*, */*;q=0,9");
+    parser.parseAcceptHeaders();
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidQualityParameter2() throws BatchException {
-    AcceptParser.parseAcceptHeaders("appication/*, */*;q=1.0001");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptHeaderValue("appication/*, */*;q=1.0001");
+    parser.parseAcceptHeaders();
   }
 
   @Test
   public void testAcceptLanguages() throws BatchException {
-    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("en-US,en;q=0.7,en-UK;q=0.9");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptLanguageHeaderValue("en-US,en;q=0.7,en-UK;q=0.9");
+    List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+
     assertNotNull(acceptLanguageHeaders);
     assertEquals(3, acceptLanguageHeaders.size());
     assertEquals("en-US", acceptLanguageHeaders.get(0));
@@ -134,20 +161,28 @@ public class AcceptParserTest {
 
   @Test
   public void testAllAcceptLanguages() throws BatchException {
-    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("*");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptLanguageHeaderValue("*");
+    List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+    
     assertNotNull(acceptLanguageHeaders);
     assertEquals(1, acceptLanguageHeaders.size());
   }
 
   @Test
   public void testLongAcceptLanguageValue() throws BatchException {
-    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("english");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptLanguageHeaderValue("english");
+    List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+    
     assertNotNull(acceptLanguageHeaders);
     assertEquals("english", acceptLanguageHeaders.get(0));
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidAcceptLanguageValue() throws BatchException {
-    AcceptParser.parseAcceptableLanguages("en_US");
+    AcceptParser parser = new AcceptParser();
+    parser.addAcceptLanguageHeaderValue("en_US");
+    parser.parseAcceptableLanguages();
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
index c9e9a6b..8451c55 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
@@ -1,54 +1,170 @@
 package org.apache.olingo.odata2.core.batch;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
 import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon;
+import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
 import org.junit.Test;
 
 public class BatchParserCommonTest {
-
+  
+  private static final String CRLF = "\r\n";
+  
   @Test
-  public void testTrimList() {
-    final List<String> list = Arrays.asList(new String[] { "123\r\n", "abc", "a\n", "\r", "123" });
-    final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
-    assertEquals(2, trimedList.size());
-    assertEquals("123\r\n", trimedList.get(0));
-    assertEquals("ab", trimedList.get(1));
+  public void testMultipleHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Content-Id: 2" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+    assertNotNull(contentIdHeaders);
+    assertEquals(2, contentIdHeaders.getValues().size());
+    assertEquals("1", contentIdHeaders.getValues().get(0));
+    assertEquals("2", contentIdHeaders.getValues().get(1));
   }
-
+  
   @Test
-  public void testTrimListWithEmptyString() {
-    final List<String> list = Arrays.asList(new String[] { "123\r\n", "", "abc", "a\n", "\r", "123" });
-    final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
-    assertEquals(3, trimedList.size());
-    assertEquals("123\r\n", trimedList.get(0));
-    assertEquals("", trimedList.get(1));
-    assertEquals("ab", trimedList.get(2));
+  public void testMultipleHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Content-Id: 1" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+    assertNotNull(contentIdHeaders);
+    assertEquals(1, contentIdHeaders.getValues().size());
+    assertEquals("1", contentIdHeaders.getValues().get(0));
   }
-
+  
   @Test
-  public void testTrimListTryToReadMoreThanStringLength() {
-    final List<String> list = Arrays.asList(new String[] { "abc\r\n", "123" });
-    final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 100);
-
-    assertEquals(2, trimedList.size());
-    assertEquals("abc\r\n", trimedList.get(0));
-    assertEquals("123", trimedList.get(1));
+  public void testHeaderSperatedByComma() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField upgradeHeader = header.get("upgrade");
+    assertNotNull(upgradeHeader);
+    assertEquals(4, upgradeHeader.getValues().size());
+    assertEquals("HTTP/2.0", upgradeHeader.getValues().get(0));
+    assertEquals("SHTTP/1.3", upgradeHeader.getValues().get(1));
+    assertEquals("IRC/6.9", upgradeHeader.getValues().get(2));
+    assertEquals("RTA/x11", upgradeHeader.getValues().get(3));
   }
-
+  
   @Test
-  public void testTrimListEmpty() {
-    final List<String> list = Arrays.asList(new String[0]);
-    final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
-    assertEquals(0, trimedList.size());
+  public void testMultipleAcceptHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+        "Accept: text/plain;q=0.3" + CRLF,
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+    assertNotNull(acceptHeader);
+    assertEquals(4, acceptHeader.getValues().size());
   }
-
+  
+  @Test
+  public void testMultipleAcceptHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+        "Accept: application/atomsvc+xml;q=0.8" + CRLF,
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+    assertNotNull(acceptHeader);
+    assertEquals(3, acceptHeader.getValues().size());
+  }
+  
+  @Test
+  public void testMultipleAccepLanguagetHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "Accept-Language: de-DE;q=0.3" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+    assertNotNull(acceptLanguageHeader);
+    assertEquals(4, acceptLanguageHeader.getValues().size());
+  }
+  
+  @Test
+  public void testMultipleAccepLanguagetHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "Accept-Language:en-US,en;q=0.7" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<String> message = new ArrayList<String>();
+    message.addAll(Arrays.asList(messageRaw));
+    
+    final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+    assertNotNull(acceptLanguageHeader);
+    assertEquals(3, acceptLanguageHeader.getValues().size());
+  }
+  
   @Test
   public void testRemoveEndingCRLF() {
     String line = "Test\r\n";

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
index 7866004..4cd0b67 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
@@ -431,7 +431,7 @@ public class BatchRequestParserTest {
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
-  
+
   @Test(expected = BatchException.class)
   public void testMissingContentTransferEncoding() throws BatchException {
     String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -439,7 +439,7 @@ public class BatchRequestParserTest {
         + CRLF
         + "--changeset_f980-1cb6-94dd" + CRLF
         + "Content-Type: application/http" + CRLF
-        //+ "Content-Transfer-Encoding: binary" + CRLF
+        // + "Content-Transfer-Encoding: binary" + CRLF
         + CRLF
         + "POST Employees('2') HTTP/1.1" + CRLF
         + "Content-Type: application/json;odata=verbose" + CRLF
@@ -449,14 +449,14 @@ public class BatchRequestParserTest {
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
-  
+
   @Test(expected = BatchException.class)
   public void testMissingContentType() throws BatchException {
     String batch = "--batch_8194-cf13-1f56" + CRLF
         + "Content-Type: multipart/mixed;boundary=changeset_f980-1cb6-94dd" + CRLF
         + CRLF
         + "--changeset_f980-1cb6-94dd" + CRLF
-        //+ "Content-Type: application/http" + CRLF
+        // + "Content-Type: application/http" + CRLF
         + "Content-Transfer-Encoding: binary" + CRLF
         + CRLF
         + "POST Employees('2') HTTP/1.1" + CRLF
@@ -467,7 +467,7 @@ public class BatchRequestParserTest {
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
-  
+
   @Test(expected = BatchException.class)
   public void testNoCloseDelimiter() throws BatchException {
     String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -605,32 +605,33 @@ public class BatchRequestParserTest {
 
     }
   }
-  
+
   @SuppressWarnings("unused")
-  @Test(expected=BatchException.class)
+  @Test(expected = BatchException.class)
+  @Ignore("This header should not be validated")
   public void testNegativeContentLength() throws BatchException, IOException {
-      String batch = ""
-          + "--batch_8194-cf13-1f56" + CRLF
-          + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
-          + "Content-Length: -2" + CRLF
-          + CRLF
-          + "--changeset_f980-1cb6-94dd" + CRLF
-          + MIME_HEADERS
-          + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
-          + CRLF
-          + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
-          + "Content-Type: application/json;odata=verbose" + CRLF
-          + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
-          + CRLF
-          + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
-          + "--changeset_f980-1cb6-94dd--" + CRLF
-          + CRLF
-          + "--batch_8194-cf13-1f56--";
-      InputStream in = new ByteArrayInputStream(batch.getBytes());
-      BatchParser parser = new BatchParser(contentType, batchProperties, true);
-      List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+    String batch = ""
+        + "--batch_8194-cf13-1f56" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
+        + "Content-Length: -2" + CRLF
+        + CRLF
+        + "--changeset_f980-1cb6-94dd" + CRLF
+        + MIME_HEADERS
+        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+        + CRLF
+        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+        + CRLF
+        + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+        + "--changeset_f980-1cb6-94dd--" + CRLF
+        + CRLF
+        + "--batch_8194-cf13-1f56--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchParser parser = new BatchParser(contentType, batchProperties, true);
+    List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
   }
-  
+
   @SuppressWarnings("unused")
   @Test
   public void testNegativeContentLengthChangeSet() throws BatchException, IOException {
@@ -655,9 +656,9 @@ public class BatchRequestParserTest {
     BatchParser parser = new BatchParser(contentType, batchProperties, true);
     List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
   }
-  
+
   @SuppressWarnings("unused")
-  @Test(expected=BatchException.class)
+  @Test(expected = BatchException.class)
   public void testNegativeContentLengthRequest() throws BatchException, IOException {
     String batch = ""
         + "--batch_8194-cf13-1f56" + CRLF
@@ -680,7 +681,7 @@ public class BatchRequestParserTest {
     BatchParser parser = new BatchParser(contentType, batchProperties, true);
     List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
   }
-  
+
   @Test
   public void testContentLengthGreatherThanBodyLength() throws BatchException, IOException {
     String batch = ""
@@ -746,6 +747,7 @@ public class BatchRequestParserTest {
   }
 
   @Test(expected = BatchException.class)
+  @Ignore("This header should not be validated")
   public void testCutChangeSetDelimiter() throws BatchException, IOException {
     String batch = ""
         + "--batch_8194-cf13-1f56" + CRLF
@@ -918,7 +920,7 @@ public class BatchRequestParserTest {
       }
     }
   }
-  
+
   @Test
   public void testNoContentId() throws BatchException {
     String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -950,10 +952,10 @@ public class BatchRequestParserTest {
         + "--batch_8194-cf13-1f56--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
     BatchParser parser = new BatchParser(contentType, batchProperties, true);
-    List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);  // No exception should be thrown
+    List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in); // No exception should be thrown
     assertNotNull(batchRequestParts);
   }
-  
+
   @Test
   public void testPreamble() throws BatchException, IOException {
     String batch = ""
@@ -1017,6 +1019,60 @@ public class BatchRequestParserTest {
         inputStreamToString(changeSetPart.getRequests().get(1).getBody()));
   }
 
+  @SuppressWarnings("unused")
+  @Test
+  public void testContentTypeCaseInsensitive() throws BatchException, IOException {
+    String batch = ""
+        + "--batch_8194-cf13-1f56" + CRLF
+        + "Content-Type: muLTiParT/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
+        + CRLF
+        + "--changeset_f980-1cb6-94dd" + CRLF
+        + MIME_HEADERS
+        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+        + "Content-Length: -2" + CRLF
+        + CRLF
+        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+        + CRLF
+        + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+        + "--changeset_f980-1cb6-94dd--" + CRLF
+        + CRLF
+        + "--batch_8194-cf13-1f56--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchParser parser = new BatchParser(contentType, batchProperties, true);
+    List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+  }
+
+  @Test
+  public void testContentTypeBoundaryCaseInsensitive() throws BatchException, IOException {
+    String batch = ""
+        + "--batch_8194-cf13-1f56" + CRLF
+        + "Content-Type: multipart/mixed; bOunDaRy=changeset_f980-1cb6-94dd" + CRLF
+        + CRLF
+        + "--changeset_f980-1cb6-94dd" + CRLF
+        + MIME_HEADERS
+        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+        + "Content-Length: -2" + CRLF
+        + CRLF
+        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+        + CRLF
+        + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+        + "--changeset_f980-1cb6-94dd--" + CRLF
+        + CRLF
+        + "--batch_8194-cf13-1f56--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchParser parser = new BatchParser(contentType, batchProperties, true);
+    List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+
+    assertNotNull(batchRequestParts);
+    assertEquals(1, batchRequestParts.size());
+    assertTrue(batchRequestParts.get(0).isChangeSet());
+    assertEquals(1, batchRequestParts.get(0).getRequests().size());
+  }
+
   @Test
   public void testEpilog() throws BatchException, IOException {
     String batch = ""

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
index a0ab9f4..a70d15a 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
@@ -26,7 +26,17 @@ public class BatchTransformatorCommonTest {
 
   @Test
   public void testValidateContentTypeMultipartMixed() throws BatchException {
-    List<String> contentTypeValues = Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED });
+    List<String> contentTypeValues =
+        Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED + "; boundary=batch_32332_32323_fdsf" });
+    Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+
+    BatchTransformatorCommon.validateContentType(headers);
+  }
+
+  @Test
+  public void testValidateContentTypeMultipartMixedCaseInsensitiv() throws BatchException {
+    List<String> contentTypeValues =
+        Arrays.asList(new String[] { "mulTiPart/MiXed; boundary=batch_32332_32323_fdsf" });
     Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
 
     BatchTransformatorCommon.validateContentType(headers);