001: /*
002: jGuard is a security framework based on top of jaas (java authentication and authorization security).
003: it is written for web applications, to resolve simply, access control problems.
004:
005: http://sourceforge.net/projects/jguard/
006:
007: Copyright (C) 2004 Charles GAY
008:
009: This library is free software; you can redistribute it and/or
010: modify it under the terms of the GNU Lesser General Public
011: License as published by the Free Software Foundation; either
012: version 2.1 of the License, or (at your option) any later version.
013:
014: This library is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018:
019: You should have received a copy of the GNU Lesser General Public
020: License along with this library; if not, write to the Free Software
021: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022:
023:
024: jGuard project home page:
025: http://sourceforge.net/projects/jguard/
026:
027: */
028: package net.sf.jguard.ext.authorization.manager;
029:
030: import java.security.Permission;
031: import java.security.PermissionCollection;
032: import java.security.Principal;
033: import java.security.ProtectionDomain;
034: import java.util.Collection;
035: import java.util.Collections;
036: import java.util.HashMap;
037: import java.util.HashSet;
038: import java.util.Iterator;
039: import java.util.List;
040: import java.util.Map;
041: import java.util.Random;
042: import java.util.Set;
043: import java.util.Stack;
044: import java.util.TreeSet;
045: import java.util.logging.Level;
046: import java.util.logging.Logger;
047:
048: import net.sf.jguard.core.authorization.permissions.Domain;
049: import net.sf.jguard.core.authorization.permissions.JGNegativePermissionCollection;
050: import net.sf.jguard.core.authorization.permissions.JGPermissionCollection;
051: import net.sf.jguard.core.authorization.permissions.JGPositivePermissionCollection;
052: import net.sf.jguard.core.authorization.permissions.NoSuchPermissionException;
053: import net.sf.jguard.core.authorization.permissions.PermissionUtils;
054: import net.sf.jguard.core.principals.RolePrincipal;
055: import net.sf.jguard.core.principals.UserPrincipal;
056: import net.sf.jguard.ext.SecurityConstants;
057: import net.sf.jguard.ext.authorization.AuthorizationException;
058: import net.sf.jguard.ext.principals.PrincipalUtils;
059:
060: /**
061: * Abstract class inherited by all the AuthorizationManager implementations.
062: * @author <a href="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
063: * @author <a href="mailto:tandilero@users.sourceforge.net">Maximiliano Batelli</a>
064: *
065: */
066: public abstract class AbstractAuthorizationManager implements
067: AuthorizationManager {
068: /** Logger for this class */
069: private static final Logger logger = Logger
070: .getLogger(AbstractAuthorizationManager.class.getName());
071:
072: protected String applicationName = null;
073: protected Map principals;
074: protected Set principalsSet;
075: protected Map domains;
076: //we add also this Set of domains to certify Domain unicity
077: protected static Set domainsSet;
078: protected JGPermissionCollection urlp;
079: //store all the permissions of all the domains
080: protected Map permissions;
081: protected Set permissionsSet;
082: //store the permissions set associated with the domain ids
083: protected Map domainsPermissions;
084: // store the hierarcy while assembly the principals to after link
085: protected Map hierarchyMap;
086: protected Map options;
087: private boolean negativePermissions;
088:
089: public AbstractAuthorizationManager() {
090: principals = new HashMap();
091: principalsSet = new TreeSet();
092: domains = new HashMap();
093: domainsSet = new TreeSet();
094: permissions = new HashMap();
095: permissionsSet = new HashSet();
096: domainsPermissions = new HashMap();
097: hierarchyMap = new HashMap();
098: urlp = null;
099: }
100:
101: /**
102: * define the application's name, and propagate it into Principals.
103: * this mechanism is done because application's name can only be known when the
104: * first request is here (bad j2ee design....).
105: * @param applicationName
106: */
107: public void setApplicationName(String applicationName) {
108:
109: this .applicationName = applicationName;
110: Iterator itPrincipalsSet = principalsSet.iterator();
111: while (itPrincipalsSet.hasNext()) {
112: RolePrincipal principalTemp = (RolePrincipal) itPrincipalsSet
113: .next();
114: principalTemp.setApplicationName(applicationName);
115: }
116: Iterator itPrincipalsMap = principals.values().iterator();
117: while (itPrincipalsMap.hasNext()) {
118: RolePrincipal principal = (RolePrincipal) itPrincipalsMap
119: .next();
120: principal.setApplicationName(applicationName);
121: }
122:
123: }
124:
125: /**
126: * with a collection of domain names, provide the corresponding set of URLDomains.
127: * @param domainNames collection of domains.
128: * @return URLPermission's Set
129: */
130: public Set getDomains(Collection domainNames) {
131: Set doms = new HashSet();
132: Iterator itDomNames = domainNames.iterator();
133:
134: while (itDomNames.hasNext()) {
135: JGPermissionCollection dom = (JGPermissionCollection) domains
136: .get(itDomNames.next());
137: doms.add(dom);
138: }
139:
140: return doms;
141: }
142:
143: /**
144: * with a collection of URLPermissions names, provide the corresponding
145: * set of URLPermissions.
146: * @param permissionNames collection of permission names to grab.
147: * @return URLPermission's Set
148: */
149: public Set getPermissions(Collection permissionNames) {
150: Set perms = new HashSet();
151: Iterator itPermNames = permissionNames.iterator();
152:
153: while (itPermNames.hasNext()) {
154: Permission perm;
155: String permissionName = (String) itPermNames.next();
156: try {
157: perm = urlp.getPermission(permissionName);
158: perms.add(perm);
159: } catch (NoSuchPermissionException e) {
160: logger.finest(" permission " + permissionName
161: + " not found in JGPermissionCollection ");
162: }
163: }
164:
165: return perms;
166: }
167:
168: /**
169: * initialize AuthorizationManager implementation.
170: * @param options
171: */
172: public void init(Map options) {
173: String negativePermission = (String) options
174: .get(SecurityConstants.NEGATIVE_PERMISSIONS);
175: if (negativePermission != null
176: && negativePermission.equalsIgnoreCase("true")) {
177: this .urlp = new JGNegativePermissionCollection();
178: this .negativePermissions = true;
179: } else {
180: this .urlp = new JGPositivePermissionCollection();
181: this .negativePermissions = false;
182: }
183: }
184:
185: /**
186: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#refresh()
187: */
188: public void refresh() {
189: init(options);
190: }
191:
192: /**
193: * compare declared Principals in the application, with principals set of the user.
194: * for the principals of the user, we retrieve corresponding permissions declared in the application,
195: * and we regroup them in a PermissionCollection.
196: * @param principals
197: * @return PermissionCollection
198: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#getPermissionCollection(java.util.Set)
199: * @see net.sf.jguard.core.authorization.manager.PermissionProvider
200: */
201: public PermissionCollection getPermissionCollection(Set principals,
202: ProtectionDomain pDomain) {
203:
204: if (logger.isLoggable(Level.FINEST)) {
205: logger.finest(" user has got " + principals.size()
206: + " principals " + principals.toString());
207: }
208: JGPermissionCollection urlpUser = null;
209: if (!negativePermissions) {
210: urlpUser = new JGPositivePermissionCollection();
211: } else {
212: urlpUser = new JGNegativePermissionCollection();
213: }
214:
215: //TODO CGA add SSODPermissions (java.security.Permissions) decorator
216: //to support Static Separation Of Duty (an RBAC feature)
217: // it will handle SSOD purpose in a static way with
218: // any AuthorizationManager implementation
219:
220: // Find the UserPrincipal to evaluate definitions
221: UserPrincipal userPrincipal = null;
222: Iterator userPrincipalsIt = principals.iterator();
223: while (userPrincipalsIt.hasNext()) {
224: Principal ppal = (Principal) userPrincipalsIt.next();
225: if (ppal instanceof UserPrincipal) {
226: userPrincipal = (UserPrincipal) ppal;
227: break;
228: }
229: }
230:
231: RolePrincipal tempUserPrincipal;
232: RolePrincipal tempDefinedPrincipal;
233:
234: Iterator definedPrincipalsIt;
235:
236: userPrincipalsIt = principals.iterator();
237:
238: //add all RolePrincipal permissions to JGPermissionCollection
239: while (userPrincipalsIt.hasNext()) {
240: Principal ppal = (Principal) userPrincipalsIt.next();
241: if (!(ppal instanceof RolePrincipal)) {
242: //we skip principal which are not RolePrincipal
243: //only jGuardPrincipals own permissions
244: continue;
245: } else {
246: tempUserPrincipal = (RolePrincipal) ppal;
247: }
248:
249: //we don't add the RolePrincipal if its definition is false
250: if (!PermissionUtils.evaluatePrincipal(tempUserPrincipal,
251: userPrincipal)) {
252: continue;
253: }
254:
255: if (logger.isLoggable(Level.FINEST)) {
256: logger
257: .finest("getPermissionCollection() - user's principal name="
258: + tempUserPrincipal.getLocalName());
259: logger
260: .finest("getPermissionCollection() - user's principal applicationName="
261: + tempUserPrincipal
262: .getApplicationName());
263: }
264: definedPrincipalsIt = principalsSet.iterator();
265: //we search the corresponding defined Principal
266: while (definedPrincipalsIt.hasNext()) {
267: tempDefinedPrincipal = (RolePrincipal) definedPrincipalsIt
268: .next();
269: if (logger.isLoggable(Level.FINEST)) {
270: logger
271: .finest("getPermissionCollection() - system's principal name="
272: + tempDefinedPrincipal
273: .getLocalName());
274: logger
275: .finest("getPermissionCollection() - system's principal applicationName="
276: + applicationName);
277: }
278:
279: //if RolePrincipal owned by the user(Authentication side) matches
280: //with the RolePrincipal owned by the application(Authorization side),
281: //we add all the related permissions in the PermissionCollection of the user
282: if (tempDefinedPrincipal.equals(tempUserPrincipal)) {
283: if (logger.isLoggable(Level.FINEST)) {
284: logger
285: .finest("getPermissionCollection() - principal name="
286: + tempUserPrincipal
287: .getLocalName()
288: + " is declared in this application ");
289: }
290: urlpUser.addAll(tempDefinedPrincipal
291: .getAllPermissions());
292: Set tempset = tempDefinedPrincipal
293: .getAllPermissions();
294:
295: if (logger.isLoggable(Level.FINEST)) {
296: logger
297: .finest("getPermissionCollection() - permissions granted are :"
298: + tempset.toString());
299: }
300:
301: break;
302: }
303: }
304: }
305:
306: if (logger.isLoggable(Level.FINEST)) {
307: logger.finest(" user has got " + urlpUser.size()
308: + " permissions: \n" + urlpUser);
309: }
310:
311: //resolve regexp in permissions
312: JGPermissionCollection resolvedPermissions = (JGPermissionCollection) PermissionUtils
313: .evaluatePermissionCollection(pDomain,
314: (PermissionCollection) urlpUser);
315: //we remove unresolved permissions
316: //and replace them with the resolved one
317: //we do that to preserve the JGpermissionCollection subclass
318: //positive or negative
319: urlpUser.clear();
320: urlpUser.addAll(resolvedPermissions);
321:
322: //TODO CGA add Dynamic Separation Of Duty (DSOD) feature specified in RBAC
323: //(Role based Access Control)
324: //we will implement it as a Permissions subclass
325: //it will check permissions against DSO constraint in a static way
326: //in conjunction with the class WorkflowCheckerFactory
327:
328: return urlpUser;
329: }
330:
331: /**
332: * clone a RolePrincipal/Role and set its name with the name of the Principal to clone plus
333: * a random number.
334: * @param roleName RolePrincipal name to clone
335: * @return cloned RolePrincipal with a different name : original JguardPrincipal name + Random integer betweeen 0 and 99999
336: * @throws AuthorizationException
337: */
338: public Principal clonePrincipal(String roleName)
339: throws AuthorizationException {
340: Random rnd = new Random();
341: String cloneName = roleName + rnd.nextInt(99999);
342:
343: return clonePrincipal(roleName, cloneName);
344: }
345:
346: /**
347: * clone a RolePrincipal/Role.
348: * @param roleName RolePrincipal name to clone
349: * @param cloneName RolePrincipal cloned name
350: * @return cloned RolePrincipal with a different name : original JguardPrincipal name + Random integer betweeen 0 and 99999
351: * @throws AuthorizationException
352: */
353: public Principal clonePrincipal(String roleName, String cloneName)
354: throws AuthorizationException {
355: cloneName = RolePrincipal.getName(cloneName, applicationName);
356: Principal role = (Principal) principals.get(roleName);
357: Principal clone = null;
358: if (role instanceof RolePrincipal) {
359: clone = (RolePrincipal) ((RolePrincipal) role).clone();
360: ((RolePrincipal) clone).setName(cloneName);
361: } else
362: clone = PrincipalUtils.getPrincipal(role.getClass()
363: .getName(), cloneName);
364:
365: //persist the newly created clone
366: createPrincipal(clone);
367:
368: return clone;
369: }
370:
371: /**
372: * return Set of domains.
373: * @return domains Set
374: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#listDomains()
375: */
376: public Set listDomains() throws AuthorizationException {
377: return domainsSet;
378: }
379:
380: /**
381: * read an URLPermission.
382: * @param permissionName
383: * @throws AuthorizationException
384: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#readPermission(java.lang.String)
385: */
386: public Permission readPermission(String permissionName)
387: throws AuthorizationException {
388: try {
389: return urlp.getPermission(permissionName);
390: } catch (NoSuchPermissionException e) {
391: throw new AuthorizationException(" permission "
392: + permissionName + " not found ");
393: }
394: }
395:
396: /**
397: * return an Domain with its associated URLPermission set.
398: * @param domainName
399: * @return Domain
400: * @throws AuthorizationException
401: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#readDomain(java.lang.String)
402: */
403: public JGPermissionCollection readDomain(String domainName)
404: throws AuthorizationException {
405: JGPermissionCollection domainFound = (JGPermissionCollection) domains
406: .get(domainName);
407: if (domainFound == null) {
408: throw new AuthorizationException(" domain with name="
409: + domainName + " is not found");
410: }
411: return domainFound;
412: }
413:
414: /**
415: * return the corresponding application role.
416: * @return role
417: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#readPrincipal(java.lang.String)
418: * @throws AuthorizationException
419: */
420: public Principal readPrincipal(String roleName)
421: throws AuthorizationException {
422: Principal principalFound = (Principal) principals.get(roleName);
423: if (principalFound == null) {
424: throw new AuthorizationException(" principal with name="
425: + roleName + " is not found");
426: }
427: return principalFound;
428: }
429:
430: /**
431: * <p>Update the permissions from jGuardPrincipals that contains this domain.</p>
432: * <p><b>Note:</b> This method is need because, first, there are no warranty that the reference
433: * of domain in the RolePrincipal object are the same from domainsSet and map and, second, the
434: * getPermissions method from RolePrincipal don't load the permissions from domains objects
435: * (it use a internal set of permissions).</p>
436: * @param domain the domain that will be updated in the principals
437: */
438: protected void updatePrincipals(Domain domain) {
439: for (Iterator principalsIt = principalsSet.iterator(); principalsIt
440: .hasNext();) {
441: RolePrincipal principal = (RolePrincipal) principalsIt
442: .next();
443:
444: //2005-06-01 vinipitta:
445: //if the principal contains the domain we remove the domain from it and replace by the
446: //current(updated) version of the domain. This forces the principal to update the
447: //permission list
448: if (principal.getDomains().contains(domain)) {
449: principal.removeDomain(domain);
450: //if we use the principal.getDomains().add method instead then this will not work!
451: principal.addDomain(domain);
452: domainsSet.remove(domain);
453: domainsSet.add(domain);
454: domains.remove(domain.getName());
455: domains.put(domain.getName(), domain);
456: }
457: }
458: }
459:
460: /**
461: * <p>Update the permissions from jGuardPrincipals <b>and</b> the associated domain.</p>
462: * <p><b>Note:</b> This method is need because, first, there are no warranty that the reference
463: * of domain in the RolePrincipal object are the same from domainsSet and map and, second, the
464: * getPermissions method from RolePrincipal don't load the permissions from domains objects
465: * (it use a internal set of permissions).</p>
466: * @param permission whose domain will be updated in the principals
467: */
468: protected void updatePrincipals(Permission permission) {
469: for (Iterator principalsIt = principalsSet.iterator(); principalsIt
470: .hasNext();) {
471: RolePrincipal principal = (RolePrincipal) principalsIt
472: .next();
473: Domain domain = getDomain(permission);
474: //2005-06-01 vinipitta:
475: //if the principal contains the domain we remove the domain from it and replace by the
476: //current(updated) version of the domain. This forces the principal to update the
477: //permission list
478: if (principal.getDomains().contains(domain)) {
479: principal.removeDomain(domain);
480: //if we use the principal.getDomains().add method instead then this will not work!
481: principal.addDomain(domain);
482: domainsSet.remove(domain);
483: domainsSet.add(domain);
484: domains.remove(domain.getName());
485: domains.put(domain.getName(), domain);
486: //we handle the use case when the principal is ited directly
487: //to a permission and not indirectly through a domain
488: } else if (principal.getOrphanedPermissions().contains(
489: permission)) {
490: principal.getOrphanedPermissions().remove(permission);
491: principal.getOrphanedPermissions().add(permission);
492: principal.getPermissions().remove(permission);
493: principal.getPermissions().add(permission);
494:
495: }
496: }
497: }
498:
499: /**
500: * update the principals with this updated domain.
501: * it implies a suppress and an addition.
502: * @param newDomain
503: * @param oldDomainName
504: */
505: protected void updatePrincipals(JGPermissionCollection newDomain,
506: String oldDomainName) {
507: JGPermissionCollection domain = new Domain(oldDomainName);
508:
509: for (Iterator principalsIt = principalsSet.iterator(); principalsIt
510: .hasNext();) {
511: RolePrincipal principal = (RolePrincipal) principalsIt
512: .next();
513:
514: //2005-06-01 vinipitta:
515: //if the principal contains the domain we remove the domain from it and replace by the
516: //current(updated) version of the domain. This forces the principal to update the
517: //permission list
518: if (principal.getDomains().contains(domain)) {
519: principal.removeDomain(domain);
520: //if we use the principal.getDomains().add method instead then this will not work!
521: principal.addDomain(newDomain);
522: }
523: }
524: }
525:
526: /**
527: * Remove the domain from all principals that have relationship with this domain.
528: * @param domainName the name of the domain that will be removed
529: */
530: protected void removeDomainFromPrincipals(String domainName) {
531: JGPermissionCollection domain = new Domain(domainName);
532:
533: for (Iterator principalsIt = principalsSet.iterator(); principalsIt
534: .hasNext();) {
535: RolePrincipal principal = (RolePrincipal) principalsIt
536: .next();
537: if (principal.getDomains().contains(domain)) {
538: principal.removeDomain(domain);
539: domains.remove(domain);
540: domainsSet.remove(domain);
541: }
542: }
543: }
544:
545: /**
546: * Remove the permission from all principals that have relationship with this permission like a
547: * orphaned permission (directly), or through a domain (indirectly).
548: * @param permissionName the name of the permission that will be removed
549: */
550: protected void removePermissionFromPrincipals(String permissionName) {
551: Permission permission = (Permission) permissions
552: .get(permissionName);
553:
554: for (Iterator principalsIt = principalsSet.iterator(); principalsIt
555: .hasNext();) {
556: RolePrincipal principal = (RolePrincipal) principalsIt
557: .next();
558: if (principal.getOrphanedPermissions().contains(permission)) {
559: principal.getOrphanedPermissions().remove(permission);
560: principal.getPermissions().remove(permission);
561: logger.finest("removePermissionFromPrincipals: "
562: + permission);
563: } else if (principal.getPermissionsFromDomains().contains(
564: permission)) {
565: principal.getPermissionsFromDomains()
566: .remove(permission);
567: principal.getPermissions().remove(permission);
568: logger.finest("removePermissionFromPrincipals: "
569: + permission);
570: }
571: }
572: }
573:
574: /**
575: * return the domain which contains the permission.
576: * @param permission
577: * @return domain which owns the permission or null if no domain contains
578: * this permisison
579: */
580: protected Domain getDomain(Permission permission) {
581: Iterator iterator = domainsSet.iterator();
582: while (iterator.hasNext()) {
583: Domain temp = (Domain) iterator.next();
584: if (temp.containsPermission(permission)) {
585: return temp;
586: }
587: }
588: //no domains contains this permission
589: return null;
590: }
591:
592: /**
593: * add the permission to the corresponding role.
594: * if the permission is not persisted, we persist it and create
595: * a corresponding Domain with the same name.
596: * @param roleName role updated
597: * @param perm permission to add
598: * @throws AuthorizationException
599: */
600: public void addToPrincipal(String roleName, Permission perm)
601: throws AuthorizationException {
602: RolePrincipal role = (RolePrincipal) principals.get(roleName);
603: if (role == null) {
604: throw new SecurityException(" Principal/role " + roleName
605: + " does not exists ");
606: }
607: //if permission does not exists, we add it
608: // and create a corresponding domain with the same name
609: if (!permissionsSet.contains(perm)) {
610: permissionsSet.add(perm);
611: permissions.put(perm.getName(), perm);
612: createDomain(perm.getName());
613: createPermission(perm, perm.getName());
614: }
615: role.addPermission(perm);
616: }
617:
618: /**
619: * add the domain to the role, and
620: * persist the domain if it does not exists?
621: * @param roleName
622: * @param domain
623: * @throws AuthorizationException
624: */
625: public void addToPrincipal(String roleName, Domain domain)
626: throws AuthorizationException {
627: RolePrincipal role = (RolePrincipal) principals.get(roleName);
628: if (role == null) {
629: throw new SecurityException(" Principal/role " + roleName
630: + " does not exists ");
631: }
632:
633: if (domainsSet.contains(domain)) {
634: domainsSet.add(domain);
635: domains.put(domain.getName(), domain);
636: createDomain(domain.getName());
637: }
638:
639: role.addDomain(domain);
640: }
641:
642: /**
643: * This commands establishes a new immediate inheritance relationship
644: * between the existing principals/principals roleAsc and the roleDesc.
645: * The command is valid if and only if the role roleAsc is not an immediate
646: * ascendant of roleDesc, and descendant does
647: * not properly inherit roleAsc principal/role (in order to avoid cycle creation).
648: *
649: * @param principalAscName the principal/role <strong>local</strong> name that will inherite.
650: * @param principalDescName the principal/role <strong>local</strong> name that will be inherited.
651: * @throws AuthorizationException if the inheritance already exists or create a cycle.
652: */
653: public void addInheritance(String principalAscName,
654: String principalDescName) throws AuthorizationException {
655:
656: //getting the principals
657: Principal principalAsc = (Principal) principals
658: .get(principalAscName);
659: Principal principalDesc = (Principal) principals
660: .get(principalDescName);
661:
662: if (principalAscName.equals(principalDescName)) {
663: logger
664: .severe("ascendant and descendant cannot be the same principal ");
665: throw new AuthorizationException(
666: "ascendant and descendant cannot be the same principal ");
667: }
668:
669: if (principalAsc == null) {
670: logger.severe("Role " + principalAscName + " not found!");
671: throw new AuthorizationException("Role " + principalAscName
672: + " not found!");
673: }
674:
675: if (principalDesc == null) {
676: logger.severe("Role " + principalDescName + " not found!");
677: throw new AuthorizationException("Role "
678: + principalDescName + " not found!");
679: }
680:
681: if (!RolePrincipal.class.isAssignableFrom(principalAsc
682: .getClass())
683: || !RolePrincipal.class.isAssignableFrom(principalDesc
684: .getClass())) {
685: throw new AuthorizationException(
686: " role inheritance is only supported by RolePrincipal \n roleAsc class="
687: + principalAsc.getClass().getName()
688: + " \n roleDesc class="
689: + principalDesc.getClass().getName());
690: }
691:
692: //check if the roleAsc is immediate ascendant of roleDesc
693: for (Iterator it = ((RolePrincipal) principalAsc)
694: .getDescendants().iterator(); it.hasNext();) {
695: if (principalDesc.equals(it.next())) {
696: logger.severe("Role " + principalAscName
697: + " is immediate ascendant of role "
698: + principalDescName + "!");
699: throw new AuthorizationException("Role "
700: + principalAscName
701: + " is immediate ascendant of role "
702: + principalDescName + "!");
703: }
704: }
705:
706: //check if roleDesc inherit roleAsc
707: //use a stack instead of a recursive method
708: Stack rolesToCheck = new Stack();
709: //used to check first all principals from one level before check the next level
710: Stack rolesFromNextLevel = new Stack();
711: rolesToCheck.addAll(((RolePrincipal) principalDesc)
712: .getDescendants());
713:
714: while (!rolesToCheck.isEmpty()) {
715: RolePrincipal role = (RolePrincipal) rolesToCheck.pop();
716: if (principalAsc.equals(role)) {
717: logger.severe("Role " + principalAscName
718: + " cannot inherit role " + principalDescName
719: + " because " + principalDescName + " inherit "
720: + principalAscName);
721: throw new AuthorizationException("Role "
722: + principalAscName + " cannot inherit role "
723: + principalDescName + " because "
724: + principalDescName + " inherit "
725: + principalAscName);
726: }
727:
728: rolesFromNextLevel.addAll(role.getDescendants());
729:
730: //is time to go to next level
731: if (rolesToCheck.isEmpty()) {
732: rolesToCheck.addAll(rolesFromNextLevel);
733:
734: //clear the second level stack
735: rolesFromNextLevel.clear();
736: }
737: }
738:
739: //update in-memory role
740: ((RolePrincipal) principalAsc).getDescendants().add(
741: principalDesc);
742:
743: //update xml
744: updatePrincipal((RolePrincipal) principalAsc);
745: }
746:
747: /**
748: * @param roleAscName the role that inherit.
749: * @param roleDescName the role that is inherited.
750: * @throws AuthorizationException if the inheritance already exists or create a cycle.
751: */
752: public void deleteInheritance(String roleAscName,
753: String roleDescName) throws AuthorizationException {
754: RolePrincipal roleAsc = (RolePrincipal) principals
755: .get(roleAscName);
756: roleAsc.getDescendants().remove(principals.get(roleDescName));
757: updatePrincipal(roleAsc);
758: }
759:
760: /**
761: * replace the inital principal with the new one.
762: * @param principal RolePrincipal updated
763: * @throws AuthorizationException
764: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#updatePrincipal(net.sf.jguard.core.principals.RolePrincipal)
765: */
766: public void updatePrincipal(Principal principal)
767: throws AuthorizationException {
768: deletePrincipal(principal);
769: createPrincipal(principal);
770: logger.finest(" updated principal=" + principal);
771: }
772:
773: /**
774: * assembly the hierarchy of jGuardPrincipals.
775: */
776: protected void assemblyHierarchy() {
777: //now that every principal is mapped, assembly the hierarchy.
778: for (Iterator it = hierarchyMap.keySet().iterator(); it
779: .hasNext();) {
780: String ascendantName = (String) it.next();
781: RolePrincipal ascendant = (RolePrincipal) principals
782: .get(ascendantName);
783:
784: for (Iterator it2 = ((List) hierarchyMap.get(ascendantName))
785: .iterator(); it2.hasNext();) {
786: RolePrincipal descendant = (RolePrincipal) it2.next();
787: ascendant.getDescendants().add(descendant);
788: logger.finest("Role " + ascendantName
789: + " inherits from role "
790: + descendant.getLocalName());
791: }
792: }
793: }
794:
795: /**
796: *
797: * @param principal
798: */
799: protected void deleteReferenceInHierarchy(RolePrincipal principal) {
800: String principalName = principal.getLocalName();
801:
802: //clean the hierarchy
803: for (Iterator it = hierarchyMap.keySet().iterator(); it
804: .hasNext();) {
805: String ascendantName = (String) it.next();
806: if (principalName.equals(ascendantName)) {
807: //we remove in memory the deleted principal
808: hierarchyMap.remove(ascendantName);
809: } else {
810: List descendants = (List) hierarchyMap
811: .get(ascendantName);
812: descendants.remove(principal);
813: }
814: }
815:
816: //clean descendants references in the principal Map
817: Collection values = principals.values();
818: Iterator itValues = values.iterator();
819: while (itValues.hasNext()) {
820: RolePrincipal ppalTemp = (RolePrincipal) itValues.next();
821: ppalTemp.getDescendants().remove(principal);
822: }
823:
824: //clean descendants references in the principal Set
825: Iterator itPrincipalsSet = principalsSet.iterator();
826: while (itPrincipalsSet.hasNext()) {
827: RolePrincipal ppalTemp = (RolePrincipal) itPrincipalsSet
828: .next();
829: ppalTemp.getDescendants().remove(principal);
830: }
831:
832: }
833:
834: /**
835: * return the principal's Set.
836: * @return principal's Set
837: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#listPrincipals()
838: */
839: public Set listPrincipals() {
840: return principalsSet;
841: }
842:
843: /**
844: * return all the permissions.
845: * @return URLPermission container
846: * @see net.sf.jguard.ext.authorization.manager.AuthorizationManager#listPermissions()
847: */
848: public JGPermissionCollection listPermissions() {
849: return new JGPositivePermissionCollection(permissionsSet);
850: }
851:
852: /**
853: * import data from the provided AbstractAuthorizationManager into
854: * our AuthorizationManager.
855: * @param authManager
856: * @throws AuthorizationException
857: */
858: public void importAuthorizationManager(
859: AuthorizationManager authManager)
860: throws AuthorizationException {
861: if (authManager.isEmpty()) {
862: logger.warning(" authManager to import is empty ");
863: return;
864: }
865: //import domains set and associated permissions
866: Set domains = authManager.getDomainsSet();
867: Iterator itDomains = domains.iterator();
868: while (itDomains.hasNext()) {
869: Domain domain = (Domain) itDomains.next();
870: createDomain(domain.getName());
871: Iterator itPermissions = domain.getPermissions().iterator();
872: while (itPermissions.hasNext()) {
873: Permission perm = (Permission) itPermissions.next();
874: createPermission(perm, domain.getName());
875: }
876: }
877:
878: //import principal set
879: Set Principals = authManager.getPrincipalsSet();
880: Iterator itPrincipals = Principals.iterator();
881: while (itPrincipals.hasNext()) {
882: Principal principal = (Principal) itPrincipals.next();
883: createPrincipal(principal);
884: }
885:
886: //import principal inheritance
887: Iterator itPrincipals2 = Principals.iterator();
888: while (itPrincipals2.hasNext()) {
889: Principal principal = (Principal) itPrincipals2.next();
890: if (principal instanceof RolePrincipal) {
891: RolePrincipal ppal = (RolePrincipal) principal;
892: Set descendants = ppal.getDescendants();
893: Iterator itDescendants = descendants.iterator();
894: while (itDescendants.hasNext()) {
895: RolePrincipal descPrincipal = (RolePrincipal) itDescendants
896: .next();
897: addInheritance(getLocalName(principal),
898: getLocalName(descPrincipal));
899: }
900: }
901: }
902:
903: }
904:
905: public final Set getDomainsSet() {
906: return Collections.unmodifiableSet(domainsSet);
907: }
908:
909: public final Map getDomains() {
910: return Collections.unmodifiableMap(domains);
911: }
912:
913: public final Map getDomainsPermissions() {
914: return Collections.unmodifiableMap(domainsPermissions);
915: }
916:
917: public final Map getHierarchyMap() {
918: return Collections.unmodifiableMap(hierarchyMap);
919: }
920:
921: public final Map getPermissions() {
922: return Collections.unmodifiableMap(permissions);
923: }
924:
925: public final Set getPermissionsSet() {
926: return Collections.unmodifiableSet(permissionsSet);
927: }
928:
929: public final Map getPrincipals() {
930: return Collections.unmodifiableMap(principals);
931: }
932:
933: public final Set getPrincipalsSet() {
934: return Collections.unmodifiableSet(principalsSet);
935: }
936:
937: protected static String getLocalName(Principal principal) {
938:
939: String name = null;
940: if (principal instanceof RolePrincipal) {
941: RolePrincipal rolePrincipal = (RolePrincipal) principal;
942: name = rolePrincipal.getLocalName();
943: } else {
944: name = principal.getName();
945: }
946: return name;
947: }
948:
949: }
|