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.security.acl.Group;
026: import java.util.Enumeration;
027: import java.util.LinkedList;
028:
029: /** An implementation of Group that allows that acts as a stack of Principals
030: with a single Principal Group member active at any time.
031: When one adds a Principal to a NestablePrincipal the Principal is pushed onto
032: the active Princpal stack and any of the Group methods operate as though the
033: Group contains only the Principal. When removing the Principal that corresponds
034: to the active Principal, the active Principal is popped from the stack and
035: the new active Principal is effectively set to the new top of the stack.
036:
037: The typical usage of this class is when doing a JAAS LoginContext login
038: to runAs a new Principal with a new CallerPrincipal identity
039: without destroying the current CallerPrincipal identity and roles.
040:
041: @author Scott.Stark@jboss.org
042: @version $Revision: 57203 $
043: */
044: public class NestablePrincipal extends SimplePrincipal implements
045: Group, Cloneable {
046: /** The serialVersionUID */
047: private static final long serialVersionUID = -6163710574424115701L;
048:
049: /** The stack of the Principals. Elements are pushed/poped by
050: inserting/removing element 0.
051: */
052: private LinkedList principalStack;
053:
054: /** Creates new NestablePrincipal with the given name
055: */
056: public NestablePrincipal(String name) {
057: super (name);
058: principalStack = new LinkedList();
059: }
060:
061: // --- Begin Group interface methods
062: /** Returns an enumeration that contains the single active Principal.
063: @return an Enumeration of the single active Principal.
064: */
065: public Enumeration members() {
066: return new IndexEnumeration();
067: }
068:
069: /** Removes the first occurence of user from the Principal stack.
070:
071: @param user the principal to remove from this group.
072: @return true if the principal was removed, or
073: * false if the principal was not a member.
074: */
075: public boolean removeMember(Principal user) {
076: return principalStack.remove(user);
077: }
078:
079: /** Pushes the user onto the Principal stack and makes it the active
080: Principal.
081: @return true always.
082: */
083: public boolean addMember(Principal user) {
084: principalStack.addFirst(user);
085: return true;
086: }
087:
088: /**
089: * Returns true if the passed principal is a member of the group.
090: * This method does a recursive search, so if a principal belongs to a
091: * group which is a member of this group, true is returned.
092: *
093: * @param member the principal whose membership is to be checked.
094: *
095: * @return true if the principal is a member of this group,
096: * false otherwise.
097: */
098: public boolean isMember(Principal member) {
099: if (principalStack.size() == 0)
100: return false;
101:
102: Object activePrincipal = principalStack.getFirst();
103: return member.equals(activePrincipal);
104: }
105:
106: public synchronized Object clone()
107: throws CloneNotSupportedException {
108: NestablePrincipal clone = (NestablePrincipal) super .clone();
109: if (clone != null)
110: clone.principalStack = (LinkedList) this .principalStack
111: .clone();
112: return clone;
113: }
114:
115: // --- End Group interface methods
116:
117: private class IndexEnumeration implements Enumeration {
118: private boolean hasMoreElements;
119:
120: IndexEnumeration() {
121: hasMoreElements = principalStack.size() > 0;
122: }
123:
124: public boolean hasMoreElements() {
125: return hasMoreElements;
126: }
127:
128: public Object nextElement() {
129: Object next = principalStack.getFirst();
130: hasMoreElements = false;
131: return next;
132: }
133: }
134: }
|