28 import java.net.URL; |
28 import java.net.URL; |
29 import java.io.IOException; |
29 import java.io.IOException; |
30 import java.net.Authenticator.RequestorType; |
30 import java.net.Authenticator.RequestorType; |
31 import java.util.Base64; |
31 import java.util.Base64; |
32 import java.util.HashMap; |
32 import java.util.HashMap; |
|
33 import java.util.concurrent.locks.ReentrantLock; |
|
34 |
33 import sun.net.www.HeaderParser; |
35 import sun.net.www.HeaderParser; |
34 import sun.util.logging.PlatformLogger; |
36 import sun.util.logging.PlatformLogger; |
35 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; |
37 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; |
36 import static sun.net.www.protocol.http.AuthScheme.KERBEROS; |
38 import static sun.net.www.protocol.http.AuthScheme.KERBEROS; |
37 import sun.security.action.GetPropertyAction; |
39 import sun.security.action.GetPropertyAction; |
56 // <code>supported</code> is set when isSupported is checked, |
58 // <code>supported</code> is set when isSupported is checked, |
57 // if it's true, a cached Negotiator is put into <code>cache</code>. |
59 // if it's true, a cached Negotiator is put into <code>cache</code>. |
58 // the cache can be used only once, so after the first use, it's cleaned. |
60 // the cache can be used only once, so after the first use, it's cleaned. |
59 static HashMap <String, Boolean> supported = null; |
61 static HashMap <String, Boolean> supported = null; |
60 static ThreadLocal <HashMap <String, Negotiator>> cache = null; |
62 static ThreadLocal <HashMap <String, Negotiator>> cache = null; |
|
63 private static final ReentrantLock negotiateLock = new ReentrantLock(); |
|
64 |
61 /* Whether cache is enabled for Negotiate/Kerberos */ |
65 /* Whether cache is enabled for Negotiate/Kerberos */ |
62 private static final boolean cacheSPNEGO; |
66 private static final boolean cacheSPNEGO; |
63 static { |
67 static { |
64 String spnegoCacheProp = |
68 String spnegoCacheProp = |
65 GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true"); |
69 GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true"); |
124 * If this method is called for the second time on an HttpCallerInfo with |
128 * If this method is called for the second time on an HttpCallerInfo with |
125 * the same hostname, the answer is retrieved from cache. |
129 * the same hostname, the answer is retrieved from cache. |
126 * |
130 * |
127 * @return true if supported |
131 * @return true if supported |
128 */ |
132 */ |
129 private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) { |
133 private static boolean isSupportedImpl(HttpCallerInfo hci) { |
130 if (supported == null) { |
134 negotiateLock.lock(); |
131 supported = new HashMap<>(); |
135 try { |
132 } |
136 if (supported == null) { |
133 String hostname = hci.host; |
137 supported = new HashMap<>(); |
134 hostname = hostname.toLowerCase(); |
138 } |
135 if (supported.containsKey(hostname)) { |
139 String hostname = hci.host; |
136 return supported.get(hostname); |
140 hostname = hostname.toLowerCase(); |
137 } |
141 if (supported.containsKey(hostname)) { |
138 |
142 return supported.get(hostname); |
139 Negotiator neg = Negotiator.getNegotiator(hci); |
143 } |
140 if (neg != null) { |
144 |
141 supported.put(hostname, true); |
145 Negotiator neg = Negotiator.getNegotiator(hci); |
142 // the only place cache.put is called. here we can make sure |
146 if (neg != null) { |
143 // the object is valid and the oneToken inside is not null |
147 supported.put(hostname, true); |
144 if (cache == null) { |
148 // the only place cache.put is called. here we can make sure |
145 cache = new ThreadLocal<>() { |
149 // the object is valid and the oneToken inside is not null |
146 @Override |
150 if (cache == null) { |
147 protected HashMap<String, Negotiator> initialValue() { |
151 cache = new ThreadLocal<>() { |
148 return new HashMap<>(); |
152 @Override |
149 } |
153 protected HashMap<String, Negotiator> initialValue() { |
150 }; |
154 return new HashMap<>(); |
151 } |
155 } |
152 cache.get().put(hostname, neg); |
156 }; |
153 return true; |
157 } |
154 } else { |
158 cache.get().put(hostname, neg); |
155 supported.put(hostname, false); |
159 return true; |
156 return false; |
160 } else { |
157 } |
161 supported.put(hostname, false); |
158 } |
162 return false; |
159 |
163 } |
160 private static synchronized HashMap<String, Negotiator> getCache() { |
164 } finally { |
161 if (cache == null) return null; |
165 negotiateLock.unlock(); |
162 return cache.get(); |
166 } |
|
167 } |
|
168 |
|
169 private static HashMap<String, Negotiator> getCache() { |
|
170 negotiateLock.lock(); |
|
171 try { |
|
172 if (cache == null) return null; |
|
173 return cache.get(); |
|
174 } finally { |
|
175 negotiateLock.unlock(); |
|
176 } |
163 } |
177 } |
164 |
178 |
165 @Override |
179 @Override |
166 protected boolean useAuthCache() { |
180 protected boolean useAuthCache() { |
167 return super.useAuthCache() && cacheSPNEGO; |
181 return super.useAuthCache() && cacheSPNEGO; |
195 * HeaderParser converts the fields to lower case, use raw instead |
209 * HeaderParser converts the fields to lower case, use raw instead |
196 * @param raw The raw header field. |
210 * @param raw The raw header field. |
197 * @return true if all goes well, false if no headers were set. |
211 * @return true if all goes well, false if no headers were set. |
198 */ |
212 */ |
199 @Override |
213 @Override |
200 public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { |
214 public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { |
201 |
215 |
202 try { |
216 try { |
203 String response; |
217 String response; |
204 byte[] incoming = null; |
218 byte[] incoming = null; |
205 String[] parts = raw.split("\\s+"); |
219 String[] parts = raw.split("\\s+"); |