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