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