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 * 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, final 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, final 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, final 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 Args.notNull(authscope, "Scope");
166 this.host = authscope.getHost();
167 this.port = authscope.getPort();
168 this.realm = authscope.getRealm();
169 this.scheme = authscope.getScheme();
170 }
171
172 /**
173 * @return the host
174 */
175 public String getHost() {
176 return this.host;
177 }
178
179 /**
180 * @return the port
181 */
182 public int getPort() {
183 return this.port;
184 }
185
186 /**
187 * @return the realm name
188 */
189 public String getRealm() {
190 return this.realm;
191 }
192
193 /**
194 * @return the scheme type
195 */
196 public String getScheme() {
197 return this.scheme;
198 }
199
200 /**
201 * Tests if the authentication scopes match.
202 *
203 * @return the match factor. Negative value signifies no match.
204 * Non-negative signifies a match. The greater the returned value
205 * the closer the match.
206 */
207 public int match(final AuthScope that) {
208 int factor = 0;
209 if (LangUtils.equals(this.scheme, that.scheme)) {
210 factor += 1;
211 } else {
212 if (this.scheme != ANY_SCHEME && that.scheme != ANY_SCHEME) {
213 return -1;
214 }
215 }
216 if (LangUtils.equals(this.realm, that.realm)) {
217 factor += 2;
218 } else {
219 if (this.realm != ANY_REALM && that.realm != ANY_REALM) {
220 return -1;
221 }
222 }
223 if (this.port == that.port) {
224 factor += 4;
225 } else {
226 if (this.port != ANY_PORT && that.port != ANY_PORT) {
227 return -1;
228 }
229 }
230 if (LangUtils.equals(this.host, that.host)) {
231 factor += 8;
232 } else {
233 if (this.host != ANY_HOST && that.host != ANY_HOST) {
234 return -1;
235 }
236 }
237 return factor;
238 }
239
240 /**
241 * @see java.lang.Object#equals(Object)
242 */
243 @Override
244 public boolean equals(final Object o) {
245 if (o == null) {
246 return false;
247 }
248 if (o == this) {
249 return true;
250 }
251 if (!(o instanceof AuthScope)) {
252 return super.equals(o);
253 }
254 final AuthScope that = (AuthScope) o;
255 return
256 LangUtils.equals(this.host, that.host)
257 && this.port == that.port
258 && LangUtils.equals(this.realm, that.realm)
259 && LangUtils.equals(this.scheme, that.scheme);
260 }
261
262 /**
263 * @see java.lang.Object#toString()
264 */
265 @Override
266 public String toString() {
267 final StringBuilder buffer = new StringBuilder();
268 if (this.scheme != null) {
269 buffer.append(this.scheme.toUpperCase(Locale.ENGLISH));
270 buffer.append(' ');
271 }
272 if (this.realm != null) {
273 buffer.append('\'');
274 buffer.append(this.realm);
275 buffer.append('\'');
276 } else {
277 buffer.append("<any realm>");
278 }
279 if (this.host != null) {
280 buffer.append('@');
281 buffer.append(this.host);
282 if (this.port >= 0) {
283 buffer.append(':');
284 buffer.append(this.port);
285 }
286 }
287 return buffer.toString();
288 }
289
290 /**
291 * @see java.lang.Object#hashCode()
292 */
293 @Override
294 public int hashCode() {
295 int hash = LangUtils.HASH_SEED;
296 hash = LangUtils.hashCode(hash, this.host);
297 hash = LangUtils.hashCode(hash, this.port);
298 hash = LangUtils.hashCode(hash, this.realm);
299 hash = LangUtils.hashCode(hash, this.scheme);
300 return hash;
301 }
302 }