View Javadoc

1   /* Copyright 2004 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  package org.acegisecurity.acl.basic;
17  
18  import org.acegisecurity.Authentication;
19  import org.acegisecurity.GrantedAuthority;
20  import org.acegisecurity.acl.AclEntry;
21  import org.acegisecurity.userdetails.UserDetails;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  
26  import java.util.List;
27  import java.util.Vector;
28  
29  
30  /***
31   * Simple implementation of {@link EffectiveAclsResolver}.
32   * 
33   * <P>
34   * This implementation does not need to understand the "recipient" types
35   * presented in a <code>BasicAclEntry</code> because it merely delegates to
36   * the detected {@link Authentication#getPrincipal()} or {@link
37   * Authentication#getAuthorities()}. The principal object or granted
38   * authorities object has its <code>Object.equals(recipient)</code> method
39   * called to make the decision as to whether the recipient in the
40   * <code>BasicAclEntry</code> is the same as the principal or granted
41   * authority.
42   * </p>
43   * 
44   * <P>
45   * This class should prove an adequate ACLs resolver if you're using standard
46   * Acegi Security classes. This is because the typical
47   * <code>Authentication</code> token is
48   * <code>UsernamePasswordAuthenticationToken</code>, which for its
49   * <code>principal</code> is usually a <code>String</code>. The
50   * <code>GrantedAuthorityImpl</code> is typically used for granted
51   * authorities, which tests for equality based on a <code>String</code>. This
52   * means <code>BasicAclDao</code>s simply need to return a <code>String</code>
53   * to represent the recipient. If you use non-<code>String</code> objects, you
54   * will probably require an alternative <code>EffectiveAclsResolver</code>.
55   * </p>
56   *
57   * @author Ben Alex
58   * @version $Id: GrantedAuthorityEffectiveAclsResolver.java,v 1.6 2005/11/29 13:10:11 benalex Exp $
59   */
60  public class GrantedAuthorityEffectiveAclsResolver
61      implements EffectiveAclsResolver {
62      //~ Static fields/initializers =============================================
63  
64      private static final Log logger = LogFactory.getLog(GrantedAuthorityEffectiveAclsResolver.class);
65  
66      //~ Methods ================================================================
67  
68      public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls,
69          Authentication filteredBy) {
70          if ((allAcls == null) || (allAcls.length == 0)) {
71              return null;
72          }
73  
74          List list = new Vector();
75  
76          if (logger.isDebugEnabled()) {
77              logger.debug("Locating AclEntry[]s (from set of "
78                  + ((allAcls == null) ? 0 : allAcls.length)
79                  + ") that apply to Authentication: " + filteredBy);
80          }
81  
82          for (int i = 0; i < allAcls.length; i++) {
83              if (!(allAcls[i] instanceof BasicAclEntry)) {
84                  continue;
85              }
86  
87              Object recipient = ((BasicAclEntry) allAcls[i])
88                  .getRecipient();
89  
90              // Allow the Authentication's getPrincipal to decide whether
91              // the presented recipient is "equal" (allows BasicAclDaos to
92              // return Strings rather than proper objects in simple cases)
93              if (filteredBy.getPrincipal().equals(recipient)) {
94                  if (logger.isDebugEnabled()) {
95                      logger.debug("Principal matches AclEntry recipient: "
96                          + recipient);
97                  }
98  
99                  list.add(allAcls[i]);
100             } else if (filteredBy.getPrincipal() instanceof UserDetails
101                 && ((UserDetails) filteredBy.getPrincipal()).getUsername()
102                     .equals(recipient)) {
103                 if (logger.isDebugEnabled()) {
104                     logger.debug(
105                         "Principal (from UserDetails) matches AclEntry recipient: "
106                         + recipient);
107                 }
108 
109                 list.add(allAcls[i]);
110             } else {
111                 // No direct match against principal; try each authority.
112                 // As with the principal, allow each of the Authentication's
113                 // granted authorities to decide whether the presented
114                 // recipient is "equal"
115                 GrantedAuthority[] authorities = filteredBy.getAuthorities();
116 
117                 if ((authorities == null) || (authorities.length == 0)) {
118                     if (logger.isDebugEnabled()) {
119                         logger.debug(
120                             "Did not match principal and there are no granted authorities, so cannot compare with recipient: "
121                             + recipient);
122                     }
123 
124                     continue;
125                 }
126 
127                 for (int k = 0; k < authorities.length; k++) {
128                     if (authorities[k].equals(recipient)) {
129                         if (logger.isDebugEnabled()) {
130                             logger.debug("GrantedAuthority: " + authorities[k]
131                                 + " matches recipient: " + recipient);
132                         }
133 
134                         list.add(allAcls[i]);
135                     }
136                 }
137             }
138         }
139 
140         // return null if appropriate (as per interface contract)
141         if (list.size() > 0) {
142             if (logger.isDebugEnabled()) {
143                 logger.debug("Returning effective AclEntry array with "
144                     + list.size() + " elements");
145             }
146 
147             return (BasicAclEntry[]) list.toArray(new BasicAclEntry[] {});
148         } else {
149             if (logger.isDebugEnabled()) {
150                 logger.debug(
151                     "Returning null AclEntry array as zero effective AclEntrys found");
152             }
153 
154             return null;
155         }
156     }
157 }