Source Code Cross Referenced for AuthenticationInfo.java in  » 6.0-JDK-Modules » j2me » sun » net » www » protocol » http » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » sun.net.www.protocol.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)AuthenticationInfo.java	1.30 06/10/10
003:         *
004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
006:         *   
007:         * This program is free software; you can redistribute it and/or  
008:         * modify it under the terms of the GNU General Public License version  
009:         * 2 only, as published by the Free Software Foundation.   
010:         *   
011:         * This program is distributed in the hope that it will be useful, but  
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
014:         * General Public License version 2 for more details (a copy is  
015:         * included at /legal/license.txt).   
016:         *   
017:         * You should have received a copy of the GNU General Public License  
018:         * version 2 along with this work; if not, write to the Free Software  
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
020:         * 02110-1301 USA   
021:         *   
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
024:         * information or have any questions. 
025:         *
026:         */
027:
028:        package sun.net.www.protocol.http;
029:
030:        import java.io.IOException;
031:        import java.net.URL;
032:        import java.util.Hashtable;
033:        import java.util.LinkedList;
034:        import java.util.ListIterator;
035:        import java.util.Enumeration;
036:        import java.util.HashMap;
037:
038:        import sun.net.www.HeaderParser;
039:
040:        /**
041:         * AuthenticationInfo: Encapsulate the information needed to
042:         * authenticate a user to a server.
043:         *
044:         * @version 1.19, 11/06/00 
045:         */
046:        //	It would be nice if this class understood about partial matching.
047:        //	If you're authorized for foo.com, chances are high you're also
048:        //	authorized for baz.foo.com.
049:        // NB:  When this gets implemented, be careful about the uncaching
050:        //	policy in HttpURLConnection.  A failure on baz.foo.com shouldn't
051:        //	uncache foo.com!
052:        abstract class AuthenticationInfo implements  Cloneable {
053:
054:            // Constants saying what kind of authroization this is.  This determines
055:            // the namespace in the hash table lookup.
056:            static final char SERVER_AUTHENTICATION = 's';
057:            static final char PROXY_AUTHENTICATION = 'p';
058:
059:            /**
060:             * Caches authentication info entered by user.  See cacheKey()
061:             */
062:            static private PathMap cache = new PathMap();
063:
064:            /** 
065:             * If true, then simultaneous authentication requests to the same realm/proxy
066:             * are serialized, in order to avoid a user having to type the same username/passwords
067:             * repeatedly, via the Authenticator. Default is false, which means that this
068:             * behavior is switched off.
069:             */
070:            static boolean serializeAuth;
071:
072:            static {
073:                serializeAuth = ((Boolean) java.security.AccessController
074:                        .doPrivileged(new sun.security.action.GetBooleanAction(
075:                                "http.auth.serializeRequests"))).booleanValue();
076:            }
077:
078:            /**
079:             * requests is used to ensure that interaction with the
080:             * Authenticator for a particular realm is single threaded.
081:             * ie. if multiple threads need to get credentials from the user
082:             * at the same time, then all but the first will block until
083:             * the first completes its authentication.
084:             */
085:            static private HashMap requests = new HashMap();
086:
087:            /* check if a request for this destination is in progress
088:             * return false immediately if not. Otherwise block until
089:             * request is finished and return true
090:             */
091:            static private boolean requestIsInProgress(String key) {
092:                if (!serializeAuth) {
093:                    /* behavior is disabled. Revert to concurrent requests */
094:                    return false;
095:                }
096:                synchronized (requests) {
097:                    Thread t, c;
098:                    c = Thread.currentThread();
099:                    if ((t = (Thread) requests.get(key)) == null) {
100:                        requests.put(key, c);
101:                        return false;
102:                    }
103:                    if (t == c) {
104:                        return false;
105:                    }
106:                    while (requests.containsKey(key)) {
107:                        try {
108:                            requests.wait();
109:                        } catch (InterruptedException e) {
110:                        }
111:                    }
112:                }
113:                /* entry may be in cache now. */
114:                return true;
115:            }
116:
117:            /* signal completion of an authentication (whether it succeeded or not) 
118:             * so that other threads can continue. 
119:             */
120:            static private void requestCompleted(String key) {
121:                synchronized (requests) {
122:                    boolean waspresent = requests.remove(key) != null;
123:                    // Uncomment this line if assertions are always
124:                    //    turned on for libraries
125:                    //assert waspresent;
126:                    requests.notifyAll();
127:                }
128:            }
129:
130:            static void printCache() {
131:                cache.print();
132:            }
133:
134:            //public String toString () {
135:            //return ("{"+type+":"+authType+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
136:            //}
137:
138:            // TODO:  This cache just grows forever.  We should put in a bounded
139:            //	      cache, or maybe something using WeakRef's.
140:
141:            /** The type (server/proxy) of authentication this is.  Used for key lookup */
142:            char type;
143:
144:            /** The authentication type (basic/digest). Also used for key lookup */
145:            char authType;
146:
147:            /** The protocol/scheme (i.e. http or https ). Need to keep the caches
148:             *  logically separate for the two protocols. This field is only used
149:             *  when constructed with a URL (the normal case for server authentication)
150:             *  For proxy authentication the protocol is not relevant.
151:             */
152:            String protocol;
153:
154:            /** The host we're authenticating against. */
155:            String host;
156:
157:            /** The port on the host we're authenticating against. */
158:            int port;
159:
160:            /** The realm we're authenticating against. */
161:            String realm;
162:
163:            /** The shortest path from the URL we authenticated against. */
164:            String path;
165:
166:            /** Use this constructor only for proxy entries */
167:            AuthenticationInfo(char type, char authType, String host, int port,
168:                    String realm) {
169:                this .type = type;
170:                this .authType = authType;
171:                this .protocol = "";
172:                this .host = host.toLowerCase();
173:                this .port = port;
174:                this .realm = realm;
175:                this .path = null;
176:            }
177:
178:            public Object clone() {
179:                try {
180:                    return super .clone();
181:                } catch (CloneNotSupportedException e) {
182:                    // Cannot happen because Cloneable implemented by AuthenticationInfo
183:                    return null;
184:                }
185:            }
186:
187:            /*
188:             * Constructor used to limit the authorization to the path within
189:             * the URL. Use this constructor for origin server entries.
190:             */
191:            AuthenticationInfo(char type, char authType, URL url, String realm) {
192:                this .type = type;
193:                this .authType = authType;
194:                this .protocol = url.getProtocol().toLowerCase();
195:                this .host = url.getHost().toLowerCase();
196:                this .port = url.getPort();
197:                if (this .port == -1) {
198:                    this .port = url.getDefaultPort();
199:                }
200:                this .realm = realm;
201:
202:                String urlPath = url.getPath();
203:                if (urlPath.length() == 0)
204:                    this .path = urlPath;
205:                else {
206:                    this .path = reducePath(urlPath);
207:                }
208:
209:            }
210:
211:            /*
212:             * reduce the path to the root of where we think the
213:             * authorization begins. This could get shorter as
214:             * the url is traversed up following a successful challenge.
215:             */
216:            static String reducePath(String urlPath) {
217:                int sepIndex = urlPath.lastIndexOf('/');
218:                int targetSuffixIndex = urlPath.lastIndexOf('.');
219:                if (sepIndex != -1)
220:                    if (sepIndex < targetSuffixIndex)
221:                        return urlPath.substring(0, sepIndex + 1);
222:                    else
223:                        return urlPath;
224:                else
225:                    return urlPath;
226:            }
227:
228:            /**
229:             * Returns info for the URL, for an HTTP server auth.  Used when we 
230:             * don't yet know the realm
231:             * (i.e. when we're preemptively setting the auth).
232:             */
233:            static AuthenticationInfo getServerAuth(URL url) {
234:                int port = url.getPort();
235:                if (port == -1) {
236:                    port = url.getDefaultPort();
237:                }
238:                String key = SERVER_AUTHENTICATION + ":"
239:                        + url.getProtocol().toLowerCase() + ":"
240:                        + url.getHost().toLowerCase() + ":" + port;
241:                return getAuth(key, url);
242:            }
243:
244:            /**
245:             * Returns info for the URL, for an HTTP server auth.  Used when we 
246:             * do know the realm (i.e. when we're responding to a challenge).
247:             * In this case we do not use the path because the protection space
248:             * is identified by the host:port:realm only
249:             */
250:            static AuthenticationInfo getServerAuth(URL url, String realm,
251:                    char atype) {
252:                int port = url.getPort();
253:                if (port == -1) {
254:                    port = url.getDefaultPort();
255:                }
256:                String key = SERVER_AUTHENTICATION + ":" + atype + ":"
257:                        + url.getProtocol().toLowerCase() + ":"
258:                        + url.getHost().toLowerCase() + ":" + port + ":"
259:                        + realm;
260:                AuthenticationInfo cached = getAuth(key, null);
261:                if ((cached == null) && requestIsInProgress(key)) {
262:                    /* check the cache again, it might contain an entry */
263:                    cached = getAuth(key, null);
264:                }
265:                return cached;
266:            }
267:
268:            /**
269:             * Return the AuthenticationInfo object from the cache if it's path is
270:             * a substring of the supplied URLs path.
271:             */
272:            static AuthenticationInfo getAuth(String key, URL url) {
273:                if (url == null) {
274:                    return cache.get(key, null);
275:                } else {
276:                    return cache.get(key, url.getPath());
277:                }
278:            }
279:
280:            /**
281:             * Returns a firewall authentication, for the given host/port.  Used
282:             * for preemptive header-setting. Note, the protocol field is always
283:             * blank for proxies.
284:             */
285:            static AuthenticationInfo getProxyAuth(String host, int port) {
286:                String key = PROXY_AUTHENTICATION + "::" + host.toLowerCase()
287:                        + ":" + port;
288:                AuthenticationInfo result = (AuthenticationInfo) cache.get(key,
289:                        null);
290:                return result;
291:            }
292:
293:            /**
294:             * Returns a firewall authentication, for the given host/port and realm.
295:             * Used in response to a challenge. Note, the protocol field is always
296:             * blank for proxies.
297:             */
298:            static AuthenticationInfo getProxyAuth(String host, int port,
299:                    String realm, char atype) {
300:                String key = PROXY_AUTHENTICATION + ":" + atype + "::"
301:                        + host.toLowerCase() + ":" + port + ":" + realm;
302:                AuthenticationInfo cached = cache.get(key, null);
303:                if ((cached == null) && requestIsInProgress(key)) {
304:                    /* check the cache again, it might contain an entry */
305:                    cached = cache.get(key, null);
306:                }
307:                return cached;
308:            }
309:
310:            /**
311:             * Add this authentication to the cache
312:             */
313:            void addToCache() {
314:                cache.put(cacheKey(true), this );
315:                if (supportsPreemptiveAuthorization()) {
316:                    cache.put(cacheKey(false), this );
317:                }
318:                endAuthRequest();
319:            }
320:
321:            void endAuthRequest() {
322:                if (!serializeAuth) {
323:                    return;
324:                }
325:                synchronized (requests) {
326:                    requestCompleted(cacheKey(true));
327:                }
328:            }
329:
330:            /**
331:             * Remove this authentication from the cache
332:             */
333:            void removeFromCache() {
334:                cache.remove(cacheKey(true), this );
335:                if (supportsPreemptiveAuthorization()) {
336:                    cache.remove(cacheKey(false), this );
337:                }
338:            }
339:
340:            /**
341:             * @return true if this authentication supports preemptive authorization
342:             */
343:            abstract boolean supportsPreemptiveAuthorization();
344:
345:            /**
346:             * @return the name of the HTTP header this authentication wants set.
347:             *		This is used for preemptive authorization.
348:             */
349:            abstract String getHeaderName();
350:
351:            /**
352:             * Calculates and returns the authentication header value based
353:             * on the stored authentication parameters. If the calculation does not depend
354:             * on the URL or the request method then these parameters are ignored.
355:             * @param url The URL
356:             * @param method The request method
357:             * @return the value of the HTTP header this authentication wants set.
358:             *		Used for preemptive authorization.
359:             */
360:            abstract String getHeaderValue(URL url, String method);
361:
362:            /**
363:             * Set header(s) on the given connection.  Subclasses must override
364:             * This will only be called for
365:             * definitive (i.e. non-preemptive) authorization.
366:             * @param conn The connection to apply the header(s) to
367:             * @param p A source of header values for this connection, if needed.
368:             * @param raw The raw header field (if needed)
369:             * @return true if all goes well, false if no headers were set.
370:             */
371:            abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p,
372:                    String raw);
373:
374:            /**
375:             * Check if the header indicates that the current auth. parameters are stale.
376:             * If so, then replace the relevant field with the new value
377:             * and return true. Otherwise return false.
378:             * returning true means the request can be retried with the same userid/password
379:             * returning false means we have to go back to the user to ask for a new
380:             * username password.
381:             */
382:            abstract boolean isAuthorizationStale(String header);
383:
384:            /**
385:             * Check for any expected authentication information in the response
386:             * from the server
387:             */
388:            abstract void checkResponse(String header, String method, URL url)
389:                    throws IOException;
390:
391:            /** 
392:             * Give a key for hash table lookups.
393:             * @param includeRealm if you want the realm considered.  Preemptively
394:             *		setting an authorization is done before the realm is known.
395:             */
396:            String cacheKey(boolean includeRealm) {
397:                // This must be kept in sync with the getXXXAuth() methods in this
398:                // class.
399:                if (includeRealm) {
400:                    return type + ":" + authType + ":" + protocol + ":" + host
401:                            + ":" + port + ":" + realm;
402:                } else {
403:                    return type + ":" + protocol + ":" + host + ":" + port;
404:                }
405:            }
406:        }
407:
408:        /*
409:         * Pathmap stores AuthenticationInfo instances, which are keyed
410:         * by the combination of:
411:         *
412:         *  1) the protocol+host+port field of the URL where the resource is located
413:         *     plus optionally the name of the authentication realm.
414:         *
415:         *  2) the "known" abs_path root of the protection space. For digest
416:         *     authentication the root is generally known because it is returned
417:         *     explicitly by the server. For basic authentication, this is not the
418:         *     case and we start with the abs_path in the request. If a subsequent
419:         *     authentication succeeds for a path higher in the same hierarchy then
420:         *     the shorter pathname replaces the longer one.
421:         *
422:         *  If the scheme does not support pre-emptive authentication, then
423:         *  only one entry is created (per successful authentication), which 
424:         *  does not inlclude the realm in the primary 1) key. 
425:         *
426:         *  If the scheme does support pre-emptive authentication (which is the
427:         *  case for both basic and digest) then two entries are created for
428:         *  each successful authentication. One, with the realm and one without.
429:         *  The one without the realm is used for pre-emptive header setting
430:         *  because at this time the realm is not known.
431:         */
432:
433:        class PathMap {
434:            Hashtable hashtable;
435:
436:            PathMap() {
437:                hashtable = new Hashtable();
438:            }
439:
440:            // put a value in map according to primary key + secondary key which
441:            // is the path field of AuthenticationInfo
442:
443:            void print() {
444:                Enumeration keys = hashtable.keys();
445:                while (keys.hasMoreElements()) {
446:                    String key = (String) keys.nextElement();
447:                    LinkedList list = (LinkedList) (hashtable.get(key));
448:                    System.out.print("pkey = " + key + " ");
449:                    ListIterator iter = list.listIterator();
450:                    while (iter.hasNext()) {
451:                        AuthenticationInfo inf = (AuthenticationInfo) iter
452:                                .next();
453:                        System.out.print(inf.path + " ");
454:                    }
455:                    System.out.println(" ");
456:                }
457:            }
458:
459:            synchronized void put(String pkey, AuthenticationInfo value) {
460:                LinkedList list = (LinkedList) hashtable.get(pkey);
461:                String skey = value.path;
462:                if (list == null) {
463:                    list = new LinkedList();
464:                    hashtable.put(pkey, list);
465:                }
466:                // Check if the path already exists or a super-set of it exists
467:                ListIterator iter = list.listIterator();
468:                while (iter.hasNext()) {
469:                    AuthenticationInfo inf = (AuthenticationInfo) iter.next();
470:                    if (inf.path == null || inf.path.startsWith(skey)) {
471:                        iter.remove();
472:                    }
473:                }
474:                iter.add(value);
475:            }
476:
477:            // get a value from map checking both primary
478:            // and secondary (urlpath) key
479:
480:            synchronized AuthenticationInfo get(String pkey, String skey) {
481:                LinkedList list = (LinkedList) hashtable.get(pkey);
482:                if (list == null || list.size() == 0) {
483:                    return null;
484:                }
485:                if (skey == null) {
486:                    // list should contain only one element
487:                    return (AuthenticationInfo) list.get(0);
488:                }
489:                ListIterator iter = list.listIterator();
490:                while (iter.hasNext()) {
491:                    AuthenticationInfo inf = (AuthenticationInfo) iter.next();
492:                    if (skey.startsWith(inf.path)) {
493:                        return inf;
494:                    }
495:                }
496:                return null;
497:            }
498:
499:            synchronized void remove(String pkey, AuthenticationInfo entry) {
500:                LinkedList list = (LinkedList) hashtable.get(pkey);
501:                if (list == null) {
502:                    return;
503:                }
504:                if (entry == null) {
505:                    list.clear();
506:                    return;
507:                }
508:                ListIterator iter = list.listIterator();
509:                while (iter.hasNext()) {
510:                    AuthenticationInfo inf = (AuthenticationInfo) iter.next();
511:                    if (entry.equals(inf)) {
512:                        iter.remove();
513:                    }
514:                }
515:            }
516:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.