Repository: incubator-juneau
Updated Branches:
  refs/heads/master de98f18d6 -> fa4736b6d


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/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
deleted file mode 100644
index a05189f..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/http/TypeRange.java
+++ /dev/null
@@ -1,276 +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.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/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Upgrade.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Upgrade.java 
b/juneau-core/src/main/java/org/apache/juneau/http/Upgrade.java
new file mode 100644
index 0000000..344943c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Upgrade.java
@@ -0,0 +1,84 @@
+// 
***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a parsed <l>Upgrade</l> HTTP request header.
+ * <p>
+ * Ask the client to upgrade to another protocol.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ * The Upgrade general-header allows the client to specify what additional 
communication protocols it supports and
+ * would like to use if the server finds it appropriate to switch protocols.
+ * The server MUST use the Upgrade header field within a 101 (Switching 
Protocols) response to indicate which
+ * protocol(s) are being switched.
+ * <p class='bcode'>
+ *     Upgrade        = "Upgrade" ":" 1#product
+ * </p>
+ * <p>
+ * For example,
+ * <p class='bcode'>
+ *     Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
+ * </p>
+ * <p>
+ * The Upgrade header field is intended to provide a simple mechanism for 
transition from HTTP/1.1 to some other,
+ * incompatible protocol.
+ * It does so by allowing the client to advertise its desire to use another 
protocol, such as a later version of HTTP
+ * with a higher major version number, even though the current request has 
been made using HTTP/1.1.
+ * This eases the difficult transition between incompatible protocols by 
allowing the client to initiate a request in
+ * the more commonly supported protocol while indicating to the server that it 
would like to use a "better" protocol if
+ * available (where "better" is determined by the server, possibly according 
to the nature of the method and/or resource
+ * being requested).
+ * <p>
+ * The Upgrade header field only applies to switching application-layer 
protocols upon the existing transport-layer
+ * connection.
+ * Upgrade cannot be used to insist on a protocol change; its acceptance and 
use by the server is optional.
+ * The capabilities and nature of the application-layer communication after 
the protocol change is entirely dependent
+ * upon the new protocol chosen, although the first action after changing the 
protocol MUST be a response to the initial
+ * HTTP request containing the Upgrade header field.
+ * <p>
+ * The Upgrade header field only applies to the immediate connection.
+ * Therefore, the upgrade keyword MUST be supplied within a Connection header 
field (section 14.10) whenever Upgrade is
+ * present in an HTTP/1.1 message.
+ * <p>
+ * The Upgrade header field cannot be used to indicate a switch to a protocol 
on a different connection.
+ * For that purpose, it is more appropriate to use a 301, 302, 303, or 305 
redirection response.
+ * <p>
+ * This specification only defines the protocol name "HTTP" for use by the 
family of Hypertext Transfer Protocols, as
+ * defined by the HTTP version rules of section 3.1 and future updates to this 
specification.
+ * Any token can be used as a protocol name; however, it will only be useful 
if both the client and server associate
+ * the name with the same protocol.
+ */
+public final class Upgrade extends HeaderStringArray {
+
+       /**
+        * Returns a parsed <code>Upgrade</code> header.
+        *
+        * @param value The <code>Upgrade</code> header string.
+        * @return The parsed <code>Upgrade</code> header, or <jk>null</jk> if 
the string was null.
+        */
+       public static Upgrade forString(String value) {
+               if (value == null)
+                       return null;
+               return new Upgrade(value);
+       }
+
+       private Upgrade(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/UserAgent.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/UserAgent.java 
b/juneau-core/src/main/java/org/apache/juneau/http/UserAgent.java
new file mode 100644
index 0000000..39c49a4
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/UserAgent.java
@@ -0,0 +1,60 @@
+// 
***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a parsed <l>User-Agent</l> HTTP request header.
+ * <p>
+ * The user agent string of the user agent.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 
Firefox/21.0
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The User-Agent request-header field contains information about the user 
agent originating the request.
+ * This is for statistical purposes, the tracing of protocol violations, and 
automated recognition of user agents for
+ * the sake of tailoring responses to avoid particular user agent limitations.
+ * User agents SHOULD include this field with requests.
+ * The field can contain multiple product tokens (section 3.8) and comments 
identifying the agent and any subproducts
+ * which form a significant part of the user agent.
+ * By convention, the product tokens are listed in order of their significance 
for identifying the application.
+ * <p class='bcode'>
+ *     User-Agent     = "User-Agent" ":" 1*( product | comment )
+ * </p>
+ * <p>
+ * Example:
+ * <p class='bcode'>
+ *     User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+ * </p>
+ */
+public final class UserAgent extends HeaderString {
+
+       /**
+        * Returns a parsed <code>User-Agent</code> header.
+        *
+        * @param value The <code>User-Agent</code> header string.
+        * @return The parsed <code>User-Agent</code> header, or <jk>null</jk> 
if the string was null.
+        */
+       public static UserAgent forString(String value) {
+               if (value == null)
+                       return null;
+               return new UserAgent(value);
+       }
+
+       private UserAgent(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Vary.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Vary.java 
b/juneau-core/src/main/java/org/apache/juneau/http/Vary.java
new file mode 100644
index 0000000..0bb3faf
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Vary.java
@@ -0,0 +1,78 @@
+// 
***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a parsed <l>Vary</l> HTTP response header.
+ * <p>
+ * Tells downstream proxies how to match future request headers to decide 
whether the cached response can be used rather
+ * than requesting a fresh one from the origin server.
+
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     Vary: *
+ *     Vary: Accept-Language
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Vary field value indicates the set of request-header fields that fully 
determines, while the response is fresh,
+ * whether a cache is permitted to use the response to reply to a subsequent 
request without revalidation.
+ * For uncacheable or stale responses, the Vary field value advises the user 
agent about the criteria that were used to
+ * select the representation.
+ * A Vary field value of "*" implies that a cache cannot determine from the 
request headers of a subsequent request
+ * whether this response is the appropriate representation.
+ * See section 13.6 for use of the Vary header field by caches.
+ * <p class='bcode'>
+ *     Vary  = "Vary" ":" ( "*" | 1#field-name )
+ * </p>
+ * <p>
+ * An HTTP/1.1 server SHOULD include a Vary header field with any cacheable 
response that is subject to server-driven
+ * negotiation.
+ * Doing so allows a cache to properly interpret future requests on that 
resource and informs the user agent about the
+ * presence of negotiation on that resource.
+ * A server MAY include a Vary header field with a non-cacheable response that 
is subject to server-driven negotiation,
+ * since this might provide the user agent with useful information about the 
dimensions over which the response varies
+ * at the time of the response.
+ * <p>
+ * A Vary field value consisting of a list of field-names signals that the 
representation selected for the response is
+ * based on a selection algorithm which considers ONLY the listed 
request-header field values in selecting the most appropriate representation.
+ * A cache MAY assume that the same selection will be made for future requests 
with the same values for the listed
+ * field names, for the duration of time for which the response is fresh.
+ * <p>
+ * The field-names given are not limited to the set of standard request-header 
fields defined by this specification.
+ * Field names are case-insensitive.
+ * <p>
+ * A Vary field value of "*" signals that unspecified parameters not limited 
to the request-headers (e.g., the network
+ * address of the client), play a role in the selection of the response 
representation.
+ * The "*" value MUST NOT be generated by a proxy server; it may only be 
generated by an origin server.
+ */
+public final class Vary extends HeaderString {
+
+       /**
+        * Returns a parsed <code>Vary</code> header.
+        *
+        * @param value The <code>Vary</code> header string.
+        * @return The parsed <code>Vary</code> header, or <jk>null</jk> if the 
string was null.
+        */
+       public static Vary forString(String value) {
+               if (value == null)
+                       return null;
+               return new Vary(value);
+       }
+
+       private Vary(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Via.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Via.java 
b/juneau-core/src/main/java/org/apache/juneau/http/Via.java
new file mode 100644
index 0000000..a280354
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Via.java
@@ -0,0 +1,115 @@
+// 
***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a parsed <l>Via</l> HTTP response header.
+ * <p>
+ * Informs the client of proxies through which the response was sent.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     Via: 1.0 fred, 1.1 example.com (Apache/1.1)
+ * </p>
+ *
+ * Informs the client of proxies through which the response was sent.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     Via: 1.0 fred, 1.1 example.com (Apache/1.1)
+ * </p>
+ * <p>
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Via general-header field MUST be used by gateways and proxies to 
indicate the intermediate protocols and
+ * recipients between the user agent and the server on requests, and between 
the origin server and the client on
+ * responses.
+ * It is analogous to the "Received" field of RFC 822 and is intended to be 
used for tracking message forwards,
+ * avoiding request loops, and identifying the protocol capabilities of all 
senders along the request/response chain.
+ * <p class='bcode'>
+ *     Via =  "Via" ":" 1#( received-protocol received-by [ comment ] )
+ *     received-protocol = [ protocol-name "/" ] protocol-version
+ *     protocol-name     = token
+ *     protocol-version  = token
+ *     received-by       = ( host [ ":" port ] ) | pseudonym
+ *     pseudonym         = token
+ * </p>
+ * <p>
+ * The received-protocol indicates the protocol version of the message 
received by the server or client along each
+ * segment of the request/response chain.
+ * The received-protocol version is appended to the Via field value when the 
message is forwarded so that information
+ * about the protocol capabilities of upstream applications remains visible to 
all recipients.
+ * <p>
+ * The protocol-name is optional if and only if it would be "HTTP".
+ * The received-by field is normally the host and optional port number of a 
recipient server or client that subsequently
+ * forwarded the message.
+ * However, if the real host is considered to be sensitive information, it MAY 
be replaced by a pseudonym.
+ * If the port is not given, it MAY be assumed to be the default port of the 
received-protocol.
+ * <p>
+ * Multiple Via field values represents each proxy or gateway that has 
forwarded the message.
+ * Each recipient MUST append its information such that the end result is 
ordered according to the sequence of
+ * forwarding applications.
+ * <p>
+ * Comments MAY be used in the Via header field to identify the software of 
the recipient proxy or gateway, analogous
+ * to the User-Agent and Server header fields.
+ * However, all comments in the Via field are optional and MAY be removed by 
any recipient prior to forwarding the
+ * message.
+ * <p>
+ * For example, a request message could be sent from an HTTP/1.0 user agent to 
an internal proxy code-named "fred",
+ * which uses HTTP/1.1 to forward the request to a public proxy at 
nowhere.com, which completes the request by
+ * forwarding it to the origin server at www.ics.uci.edu.
+ * The request received by www.ics.uci.edu would then have the following Via 
header field:
+ * <p class='bcode'>
+ *     Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
+ * </p>
+ * <p>
+ * Proxies and gateways used as a portal through a network firewall SHOULD 
NOT, by default, forward the names and ports
+ * of hosts within the firewall region.
+ * This information SHOULD only be propagated if explicitly enabled.
+ * If not enabled, the received-by host of any host behind the firewall SHOULD 
be replaced by an appropriate pseudonym
+ * for that host.
+ * <p>
+ * For organizations that have strong privacy requirements for hiding internal 
structures, a proxy MAY combine an
+ * ordered subsequence of Via header field entries with identical 
received-protocol values into a single such entry.
+ * For example...
+ * <p class='bcode'>
+ *     Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
+ * </p>
+ * <p>
+ * ...could be collapsed to...
+ * <p class='bcode'>
+ *     Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
+ * </p>
+ * <p>
+ * Applications SHOULD NOT combine multiple entries unless they are all under 
the same organizational control and the
+ * hosts have already been replaced by pseudonyms.
+ * Applications MUST NOT combine entries which have different 
received-protocol values.
+ */
+public final class Via extends HeaderStringArray {
+
+       /**
+        * Returns a parsed <code>Via</code> header.
+        *
+        * @param value The <code>Via</code> header string.
+        * @return The parsed <code>Via</code> header, or <jk>null</jk> if the 
string was null.
+        */
+       public static Via forString(String value) {
+               if (value == null)
+                       return null;
+               return new Via(value);
+       }
+
+       private Via(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Warning.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Warning.java 
b/juneau-core/src/main/java/org/apache/juneau/http/Warning.java
new file mode 100644
index 0000000..2267fe7
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Warning.java
@@ -0,0 +1,123 @@
+// 
***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a parsed <l>Warning</l> HTTP request/response header.
+ * <p>
+ * A general warning about possible problems with the entity body.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     Warning: 199 Miscellaneous warning
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Warning general-header field is used to carry additional information 
about the status or transformation of a
+ * message which might not be reflected in the message.
+ * This information is typically used to warn about a possible lack of 
semantic transparency from caching operations
+ * or transformations applied to the entity body of the message.
+ * <p>
+ * Warning headers are sent with responses using:
+ * <p class='bcode'>
+ *     Warning    = "Warning" ":" 1#warning-value
+ *     warning-value = warn-code SP warn-agent SP warn-text
+ *                                           [SP warn-date]
+ *     warn-code  = 3DIGIT
+ *     warn-agent = ( host [ ":" port ] ) | pseudonym
+ *                     ; the name or pseudonym of the server adding
+ *                     ; the Warning header, for use in debugging
+ *     warn-text  = quoted-string
+ *     warn-date  = <"> HTTP-date <">
+ * </p>
+ * <p>
+ * A response MAY carry more than one Warning header.
+ * <p>
+ * The warn-text SHOULD be in a natural language and character set that is 
most likely to be intelligible to the human
+ * user receiving the response.
+ * This decision MAY be based on any available knowledge, such as the location 
of the cache or user, the
+ * Accept-Language field in a request, the Content-Language field in a 
response, etc.
+ * The default language is English and the default character set is ISO-8859-1.
+ * <p>
+ * If a character set other than ISO-8859-1 is used, it MUST be encoded in the 
warn-text using the method described in
+ * RFC 2047.
+ * <p>
+ * Warning headers can in general be applied to any message, however some 
specific warn-codes are specific to caches
+ * and can only be applied to response messages.
+ * New Warning headers SHOULD be added after any existing Warning headers.
+ * A cache MUST NOT delete any Warning header that it received with a message.
+ * However, if a cache successfully validates a cache entry, it SHOULD remove 
any Warning headers previously attached
+ * to that entry except as specified for specific Warning codes.
+ * It MUST then add any Warning headers received in the validating response.
+ * In other words, Warning headers are those that would be attached to the 
most recent relevant response.
+ * <p>
+ * When multiple Warning headers are attached to a response, the user agent 
ought to inform the user of as many of them
+ * as possible, in the order that they appear in the response.
+ * If it is not possible to inform the user of all of the warnings, the user 
agent SHOULD follow these heuristics:
+ * <ul>
+ *     <li>Warnings that appear early in the response take priority over those 
appearing later in the response.
+ *     <li>Warnings in the user's preferred character set take priority over 
warnings in other character sets but with
+ * identical warn-codes and warn-agents.
+ * </ul>
+ * Systems that generate multiple Warning headers SHOULD order them with this 
user agent behavior in mind.
+ * <p>
+ * Requirements for the behavior of caches with respect to Warnings are stated 
in section 13.1.2.
+ * <p>
+ * This is a list of the currently-defined warn-codes, each with a recommended 
warn-text in English, and a description
+ * of its meaning.
+ * <ul>
+ *     <li>110 Response is stale MUST be included whenever the returned 
response is stale.
+ *     <li>111 Revalidation failed MUST be included if a cache returns a stale 
response because an attempt to revalidate
+ *             the response failed, due to an inability to reach the server.
+ *     <li>112 Disconnected operation SHOULD be included if the cache is 
intentionally disconnected from the rest of the
+ *             network for a period of time.
+ *     <li>113 Heuristic expiration MUST be included if the cache 
heuristically chose a freshness lifetime greater than
+ *             24 hours and the response's age is greater than 24 hours.
+ *     <li>199 Miscellaneous warning The warning text MAY include arbitrary 
information to be presented to a human user,
+ *             or logged. A system receiving this warning MUST NOT take any 
automated action, besides presenting the warning
+ *             to the user.
+ *     <li>214 Transformation applied MUST be added by an intermediate cache 
or proxy if it applies any transformation
+ *             changing the content-coding (as specified in the 
Content-Encoding header) or media-type (as specified in the
+ *             Content-Type header) of the response, or the entity-body of the 
response, unless this Warning code already
+ *             appears in the response.
+ *     <li>299 Miscellaneous persistent warning The warning text MAY include 
arbitrary information to be presented to a
+ *             human user, or logged. A system receiving this warning MUST NOT 
take any automated action.
+ * </ul>
+ * If an implementation sends a message with one or more Warning headers whose 
version is HTTP/1.0 or lower, then the
+ * sender MUST include in each warning-value a warn-date that matches the date 
in the response.
+ * <p>
+ * If an implementation receives a message with a warning-value that includes 
a warn-date, and that warn-date is
+ * different from the Date value in the response, then that warning-value MUST 
be deleted from the message before
+ * storing, forwarding, or using it.
+ * (This prevents bad consequences of naive caching of Warning header fields.)
+ * If all of the warning-values are deleted for this reason, the Warning 
header MUST be deleted as well.
+ */
+public final class Warning extends HeaderString {
+
+       /**
+        * Returns a parsed <code>Warning</code> header.
+        *
+        * @param value The <code>Warning</code> header string.
+        * @return The parsed <code>Warning</code> header, or <jk>null</jk> if 
the string was null.
+        */
+       public static Warning forString(String value) {
+               if (value == null)
+                       return null;
+               return new Warning(value);
+       }
+
+       private Warning(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/http/WwwAuthenticate.java 
b/juneau-core/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
new file mode 100644
index 0000000..448ced9
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/WwwAuthenticate.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.http;
+
+/**
+ * Represents a parsed <l>WWW-Authenticate </l> HTTP response header.
+ * <p>
+ * Indicates the authentication scheme that should be used to access the 
requested entity.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ *     WWW-Authenticate: Basic
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The WWW-Authenticate response-header field MUST be included in 401 
(Unauthorized) response messages.
+ * The field value consists of at least one challenge that indicates the 
authentication scheme(s) and parameters
+ * applicable to the Request-URI.
+ * <p class='bcode'>
+ *     WWW-Authenticate  = "WWW-Authenticate" ":" 1#challenge
+ * </p>
+ * <p>
+ * The HTTP access authentication process is described in "HTTP 
Authentication: Basic and Digest Access Authentication".
+ * User agents are advised to take special care in parsing the 
WWW-Authenticate field value as it might contain more
+ * than one challenge, or if more than one WWW-Authenticate header field is 
provided, the contents of a challenge
+ * itself can contain a comma-separated list of authentication parameters.
+ */
+public final class WwwAuthenticate extends HeaderString {
+
+       /**
+        * Returns a parsed <code>WWW-Authenticate</code> header.
+        *
+        * @param value The <code>WWW-Authenticate</code> header string.
+        * @return The parsed <code>WWW-Authenticate</code> header, or 
<jk>null</jk> if the string was null.
+        */
+       public static WwwAuthenticate forString(String value) {
+               if (value == null)
+                       return null;
+               return new WwwAuthenticate(value);
+       }
+
+       private WwwAuthenticate(String value) {
+               super(value);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/internal/Cache.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/Cache.java 
b/juneau-core/src/main/java/org/apache/juneau/internal/Cache.java
new file mode 100644
index 0000000..2b31062
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/Cache.java
@@ -0,0 +1,81 @@
+// 
***************************************************************************************************************************
+// * 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.internal;
+
+import java.util.concurrent.*;
+
+/**
+ * Simple in-memory cache of objects.
+ * <p>
+ * Essentially just a wrapper around a ConcurrentHashMap.
+ *
+ * @param <K> The key type.
+ * @param <V> The value type.
+ */
+public class Cache<K,V> {
+       private final boolean nocache;
+       private final int maxSize;
+       private final ConcurrentHashMap<K,V> cache;
+
+       /**
+        * Constructor.
+        *
+        * @param disabled If <jk>true</jk> then the cache is disabled.
+        * @param maxSize The maximum size of the cache.  If this threshold is 
reached, the cache is flushed.
+        */
+       public Cache(boolean disabled, int maxSize) {
+               this.nocache = disabled;
+               this.maxSize = maxSize;
+               if (! nocache)
+                       cache = new ConcurrentHashMap<K,V>();
+               else
+                       cache = null;
+       }
+
+       /**
+        * Retrieves the value with the specified key from this cache.
+        *
+        * @param key The key.
+        * @return The value, or <jk>null</jk> if the value is not in the 
cache, or the cache is disabled.
+        */
+       public V get(K key) {
+               if (nocache)
+                       return null;
+               return cache.get(key);
+       }
+
+       /**
+        * Adds the value with the specified key to this cache.
+        *
+        * @param key The key.
+        * @param value The value.
+        * @return Either the value already in the cache if it already exists, 
or the same value passed in.
+        * Always returns the same value if the cache is disabled.
+        */
+       public V put(K key, V value) {
+               if (nocache)
+                       return value;
+
+               // Prevent OOM in case of DDOS
+               if (cache.size() > maxSize)
+                       cache.clear();
+
+               while (true) {
+                       V v = cache.get(key);
+                       if (v != null)
+                               return v;
+                       cache.putIfAbsent(key, value);
+                       return value;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/internal/DateUtils.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/internal/DateUtils.java 
b/juneau-core/src/main/java/org/apache/juneau/internal/DateUtils.java
new file mode 100644
index 0000000..48565c4
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/DateUtils.java
@@ -0,0 +1,186 @@
+// 
***************************************************************************************************************************
+// * 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.internal;
+
+import java.lang.ref.*;
+import java.text.*;
+import java.util.*;
+
+/**
+ * A utility class for parsing and formatting HTTP dates as used in cookies and
+ * other headers.  This class handles dates as defined by RFC 2616 section
+ * 3.3.1 as well as some other common non-standard formats.
+ * <p>
+ * This class was copied from HttpClient 4.3.
+ */
+public final class DateUtils {
+
+       /**
+        * Date format pattern used to parse HTTP date headers in RFC 1123 
format.
+        */
+       public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss 
zzz";
+
+       /**
+        * Date format pattern used to parse HTTP date headers in RFC 1036 
format.
+        */
+       public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss 
zzz";
+
+       /**
+        * Date format pattern used to parse HTTP date headers in ANSI C 
<code>asctime()</code> format.
+        */
+       public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
+       private static final String[] DEFAULT_PATTERNS = new String[] { 
PATTERN_RFC1123, PATTERN_RFC1036, PATTERN_ASCTIME };
+       private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
+       private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+       static {
+               final Calendar calendar = Calendar.getInstance();
+               calendar.setTimeZone(GMT);
+               calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
+               calendar.set(Calendar.MILLISECOND, 0);
+               DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
+       }
+
+       /**
+        * Parses a date value. The formats used for parsing the date value are 
retrieved from the default http params.
+        *
+        * @param dateValue the date value to parse
+        * @return the parsed date or null if input could not be parsed
+        */
+       public static Date parseDate(final String dateValue) {
+               return parseDate(dateValue, null, null);
+       }
+
+       /**
+        * Parses the date value using the given date formats.
+        *
+        * @param dateValue the date value to parse
+        * @param dateFormats the date formats to use
+        *
+        * @return the parsed date or null if input could not be parsed
+        */
+       public static Date parseDate(final String dateValue, final String[] 
dateFormats) {
+               return parseDate(dateValue, dateFormats, null);
+       }
+
+       /**
+        * Parses the date value using the given date formats.
+        *
+        * @param dateValue the date value to parse
+        * @param dateFormats the date formats to use
+        * @param startDate During parsing, two digit years will be placed in 
the range <code>startDate</code> to
+        *      <code>startDate + 100 years</code>. This value may be 
<code>null</code>. When
+        *      <code>null</code> is given as a parameter, year 
<code>2000</code> will be used.
+        *
+        * @return the parsed date or null if input could not be parsed
+        */
+       public static Date parseDate(final String dateValue, final String[] 
dateFormats, final Date startDate) {
+               final String[] localDateFormats = dateFormats != null ? 
dateFormats : DEFAULT_PATTERNS;
+               final Date localStartDate = startDate != null ? startDate : 
DEFAULT_TWO_DIGIT_YEAR_START;
+               String v = dateValue;
+               // trim single quotes around date if present
+               // see issue #5279
+               if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
+                       v = v.substring(1, v.length() - 1);
+               }
+               for (final String dateFormat : localDateFormats) {
+                       final SimpleDateFormat dateParser = 
DateFormatHolder.formatFor(dateFormat);
+                       dateParser.set2DigitYearStart(localStartDate);
+                       final ParsePosition pos = new ParsePosition(0);
+                       final Date result = dateParser.parse(v, pos);
+                       if (pos.getIndex() != 0) {
+                               return result;
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Formats the given date according to the RFC 1123 pattern.
+        *
+        * @param date The date to format.
+        * @return An RFC 1123 formatted date string.
+        *
+        * @see #PATTERN_RFC1123
+        */
+       public static String formatDate(final Date date) {
+               return formatDate(date, PATTERN_RFC1123);
+       }
+
+       /**
+        * Formats the given date according to the specified pattern. The 
pattern must conform to that used by the
+        * {@link SimpleDateFormat simple date format} class.
+        *
+        * @param date The date to format.
+        * @param pattern The pattern to use for formatting the date.
+        * @return A formatted date string.
+        * @throws IllegalArgumentException If the given date pattern is 
invalid.
+        * @see SimpleDateFormat
+        */
+       public static String formatDate(final Date date, final String pattern) {
+               final SimpleDateFormat formatter = 
DateFormatHolder.formatFor(pattern);
+               return formatter.format(date);
+       }
+
+       /**
+        * Clears thread-local variable containing {@link java.text.DateFormat} 
cache.
+        */
+       public static void clearThreadLocal() {
+               DateFormatHolder.clearThreadLocal();
+       }
+
+       /** This class should not be instantiated. */
+       private DateUtils() {
+       }
+
+       /**
+        * A factory for {@link SimpleDateFormat}s. The instances are stored in 
a threadlocal way because SimpleDateFormat
+        * is not threadsafe as noted in {@link SimpleDateFormat its javadoc}.
+        *
+        */
+       final static class DateFormatHolder {
+               private static final 
ThreadLocal<SoftReference<Map<String,SimpleDateFormat>>> THREADLOCAL_FORMATS = 
new ThreadLocal<SoftReference<Map<String,SimpleDateFormat>>>() {
+                       @Override
+                       protected SoftReference<Map<String,SimpleDateFormat>> 
initialValue() {
+                               return new 
SoftReference<Map<String,SimpleDateFormat>>(new 
HashMap<String,SimpleDateFormat>());
+                       }
+               };
+
+               /**
+                * creates a {@link SimpleDateFormat} for the requested format 
string.
+                *
+                * @param pattern a non-<code>null</code> format String 
according to {@link SimpleDateFormat}. The format is not
+                *      checked against <code>null</code> since all paths go 
through {@link DateUtils}.
+                * @return the requested format. This simple dateformat should 
not be used to
+                *      {@link SimpleDateFormat#applyPattern(String) apply} to 
a different pattern.
+                */
+               public static SimpleDateFormat formatFor(final String pattern) {
+                       final SoftReference<Map<String,SimpleDateFormat>> ref = 
THREADLOCAL_FORMATS.get();
+                       Map<String,SimpleDateFormat> formats = ref.get();
+                       if (formats == null) {
+                               formats = new 
HashMap<String,SimpleDateFormat>();
+                               THREADLOCAL_FORMATS.set(new 
SoftReference<Map<String,SimpleDateFormat>>(formats));
+                       }
+                       SimpleDateFormat format = formats.get(pattern);
+                       if (format == null) {
+                               format = new SimpleDateFormat(pattern, 
Locale.US);
+                               format.setTimeZone(TimeZone.getTimeZone("GMT"));
+                               formats.put(pattern, format);
+                       }
+                       return format;
+               }
+
+               public static void clearThreadLocal() {
+                       THREADLOCAL_FORMATS.remove();
+               }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/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 bee95d9..8d324fe 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
@@ -1316,4 +1316,20 @@ public final class StringUtils {
                }
                return 0;
        }
+
+       /**
+        * Returns the character at the specified index in the string without 
throwing exceptions.
+        *
+        * @param s The string.
+        * @param i The index position.
+        * @return The character at the specified index, or <code>0</code> if 
the index is out-of-range or the string
+        *      is <jk>null</jk>.
+        */
+       public static char charAt(String s, int i) {
+               if (s == null)
+                       return 0;
+               if (i < 0 || i >= s.length())
+                       return 0;
+               return s.charAt(i);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/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 9c381b5..f4a4559 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
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import javax.xml.stream.*;
+import javax.xml.stream.Location;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;

Reply via email to