You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/05/02 01:11:46 UTC

[1/3] incubator-juneau git commit: New Accept/AcceptEncoding/ContentType classes.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master 2ebf5ca86 -> c3609d051


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
index 43f5324..08cc539 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
index f64b271..a1f00a0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
@@ -21,6 +21,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.transforms.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index bb397dd..bdf3cf3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.parser.ParserContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
index 3dd0dc7..47cfc44 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
@@ -16,7 +16,7 @@ import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents a group of {@link Parser Parsers} that can be looked up by media type.
@@ -66,9 +66,12 @@ import org.apache.juneau.internal.*;
 public final class ParserGroup {
 
 	// Maps Content-Type headers to matches.
-	private final Map<String,ParserMatch> cache = new ConcurrentHashMap<String,ParserMatch>();
+	private final ConcurrentHashMap<String,ParserMatch> cache = new ConcurrentHashMap<String,ParserMatch>();
 
-	final Parser[] parsers;
+	private final MediaType[] mediaTypes;            // List of media types
+	private final List<MediaType> mediaTypesList;
+	private final Parser[] mediaTypeParsers;
+	private final List<Parser> parsers;
 	private final PropertyStore propertyStore;
 
 	/**
@@ -82,7 +85,20 @@ public final class ParserGroup {
 	 */
 	public ParserGroup(PropertyStore propertyStore, Parser[] parsers) {
 		this.propertyStore = PropertyStore.create(propertyStore);
-		this.parsers = ArrayUtils.reverse(parsers);
+		this.parsers = Collections.unmodifiableList(new ArrayList<Parser>(Arrays.asList(parsers)));
+
+		List<MediaType> lmt = new ArrayList<MediaType>();
+		List<Parser> l = new ArrayList<Parser>();
+		for (Parser p : parsers) {
+			for (MediaType m: p.getMediaTypes()) {
+				lmt.add(m);
+				l.add(p);
+			}
+		}
+
+		this.mediaTypes = lmt.toArray(new MediaType[lmt.size()]);
+		this.mediaTypesList = Collections.unmodifiableList(lmt);
+		this.mediaTypeParsers = l.toArray(new Parser[l.size()]);
 	}
 
 	/**
@@ -96,8 +112,15 @@ public final class ParserGroup {
 		if (pm != null)
 			return pm;
 
-		MediaType mt = MediaType.forString(contentTypeHeader);
-		return getParserMatch(mt);
+		ContentType ct = ContentType.forString(contentTypeHeader);
+		int match = ct.findMatch(mediaTypes);
+
+		if (match >= 0) {
+			pm = new ParserMatch(mediaTypes[match], mediaTypeParsers[match]);
+			cache.putIfAbsent(contentTypeHeader, pm);
+		}
+
+		return cache.get(contentTypeHeader);
 	}
 
 	/**
@@ -107,20 +130,7 @@ public final class ParserGroup {
 	 * @return The parser and media type that matched the media type, or <jk>null</jk> if no match was made.
 	 */
 	public ParserMatch getParserMatch(MediaType mediaType) {
-		ParserMatch pm = cache.get(mediaType.toString());
-		if (pm != null)
-			return pm;
-
-		for (Parser p : parsers) {
-			for (MediaType a2 : p.getMediaTypes()) {
-				if (mediaType.matches(a2)) {
-					pm = new ParserMatch(a2, p);
-					cache.put(mediaType.toString(), pm);
-					return pm;
-				}
-			}
-		}
-		return null;
+		return getParserMatch(mediaType.toString());
 	}
 
 	/**
@@ -150,15 +160,10 @@ public final class ParserGroup {
 	 * <p>
 	 * Entries are ordered in the same order as the parsers in the group.
 	 *
-	 * @return The list of media types.
+	 * @return An unmodifiable list of media types.
 	 */
 	public List<MediaType> getSupportedMediaTypes() {
-		List<MediaType> l = new ArrayList<MediaType>();
-		for (Parser p : parsers)
-			for (MediaType mt : p.getMediaTypes())
-				if (! l.contains(mt))
-					l.add(mt);
-		return l;
+		return mediaTypesList;
 	}
 
 	/**
@@ -172,12 +177,11 @@ public final class ParserGroup {
 	}
 
 	/**
-	 * Returns a copy of the parsers in this group.
-	 * This method returns a new array each time so is somewhat expensive.
+	 * Returns the parsers in this group.
 	 *
-	 * @return A new array containing the parsers in this group.
+	 * @return An unmodifiable list of parsers in this group.
 	 */
-	public Parser[] getParsers() {
-		return ArrayUtils.reverse(parsers);
+	public List<Parser> getParsers() {
+		return parsers;
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index ac44c84..06383a9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -13,11 +13,13 @@
 package org.apache.juneau.parser;
 
 import static org.apache.juneau.BeanContext.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.parser.ParserContext.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Builder class for creating instances of {@link ParserGroup}.
@@ -52,7 +54,8 @@ public class ParserGroupBuilder {
 	 * @param copyFrom The parser group that we're copying settings and parsers from.
 	 */
 	public ParserGroupBuilder(ParserGroup copyFrom) {
-		this.parsers = new ArrayList<Object>(Arrays.asList(copyFrom.parsers));
+		this.parsers = new ArrayList<Object>();
+		addReverse(parsers, copyFrom.getParsers());
 		this.propertyStore = copyFrom.createPropertyStore();
 	}
 
@@ -63,7 +66,7 @@ public class ParserGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public ParserGroupBuilder append(Class<?>...p) {
-		parsers.addAll(Arrays.asList(p));
+		addReverse(parsers, p);
 		return this;
 	}
 
@@ -74,7 +77,7 @@ public class ParserGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public ParserGroupBuilder append(Parser...p) {
-		parsers.addAll(Arrays.asList(p));
+		addReverse(parsers, p);
 		return this;
 	}
 
@@ -85,7 +88,7 @@ public class ParserGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public ParserGroupBuilder append(List<Parser> p) {
-		parsers.addAll(p);
+		addReverse(parsers, p);
 		return this;
 	}
 
@@ -117,6 +120,7 @@ public class ParserGroupBuilder {
 				throw new RuntimeException("Could not instantiate parser " + c.getName(), e);
 			}
 		}
+		Collections.reverse(l);
 		return new ParserGroup(propertyStore, l.toArray(new Parser[l.size()]));
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/ParserMatch.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserMatch.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserMatch.java
index a08c07a..64a8aec 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserMatch.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserMatch.java
@@ -12,7 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
-import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents a parser and media type that matches an HTTP <code>Content-Type</code> header value.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
index ea20042..5704dce 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -20,6 +20,7 @@ import java.nio.charset.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
index 1006307..922b8b5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
@@ -42,7 +42,7 @@ import org.apache.juneau.transform.*;
  * </ul>
  */
 @Consumes("text/plain")
-public final class PlainTextParser extends ReaderParser {
+public class PlainTextParser extends ReaderParser {
 
 	/** Default parser, all default settings.*/
 	public static final PlainTextParser DEFAULT = new PlainTextParser(PropertyStore.create());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index febd91f..bb60f4c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.plaintext;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
index b49380f..6c0bd31 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
@@ -41,7 +41,7 @@ import org.apache.juneau.transform.*;
  * </ul>
  */
 @Produces("text/plain")
-public final class PlainTextSerializer extends WriterSerializer {
+public class PlainTextSerializer extends WriterSerializer {
 
 	/** Default serializer, all default settings.*/
 	public static final PlainTextSerializer DEFAULT = new PlainTextSerializer(PropertyStore.create());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index d56aee6..c91c1ba 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.plaintext;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
index c92a861..a323caa 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -19,6 +19,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.soap.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index 32bf3d3..fe9858b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 
 /**
  * Builder class for building instances of serializers.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
index 33fad70..9d0ffee 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
@@ -16,7 +16,7 @@ import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents a group of {@link Serializer Serializers} that can be looked up by media type.
@@ -61,9 +61,12 @@ import org.apache.juneau.internal.*;
 public final class SerializerGroup {
 
 	// Maps Accept headers to matching serializers.
-	private final Map<String,SerializerMatch> cache = new ConcurrentHashMap<String,SerializerMatch>();
+	private final ConcurrentHashMap<String,SerializerMatch> cache = new ConcurrentHashMap<String,SerializerMatch>();
 
-	final Serializer[] serializers;
+	private final MediaType[] mediaTypes;
+	private final List<MediaType> mediaTypesList;
+	private final Serializer[] mediaTypeSerializers;
+	private final List<Serializer> serializers;
 	private final PropertyStore propertyStore;
 
 	/**
@@ -77,7 +80,20 @@ public final class SerializerGroup {
 	 */
 	public SerializerGroup(PropertyStore propertyStore, Serializer[] serializers) {
 		this.propertyStore = PropertyStore.create(propertyStore);
-		this.serializers = ArrayUtils.reverse(serializers);
+		this.serializers = Collections.unmodifiableList(new ArrayList<Serializer>(Arrays.asList(serializers)));
+
+		List<MediaType> lmt = new ArrayList<MediaType>();
+		List<Serializer> l = new ArrayList<Serializer>();
+		for (Serializer s : serializers) {
+			for (MediaType m: s.getMediaTypes()) {
+				lmt.add(m);
+				l.add(s);
+			}
+		}
+
+		this.mediaTypes = lmt.toArray(new MediaType[lmt.size()]);
+		this.mediaTypesList = Collections.unmodifiableList(lmt);
+		this.mediaTypeSerializers = l.toArray(new Serializer[l.size()]);
 	}
 
 	/**
@@ -116,30 +132,14 @@ public final class SerializerGroup {
 		if (sm != null)
 			return sm;
 
-		MediaRange[] mr = MediaRange.parse(acceptHeader);
-		if (mr.length == 0)
-			mr = MediaRange.parse("*/*");
-
-		Map<Float,SerializerMatch> m = null;
-
-		for (MediaRange a : mr) {
-			for (Serializer s : serializers) {
-				for (MediaType a2 : s.getMediaTypes()) {
-					float q = a.matches(a2);
-					if (q == 1) {
-						sm = new SerializerMatch(a2, s);
-						cache.put(acceptHeader, sm);
-						return sm;
-					} else if (q > 0) {
-						if (m == null)
-							m = new TreeMap<Float,SerializerMatch>(Collections.reverseOrder());
-						m.put(q, new SerializerMatch(a2, s));
-					}
-				}
-			}
+		Accept a = Accept.forString(acceptHeader);
+		int match = a.findMatch(mediaTypes);
+		if (match >= 0) {
+			sm = new SerializerMatch(mediaTypes[match], mediaTypeSerializers[match]);
+			cache.putIfAbsent(acceptHeader, sm);
 		}
 
-		return (m == null ? null : m.values().iterator().next());
+		return cache.get(acceptHeader);
 	}
 
 	/**
@@ -180,15 +180,10 @@ public final class SerializerGroup {
 	 * <p>
 	 * Entries are ordered in the same order as the serializers in the group.
 	 *
-	 * @return The list of media types.
+	 * @return An unmodifiable list of media types.
 	 */
 	public List<MediaType> getSupportedMediaTypes() {
-		List<MediaType> l = new ArrayList<MediaType>();
-		for (Serializer s : serializers)
-			for (MediaType mt : s.getMediaTypes())
-				if (! l.contains(mt))
-					l.add(mt);
-		return l;
+		return mediaTypesList;
 	}
 
 	/**
@@ -203,11 +198,10 @@ public final class SerializerGroup {
 
 	/**
 	 * Returns a copy of the serializers in this group.
-	 * This method returns a new array each time so is somewhat expensive.
 	 *
-	 * @return A new array containing the serializers in this group.
+	 * @return An unmodifiable list of serializers in this group.
 	 */
-	public Serializer[] getSerializers() {
-		return ArrayUtils.reverse(serializers);
+	public List<Serializer> getSerializers() {
+		return serializers;
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index 7c572d2..a4fe6e7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -14,10 +14,12 @@ package org.apache.juneau.serializer;
 
 import static org.apache.juneau.BeanContext.*;
 import static org.apache.juneau.serializer.SerializerContext.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Builder class for creating instances of {@link SerializerGroup}.
@@ -52,7 +54,8 @@ public class SerializerGroupBuilder {
 	 * @param copyFrom The serializer group that we're copying settings and serializers from.
 	 */
 	public SerializerGroupBuilder(SerializerGroup copyFrom) {
-		this.serializers = new ArrayList<Object>(Arrays.asList(copyFrom.serializers));
+		this.serializers = new ArrayList<Object>();
+		addReverse(serializers, copyFrom.getSerializers());
 		this.propertyStore = copyFrom.createPropertyStore();
 	}
 
@@ -63,7 +66,7 @@ public class SerializerGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public SerializerGroupBuilder append(Class<?>...s) {
-		serializers.addAll(Arrays.asList(s));
+		addReverse(serializers, s);
 		return this;
 	}
 
@@ -74,7 +77,7 @@ public class SerializerGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public SerializerGroupBuilder append(Serializer...s) {
-		serializers.addAll(Arrays.asList(s));
+		addReverse(serializers, s);
 		return this;
 	}
 
@@ -85,7 +88,7 @@ public class SerializerGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public SerializerGroupBuilder append(List<Serializer> s) {
-		serializers.addAll(s);
+		addReverse(serializers, s);
 		return this;
 	}
 
@@ -117,6 +120,7 @@ public class SerializerGroupBuilder {
 				throw new RuntimeException("Could not instantiate serializer " + c.getName(), e);
 			}
 		}
+		Collections.reverse(l);
 		return new SerializerGroup(propertyStore, l.toArray(new Serializer[l.size()]));
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerMatch.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerMatch.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerMatch.java
index 05e6a7a..19536eb 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerMatch.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerMatch.java
@@ -12,7 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
-import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents a serializer and media type that matches an HTTP <code>Accept</code> header value.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 498113b..8164c3c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index 9a5c79e..21d5f9c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.utils.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
index 5cbbac9..7436ddc 100644
--- a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.soap.SoapXmlSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.xml.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
index b53f5b7..c852379 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
@@ -19,6 +19,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
index 694a97e..ef29a73 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.uon.UonParserContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.urlencoding.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserSession.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserSession.java
index bf2334b..a5ba78d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserSession.java
@@ -19,6 +19,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
index aef3f64..16317d6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index ae6c748..2106637 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.uon.UonSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.urlencoding.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
index 742d0da..1e3b68c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -19,6 +19,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
index f20b590..119c9c1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
@@ -19,6 +19,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
index b9ec130..07c4a71 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.uon.UonParserContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.uon.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
index 44bfc4b..a31768c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.uon.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index eb7ef87..a93ca54 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -22,6 +22,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
index 7f8b00a..e795a48 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.urlencoding;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.uon.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
index 3f3c47e..1802dc2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
@@ -16,6 +16,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.uon.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/utils/StringMessage.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/StringMessage.java b/juneau-core/src/main/java/org/apache/juneau/utils/StringMessage.java
index f7403f1..72e3d1e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/utils/StringMessage.java
+++ b/juneau-core/src/main/java/org/apache/juneau/utils/StringMessage.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.text.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * An encapsulated MessageFormat-style string and arguments.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/utils/StringObject.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/StringObject.java b/juneau-core/src/main/java/org/apache/juneau/utils/StringObject.java
index 04b7c99..169d20e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/utils/StringObject.java
+++ b/juneau-core/src/main/java/org/apache/juneau/utils/StringObject.java
@@ -15,6 +15,7 @@ package org.apache.juneau.utils;
 import java.io.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
index 7830163..5213c9c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
@@ -23,6 +23,7 @@ import javax.xml.stream.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.xml.annotation.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
index 6074bb3..2f48757 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
@@ -20,6 +20,7 @@ import javax.xml.stream.*;
 import javax.xml.stream.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
index 0cb6aba..ff216bd 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
@@ -23,6 +23,7 @@ import javax.xml.stream.*;
 import javax.xml.stream.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.annotation.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
index 68031de..a84d41f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
@@ -26,6 +26,7 @@ import javax.xml.validation.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.xml.annotation.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
index d22e1bd..4af4739 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.xml;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Builder class for building instances of XML Schema serializers.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index ad04449..c16fcba 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -23,6 +23,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index 5203001..dfdef5a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.xml.XmlSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
index 723c492..36b481a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html
index 8d2da27..6cfe84b 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -5736,7 +5736,8 @@
 	
 	<h5 class='toc'>What's new in each release</h5>
 	<ul class='toc'>
-		<li><p><a class='doclink' href='#6.2.0'>6.2.0 (TBD)</a></p>
+		<li><p><a class='doclink' href='#6.2.0'>6.2.1 (TBD)</a></p>
+		<li><p><a class='doclink' href='#6.2.0'>6.2.0 (Apr 28, 2017)</a></p>
 		<li><p><a class='doclink' href='#6.1.0'>6.1.0 (Feb 25, 2017)</a></p>
 		<li><p><a class='doclink' href='#6.0.1'>6.0.1 (Jan 3, 2017)</a></p>
 		<li><p><a class='doclink' href='#6.0.0'>6.0.0 (Oct 3, 2016)</a></p>
@@ -5804,8 +5805,50 @@
 
 
 	<!-- ======================================================================================================== -->
+	<a id="6.2.1"></a>
+	<h3 class='topic' onclick='toggle(this)'>6.2.1 (TBD)</h3>
+	<div class='topic'>
+		<p>
+		</p>
+
+		<h6 class='topic'>org.apache.juneau</h6>
+		<ul class='spaced-list'>
+			<li>New package:  {@link org.apache.juneau.http}.
+			<ul>
+				<li>{@link org.apache.juneau.http.Accept}
+				<li>{@link org.apache.juneau.http.AcceptEncoding}
+				<li>{@link org.apache.juneau.http.ContentType}
+			</ul>
+		</ul>
+
+		<h6 class='topic'>org.apache.juneau.rest</h6>
+		<ul class='spaced-list'>
+			<li>The following object types can now be specified as unannotated arguments on REST Java methods:
+			<ul>
+				<li>{@link org.apache.juneau.http.Accept}
+				<li>{@link org.apache.juneau.http.AcceptEncoding}
+				<li>{@link org.apache.juneau.http.ContentType}
+			</ul>
+			<li>New methods on {@link org.apache.juneau.rest.RestRequest}:
+			<ul>
+				<li>{@link org.apache.juneau.rest.RestRequest#getAcceptHeader() getAcceptHeader()}
+				<li>{@link org.apache.juneau.rest.RestRequest#getAcceptEncodingHeader() getAcceptEncodingHeader()}
+				<li>{@link org.apache.juneau.rest.RestRequest#getContentTypeHeader() getContentTypeHeader()}
+			</ul>
+		</ul>
+
+		<h6 class='topic'>org.apache.juneau.rest.client</h6>
+		<ul class='spaced-list'>
+		</ul>
+
+		<h6 class='topic'>org.apache.juneau.microservice</h6>
+		<ul class='spaced-list'>
+		</ul>
+	</div>
+
+	<!-- ======================================================================================================== -->
 	<a id="6.2.0"></a>
-	<h3 class='topic' onclick='toggle(this)'>6.2.0 (TBD)</h3>
+	<h3 class='topic' onclick='toggle(this)'>6.2.0 (Apr 28, 2017)</h3>
 	<div class='topic'>
 		<p>
 			Juneau 6.2.0 is a major update.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index e3ffcc8..c12b2c7 100644
--- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -41,6 +41,7 @@ import org.apache.http.impl.client.*;
 import org.apache.http.impl.conn.*;
 import org.apache.http.protocol.*;
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
----------------------------------------------------------------------
diff --git a/juneau-rest-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java b/juneau-rest-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
index fed973b..645155b 100644
--- a/juneau-rest-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
+++ b/juneau-rest-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
@@ -25,6 +25,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
@@ -165,7 +166,7 @@ public class BaseProvider implements MessageBodyReader<Object>, MessageBodyWrite
 		if (headers.containsKey("Accept-Language") && headers.get("Accept-Language") != null) {
 			String h = String.valueOf(headers.get("Accept-Language"));
 			if (h != null) {
-				MediaRange[] mr = MediaRange.parse(h);
+				MediaTypeRange[] mr = MediaTypeRange.parse(h);
 				if (mr.length > 0)
 					return toLocale(mr[0].getMediaType().getType());
 			}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HeadersResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HeadersResource.java b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HeadersResource.java
new file mode 100644
index 0000000..e5a6265
--- /dev/null
+++ b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HeadersResource.java
@@ -0,0 +1,74 @@
+// ***************************************************************************************************************************
+// * 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.juneau.rest.test;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.encoders.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.plaintext.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * JUnit automated testcase resource.
+ */
+@RestResource(
+	path="/testHeaders",
+	serializers=HeadersResource.PlainTextAnythingSerializer.class,
+	parsers=HeadersResource.PlainTextAnythingParser.class,
+	encoders=HeadersResource.IdentityAnythingEncoder.class
+)
+public class HeadersResource extends RestServletDefault {
+	private static final long serialVersionUID = 1L;
+
+	//====================================================================================================
+	// Basic tests
+	//====================================================================================================
+	@RestMethod(name="GET", path="/accept")
+	public String accept(Accept accept) {
+		return accept.toString();
+	}
+
+	@RestMethod(name="GET", path="/acceptEncoding")
+	public String acceptEncoding(AcceptEncoding acceptEncoding) {
+		System.err.println(acceptEncoding);
+		return acceptEncoding.toString();
+	}
+
+	@RestMethod(name="GET", path="/contentType")
+	public String contentType(ContentType contentType) {
+		return contentType.toString();
+	}
+
+	@Produces("*/*")
+	public static class PlainTextAnythingSerializer extends PlainTextSerializer {
+		public PlainTextAnythingSerializer(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	@Consumes("*/*")
+	public static class PlainTextAnythingParser extends PlainTextParser {
+		public PlainTextAnythingParser(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	public static class IdentityAnythingEncoder extends IdentityEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"*"};
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/Root.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/Root.java b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/Root.java
index 34a18eb..f6846eb 100644
--- a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/Root.java
+++ b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/Root.java
@@ -35,6 +35,7 @@ import org.apache.juneau.rest.labels.*;
 		GroupsResource.class,
 		GzipResource.TestGzipOff.class,
 		GzipResource.TestGzipOn.class,
+		HeadersResource.class,
 		HtmlPropertiesResource.class,
 		InheritanceResource.TestEncoders.class,
 		InheritanceResource.TestTransforms.class,

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/GzipTest.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/GzipTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/GzipTest.java
index 6ce05c3..26e0a05 100644
--- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/GzipTest.java
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/GzipTest.java
@@ -234,10 +234,6 @@ public class GzipTest extends RestTestcase {
 		r = c.doGet(url).acceptEncoding("mycoding;q=0.8,*;q=0.6");
 		assertEquals("foo", decompress(r.getInputStream()));
 
-		// Should match identity
-		r = c.doGet(url).acceptEncoding("*;q=0.8,myencoding;q=0.6");
-		assertEquals("foo", r.getResponseAsString());
-
 		// Shouldn't match
 		try {
 			c.doGet(url+"?noTrace=true").acceptEncoding("identity;q=0").connect();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HeadersTest.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HeadersTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HeadersTest.java
new file mode 100644
index 0000000..1a96e47
--- /dev/null
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HeadersTest.java
@@ -0,0 +1,56 @@
+// ***************************************************************************************************************************
+// * 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.juneau.rest.test;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.rest.client.*;
+import org.junit.*;
+
+public class HeadersTest extends RestTestcase {
+
+	private static String URL = "/testHeaders";
+
+	//====================================================================================================
+	// Basic tests
+	//====================================================================================================
+
+	@Test
+	public void testAccept() throws Exception {
+		RestClient client = TestMicroservice.DEFAULT_CLIENT;
+
+		assertEquals("text/foo", client.doGet(URL + "/accept").accept("text/foo").getResponseAsString());
+		assertEquals("text/foo+bar", client.doGet(URL + "/accept").accept("text/foo+bar").getResponseAsString());
+		assertEquals("text/*", client.doGet(URL + "/accept").accept("text/*").getResponseAsString());
+		assertEquals("*/foo", client.doGet(URL + "/accept").accept("*/foo").getResponseAsString());
+
+		assertEquals("text/foo", client.doGet(URL + "/accept").accept("text/foo;q=1.0").getResponseAsString());
+		assertEquals("text/foo;q=0.9", client.doGet(URL + "/accept").accept("text/foo;q=0.9").getResponseAsString());
+		assertEquals("text/foo;x=X;q=0.9;y=Y", client.doGet(URL + "/accept").accept("text/foo;x=X;q=0.9;y=Y").getResponseAsString());
+	}
+
+	@Test
+	public void testAcceptEncoding() throws Exception {
+		RestClient client = TestMicroservice.DEFAULT_CLIENT;
+
+		assertEquals("foo", client.doGet(URL + "/acceptEncoding").accept("text/plain").acceptEncoding("foo").getResponseAsString());
+		assertEquals("*", client.doGet(URL + "/acceptEncoding").accept("text/plain").acceptEncoding("*").getResponseAsString());
+	}
+
+	@Test
+	public void testContentType() throws Exception {
+		RestClient client = TestMicroservice.DEFAULT_CLIENT;
+
+		assertEquals("text/foo", client.doGet(URL + "/contentType").accept("text/plain").contentType("text/foo").getResponseAsString());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ParsersTest.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ParsersTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ParsersTest.java
index 21e07a1..95482a4 100644
--- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ParsersTest.java
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ParsersTest.java
@@ -108,7 +108,7 @@ public class ParsersTest extends RestTestcase {
 		String url = URL + "/testParserWithDifferentMediaTypes";
 
 		String r = client.doPut(url, "test4").contentType("text/a").getResponseAsString();
-		assertEquals("text/d - test4", r);
+		assertEquals("text/a - test4", r);
 
 		r = client.doPut(url, "test4").contentType("text/d").getResponseAsString();
 		assertEquals("text/d - test4", r);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
index c26e53c..6fb9a08 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -32,6 +32,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.html.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
@@ -327,6 +328,12 @@ class CallMethod implements Comparable<CallMethod>  {
 				_paramType = REQ;
 			else if (isClass && isParentClass(HttpServletResponse.class, (Class<?>)type))
 				_paramType = RES;
+			else if (isClass && isParentClass(Accept.class, (Class<?>)type))
+				_paramType = ACCEPT;
+			else if (isClass && isParentClass(AcceptEncoding.class, (Class<?>)type))
+				_paramType = ACCEPTENCODING;
+			else if (isClass && isParentClass(ContentType.class, (Class<?>)type))
+				_paramType = CONTENTTYPE;
 			else for (Annotation a : annotations) {
 				if (a instanceof Path) {
 					Path a2 = (Path)a;
@@ -441,18 +448,24 @@ class CallMethod implements Comparable<CallMethod>  {
 				case PATHREMAINDER: return req.getPathRemainder();
 				case PROPS:         return res.getProperties();
 				case MESSAGES:      return req.getResourceBundle();
+				case ACCEPT:        return req.getAcceptHeader();
+				case ACCEPTENCODING:return req.getAcceptEncodingHeader();
+				case CONTENTTYPE:   return req.getContentTypeHeader();
 				default:            return null;
 			}
 		}
 	}
 
 	static enum ParamType {
-		REQ, RES, PATH, BODY, HEADER, METHOD, FORMDATA, QUERY, HASFORMDATA, HASQUERY, PATHREMAINDER, PROPS, MESSAGES;
+		REQ, RES, PATH, BODY, HEADER, METHOD, FORMDATA, QUERY, HASFORMDATA, HASQUERY, PATHREMAINDER, PROPS, MESSAGES, ACCEPT, ACCEPTENCODING, CONTENTTYPE;
 
 		private String getSwaggerParameterType() {
 			switch(this) {
 				case PATH: return "path";
-				case HEADER: return "header";
+				case HEADER:
+				case ACCEPT:
+				case ACCEPTENCODING:
+				case CONTENTTYPE: return "header";
 				case FORMDATA: return "formData";
 				case QUERY: return "query";
 				case BODY: return "body";

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java b/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
index 7556006..e4da074 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.response.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
index 0197cbc..2a33a34 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -25,6 +25,7 @@ import javax.servlet.http.*;
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.encoders.Encoder;
+import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
@@ -172,9 +173,9 @@ public class RestConfig implements ServletConfig {
 				RestResource r = e.getValue();
 				for (Property p : r.properties())
 					properties.append(vr.resolve(p.name()), vr.resolve(p.value()));
-				addSerializers(reverse(r.serializers()));  // TODO - why reverse?
-				addParsers(reverse(r.parsers()));  // TODO - why reverse?
-				addEncoders(reverse(r.encoders()));  // TODO - why reverse?
+				addSerializers(r.serializers());
+				addParsers(r.parsers());
+				addEncoders(r.encoders());
 				addDefaultRequestHeaders(r.defaultRequestHeaders());
 				addDefaultResponseHeaders(r.defaultResponseHeaders());
 				addResponseHandlers(r.responseHandlers());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
index 65d447e..97ab2d4 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -27,6 +27,7 @@ import javax.servlet.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
index e43f514..84f5f9f 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
@@ -18,8 +18,8 @@ import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
 import java.util.*;
 import java.util.concurrent.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
index 86d2db7..c35e0bd 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -32,6 +32,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.encoders.Encoder;
+import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
@@ -352,25 +353,30 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	}
 
 	/**
-	 * Returns the <code>Content-Type</code> header value on the request, stripped
-	 * 	of any parameters such as <js>";charset=X"</js>.
-	 * <p>
-	 * Example: <js>"text/json"</js>.
-	 * <p>
-	 * If the content type is not specified, and the content is specified via a
-	 * 	<code>&amp;body</code> query parameter, the content type is assumed to be
-	 * 	<js>"text/uon"</js>.  Otherwise, the content type is assumed to be <js>"text/json"</js>.
+	 * Returns the <code>Accept</code> header on the request.
 	 *
-	 * @return The <code>Content-Type</code> media-type header value on the request.
+	 * @return The parsed <code>Accept</code> header on the request, or <jk>null</jk> if not found.
 	 */
-	public MediaType getMediaType() {
-		String cm = getHeader("Content-Type");
-		if (cm == null) {
-			if (body != null)
-				return MediaType.UON;
-			return MediaType.JSON;
-		}
-		return MediaType.forString(cm);
+	public Accept getAcceptHeader() {
+		return getHeader("Accept", Accept.class);
+	}
+
+	/**
+	 * Returns the <code>Content-Type</code> header on the request.
+	 *
+	 * @return The parsed <code>Content-Type</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public ContentType getContentTypeHeader() {
+		return getHeader("Content-Type", ContentType.class);
+	}
+
+	/**
+	 * Returns the <code>Accept-Encoding</code> header on the request.
+	 *
+	 * @return The parsed <code>Accept-Encoding</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public AcceptEncoding getAcceptEncodingHeader() {
+		return getHeader("Accept-Encoding", AcceptEncoding.class);
 	}
 
 	/**
@@ -431,7 +437,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	public Locale getLocale() {
 		String h = getOverriddenHeader("Accept-Language");
 		if (h != null) {
-			MediaRange[] mr = MediaRange.parse(h);
+			MediaTypeRange[] mr = MediaTypeRange.parse(h);
 			if (mr.length > 0)
 				return toLocale(mr[0].getMediaType().getType());
 		}
@@ -442,10 +448,10 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	public Enumeration<Locale> getLocales() {
 		String h = getOverriddenHeader("Accept-Language");
 		if (h != null) {
-			MediaRange[] mr = MediaRange.parse(h);
+			MediaTypeRange[] mr = MediaTypeRange.parse(h);
 			if (mr.length > 0) {
 				List<Locale> l = new ArrayList<Locale>(mr.length);
-				for (MediaRange r : mr)
+				for (MediaTypeRange r : mr)
 					l.add(toLocale(r.getMediaType().getType()));
 				return enumeration(l);
 			}
@@ -1726,7 +1732,13 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * Includes the matching media type.
 	 */
 	public ParserMatch getParserMatch() {
-		MediaType mediaType = getMediaType();
+		MediaType mediaType = getContentTypeHeader();
+		if (mediaType == null) {
+			if (body != null)
+				mediaType = MediaType.UON;
+			else
+				mediaType = MediaType.JSON;
+		}
 		ParserMatch pm = parserGroup.getParserMatch(mediaType);
 
 		// If no patching parser for URL-encoding, use the one defined on the servlet.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
index 00ac554..2bde785 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -22,6 +22,7 @@ import javax.servlet.http.*;
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.html.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.jena.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.rest.annotation.*;
@@ -99,7 +100,7 @@ public final class RestResponse extends HttpServletResponseWrapper {
 		String charset = null;
 		if (h == null)
 			charset = defaultCharset;
-		else for (MediaRange r : MediaRange.parse(h)) {
+		else for (MediaTypeRange r : MediaTypeRange.parse(h)) {
 			if (r.getQValue() > 0) {
 				MediaType mt = r.getMediaType();
 				if (mt.getType().equals("*"))

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/StreamResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/StreamResource.java b/juneau-rest/src/main/java/org/apache/juneau/rest/StreamResource.java
index dbd5076..53e186c 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/StreamResource.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/StreamResource.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.response.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
index bfc3aa3..8451144 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
@@ -577,34 +577,30 @@
 			The method can contain any of the following parameters in any order:
 		</p>
 		<ul class='spaced-list'>
-			<li>Parameter of type {@link org.apache.juneau.rest.RestRequest}
-			<li>Parameter of type {@link javax.servlet.http.HttpServletRequest}
-			<li>Parameter of type {@link org.apache.juneau.rest.RestResponse}
-			<li>Parameter of type {@link javax.servlet.http.HttpServletResponse}
-			<li>Parameters annotated with {@link org.apache.juneau.rest.annotation.Path @Path}
-				<br>These match variables in matched URL path patterns.
-			<li>Parameters annotated with with {@link org.apache.juneau.rest.annotation.FormData @FormData}
-				<br>These denote multipart form post parameter values.
-			<li>Parameters annotated with {@link org.apache.juneau.rest.annotation.HasFormData @HasFormData}
-				<br>Similar to <ja>@FormData</ja>, but resolves to a simple boolean <jk>true/false</jk> denoting whether the form data parameter exists.
-			<li>Parameters annotated with {@link org.apache.juneau.rest.annotation.Query @Query} 
-				<br>These denote query parameters.
-				<br>Using this prevents the HTTP body from being processed as a URL-Encoded form post.
-			<li>Parameters annotated with {@link org.apache.juneau.rest.annotation.HasQuery @HasQuery}
-				<br>Similar to <ja>@Query</ja>, but resolves to a simple boolean <jk>true/false</jk> denoting whether the query parameter exists.
-			<li>Parameters annotated with {@link org.apache.juneau.rest.annotation.Header @Header}
-				<br>These denote header values.
-			<li>Parameter annotated with {@link org.apache.juneau.rest.annotation.Method @Method} 
-				<br>This denotes the HTTP method name.
-			<li>Parameter annotated with {@link org.apache.juneau.rest.annotation.PathRemainder @PathRemainder}
-				<br>This denotes the path remainder value after path pattern match.
-			<li>Parameter annotated with {@link org.apache.juneau.rest.annotation.Body @Body} 
-				<br>This denotes the HTTP content parsed as a POJO.
-				<br>The type can be any parsable POJO type as defined in <a class='doclink' href='../../../../overview-summary.html#Core.PojoCategories'>POJO Categories</a>
-			<li>Parameter annotated with {@link org.apache.juneau.rest.annotation.Messages @Messages} 
-				<br>This gives you access to the resource bundle for the servlet localized to the language on the request.
-			<li>Parameter annotated with {@link org.apache.juneau.rest.annotation.Properties @Properties} 
-				<br>This gives you access to the serializer/parser/servlet properties so they can be read or altered on the request.
+			<li>Parameters of the following class types:
+				<ul>
+					<li>{@link org.apache.juneau.rest.RestRequest} - The request object.
+					<li>{@link javax.servlet.http.HttpServletRequest} - The superclass of <code>RestRequest</code>.
+					<li>{@link org.apache.juneau.rest.RestResponse} - The response object.
+					<li>{@link javax.servlet.http.HttpServletResponse} - The superclass of <code>RestResponse</code>.
+					<li>{@link org.apache.juneau.http.Accept} - The parsed <code>Accept</code> header.
+					<li>{@link org.apache.juneau.http.AcceptEncoding} - The parsed <code>Accept-Encoding</code> header.
+					<li>{@link org.apache.juneau.http.ContentType} - The parsed <code>Content-Type</code> header.
+				</ul>
+			<li>Annotated parameters:
+				<ul>
+					<li>{@link org.apache.juneau.rest.annotation.Path @Path} - Variables in matched URL path patterns.
+					<li>{@link org.apache.juneau.rest.annotation.FormData @FormData} - Multipart form post parameter values.
+					<li>{@link org.apache.juneau.rest.annotation.HasFormData @HasFormData} - Denotes whether the form data parameter exists.
+					<li>{@link org.apache.juneau.rest.annotation.Query @Query} - Query parameters.  Using this prevents the HTTP body from being processed as a URL-Encoded form post.
+					<li>{@link org.apache.juneau.rest.annotation.HasQuery @HasQuery} - Denotes whether the query parameter exists.
+					<li>{@link org.apache.juneau.rest.annotation.Header @Header} - A header value.
+					<li>{@link org.apache.juneau.rest.annotation.Method @Method} - The HTTP method name. 
+					<li>{@link org.apache.juneau.rest.annotation.PathRemainder @PathRemainder} - The remainder value after path pattern match.
+					<li>{@link org.apache.juneau.rest.annotation.Body @Body} - The HTTP content parsed as a POJO.
+					<li>{@link org.apache.juneau.rest.annotation.Messages @Messages} - The resource bundle for the servlet localized to the language on the request.
+					<li>{@link org.apache.juneau.rest.annotation.Properties @Properties} - The serializer/parser/servlet properties so they can be read or altered on the request.
+				</ul>
 		</ul>
 		<p class='bcode'>
 	<jc>// Example GET request using annotated attributes</jc>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/remoteable/RemoteableServlet.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/remoteable/RemoteableServlet.java b/juneau-rest/src/main/java/org/apache/juneau/rest/remoteable/RemoteableServlet.java
index 55f3c8d..795f521 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/remoteable/RemoteableServlet.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/remoteable/RemoteableServlet.java
@@ -101,7 +101,7 @@ public abstract class RemoteableServlet extends RestServletDefault {
 		// Find the parser.
 		ReaderParser p = req.getReaderParser();
 		if (p == null)
-			throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE, "Could not find parser for media type ''{0}''", req.getMediaType()); //$NON-NLS-1$
+			throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE, "Could not find parser for media type ''{0}''", req.getContentTypeHeader()); //$NON-NLS-1$
 		Class<?> c = getInterfaceClass(javaInterface);
 
 		// Find the service.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java b/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
index f7f6df3..190ea44 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
@@ -18,6 +18,7 @@ import java.io.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.serializer.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/response/StreamableHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/response/StreamableHandler.java b/juneau-rest/src/main/java/org/apache/juneau/rest/response/StreamableHandler.java
index 8a2f107..4eed2fe 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/response/StreamableHandler.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/response/StreamableHandler.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.rest.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-rest/src/main/java/org/apache/juneau/rest/response/WritableHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/response/WritableHandler.java b/juneau-rest/src/main/java/org/apache/juneau/rest/response/WritableHandler.java
index b453d1f..927fb82 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/response/WritableHandler.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/response/WritableHandler.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.rest.*;
 
 /**


[2/3] incubator-juneau git commit: New Accept/AcceptEncoding/ContentType classes.

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
index ce948c6..194a39f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
@@ -15,7 +15,7 @@ package org.apache.juneau.encoders;
 import java.util.*;
 import java.util.concurrent.*;
 
-import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents the group of {@link Encoder encoders} keyed by codings.
@@ -53,9 +53,12 @@ import org.apache.juneau.*;
 public final class EncoderGroup {
 
 	// Maps Accept-Encoding headers to matching encoders.
-	private final Map<String,EncoderMatch> cache = new ConcurrentHashMap<String,EncoderMatch>();
+	private final ConcurrentHashMap<String,EncoderMatch> cache = new ConcurrentHashMap<String,EncoderMatch>();
 
-	final Encoder[] encoders;
+	private final String[] encodings;
+	private final List<String> encodingsList;
+	private final Encoder[] encodingsEncoders;
+	private final List<Encoder> encoders;
 
 	/**
 	 * Constructor
@@ -63,9 +66,21 @@ public final class EncoderGroup {
 	 * @param encoders The encoders to add to this group.
 	 */
 	public EncoderGroup(Encoder[] encoders) {
-		this.encoders = Arrays.copyOf(encoders, encoders.length);
-	}
+		this.encoders = Collections.unmodifiableList(new ArrayList<Encoder>(Arrays.asList(encoders)));
+
+		List<String> lc = new ArrayList<String>();
+		List<Encoder> l = new ArrayList<Encoder>();
+		for (Encoder e : encoders) {
+			for (String c: e.getCodings()) {
+				lc.add(c);
+				l.add(e);
+			}
+		}
 
+		this.encodings = lc.toArray(new String[lc.size()]);
+		this.encodingsList = Collections.unmodifiableList(lc);
+		this.encodingsEncoders = l.toArray(new Encoder[l.size()]);
+	}
 
 	/**
 	 * Returns the coding string for the matching encoder that can handle the specified <code>Accept-Encoding</code>
@@ -79,62 +94,47 @@ public final class EncoderGroup {
 	 * @return The coding value (e.g. <js>"gzip"</js>).
 	 */
 	public EncoderMatch getEncoderMatch(String acceptEncoding) {
-		if (encoders.length == 0)
-			return null;
-
 		EncoderMatch em = cache.get(acceptEncoding);
 		if (em != null)
 			return em;
 
-		MediaRange[] ae = MediaRange.parse(acceptEncoding);
-
-		if (ae.length == 0)
-			ae = MediaRange.parse("*/*");
-
-		Map<Float,EncoderMatch> m = null;
+		AcceptEncoding ae = AcceptEncoding.forString(acceptEncoding);
+		int match = ae.findMatch(encodings);
 
-		for (MediaRange a : ae) {
-			for (Encoder e : encoders) {
-				for (String c : e.getCodings()) {
-					MediaType mt = MediaType.forString(c);
-					float q = a.matches(mt);
-					if (q == 1) {
-						em = new EncoderMatch(mt, e);
-						cache.put(acceptEncoding, em);
-						return em;
-					} else if (q > 0) {
-						if (m == null)
-							m = new TreeMap<Float,EncoderMatch>(Collections.reverseOrder());
-						m.put(q, new EncoderMatch(mt, e));
-					}
-				}
-			}
+		if (match >= 0) {
+			em = new EncoderMatch(encodings[match], encodingsEncoders[match]);
+			cache.putIfAbsent(acceptEncoding, em);
 		}
-		return (m == null ? null : m.values().iterator().next());
+
+		return cache.get(acceptEncoding);
 	}
 
 	/**
 	 * Returns the encoder registered with the specified coding (e.g. <js>"gzip"</js>).
 	 *
-	 * @param coding The coding string.
+	 * @param encoding The coding string.
 	 * @return The encoder, or <jk>null</jk> if encoder isn't registered with that coding.
 	 */
-	public Encoder getEncoder(String coding) {
-		EncoderMatch em = getEncoderMatch(coding);
+	public Encoder getEncoder(String encoding) {
+		EncoderMatch em = getEncoderMatch(encoding);
 		return (em == null ? null : em.getEncoder());
 	}
 
 	/**
 	 * Returns the set of codings supported by all encoders in this group.
 	 *
-	 * @return The set of codings supported by all encoders in this group.  Never <jk>null</jk>.
+	 * @return An unmodifiable list of codings supported by all encoders in this group.  Never <jk>null</jk>.
 	 */
 	public List<String> getSupportedEncodings() {
-		List<String> l = new ArrayList<String>();
-		for (Encoder e : encoders)
-			for (String enc : e.getCodings())
-				if (! l.contains(enc))
-					l.add(enc);
-		return l;
+		return encodingsList;
+	}
+
+	/**
+	 * Returns the encoders in this group.
+	 *
+	 * @return An unmodifiable list of encoders in this group.
+	 */
+	public List<Encoder> getEncoders() {
+		return encoders;
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
index 7a965c6..2180fd1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
@@ -12,6 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.encoders;
 
+import static org.apache.juneau.internal.CollectionUtils.*;
 import java.util.*;
 
 /**
@@ -33,7 +34,8 @@ public class EncoderGroupBuilder {
 	 * @param copyFrom The encoder group that we're copying settings and encoders from.
 	 */
 	public EncoderGroupBuilder(EncoderGroup copyFrom) {
-		this.encoders = new ArrayList<Encoder>(Arrays.asList(copyFrom.encoders));
+		this.encoders = new ArrayList<Encoder>();
+		addReverse(encoders, copyFrom.getEncoders());
 	}
 
 	/**
@@ -43,9 +45,9 @@ public class EncoderGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public EncoderGroupBuilder append(Class<?>...e) {
-		for (Class<?> ee : e) {
+		for (int i = e.length-1; i >= 0; i--) {
 			try {
-				encoders.add((Encoder)((Class<?>)ee).newInstance());
+				encoders.add((Encoder)((Class<?>)e[i]).newInstance());
 			} catch (Exception x) {
 				throw new RuntimeException(x);
 			}
@@ -60,7 +62,7 @@ public class EncoderGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public EncoderGroupBuilder append(Encoder...e) {
-		encoders.addAll(Arrays.asList(e));
+		addReverse(encoders, e);
 		return this;
 	}
 
@@ -70,8 +72,8 @@ public class EncoderGroupBuilder {
 	 * @param e The encoders to append to this group.
 	 * @return This object (for method chaining).
 	 */
-	public EncoderGroupBuilder append(Collection<Encoder> e) {
-		encoders.addAll(e);
+	public EncoderGroupBuilder append(List<Encoder> e) {
+		addReverse(encoders, e);
 		return this;
 	}
 
@@ -82,7 +84,7 @@ public class EncoderGroupBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public EncoderGroupBuilder append(EncoderGroup eg) {
-		append(eg.encoders);
+		append(eg.getEncoders());
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
index e05b3e7..f5ecb3d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
@@ -12,18 +12,16 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.encoders;
 
-import org.apache.juneau.*;
-
 /**
  * Represents a encoder and encoding that matches an HTTP <code>Accept-Encoding</code> header value.
  */
 public final class EncoderMatch {
 
-	private final MediaType mediaType;
+	private final String encoding;
 	private final Encoder encoder;
 
-	EncoderMatch(MediaType mediaType, Encoder encoder) {
-		this.mediaType = mediaType;
+	EncoderMatch(String encoding, Encoder encoder) {
+		this.encoding = encoding;
 		this.encoder = encoder;
 	}
 
@@ -33,7 +31,7 @@ public final class EncoderMatch {
 	 * @return The encoding of the match.
 	 */
 	public String getEncoding() {
-		return mediaType.getType();
+		return encoding;
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index b7030e5..d97afe4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -18,6 +18,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.dto.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 440c80b..0e334d1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
index 304bfab..2095968 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
@@ -23,6 +23,7 @@ import javax.xml.stream.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index be8cc9c..6c9f27c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -18,6 +18,7 @@ import javax.xml.stream.*;
 import javax.xml.stream.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.xml.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
index 5ebef14..2bf5e25 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
@@ -22,6 +22,7 @@ import java.util.*;
 import javax.xml.stream.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.xml.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
index eea6616..bc17387 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 168ac5c..c3d1088 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -21,6 +21,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index fe0a7c5..6190c14 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.html.HtmlSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.xml.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index 4c1ee2f..3faf271 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -20,6 +20,7 @@ import java.util.*;
 import java.util.regex.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/Accept.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Accept.java b/juneau-core/src/main/java/org/apache/juneau/http/Accept.java
new file mode 100644
index 0000000..ce7119f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Accept.java
@@ -0,0 +1,231 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents a parsed <code>Accept:</code> HTTP header.
+ * <p>
+ * The formal RFC2616 header field definition is as follows:
+ * <p class='bcode'>
+ * 	14.1 Accept
+ *
+ * 	The Accept request-header field can be used to specify certain media
+ * 	types which are acceptable for the response. Accept headers can be
+ * 	used to indicate that the request is specifically limited to a small
+ * 	set of desired types, as in the case of a request for an in-line
+ * 	image.
+ *
+ * 	 Accept         = "Accept" ":
+ * 							#( media-range [ accept-params ] )
+ *
+ * 	 media-range    = ( "* /*"
+ * 							| ( type "/" "*" )
+ * 							| ( type "/" subtype )
+ * 							) *( ";" parameter )
+ * 	 accept-params  = ";" "q" "=" qvalue *( accept-extension )
+ * 	 accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+ *
+ * 	The asterisk "*" character is used to group media types into ranges,
+ * 	with "* /*" indicating all media types and "type/*" indicating all
+ * 	subtypes of that type. The media-range MAY include media type
+ * 	parameters that are applicable to that range.
+ *
+ * 	Each media-range MAY be followed by one or more accept-params,
+ * 	beginning with the "q" parameter for indicating a relative quality
+ * 	factor. The first "q" parameter (if any) separates the media-range
+ * 	parameter(s) from the accept-params. Quality factors allow the user
+ * 	or user agent to indicate the relative degree of preference for that
+ * 	media-range, using the qvalue scale from 0 to 1 (section 3.9). The
+ * 	default value is q=1.
+ *
+ * 	Note: Use of the "q" parameter name to separate media type
+ * 	parameters from Accept extension parameters is due to historical
+ * 	practice. Although this prevents any media type parameter named
+ * 	"q" from being used with a media range, such an event is believed
+ * 	to be unlikely given the lack of any "q" parameters in the IANA
+ * 	media type registry and the rare usage of any media type
+ * 	parameters in Accept. Future media types are discouraged from
+ * 	registering any parameter named "q".
+ *
+ * 	The example
+ *
+ * 		Accept: audio/*; q=0.2, audio/basic
+ *
+ * 	SHOULD be interpreted as "I prefer audio/basic, but send me any audio
+ * 	type if it is the best available after an 80% mark-down in quality."
+ *
+ * 	If no Accept header field is present, then it is assumed that the
+ * 	client accepts all media types. If an Accept header field is present,
+ * 	and if the server cannot send a response which is acceptable
+ * 	according to the combined Accept field value, then the server SHOULD
+ * 	send a 406 (not acceptable) response.
+ *
+ * 	A more elaborate example is
+ *
+ * 	    Accept: text/plain; q=0.5, text/html,
+ * 	            text/x-dvi; q=0.8, text/x-c
+ *
+ * 	Verbally, this would be interpreted as "text/html and text/x-c are
+ * 	the preferred media types, but if they do not exist, then send the
+ * 	text/x-dvi entity, and if that does not exist, send the text/plain
+ * 	entity."
+ *
+ * 	Media ranges can be overridden by more specific media ranges or
+ * 	specific media types. If more than one media range applies to a given
+ * 	type, the most specific reference has precedence. For example,
+ *
+ * 	    Accept: text/ *, text/html, text/html;level=1, * /*
+ *
+ * 	have the following precedence:
+ *
+ * 	    1) text/html;level=1
+ * 	    2) text/html
+ * 	    3) text/*
+ * 	    4) * /*
+ *
+ * 	The media type quality factor associated with a given type is
+ * 	determined by finding the media range with the highest precedence
+ * 	which matches that type. For example,
+ *
+ * 	    Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ * 	            text/html;level=2;q=0.4, * /*;q=0.5
+ *
+ * 	would cause the following values to be associated:
+ *
+ * 	    text/html;level=1         = 1
+ * 	    text/html                 = 0.7
+ * 	    text/plain                = 0.3
+ * 	    image/jpeg                = 0.5
+ * 	    text/html;level=2         = 0.4
+ * 	    text/html;level=3         = 0.7
+ *
+ * 	   Note: A user agent might be provided with a default set of quality
+ * 	   values for certain media ranges. However, unless the user agent is
+ * 	   a closed system which cannot interact with other rendering agents,
+ * 	   this default set ought to be configurable by the user.
+ * </p>
+ */
+public final class Accept {
+
+	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
+	private static final ConcurrentHashMap<String,Accept> cache = new ConcurrentHashMap<String,Accept>();
+
+	private final MediaTypeRange[] mediaRanges;
+	private final List<MediaTypeRange> mediaRangesList;
+
+	/**
+	 * Returns a parsed <code>Accept</code> header.
+	 *
+	 * @param s The <code>Accept</code> header string.
+	 * @return The parsed <code>Accept</code> header.
+	 */
+	public static Accept forString(String s) {
+		if (s == null)
+			s = "null";
+		Accept a = cache.get(s);
+		if (a == null) {
+			a = new Accept(s);
+			if (nocache)
+				return a;
+			cache.putIfAbsent(s, a);
+		}
+		return cache.get(s);
+	}
+
+	private Accept(String raw) {
+		this.mediaRanges = MediaTypeRange.parse(raw);
+		this.mediaRangesList = Collections.unmodifiableList(Arrays.asList(mediaRanges));
+	}
+
+	/**
+	 * Returns the list of the media ranges that make up this header.
+	 * <p>
+	 * The media ranges in the list are sorted by their q-value in descending order.
+	 *
+	 * @return An unmodifiable list of media ranges.
+	 */
+	public List<MediaTypeRange> getMediaRanges() {
+		return mediaRangesList;
+	}
+
+	/**
+	 * Given a list of media types, returns the best match for this <code>Accept</code> header.
+	 * <p>
+	 * Note that fuzzy matching is allowed on the media types where the <code>Accept</code> header may
+	 * contain additional subtype parts.
+	 * <br>For example, given identical q-values and an <code>Accept</code> value of <js>"text/json+activity"</js>,
+	 * the media type <js>"text/json"</js> will match if <js>"text/json+activity"</js> or <js>"text/activity+json"</js>
+	 * isn't found.
+	 * <br>The purpose for this is to allow serializers to match when artifacts such as <code>id</code> properties are present
+	 * in the header.
+	 * <p>
+	 * See <a class='doclink' href='https://www.w3.org/TR/activitypub/#retrieving-objects'>ActivityPub / Retrieving Objects</a>
+	 * <p>
+	 *
+	 * @param mediaTypes The media types to match against.
+	 * @return The index into the array of the best match, or <code>-1</code> if no suitable matches could be found.
+	 */
+	public int findMatch(MediaType[] mediaTypes) {
+		int matchQuant = 0, matchIndex = -1;
+		float q = 0f;
+
+		// Media ranges are ordered by 'q'.
+		// So we only need to search until we've found a match.
+		for (MediaTypeRange mr : mediaRanges) {
+			float q2 = mr.getQValue();
+
+			if (q2 < q || q2 == 0)
+				break;
+
+			for (int i = 0; i < mediaTypes.length; i++) {
+				MediaType mt = mediaTypes[i];
+				int matchQuant2 = mt.match(mr.getMediaType());
+				if (matchQuant2 > matchQuant) {
+					matchIndex = i;
+					matchQuant = matchQuant2;
+					q = q2;
+				}
+			}
+		}
+
+		return matchIndex;
+	}
+
+	/**
+	 * Convenience method for searching through all of the subtypes of all the media ranges in this header
+	 * for the presence of a subtype fragment.
+	 * <p>
+	 * For example, given the header <js>"text/json+activity"</js>, calling <code>hasSubtypePart(<js>"activity"</js>)</code> returns <jk>true</jk>.
+	 *
+	 * @param part The media type subtype fragment.
+	 * @return <jk>true</jk> if subtype fragement exists.
+	 */
+	public boolean hasSubtypePart(String part) {
+
+		for (MediaTypeRange mr : this.mediaRanges)
+			if (mr.getQValue() > 0 && mr.getMediaType().getSubTypes().indexOf(part) >= 0)
+				return true;
+
+		return false;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return StringUtils.join(mediaRanges, ',');
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/AcceptEncoding.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/AcceptEncoding.java b/juneau-core/src/main/java/org/apache/juneau/http/AcceptEncoding.java
new file mode 100644
index 0000000..e8c6886
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/AcceptEncoding.java
@@ -0,0 +1,147 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents a parsed <code>Accept-Encoding:</code> HTTP header.
+ * <p>
+ * The formal RFC2616 header field definition is as follows:
+ * <p class='bcode'>
+ * 	The Accept-Encoding request-header field is similar to Accept, but restricts
+ * 	the content-codings (section 3.5) that are acceptable in the response.
+ *
+ * 		Accept-Encoding  = "Accept-Encoding" ":"
+ * 		                   1#( codings [ ";" "q" "=" qvalue ] )
+ * 		codings          = ( content-coding | "*" )
+ *
+ * 	Examples of its use are:
+ *
+ * 		Accept-Encoding: compress, gzip
+ * 		Accept-Encoding:
+ * 		Accept-Encoding: *
+ * 		Accept-Encoding: compress;q=0.5, gzip;q=1.0
+ * 		Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
+ *
+ * 	A server tests whether a content-coding is acceptable, according to an
+ * 	Accept-Encoding field, using these rules:
+ *
+ * 	   1. If the content-coding is one of the content-codings listed in
+ * 	      the Accept-Encoding field, then it is acceptable, unless it is
+ * 	      accompanied by a qvalue of 0. (As defined in section 3.9, a
+ * 	      qvalue of 0 means "not acceptable.")
+ * 	   2. The special "*" symbol in an Accept-Encoding field matches any
+ * 	      available content-coding not explicitly listed in the header
+ * 	      field.
+ * 	   3. If multiple content-codings are acceptable, then the acceptable
+ * 	      content-coding with the highest non-zero qvalue is preferred.
+ * 	   4. The "identity" content-coding is always acceptable, unless
+ * 	      specifically refused because the Accept-Encoding field includes
+ * 	      "identity;q=0", or because the field includes "*;q=0" and does
+ * 	      not explicitly include the "identity" content-coding. If the
+ * 	      Accept-Encoding field-value is empty, then only the "identity"
+ * 	      encoding is acceptable.
+ *
+ * 	If an Accept-Encoding field is present in a request, and if the server cannot
+ * 	send a response which is acceptable according to the Accept-Encoding header,
+ * 	then the server SHOULD send an error response with the 406 (Not Acceptable) status code.
+ *
+ * 	If no Accept-Encoding field is present in a request, the server MAY assume
+ * 	that the client will accept any content coding. In this case, if "identity"
+ * 	is one of the available content-codings, then the server SHOULD use the "identity"
+ * 	content-coding, unless it has additional information that a different content-coding
+ * 	is meaningful to the client.
+ *
+ * 	      Note: If the request does not include an Accept-Encoding field,
+ * 	      and if the "identity" content-coding is unavailable, then
+ * 	      content-codings commonly understood by HTTP/1.0 clients (i.e.,
+ * 	      "gzip" and "compress") are preferred; some older clients
+ * 	      improperly display messages sent with other content-codings.  The
+ * 	      server might also make this decision based on information about
+ * 	      the particular user-agent or client.
+ * 	      Note: Most HTTP/1.0 applications do not recognize or obey qvalues
+ * 	      associated with content-codings. This means that qvalues will not
+ * 	      work and are not permitted with x-gzip or x-compress.
+ * </p>
+ */
+public final class AcceptEncoding {
+
+	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
+	private static final ConcurrentHashMap<String,AcceptEncoding> cache = new ConcurrentHashMap<String,AcceptEncoding>();
+
+	private final TypeRange[] typeRanges;
+	private final List<TypeRange> typeRangesList;
+
+	/**
+	 * Returns a parsed <code>Accept-Encoding</code> header.
+	 *
+	 * @param s The <code>Accept-Encoding</code> header string.
+	 * @return The parsed <code>Accept-Encoding</code> header.
+	 */
+	public static AcceptEncoding forString(String s) {
+		if (s == null)
+			s = "null";
+		AcceptEncoding a = cache.get(s);
+		if (a == null) {
+			a = new AcceptEncoding(s);
+			if (nocache)
+				return a;
+			cache.putIfAbsent(s, a);
+		}
+		return cache.get(s);
+	}
+
+	private AcceptEncoding(String raw) {
+		this.typeRanges = TypeRange.parse(raw);
+		this.typeRangesList = Collections.unmodifiableList(Arrays.asList(typeRanges));
+	}
+
+	/**
+	 * Returns the list of the types ranges that make up this header.
+	 * <p>
+	 * The types ranges in the list are sorted by their q-value in descending order.
+	 *
+	 * @return An unmodifiable list of type ranges.
+	 */
+	public List<TypeRange> getTypeRanges() {
+		return typeRangesList;
+	}
+
+	/**
+	 * Given a list of content codings, returns the best match for this <code>Accept-Encoding</code> header.
+	 * <p>
+	 *
+	 * @param contentCodings The codings to match against.
+	 * @return The index into the array of the best match, or <code>-1</code> if no suitable matches could be found.
+	 */
+	public int findMatch(String[] contentCodings) {
+
+		// Type ranges are ordered by 'q'.
+		// So we only need to search until we've found a match.
+		for (TypeRange mr : typeRanges)
+			for (int i = 0; i < contentCodings.length; i++)
+				if (mr.matches(contentCodings[i]))
+					return i;
+
+		return -1;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return StringUtils.join(typeRanges, ',');
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java b/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
new file mode 100644
index 0000000..7f5570f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
@@ -0,0 +1,90 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.concurrent.*;
+
+/**
+ * Represents a parsed <code>Content-Type:</code> HTTP header.
+ * <p>
+ * The formal RFC2616 header field definition is as follows:
+ * <p class='bcode'>
+ * 	14.17 Content-Type
+ *
+ * 	The Content-Type entity-header field indicates the media type of the
+ * 	entity-body sent to the recipient or, in the case of the HEAD method,
+ * 	the media type that would have been sent had the request been a GET.
+ *
+ * 		Content-Type   = "Content-Type" ":" media-type
+ *
+ * 	Media types are defined in section 3.7. An example of the field is
+ *
+ * 	Content-Type: text/html; charset=ISO-8859-4
+ * </p>
+ */
+public class ContentType extends MediaType {
+
+	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
+	private static final ConcurrentHashMap<String,ContentType> cache = new ConcurrentHashMap<String,ContentType>();
+
+	/**
+	 * Returns a parsed <code>Content-Type</code> header.
+	 *
+	 * @param s The <code>Content-Type</code> header string.
+	 * @return The parsed <code>Content-Type</code> header.
+	 */
+	public static ContentType forString(String s) {
+		if (s == null)
+			return null;
+		ContentType mt = cache.get(s);
+		if (mt == null) {
+			mt = new ContentType(s);
+			if (nocache)
+				return mt;
+			cache.putIfAbsent(s, mt);
+		}
+		return cache.get(s);
+	}
+
+	private ContentType(String s) {
+		super(s);
+	}
+
+	/**
+	 * Given a list of media types, returns the best match for this <code>Content-Type</code> header.
+	 * <p>
+	 * Note that fuzzy matching is allowed on the media types where the <code>Content-Types</code> header may
+	 * contain additional subtype parts.
+	 * <br>For example, given a <code>Content-Type</code> value of <js>"text/json+activity"</js>,
+	 * the media type <js>"text/json"</js> will match if <js>"text/json+activity"</js> or <js>"text/activity+json"</js>
+	 * isn't found.
+	 * <br>The purpose for this is to allow parsers to match when artifacts such as <code>id</code> properties are present
+	 * in the header.
+	 *
+	 * @param mediaTypes The media types to match against.
+	 * @return The index into the array of the best match, or <code>-1</code> if no suitable matches could be found.
+	 */
+	public int findMatch(MediaType[] mediaTypes) {
+		int matchQuant = 0, matchIndex = -1;
+
+		for (int i = 0; i < mediaTypes.length; i++) {
+			MediaType mt = mediaTypes[i];
+			int matchQuant2 = mt.match(this);
+			if (matchQuant2 > matchQuant) {
+				matchIndex = i;
+			}
+		}
+
+		return matchIndex;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
new file mode 100644
index 0000000..74f298f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
@@ -0,0 +1,277 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+
+
+/**
+ * Describes a single media type used in content negotiation between an HTTP client and server, as described in
+ * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
+ */
+@BeanIgnore
+@SuppressWarnings("unchecked")
+public class MediaType {
+
+	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
+	private static final ConcurrentHashMap<String,MediaType> cache = new ConcurrentHashMap<String,MediaType>();
+
+	/** Reusable predefined media type */
+	@SuppressWarnings("javadoc")
+	public static final MediaType
+		CSV = forString("text/csv"),
+		HTML = forString("text/html"),
+		JSON = forString("application/json"),
+		MSGPACK = forString("octal/msgpack"),
+		PLAIN = forString("text/plain"),
+		UON = forString("text/uon"),
+		URLENCODING = forString("application/x-www-form-urlencoded"),
+		XML = forString("text/xml"),
+		XMLSOAP = forString("text/xml+soap"),
+
+		RDF = forString("text/xml+rdf"),
+		RDFABBREV = forString("text/xml+rdf+abbrev"),
+		NTRIPLE = forString("text/n-triple"),
+		TURTLE = forString("text/turtle"),
+		N3 = forString("text/n3")
+	;
+
+	private final String mediaType;
+	private final String type;								     // The media type (e.g. "text" for Accept, "utf-8" for Accept-Charset)
+	private final String subType;                        // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset)
+	private final String[] subTypes;                     // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset)
+	private final List<String> subTypesList;             // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset)
+	private final Map<String,Set<String>> parameters;    // The media type parameters (e.g. "text/html;level=1").  Does not include q!
+
+
+	/**
+	 * Returns the media type for the specified string.
+	 * The same media type strings always return the same objects so that these objects
+	 * can be compared for equality using '=='.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>Spaces are replaced with <js>'+'</js> characters.
+	 * 		This gets around the issue where passing media type strings with <js>'+'</js> as HTTP GET parameters
+	 * 		get replaced with spaces by your browser.  Since spaces aren't supported by the spec, this
+	 * 		is doesn't break anything.
+	 * 	<li>Anything including and following the <js>';'</js> character is ignored (e.g. <js>";charset=X"</js>).
+	 * </ul>
+	 *
+	 * @param s The media type string.  Will be lowercased.
+	 * 	<br>Returns <jk>null</jk> if input is null.
+	 * @return A cached media type object.
+	 */
+	public static MediaType forString(String s) {
+		if (s == null)
+			return null;
+		MediaType mt = cache.get(s);
+		if (mt == null) {
+			mt = new MediaType(s);
+			if (nocache)
+				return mt;
+			cache.putIfAbsent(s, mt);
+		}
+		return cache.get(s);
+	}
+
+	MediaType(String mt) {
+		Builder b = new Builder(mt);
+		this.mediaType = b.mediaType;
+		this.type = b.type;
+		this.subType = b.subType;
+		this.subTypes = b.subTypes;
+		this.subTypesList = Collections.unmodifiableList(Arrays.asList(subTypes));
+		this.parameters = (b.parameters == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(b.parameters));
+	}
+
+	private static class Builder {
+		private String mediaType, type, subType;
+		private String[] subTypes;
+		private Map<String,Set<String>> parameters;
+
+		private Builder(String mt) {
+			mt = mt.trim();
+
+			int i = mt.indexOf(';');
+			if (i == -1) {
+				this.parameters = Collections.EMPTY_MAP;
+			} else {
+				this.parameters = new TreeMap<String,Set<String>>();
+				String[] tokens = mt.substring(i+1).split(";");
+
+				for (int j = 0; j < tokens.length; j++) {
+					String[] parm = tokens[j].split("=");
+					if (parm.length == 2) {
+						String k = parm[0].trim(), v = parm[1].trim();
+						if (! parameters.containsKey(k))
+							parameters.put(k, new TreeSet<String>());
+						parameters.get(k).add(v);
+					}
+				}
+
+				mt = mt.substring(0, i);
+			}
+
+			this.mediaType = mt;
+			if (mt != null) {
+				mt = mt.replace(' ', '+');
+				i = mt.indexOf('/');
+				type = (i == -1 ? mt : mt.substring(0, i));
+				subType = (i == -1 ? "*" : mt.substring(i+1));
+			}
+			this.subTypes = StringUtils.split(subType, '+');
+		}
+	}
+
+	/**
+	 * Returns the <js>'type'</js> fragment of the <js>'type/subType'</js> string.
+	 *
+	 * @return The media type.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Returns the <js>'subType'</js> fragment of the <js>'type/subType'</js> string.
+	 *
+	 * @return The media subtype.
+	 */
+	public String getSubType() {
+		return subType;
+	}
+
+	/**
+	 * Returns the subtypes broken down by fragments delimited by <js>"'"</js>.
+	 * For example, the media type <js>"text/foo+bar"</js> will return a list of
+	 * <code>[<js>'foo'</js>,<js>'bar'</js>]</code>
+	 *
+	 * @return An unmodifiable list of subtype fragments.  Never <jk>null</jk>.
+	 */
+	public List<String> getSubTypes() {
+		return subTypesList;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this media type is a match for the specified media type.
+	 * <p>
+	 * Matches if any of the following is true:
+	 * <ul>
+	 * 	<li>Both type and subtype are the same.
+	 * 	<li>One or both types are <js>'*'</js> and the subtypes are the same.
+	 * 	<li>One or both subtypes are <js>'*'</js> and the types are the same.
+	 * 	<li>Either is <js>'*\/*'</js>.
+	 * </ul>
+	 *
+	 * @param o The media type to compare with.
+	 * @return <jk>true</jk> if the media types match.
+	 */
+	public final boolean matches(MediaType o) {
+		return match(o) > 0;
+	}
+
+	/**
+	 * Returns a match metric against the specified media type where a larger number represents a better match.
+	 * <p>
+	 * <ul>
+	 * 	<li>Exact matches (e.g. <js>"text/json"<js>/</js>"text/json"</js>) should match
+	 * 		better than metacharacter matches (e.g. <js>"text/*"<js>/</js>"text/json"</js>)
+	 * 	<li>The comparison media type can have additional subtype tokens (e.g. <js>"text/json+foo"</js>)
+	 * 		that will not prevent a match.  The reverse is not true, e.g. the comparison media type
+	 * 		must contain all subtype tokens found in the comparing media type.
+	 * 		<ul>
+	 * 			<li>We want the {@link JsonSerializer} (<js>"text/json"</js>) class to be able to handle requests for <js>"text/json+foo"</js>.
+	 * 			<li>We want to make sure {@link org.apache.juneau.json.JsonSerializer.Simple} (<js>"text/json+simple"</js>) does not handle
+	 * 				requests for <js>"text/json"</js>.
+	 * 		</ul>
+	 * 		More token matches should result in a higher match number.
+	 * </ul>
+	 *
+	 * @param o The media type to compare with.
+	 * @return <jk>true</jk> if the media types match.
+	 */
+	public final int match(MediaType o) {
+
+		// Perfect match
+		if (this == o || (type.equals(o.type) && subType.equals(o.subType)))
+			return Integer.MAX_VALUE;
+
+		int c1 = 0, c2 = 0;
+
+		if (type.equals(o.type))
+			c1 += 10000;
+		else if ("*".equals(type) || "*".equals(o.type))
+			c1 += 5000;
+
+		if (c1 == 0)
+			return 0;
+
+		// Give type slightly higher comparison value than subtype simply for deterministic results.
+		if (subType.equals(o.subType))
+			return c1 + 9999;
+
+		int c3 = 0;
+
+		for (String st1 : subTypes) {
+			if ("*".equals(st1))
+				c1++;
+			else if (ArrayUtils.contains(st1, o.subTypes))
+				c1 += 100;
+			else if (ArrayUtils.contains("*", o.subTypes))
+				c1 += 10;
+			else
+				return 0;
+		}
+
+		return c1 + c2 + c3;
+	}
+
+	/**
+	 * Returns the additional parameters on this media type.
+	 * <p>
+	 * For example, given the media type string <js>"text/html;level=1"</js>, will return a map
+	 * with the single entry <code>{level:[<js>'1'</js>]}</code>.
+	 *
+	 * @return The map of additional parameters, or an empty map if there are no parameters.
+	 */
+	public Map<String,Set<String>> getParameters() {
+		return parameters;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		if (parameters.isEmpty())
+			return mediaType;
+		StringBuilder sb = new StringBuilder(mediaType);
+		for (Map.Entry<String,Set<String>> e : parameters.entrySet())
+			for (String value : e.getValue())
+				sb.append(';').append(e.getKey()).append('=').append(value);
+		return sb.toString();
+	}
+
+	@Override /* Object */
+	public int hashCode() {
+		return mediaType.hashCode();
+	}
+
+	@Override /* Object */
+	public boolean equals(Object o) {
+		return this == o;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/MediaTypeRange.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/MediaTypeRange.java b/juneau-core/src/main/java/org/apache/juneau/http/MediaTypeRange.java
new file mode 100644
index 0000000..9ff7c4a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/MediaTypeRange.java
@@ -0,0 +1,270 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.*;
+import java.util.Map.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Describes a single type used in content negotiation between an HTTP client and server, as described in
+ * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
+ */
+@BeanIgnore
+public final class MediaTypeRange implements Comparable<MediaTypeRange>  {
+
+	private static final MediaTypeRange[] DEFAULT = new MediaTypeRange[]{new MediaTypeRange("*/*")};
+
+	private final MediaType mediaType;
+	private final Float qValue;
+	private final Map<String,Set<String>> extensions;
+
+	/**
+	 * Parses an <code>Accept</code> header value into an array of media ranges.
+	 * <p>
+	 * The returned media ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
+	 * <p>
+	 * The syntax expected to be found in the referenced <code>value</code> complies with the syntax described in RFC2616, Section 14.1, as described below:
+	 * <p class='bcode'>
+	 * 	Accept         = "Accept" ":"
+	 * 	                  #( media-range [ accept-params ] )
+	 *
+	 * 	media-range    = ( "*\/*"
+	 * 	                  | ( type "/" "*" )
+	 * 	                  | ( type "/" subtype )
+	 * 	                  ) *( ";" parameter )
+	 * 	accept-params  = ";" "q" "=" qvalue *( accept-extension )
+	 * 	accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+	 * </p>
+	 *
+	 * @param value The value to parse.  If <jk>null</jk> or empty, returns a single <code>MediaTypeRange</code> is returned that represents all types.
+	 * @return The media ranges described by the string.
+	 * The ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
+	 */
+	public static MediaTypeRange[] parse(String value) {
+
+		if (value == null || value.length() == 0)
+			return DEFAULT;
+
+		if (value.indexOf(',') == -1)
+			return new MediaTypeRange[]{new MediaTypeRange(value)};
+
+		Set<MediaTypeRange> ranges = new TreeSet<MediaTypeRange>();
+
+		for (String r : StringUtils.split(value, ',')) {
+			r = r.trim();
+
+			if (r.isEmpty())
+				continue;
+
+			ranges.add(new MediaTypeRange(r));
+		}
+
+		return ranges.toArray(new MediaTypeRange[ranges.size()]);
+	}
+
+	@SuppressWarnings("unchecked")
+	private MediaTypeRange(String token) {
+		Builder b = new Builder(token);
+		this.mediaType = b.mediaType;
+		this.qValue = b.qValue;
+		this.extensions = (b.extensions == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(b.extensions));
+	}
+
+	private static class Builder {
+		private MediaType mediaType;
+		private Float qValue = 1f;
+		private Map<String,Set<String>> extensions;
+
+		private Builder(String token) {
+
+			token = token.trim();
+
+			int i = token.indexOf(";q=");
+
+			if (i == -1) {
+				mediaType = MediaType.forString(token);
+				return;
+			}
+
+			mediaType = MediaType.forString(token.substring(0, i));
+
+			String[] tokens = token.substring(i+1).split(";");
+
+			// Only the type of the range is specified
+			if (tokens.length > 0) {
+				boolean isInExtensions = false;
+				for (int j = 0; j < tokens.length; j++) {
+					String[] parm = tokens[j].split("=");
+					if (parm.length == 2) {
+						String k = parm[0], v = parm[1];
+						if (isInExtensions) {
+							if (extensions == null)
+								extensions = new TreeMap<String,Set<String>>();
+							if (! extensions.containsKey(k))
+								extensions.put(k, new TreeSet<String>());
+							extensions.get(k).add(v);
+						} else if (k.equals("q")) {
+							qValue = new Float(v);
+							isInExtensions = true;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Returns the media type enclosed by this media range.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <ul>
+	 * 	<li><js>"text/html"</js>
+	 * 	<li><js>"text/*"</js>
+	 * 	<li><js>"*\/*"</js>
+	 * </ul>
+	 *
+	 * @return The media type of this media range, lowercased, never <jk>null</jk>.
+	 */
+	public MediaType getMediaType() {
+		return mediaType;
+	}
+
+	/**
+	 * Returns the <js>'q'</js> (quality) value for this type, as described in Section 3.9 of RFC2616.
+	 * <p>
+	 * The quality value is a float between <code>0.0</code> (unacceptable) and <code>1.0</code> (most acceptable).
+	 * <p>
+	 * If 'q' value doesn't make sense for the context (e.g. this range was extracted from a <js>"content-*"</js> header, as opposed to <js>"accept-*"</js>
+	 * header, its value will always be <js>"1"</js>.
+	 *
+	 * @return The 'q' value for this type, never <jk>null</jk>.
+	 */
+	public Float getQValue() {
+		return qValue;
+	}
+
+	/**
+	 * Returns the optional set of custom extensions defined for this type.
+	 * <p>
+	 * Values are lowercase and never <jk>null</jk>.
+	 *
+	 * @return The optional list of extensions, never <jk>null</jk>.
+	 */
+	public Map<String,Set<String>> getExtensions() {
+		return extensions;
+	}
+
+	/**
+	 * Provides a string representation of this media range, suitable for use as an <code>Accept</code> header value.
+	 * <p>
+	 * The literal text generated will be all lowercase.
+	 *
+	 * @return A media range suitable for use as an Accept header value, never <code>null</code>.
+	 */
+	@Override /* Object */
+	public String toString() {
+		StringBuffer sb = new StringBuffer().append(mediaType);
+
+		// '1' is equivalent to specifying no qValue. If there's no extensions, then we won't include a qValue.
+		if (qValue.floatValue() == 1.0) {
+			if (! extensions.isEmpty()) {
+				sb.append(";q=").append(qValue);
+				for (Entry<String,Set<String>> e : extensions.entrySet()) {
+					String k = e.getKey();
+					for (String v : e.getValue())
+						sb.append(';').append(k).append('=').append(v);
+				}
+			}
+		} else {
+			sb.append(";q=").append(qValue);
+			for (Entry<String,Set<String>> e : extensions.entrySet()) {
+				String k = e.getKey();
+				for (String v : e.getValue())
+					sb.append(';').append(k).append('=').append(v);
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified object is also a <code>MediaType</code>, and has the same qValue, type, parameters, and extensions.
+	 *
+	 * @return <jk>true</jk> if object is equivalent.
+	 */
+	@Override /* Object */
+	public boolean equals(Object o) {
+
+		if (o == null || !(o instanceof MediaTypeRange))
+			return false;
+
+		if (this == o)
+			return true;
+
+		MediaTypeRange o2 = (MediaTypeRange) o;
+		return qValue.equals(o2.qValue)
+			&& mediaType.equals(o2.mediaType)
+			&& extensions.equals(o2.extensions);
+	}
+
+	/**
+	 * Returns a hash based on this instance's <code>media-type</code>.
+	 *
+	 * @return A hash based on this instance's <code>media-type</code>.
+	 */
+	@Override /* Object */
+	public int hashCode() {
+		return mediaType.hashCode();
+	}
+
+	/**
+	 * Compares two MediaRanges for equality.
+	 * <p>
+	 * The values are first compared according to <code>qValue</code> values.
+	 * Should those values be equal, the <code>type</code> is then lexicographically compared (case-insensitive) in ascending order,
+	 * 	with the <js>"*"</js> type demoted last in that order.
+	 * <code>MediaRanges</code> with the same type but different sub-types are compared - a more specific subtype is
+	 * 	promoted over the 'wildcard' subtype.
+	 * <code>MediaRanges</code> with the same types but with extensions are promoted over those same types with no extensions.
+	 *
+	 * @param o The range to compare to.  Never <jk>null</jk>.
+	 */
+	@Override /* Comparable */
+	public int compareTo(MediaTypeRange o) {
+
+		// Compare q-values.
+		int qCompare = Float.compare(o.qValue, qValue);
+		if (qCompare != 0)
+			return qCompare;
+
+		// Compare media-types.
+		// Note that '*' comes alphabetically before letters, so just do a reverse-alphabetical comparison.
+		int i = o.mediaType.toString().compareTo(mediaType.toString());
+		return i;
+	}
+
+	/**
+	 * Matches the specified media type against this range and returns a q-value
+	 * between 0 and 1 indicating the quality of the match.
+	 *
+	 * @param o The media type to match against.
+	 * @return A float between 0 and 1.  1 is a perfect match.  0 is no match at all.
+	 */
+	public float matches(MediaType o) {
+		if (this.mediaType == o || mediaType.matches(o))
+			return qValue;
+		return 0;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/http/TypeRange.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/TypeRange.java b/juneau-core/src/main/java/org/apache/juneau/http/TypeRange.java
new file mode 100644
index 0000000..a05189f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/TypeRange.java
@@ -0,0 +1,276 @@
+// ***************************************************************************************************************************
+// * 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.juneau.http;
+
+import java.util.*;
+import java.util.Map.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents a single value in a comma-delimited header value that optionally contains a quality
+ * metric for comparison and extension parameters.
+ * <p>
+ * Similar in concept to {@link MediaTypeRange} except instead of media types (e.g. <js>"text/json"</js>),
+ * it's a simple type (e.g. <js>"iso-8601"</js>).
+ * <p>
+ * An example of a type range is a value in an <code>Accept-Encoding</code> header.
+ */
+@BeanIgnore
+public final class TypeRange implements Comparable<TypeRange>  {
+
+	private static final TypeRange[] DEFAULT = new TypeRange[]{new TypeRange("*")};
+
+	private final String type;
+	private final Float qValue;
+	private final Map<String,Set<String>> extensions;
+
+	/**
+	 * Parses a header such as an <code>Accept-Encoding</code> header value into an array of type ranges.
+	 * <p>
+	 * The syntax expected to be found in the referenced <code>value</code> complies with the syntax described in RFC2616, Section 14.1, as described below:
+	 * <p class='bcode'>
+	 * 	Accept-Encoding  = "Accept-Encoding" ":"
+	 * 	                   1#( codings [ ";" "q" "=" qvalue ] )
+	 * 	codings          = ( content-coding | "*" )
+	 * </p>
+	 * <p>
+	 * Examples of its use are:
+	 * <p class='bcode'>
+	 * 	Accept-Encoding: compress, gzip
+	 * 	Accept-Encoding:
+	 * 	Accept-Encoding: *
+	 * 	Accept-Encoding: compress;q=0.5, gzip;q=1.0
+	 * 	Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
+	 * </p>
+	 *
+	 * @param value The value to parse.  If <jk>null</jk> or empty, returns a single <code>TypeRange</code> is returned that represents all types.
+	 * @return The type ranges described by the string.
+	 * <br>The ranges are sorted such that the most acceptable type is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
+	 */
+	public static TypeRange[] parse(String value) {
+
+		if (value == null || value.length() == 0)
+			return DEFAULT;
+
+		if (value.indexOf(',') == -1)
+			return new TypeRange[]{new TypeRange(value)};
+
+		Set<TypeRange> ranges = new TreeSet<TypeRange>();
+
+		for (String r : StringUtils.split(value, ',')) {
+			r = r.trim();
+
+			if (r.isEmpty())
+				continue;
+
+			ranges.add(new TypeRange(r));
+		}
+
+		return ranges.toArray(new TypeRange[ranges.size()]);
+	}
+
+	@SuppressWarnings("unchecked")
+	private TypeRange(String token) {
+		Builder b = new Builder(token);
+		this.type = b.type;
+		this.qValue = b.qValue;
+		this.extensions = (b.extensions == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(b.extensions));
+	}
+
+	private static class Builder {
+		private String type;
+		private Float qValue = 1f;
+		private Map<String,Set<String>> extensions;
+
+		private Builder(String token) {
+
+			token = token.trim();
+
+			int i = token.indexOf(";q=");
+
+			if (i == -1) {
+				type = token;
+				return;
+			}
+
+			type = token.substring(0, i);
+
+			String[] tokens = token.substring(i+1).split(";");
+
+			// Only the type of the range is specified
+			if (tokens.length > 0) {
+				boolean isInExtensions = false;
+				for (int j = 0; j < tokens.length; j++) {
+					String[] parm = tokens[j].split("=");
+					if (parm.length == 2) {
+						String k = parm[0], v = parm[1];
+						if (isInExtensions) {
+							if (extensions == null)
+								extensions = new TreeMap<String,Set<String>>();
+							if (! extensions.containsKey(k))
+								extensions.put(k, new TreeSet<String>());
+							extensions.get(k).add(v);
+						} else if (k.equals("q")) {
+							qValue = new Float(v);
+							isInExtensions = true;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Returns the type enclosed by this type range.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <ul>
+	 * 	<li><js>"compress"</js>
+	 * 	<li><js>"gzip"</js>
+	 * 	<li><js>"*"</js>
+	 * </ul>
+	 *
+	 * @return The type of this type range, lowercased, never <jk>null</jk>.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Returns the <js>'q'</js> (quality) value for this type, as described in Section 3.9 of RFC2616.
+	 * <p>
+	 * The quality value is a float between <code>0.0</code> (unacceptable) and <code>1.0</code> (most acceptable).
+	 * <p>
+	 * If 'q' value doesn't make sense for the context (e.g. this range was extracted from a <js>"content-*"</js> header, as opposed to <js>"accept-*"</js>
+	 * header, its value will always be <js>"1"</js>.
+	 *
+	 * @return The 'q' value for this type, never <jk>null</jk>.
+	 */
+	public Float getQValue() {
+		return qValue;
+	}
+
+	/**
+	 * Returns the optional set of custom extensions defined for this type.
+	 * <p>
+	 * Values are lowercase and never <jk>null</jk>.
+	 *
+	 * @return The optional list of extensions, never <jk>null</jk>.
+	 */
+	public Map<String,Set<String>> getExtensions() {
+		return extensions;
+	}
+
+	/**
+	 * Provides a string representation of this media range, suitable for use as an <code>Accept</code> header value.
+	 * <p>
+	 * The literal text generated will be all lowercase.
+	 *
+	 * @return A media range suitable for use as an Accept header value, never <code>null</code>.
+	 */
+	@Override /* Object */
+	public String toString() {
+		StringBuffer sb = new StringBuffer().append(type);
+
+		// '1' is equivalent to specifying no qValue. If there's no extensions, then we won't include a qValue.
+		if (qValue.floatValue() == 1.0) {
+			if (! extensions.isEmpty()) {
+				sb.append(";q=").append(qValue);
+				for (Entry<String,Set<String>> e : extensions.entrySet()) {
+					String k = e.getKey();
+					for (String v : e.getValue())
+						sb.append(';').append(k).append('=').append(v);
+				}
+			}
+		} else {
+			sb.append(";q=").append(qValue);
+			for (Entry<String,Set<String>> e : extensions.entrySet()) {
+				String k = e.getKey();
+				for (String v : e.getValue())
+					sb.append(';').append(k).append('=').append(v);
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified object is also a <code>MediaType</code>, and has the same qValue, type, parameters, and extensions.
+	 *
+	 * @return <jk>true</jk> if object is equivalent.
+	 */
+	@Override /* Object */
+	public boolean equals(Object o) {
+
+		if (o == null || !(o instanceof TypeRange))
+			return false;
+
+		if (this == o)
+			return true;
+
+		TypeRange o2 = (TypeRange) o;
+		return qValue.equals(o2.qValue)
+			&& type.equals(o2.type)
+			&& extensions.equals(o2.extensions);
+	}
+
+	/**
+	 * Returns a hash based on this instance's <code>media-type</code>.
+	 *
+	 * @return A hash based on this instance's <code>media-type</code>.
+	 */
+	@Override /* Object */
+	public int hashCode() {
+		return type.hashCode();
+	}
+
+	/**
+	 * Compares two MediaRanges for equality.
+	 * <p>
+	 * The values are first compared according to <code>qValue</code> values.
+	 * Should those values be equal, the <code>type</code> is then lexicographically compared (case-insensitive) in ascending order,
+	 * 	with the <js>"*"</js> type demoted last in that order.
+	 * <code>TypeRanges</code> with the same types but with extensions are promoted over those same types with no extensions.
+	 *
+	 * @param o The range to compare to.  Never <jk>null</jk>.
+	 */
+	@Override /* Comparable */
+	public int compareTo(TypeRange o) {
+
+		// Compare q-values.
+		int qCompare = Float.compare(o.qValue, qValue);
+		if (qCompare != 0)
+			return qCompare;
+
+		// Compare media-types.
+		// Note that '*' comes alphabetically before letters, so just do a reverse-alphabetical comparison.
+		int i = o.type.toString().compareTo(type.toString());
+		return i;
+	}
+
+	/**
+	 * Checks if the specified type matches this range.
+	 * <p>
+	 * The type will match this range if the range type string is the same or <js>"*"</js>.
+	 *
+	 * @param type The type to match against this range.
+	 * @return <jk>true</jk> if the specified type matches this range.
+	 */
+	@SuppressWarnings("hiding")
+	public boolean matches(String type) {
+		if (qValue == 0)
+			return false;
+		return this.type.equals(type) || this.type.equals("*");
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
index 5bc7009..b8c504c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
@@ -15,6 +15,7 @@ package org.apache.juneau.ini;
 import java.io.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Wraps a {@link ConfigFile} in a {@link Writable} to be rendered as plain text.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java
index effd363..5199af1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java
@@ -271,6 +271,39 @@ public final class ArrayUtils {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if the specified array contains the specified element
+	 * 	using the {@link String#equals(Object)} method.
+	 *
+	 * @param element The element to check for.
+	 * @param array The array to check.
+	 * @return <jk>true</jk> if the specified array contains the specified element,
+	 * 	<jk>false</jk> if the array or element is <jk>null</jk>.
+	 */
+	public static boolean contains(String element, String[] array) {
+		return indexOf(element, array) != -1;
+	}
+
+	/**
+	 * Returns the index position of the element in the specified array
+	 * 	using the {@link String#equals(Object)} method.
+	 *
+	 * @param element The element to check for.
+	 * @param array The array to check.
+	 * @return The index position of the element in the specified array, or
+	 * 	<code>-1</code> if the array doesn't contain the element, or the array or element is <jk>null</jk>.
+	 */
+	public static int indexOf(String element, String[] array) {
+		if (element == null)
+			return -1;
+		if (array == null)
+			return -1;
+		for (int i = 0; i < array.length; i++)
+			if (element.equals(array[i]))
+				return i;
+		return -1;
+	}
+
+	/**
 	 * Converts a primitive wrapper array (e.g. <code>Integer[]</code>) to a primitive array (e.g. <code><jk>int</jk>[]</code>).
 	 *
 	 * @param o The array to convert.  Must be a primitive wrapper array.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/internal/CollectionUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/CollectionUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/CollectionUtils.java
index c413427..6c12246 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/CollectionUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/CollectionUtils.java
@@ -52,4 +52,36 @@ public class CollectionUtils {
 			l.add(o);
 		return l;
 	}
+
+	/**
+	 * Adds the contents of one list to the other in reverse order.
+	 * <p>
+	 * i.e. add values from 2nd list from end-to-start order to the end of the 1st list.
+	 *
+	 * @param list The list to append to.
+	 * @param append Contains the values to append to the list.
+	 * @return The same list.
+	 */
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public static List<?> addReverse(List list, List append) {
+		for (ListIterator i = append.listIterator(append.size()); i.hasPrevious();)
+			list.add(i.previous());
+		return list;
+	}
+
+	/**
+	 * Adds the contents of the array to the list in reverse order.
+	 * <p>
+	 * i.e. add values from the array from end-to-start order to the end of the list.
+	 *
+	 * @param list The list to append to.
+	 * @param append Contains the values to append to the list.
+	 * @return The same list.
+	 */
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public static List<?> addReverse(List list, Object[] append) {
+		for (int i = append.length - 1; i >= 0; i--)
+			list.add(append[i]);
+		return list;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
index a5bc00e..bee95d9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -480,6 +480,8 @@ public final class StringUtils {
 			return null;
 		if (isEmpty(s))
 			return new String[0];
+		if (s.indexOf(c) == -1)
+			return new String[]{s};
 
 		List<String> l = new LinkedList<String>();
 		char[] sArray = s.toCharArray();
@@ -522,6 +524,83 @@ public final class StringUtils {
 	}
 
 	/**
+	 * Splits a list of key-value pairs into an ordered map.
+	 * <p>
+	 * Example:
+	 * <p class='bcode'>
+	 * 	String in = <js>"foo=1;bar=2"</js>;
+	 * 	Map m = StringUtils.<jsm>splitMap</jsm>(in, <js>';'</js>, <js>'='</js>, <jk>true</jk>);
+	 * </p>
+	 *
+	 * @param s The string to split.
+	 * @param delim The delimiter between the key-value pairs.
+	 * @param eq The delimiter between the key and value.
+	 * @param trim Trim strings after parsing.
+	 * @return The parsed map.  Never <jk>null</jk>.
+	 */
+	@SuppressWarnings("unchecked")
+	public static Map<String,String> splitMap(String s, char delim, char eq, boolean trim) {
+
+		char[] unEscapeChars = new char[]{'\\', delim, eq};
+
+		if (s == null)
+			return null;
+		if (isEmpty(s))
+			return Collections.EMPTY_MAP;
+
+		Map<String,String> m = new LinkedHashMap<String,String>();
+
+		int
+			S1 = 1,  // Found start of key, looking for equals.
+			S2 = 2;  // Found equals, looking for delimiter (or end).
+
+		int state = S1;
+
+		char[] sArray = s.toCharArray();
+		int x1 = 0, escapeCount = 0;
+		String key = null;
+		for (int i = 0; i < sArray.length + 1; i++) {
+			char c = i == sArray.length ? delim : sArray[i];
+			if (c == '\\')
+				escapeCount++;
+			if (escapeCount % 2 == 0) {
+				if (state == S1) {
+					if (c == eq) {
+						key = s.substring(x1, i);
+						if (trim)
+							key = trim(key);
+						key = unEscapeChars(key, unEscapeChars);
+						state = S2;
+						x1 = i+1;
+					} else if (c == delim) {
+						key = s.substring(x1, i);
+						if (trim)
+							key = trim(key);
+						key = unEscapeChars(key, unEscapeChars);
+						m.put(key, "");
+						state = S1;
+						x1 = i+1;
+					}
+				} else if (state == S2) {
+					if (c == delim) {
+						String val = s.substring(x1, i);
+						if (trim)
+							val = trim(val);
+						val = unEscapeChars(val, unEscapeChars);
+						m.put(key, val);
+						key = null;
+						x1 = i+1;
+						state = S1;
+					}
+				}
+			}
+			if (c != '\\') escapeCount = 0;
+		}
+
+		return m;
+	}
+
+	/**
 	 * Returns <jk>true</jk> if specified string is <jk>null</jk> or empty.
 	 *
 	 * @param s The string to check.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index 2608028..210460b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.jso;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index c4d7d40..88d89c5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.jso;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
index d362112..c07c8b7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index ed550cc..1d6a3ad 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.json;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
index 02ae190..f495bca 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
index 3e28eab..df974ea 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index 9a8616f..eb4a1ea 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.json;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 
 /**
  * Builder class for building instances of JSON Schema serializers.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 91945d4..71859f4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -19,6 +19,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 97323aa..0715dd1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.json.JsonSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index dd8b8a1..ef1a975 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 8895f33..bd9128c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -19,6 +19,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 3e68801..26df53b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.msgpack;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
index 24a40e7..57beda3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index 89e736b..e0108ea 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -17,6 +17,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index f909e14..2c29538 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.msgpack;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**



[3/3] incubator-juneau git commit: New Accept/AcceptEncoding/ContentType classes.

Posted by ja...@apache.org.
New Accept/AcceptEncoding/ContentType classes.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/c3609d05
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/c3609d05
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/c3609d05

Branch: refs/heads/master
Commit: c3609d0518c07d1e96b62dee42eda40050a9fe02
Parents: 2ebf5ca
Author: JamesBognar <ja...@apache.org>
Authored: Mon May 1 21:11:38 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Mon May 1 21:11:38 2017 -0400

----------------------------------------------------------------------
 .../java/org/apache/juneau/jena/RdfParser.java  |   1 +
 .../apache/juneau/jena/RdfParserBuilder.java    |   1 +
 .../apache/juneau/jena/RdfParserSession.java    |   1 +
 .../org/apache/juneau/jena/RdfSerializer.java   |   1 +
 .../juneau/jena/RdfSerializerBuilder.java       |   1 +
 .../juneau/jena/RdfSerializerSession.java       |   1 +
 .../java/org/apache/juneau/MediaRangeTest.java  |  65 ----
 .../test/java/org/apache/juneau/TestUtils.java  |  24 +-
 .../juneau/encoders/EncoderGroupTest.java       | 116 +++++++
 .../juneau/https/AcceptExtensionsTest.java      | 118 +++++++
 .../org/apache/juneau/https/AcceptTest.java     | 128 ++++++++
 .../org/apache/juneau/https/MediaRangeTest.java |  66 ++++
 .../apache/juneau/parser/ParserGroupTest.java   | 125 ++++++++
 .../juneau/serializer/SerializerGroupTest.java  | 166 ++++++++++
 .../juneau/utils/CollectionUtilsTest.java       |   4 +-
 .../apache/juneau/utils/StringUtilsTest.java    |  17 +
 .../java/org/apache/juneau/BeanContext.java     |   1 +
 .../java/org/apache/juneau/BeanSession.java     |   1 +
 .../org/apache/juneau/CoreObjectBuilder.java    |   1 +
 .../main/java/org/apache/juneau/MediaRange.java | 321 -------------------
 .../main/java/org/apache/juneau/MediaType.java  | 158 ---------
 .../main/java/org/apache/juneau/Streamable.java |   2 +
 .../main/java/org/apache/juneau/Writable.java   |   2 +
 .../org/apache/juneau/csv/CsvParserBuilder.java |   1 +
 .../org/apache/juneau/csv/CsvParserSession.java |   1 +
 .../apache/juneau/csv/CsvSerializerBuilder.java |   1 +
 .../apache/juneau/csv/CsvSerializerSession.java |   1 +
 .../apache/juneau/dto/swagger/Operation.java    |   2 +-
 .../org/apache/juneau/dto/swagger/Swagger.java  |   2 +-
 .../apache/juneau/encoders/EncoderGroup.java    |  82 ++---
 .../juneau/encoders/EncoderGroupBuilder.java    |  16 +-
 .../apache/juneau/encoders/EncoderMatch.java    |  10 +-
 .../apache/juneau/html/HtmlDocSerializer.java   |   1 +
 .../juneau/html/HtmlDocSerializerSession.java   |   1 +
 .../java/org/apache/juneau/html/HtmlParser.java |   1 +
 .../apache/juneau/html/HtmlParserBuilder.java   |   1 +
 .../apache/juneau/html/HtmlParserSession.java   |   1 +
 .../juneau/html/HtmlSchemaDocSerializer.java    |   1 +
 .../org/apache/juneau/html/HtmlSerializer.java  |   1 +
 .../juneau/html/HtmlSerializerBuilder.java      |   1 +
 .../juneau/html/HtmlSerializerSession.java      |   1 +
 .../java/org/apache/juneau/http/Accept.java     | 231 +++++++++++++
 .../org/apache/juneau/http/AcceptEncoding.java  | 147 +++++++++
 .../org/apache/juneau/http/ContentType.java     |  90 ++++++
 .../java/org/apache/juneau/http/MediaType.java  | 277 ++++++++++++++++
 .../org/apache/juneau/http/MediaTypeRange.java  | 270 ++++++++++++++++
 .../java/org/apache/juneau/http/TypeRange.java  | 276 ++++++++++++++++
 .../apache/juneau/ini/ConfigFileWritable.java   |   1 +
 .../org/apache/juneau/internal/ArrayUtils.java  |  33 ++
 .../apache/juneau/internal/CollectionUtils.java |  32 ++
 .../org/apache/juneau/internal/StringUtils.java |  79 +++++
 .../org/apache/juneau/jso/JsoParserBuilder.java |   1 +
 .../apache/juneau/jso/JsoSerializerBuilder.java |   1 +
 .../java/org/apache/juneau/json/JsonParser.java |   1 +
 .../apache/juneau/json/JsonParserBuilder.java   |   1 +
 .../apache/juneau/json/JsonParserSession.java   |   1 +
 .../juneau/json/JsonSchemaSerializer.java       |   1 +
 .../json/JsonSchemaSerializerBuilder.java       |   1 +
 .../org/apache/juneau/json/JsonSerializer.java  |   1 +
 .../juneau/json/JsonSerializerBuilder.java      |   1 +
 .../juneau/json/JsonSerializerSession.java      |   1 +
 .../apache/juneau/msgpack/MsgPackParser.java    |   1 +
 .../juneau/msgpack/MsgPackParserBuilder.java    |   1 +
 .../juneau/msgpack/MsgPackParserSession.java    |   1 +
 .../juneau/msgpack/MsgPackSerializer.java       |   1 +
 .../msgpack/MsgPackSerializerBuilder.java       |   1 +
 .../msgpack/MsgPackSerializerSession.java       |   1 +
 .../java/org/apache/juneau/parser/Parser.java   |   1 +
 .../org/apache/juneau/parser/ParserBuilder.java |   1 +
 .../org/apache/juneau/parser/ParserGroup.java   |  68 ++--
 .../juneau/parser/ParserGroupBuilder.java       |  12 +-
 .../org/apache/juneau/parser/ParserMatch.java   |   2 +-
 .../org/apache/juneau/parser/ParserSession.java |   1 +
 .../juneau/plaintext/PlainTextParser.java       |   2 +-
 .../plaintext/PlainTextParserBuilder.java       |   1 +
 .../juneau/plaintext/PlainTextSerializer.java   |   2 +-
 .../plaintext/PlainTextSerializerBuilder.java   |   1 +
 .../apache/juneau/serializer/Serializer.java    |   1 +
 .../juneau/serializer/SerializerBuilder.java    |   1 +
 .../juneau/serializer/SerializerGroup.java      |  68 ++--
 .../serializer/SerializerGroupBuilder.java      |  12 +-
 .../juneau/serializer/SerializerMatch.java      |   2 +-
 .../juneau/serializer/SerializerSession.java    |   1 +
 .../juneau/serializer/WriterSerializer.java     |   1 +
 .../juneau/soap/SoapXmlSerializerBuilder.java   |   1 +
 .../java/org/apache/juneau/uon/UonParser.java   |   1 +
 .../org/apache/juneau/uon/UonParserBuilder.java |   1 +
 .../org/apache/juneau/uon/UonParserSession.java |   1 +
 .../org/apache/juneau/uon/UonSerializer.java    |   1 +
 .../apache/juneau/uon/UonSerializerBuilder.java |   1 +
 .../apache/juneau/uon/UonSerializerSession.java |   1 +
 .../juneau/urlencoding/UrlEncodingParser.java   |   1 +
 .../urlencoding/UrlEncodingParserBuilder.java   |   1 +
 .../urlencoding/UrlEncodingParserSession.java   |   1 +
 .../urlencoding/UrlEncodingSerializer.java      |   1 +
 .../UrlEncodingSerializerBuilder.java           |   1 +
 .../UrlEncodingSerializerSession.java           |   1 +
 .../org/apache/juneau/utils/StringMessage.java  |   1 +
 .../org/apache/juneau/utils/StringObject.java   |   1 +
 .../java/org/apache/juneau/xml/XmlParser.java   |   1 +
 .../org/apache/juneau/xml/XmlParserBuilder.java |   1 +
 .../org/apache/juneau/xml/XmlParserSession.java |   1 +
 .../apache/juneau/xml/XmlSchemaSerializer.java  |   1 +
 .../juneau/xml/XmlSchemaSerializerBuilder.java  |   1 +
 .../org/apache/juneau/xml/XmlSerializer.java    |   1 +
 .../apache/juneau/xml/XmlSerializerBuilder.java |   1 +
 .../apache/juneau/xml/XmlSerializerSession.java |   1 +
 juneau-core/src/main/javadoc/overview.html      |  47 ++-
 .../juneau/rest/client/RestClientBuilder.java   |   1 +
 .../apache/juneau/rest/jaxrs/BaseProvider.java  |   3 +-
 .../juneau/rest/test/HeadersResource.java       |  74 +++++
 .../java/org/apache/juneau/rest/test/Root.java  |   1 +
 .../org/apache/juneau/rest/test/GzipTest.java   |   4 -
 .../apache/juneau/rest/test/HeadersTest.java    |  56 ++++
 .../apache/juneau/rest/test/ParsersTest.java    |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java |  17 +-
 .../org/apache/juneau/rest/ReaderResource.java  |   1 +
 .../java/org/apache/juneau/rest/RestConfig.java |   7 +-
 .../org/apache/juneau/rest/RestContext.java     |   1 +
 .../apache/juneau/rest/RestInfoProvider.java    |   2 +-
 .../org/apache/juneau/rest/RestRequest.java     |  54 ++--
 .../org/apache/juneau/rest/RestResponse.java    |   3 +-
 .../org/apache/juneau/rest/StreamResource.java  |   1 +
 .../java/org/apache/juneau/rest/package.html    |  52 ++-
 .../rest/remoteable/RemoteableServlet.java      |   2 +-
 .../juneau/rest/response/DefaultHandler.java    |   1 +
 .../juneau/rest/response/StreamableHandler.java |   1 +
 .../juneau/rest/response/WritableHandler.java   |   1 +
 128 files changed, 2673 insertions(+), 756 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
index 9bc336e..ffe2453 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -21,6 +21,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index 1a71a2b..03dbc48 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -18,6 +18,7 @@ import static org.apache.juneau.jena.RdfParserContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
index db1cbdc..f699443 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
index 9b254a9..ecbc618 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 6b8e5bb..da3b59a 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -18,6 +18,7 @@ import static org.apache.juneau.jena.RdfSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
index df13cea..199f144 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.msgpack.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java b/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
deleted file mode 100644
index 882ca6a..0000000
--- a/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
+++ /dev/null
@@ -1,65 +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.juneau;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.apache.juneau.json.*;
-import org.junit.*;
-import org.junit.runner.*;
-import org.junit.runners.*;
-
-/**
- * Verifies that the MediaRange and MediaType classes parse and sort Accept headers correctly.
- */
-@RunWith(Parameterized.class)
-public class MediaRangeTest {
-	@Parameterized.Parameters
-	public static Collection<Object[]> getParameters() {
-		return Arrays.asList(new Object[][] {
-			{ "0", "text/json", "['text/json']" },
-			{ "1", "text/json,text/*", "['text/json','text/*']" },
-			{ "2", "text/*,text/json", "['text/json','text/*']" },
-			{ "3", "text/*,text/*", "['text/*']" },
-			{ "4", "*/text,text/*", "['text/*','*/text']" },
-			{ "5", "text/*,*/text", "['text/*','*/text']" },
-			{ "6", "A;q=0.9,B;q=0.1", "['a;q=0.9','b;q=0.1']" },
-			{ "7", "B;q=0.9,A;q=0.1", "['b;q=0.9','a;q=0.1']" },
-			{ "8", "A,B;q=0.9,C;q=0.1,D;q=0", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-			{ "9", "D;q=0,C;q=0.1,B;q=0.9,A", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-			{ "10", "A;q=1,B;q=0.9,C;q=0.1,D;q=0", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-			{ "11", "D;q=0,C;q=0.1,B;q=0.9,A;q=1", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-			{ "12", "A;q=0,B;q=0.1,C;q=0.9,D;q=1", "['d','c;q=0.9','b;q=0.1','a;q=0.0']" },
-			{ "13", "*", "['*']" },
-			{ "14", "", "['*/*']" },
-			{ "15", null, "['*/*']" },
-			{ "16", "foo/bar/baz", "['foo/bar/baz']" },
-		});
-	}
-	
-	private String label, mediaRange, expected;
-	
-	public MediaRangeTest(String label, String mediaRange, String expected) {
-		this.label = label;
-		this.mediaRange = mediaRange;
-		this.expected = expected;
-	}
-	
-	@Test
-	public void test() {
-		MediaRange[] r = MediaRange.parse(mediaRange);
-		assertEquals(label + " failed", expected, JsonSerializer.DEFAULT_LAX.toString(r));
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java b/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
index eaeb4e7..4405efd 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
@@ -437,14 +437,13 @@ public class TestUtils {
 	 * If it's a byte[], convert it to a UTF-8 encoded String.
 	 */
 	public static String toString(Object o) {
+		if (o == null)
+			return null;
 		if (o instanceof String)
 			return (String)o;
-		try {
-			return new String((byte[])o, "UTF-8");
-		} catch (UnsupportedEncodingException e) {
-			e.printStackTrace();
-		}
-		return null;
+		if (o instanceof byte[])
+			return new String((byte[])o, IOUtils.UTF8);
+		return o.toString();
 	}
 
 	private static ThreadLocal<TimeZone> systemTimeZone = new ThreadLocal<TimeZone>();
@@ -497,9 +496,9 @@ public class TestUtils {
 	/**
 	 * Same as {@link Assert#assertEquals(String,String,String) except takes in a MessageFormat-style message.
 	 */
-	public static void assertEquals(String expected, String actual, String msg, Object...args) {
-		if (! StringUtils.isEquals(expected, actual))
-			throw new ComparisonFailure(MessageFormat.format(msg, args), expected, actual);			
+	public static void assertEquals(Object expected, Object actual, String msg, Object...args) {
+		if (! isEquals(expected, actual))
+			throw new ComparisonFailure(MessageFormat.format(msg, args), toString(expected), toString(actual));			
 	}
 	
 	/**
@@ -518,4 +517,11 @@ public class TestUtils {
 		throw new AssertionError(new StringMessage("Expected type {0} but was {1}", type, (o == null ? null : o.getClass())));
 	}
 	
+	private static boolean isEquals(Object o1, Object o2) {
+		if (o1 == null)
+			return o2 == null;
+		if (o2 == null)
+			return false;
+		return o1.equals(o2);
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java b/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
new file mode 100755
index 0000000..e6e2ec1
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
@@ -0,0 +1,116 @@
+// ***************************************************************************************************************************
+// * 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.juneau.encoders;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class EncoderGroupTest {
+
+	//====================================================================================================
+	// Test matching
+	//====================================================================================================
+	@Test
+	public void testEncoderGroupMatching() throws Exception {
+		
+		EncoderGroup g = new EncoderGroupBuilder().append(Encoder1.class, Encoder2.class, Encoder3.class).build();
+		assertType(Encoder1.class, g.getEncoder("gzip1"));
+		assertType(Encoder2.class, g.getEncoder("gzip2"));
+		assertType(Encoder2.class, g.getEncoder("gzip2a"));
+		assertType(Encoder3.class, g.getEncoder("gzip3"));
+		assertType(Encoder3.class, g.getEncoder("gzip3a"));
+		assertType(Encoder3.class, g.getEncoder("gzip3,gzip2,gzip1"));
+		assertType(Encoder1.class, g.getEncoder("gzip3;q=0.9,gzip2;q=0.1,gzip1"));
+		assertType(Encoder3.class, g.getEncoder("gzip2;q=0.9,gzip1;q=0.1,gzip3"));
+		assertType(Encoder2.class, g.getEncoder("gzip1;q=0.9,gzip3;q=0.1,gzip2"));
+	}
+	
+	public static class Encoder1 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"gzip1"};
+		}
+	}
+	
+	public static class Encoder2 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"gzip2","gzip2a"};
+		}
+	}
+
+	public static class Encoder3 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"gzip3","gzip3a"};
+		}
+	}
+	
+	//====================================================================================================
+	// Test inheritence
+	//====================================================================================================
+	@Test
+	public void testInheritence() throws Exception {
+		EncoderGroupBuilder gb = null;
+		EncoderGroup g = null;
+		
+		gb = new EncoderGroupBuilder().append(E1.class, E2.class);
+		g = gb.build();
+		assertObjectEquals("['E1','E2','E2a']", g.getSupportedEncodings());
+		
+		gb = new EncoderGroupBuilder(g).append(E3.class, E4.class);
+		g = gb.build();
+		assertObjectEquals("['E3','E4','E4a','E1','E2','E2a']", g.getSupportedEncodings());
+
+		gb = new EncoderGroupBuilder(g).append(E5.class);
+		g = gb.build();
+		assertObjectEquals("['E5','E3','E4','E4a','E1','E2','E2a']", g.getSupportedEncodings());
+	}
+	
+	public static class E1 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"E1"};
+		}
+	}
+	
+	public static class E2 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"E2","E2a"};
+		}
+	}
+
+	public static class E3 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"E3"};
+		}
+	}
+	
+	public static class E4 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"E4","E4a"};
+		}
+	}
+	
+	public static class E5 extends GzipEncoder {
+		@Override /* Encoder */
+		public String[] getCodings() {
+			return new String[]{"E5"};
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
new file mode 100644
index 0000000..be8b0f0
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
@@ -0,0 +1,118 @@
+// ***************************************************************************************************************************
+// * 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.juneau.https;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.http.*;
+import org.junit.*;
+
+/**
+ * Verifies that the Accept class handles parameters and extensions correctly.
+ */
+public class AcceptExtensionsTest {
+
+	//--------------------------------------------------------------------------------
+	// Verifies that media type parameters are distinguished from media range extensions.
+	//--------------------------------------------------------------------------------
+	@Test
+	public void testExtensions() throws Exception {
+		Accept accept;
+		MediaTypeRange mr;
+		
+		accept = Accept.forString("text/json");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json", mr);
+		assertTextEquals("text/json", mr.getMediaType());
+		assertObjectEquals("{}", mr.getMediaType().getParameters());
+		assertTextEquals("1.0", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+
+		accept = Accept.forString("foo,bar");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("foo", mr);
+		assertTextEquals("foo", mr.getMediaType());
+		assertObjectEquals("{}", mr.getMediaType().getParameters());
+		assertTextEquals("1.0", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+
+		accept = Accept.forString(" foo , bar ");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("foo", mr);
+		assertTextEquals("foo", mr.getMediaType());
+		assertObjectEquals("{}", mr.getMediaType().getParameters());
+		assertTextEquals("1.0", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+
+		accept = Accept.forString("text/json;a=1;q=0.9;b=2");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;a=1;q=0.9;b=2", mr);
+		assertTextEquals("text/json;a=1", mr.getMediaType());
+		assertObjectEquals("{a:['1']}", mr.getMediaType().getParameters());
+		assertTextEquals("0.9", mr.getQValue());
+		assertObjectEquals("{b:['2']}", mr.getExtensions());
+		
+		accept = Accept.forString("text/json;a=1;a=2;q=0.9;b=3;b=4");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;a=1;a=2;q=0.9;b=3;b=4", mr);
+		assertTextEquals("text/json;a=1;a=2", mr.getMediaType());
+		assertObjectEquals("{a:['1','2']}", mr.getMediaType().getParameters());
+		assertTextEquals("0.9", mr.getQValue());
+		assertObjectEquals("{b:['3','4']}", mr.getExtensions());
+
+		accept = Accept.forString("text/json;a=1");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;a=1", mr);
+		assertTextEquals("text/json;a=1", mr.getMediaType());
+		assertObjectEquals("{a:['1']}", mr.getMediaType().getParameters());
+		assertTextEquals("1.0", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+
+		accept = Accept.forString("text/json;a=1;");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;a=1", mr);
+		assertTextEquals("text/json;a=1", mr.getMediaType());
+		assertObjectEquals("{a:['1']}", mr.getMediaType().getParameters());
+		assertTextEquals("1.0", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+		
+		accept = Accept.forString("text/json;q=0.9");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;q=0.9", mr);
+		assertTextEquals("text/json", mr.getMediaType());
+		assertObjectEquals("{}", mr.getMediaType().getParameters());
+		assertTextEquals("0.9", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+
+		accept = Accept.forString("text/json;q=0.9;");
+		mr = accept.getMediaRanges().get(0);
+		assertTextEquals("text/json;q=0.9", mr);
+		assertTextEquals("text/json", mr.getMediaType());
+		assertObjectEquals("{}", mr.getMediaType().getParameters());
+		assertTextEquals("0.9", mr.getQValue());
+		assertObjectEquals("{}", mr.getExtensions());
+	}
+	
+	//--------------------------------------------------------------------------------
+	// Tests the Accept.hasSubtypePart() method.
+	//--------------------------------------------------------------------------------
+	@Test
+	public void testHasSubtypePart() {
+		Accept accept = Accept.forString("text/json+x,text/foo+y;q=0.0");
+		assertTrue(accept.hasSubtypePart("json"));
+		assertTrue(accept.hasSubtypePart("x"));
+		assertFalse(accept.hasSubtypePart("foo"));
+		assertFalse(accept.hasSubtypePart("y"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java
new file mode 100644
index 0000000..dd905a6
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java
@@ -0,0 +1,128 @@
+// ***************************************************************************************************************************
+// * 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.juneau.https;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+
+/**
+ * Verifies that the Accept class handles matching correctly.
+ */
+@RunWith(Parameterized.class)
+public class AcceptTest {
+	@Parameterized.Parameters
+	public static Collection<Object[]> getParameters() {
+		return Arrays.asList(new Object[][] {
+			
+			// label, accept-header, media-types, expected-index
+			
+			// Simple matches
+			{ "SimpleMatch-1", "text/json", "['text/json']", 0 },
+			{ "SimpleMatch-2", "text/json", "['text/json','text/foo']", 0 },
+			{ "SimpleMatch-3", "text/json", "['text/foo','text/json']", 1 },
+			
+			// Simple no-matches
+			{ "SimpleNoMatch-1", "text/jsonx", "['text/json']", -1 },
+			{ "SimpleNoMatch-2", "text/jso", "['text/json']", -1 },
+			{ "SimpleNoMatch-3", "text/json", "['application/json']", -1 },
+			{ "SimpleNoMatch-4", "text/json", "[]", -1 },
+			{ "SimpleNoMatch-5", null, "['text/json']", -1 },
+			
+			// Meta-character matches
+			{ "MetaMatch-1", "text/*", "['text/a','text/b+c','text/b+d+e']", 2 },
+			{ "MetaMatch-2", "text/b+*", "['text/a','text/b+c','text/b+d+e']", 2 },
+			{ "MetaMatch-3", "text/c+*", "['text/a','text/b+c','text/b+d+e']", 1 },
+			{ "MetaMatch-4", "text/b+d+e", "['text/a','text/b+c','text/b+d']", 2 },
+			{ "MetaMatch-5", "text/b+*", "['text/a','text/b+c','text/b+d']", 1 },
+			{ "MetaMatch-6", "text/d+e+*", "['text/a','text/b+c','text/b+d+e']", 2 },
+
+			{ "MetaMatch-7", "*/a", "['text/a','application/a']", 0 },
+			{ "MetaMatch-8", "*/*", "['text/a','text/b+c']", 1 },
+			{ "MetaMatch-9", "*/*", "['text/b+c','text/a']", 0 },
+
+			// Reverse meta-character matches
+			{ "RevMetaMatch-1", "text/a", "['text/*']", 0 },
+			{ "RevMetaMatch-3", "text/a", "['*/a']", 0 },
+			{ "RevMetaMatch-3", "text/a", "['*/*']", 0 },
+			
+			// Meta-character mixture matches
+			{ "MixedMetaMatch-1", "text/*", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 0 },
+			{ "MixedMetaMatch-2", "*/a", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 1 },
+			{ "MixedMetaMatch-3", "*/*", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 0 },
+			{ "MixedMetaMatch-4", "text/a+*", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 2 },
+			{ "MixedMetaMatch-5", "text/c+*", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 3 },
+			{ "MixedMetaMatch-6", "text/d+*", "['text/*','text/a','text/a+b','text/b+c','text/d+*']", 4 },
+
+			// Fuzzy matches
+			{ "Fuzzy-1", "text/1+2", "['text/1+2']", 0 },
+			// Order of subtype parts shouldn't matter.
+			{ "Fuzzy-2", "text/2+1", "['text/1+2']", 0 },
+			// Should match if Accept has 'extra' subtypes.
+			// For example, "Accept: text/json+activity" should match against the "text/json" serializer.
+			{ "Fuzzy-3", "text/1+2", "['text/1']", 0 },
+			// Shouldn't match because the accept media type must be at least a subset of the real media type
+			// For example, "Accept: text/json" should not match against the "text/json+lax" serializer.
+			{ "Fuzzy-4", "text/1", "['text/1+2']", -1 },
+			{ "Fuzzy-5", "text/1+2", "['text/1','text/1+3']", 0 },
+			// "text/1+2" should be a better match than just "text/1"
+			{ "Fuzzy-6", "text/1+2", "['text/1','text/1+2','text/1+2+3']", 1 },
+			// Same as last, but mix up the order a bit.
+			{ "Fuzzy-7", "text/1+2", "['text/1+2+3','text/1','text/1+2']", 2 },
+			// Same as last, but mix up the order of the subtypes as well.
+			{ "Fuzzy-8", "text/1+2", "['text/3+2+1','text/1','text/2+1']", 2 },
+			{ "Fuzzy-9", "text/1+2+3+4", "['text/1+2','text/1+2+3']", 1 },
+			{ "Fuzzy-10", "text/1+2+3+4", "['text/1+2+3','text/1+2']", 0 },
+			{ "Fuzzy-11", "text/4+2+3+1", "['text/1+2+3','text/1+2']", 0 },
+			{ "Fuzzy-12", "text/4+2+3+1", "['text/1+2','text/1+2+3']", 1 },
+			
+			// Q metrics
+			{ "Q-1", "text/A;q=0.9,text/B;q=0.1", "['text/A','text/B']", 0 },
+			{ "Q-2", "text/A;q=0.9,text/B;q=0.1", "['text/B','text/A']", 1 },
+			{ "Q-3", "text/A+1;q=0.9,text/B;q=0.1", "['text/A','text/B']", 0 },
+			{ "Q-4", "text/A;q=0.9,text/B+1;q=0.1", "['text/A','text/B+1']", 0 },
+			{ "Q-5", "text/A;q=0.9,text/A+1;q=0.1", "['text/A+1','text/A']", 1 },
+
+			// Test q=0
+			{ "Q0-1", "text/A;q=0,text/B;q=0.1", "['text/A','text/B']", 1 },
+			{ "Q0-2", "text/A;q=0,text/B;q=0.1", "['text/A','text/A+1']", -1 },
+			
+			// Test media types with parameters
+			{ "Parms-1", "text/A", "['text/A;foo=bar','text/B']", 0 },
+			{ "Parms-2", "text/A;foo=bar", "['text/A','text/B']", 0 },
+		});
+	}
+	
+	private String label, accept, mediaTypes;
+	private int expected;
+	
+	public AcceptTest(String label, String accept, String mediaTypes, int expected) {
+		this.label = label;
+		this.accept = accept;
+		this.mediaTypes = mediaTypes;
+		this.expected = expected;
+	}
+	
+	@Test
+	public void test() throws Exception {
+		Accept accept = Accept.forString(this.accept);
+		MediaType[] mt = JsonParser.DEFAULT.parse(mediaTypes, MediaType[].class);
+		int r = accept.findMatch(mt);
+		TestUtils.assertEquals(expected, r, "{0} failed", label);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java b/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
new file mode 100644
index 0000000..afeb782
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
@@ -0,0 +1,66 @@
+// ***************************************************************************************************************************
+// * 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.juneau.https;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.http.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+
+/**
+ * Verifies that the MediaRange and MediaType classes parse and sort Accept headers correctly.
+ */
+@RunWith(Parameterized.class)
+public class MediaRangeTest {
+	@Parameterized.Parameters
+	public static Collection<Object[]> getParameters() {
+		return Arrays.asList(new Object[][] {
+			{ "0", "text/json", "['text/json']" },
+			{ "1", "text/json,text/*", "['text/json','text/*']" },
+			{ "2", "text/*,text/json", "['text/json','text/*']" },
+			{ "3", "text/*,text/*", "['text/*']" },
+			{ "4", "*/text,text/*", "['text/*','*/text']" },
+			{ "5", "text/*,*/text", "['text/*','*/text']" },
+			{ "6", "a;q=0.9,b;q=0.1", "['a;q=0.9','b;q=0.1']" },
+			{ "7", "b;q=0.9,a;q=0.1", "['b;q=0.9','a;q=0.1']" },
+			{ "8", "a,b;q=0.9,c;q=0.1,d;q=0", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+			{ "9", "d;q=0,c;q=0.1,b;q=0.9,a", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+			{ "10", "a;q=1,b;q=0.9,c;q=0.1,d;q=0", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+			{ "11", "d;q=0,c;q=0.1,b;q=0.9,a;q=1", "['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+			{ "12", "a;q=0,b;q=0.1,c;q=0.9,d;q=1", "['d','c;q=0.9','b;q=0.1','a;q=0.0']" },
+			{ "13", "*", "['*']" },
+			{ "14", "", "['*/*']" },
+			{ "15", null, "['*/*']" },
+			{ "16", "foo/bar/baz", "['foo/bar/baz']" },
+		});
+	}
+	
+	private String label, mediaRange, expected;
+	
+	public MediaRangeTest(String label, String mediaRange, String expected) {
+		this.label = label;
+		this.mediaRange = mediaRange;
+		this.expected = expected;
+	}
+	
+	@Test
+	public void test() {
+		MediaTypeRange[] r = MediaTypeRange.parse(mediaRange);
+		assertEquals(label + " failed", expected, JsonSerializer.DEFAULT_LAX.toString(r));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java b/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
new file mode 100755
index 0000000..79d3b11
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
@@ -0,0 +1,125 @@
+// ***************************************************************************************************************************
+// * 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.juneau.parser;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class ParserGroupTest {
+
+	//====================================================================================================
+	// Test parser group matching
+	//====================================================================================================
+	@Test
+	public void testParserGroupMatching() throws Exception {
+		
+		ParserGroup g = new ParserGroupBuilder().append(Parser1.class, Parser2.class, Parser3.class).build();
+		assertType(Parser1.class, g.getParser("text/foo"));
+		assertType(Parser1.class, g.getParser("text/foo_a"));
+		assertType(Parser1.class, g.getParser("text/foo_a+xxx"));
+		assertType(Parser1.class, g.getParser("text/xxx+foo_a"));
+		assertType(Parser2.class, g.getParser("text/foo+bar"));
+		assertType(Parser2.class, g.getParser("text/foo+bar_a"));
+		assertType(Parser2.class, g.getParser("text/bar+foo"));
+		assertType(Parser2.class, g.getParser("text/bar+foo+xxx"));
+		assertType(Parser3.class, g.getParser("text/baz"));
+		assertType(Parser3.class, g.getParser("text/baz_a"));
+		assertType(Parser3.class, g.getParser("text/baz+yyy"));
+		assertType(Parser3.class, g.getParser("text/baz_a+yyy"));
+		assertType(Parser3.class, g.getParser("text/yyy+baz"));
+		assertType(Parser3.class, g.getParser("text/yyy+baz_a"));
+	}
+	
+	
+	@Consumes("text/foo,text/foo_a")
+	public static class Parser1 extends JsonParser {
+		public Parser1(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Consumes("text/foo+bar,text/foo+bar_a")
+	public static class Parser2 extends JsonParser {
+		public Parser2(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	@Consumes("text/baz,text/baz_a")
+	public static class Parser3 extends JsonParser {
+		public Parser3(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	//====================================================================================================
+	// Test inheritence
+	//====================================================================================================
+	@Test
+	public void testInheritence() throws Exception {
+		ParserGroupBuilder gb = null;
+		ParserGroup g = null;
+		
+		gb = new ParserGroupBuilder().append(P1.class, P2.class);
+		g = gb.build();
+		assertObjectEquals("['text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+		
+		gb = new ParserGroupBuilder(g).append(P3.class, P4.class);
+		g = gb.build();
+		assertObjectEquals("['text/3','text/4','text/4a','text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+
+		gb = new ParserGroupBuilder(g).append(P5.class);
+		g = gb.build();
+		assertObjectEquals("['text/5','text/3','text/4','text/4a','text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+	}
+	
+	@Consumes("text/1")
+	public static class P1 extends JsonParser {
+		public P1(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Consumes("text/2,text/2a")
+	public static class P2 extends JsonParser {
+		public P2(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	@Consumes("text/3")
+	public static class P3 extends JsonParser {
+		public P3(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Consumes("text/4,text/4a")
+	public static class P4 extends JsonParser {
+		public P4(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Consumes("text/5")
+	public static class P5 extends JsonParser {
+		public P5(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java b/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
new file mode 100755
index 0000000..2bcf413
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
@@ -0,0 +1,166 @@
+// ***************************************************************************************************************************
+// * 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.juneau.serializer;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class SerializerGroupTest {
+
+	//====================================================================================================
+	// Trim nulls from beans
+	//====================================================================================================
+	@Test
+	public void testSerializerGroupMatching() throws Exception {
+		
+		SerializerGroup sg = new SerializerGroupBuilder().append(SA1.class, SA2.class, SA3.class).build();
+		assertType(SA1.class, sg.getSerializer("text/foo"));
+		assertType(SA1.class, sg.getSerializer("text/foo_a"));
+		assertType(SA1.class, sg.getSerializer("text/xxx+foo_a"));
+		assertType(SA1.class, sg.getSerializer("text/foo_a+xxx"));
+		assertType(SA2.class, sg.getSerializer("text/foo+bar"));
+		assertType(SA2.class, sg.getSerializer("text/foo+bar_a"));
+		assertType(SA2.class, sg.getSerializer("text/bar+foo"));
+		assertType(SA2.class, sg.getSerializer("text/bar_a+foo"));
+		assertType(SA2.class, sg.getSerializer("text/bar+foo+xxx"));
+		assertType(SA2.class, sg.getSerializer("text/bar_a+foo+xxx"));
+		assertType(SA3.class, sg.getSerializer("text/baz"));
+		assertType(SA3.class, sg.getSerializer("text/baz_a"));
+		assertType(SA3.class, sg.getSerializer("text/baz+yyy"));
+		assertType(SA3.class, sg.getSerializer("text/baz_a+yyy"));
+		assertType(SA3.class, sg.getSerializer("text/yyy+baz"));
+		assertType(SA3.class, sg.getSerializer("text/yyy+baz_a"));
+		
+		assertType(SA1.class, sg.getSerializer("text/foo;q=0.9,text/foo+bar;q=0.8"));
+		assertType(SA2.class, sg.getSerializer("text/foo;q=0.8,text/foo+bar;q=0.9"));
+	}
+	
+	
+	@Produces("text/foo,text/foo_a")
+	public static class SA1 extends JsonSerializer {
+		public SA1(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("text/foo+bar,text/foo+bar_a")
+	public static class SA2 extends JsonSerializer {
+		public SA2(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	@Produces("text/baz,text/baz_a")
+	public static class SA3 extends JsonSerializer {
+		public SA3(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	//====================================================================================================
+	// Test inheritence
+	//====================================================================================================
+	@Test
+	public void testInheritence() throws Exception {
+		SerializerGroupBuilder gb = null;
+		SerializerGroup g = null;
+		
+		gb = new SerializerGroupBuilder().append(SB1.class, SB2.class);
+		g = gb.build();
+		assertObjectEquals("['text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+		
+		gb = new SerializerGroupBuilder(g).append(SB3.class, SB4.class);
+		g = gb.build();
+		assertObjectEquals("['text/3','text/4','text/4a','text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+
+		gb = new SerializerGroupBuilder(g).append(SB5.class);
+		g = gb.build();
+		assertObjectEquals("['text/5','text/3','text/4','text/4a','text/1','text/2','text/2a']", g.getSupportedMediaTypes());
+	}
+	
+	@Produces("text/1")
+	public static class SB1 extends JsonSerializer {
+		public SB1(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("text/2,text/2a")
+	public static class SB2 extends JsonSerializer {
+		public SB2(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+
+	@Produces("text/3")
+	public static class SB3 extends JsonSerializer {
+		public SB3(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("text/4,text/4a")
+	public static class SB4 extends JsonSerializer {
+		public SB4(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("text/5")
+	public static class SB5 extends JsonSerializer {
+		public SB5(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	//====================================================================================================
+	// Test media type with meta-characters
+	//====================================================================================================
+	@Test
+	public void testMediaTypesWithMetaCharacters() throws Exception {
+		SerializerGroupBuilder gb = null;
+		SerializerGroup g = null;
+		
+		gb = new SerializerGroupBuilder().append(SC1.class, SC2.class, SC3.class);
+		g = gb.build();
+		assertType(SC1.class, g.getSerializer("text/foo"));
+		assertType(SC2.class, g.getSerializer("foo/json"));
+		assertType(SC3.class, g.getSerializer("foo/foo"));
+	}
+	
+	@Produces("text/*")
+	public static class SC1 extends JsonSerializer {
+		public SC1(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("*/json")
+	public static class SC2 extends JsonSerializer {
+		public SC2(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+	
+	@Produces("*/*")
+	public static class SC3 extends JsonSerializer {
+		public SC3(PropertyStore propertyStore) {
+			super(propertyStore);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java b/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
index bc4b94e..7bd042e 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
@@ -16,6 +16,8 @@ import static org.apache.juneau.TestUtils.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.junit.Assert.*;
 
+import java.util.*;
+
 import org.apache.juneau.*;
 import org.junit.*;
 
@@ -27,7 +29,7 @@ public class CollectionUtilsTest {
 	//====================================================================================================
 	@Test
 	public void testReverse() throws Exception {
-		assertNull(reverse(null));
+		assertNull(reverse((Map<?,?>)null));
 
 		assertObjectEquals("{b:2,a:1}", reverse(new ObjectMap("{a:1,b:2}")));
 		assertObjectEquals("{}", reverse(new ObjectMap("{}")));

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java b/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
index 95c340b..f74d75e 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
@@ -700,4 +700,21 @@ public class StringUtilsTest {
 		in = null;
 		assertEquals("", getField(0, in, ','));
 	}
+
+	//====================================================================================================
+	// parseMap(String,char,char,boolean)
+	//====================================================================================================
+	@Test
+	public void testSplitMap() {
+		assertObjectEquals("{a:'1'}", splitMap("a=1", ',', '=', true));
+		assertObjectEquals("{a:'1',b:'2'}", splitMap("a=1,b=2", ',', '=', true));
+		assertObjectEquals("{a:'1',b:'2'}", splitMap(" a = 1 , b = 2 ", ',', '=', true));
+		assertObjectEquals("{' a ':' 1 ',' b ':' 2 '}", splitMap(" a = 1 , b = 2 ", ',', '=', false));
+		assertObjectEquals("{a:''}", splitMap("a", ',', '=', true));
+		assertObjectEquals("{a:'',b:''}", splitMap("a,b", ',', '=', true));
+		assertObjectEquals("{a:'1',b:''}", splitMap("a=1,b", ',', '=', true));
+		assertObjectEquals("{a:'',b:'1'}", splitMap("a,b=1", ',', '=', true));
+		assertObjectEquals("{'a=':'1'}", splitMap("a\\==1", ',', '=', true));
+		assertObjectEquals("{'a\\\\':'1'}", splitMap("a\\\\=1", ',', '=', true));
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index 0977ba0..c5df1d1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -23,6 +23,7 @@ import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
index ad1cee6..525f0e3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
index 2f01917..f566a92 100644
--- a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/MediaRange.java b/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
deleted file mode 100644
index 5a21882..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
+++ /dev/null
@@ -1,321 +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.juneau;
-
-import java.util.*;
-import java.util.Map.*;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Describes a single type used in content negotiation between an HTTP client and server, as described in
- * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
- */
-@BeanIgnore
-public final class MediaRange implements Comparable<MediaRange>  {
-
-	private static final MediaRange[] DEFAULT = new MediaRange[]{new MediaRange("*/*")};
-
-	private final MediaType mediaType;
-	private final Float qValue;
-	private final Map<String,Set<String>> parameters, extensions;
-
-	/**
-	 * Parses a media range fragement of an <code>Accept</code> header value into a single media range object..
-	 * <p>
-	 * The syntax expected to be found in the referenced <code>value</code> complies with the syntax described in RFC2616, Section 14.1, as described below:
-	 * <p class='bcode'>
-	 * 	media-range    = ( "*\/*"
-	 * 	                  | ( type "/" "*" )
-	 * 	                  | ( type "/" subtype )
-	 * 	                  ) *( ";" parameter )
-	 * 	accept-params  = ";" "q" "=" qvalue *( accept-extension )
-	 * 	accept-extension = ";" token [ "=" ( token | quoted-string ) ]
-	 * </p>
-	 * @param mediaRangeFragment The media range fragement string.
-	 */
-	private MediaRange(String mediaRangeFragment) {
-
-		String r = mediaRangeFragment;
-		Float _qValue = 1f;
-		MediaType _mediaType = null;
-		Map<String,Set<String>> _parameters = null;
-		Map<String,Set<String>> _extensions = null;
-
-		r = r.trim();
-
-		int i = r.indexOf(';');
-
-		if (i == -1) {
-			_mediaType = MediaType.forString(r);
-
-		} else {
-
-			_mediaType = MediaType.forString(r.substring(0, i));
-
-			String[] tokens = r.substring(i+1).split(";");
-
-			// Only the type of the range is specified
-			if (tokens.length > 0) {
-
-				boolean isInExtensions = false;
-				for (int j = 0; j < tokens.length; j++) {
-					String[] parm = tokens[j].split("=");
-					if (parm.length == 2) {
-						String k = parm[0], v = parm[1];
-						if (isInExtensions) {
-							if (_extensions == null)
-								_extensions = new TreeMap<String,Set<String>>();
-							if (! _extensions.containsKey(parm[0]))
-								_extensions.put(parm[0], new TreeSet<String>());
-							_extensions.get(parm[0]).add(parm[1]);
-						} else if (k.equals("q")) {
-							_qValue = new Float(v);
-							isInExtensions = true;
-						} else /*(! isInExtensions)*/ {
-							if (_parameters == null)
-								_parameters = new TreeMap<String,Set<String>>();
-							if (! _parameters.containsKey(parm[0]))
-								_parameters.put(parm[0], new TreeSet<String>());
-							_parameters.get(parm[0]).add(parm[1]);
-						}
-					}
-				}
-			}
-		}
-		if (_parameters == null)
-			_parameters = Collections.emptyMap();
-		if (_extensions == null)
-			_extensions = Collections.emptyMap();
-
-		this.mediaType = _mediaType;
-		this.parameters = _parameters;
-		this.qValue = _qValue;
-		this.extensions = _extensions;
-	}
-
-	/**
-	 * Returns the media type enclosed by this media range.
-	 *
-	 * <h5 class='section'>Examples:</h5>
-	 * <ul>
-	 * 	<li><js>"text/html"</js>
-	 * 	<li><js>"text/*"</js>
-	 * 	<li><js>"*\/*"</js>
-	 * </ul>
-	 *
-	 * @return The media type of this media range, lowercased, never <jk>null</jk>.
-	 */
-	public MediaType getMediaType() {
-		return mediaType;
-	}
-
-	/**
-	 * Returns the <js>'q'</js> (quality) value for this type, as described in Section 3.9 of RFC2616.
-	 * <p>
-	 * The quality value is a float between <code>0.0</code> (unacceptable) and <code>1.0</code> (most acceptable).
-	 * <p>
-	 * If 'q' value doesn't make sense for the context (e.g. this range was extracted from a <js>"content-*"</js> header, as opposed to <js>"accept-*"</js>
-	 * header, its value will always be <js>"1"</js>.
-	 *
-	 * @return The 'q' value for this type, never <jk>null</jk>.
-	 */
-	public Float getQValue() {
-		return qValue;
-	}
-
-	/**
-	 * Returns the optional set of parameters associated to the type as returned by {@link #getMediaType()}.
-	 * <p>
-	 * The parameters are those values as described in standardized MIME syntax.
-	 * An example of such a parameter in string form might be <js>"level=1"</js>.
-	 * <p>
-	 * Values are lowercase and never <jk>null</jk>.
-	 *
-	 * @return The optional list of parameters, never <jk>null</jk>.
-	 */
-	public Map<String,Set<String>> getParameters() {
-		return parameters;
-	}
-
-	/**
-	 * Returns the optional set of custom extensions defined for this type.
-	 * <p>
-	 * Values are lowercase and never <jk>null</jk>.
-	 *
-	 * @return The optional list of extensions, never <jk>null</jk>.
-	 */
-	public Map<String,Set<String>> getExtensions() {
-		return extensions;
-	}
-
-	/**
-	 * Provides a string representation of this media range, suitable for use as an <code>Accept</code> header value.
-	 * <p>
-	 * The literal text generated will be all lowercase.
-	 *
-	 * @return A media range suitable for use as an Accept header value, never <code>null</code>.
-	 */
-	@Override /* Object */
-	public String toString() {
-		StringBuffer sb = new StringBuffer().append(mediaType);
-
-		for (Entry<String,Set<String>> e : parameters.entrySet()) {
-			String k = e.getKey();
-			for (String v : e.getValue())
-				sb.append(';').append(k).append('=').append(v);
-		}
-
-		// '1' is equivalent to specifying no qValue. If there's no extensions, then we won't include a qValue.
-		if (qValue.floatValue() == 1.0) {
-			if (! extensions.isEmpty()) {
-				sb.append(";q=").append(qValue);
-				for (Entry<String,Set<String>> e : extensions.entrySet()) {
-					String k = e.getKey();
-					for (String v : e.getValue())
-						sb.append(';').append(k).append('=').append(v);
-				}
-			}
-		} else {
-			sb.append(";q=").append(qValue);
-			for (Entry<String,Set<String>> e : extensions.entrySet()) {
-				String k = e.getKey();
-				for (String v : e.getValue())
-					sb.append(';').append(k).append('=').append(v);
-			}
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Returns <jk>true</jk> if the specified object is also a <code>MediaType</code>, and has the same qValue, type, parameters, and extensions.
-	 *
-	 * @return <jk>true</jk> if object is equivalent.
-	 */
-	@Override /* Object */
-	public boolean equals(Object o) {
-
-		if (o == null || !(o instanceof MediaRange))
-			return false;
-
-		if (this == o)
-			return true;
-
-		MediaRange o2 = (MediaRange) o;
-		return qValue.equals(o2.qValue)
-			&& mediaType.equals(o2.mediaType)
-			&& parameters.equals(o2.parameters)
-			&& extensions.equals(o2.extensions);
-	}
-
-	/**
-	 * Returns a hash based on this instance's <code>media-type</code>.
-	 *
-	 * @return A hash based on this instance's <code>media-type</code>.
-	 */
-	@Override /* Object */
-	public int hashCode() {
-		return mediaType.hashCode();
-	}
-
-	/**
-	 * Parses an <code>Accept</code> header value into an array of media ranges.
-	 * <p>
-	 * The returned media ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
-	 * <p>
-	 * The syntax expected to be found in the referenced <code>value</code> complies with the syntax described in RFC2616, Section 14.1, as described below:
-	 * <p class='bcode'>
-	 * 	Accept         = "Accept" ":"
-	 * 	                  #( media-range [ accept-params ] )
-	 *
-	 * 	media-range    = ( "*\/*"
-	 * 	                  | ( type "/" "*" )
-	 * 	                  | ( type "/" subtype )
-	 * 	                  ) *( ";" parameter )
-	 * 	accept-params  = ";" "q" "=" qvalue *( accept-extension )
-	 * 	accept-extension = ";" token [ "=" ( token | quoted-string ) ]
-	 * </p>
-	 * This method can also be used on other headers such as <code>Accept-Charset</code> and <code>Accept-Encoding</code>...
-	 * <p class='bcode'>
-	 * 	Accept-Charset = "Accept-Charset" ":"
-	 * 	1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
-	 * </p>
-	 *
-	 * @param value The value to parse.  If <jk>null</jk> or empty, returns a single <code>MediaRange</code> is returned that represents all types.
-	 * @return The media ranges described by the string.
-	 * The ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
-	 */
-	public static MediaRange[] parse(String value) {
-
-		if (value == null || value.length() == 0)
-			return DEFAULT;
-
-		value = value.toLowerCase(Locale.ENGLISH);
-
-		if (value.indexOf(',') == -1)
-			return new MediaRange[]{new MediaRange(value)};
-
-		Set<MediaRange> ranges = new TreeSet<MediaRange>();
-
-		for (String r : StringUtils.split(value, ',')) {
-			r = r.trim();
-
-			if (r.isEmpty())
-				continue;
-
-			ranges.add(new MediaRange(r));
-		}
-
-		return ranges.toArray(new MediaRange[ranges.size()]);
-	}
-
-	/**
-	 * Compares two MediaRanges for equality.
-	 * <p>
-	 * The values are first compared according to <code>qValue</code> values.
-	 * Should those values be equal, the <code>type</code> is then lexicographically compared (case-insensitive) in ascending order,
-	 * 	with the <js>"*"</js> type demoted last in that order.
-	 * <code>MediaRanges</code> with the same type but different sub-types are compared - a more specific subtype is
-	 * 	promoted over the 'wildcard' subtype.
-	 * <code>MediaRanges</code> with the same types but with extensions are promoted over those same types with no extensions.
-	 *
-	 * @param o The range to compare to.  Never <jk>null</jk>.
-	 */
-	@Override /* Comparable */
-	public int compareTo(MediaRange o) {
-
-		// Compare q-values.
-		int qCompare = Float.compare(o.qValue, qValue);
-		if (qCompare != 0)
-			return qCompare;
-
-		// Compare media-types.
-		// Note that '*' comes alphabetically before letters, so just do a reverse-alphabetical comparison.
-		int i = o.mediaType.toString().compareTo(mediaType.toString());
-		return i;
-	}
-
-	/**
-	 * Matches the specified media type against this range and returns a q-value
-	 * between 0 and 1 indicating the quality of the match.
-	 *
-	 * @param o The media type to match against.
-	 * @return A float between 0 and 1.  1 is a perfect match.  0 is no match at all.
-	 */
-	public float matches(MediaType o) {
-		if (this.mediaType == o || mediaType.matches(o))
-			return qValue;
-		return 0;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/MediaType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/MediaType.java b/juneau-core/src/main/java/org/apache/juneau/MediaType.java
deleted file mode 100644
index 966f445..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/MediaType.java
+++ /dev/null
@@ -1,158 +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.juneau;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.apache.juneau.annotation.*;
-
-
-/**
- * Describes a single media type used in content negotiation between an HTTP client and server, as described in
- * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
- */
-@BeanIgnore
-public final class MediaType {
-
-	private static final ConcurrentHashMap<String,MediaType> cache = new ConcurrentHashMap<String,MediaType>();
-
-	/** Reusable predefined media type */
-	@SuppressWarnings("javadoc")
-	public static final MediaType
-		CSV = forString("text/csv"),
-		HTML = forString("text/html"),
-		JSON = forString("application/json"),
-		MSGPACK = forString("octal/msgpack"),
-		PLAIN = forString("text/plain"),
-		UON = forString("text/uon"),
-		URLENCODING = forString("application/x-www-form-urlencoded"),
-		XML = forString("text/xml"),
-		XMLSOAP = forString("text/xml+soap"),
-
-		RDF = forString("text/xml+rdf"),
-		RDFABBREV = forString("text/xml+rdf+abbrev"),
-		NTRIPLE = forString("text/n-triple"),
-		TURTLE = forString("text/turtle"),
-		N3 = forString("text/n3")
-	;
-
-	private final String mediaType;
-	private final String type;								// The media type (e.g. "text" for Accept, "utf-8" for Accept-Charset)
-	private final String subType;                   // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset)
-
-	/**
-	 * Returns the media type for the specified string.
-	 * The same media type strings always return the same objects so that these objects
-	 * can be compared for equality using '=='.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>Spaces are replaced with <js>'+'</js> characters.
-	 * 		This gets around the issue where passing media type strings with <js>'+'</js> as HTTP GET parameters
-	 * 		get replaced with spaces by your browser.  Since spaces aren't supported by the spec, this
-	 * 		is doesn't break anything.
-	 * 	<li>Anything including and following the <js>';'</js> character is ignored (e.g. <js>";charset=X"</js>).
-	 * </ul>
-	 *
-	 * @param s The media type string.  Will be lowercased.
-	 * 	<br>Returns <jk>null</jk> if input is null.
-	 * @return A cached media type object.
-	 */
-	public static MediaType forString(String s) {
-		if (s == null)
-			return null;
-		MediaType mt = cache.get(s);
-		if (mt == null) {
-			mt = new MediaType(s);
-			cache.putIfAbsent(s, mt);
-		}
-		return cache.get(s);
-	}
-
-	private MediaType(String mt) {
-		int i = mt.indexOf(';');
-		if (i != -1)
-			mt = mt.substring(0, i);
-
-		mt = mt.toLowerCase(Locale.ENGLISH);
-		this.mediaType = mt;
-		String _type = null, _subType = null;
-		if (mt != null) {
-			mt = mt.replace(' ', '+');
-			i = mt.indexOf('/');
-			_type = (i == -1 ? mt : mt.substring(0, i));
-			_subType = (i == -1 ? "*" : mt.substring(i+1));
-		}
-		this.type = _type;
-		this.subType = _subType;
-	}
-
-	/**
-	 * Returns the <js>'type'</js> fragment of the <js>'type/subType'</js> string.
-	 *
-	 * @return The media type.
-	 */
-	public String getType() {
-		return type;
-	}
-
-	/**
-	 * Returns the <js>'subType'</js> fragment of the <js>'type/subType'</js> string.
-	 *
-	 * @return The media subtype.
-	 */
-	public String getSubType() {
-		return subType;
-	}
-
-	/**
-	 * Returns <jk>true</jk> if this media type is a match for the specified media type.
-	 * <p>
-	 * Matches if any of the following is true:
-	 * <ul>
-	 * 	<li>Both type and subtype are the same.
-	 * 	<li>One or both types are <js>'*'</js> and the subtypes are the same.
-	 * 	<li>One or both subtypes are <js>'*'</js> and the types are the same.
-	 * 	<li>Either is <js>'*\/*'</js>.
-	 * </ul>
-	 *
-	 * @param o The media type to compare with.
-	 * @return <jk>true</jk> if the media types match.
-	 */
-	public final boolean matches(MediaType o) {
-		if (this == o)
-			return true;
-
-		if (type.equals(o.type) || (type.equals("*")) || (o.type.equals("*")))
-			if (subType.equals(o.subType) || subType.equals("*") || o.subType.equals("*"))
-				return true;
-
-		return false;
-	}
-
-	@Override /* Object */
-	public String toString() {
-		return mediaType;
-	}
-
-	@Override /* Object */
-	public int hashCode() {
-		return mediaType.hashCode();
-	}
-
-	@Override /* Object */
-	public boolean equals(Object o) {
-		return this == o;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/Streamable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Streamable.java b/juneau-core/src/main/java/org/apache/juneau/Streamable.java
index 6cb8237..84fb539 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Streamable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Streamable.java
@@ -14,6 +14,8 @@ package org.apache.juneau;
 
 import java.io.*;
 
+import org.apache.juneau.http.*;
+
 /**
  * Interface that identifies that an object can be serialized directly to an output stream.
  * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/Writable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Writable.java b/juneau-core/src/main/java/org/apache/juneau/Writable.java
index 20dd7e0..bd9298f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Writable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Writable.java
@@ -14,6 +14,8 @@ package org.apache.juneau;
 
 import java.io.*;
 
+import org.apache.juneau.http.*;
+
 /**
  * Interface that identifies that an object can be serialized directly to a writer.
  * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index a8d1fb1..addbbb7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.csv;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
index 151b8b6..548cbd2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index 0715bb5..48d7ae3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.csv;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
index bee169f..163928b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
@@ -16,6 +16,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
index 8dc3e50..ff9a505 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
@@ -14,8 +14,8 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 
 /**
  * Describes a single API operation on a path.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index c40dbff..134d4e5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -14,8 +14,8 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.utils.*;
 
 /**