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

[3/4] incubator-juneau git commit: Add HTTP header classes.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/ContentLocation.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/ContentLocation.java b/juneau-core/src/main/java/org/apache/juneau/http/ContentLocation.java
new file mode 100644
index 0000000..d8b19f4
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/ContentLocation.java
@@ -0,0 +1,72 @@
+// ***************************************************************************************************************************
+// * 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>Content-Location</l> HTTP response header.
+ * <p>
+ * An alternate location for the returned data.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Content-Location: /index.htm
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Content-Location entity-header field MAY be used to supply the resource location for the entity enclosed in the
+ * message when that entity is accessible from a location separate from the requested resource's URI.
+ * A server SHOULD provide a Content-Location for the variant corresponding to the response entity; especially in the
+ * case where a resource has multiple entities associated with it, and those entities actually have separate locations
+ * by which they might be individually accessed, the server SHOULD provide a Content-Location for the particular variant
+ * which is returned.
+ * <p class='bcode'>
+ * 	Content-Location = "Content-Location" ":"
+ * 	                   ( absoluteURI | relativeURI )
+ * </p>
+ * <p>
+ * The value of Content-Location also defines the base URI for the entity.
+ * <p>
+ * The Content-Location value is not a replacement for the original requested URI; it is only a statement of the
+ * location of the resource corresponding to this particular entity at the time of the request.
+ * Future requests MAY specify the Content-Location URI as the request- URI if the desire is to identify the source of
+ * that particular entity.
+ * <p>
+ * A cache cannot assume that an entity with a Content-Location different from the URI used to retrieve it can be used
+ * to respond to later requests on that Content-Location URI.
+ * However, the Content- Location can be used to differentiate between multiple entities retrieved from a single
+ * requested resource, as described in section 13.6.
+ * <p>
+ * If the Content-Location is a relative URI, the relative URI is interpreted relative to the Request-URI.
+ * <p>
+ * The meaning of the Content-Location header in PUT or POST requests is undefined; servers are free to ignore it in
+ * those cases.
+ */
+public final class ContentLocation extends HeaderUri {
+
+	/**
+	 * Returns a parsed <code>Content-Location</code> header.
+	 *
+	 * @param value The <code>Content-Location</code> header string.
+	 * @return The parsed <code>Content-Location</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static ContentLocation forString(String value) {
+		if (value == null)
+			return null;
+		return new ContentLocation(value);
+	}
+
+	private ContentLocation(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/ContentRange.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/ContentRange.java b/juneau-core/src/main/java/org/apache/juneau/http/ContentRange.java
new file mode 100644
index 0000000..d437b3b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/ContentRange.java
@@ -0,0 +1,126 @@
+// ***************************************************************************************************************************
+// * 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>Content-Range</l> HTTP response header.
+ * <p>
+ * Where in a full body message this partial message belongs.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Content-Range: bytes 21010-47021/47022
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ * The Content-Range entity-header is sent with a partial entity-body to specify where in the full entity-body the
+ * partial body should be applied.
+ * Range units are defined in section 3.12.
+ * <p class='bcode'>
+ * 	Content-Range = "Content-Range" ":" content-range-spec
+ * 	content-range-spec      = byte-content-range-spec
+ * 	byte-content-range-spec = bytes-unit SP
+ * 	                          byte-range-resp-spec "/"
+ * 	                          ( instance-length | "*" )
+ * 	byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
+ * 	                               | "*"
+ * 	instance-length           = 1*DIGIT
+ * </p>
+ * <p>
+ * The header SHOULD indicate the total length of the full entity-body, unless this length is unknown or difficult to
+ * determine.
+ * The asterisk "*" character means that the instance-length is unknown at the time when the response was generated.
+ * <p>
+ * Unlike byte-ranges-specifier values (see section 14.35.1), a byte- range-resp-spec MUST only specify one range, and
+ * MUST contain absolute byte positions for both the first and last byte of the range.
+ * <p>
+ * A byte-content-range-spec with a byte-range-resp-spec whose last- byte-pos value is less than its first-byte-pos
+ * value, or whose instance-length value is less than or equal to its last-byte-pos value, is invalid.
+ * The recipient of an invalid byte-content-range- spec MUST ignore it and any content transferred along with it.
+ * <p>
+ * A server sending a response with status code 416 (Requested range not satisfiable) SHOULD include a Content-Range
+ * field with a byte-range- resp-spec of "*".
+ * The instance-length specifies the current length of the selected resource.
+ * A response with status code 206 (Partial Content) MUST NOT include a Content-Range field with a byte-range-resp-spec
+ * of "*".
+ * <p>
+ * Examples of byte-content-range-spec values, assuming that the entity contains a total of 1234 bytes:
+ * <p class='bcode'>
+ * 	The first 500 bytes:
+ * 	 bytes 0-499/1234
+ * 	The second 500 bytes:
+ * 	 bytes 500-999/1234
+ * 	All except for the first 500 bytes:
+ * 	 bytes 500-1233/1234
+ * 	The last 500 bytes:
+ * 	 bytes 734-1233/1234
+ * </p>
+ * <p>
+ * When an HTTP message includes the content of a single range (for example, a response to a request for a single range,
+ * or to a request for a set of ranges that overlap without any holes), this content is transmitted with a Content-Range
+ * header, and a Content-Length header showing the number of bytes actually transferred.
+ * For example:
+ * <p class='bcode'>
+ * 	HTTP/1.1 206 Partial content
+ * 	Date: Wed, 15 Nov 1995 06:25:24 GMT
+ * 	Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ * 	Content-Range: bytes 21010-47021/47022
+ * 	Content-Length: 26012
+ * 	Content-Type: image/gif
+ * </p>
+ * <p>
+ * When an HTTP message includes the content of multiple ranges (for example, a response to a request for multiple
+ * non-overlapping ranges), these are transmitted as a multipart message.
+ * The multipart media type used for this purpose is "multipart/byteranges" as defined in appendix 19.2.
+ * See appendix 19.6.3 for a compatibility issue.
+ * <p>
+ * A response to a request for a single range MUST NOT be sent using the multipart/byteranges media type.
+ * A response to a request for multiple ranges, whose result is a single range, MAY be sent as a multipart/byteranges
+ * media type with one part.
+ * A client that cannot decode a multipart/byteranges message MUST NOT ask for multiple byte-ranges in a single request.
+ * <p>
+ * When a client requests multiple byte-ranges in one request, the server SHOULD return them in the order that they
+ * appeared in the request.
+ * <p>
+ * If the server ignores a byte-range-spec because it is syntactically invalid, the server SHOULD treat the request as
+ * if the invalid Range header field did not exist.
+ * (Normally, this means return a 200 response containing the full entity).
+ * <p>
+ * If the server receives a request (other than one including an If- Range request-header field) with an unsatisfiable
+ * Range request- header field
+ * (that is, all of whose byte-range-spec values have a first-byte-pos value greater than the current length of the
+ * selected resource),
+ * it SHOULD return a response code of 416 (Requested range not satisfiable) (section 10.4.17).
+ * <p>
+ * Note: clients cannot depend on servers to send a 416 (Requested range not satisfiable) response instead of a 200 (OK)
+ * response for
+ * an unsatisfiable Range request-header, since not all servers implement this request-header.
+ */
+public final class ContentRange extends HeaderString {
+
+	/**
+	 * Returns a parsed <code>Content-Range</code> header.
+	 *
+	 * @param value The <code>Content-Range</code> header string.
+	 * @return The parsed <code>Content-Range</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static ContentRange forString(String value) {
+		if (value == null)
+			return null;
+		return new ContentRange(value);
+	}
+
+	private ContentRange(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/ContentType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java b/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
index fcf48d8..f2a0dd4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
+++ b/juneau-core/src/main/java/org/apache/juneau/http/ContentType.java
@@ -12,56 +12,54 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http;
 
-import java.util.concurrent.*;
+import static org.apache.juneau.http.Constants.*;
+
+import org.apache.juneau.internal.*;
 
 /**
- * Represents a parsed <code>Content-Type:</code> HTTP header.
+ * Represents a parsed <l>Content-Type</l> HTTP request/response header.
  * <p>
- * The formal RFC2616 header field definition is as follows:
- * <p class='bcode'>
- * 	14.17 Content-Type
+ * The MIME type of this content.
  *
- * 	The Content-Type entity-header field indicates the media type of the
- * 	entity-body sent to the recipient or, in the case of the HEAD method,
- * 	the media type that would have been sent had the request been a GET.
- *
- * 		Content-Type   = "Content-Type" ":" media-type
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Content-Type: text/html; charset=utf-8
+ * </p>
  *
- * 	Media types are defined in section 3.7. An example of the field is
+ * <h6 class='topic'>RFC2616 Specification</h6>
  *
+ * The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the
+ * case of the HEAD method, the media type that would have been sent had the request been a GET.
+ * <p class='bcode'>
+ * 	Content-Type   = "Content-Type" ":" media-type
+ * </p>
+ * <p>
+ * Media types are defined in section 3.7.
+ * An example of the field is...
+ * <p class='bcode'>
  * 	Content-Type: text/html; charset=ISO-8859-4
  * </p>
  */
 public class ContentType extends MediaType {
 
-	private static final boolean nocache = Boolean.getBoolean("juneau.http.ContentType.nocache");
-	private static final ConcurrentHashMap<String,ContentType> cache = new ConcurrentHashMap<String,ContentType>();
+	private static Cache<String,ContentType> cache = new Cache<String,ContentType>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
 	 * Returns a parsed <code>Content-Type</code> header.
 	 *
-	 * @param s The <code>Content-Type</code> header string.
+	 * @param value The <code>Content-Type</code> header string.
 	 * @return The parsed <code>Content-Type</code> header, or <jk>null</jk> if the string was null.
 	 */
-	public static ContentType forString(String s) {
-		if (s == null)
+	public static ContentType forString(String value) {
+		if (value == null)
 			return null;
-
-		// Prevent OOM in case of DDOS
-		if (cache.size() > 1000)
-			cache.clear();
-
-		while (true) {
-			ContentType mt = cache.get(s);
-			if (mt != null)
-				return mt;
-			mt = new ContentType(s);
-			if (nocache)
-				return mt;
-			cache.putIfAbsent(s, mt);
-		}
+		ContentType ct = cache.get(value);
+		if (ct == null)
+			ct = cache.put(value, new ContentType(value));
+		return ct;
 	}
 
+
 	private ContentType(String s) {
 		super(s);
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Date.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Date.java b/juneau-core/src/main/java/org/apache/juneau/http/Date.java
new file mode 100644
index 0000000..21a0ba7
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Date.java
@@ -0,0 +1,83 @@
+// ***************************************************************************************************************************
+// * 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>Date</l> HTTP request/response header.
+ * <p>
+ * The date and time that the message was sent (in "HTTP-date" format as defined by RFC 7231).
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Date: Tue, 15 Nov 1994 08:12:31 GMT
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Date general-header field represents the date and time at which the message was originated, having the same
+ * semantics as orig-date in RFC 822.
+ * The field value is an HTTP-date, as described in section 3.3.1; it MUST be sent in RFC 1123 [8]-date format.
+ * <p class='bcode'>
+ * 	Date  = "Date" ":" HTTP-date
+ * </p>
+ * <p>
+ * An example is...
+ * <p class='bcode'>
+ * 	Date: Tue, 15 Nov 1994 08:12:31 GMT
+ * </p>
+ * <p>
+ * Origin servers MUST include a Date header field in all responses, except in these cases:
+ * <ol>
+ * 	<li>If the response status code is 100 (Continue) or 101 (Switching Protocols), the response MAY include a Date
+ * header field, at the server's option.
+ * 	<li>If the response status code conveys a server error, e.g. 500 (Internal Server Error) or 503 (Service
+ * Unavailable), and it is inconvenient or impossible to generate a valid Date.
+ * 	<li>If the server does not have a clock that can provide a reasonable approximation of the current time, its
+ * responses MUST NOT include a Date header field.
+ * 		In this case, the rules in section 14.18.1 MUST be followed.
+ * </ol>
+ * A received message that does not have a Date header field MUST be assigned one by the recipient if the message will
+ * be cached by that recipient or gatewayed via a protocol which requires a Date.
+ * An HTTP implementation without a clock MUST NOT cache responses without revalidating them on every use.
+ * An HTTP cache, especially a shared cache, SHOULD use a mechanism, such as NTP, to synchronize its clock with a
+ * reliable external standard.
+ * <p>
+ * Clients SHOULD only send a Date header field in messages that include an entity-body, as in the case of the PUT and
+ * POST requests, and even then it is optional.
+ * A client without a clock MUST NOT send a Date header field in a request.
+ * <p>
+ * The HTTP-date sent in a Date header SHOULD NOT represent a date and time subsequent to the generation of the message.
+ * It SHOULD represent the best available approximation of the date and time of message generation, unless the
+ * implementation has no means of generating a reasonably accurate date and time.
+ * In theory, the date ought to represent the moment just before the entity is generated.
+ * In practice, the date can be generated at any time during the message origination without affecting its semantic
+ * value.
+ */
+public final class Date extends HeaderDate {
+
+	/**
+	 * Returns a parsed <code>Date</code> header.
+	 *
+	 * @param value The <code>Date</code> header string.
+	 * @return The parsed <code>Date</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static Date forString(String value) {
+		if (value == null)
+			return null;
+		return new Date(value);
+	}
+
+	private Date(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/ETag.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/ETag.java b/juneau-core/src/main/java/org/apache/juneau/http/ETag.java
new file mode 100644
index 0000000..782e2bd
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/ETag.java
@@ -0,0 +1,58 @@
+// ***************************************************************************************************************************
+// * 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>ETag</l> HTTP response header.
+ * <p>
+ * An identifier for a specific version of a resource, often a message digest.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	ETag: "737060cd8c284d8af7ad3082f209582d"
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The ETag response-header field provides the current value of the entity tag for the requested variant.
+ * The headers used with entity tags are described in sections 14.24, 14.26 and 14.44.
+ * The entity tag MAY be used for comparison with other entities from the same resource (see section 13.3.3).
+ * <p class='bcode'>
+ * 	ETag = "ETag" ":" entity-tag
+ * </p>
+ * <p>
+ * Examples:
+ * <p class='bcode'>
+ * 	ETag: "xyzzy"
+ * 	ETag: W/"xyzzy"
+ * 	ETag: ""
+ * </p>
+ */
+public final class ETag extends HeaderString {
+
+	/**
+	 * Returns a parsed <code>ETag</code> header.
+	 *
+	 * @param value The <code>ETag</code> header string.
+	 * @return The parsed <code>ETag</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static ETag forString(String value) {
+		if (value == null)
+			return null;
+		return new ETag(value);
+	}
+
+	private ETag(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/EntityValidator.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/EntityValidator.java b/juneau-core/src/main/java/org/apache/juneau/http/EntityValidator.java
new file mode 100644
index 0000000..7dbb73d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/EntityValidator.java
@@ -0,0 +1,72 @@
+// ***************************************************************************************************************************
+// * 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 validator value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	ETag: "123456789"    – A strong ETag validator
+ * 	ETag: W/"123456789"  – A weak ETag validator
+ * </p>
+ */
+public class EntityValidator {
+
+	private final String value;
+	private final boolean isWeak;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param value The validator string value.
+	 */
+	protected EntityValidator(String value) {
+		value = value.trim();
+		isWeak = value.startsWith("W/");
+		if (isWeak)
+			value = value.substring(2);
+		if (value.length() > 1 && value.charAt(0) == '"' && value.charAt(value.length()-1) == '"')
+			value = value.substring(1, value.length()-1);
+		this.value = value;
+	}
+
+	/**
+	 * Returns the validator value stripped of quotes and weak tag.
+	 * @return The validator value.
+	 */
+	public String asString() {
+		return value;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the weak flag is present in the value.
+	 * @return <jk>true</jk> if the weak flag is present in the value.
+	 */
+	public boolean isWeak() {
+		return isWeak;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the validator string value is <code>*</code>.
+	 * @return <jk>true</jk> if the validator string value is <code>*</code>.
+	 */
+	public boolean isAny() {
+		return "*".equals(value);
+	}
+
+	@Override
+	public String toString() {
+		return (isWeak ? "W/" : "") + (isAny() ? "*" : ('"' + value + '"'));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Expect.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Expect.java b/juneau-core/src/main/java/org/apache/juneau/http/Expect.java
new file mode 100644
index 0000000..e5e6910
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Expect.java
@@ -0,0 +1,73 @@
+// ***************************************************************************************************************************
+// * 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>Expect</l> HTTP request header.
+ * <p>
+ * Indicates that particular server behaviors are required by the client.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Expect: 100-continue
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Expect request-header field is used to indicate that particular server behaviors are required by the client.
+ * <p class='bcode'>
+ * 	Expect       =  "Expect" ":" 1#expectation
+ * 	expectation  =  "100-continue" | expectation-extension
+ * 	expectation-extension =  token [ "=" ( token | quoted-string )
+ * 	                         *expect-params ]
+ * 	expect-params =  ";" token [ "=" ( token | quoted-string ) ]
+ * </p>
+ * <p>
+ * A server that does not understand or is unable to comply with any of the expectation values in the Expect field of a
+ * request MUST respond with appropriate error status.
+ * The server MUST respond with a 417 (Expectation Failed) status if any of the expectations cannot be met or, if there
+ * are other problems with the request, some other 4xx status.
+ * <p>
+ * This header field is defined with extensible syntax to allow for future extensions.
+ * If a server receives a request containing an Expect field that includes an expectation-extension that it does not
+ * support, it MUST respond with a 417 (Expectation Failed) status.
+ * <p>
+ * Comparison of expectation values is case-insensitive for unquoted tokens (including the 100-continue token), and is
+ * case-sensitive for quoted-string expectation-extensions.
+ * <p>
+ * The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST return a 417 (Expectation Failed) status if it
+ * receives a request with an expectation that it cannot meet.
+ * However, the Expect request-header itself is end-to-end; it MUST be forwarded if the request is forwarded.
+ * <p>
+ * Many older HTTP/1.0 and HTTP/1.1 applications do not understand the Expect header.
+ * <p>
+ * See section 8.2.3 for the use of the 100 (continue) status.
+ */
+public final class Expect extends HeaderString {
+
+	/**
+	 * Returns a parsed <code>Expect</code> header.
+	 *
+	 * @param value The <code>Expect</code> header string.
+	 * @return The parsed <code>Expect</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static Expect forString(String value) {
+		if (value == null)
+			return null;
+		return new Expect(value);
+	}
+
+	private Expect(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/Expires.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Expires.java b/juneau-core/src/main/java/org/apache/juneau/http/Expires.java
new file mode 100644
index 0000000..1d6cfe8
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Expires.java
@@ -0,0 +1,80 @@
+// ***************************************************************************************************************************
+// * 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>Expires</l> HTTP response header.
+ * <p>
+ * Gives the date/time after which the response is considered stale (in "HTTP-date" format as defined by RFC 7231).
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Expires: Thu, 01 Dec 1994 16:00:00 GMT
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ * The Expires entity-header field gives the date/time after which the response is considered stale.
+ * A stale cache entry may not normally be returned by a cache (either a proxy cache or a user agent cache) unless it is
+ * first validated with the origin server
+ * (or with an intermediate cache that has a fresh copy of the entity).
+ * See section 13.2 for further discussion of the expiration model.
+ * <p>
+ * The presence of an Expires field does not imply that the original resource will change or cease to exist at, before,
+ * or after that time.
+ * <p>
+ * The format is an absolute date and time as defined by HTTP-date in section 3.3.1; it MUST be in RFC 1123 date format:
+ * <p class='bcode'>
+ * 	Expires = "Expires" ":" HTTP-date
+ * </p>
+ * <p>
+ * An example of its use is...
+ * <p class='bcode'>
+ * 	Expires: Thu, 01 Dec 1994 16:00:00 GMT
+ * </p>
+ * <p>
+ * Note: if a response includes a Cache-Control field with the max-age directive (see section 14.9.3), that directive
+ * overrides the Expires field.
+ * <p>
+ * HTTP/1.1 clients and caches MUST treat other invalid date formats, especially including the value "0", as in the past
+ * (i.e., "already expired").
+ * <p>
+ * To mark a response as "already expired," an origin server sends an Expires date that is equal to the Date header
+ * value.
+ * (See the rules for expiration calculations in section 13.2.4.)
+ * <p>
+ * To mark a response as "never expires," an origin server sends an Expires date approximately one year from the time
+ * the response is sent.
+ * HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.
+ * <p>
+ * The presence of an Expires header field with a date value of some time in the future on a response that otherwise
+ * would by default be non-cacheable indicates that the response is cacheable, unless indicated otherwise by a
+ * Cache-Control header field (section 14.9).
+ */
+public final class Expires extends HeaderDate {
+
+	/**
+	 * Returns a parsed <code>Expires</code> header.
+	 *
+	 * @param value The <code>Expires</code> header string.
+	 * @return The parsed <code>Expires</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static Expires forString(String value) {
+		if (value == null)
+			return null;
+		return new Expires(value);
+	}
+
+	private Expires(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/From.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/From.java b/juneau-core/src/main/java/org/apache/juneau/http/From.java
new file mode 100644
index 0000000..7ac0f7a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/From.java
@@ -0,0 +1,72 @@
+// ***************************************************************************************************************************
+// * 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>From</l> HTTP request header.
+ * <p>
+ * The email address of the user making the request.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	From: user@example.com
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The From request-header field, if given, SHOULD contain an Internet e-mail address for the human user who controls
+ * the requesting user agent.
+ * The address SHOULD be machine-usable, as defined by "mailbox" in RFC 822 [9] as updated by RFC 1123 [8]:
+ * <p class='bcode'>
+ * 	From   = "From" ":" mailbox
+ * </p>
+ * <p>
+ * An example is:
+ * <p class='bcode'>
+ * 	From: webmaster@w3.org
+ * </p>
+ * <p>
+ * This header field MAY be used for logging purposes and as a means for identifying the source of invalid or unwanted
+ * requests.
+ * It SHOULD NOT be used as an insecure form of access protection.
+ * The interpretation of this field is that the request is being performed on behalf of the person given, who accepts
+ * responsibility for the method performed.
+ * In particular, robot agents SHOULD include this header so that the person responsible for running the robot can be
+ * contacted if problems occur on the receiving end.
+ * <p>
+ * The Internet e-mail address in this field MAY be separate from the Internet host which issued the request.
+ * For example, when a request is passed through a proxy the original issuer's address SHOULD be used.
+ * <p>
+ * The client SHOULD NOT send the From header field without the user's approval, as it might conflict with the user's
+ * privacy interests or their site's security policy.
+ * It is strongly recommended that the user be able to disable, enable, and modify the value of this field at any time
+ * prior to a request.
+ */
+public final class From extends HeaderString {
+
+	/**
+	 * Returns a parsed <code>From</code> header.
+	 *
+	 * @param value The <code>From</code> header string.
+	 * @return The parsed <code>From</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static From forString(String value) {
+		if (value == null)
+			return null;
+		return new From(value);
+	}
+
+	private From(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/HeaderDate.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderDate.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderDate.java
new file mode 100644
index 0000000..fa2b0f0
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderDate.java
@@ -0,0 +1,51 @@
+// ***************************************************************************************************************************
+// * 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 org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of a single HTTP-date.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+ * </p>
+ */
+public class HeaderDate {
+
+	private final java.util.Date date;
+	private final String raw;
+
+	/**
+	 * Constructor.
+	 * @param raw The raw header value.
+	 */
+	protected HeaderDate(String raw) {
+		this.raw = raw;
+		this.date = DateUtils.parseDate(raw);
+	}
+
+	/**
+	 * Returns this header value as a {@link java.util.Date}.
+	 * @return This header value as a {@link java.util.Date}, or <jk>null</jk> if the header could not be parsed.
+	 */
+	public java.util.Date asDate() {
+		return date;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return raw;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidator.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidator.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidator.java
new file mode 100644
index 0000000..c20591e
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidator.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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;
+
+/**
+ * Category of headers that consist of a single entity validator value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	ETag: "xyzzy"
+ * </p>
+ */
+public class HeaderEntityValidator {
+
+	private final EntityValidator value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderEntityValidator(String value) {
+		this.value = new EntityValidator(value);
+	}
+
+	/**
+	 * Returns this header value as a {@link EntityValidator} object.
+	 * @return this header value as a {@link EntityValidator} object.
+	 */
+	public EntityValidator asValidator() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return value.toString();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidatorArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidatorArray.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidatorArray.java
new file mode 100644
index 0000000..358492a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEntityValidatorArray.java
@@ -0,0 +1,55 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of a comma-delimited list of entity validator values.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	If-Match: "xyzzy"
+ * 	If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ * 	If-Match: *
+ * </p>
+ */
+public class HeaderEntityValidatorArray {
+
+	private final EntityValidator[] value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderEntityValidatorArray(String value) {
+		String[] s = StringUtils.split(value, ',');
+		this.value = new EntityValidator[s.length];
+		for (int i = 0; i < s.length; i++) {
+			this.value[i] = new EntityValidator(s[i]);
+		}
+	}
+
+	/**
+	 * Returns this header value as an array of {@link EntityValidator} objects.
+	 * @return this header value as an array of {@link EntityValidator} objects.
+	 */
+	public EntityValidator[] asValidators() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return StringUtils.join(value, ", ");
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderEnum.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderEnum.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEnum.java
new file mode 100644
index 0000000..cccec8c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderEnum.java
@@ -0,0 +1,70 @@
+// ***************************************************************************************************************************
+// * 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;
+
+/**
+ * Category of headers that consist of a single enum value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Accept-Ranges: bytes
+ * </p>
+ * @param <E> The enum type.
+ */
+public class HeaderEnum<E extends Enum<E>> {
+
+	private final String value;
+	private final E enumValue;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 * @param enumClass The enum class.
+	 * @param def The default enum value if the value could not be parsed.
+	 */
+	protected HeaderEnum(String value, Class<E> enumClass, E def) {
+		this.value = value;
+		E _enumValue = def;
+		try {
+			_enumValue = Enum.valueOf(enumClass, value.toUpperCase());
+		} catch (Exception e) {
+			_enumValue = def;
+		}
+		this.enumValue = _enumValue;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified value is the same using {@link String#equalsIgnoreCase(String)}.
+	 *
+	 * @return <jk>true</jk> if the specified value is the same.
+	 */
+	public E asEnum() {
+		return enumValue;
+	}
+
+	/**
+	 * Returns this header as a simple string value.
+	 * <p>
+	 * Functionally equivalent to calling {@link #toString()}.
+	 *
+	 * @return This header as a simple string.
+	 */
+	public String asString() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return value == null ? "" : value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderInteger.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderInteger.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderInteger.java
new file mode 100644
index 0000000..5b23064
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderInteger.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * 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;
+
+/**
+ * Category of headers that consist of a single integer value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Age: 300
+ * </p>
+ */
+public class HeaderInteger {
+
+	private final int value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderInteger(String value) {
+		int _value = 0;
+		try {
+			_value = Integer.parseInt(value);
+		} catch (NumberFormatException e) {
+			try {
+				Long.parseLong(value);
+				_value = Integer.MAX_VALUE;
+			} catch (NumberFormatException e2) {}
+		}
+		this.value = _value;
+	}
+
+	/**
+	 * Returns this header as a simple string value.
+	 * <p>
+	 * Functionally equivalent to calling {@link #toString()}.
+	 *
+	 * @return This header as a simple string.
+	 */
+	public int asInt() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return String.valueOf(value);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderRangeArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderRangeArray.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderRangeArray.java
new file mode 100644
index 0000000..0163957
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderRangeArray.java
@@ -0,0 +1,74 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of simple comma-delimited lists of strings with q-values.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Accept-Encoding: compress;q=0.5, gzip;q=1.0
+ * </p>
+ */
+public class HeaderRangeArray {
+
+	final StringRange[] typeRanges;
+	private final List<StringRange> typeRangesList;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderRangeArray(String value) {
+		this.typeRanges = StringRange.parse(value);
+		this.typeRangesList = Collections.unmodifiableList(Arrays.asList(typeRanges));
+	}
+
+	/**
+	 * Given a list of type values, returns the best match for this header.
+	 *
+	 * @param types The types to match against.
+	 * @return The index into the array of the best match, or <code>-1</code> if no suitable matches could be found.
+	 */
+	public int findMatch(String[] types) {
+
+		// Type ranges are ordered by 'q'.
+		// So we only need to search until we've found a match.
+		for (StringRange mr : typeRanges)
+			for (int i = 0; i < types.length; i++)
+				if (mr.matches(types[i]))
+					return i;
+
+		return -1;
+	}
+
+	/**
+	 * Returns the list of the types ranges that make up this header.
+	 * <p>
+	 * The types ranges in the list are sorted by their q-value in descending order.
+	 *
+	 * @return An unmodifiable list of type ranges.
+	 */
+	public List<StringRange> asSimpleRanges() {
+		return typeRangesList;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return StringUtils.join(typeRanges, ',');
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderString.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderString.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderString.java
new file mode 100644
index 0000000..6e34304
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderString.java
@@ -0,0 +1,72 @@
+// ***************************************************************************************************************************
+// * 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 org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of a single string value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Accept-Ranges: bytes
+ * </p>
+ */
+public class HeaderString {
+
+	final String value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderString(String value) {
+		this.value = StringUtils.trim(value);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified value is the same using {@link String#equalsIgnoreCase(String)}.
+	 *
+	 * @param compare The value to compare against.
+	 * @return <jk>true</jk> if the specified value is the same.
+	 */
+	public boolean eqIC(String compare) {
+		return value.equalsIgnoreCase(compare);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified value is the same using {@link String#equals(Object)}.
+	 *
+	 * @param compare The value to compare against.
+	 * @return <jk>true</jk> if the specified value is the same.
+	 */
+	public boolean eq(String compare) {
+		return value.equals(compare);
+	}
+
+	/**
+	 * Returns this header as a simple string value.
+	 * <p>
+	 * Functionally equivalent to calling {@link #toString()}.
+	 *
+	 * @return This header as a simple string.
+	 */
+	public String asString() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return value == null ? "" : value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderStringArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderStringArray.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderStringArray.java
new file mode 100644
index 0000000..803cd66
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderStringArray.java
@@ -0,0 +1,80 @@
+// ***************************************************************************************************************************
+// * 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 org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of a comma-delimited list of string values.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Allow: GET, PUT
+ * </p>
+ */
+public class HeaderStringArray {
+
+	private final String[] value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderStringArray(String value) {
+		this.value = StringUtils.split(value, ',');
+	}
+
+	/**
+	 * Returns this header as a simple string value.
+	 * <p>
+	 * Functionally equivalent to calling {@link #toString()}.
+	 *
+	 * @return This header as a simple string.
+	 */
+	public String asString() {
+		return StringUtils.join(value, ',');
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this header contains the specified value.
+	 *
+	 * @param val The value to check for.
+	 * @return <jk>true</jk> if this header contains the specified value.
+	 */
+	public boolean contains(String val) {
+		if (val != null)
+			for (String v : value)
+				if (val.equals(v))
+					return true;
+		return false;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this header contains the specified value using {@link String#equalsIgnoreCase(String)}.
+	 *
+	 * @param val The value to check for.
+	 * @return <jk>true</jk> if this header contains the specified value.
+	 */
+	public boolean containsIC(String val) {
+		if (val != null)
+			for (String v : value)
+				if (val.equalsIgnoreCase(v))
+					return true;
+		return false;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return asString();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/HeaderUri.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/HeaderUri.java b/juneau-core/src/main/java/org/apache/juneau/http/HeaderUri.java
new file mode 100644
index 0000000..d38deb2
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/HeaderUri.java
@@ -0,0 +1,62 @@
+// ***************************************************************************************************************************
+// * 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.net.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Category of headers that consist of a single URL value.
+ * <p>
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Location: http://www.w3.org/pub/WWW/People.html
+ * </p>
+ */
+public class HeaderUri{
+
+	final String value;
+
+	/**
+	 * Constructor.
+	 * @param value The raw header value.
+	 */
+	protected HeaderUri(String value) {
+		this.value = StringUtils.trim(value);
+	}
+
+	/**
+	 * Returns this header as a {@link URI}.
+	 * @return This header as a {@link URI}.
+	 */
+	public URI asURI() {
+		return URI.create(toString());
+	}
+
+	/**
+	 * Returns this header as a simple string value.
+	 * <p>
+	 * Functionally equivalent to calling {@link #toString()}.
+	 *
+	 * @return This header as a simple string.
+	 */
+	public String asString() {
+		return value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return value == null ? "" : value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/fa4736b6/juneau-core/src/main/java/org/apache/juneau/http/Host.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/Host.java b/juneau-core/src/main/java/org/apache/juneau/http/Host.java
new file mode 100644
index 0000000..cefac84
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/Host.java
@@ -0,0 +1,75 @@
+// ***************************************************************************************************************************
+// * 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>Host</l> HTTP request header.
+ * <p>
+ * The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening.
+ * The port number may be omitted if the port is the standard port for the service requested.
+ * Mandatory since HTTP/1.1.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	Host: en.wikipedia.org:8080
+ * 	Host: en.wikipedia.org
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The Host request-header field specifies the Internet host and port number of the resource being requested, as
+ * obtained from the original URI given by the user or referring resource (generally an HTTP URL, as described in
+ * section 3.2.2).
+ * The Host field value MUST represent the naming authority of the origin server or gateway given by the original URL.
+ * This allows the origin server or gateway to differentiate between internally-ambiguous URLs, such as the root "/" URL
+ * of a server for multiple host names on a single IP address.
+ * <p class='bcode'>
+ * 	Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
+ * </p>
+ * <p>
+ * A "host" without any trailing port information implies the default port for the service requested (e.g., "80" for an
+ * HTTP URL).
+ * For example, a request on the origin server for <http://www.w3.org/pub/WWW/> would properly include:
+ * <p class='bcode'>
+ * 	GET /pub/WWW/ HTTP/1.1
+ * 	Host: www.w3.org
+ * </p>
+ * <p>
+ * A client MUST include a Host header field in all HTTP/1.1 request messages.
+ * If the requested URI does not include an Internet host name for the service being requested, then the Host header
+ * field MUST be given with an empty value.
+ * An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that
+ * identifies the service being requested by the proxy.
+ * All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request
+ * message which lacks a Host header field.
+ * <p>
+ * See sections 5.2 and 19.6.1.1 for other requirements relating to Host.
+ */
+public final class Host extends HeaderString {
+
+	/**
+	 * Returns a parsed <code>Host</code> header.
+	 *
+	 * @param value The <code>Host</code> header string.
+	 * @return The parsed <code>Host</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static Host forString(String value) {
+		if (value == null)
+			return null;
+		return new Host(value);
+	}
+
+	private Host(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/IfMatch.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/IfMatch.java b/juneau-core/src/main/java/org/apache/juneau/http/IfMatch.java
new file mode 100644
index 0000000..a4aab7f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/IfMatch.java
@@ -0,0 +1,90 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+/**
+ * Represents a parsed <l>If-Match</l> HTTP request header.
+ * <p>
+ * Only perform the action if the client supplied entity matches the same entity on the server.
+ * This is mainly for methods like PUT to only update a resource if it has not been modified since the user last
+ * updated it.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	If-Match: "737060cd8c284d8af7ad3082f209582d"
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The If-Match request-header field is used with a method to make it conditional.
+ * A client that has one or more entities previously obtained from the resource can verify that one of those entities
+ * is current by including a list of their associated entity tags in the If-Match header field.
+ * Entity tags are defined in section 3.11.
+ * The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction
+ * overhead.
+ * It is also used, on updating requests, to prevent inadvertent modification of the wrong version of a resource.
+ * As a special case, the value "*" matches any current entity of the resource.
+ * <p class='bcode'>
+ * 	If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
+ * </p>
+ * <p>
+ * If any of the entity tags match the entity tag of the entity that would have been returned in the response to a
+ * similar GET request (without the If-Match header) on that resource, or if "*" is given and any current entity exists
+ * for that resource, then the server MAY perform the requested method as if the If-Match header field did not exist.
+ * <p>
+ * A server MUST use the strong comparison function (see section 13.3.3) to compare the entity tags in If-Match.
+ * <p>
+ * If none of the entity tags match, or if "*" is given and no current entity exists, the server MUST NOT perform the
+ * requested method, and MUST return a 412 (Precondition Failed) response.
+ * This behavior is most useful when the client wants to prevent an updating method, such as PUT, from modifying a
+ * resource that has changed since the client last retrieved it.
+ * <p>
+ * If the request would, without the If-Match header field, result in anything other than a 2xx or 412 status, then the
+ * If-Match header MUST be ignored.
+ * <p>
+ * The meaning of "If-Match: *" is that the method SHOULD be performed if the representation selected by the origin
+ * server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and MUST NOT be performed if the
+ * representation does not exist.
+ * <p>
+ * A request intended to update a resource (e.g., a PUT) MAY include an If-Match header field to signal that the request
+ * method MUST NOT be applied if the entity corresponding to the If-Match value (a single entity tag) is no longer a
+ * representation of that resource.
+ * This allows the user to indicate that they do not wish the request to be successful if the resource has been changed
+ * without their knowledge.
+ * Examples:
+ * <p class='bcode'>
+ * 	If-Match: "xyzzy"
+ * 	If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ * 	If-Match: *
+ * </p>
+ * The result of a request having both an If-Match header field and either an If-None-Match or an If-Modified-Since
+ * header fields is undefined by this specification.
+ */
+public final class IfMatch extends HeaderEntityValidatorArray {
+
+	/**
+	 * Returns a parsed <code>If-Match</code> header.
+	 *
+	 * @param value The <code>If-Match</code> header string.
+	 * @return The parsed <code>If-Match</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static IfMatch forString(String value) {
+		if (value == null)
+			return null;
+		return new IfMatch(value);
+	}
+
+	private IfMatch(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/IfModifiedSince.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/IfModifiedSince.java b/juneau-core/src/main/java/org/apache/juneau/http/IfModifiedSince.java
new file mode 100644
index 0000000..28f1ef4
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/http/IfModifiedSince.java
@@ -0,0 +1,92 @@
+// ***************************************************************************************************************************
+// * 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>If-Modified-Since</l> HTTP request header.
+ * <p>
+ * Allows a 304 Not Modified to be returned if content is unchanged.
+ *
+ * <h6 class='figure'>Example</h6>
+ * <p class='bcode'>
+ * 	If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+ * </p>
+ *
+ * <h6 class='topic'>RFC2616 Specification</h6>
+ *
+ * The If-Modified-Since request-header field is used with a method to make it conditional:
+ * if the requested variant has not been modified since the time specified in this field, an entity will not be returned
+ * from the server; instead, a 304 (not modified) response will be returned without any message-body.
+ * <p class='bcode'>
+ * 	If-Modified-Since = "If-Modified-Since" ":" HTTP-date
+ * </p>
+ * <p>
+ * An example of the field is:
+ * <p class='bcode'>
+ * 	If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+ * </p>
+ * <p>
+ * A GET method with an If-Modified-Since header and no Range header requests that the identified entity be transferred
+ * only if it has been modified since the date given by the If-Modified-Since header.
+ * The algorithm for determining this includes the following cases:
+ * <ol>
+ * 	<li>If the request would normally result in anything other than a 200 (OK) status, or if the passed
+ * 		If-Modified-Since date is invalid, the response is exactly the same as for a normal GET.
+ * 		A date which is later than the server's current time is invalid.
+ * 	<li>If the variant has been modified since the If-Modified-Since date, the response is exactly the same as for a
+ * 		normal GET.
+ * 	<li>If the variant has not been modified since a valid If-Modified-Since date, the server SHOULD return a 304
+ * 		(Not Modified) response.
+ * </ol>
+ * The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction
+ * overhead.
+ * <p>
+ * Note: The Range request-header field modifies the meaning of If-Modified-Since; see section 14.35 for full details.
+ * <p>
+ * Note: If-Modified-Since times are interpreted by the server, whose clock might not be synchronized with the client.
+ * <p>
+ * Note: When handling an If-Modified-Since header field, some servers will use an exact date comparison function,
+ * rather than a less-than function, for deciding whether to send a 304 (Not Modified) response.
+ * To get best results when sending an If-Modified-Since header field for cache validation, clients are
+ * advised to use the exact date string received in a previous Last-Modified header field whenever possible.
+ * <p>
+ * Note: If a client uses an arbitrary date in the If-Modified-Since header instead of a date taken from the
+ * Last-Modified header for the same request, the client should be aware of the fact that this date is interpreted in
+ * the server's understanding of time.
+ * The client should consider unsynchronized clocks and rounding problems due to the different encodings of time between
+ * the client and server.
+ * This includes the possibility of race conditions if the document has changed between the time it was first requested
+ * and the If-Modified-Since date of a subsequent request, and the possibility of clock-skew-related problems if the
+ * If-Modified-Since date is derived from the client's clock without correction to the server's clock.
+ * Corrections for different time bases between client and server are at best approximate due to network latency.
+ * The result of a request having both an If-Modified-Since header field and either an If-Match or an
+ * If-Unmodified-Since header fields is undefined by this specification.
+ */
+public final class IfModifiedSince extends HeaderDate {
+
+	/**
+	 * Returns a parsed <code>If-Modified-Since</code> header.
+	 *
+	 * @param value The <code>If-Modified-Since</code> header string.
+	 * @return The parsed <code>If-Modified-Since</code> header, or <jk>null</jk> if the string was null.
+	 */
+	public static IfModifiedSince forString(String value) {
+		if (value == null)
+			return null;
+		return new IfModifiedSince(value);
+	}
+
+	private IfModifiedSince(String value) {
+		super(value);
+	}
+}