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>&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.*;
/**