View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.auth;
28  
29  import java.util.Locale;
30  
31  import org.apache.http.HttpHost;
32  import org.apache.http.annotation.Immutable;
33  import org.apache.http.util.Args;
34  import org.apache.http.util.LangUtils;
35  
36  /**
37   * {@code AuthScope} represents an authentication scope consisting of a host name,
38   * a port number, a realm name and an authentication scheme name.
39   * <p>
40   * This class can also optionally contain a host of origin, if created in response
41   * to authentication challenge from a specific host.
42   * </p>
43   * @since 4.0
44   */
45  @Immutable
46  public class AuthScope {
47  
48      /**
49       * The {@code null} value represents any host. In the future versions of
50       * HttpClient the use of this parameter will be discontinued.
51       */
52      public static final String ANY_HOST = null;
53  
54      /**
55       * The {@code -1} value represents any port.
56       */
57      public static final int ANY_PORT = -1;
58  
59      /**
60       * The {@code null} value represents any realm.
61       */
62      public static final String ANY_REALM = null;
63  
64      /**
65       * The {@code null} value represents any authentication scheme.
66       */
67      public static final String ANY_SCHEME = null;
68  
69      /**
70       * Default scope matching any host, port, realm and authentication scheme.
71       * In the future versions of HttpClient the use of this parameter will be
72       * discontinued.
73       */
74      public static final AuthScope ANY = new AuthScope(ANY_HOST, ANY_PORT, ANY_REALM, ANY_SCHEME);
75  
76      /** The authentication scheme the credentials apply to. */
77      private final String scheme;
78  
79      /** The realm the credentials apply to. */
80      private final String realm;
81  
82      /** The host the credentials apply to. */
83      private final String host;
84  
85      /** The port the credentials apply to. */
86      private final int port;
87  
88      /** The original host, if known */
89      private final HttpHost origin;
90  
91      /**
92       * Defines auth scope with the given {@code host}, {@code port}, {@code realm}, and
93       * {@code schemeName}.
94       *
95       * @param host authentication host. May be {@link #ANY_HOST} if applies
96       *   to any host.
97       * @param port authentication port. May be {@link #ANY_PORT} if applies
98       *   to any port of the host.
99       * @param realm authentication realm. May be {@link #ANY_REALM} if applies
100      *   to any realm on the host.
101      * @param schemeName authentication scheme. May be {@link #ANY_SCHEME} if applies
102      *   to any scheme supported by the host.
103      */
104     public AuthScope(
105             final String host,
106             final int port,
107             final String realm,
108             final String schemeName) {
109         this.host = host == null ? ANY_HOST: host.toLowerCase(Locale.ROOT);
110         this.port = port < 0 ? ANY_PORT : port;
111         this.realm = realm == null ? ANY_REALM : realm;
112         this.scheme = schemeName == null ? ANY_SCHEME : schemeName.toUpperCase(Locale.ROOT);
113         this.origin = null;
114     }
115 
116     /**
117      * Defines auth scope for a specific host of origin.
118      *
119      * @param origin host of origin
120      * @param realm authentication realm. May be {@link #ANY_REALM} if applies
121      *   to any realm on the host.
122      * @param schemeName authentication scheme. May be {@link #ANY_SCHEME} if applies
123      *   to any scheme supported by the host.
124      *
125      * @since 4.2
126      */
127     public AuthScope(
128             final HttpHost origin,
129             final String realm,
130             final String schemeName) {
131         Args.notNull(origin, "Host");
132         this.host = origin.getHostName();
133         this.port = origin.getPort() < 0 ? ANY_PORT : origin.getPort();
134         this.realm = realm == null ? ANY_REALM : realm;
135         this.scheme = schemeName == null ? ANY_SCHEME : schemeName.toUpperCase(Locale.ROOT);
136         this.origin = origin;
137     }
138 
139     /**
140      * Defines auth scope for a specific host of origin.
141      *
142      * @param origin host of origin
143      *
144      * @since 4.2
145      */
146     public AuthScope(final HttpHost origin) {
147         this(origin, ANY_REALM, ANY_SCHEME);
148     }
149 
150     /**
151      * Defines auth scope with the given {@code host}, {@code port} and {@code realm}.
152      *
153      * @param host authentication host. May be {@link #ANY_HOST} if applies
154      *   to any host.
155      * @param port authentication port. May be {@link #ANY_PORT} if applies
156      *   to any port of the host.
157      * @param realm authentication realm. May be {@link #ANY_REALM} if applies
158      *   to any realm on the host.
159      */
160     public AuthScope(final String host, final int port, final String realm) {
161         this(host, port, realm, ANY_SCHEME);
162     }
163 
164     /**
165      * Defines auth scope with the given {@code host} and {@code port}.
166      *
167      * @param host authentication host. May be {@link #ANY_HOST} if applies
168      *   to any host.
169      * @param port authentication port. May be {@link #ANY_PORT} if applies
170      *   to any port of the host.
171      */
172     public AuthScope(final String host, final int port) {
173         this(host, port, ANY_REALM, ANY_SCHEME);
174     }
175 
176     /**
177      * Creates a copy of the given credentials scope.
178      */
179     public AuthScope(final AuthScope authscope) {
180         super();
181         Args.notNull(authscope, "Scope");
182         this.host = authscope.getHost();
183         this.port = authscope.getPort();
184         this.realm = authscope.getRealm();
185         this.scheme = authscope.getScheme();
186         this.origin = authscope.getOrigin();
187     }
188 
189     /**
190      * @return host of origin. If unknown returns @null,
191      *
192      * @since 4.4
193      */
194     public HttpHost getOrigin() {
195         return this.origin;
196     }
197 
198     /**
199      * @return the host
200      */
201     public String getHost() {
202         return this.host;
203     }
204 
205     /**
206      * @return the port
207      */
208     public int getPort() {
209         return this.port;
210     }
211 
212     /**
213      * @return the realm name
214      */
215     public String getRealm() {
216         return this.realm;
217     }
218 
219     /**
220      * @return the scheme type
221      */
222     public String getScheme() {
223         return this.scheme;
224     }
225 
226     /**
227      * Tests if the authentication scopes match.
228      *
229      * @return the match factor. Negative value signifies no match.
230      *    Non-negative signifies a match. The greater the returned value
231      *    the closer the match.
232      */
233     public int match(final AuthScope that) {
234         int factor = 0;
235         if (LangUtils.equals(this.scheme, that.scheme)) {
236             factor += 1;
237         } else {
238             if (this.scheme != ANY_SCHEME && that.scheme != ANY_SCHEME) {
239                 return -1;
240             }
241         }
242         if (LangUtils.equals(this.realm, that.realm)) {
243             factor += 2;
244         } else {
245             if (this.realm != ANY_REALM && that.realm != ANY_REALM) {
246                 return -1;
247             }
248         }
249         if (this.port == that.port) {
250             factor += 4;
251         } else {
252             if (this.port != ANY_PORT && that.port != ANY_PORT) {
253                 return -1;
254             }
255         }
256         if (LangUtils.equals(this.host, that.host)) {
257             factor += 8;
258         } else {
259             if (this.host != ANY_HOST && that.host != ANY_HOST) {
260                 return -1;
261             }
262         }
263         return factor;
264     }
265 
266     /**
267      * @see java.lang.Object#equals(Object)
268      */
269     @Override
270     public boolean equals(final Object o) {
271         if (o == null) {
272             return false;
273         }
274         if (o == this) {
275             return true;
276         }
277         if (!(o instanceof AuthScope)) {
278             return super.equals(o);
279         }
280         final AuthScope that = (AuthScope) o;
281         return
282         LangUtils.equals(this.host, that.host)
283           && this.port == that.port
284           && LangUtils.equals(this.realm, that.realm)
285           && LangUtils.equals(this.scheme, that.scheme);
286     }
287 
288     /**
289      * @see java.lang.Object#toString()
290      */
291     @Override
292     public String toString() {
293         final StringBuilder buffer = new StringBuilder();
294         if (this.scheme != null) {
295             buffer.append(this.scheme.toUpperCase(Locale.ROOT));
296             buffer.append(' ');
297         }
298         if (this.realm != null) {
299             buffer.append('\'');
300             buffer.append(this.realm);
301             buffer.append('\'');
302         } else {
303             buffer.append("<any realm>");
304         }
305         if (this.host != null) {
306             buffer.append('@');
307             buffer.append(this.host);
308             if (this.port >= 0) {
309                 buffer.append(':');
310                 buffer.append(this.port);
311             }
312         }
313         return buffer.toString();
314     }
315 
316     /**
317      * @see java.lang.Object#hashCode()
318      */
319     @Override
320     public int hashCode() {
321         int hash = LangUtils.HASH_SEED;
322         hash = LangUtils.hashCode(hash, this.host);
323         hash = LangUtils.hashCode(hash, this.port);
324         hash = LangUtils.hashCode(hash, this.realm);
325         hash = LangUtils.hashCode(hash, this.scheme);
326         return hash;
327     }
328 }