Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
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 */
28 package ch.boye.httpclientandroidlib.impl.client;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
38 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
39 /* LogFactory removed by HttpClient for Android script. */
40 import ch.boye.httpclientandroidlib.FormattedHeader;
41 import ch.boye.httpclientandroidlib.Header;
42 import ch.boye.httpclientandroidlib.HttpResponse;
43 import ch.boye.httpclientandroidlib.annotation.Immutable;
44 import ch.boye.httpclientandroidlib.auth.AuthScheme;
45 import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
46 import ch.boye.httpclientandroidlib.auth.AuthenticationException;
47 import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
48 import ch.boye.httpclientandroidlib.client.AuthenticationHandler;
49 import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
50 import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
51 import ch.boye.httpclientandroidlib.protocol.HTTP;
52 import ch.boye.httpclientandroidlib.protocol.HttpContext;
53 import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
55 /**
56 * Base class for {@link AuthenticationHandler} implementations.
57 *
58 * @since 4.0
59 */
60 @Immutable
61 public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {
63 public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
65 private static final List<String> DEFAULT_SCHEME_PRIORITY =
66 Collections.unmodifiableList(Arrays.asList(new String[] {
67 AuthPolicy.SPNEGO,
68 AuthPolicy.NTLM,
69 AuthPolicy.DIGEST,
70 AuthPolicy.BASIC
71 }));
73 public AbstractAuthenticationHandler() {
74 super();
75 }
77 protected Map<String, Header> parseChallenges(
78 final Header[] headers) throws MalformedChallengeException {
80 Map<String, Header> map = new HashMap<String, Header>(headers.length);
81 for (Header header : headers) {
82 CharArrayBuffer buffer;
83 int pos;
84 if (header instanceof FormattedHeader) {
85 buffer = ((FormattedHeader) header).getBuffer();
86 pos = ((FormattedHeader) header).getValuePos();
87 } else {
88 String s = header.getValue();
89 if (s == null) {
90 throw new MalformedChallengeException("Header value is null");
91 }
92 buffer = new CharArrayBuffer(s.length());
93 buffer.append(s);
94 pos = 0;
95 }
96 while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
97 pos++;
98 }
99 int beginIndex = pos;
100 while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
101 pos++;
102 }
103 int endIndex = pos;
104 String s = buffer.substring(beginIndex, endIndex);
105 map.put(s.toLowerCase(Locale.ENGLISH), header);
106 }
107 return map;
108 }
110 /**
111 * Returns default list of auth scheme names in their order of preference.
112 *
113 * @return list of auth scheme names
114 */
115 protected List<String> getAuthPreferences() {
116 return DEFAULT_SCHEME_PRIORITY;
117 }
119 /**
120 * Returns default list of auth scheme names in their order of preference
121 * based on the HTTP response and the current execution context.
122 *
123 * @param response HTTP response.
124 * @param context HTTP execution context.
125 *
126 * @since 4.1
127 */
128 protected List<String> getAuthPreferences(
129 final HttpResponse response,
130 final HttpContext context) {
131 return getAuthPreferences();
132 }
134 public AuthScheme selectScheme(
135 final Map<String, Header> challenges,
136 final HttpResponse response,
137 final HttpContext context) throws AuthenticationException {
139 AuthSchemeRegistry registry = (AuthSchemeRegistry) context.getAttribute(
140 ClientContext.AUTHSCHEME_REGISTRY);
141 if (registry == null) {
142 throw new IllegalStateException("AuthScheme registry not set in HTTP context");
143 }
145 Collection<String> authPrefs = getAuthPreferences(response, context);
146 if (authPrefs == null) {
147 authPrefs = DEFAULT_SCHEME_PRIORITY;
148 }
150 if (this.log.isDebugEnabled()) {
151 this.log.debug("Authentication schemes in the order of preference: "
152 + authPrefs);
153 }
155 AuthScheme authScheme = null;
156 for (String id: authPrefs) {
157 Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
159 if (challenge != null) {
160 if (this.log.isDebugEnabled()) {
161 this.log.debug(id + " authentication scheme selected");
162 }
163 try {
164 authScheme = registry.getAuthScheme(id, response.getParams());
165 break;
166 } catch (IllegalStateException e) {
167 if (this.log.isWarnEnabled()) {
168 this.log.warn("Authentication scheme " + id + " not supported");
169 // Try again
170 }
171 }
172 } else {
173 if (this.log.isDebugEnabled()) {
174 this.log.debug("Challenge for " + id + " authentication scheme not available");
175 // Try again
176 }
177 }
178 }
179 if (authScheme == null) {
180 // If none selected, something is wrong
181 throw new AuthenticationException(
182 "Unable to respond to any of these challenges: "
183 + challenges);
184 }
185 return authScheme;
186 }
188 }