1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53:
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61:
62: public final class Subject implements Serializable
63: {
64:
65:
66:
67: private static final long serialVersionUID = -8308522755600156056L;
68:
69:
73: private final Set principals;
74:
75:
78: private boolean readOnly;
79:
80: private final transient SecureSet pubCred;
81: private final transient SecureSet privCred;
82:
83:
84:
85:
86: public Subject()
87: {
88: principals = new SecureSet (this, SecureSet.PRINCIPALS);
89: pubCred = new SecureSet (this, SecureSet.PUBLIC_CREDENTIALS);
90: privCred = new SecureSet (this, SecureSet.PRIVATE_CREDENTIALS);
91: readOnly = false;
92: }
93:
94: public Subject (final boolean readOnly,
95: final Set<? extends Principal> principals,
96: final Set<?> pubCred, final Set<?> privCred)
97: {
98: if (principals == null || pubCred == null || privCred == null)
99: {
100: throw new NullPointerException();
101: }
102: this.principals = new SecureSet (this, SecureSet.PRINCIPALS, principals);
103: this.pubCred = new SecureSet (this, SecureSet.PUBLIC_CREDENTIALS, pubCred);
104: this.privCred = new SecureSet (this, SecureSet.PRIVATE_CREDENTIALS, privCred);
105: this.readOnly = readOnly;
106: }
107:
108:
109:
110:
111:
126: public static Subject getSubject (final AccessControlContext context)
127: {
128: final SecurityManager sm = System.getSecurityManager();
129: if (sm != null)
130: {
131: sm.checkPermission (new AuthPermission ("getSubject"));
132: }
133: DomainCombiner dc = context.getDomainCombiner();
134: if (!(dc instanceof SubjectDomainCombiner))
135: {
136: return null;
137: }
138: return ((SubjectDomainCombiner) dc).getSubject();
139: }
140:
141:
153: public static Object doAs (final Subject subject, final PrivilegedAction action)
154: {
155: final SecurityManager sm = System.getSecurityManager();
156: if (sm != null)
157: {
158: sm.checkPermission (new AuthPermission ("doAs"));
159: }
160: AccessControlContext context =
161: new AccessControlContext (AccessController.getContext(),
162: new SubjectDomainCombiner (subject));
163: return AccessController.doPrivileged (action, context);
164: }
165:
166:
179: public static Object doAs (final Subject subject,
180: final PrivilegedExceptionAction action)
181: throws PrivilegedActionException
182: {
183: final SecurityManager sm = System.getSecurityManager();
184: if (sm != null)
185: {
186: sm.checkPermission (new AuthPermission ("doAs"));
187: }
188: AccessControlContext context =
189: new AccessControlContext (AccessController.getContext(),
190: new SubjectDomainCombiner(subject));
191: return AccessController.doPrivileged (action, context);
192: }
193:
194:
208: public static Object doAsPrivileged (final Subject subject,
209: final PrivilegedAction action,
210: final AccessControlContext acc)
211: {
212: final SecurityManager sm = System.getSecurityManager();
213: if (sm != null)
214: {
215: sm.checkPermission (new AuthPermission ("doAsPrivileged"));
216: }
217: AccessControlContext context =
218: new AccessControlContext (acc, new SubjectDomainCombiner (subject));
219: return AccessController.doPrivileged (action, context);
220: }
221:
222:
237: public static Object doAsPrivileged (final Subject subject,
238: final PrivilegedExceptionAction action,
239: AccessControlContext acc)
240: throws PrivilegedActionException
241: {
242: final SecurityManager sm = System.getSecurityManager();
243: if (sm != null)
244: {
245: sm.checkPermission (new AuthPermission ("doAsPrivileged"));
246: }
247: if (acc == null)
248: acc = new AccessControlContext (new java.security.ProtectionDomain[0]);
249: AccessControlContext context =
250: new AccessControlContext (acc, new SubjectDomainCombiner (subject));
251: return AccessController.doPrivileged (action, context);
252: }
253:
254:
255:
256:
257: public boolean equals (Object o)
258: {
259: if (!(o instanceof Subject))
260: {
261: return false;
262: }
263: Subject that = (Subject) o;
264: return principals.containsAll (that.getPrincipals()) &&
265: pubCred.containsAll (that.getPublicCredentials()) &&
266: privCred.containsAll (that.getPrivateCredentials());
267: }
268:
269: public Set<Principal> getPrincipals()
270: {
271: return principals;
272: }
273:
274: public <T extends Principal> Set<T> getPrincipals(Class<T> clazz)
275: {
276: HashSet result = new HashSet (principals.size());
277: for (Iterator it = principals.iterator(); it.hasNext(); )
278: {
279: Object o = it.next();
280: if (o != null && clazz.isAssignableFrom (o.getClass()))
281: {
282: result.add(o);
283: }
284: }
285: return Collections.unmodifiableSet (result);
286: }
287:
288: public Set<Object> getPrivateCredentials()
289: {
290: return privCred;
291: }
292:
293: public <T> Set<T> getPrivateCredentials (Class<T> clazz)
294: {
295: HashSet result = new HashSet (privCred.size());
296: for (Iterator it = privCred.iterator(); it.hasNext(); )
297: {
298: Object o = it.next();
299: if (o != null && clazz.isAssignableFrom (o.getClass()))
300: {
301: result.add(o);
302: }
303: }
304: return Collections.unmodifiableSet (result);
305: }
306:
307: public Set<Object> getPublicCredentials()
308: {
309: return pubCred;
310: }
311:
312: public <T> Set<T> getPublicCredentials (Class<T> clazz)
313: {
314: HashSet result = new HashSet (pubCred.size());
315: for (Iterator it = pubCred.iterator(); it.hasNext(); )
316: {
317: Object o = it.next();
318: if (o != null && clazz.isAssignableFrom (o.getClass()))
319: {
320: result.add(o);
321: }
322: }
323: return Collections.unmodifiableSet (result);
324: }
325:
326: public int hashCode()
327: {
328: return principals.hashCode() + privCred.hashCode() + pubCred.hashCode();
329: }
330:
331:
336: public boolean isReadOnly()
337: {
338: return readOnly;
339: }
340:
341:
348: public void setReadOnly()
349: {
350: final SecurityManager sm = System.getSecurityManager();
351: if (sm != null)
352: {
353: sm.checkPermission (new AuthPermission ("setReadOnly"));
354: }
355: readOnly = true;
356: }
357:
358: public String toString()
359: {
360: return Subject.class.getName() + " [ principals=" + principals +
361: ", private credentials=" + privCred + ", public credentials=" +
362: pubCred + ", read-only=" + readOnly + " ]";
363: }
364:
365:
366:
367:
368:
371: private static class SecureSet extends AbstractSet implements Serializable
372: {
373:
374:
375:
376: private static final long serialVersionUID = 7911754171111800359L;
377:
378: static final int PRINCIPALS = 0;
379: static final int PUBLIC_CREDENTIALS = 1;
380: static final int PRIVATE_CREDENTIALS = 2;
381:
382: private final Subject subject;
383: private final LinkedList elements;
384: private final transient int type;
385:
386:
387:
388:
389: SecureSet (final Subject subject, final int type, final Collection inElements)
390: {
391: this (subject, type);
392: for (Iterator it = inElements.iterator(); it.hasNext(); )
393: {
394: Object o = it.next();
395: if (type == PRINCIPALS && !(o instanceof Principal))
396: {
397: throw new IllegalArgumentException(o+" is not a Principal");
398: }
399: if (!this.elements.contains (o))
400: {
401: this.elements.add (o);
402: }
403: }
404: }
405:
406: SecureSet (final Subject subject, final int type)
407: {
408: this.subject = subject;
409: this.type = type;
410: this.elements = new LinkedList();
411: }
412:
413:
414:
415:
416: public synchronized int size()
417: {
418: return elements.size();
419: }
420:
421: public Iterator iterator()
422: {
423: return elements.iterator();
424: }
425:
426: public synchronized boolean add(Object element)
427: {
428: if (subject.isReadOnly())
429: {
430: throw new IllegalStateException ("subject is read-only");
431: }
432: final SecurityManager sm = System.getSecurityManager();
433: switch (type)
434: {
435: case PRINCIPALS:
436: if (sm != null)
437: {
438: sm.checkPermission (new AuthPermission ("modifyPrincipals"));
439: }
440: if (!(element instanceof Principal))
441: {
442: throw new IllegalArgumentException ("element is not a Principal");
443: }
444: break;
445:
446: case PUBLIC_CREDENTIALS:
447: if (sm != null)
448: {
449: sm.checkPermission (new AuthPermission ("modifyPublicCredentials"));
450: }
451: break;
452:
453: case PRIVATE_CREDENTIALS:
454: if (sm != null)
455: {
456: sm.checkPermission (new AuthPermission ("modifyPrivateCredentials"));
457: }
458: break;
459:
460: default:
461: throw new Error ("this statement should be unreachable");
462: }
463:
464: if (elements.contains (element))
465: {
466: return false;
467: }
468:
469: return elements.add (element);
470: }
471:
472: public synchronized boolean remove (final Object element)
473: {
474: if (subject.isReadOnly())
475: {
476: throw new IllegalStateException ("subject is read-only");
477: }
478: final SecurityManager sm = System.getSecurityManager();
479: switch (type)
480: {
481: case PRINCIPALS:
482: if (sm != null)
483: {
484: sm.checkPermission (new AuthPermission ("modifyPrincipals"));
485: }
486: if (!(element instanceof Principal))
487: {
488: throw new IllegalArgumentException ("element is not a Principal");
489: }
490: break;
491:
492: case PUBLIC_CREDENTIALS:
493: if (sm != null)
494: {
495: sm.checkPermission (new AuthPermission ("modifyPublicCredentials"));
496: }
497: break;
498:
499: case PRIVATE_CREDENTIALS:
500: if (sm != null)
501: {
502: sm.checkPermission (new AuthPermission ("modifyPrivateCredentials"));
503: }
504: break;
505:
506: default:
507: throw new Error("this statement should be unreachable");
508: }
509:
510: return elements.remove(element);
511: }
512:
513: public synchronized boolean contains (final Object element)
514: {
515: return elements.contains (element);
516: }
517:
518: public boolean removeAll (final Collection c)
519: {
520: if (subject.isReadOnly())
521: {
522: throw new IllegalStateException ("subject is read-only");
523: }
524: return super.removeAll (c);
525: }
526:
527: public boolean retainAll (final Collection c)
528: {
529: if (subject.isReadOnly())
530: {
531: throw new IllegalStateException ("subject is read-only");
532: }
533: return super.retainAll (c);
534: }
535:
536: public void clear()
537: {
538: if (subject.isReadOnly())
539: {
540: throw new IllegalStateException ("subject is read-only");
541: }
542: elements.clear();
543: }
544:
545: private synchronized void writeObject (ObjectOutputStream out)
546: throws IOException
547: {
548: throw new UnsupportedOperationException ("FIXME: determine serialization");
549: }
550:
551: private void readObject (ObjectInputStream in)
552: throws ClassNotFoundException, IOException
553: {
554: throw new UnsupportedOperationException ("FIXME: determine serialization");
555: }
556: }
557: }