1 /* 2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.acl; 27 28 import java.util.*; 29 import java.security.*; 30 import java.security.acl.*; 31 32 /** 33 * This class implements a group of principals. 34 * @author Satish Dharmaraj 35 */ 36 public class GroupImpl implements Group { 37 private Vector<Principal> groupMembers = new Vector<>(50, 100); 38 private String group; 39 40 /** 41 * Constructs a Group object with no members. 42 * @param groupName the name of the group 43 */ 44 public GroupImpl(String groupName) { 45 this.group = groupName; 46 } 47 48 /** 49 * adds the specified member to the group. 50 * @param user The principal to add to the group. 51 * @return true if the member was added - false if the 52 * member could not be added. 53 */ 54 public boolean addMember(Principal user) { 55 if (groupMembers.contains(user)) 56 return false; 57 58 // do not allow groups to be added to itself. 59 if (group.equals(user.toString())) 60 throw new IllegalArgumentException(); 61 62 groupMembers.addElement(user); 63 return true; 64 } 65 66 /** 67 * removes the specified member from the group. 68 * @param user The principal to remove from the group. 69 * @param true if the principal was removed false if 70 * the principal was not a member 71 */ 72 public boolean removeMember(Principal user) { 73 return groupMembers.removeElement(user); 74 } 75 76 /** 77 * returns the enumeration of the members in the group. 78 */ 79 public Enumeration<? extends Principal> members() { 80 return groupMembers.elements(); 81 } 82 83 /** 84 * This function returns true if the group passed matches 85 * the group represented in this interface. 86 * @param another The group to compare this group to. 87 */ 88 public boolean equals(Object obj) { 89 if (this == obj) { 90 return true; 91 } 92 if (obj instanceof Group == false) { 93 return false; 94 } 95 Group another = (Group)obj; 96 return group.equals(another.toString()); 97 } 98 99 // equals(Group) for compatibility 100 public boolean equals(Group another) { 101 return equals((Object)another); 102 } 103 104 /** 105 * Prints a stringified version of the group. 106 */ 107 public String toString() { 108 return group; 109 } 110 111 /** 112 * return a hashcode for the principal. 113 */ 114 public int hashCode() { 115 return group.hashCode(); 116 } 117 118 /** 119 * returns true if the passed principal is a member of the group. 120 * @param member The principal whose membership must be checked for. 121 * @return true if the principal is a member of this group, 122 * false otherwise 123 */ 124 public boolean isMember(Principal member) { 125 126 // 127 // if the member is part of the group (common case), return true. 128 // if not, recursively search depth first in the group looking for the 129 // principal. 130 // 131 if (groupMembers.contains(member)) { 132 return true; 133 } else { 134 Vector<Group> alreadySeen = new Vector<>(10); 135 return isMemberRecurse(member, alreadySeen); 136 } 137 } 138 139 /** 140 * return the name of the principal. 141 */ 142 public String getName() { 143 return group; 144 } 145 146 // 147 // This function is the recursive search of groups for this 148 // implementation of the Group. The search proceeds building up 149 // a vector of already seen groups. Only new groups are considered, 150 // thereby avoiding loops. 151 // 152 boolean isMemberRecurse(Principal member, Vector<Group> alreadySeen) { 153 Enumeration<? extends Principal> e = members(); 154 while (e.hasMoreElements()) { 155 boolean mem = false; 156 Principal p = (Principal) e.nextElement(); 157 158 // if the member is in this collection, return true 159 if (p.equals(member)) { 160 return true; 161 } else if (p instanceof GroupImpl) { 162 // 163 // if not recurse if the group has not been checked already. 164 // Can call method in this package only if the object is an 165 // instance of this class. Otherwise call the method defined 166 // in the interface. (This can lead to a loop if a mixture of 167 // implementations form a loop, but we live with this improbable 168 // case rather than clutter the interface by forcing the 169 // implementation of this method.) 170 // 171 GroupImpl g = (GroupImpl) p; 172 alreadySeen.addElement(this); 173 if (!alreadySeen.contains(g)) 174 mem = g.isMemberRecurse(member, alreadySeen); 175 } else if (p instanceof Group) { 176 Group g = (Group) p; 177 if (!alreadySeen.contains(g)) 178 mem = g.isMember(member); 179 } 180 181 if (mem) 182 return mem; 183 } 184 return false; 185 } 186 }