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