Source Code Cross Referenced for SecurityAssociation.java in  » EJB-Server-JBoss-4.2.1 » security » org » jboss » security » 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 » EJB Server JBoss 4.2.1 » security » org.jboss.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JBoss, Home of Professional Open Source.
003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004:         * as indicated by the @author tags. See the copyright.txt file in the
005:         * distribution for a full listing of individual contributors.
006:         *
007:         * This is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU Lesser General Public License as
009:         * published by the Free Software Foundation; either version 2.1 of
010:         * the License, or (at your option) any later version.
011:         *
012:         * This software is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this software; if not, write to the Free
019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021:         */
022:        package org.jboss.security;
023:
024:        import java.security.Principal;
025:        import java.util.ArrayList;
026:        import java.util.HashMap;
027:        import javax.security.auth.Subject;
028:
029:        import org.jboss.logging.Logger;
030:
031:        /**
032:         * The SecurityAssociation class maintains the security principal and
033:         * credentials. This can be done on either a singleton basis or a thread local
034:         * basis depending on the server property. When the server property has been set
035:         * to true, the security information is maintained in thread local storage. The
036:         * type of thread local storage depends on the org.jboss.security.SecurityAssociation.ThreadLocal
037:         * property. If this property is true, then the thread local storage object is
038:         * of type java.lang.ThreadLocal which results in the current thread's security
039:         * information NOT being propagated to child threads.
040:         *
041:         * When the property is false or does not exist, the thread local storage object
042:         * is of type java.lang.InheritableThreadLocal, and any threads spawned by the
043:         * current thread will inherit the security information of the current thread.
044:         * Subseqent changes to the current thread's security information are NOT
045:         * propagated to any previously spawned child threads.
046:         *
047:         * When the server property is false, security information is maintained in
048:         * class variables which makes the information available to all threads within
049:         * the current VM.
050:         * 
051:         * Note that this is not a public API class. Its an implementation detail that
052:         * is subject to change without notice.
053:         * 
054:         * @author Daniel O'Connor (docodan@nycap.rr.com)
055:         * @author Scott.Stark@jboss.org
056:         * @version $Revision: 57203 $
057:         */
058:        public final class SecurityAssociation {
059:            private static Logger log = Logger
060:                    .getLogger(SecurityAssociation.class);
061:            /**
062:             * A flag indicating if trace level logging should be performed
063:             */
064:            private static boolean trace;
065:            /**
066:             * A flag indicating if security information is global or thread local
067:             */
068:            private static boolean server;
069:            /**
070:             * The SecurityAssociation principal used when the server flag is false
071:             */
072:            private static Principal principal;
073:            /**
074:             * The SecurityAssociation credential used when the server flag is false
075:             */
076:            private static Object credential;
077:
078:            /**
079:             * The SecurityAssociation principal used when the server flag is true
080:             */
081:            private static ThreadLocal threadPrincipal;
082:            /**
083:             * The SecurityAssociation credential used when the server flag is true
084:             */
085:            private static ThreadLocal threadCredential;
086:            /**
087:             * The SecurityAssociation HashMap<String, Object>
088:             */
089:            private static ThreadLocal threadContextMap;
090:
091:            /**
092:             * Thread local stacks of run-as principal roles used to implement J2EE
093:             * run-as identity propagation
094:             */
095:            private static RunAsThreadLocalStack threadRunAsStacks;
096:            /**
097:             * Thread local stacks of authenticated subject used to control the current
098:             * caller security context
099:             */
100:            private static SubjectThreadLocalStack threadSubjectStacks;
101:
102:            /**
103:             * The permission required to access getPrincpal, getCredential
104:             */
105:            private static final RuntimePermission getPrincipalInfoPermission = new RuntimePermission(
106:                    "org.jboss.security.SecurityAssociation.getPrincipalInfo");
107:            /**
108:             * The permission required to access getSubject
109:             */
110:            private static final RuntimePermission getSubjectPermission = new RuntimePermission(
111:                    "org.jboss.security.SecurityAssociation.getSubject");
112:            /**
113:             * The permission required to access setPrincpal, setCredential, setSubject
114:             * pushSubjectContext, popSubjectContext
115:             */
116:            private static final RuntimePermission setPrincipalInfoPermission = new RuntimePermission(
117:                    "org.jboss.security.SecurityAssociation.setPrincipalInfo");
118:            /**
119:             * The permission required to access setServer
120:             */
121:            private static final RuntimePermission setServerPermission = new RuntimePermission(
122:                    "org.jboss.security.SecurityAssociation.setServer");
123:            /**
124:             * The permission required to access pushRunAsIdentity/popRunAsIdentity
125:             */
126:            private static final RuntimePermission setRunAsIdentity = new RuntimePermission(
127:                    "org.jboss.security.SecurityAssociation.setRunAsRole");
128:            /**
129:             * The permission required to get the current security context info
130:             */
131:            private static final RuntimePermission getContextInfo = new RuntimePermission(
132:                    "org.jboss.security.SecurityAssociation.accessContextInfo",
133:                    "get");
134:            /**
135:             * The permission required to set the current security context info
136:             */
137:            private static final RuntimePermission setContextInfo = new RuntimePermission(
138:                    "org.jboss.security.SecurityAssociation.accessContextInfo",
139:                    "set");
140:
141:            static {
142:                String flag = SecurityActions.getProperty(
143:                        "org.jboss.security.SecurityAssociation.ThreadLocal",
144:                        "false");
145:                boolean useThreadLocal = Boolean.valueOf(flag).booleanValue();
146:                log.debug("Using ThreadLocal: " + useThreadLocal);
147:
148:                trace = log.isTraceEnabled();
149:                if (useThreadLocal) {
150:                    threadPrincipal = new ThreadLocal();
151:                    threadCredential = new ThreadLocal();
152:                    threadContextMap = new ThreadLocal() {
153:                        protected Object initialValue() {
154:                            return new HashMap();
155:                        }
156:                    };
157:                } else {
158:                    threadPrincipal = new InheritableThreadLocal();
159:                    threadCredential = new InheritableThreadLocal();
160:                    threadContextMap = new HashMapInheritableLocal();
161:                }
162:                threadRunAsStacks = new RunAsThreadLocalStack(useThreadLocal);
163:                threadSubjectStacks = new SubjectThreadLocalStack(
164:                        useThreadLocal);
165:            }
166:
167:            /**
168:             * Get the current authentication principal information. If a security
169:             * manager is present, then this method calls the security manager's
170:             * <code>checkPermission</code> method with a
171:             * <code>RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
172:             * </code> permission to ensure it's ok to access principal information. If
173:             * not, a <code>SecurityException</code> will be thrown.
174:             * @return Principal, the current principal identity.
175:             */
176:            public static Principal getPrincipal() {
177:                SecurityManager sm = System.getSecurityManager();
178:                if (sm != null)
179:                    sm.checkPermission(getPrincipalInfoPermission);
180:
181:                Principal thePrincipal = principal;
182:
183:                if (server)
184:                    thePrincipal = (Principal) threadPrincipal.get();
185:
186:                if (trace)
187:                    log.trace("getPrincipal, principal=" + thePrincipal);
188:
189:                return thePrincipal;
190:            }
191:
192:            /**
193:             * Get the caller's principal. If a security manager is present,
194:             * then this method calls the security manager's <code>checkPermission</code>
195:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
196:             * </code> permission to ensure it's ok to access principal information. If
197:             * not, a <code>SecurityException</code> will be thrown.
198:             * 
199:             * @return Principal, the current principal identity.
200:             */
201:            public static Principal getCallerPrincipal() {
202:                SecurityManager sm = System.getSecurityManager();
203:                if (sm != null)
204:                    sm.checkPermission(getPrincipalInfoPermission);
205:
206:                Principal thePrincipal = peekRunAsIdentity(1);
207:                if (thePrincipal == null) {
208:                    if (server)
209:                        thePrincipal = (Principal) threadPrincipal.get();
210:                    else
211:                        thePrincipal = principal;
212:                }
213:                if (trace)
214:                    log.trace("getCallerPrincipal, principal=" + thePrincipal);
215:                return thePrincipal;
216:            }
217:
218:            /**
219:             * Get the current authentication credential information. This can be of any type
220:             * including: a String password, a char[] password, an X509 cert, etc. If a
221:             * security manager is present, then this method calls the security manager's
222:             * <code>checkPermission</code> method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
223:             * </code> permission to ensure it's ok to access principal information. If
224:             * not, a <code>SecurityException</code> will be thrown.
225:             * @return Object, the credential that proves the principal identity.
226:             */
227:            public static Object getCredential() {
228:                SecurityManager sm = System.getSecurityManager();
229:                if (sm != null)
230:                    sm.checkPermission(getPrincipalInfoPermission);
231:
232:                if (server)
233:                    return threadCredential.get();
234:                else
235:                    return credential;
236:            }
237:
238:            /**
239:             * Get the current Subject information. If a security manager is present,
240:             * then this method calls the security manager's checkPermission method with
241:             * a  RuntimePermission("org.jboss.security.SecurityAssociation.getSubject")
242:             * permission to ensure it's ok to access principal information. If not, a
243:             * SecurityException will be thrown. Note that this method does not consider
244:             * whether or not a run-as identity exists. For access to this information
245:             * see the JACC PolicyContextHandler registered under the key
246:             * "javax.security.auth.Subject.container"
247:             * @return Subject, the current Subject identity.
248:             * @see javax.security.jacc.PolicyContext#getContext(String)
249:             */
250:            public static Subject getSubject() {
251:                SecurityManager sm = System.getSecurityManager();
252:                if (sm != null)
253:                    sm.checkPermission(getSubjectPermission);
254:
255:                SubjectContext sc = threadSubjectStacks.peek();
256:                if (trace)
257:                    log.trace("getSubject, sc=" + sc);
258:                Subject subject = null;
259:                if (sc != null)
260:                    subject = sc.getSubject();
261:                return subject;
262:            }
263:
264:            /**
265:             * Set the current principal information. If a security manager is present,
266:             * then this method calls the security manager's <code>checkPermission</code>
267:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
268:             * </code> permission to ensure it's ok to access principal information. If
269:             * not, a <code>SecurityException</code> will be thrown.
270:             * @param principal - the current principal identity.
271:             */
272:            public static void setPrincipal(Principal principal) {
273:                SecurityManager sm = System.getSecurityManager();
274:                if (sm != null)
275:                    sm.checkPermission(setPrincipalInfoPermission);
276:
277:                if (trace)
278:                    log.trace("setPrincipal, p=" + principal + ", server="
279:                            + server);
280:                if (server) {
281:                    threadPrincipal.set(principal);
282:                } else
283:                    SecurityAssociation.principal = principal;
284:                // Integrate with the new SubjectContext 
285:                SubjectContext sc = threadSubjectStacks.peek();
286:                if (sc == null) {
287:                    // There is no active security context
288:                    sc = new SubjectContext();
289:                    threadSubjectStacks.push(sc);
290:                } else if ((sc.getFlags() & SubjectContext.PRINCIPAL_WAS_SET) != 0) {
291:                    // The current security context has its principal set
292:                    sc = new SubjectContext();
293:                    threadSubjectStacks.push(sc);
294:                }
295:                sc.setPrincipal(principal);
296:                if (trace)
297:                    log.trace("setPrincipal, sc=" + sc);
298:            }
299:
300:            /**
301:             * Set the current principal credential information. This can be of any type
302:             * including: a String password, a char[] password, an X509 cert, etc.
303:             *
304:             * If a security manager is present, then this method calls the security
305:             * manager's <code>checkPermission</code> method with a <code>
306:             * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
307:             * </code> permission to ensure it's ok to access principal information. If
308:             * not, a <code>SecurityException</code> will be thrown.
309:             * @param credential - the credential that proves the principal identity.
310:             */
311:            public static void setCredential(Object credential) {
312:                SecurityManager sm = System.getSecurityManager();
313:                if (sm != null)
314:                    sm.checkPermission(setPrincipalInfoPermission);
315:
316:                if (server)
317:                    threadCredential.set(credential);
318:                else
319:                    SecurityAssociation.credential = credential;
320:                // Integrate with the new SubjectContext 
321:                SubjectContext sc = threadSubjectStacks.peek();
322:                if (sc == null) {
323:                    // There is no active security context
324:                    sc = new SubjectContext();
325:                    threadSubjectStacks.push(sc);
326:                } else if ((sc.getFlags() & SubjectContext.CREDENTIAL_WAS_SET) != 0) {
327:                    // The current security context has its principal set
328:                    sc = new SubjectContext();
329:                    threadSubjectStacks.push(sc);
330:                }
331:                sc.setCredential(credential);
332:                if (trace)
333:                    log.trace("setCredential, sc=" + sc);
334:            }
335:
336:            /**
337:             * Set the current Subject information. If a security manager is present,
338:             * then this method calls the security manager's <code>checkPermission</code>
339:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
340:             * </code> permission to ensure it's ok to access principal information. If
341:             * not, a <code>SecurityException</code> will be thrown.
342:             * @param subject - the current identity.
343:             */
344:            public static void setSubject(Subject subject) {
345:                SecurityManager sm = System.getSecurityManager();
346:                if (sm != null)
347:                    sm.checkPermission(setPrincipalInfoPermission);
348:
349:                if (trace)
350:                    log
351:                            .trace("setSubject, s=" + subject + ", server="
352:                                    + server);
353:                // Integrate with the new SubjectContext 
354:                SubjectContext sc = threadSubjectStacks.peek();
355:                if (sc == null) {
356:                    // There is no active security context
357:                    sc = new SubjectContext();
358:                    threadSubjectStacks.push(sc);
359:                } else if ((sc.getFlags() & SubjectContext.SUBJECT_WAS_SET) != 0) {
360:                    // The current security context has its subject set
361:                    sc = new SubjectContext();
362:                    threadSubjectStacks.push(sc);
363:                }
364:                sc.setSubject(subject);
365:                if (trace)
366:                    log.trace("setSubject, sc=" + sc);
367:            }
368:
369:            /**
370:             * Get the current thread context info. If a security manager is present,
371:             * then this method calls the security manager's <code>checkPermission</code>
372:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.accessContextInfo",
373:             * "get") </code> permission to ensure it's ok to access context information.
374:             * If not, a <code>SecurityException</code> will be thrown.
375:             * @param key - the context key
376:             * @return the mapping for the key in the current thread context
377:             */
378:            public static Object getContextInfo(Object key) {
379:                SecurityManager sm = System.getSecurityManager();
380:                if (sm != null)
381:                    sm.checkPermission(getContextInfo);
382:
383:                HashMap contextInfo = (HashMap) threadContextMap.get();
384:                return contextInfo.get(key);
385:            }
386:
387:            /**
388:             * Set the current thread context info. If a security manager is present,
389:             * then this method calls the security manager's <code>checkPermission</code>
390:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.accessContextInfo",
391:             * "set") </code> permission to ensure it's ok to access context information.
392:             * If not, a <code>SecurityException</code> will be thrown.
393:             * @param key - the context key
394:             * @param value - the context value to associate under key
395:             * @return the previous mapping for the key if one exists
396:             */
397:            public static Object setContextInfo(Object key, Object value) {
398:                SecurityManager sm = System.getSecurityManager();
399:                if (sm != null)
400:                    sm.checkPermission(setContextInfo);
401:
402:                HashMap contextInfo = (HashMap) threadContextMap.get();
403:                return contextInfo.put(key, value);
404:            }
405:
406:            /**
407:             * Push the current authenticated context. This sets the authenticated subject
408:             * along with the principal and proof of identity that was used to validate
409:             * the subject. This context is used for authorization checks. Typically
410:             * just the subject as seen by getSubject() is input into the authorization.
411:             * When run under a security manager this requires the
412:             * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
413:             * permission.
414:             * @param subject - the authenticated subject
415:             * @param principal - the principal that was input into the authentication
416:             * @param credential - the credential that was input into the authentication
417:             */
418:            public static void pushSubjectContext(Subject subject,
419:                    Principal principal, Object credential) {
420:                SecurityManager sm = System.getSecurityManager();
421:                if (sm != null)
422:                    sm.checkPermission(setPrincipalInfoPermission);
423:
424:                // Set the legacy single-value access points
425:                if (server) {
426:                    threadPrincipal.set(principal);
427:                    threadCredential.set(credential);
428:                } else {
429:                    SecurityAssociation.principal = principal;
430:                    SecurityAssociation.credential = credential;
431:                }
432:                // Push the subject context
433:                SubjectContext sc = new SubjectContext(subject, principal,
434:                        credential);
435:                threadSubjectStacks.push(sc);
436:                if (trace)
437:                    log.trace("pushSubjectContext, subject=" + subject
438:                            + ", sc=" + sc);
439:            }
440:
441:            /**
442:             * Push a duplicate of the current SubjectContext if one exists.
443:             * When run under a security manager this requires the
444:             * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
445:             * permission.
446:             */
447:            public static void dupSubjectContext() {
448:                SecurityManager sm = System.getSecurityManager();
449:                if (sm != null)
450:                    sm.checkPermission(setPrincipalInfoPermission);
451:
452:                SubjectContext sc = threadSubjectStacks.dup();
453:                if (trace)
454:                    log.trace("dupSubjectContext, sc=" + sc);
455:            }
456:
457:            /**
458:             * Pop the current SubjectContext from the previous pushSubjectContext call
459:             * and return the pushed SubjectContext ig there was one.
460:             * When run under a security manager this requires the
461:             * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
462:             * permission.
463:             * @return the SubjectContext pushed previously by a pushSubjectContext call
464:             */
465:            public static SubjectContext popSubjectContext() {
466:                SecurityManager sm = System.getSecurityManager();
467:                if (sm != null)
468:                    sm.checkPermission(setPrincipalInfoPermission);
469:
470:                SubjectContext sc = threadSubjectStacks.pop();
471:                if (trace) {
472:                    log.trace("popSubjectContext, sc=" + sc);
473:                }
474:
475:                Principal principal = null;
476:                Object credential = null;
477:
478:                SubjectContext top = threadSubjectStacks.peek();
479:
480:                if (top != null) {
481:                    principal = top.getPrincipal();
482:                    credential = top.getCredential();
483:                }
484:
485:                if (server) {
486:                    threadPrincipal.set(principal);
487:                    threadCredential.set(credential);
488:                } else {
489:                    SecurityAssociation.principal = principal;
490:                    SecurityAssociation.credential = credential;
491:                }
492:
493:                return sc;
494:            }
495:
496:            /**
497:             * Look at the current thread of control's authenticated identity on the top
498:             * of the stack.
499:             * When run under a security manager this requires the
500:             * RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
501:             * permission.
502:             * @return the SubjectContext pushed previously by a pushSubjectContext call
503:             */
504:            public static SubjectContext peekSubjectContext() {
505:                SecurityManager sm = System.getSecurityManager();
506:                if (sm != null)
507:                    sm.checkPermission(getPrincipalInfoPermission);
508:
509:                return threadSubjectStacks.peek();
510:            }
511:
512:            /**
513:             * Clear all principal information. If a security manager is present, then
514:             * this method calls the security manager's <code>checkPermission</code>
515:             * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
516:             * </code> permission to ensure it's ok to access principal information. If
517:             * not, a <code>SecurityException</code> will be thrown.
518:             */
519:            public static void clear() {
520:                SecurityManager sm = System.getSecurityManager();
521:                if (sm != null)
522:                    sm.checkPermission(setPrincipalInfoPermission);
523:
524:                if (trace)
525:                    log.trace("clear, server=" + server);
526:                if (server == true) {
527:                    threadPrincipal.set(null);
528:                    threadCredential.set(null);
529:                } else {
530:                    SecurityAssociation.principal = null;
531:                    SecurityAssociation.credential = null;
532:                }
533:                // Remove all subject contexts
534:                threadSubjectStacks.clear();
535:            }
536:
537:            /**
538:             * Push the current thread of control's run-as identity.
539:             */
540:            public static void pushRunAsIdentity(RunAsIdentity runAs) {
541:                SecurityManager sm = System.getSecurityManager();
542:                if (sm != null)
543:                    sm.checkPermission(setRunAsIdentity);
544:                if (trace)
545:                    log.trace("pushRunAsIdentity, runAs=" + runAs);
546:
547:                threadRunAsStacks.push(runAs);
548:            }
549:
550:            /**
551:             * Pop the current thread of control's run-as identity.
552:             */
553:            public static RunAsIdentity popRunAsIdentity() {
554:                SecurityManager sm = System.getSecurityManager();
555:                if (sm != null)
556:                    sm.checkPermission(setRunAsIdentity);
557:                RunAsIdentity runAs = threadRunAsStacks.pop();
558:                if (trace)
559:                    log.trace("popRunAsIdentity, runAs=" + runAs);
560:                return runAs;
561:            }
562:
563:            /**
564:             * Look at the current thread of control's run-as identity on the top of the
565:             * stack.
566:             */
567:            public static RunAsIdentity peekRunAsIdentity() {
568:                return peekRunAsIdentity(0);
569:            }
570:
571:            /**
572:             * Look at the current thread of control's run-as identity at the indicated
573:             * depth. Typically depth is either 0 for the identity the current caller
574:             * run-as that will be assumed, or 1 for the active run-as the previous
575:             * caller has assumed.
576:             * @return RunAsIdentity depth frames up.
577:             */
578:            public static RunAsIdentity peekRunAsIdentity(int depth) {
579:                RunAsIdentity runAs = threadRunAsStacks.peek(depth);
580:                return runAs;
581:            }
582:
583:            /**
584:             * Set the server mode of operation. When the server property has been set to
585:             * true, the security information is maintained in thread local storage. This
586:             * should be called to enable property security semantics in any
587:             * multi-threaded environment where more than one thread requires that
588:             * security information be restricted to the thread's flow of control.
589:             *
590:             * If a security manager is present, then this method calls the security
591:             * manager's <code>checkPermission</code> method with a <code>
592:             * RuntimePermission("org.jboss.security.SecurityAssociation.setServer")
593:             * </code> permission to ensure it's ok to access principal information. If
594:             * not, a <code>SecurityException</code> will be thrown.
595:             */
596:            public static void setServer() {
597:                SecurityManager sm = System.getSecurityManager();
598:                if (sm != null)
599:                    sm.checkPermission(setServerPermission);
600:
601:                server = true;
602:            }
603:
604:            /**
605:             * A subclass of ThreadLocal that implements a value stack using an ArrayList
606:             * and implements push, pop and peek stack operations on the thread local
607:             * ArrayList.
608:             */
609:            private static class RunAsThreadLocalStack {
610:                ThreadLocal local;
611:
612:                RunAsThreadLocalStack(boolean threadLocal) {
613:                    if (threadLocal == true)
614:                        local = new ArrayListLocal();
615:                    else
616:                        local = new ArrayListInheritableLocal();
617:                }
618:
619:                int size() {
620:                    ArrayList stack = (ArrayList) local.get();
621:                    return stack.size();
622:                }
623:
624:                void push(RunAsIdentity runAs) {
625:                    ArrayList stack = (ArrayList) local.get();
626:                    stack.add(runAs);
627:                }
628:
629:                RunAsIdentity pop() {
630:                    ArrayList stack = (ArrayList) local.get();
631:                    RunAsIdentity runAs = null;
632:                    int lastIndex = stack.size() - 1;
633:                    if (lastIndex >= 0)
634:                        runAs = (RunAsIdentity) stack.remove(lastIndex);
635:                    return runAs;
636:                }
637:
638:                /**
639:                 * Look for the first non-null run-as identity on the stack starting
640:                 * with the value at depth.
641:                 * @return The run-as identity if one exists, null otherwise.
642:                 */
643:                RunAsIdentity peek(int depth) {
644:                    ArrayList stack = (ArrayList) local.get();
645:                    RunAsIdentity runAs = null;
646:                    final int stackSize = stack.size();
647:                    do {
648:                        int index = stackSize - 1 - depth;
649:                        if (index >= 0)
650:                            runAs = (RunAsIdentity) stack.get(index);
651:                        depth++;
652:                    } while (runAs == null && depth <= stackSize - 1);
653:                    return runAs;
654:                }
655:            }
656:
657:            /**
658:             * The encapsulation of the authenticated subject
659:             */
660:            public static class SubjectContext {
661:                public static final int SUBJECT_WAS_SET = 1;
662:                public static final int PRINCIPAL_WAS_SET = 2;
663:                public static final int CREDENTIAL_WAS_SET = 4;
664:
665:                private Subject subject;
666:                private Principal principal;
667:                private Object credential;
668:                private int flags;
669:
670:                public SubjectContext() {
671:                    this .flags = 0;
672:                }
673:
674:                public SubjectContext(Subject s, Principal p, Object cred) {
675:                    this .subject = s;
676:                    this .principal = p;
677:                    this .credential = cred;
678:                    this .flags = SUBJECT_WAS_SET | PRINCIPAL_WAS_SET
679:                            | CREDENTIAL_WAS_SET;
680:                }
681:
682:                public Subject getSubject() {
683:                    return subject;
684:                }
685:
686:                public void setSubject(Subject subject) {
687:                    this .subject = subject;
688:                    this .flags |= SUBJECT_WAS_SET;
689:                }
690:
691:                public Principal getPrincipal() {
692:                    return principal;
693:                }
694:
695:                public void setPrincipal(Principal principal) {
696:                    this .principal = principal;
697:                    this .flags |= PRINCIPAL_WAS_SET;
698:                }
699:
700:                public Object getCredential() {
701:                    return credential;
702:                }
703:
704:                public void setCredential(Object credential) {
705:                    this .credential = credential;
706:                    this .flags |= CREDENTIAL_WAS_SET;
707:                }
708:
709:                public int getFlags() {
710:                    return this .flags;
711:                }
712:
713:                public String toString() {
714:                    StringBuffer tmp = new StringBuffer(super .toString());
715:                    tmp.append("{principal=");
716:                    tmp.append(principal);
717:                    tmp.append(",subject=");
718:                    if (subject != null)
719:                        tmp.append(System.identityHashCode(subject));
720:                    else
721:                        tmp.append("null");
722:                    tmp.append("}");
723:                    return tmp.toString();
724:                }
725:            }
726:
727:            private static class SubjectThreadLocalStack {
728:                ThreadLocal local;
729:
730:                SubjectThreadLocalStack(boolean threadLocal) {
731:                    if (threadLocal == true)
732:                        local = new ArrayListLocal();
733:                    else
734:                        local = new ArrayListInheritableLocal();
735:                }
736:
737:                int size() {
738:                    ArrayList stack = (ArrayList) local.get();
739:                    return stack.size();
740:                }
741:
742:                void push(SubjectContext context) {
743:                    ArrayList stack = (ArrayList) local.get();
744:                    stack.add(context);
745:                }
746:
747:                SubjectContext dup() {
748:                    ArrayList stack = (ArrayList) local.get();
749:                    SubjectContext context = null;
750:                    int lastIndex = stack.size() - 1;
751:                    if (lastIndex >= 0) {
752:                        context = (SubjectContext) stack.get(lastIndex);
753:                        stack.add(context);
754:                    }
755:                    return context;
756:                }
757:
758:                SubjectContext pop() {
759:                    ArrayList stack = (ArrayList) local.get();
760:                    SubjectContext context = null;
761:                    int lastIndex = stack.size() - 1;
762:                    if (lastIndex >= 0)
763:                        context = (SubjectContext) stack.remove(lastIndex);
764:                    return context;
765:                }
766:
767:                /**
768:                 * Look for the first non-null run-as identity on the stack starting
769:                 * with the value at depth.
770:                 * @return The run-as identity if one exists, null otherwise.
771:                 */
772:                SubjectContext peek() {
773:                    ArrayList stack = (ArrayList) local.get();
774:                    SubjectContext context = null;
775:                    int lastIndex = stack.size() - 1;
776:                    if (lastIndex >= 0)
777:                        context = (SubjectContext) stack.get(lastIndex);
778:                    return context;
779:                }
780:
781:                /**
782:                 * Remove all SubjectContext from the current thread stack
783:                 */
784:                void clear() {
785:                    ArrayList stack = (ArrayList) local.get();
786:                    stack.clear();
787:                }
788:            }
789:
790:            private static class ArrayListLocal extends ThreadLocal {
791:                protected Object initialValue() {
792:                    return new ArrayList();
793:                }
794:
795:            }
796:
797:            private static class ArrayListInheritableLocal extends
798:                    InheritableThreadLocal {
799:                /**
800:                 * Override to make a copy of the parent as not doing so results in multiple
801:                 * threads sharing the unsynchronized list of the parent thread.
802:                 * @param parentValue - the parent ArrayList
803:                 * @return a copy of the parent thread list
804:                 */
805:                protected Object childValue(Object parentValue) {
806:                    ArrayList list = (ArrayList) parentValue;
807:                    /* It seems there are scenarios where the size can change during the copy so there is
808:                    a fallback to an empty list here.
809:                     */
810:                    ArrayList copy = null;
811:                    try {
812:                        copy = new ArrayList(list);
813:                    } catch (Throwable t) {
814:                        log.debug("Failed to copy parent list, using new list");
815:                        copy = new ArrayList();
816:                    }
817:                    return copy;
818:                }
819:
820:                protected Object initialValue() {
821:                    return new ArrayList();
822:                }
823:
824:            }
825:
826:            private static class HashMapInheritableLocal extends
827:                    InheritableThreadLocal {
828:                /**
829:                 * Override to make a copy of the parent as not doing so results in multiple
830:                 * threads sharing the unsynchronized map of the parent thread.
831:                 * @param parentValue - the parent HashMap
832:                 * @return a copy of the parent thread map
833:                 */
834:                protected Object childValue(Object parentValue) {
835:                    HashMap map = (HashMap) parentValue;
836:                    /* It seems there are scenarios where the size can change during the copy so there is
837:                    a fallback to an empty map here.
838:                     */
839:                    HashMap copy = null;
840:                    try {
841:                        copy = new HashMap(map);
842:                    } catch (Throwable t) {
843:                        log.debug("Failed to copy parent map, using new map");
844:                        copy = new HashMap();
845:                    }
846:                    return copy;
847:                }
848:
849:                protected Object initialValue() {
850:                    return new HashMap();
851:                }
852:
853:            }
854:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.