001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.core.security;
019:
020: import java.security.acl.Permission;
021: import java.util.ArrayList;
022: import java.util.HashMap;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.Set;
027:
028: import de.finix.contelligent.CallData;
029: import de.finix.contelligent.exception.NotOwnerException;
030: import de.finix.contelligent.logging.LoggingService;
031:
032: /**
033: * This is a control class that makes it easy to find out if a particular
034: * {@link ContelligentPrincipal principal} has a given Permission. <BR>
035: * A principal may be a {@link User} or {@link Role} instance. If a role gets a
036: * permission assigned every user with this specific role automatically has the
037: * same permission.
038: *
039: * It roughly follows the <code>java.security.acl.acl</code> interface from
040: * Sun.
041: */
042: public class AccessControlList implements Cloneable {
043: final static org.apache.log4j.Logger log = LoggingService
044: .getLogger(AccessControlList.class);
045:
046: public static final String MODE_UNSET = "UNSET";
047:
048: private String name;
049:
050: /**
051: * Contains the owners of this acl, so entries are all
052: * {@link ContelligentPrincipal} instances.
053: */
054: private HashSet ownerSet;
055:
056: /**
057: * Maps a {@link de.finix.contelligent.client.security.Principal} to its set
058: * of {@link AclEntry acl-entries}. (so the map contains (Principal,Set)
059: * entries)
060: */
061: private HashMap entryMap = new HashMap();
062:
063: /**
064: * Creates a new <code>AccessControlList</code> instance.
065: *
066: * @param name
067: * a <code>String</code> value
068: * @param owner
069: * a <code>Principal</code> value
070: */
071: public AccessControlList(String name, ContelligentPrincipal owner) {
072: this .name = name;
073: ownerSet = new HashSet();
074: ownerSet.add(owner);
075: if (log.isDebugEnabled()) {
076: log.debug("instance with name '" + name + "' and owner '"
077: + owner + "' created.");
078: }
079: }
080:
081: public AccessControlList(String name, Set ownerSet) {
082: if (ownerSet.isEmpty()) {
083: log.error("cannot initialize acl with empty owner-set!");
084: throw new PrincipalTypeException(
085: "[AccessControlList '"
086: + name
087: + "'] - cannot initialize acl with emtpy owner-set!");
088: }
089: this .name = name;
090: this .ownerSet = new HashSet();
091: this .ownerSet.addAll(ownerSet);
092: if (log.isDebugEnabled()) {
093: log.debug("instance with name '" + name + "' created.");
094: }
095: }
096:
097: /** needed by clone() method */
098: private AccessControlList(String name) {
099: this .name = name;
100: ownerSet = null;
101: entryMap = null;
102: }
103:
104: // ============================================================================
105: // methods from interface Owner
106: // ============================================================================
107:
108: /**
109: * Make the given user the single owner
110: *
111: * @param caller
112: * the user invoking this method. It must be an owner of the ACL.
113: * @return true if successful, false if newOwner is already an owner.
114: * @exception NotOwnerException
115: * if the caller user is not an owner of the ACL.
116: */
117: public boolean setOwner(User caller, ContelligentPrincipal newOwner)
118: throws NotOwnerException {
119: if (isOwner(caller)
120: || ContelligentSecurityManager
121: .getInstance()
122: .hasPrivilege(
123: caller,
124: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
125: boolean answer = !isOwner(newOwner);
126: ownerSet.clear();
127: ownerSet.add(newOwner);
128: return answer;
129: } else {
130: log.error("'" + name + "':addOwner() - caller '" + caller
131: + "' is not an owner of this acl!");
132: throw new NotOwnerException(caller, name);
133: }
134: }
135:
136: /**
137: * Adds an owner. Only owners can modify ACL contents. The caller User must
138: * be an owner of the ACL in order to invoke this method. That is, only an
139: * owner can add another owner. The initial owner is configured at ACL
140: * construction time.
141: *
142: * @param caller
143: * the user invoking this method. It must be an owner of the ACL.
144: * @return true if successful, false if newOwner is already an owner.
145: * @exception NotOwnerException
146: * if the caller user is not an owner of the ACL.
147: */
148: public boolean addOwner(User caller, ContelligentPrincipal newOwner)
149: throws NotOwnerException {
150: if (isOwner(caller)
151: || ContelligentSecurityManager
152: .getInstance()
153: .hasPrivilege(
154: caller,
155: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
156: return ownerSet.add(newOwner);
157: } else {
158: log.error("'" + name + "':addOwner() - caller '" + caller
159: + "' is not an owner of this acl!");
160: throw new NotOwnerException(caller, name);
161: }
162: }
163:
164: /**
165: * Deletes an owner. If this is the last owner in the ACL, an exception is
166: * raised.
167: * <p>
168: * The caller user must be an owner of the ACL in order to invoke this
169: * method.
170: *
171: * @param caller
172: * the user invoking this method. It must be an owner of the ACL.
173: * @param owner
174: * the owner to be removed from the set of owners.
175: * @return true if the owner is removed, false if the owner is not part of
176: * the set of owners.
177: * @exception NotOwnerException
178: * if the caller user is not an owner of the ACL.
179: * @exception LastOwnerException
180: * if there is only one owner left, so that deleteOwner would
181: * leave the ACL owner-less.
182: */
183: public boolean deleteOwner(User caller, ContelligentPrincipal owner)
184: throws NotOwnerException, LastOwnerException {
185: if (isOwner(caller)
186: || ContelligentSecurityManager
187: .getInstance()
188: .hasPrivilege(
189: caller,
190: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
191: if (ownerSet.size() > 1) {
192: return ownerSet.remove(owner);
193: } else {
194: throw new LastOwnerException(
195: "cannot removeType last owner '" + owner
196: + "' from acl '" + name + "'");
197: }
198: } else {
199: log.error("'" + name + "':deleteOwner() - caller '"
200: + caller + "' is not an owner of this acl!");
201: throw new NotOwnerException(caller, name);
202: }
203: }
204:
205: /**
206: * Returns a newly created Set containing the owners of this acl. Note that
207: * an owner can be either of type {@link Role} or {@link User} so to be safe
208: * always cast the set elements to the super interface
209: * {@link ContelligentPrincipal} only!
210: *
211: * @return a <code>Set</code> containing objects of type
212: * {@link ContelligentPrincipal}, the owners of this acl.
213: */
214: public Set getOwners() {
215: return new HashSet(ownerSet);
216: }
217:
218: // ============================================================================
219: // methods of interface Acl
220: // ============================================================================
221:
222: /**
223: * Sets the name of this ACL.
224: *
225: * @param caller
226: * the user invoking this method, must be an owner of this ACL.
227: * @param name
228: * the name to be given to this ACL.
229: * @exception NotOwnerException
230: * if the caller user is not an owner of this ACL.
231: */
232: public void setName(User caller, String name)
233: throws NotOwnerException {
234: if (isOwner(caller)) {
235: this .name = name;
236: } else {
237: log.error("'" + this .name + "':setName - caller '" + caller
238: + "' is not an owner of this acl!");
239: throw new NotOwnerException(caller, this .name);
240: }
241: }
242:
243: /**
244: * Returns the name of this ACL.
245: *
246: * @return the name of this ACL.
247: */
248: public String getName() {
249: return name;
250: }
251:
252: /**
253: * Adds an {@link AclEntry} to this ACL. An entry associates a Principal
254: * with a permission and a socalled mode which indicates if the permission
255: * is granted or denied. <BR>
256: * <em>Caution:</em> if there's already an entry for the same principal
257: * and permission this entry is NOT replaced no matter what the modes are
258: * because those entries are considered to be {@link AclEntry#equals equal}.
259: * That means an entry
260: *
261: * <pre>
262: * ALLOW user READ
263: * </pre>
264: *
265: * doesn't replace an existing entry
266: *
267: * <pre>
268: * DENY user READ
269: * </pre>! To achieve this you must {@link #removeEntry removeType} the
270: * entry first.
271: *
272: * @param caller
273: * the user invoking this method. It must be an owner of this
274: * ACL.
275: * @param entry
276: * {@link AclEntry} to be added to this ACL.
277: * @return true if the entry was added, false if an entry with the same
278: * permission (positive or negative) for the same principal is
279: * already present in this ACL.
280: * @exception NotOwnerException
281: * if the caller user is not an owner of this ACL.
282: */
283: public boolean addEntry(User caller, AclEntry entry)
284: throws NotOwnerException {
285: if (isOwner(caller)
286: || ContelligentSecurityManager
287: .getInstance()
288: .hasPrivilege(
289: caller,
290: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
291: ContelligentPrincipal principal = entry.getPrincipal();
292: if (entryMap.containsKey(principal)) {
293: Set entrySet = (Set) entryMap.get(principal);
294: boolean result = entrySet.add(entry);
295: if (log.isDebugEnabled()) {
296: if (result)
297: log
298: .debug("'"
299: + name
300: + "':addEntry() - entry for principal '"
301: + principal + "' added.");
302: else
303: log
304: .debug("'"
305: + name
306: + "':addEntry() - there was already an equal entry in this acl! (entry to add was '"
307: + entry + "')");
308: }
309: return result;
310: } else {
311: Set entrySet = new HashSet();
312: entrySet.add(entry);
313: entryMap.put(principal, entrySet);
314: if (log.isDebugEnabled()) {
315: log
316: .debug("'"
317: + name
318: + "':addEntry() - new entry for principal '"
319: + principal + "' created.");
320: }
321: return true;
322: }
323: } else {
324: log.error("'" + name + "':addEntry - caller '" + caller
325: + "' is not an owner of this acl!");
326: throw new NotOwnerException(caller, name);
327: }
328: }
329:
330: /**
331: * Adds all entries of the given ACL to this ACL if there's not already such
332: * an entry. This means the other ACL does NOT overwrite this instance.
333: *
334: * @param caller
335: * an <code>User</code> value
336: * @param otherACL
337: * an <code>AccessControlList</code> value
338: * @return a <code>boolean</code> value
339: * @exception NotOwnerException
340: * if an error occurs
341: */
342: public void addACL(User caller, AccessControlList otherACL)
343: throws NotOwnerException {
344: if (isOwner(caller)
345: || ContelligentSecurityManager
346: .getInstance()
347: .hasPrivilege(
348: caller,
349: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
350: final boolean debugEnabled = log.isDebugEnabled();
351: if (debugEnabled) {
352: log.debug("'" + name
353: + "':addACL() - trying to add ACL '" + otherACL
354: + "' to myself which is '" + this + "' ...");
355: }
356: Iterator otherMapEntries = otherACL.entryMap.entrySet()
357: .iterator();
358: while (otherMapEntries.hasNext()) {
359: Map.Entry otherMapEntry = (Map.Entry) otherMapEntries
360: .next();
361: ContelligentPrincipal principal = (ContelligentPrincipal) otherMapEntry
362: .getKey();
363: if (entryMap.containsKey(principal)) {
364: Set myAclEntrySet = (Set) entryMap.get(principal);
365: Iterator it = ((Set) otherMapEntry.getValue())
366: .iterator();
367: if (debugEnabled) {
368: log.debug("'" + name
369: + "':addACL() - ... checking set '"
370: + myAclEntrySet + "' ...");
371: }
372: while (it.hasNext()) {
373: AclEntry otherAclEntry = (AclEntry) it.next();
374: if (!(myAclEntrySet.contains(otherAclEntry))) {
375: if (debugEnabled) {
376: log
377: .debug("'"
378: + name
379: + "':addACL() - ... adding clone of aclEntry '"
380: + otherAclEntry
381: + "' ...");
382: }
383: AclEntry clone = (AclEntry) otherAclEntry
384: .clone();
385: clone.setIsInherited(true);
386: myAclEntrySet.add(clone);
387: }
388: }
389: } else {
390: // entryMap.put(principal, otherMapEntry.getValue());
391: Iterator it = ((Set) otherMapEntry.getValue())
392: .iterator();
393: if (debugEnabled) {
394: log
395: .debug("'"
396: + name
397: + "':addACL() - ... I have no entry-set for principal '"
398: + principal
399: + "', adding whole set from other ACL ...");
400: }
401: Set newAclEntrySet = new HashSet();
402: while (it.hasNext()) {
403: AclEntry otherAclEntry = (AclEntry) it.next();
404: if (debugEnabled) {
405: log
406: .debug("'"
407: + name
408: + "':addACL() - ... adding clone of aclEntry '"
409: + otherAclEntry + "' ...");
410: }
411: AclEntry clone = (AclEntry) otherAclEntry
412: .clone();
413: clone.setIsInherited(true);
414: newAclEntrySet.add(clone);
415: }
416: entryMap.put(principal, newAclEntrySet);
417: }
418: }
419: } else {
420: log.error("'" + name + "':addACL - caller '" + caller
421: + "' is not an owner of this acl!");
422: throw new NotOwnerException(caller, name);
423: }
424: }
425:
426: /**
427: * Removes an ACL entry from this ACL.
428: *
429: * @param caller
430: * the user invoking this method. It must be an owner of this
431: * ACL.
432: * @param entry
433: * the ACL entry to be removed from this ACL.
434: * @return true on success, false if the entry is not part of this ACL.
435: * @exception NotOwnerException
436: * if the caller user is not an owner of this Acl.
437: */
438: public boolean removeEntry(User caller, AclEntry entry)
439: throws NotOwnerException {
440: if (isOwner(caller)
441: || ContelligentSecurityManager
442: .getInstance()
443: .hasPrivilege(
444: caller,
445: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
446: ContelligentPrincipal principal = entry.getPrincipal();
447: if (!entryMap.containsKey(principal)) {
448: if (log.isDebugEnabled()) {
449: log
450: .debug("'"
451: + name
452: + "':removeEntry - there's no entry for principal '"
453: + principal + "'!");
454: }
455: return false;
456: } else {
457: Set permSet = (Set) entryMap.get(principal);
458: boolean result = permSet.remove(entry);
459: if (log.isDebugEnabled()) {
460: if (result)
461: log
462: .debug("'"
463: + name
464: + "':removeEntry - entry of principal '"
465: + principal + "' removed.");
466: else
467: log
468: .debug("'"
469: + name
470: + "':removeEntry - there's not entry equal to '"
471: + entry + "' in this acl.");
472: }
473: return result;
474: }
475: } else {
476: log.error("'" + name + "':removeEntry - caller '" + caller
477: + "' is not an owner of this acl!");
478: throw new NotOwnerException(caller, name);
479: }
480: }
481:
482: /**
483: * Removes all ACL entries from this ACL.
484: *
485: * @param caller
486: * the user invoking this method. It must be an owner of this
487: * ACL.
488: * @exception NotOwnerException
489: * if the caller user is not an owner of this Acl.
490: */
491: public void removeEntries(User caller) throws NotOwnerException {
492: if (isOwner(caller)
493: || ContelligentSecurityManager
494: .getInstance()
495: .hasPrivilege(
496: caller,
497: ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
498: entryMap.clear();
499: } else {
500: log.error("'" + name + "':removeEntry - caller '" + caller
501: + "' is not an owner of this acl!");
502: throw new NotOwnerException(caller, name);
503: }
504: }
505:
506: /**
507: * Returns an Iterator for the set of AclEntries for the specified principal
508: * (representing an entity such as an individual or a group).
509: *
510: * @param principal
511: * the principal whose permission set is to be returned.
512: * @return an iterator over the set of AclEntries for the specified
513: * principal
514: */
515: public Iterator entries(ContelligentPrincipal principal) {
516: if (entryMap.containsKey(principal)) {
517: if (log.isDebugEnabled()) {
518: log
519: .debug("'"
520: + name
521: + "':entries() - returning iterator for set of acl-entries of principal '"
522: + principal + "'.");
523: }
524: return new HashSet((Set) entryMap.get(principal))
525: .iterator();
526: } else {
527: if (log.isDebugEnabled()) {
528: log.debug("'" + name
529: + "':entries() - returning empty iterator!");
530: }
531: return new HashSet().iterator();
532: }
533: }
534:
535: /**
536: * Returns the set of acl-entries of the specified principal or an empty
537: * <code>HashSet</code> if this principal does not have any entry.
538: *
539: * @param principal
540: * a <code>ContelligentPrincipal</code> value
541: * @return a <code>Set</code> value
542: */
543: public Set entrySet(ContelligentPrincipal principal) {
544: if (entryMap.containsKey(principal)) {
545: if (log.isDebugEnabled()) {
546: log
547: .debug("'"
548: + name
549: + "':entrySet() - returning set of acl-entries of principal '"
550: + principal + "'.");
551: }
552: return new HashSet((Set) entryMap.get(principal));
553: } else {
554: return new HashSet();
555: }
556: }
557:
558: /**
559: * Returns true if there are no acl-entries for the specified principal
560: * within this ACL.
561: *
562: * @param principal
563: * a <code>ContelligentPrincipal</code> value
564: * @return a <code>boolean</code> value
565: */
566: public boolean hasEntries(ContelligentPrincipal principal) {
567: if (entryMap.isEmpty() || !(entryMap.containsKey(principal))) {
568: return true;
569: } else {
570: return ((Set) entryMap.get(principal)).isEmpty();
571: }
572: }
573:
574: /**
575: * Returns true if there are no acl-entries for any principal within this
576: * ACL.
577: *
578: * @return a <code>boolean</code> value
579: */
580: public boolean isEmpty() {
581: return (entryMap == null || entryMap.isEmpty());
582: }
583:
584: /**
585: * Returns the set of all acl-entries of this acl or an empty
586: * <code>HashSet</code> if there are no entries at all.
587: *
588: * Describe <code>entrySet</code> method here.
589: *
590: * @return a <code>Set</code> value
591: */
592: public Set entrySet() {
593: if (log.isDebugEnabled()) {
594: log
595: .debug("'"
596: + name
597: + "':entrySet() - returning set containing all acl-entries of this acl.");
598: }
599: Iterator entrySets = entryMap.values().iterator();
600: Set set = new HashSet();
601: while (entrySets.hasNext()) {
602: set.addAll((Set) entrySets.next());
603: }
604: return set;
605: }
606:
607: /**
608: * Checks whether or not the specified principal has the specified
609: * permission and returns the result. More specifically, this method checks
610: * if this ACL contains a set of {@link AclEntry acl-entries} for the given
611: * principal or if the principal is a {@link User} for any of its
612: * {@link User#getRoles roles}. <BR>
613: * If no entry is found the result is false otherwise the result is
614: * calculated with the following algorithm:
615: * <OL>
616: * <LI> if there's an entry with mode {@link ComponentAccess#DENY DENY} for
617: * the principal the result is false.
618: * <LI> if there's an entry with mode {@link ComponentAccess#ALLOW ALLOW}
619: * for the principal the result is true.
620: * <LI> If the principal is not a {@link User} the result is false,
621: * otherwise the roles of the user are checked:
622: * <OL>
623: * <LI> if for any roles there's an entry with mode
624: * {@link ComponentAccess#DENY DENY} the result is false.
625: * <LI> otherwise if there's an entry for any of the roles with mode
626: * {@link ComponentAccess#ALLOW ALLOW} the result is true.
627: * </OL>
628: * </OL>
629: * In any other case the result is false.
630: *
631: * @param principal
632: * the principal, assumed to be a valid authenticated Principal.
633: * @param permission
634: * the permission to be checked for.
635: *
636: * @return true if the principal has the specified permission, false
637: * otherwise.
638: */
639: public boolean checkPermission(ContelligentPrincipal principal,
640: Permission permission, CallData callData) {
641: final boolean debugEnabled = log.isDebugEnabled();
642: if (principal instanceof SystemUser) {
643: if (debugEnabled) {
644: log.debug("'" + name
645: + "':checkPermission() - principal '"
646: + principal
647: + "' is system user -> everything allowed!");
648: }
649: return true;
650: }
651:
652: if (ContelligentSecurityManager.getInstance().hasPrivilege(
653: principal,
654: ContelligentSecurityManager.Privilege.IGNORE_ACLS)) {
655: if (debugEnabled) {
656: log.debug("'" + name
657: + "':checkPermission() - principal '"
658: + principal
659: + "' is root user -> everything allowed!");
660: }
661: return true;
662: }
663: return checkRealPermission(principal, permission, callData);
664: }
665:
666: public boolean checkRealPermission(ContelligentPrincipal principal,
667: Permission permission, CallData callData) {
668: final boolean debugEnabled = log.isDebugEnabled();
669: if (debugEnabled) {
670: log.debug("'" + name + "':checkPermission() - checking '"
671: + principal + "' for permission '" + permission
672: + "' (this ACL contains: " + this + ") ...");
673: }
674:
675: // check direct permissions for this principal first:
676: if (entryMap.containsKey(principal)) {
677: Set entrySet = (Set) entryMap.get(principal);
678: Iterator it = entrySet.iterator();
679: while (it.hasNext()) {
680: AclEntry entry = (AclEntry) it.next();
681: if (entry.isValid(callData)) {
682: if (permission.equals(entry.getPermission())) {
683: if (entry.getMode()
684: .equals(ComponentAccess.DENY)) {
685: if (debugEnabled) {
686: log
687: .debug("'"
688: + name
689: + "':checkPermission() - found personal DENY entry for principal '"
690: + principal
691: + "', returning false.");
692: }
693: return false;
694: }
695: if (entry.getMode().equals(
696: ComponentAccess.ALLOW)) {
697: if (debugEnabled) {
698: log
699: .debug("'"
700: + name
701: + "':checkPermission() - found personal ALLOW entry for principal '"
702: + principal
703: + "', returning true.");
704: }
705: return true;
706: }
707: }
708: }
709: }
710: }
711:
712: boolean result = false;
713: // if the principal is a {@link User}, check for his roles:
714: if (principal instanceof User) {
715: Iterator roleIter = ((User) principal).getRoles()
716: .iterator();
717: while (roleIter.hasNext()) {
718: ContelligentPrincipal role = (ContelligentPrincipal) roleIter
719: .next();
720: if (debugEnabled) {
721: log
722: .debug("'"
723: + name
724: + "':checkPermission() - ... searching entry-map for role '"
725: + role + "' (entry-map is '"
726: + entryMap + ") ...");
727: }
728:
729: if (entryMap.containsKey(role)) {
730: Set entrySet = (Set) entryMap.get(role);
731: if (debugEnabled) {
732: log
733: .debug("'"
734: + name
735: + "':checkPermission() - ... checking entries of role '"
736: + role + "' ...");
737: }
738: Iterator entryIter = entrySet.iterator();
739: while (entryIter.hasNext()) {
740: AclEntry entry = (AclEntry) entryIter.next();
741: if (entry.isValid(callData)) {
742: if (permission
743: .equals(entry.getPermission())) {
744: if (entry.getMode().equals(
745: ComponentAccess.DENY)) {
746: if (debugEnabled) {
747: log
748: .debug("'"
749: + name
750: + "':checkPermission() - found DENY entry for role '"
751: + role
752: + "', returning false.");
753: }
754: return false;
755: } else if (entry.getMode().equals(
756: ComponentAccess.ALLOW)) {
757: if (debugEnabled) {
758: log
759: .debug("'"
760: + name
761: + "':checkPermission() - found ALLOW entry for role '"
762: + role
763: + "' ...");
764: }
765: result = true;
766: }
767: }
768: }
769: }
770: }
771: }
772: }
773: if (debugEnabled) {
774: log.debug("'" + name
775: + "':checkPermission() - end with result: "
776: + result);
777: }
778: return result;
779: }
780:
781: /**
782: * Returns a string representation of the ACL contents.
783: *
784: * @return a string representation of the ACL contents.
785: */
786: public String toString() {
787: return ("ACL[" + name + ": " + entryMap.values() + "]");
788: }
789:
790: /**
791: * Clones this ACL.
792: *
793: * @return a clone of this ACL.
794: */
795: public Object clone() {
796: AccessControlList clone = new AccessControlList(this .name);
797: clone.ownerSet = (HashSet) this .ownerSet.clone();
798: clone.entryMap = (HashMap) this .entryMap.clone();
799: return clone;
800: }
801:
802: /**
803: * Returns an <code>Iterator</code> over set of all
804: * {@link AclEntry acl-entries} this ACL contains.
805: *
806: * @return an <code>Iterator</code> value
807: */
808: public Iterator entrySets() {
809: return new ArrayList(entryMap.values()).iterator();
810: }
811:
812: /**
813: * Returns true if the given user is an owner of this ACL.
814: * <em>Note that the SYSTEM user is always an owner</em.
815: *
816: * @param principal the principal to be checked to determine whether or not
817: * it is an owner.
818: * @return true if the passed user is in the set of owners, false if not.
819: */
820: public boolean isOwner(ContelligentPrincipal principal) {
821: if (ContelligentSecurityManager.getSystemUser().equals(
822: principal))
823: return true;
824:
825: if (ownerSet.contains(principal))
826: return true;
827:
828: if (principal instanceof User) {
829: Iterator it = ((User) principal).getRoles().iterator();
830: while (it.hasNext()) {
831: if (ownerSet.contains(it.next())) {
832: if (log.isDebugEnabled()) {
833: log
834: .debug("'"
835: + name
836: + "':isOwner() - one of the roles of user '"
837: + principal
838: + "' is contained in owner-role-set!!!");
839: }
840: return true;
841: }
842: }
843: }
844: return false;
845: }
846:
847: }
|