/**
* Copyright (c) 2009 Juwi MacMillan Group GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.juwimm.cms.authorization.jaas;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Enumeration;
import java.util.LinkedList;
/**
* <p>Title: ConQuest</p>
* <p>Description: Enterprise Content Management</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: JuwiMacMillan Group</p>
* @author <a href="s.kulawik@juwimm.com">Sascha-Matthias Kulawik</a>
* @author Scott.Stark@jboss.org
* @version $Revision: 1.1 $
*
* An implementation of Group that allows that acts as a stack of Groups
* with a single Group member active at any time.
* When one adds a Group to a NestableGroup the Group is pushed onto
* the active Group stack and any of the Group methods operate as though the
* NestableGroup contains only the Group. When removing the Group that
* corresponds to the active Group, the active Group is popped from the stack and
* the new active Group is set to the new top of the stack.
*
* The typical usage of this class is when doing a JAAS LoginContext login
* to runAs a new Principal with a new set of roles that should be added
* without destroying the current identity and roles.
*/
public class NestableGroup extends SimplePrincipal implements Group {
private static final long serialVersionUID = 1082108775321102765L;
/** The stack of the Groups. Elements are pushed/poped by
inserting/removing element 0.
*/
private LinkedList rolesStack;
/** Creates new NestableGroup with the given name
*/
public NestableGroup(String name) {
super(name);
rolesStack = new LinkedList();
}
// --- Begin Group interface methods
/** Returns an enumeration that contains the single active Principal.
@return an Enumeration of the single active Principal.
*/
public Enumeration members() {
return new IndexEnumeration();
}
/** Removes the first occurence of user from the Principal stack.
@param user the principal to remove from this group.
@return true if the principal was removed, or
* false if the principal was not a member.
*/
public boolean removeMember(Principal user) {
return rolesStack.remove(user);
}
/**
* Pushes the group onto the Group stack and makes it the active Group.
* @param group the instance of Group that contains the roles to set as the active Group.
* @exception IllegalArgumentException, thrown if group is not an instance of Group.
* @return true always.
*/
public boolean addMember(Principal group) {
if (!(group instanceof Group)) { throw new IllegalArgumentException("The addMember argument must be a Group"); }
rolesStack.addFirst(group);
return true;
}
/**
* Returns true if the passed principal is a member of the active group.
* This method does a recursive search, so if a principal belongs to a
* group which is a member of this group, true is returned.
@param member the principal whose membership is to be checked.
@return true if the principal is a member of this group, false otherwise.
*/
public boolean isMember(Principal member) {
if (rolesStack.size() == 0) { return false; }
Group activeGroup = (Group) rolesStack.getFirst();
boolean isMember = activeGroup.isMember(member);
return isMember;
}
@Override
public String toString() {
StringBuffer tmp = new StringBuffer(getName());
tmp.append("(members:");
Enumeration iter = members();
while (iter.hasMoreElements()) {
tmp.append(iter.nextElement());
tmp.append(',');
}
tmp.setCharAt(tmp.length() - 1, ')');
return tmp.toString();
}
// --- End Group interface methods
/**
*
*/
private class IndexEnumeration implements Enumeration {
private Enumeration iter;
IndexEnumeration() {
if (rolesStack.size() > 0) {
Group grp = (Group) rolesStack.get(0);
iter = grp.members();
}
}
public boolean hasMoreElements() {
boolean hasMore = iter != null && iter.hasMoreElements();
return hasMore;
}
public Object nextElement() {
Object next = null;
if (iter != null) {
next = iter.nextElement();
}
return next;
}
}
}