juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [1/4] incubator-juneau git commit: Add HTTP header classes.
Date Sat, 06 May 2017 16:24:36 GMT
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.*;


Mime
View raw message