001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.acl.basic;
017:
018: import org.acegisecurity.Authentication;
019: import org.acegisecurity.GrantedAuthority;
020:
021: import org.acegisecurity.acl.AclEntry;
022:
023: import org.acegisecurity.userdetails.UserDetails;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027:
028: import java.util.List;
029: import java.util.Vector;
030:
031: /**
032: * Simple implementation of {@link EffectiveAclsResolver}.<P>This implementation does not need to understand the
033: * "recipient" types presented in a <code>BasicAclEntry</code> because it merely delegates to the detected {@link
034: * Authentication#getPrincipal()} or {@link Authentication#getAuthorities()}. The principal object or granted
035: * authorities object has its <code>Object.equals(recipient)</code> method called to make the decision as to whether
036: * the recipient in the <code>BasicAclEntry</code> is the same as the principal or granted authority.</p>
037: * <P>This class should prove an adequate ACLs resolver if you're using standard Acegi Security classes. This is
038: * because the typical <code>Authentication</code> token is <code>UsernamePasswordAuthenticationToken</code>, which
039: * for its <code>principal</code> is usually a <code>String</code>. The <code>GrantedAuthorityImpl</code> is typically
040: * used for granted authorities, which tests for equality based on a <code>String</code>. This means
041: * <code>BasicAclDao</code>s simply need to return a <code>String</code> to represent the recipient. If you use
042: * non-<code>String</code> objects, you will probably require an alternative <code>EffectiveAclsResolver</code>.</p>
043: *
044: * @author Ben Alex
045: * @version $Id: GrantedAuthorityEffectiveAclsResolver.java 1784 2007-02-24 21:00:24Z luke_t $
046: */
047: public class GrantedAuthorityEffectiveAclsResolver implements
048: EffectiveAclsResolver {
049: //~ Static fields/initializers =====================================================================================
050:
051: private static final Log logger = LogFactory
052: .getLog(GrantedAuthorityEffectiveAclsResolver.class);
053:
054: //~ Methods ========================================================================================================
055:
056: public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls,
057: Authentication filteredBy) {
058: if ((allAcls == null) || (allAcls.length == 0)) {
059: return null;
060: }
061:
062: List list = new Vector();
063:
064: if (logger.isDebugEnabled()) {
065: logger.debug("Locating AclEntry[]s (from set of "
066: + ((allAcls == null) ? 0 : allAcls.length)
067: + ") that apply to Authentication: " + filteredBy);
068: }
069:
070: for (int i = 0; i < allAcls.length; i++) {
071: if (!(allAcls[i] instanceof BasicAclEntry)) {
072: continue;
073: }
074:
075: Object recipient = ((BasicAclEntry) allAcls[i])
076: .getRecipient();
077:
078: // Allow the Authentication's getPrincipal to decide whether
079: // the presented recipient is "equal" (allows BasicAclDaos to
080: // return Strings rather than proper objects in simple cases)
081: if (filteredBy.getPrincipal().equals(recipient)) {
082: if (logger.isDebugEnabled()) {
083: logger
084: .debug("Principal matches AclEntry recipient: "
085: + recipient);
086: }
087:
088: list.add(allAcls[i]);
089: } else if (filteredBy.getPrincipal() instanceof UserDetails
090: && ((UserDetails) filteredBy.getPrincipal())
091: .getUsername().equals(recipient)) {
092: if (logger.isDebugEnabled()) {
093: logger
094: .debug("Principal (from UserDetails) matches AclEntry recipient: "
095: + recipient);
096: }
097:
098: list.add(allAcls[i]);
099: } else {
100: // No direct match against principal; try each authority.
101: // As with the principal, allow each of the Authentication's
102: // granted authorities to decide whether the presented
103: // recipient is "equal"
104: GrantedAuthority[] authorities = filteredBy
105: .getAuthorities();
106:
107: if ((authorities == null) || (authorities.length == 0)) {
108: if (logger.isDebugEnabled()) {
109: logger
110: .debug("Did not match principal and there are no granted authorities, "
111: + "so cannot compare with recipient: "
112: + recipient);
113: }
114:
115: continue;
116: }
117:
118: for (int k = 0; k < authorities.length; k++) {
119: if (authorities[k].equals(recipient)) {
120: if (logger.isDebugEnabled()) {
121: logger.debug("GrantedAuthority: "
122: + authorities[k]
123: + " matches recipient: "
124: + recipient);
125: }
126:
127: list.add(allAcls[i]);
128: }
129: }
130: }
131: }
132:
133: // return null if appropriate (as per interface contract)
134: if (list.size() > 0) {
135: if (logger.isDebugEnabled()) {
136: logger.debug("Returning effective AclEntry array with "
137: + list.size() + " elements");
138: }
139:
140: return (BasicAclEntry[]) list
141: .toArray(new BasicAclEntry[] {});
142: } else {
143: if (logger.isDebugEnabled()) {
144: logger
145: .debug("Returning null AclEntry array as zero effective AclEntrys found");
146: }
147:
148: return null;
149: }
150: }
151: }
|