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 AuthScopepe.html#AuthScope">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 AuthScopehScope.html#AuthScope">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./../../../org/apache/http/auth/AuthScope.html#AuthScope">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 }