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.afterinvocation;
17  
18  import org.acegisecurity.AccessDeniedException;
19  import org.acegisecurity.AfterInvocationManager;
20  import org.acegisecurity.Authentication;
21  import org.acegisecurity.ConfigAttribute;
22  import org.acegisecurity.ConfigAttributeDefinition;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  import org.springframework.beans.factory.InitializingBean;
28  
29  import java.util.Iterator;
30  import java.util.List;
31  
32  
33  /***
34   * Provider-based implementation of {@link AfterInvocationManager}.
35   * 
36   * <p>
37   * Handles configuration of a bean context defined list of  {@link
38   * AfterInvocationProvider}s.
39   * </p>
40   * 
41   * <p>
42   * Every <code>AfterInvocationProvider</code> will be polled when the {@link
43   * #decide(Authentication, Object, ConfigAttributeDefinition, Object)} method
44   * is called. The <code>Object</code> returned from each provider will be
45   * presented to the successive provider for processing. This means each
46   * provider <b>must</b> ensure they return the <code>Object</code>, even if
47   * they are not interested in the "after invocation" decision (perhaps as the
48   * secure object invocation did not include a configuration attribute a given
49   * provider is configured to respond to).
50   * </p>
51   *
52   * @author Ben Alex
53   * @version $Id: AfterInvocationProviderManager.java,v 1.3 2005/11/17 00:55:56 benalex Exp $
54   */
55  public class AfterInvocationProviderManager implements AfterInvocationManager,
56      InitializingBean {
57      //~ Static fields/initializers =============================================
58  
59      protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class);
60  
61      //~ Instance fields ========================================================
62  
63      private List providers;
64  
65      //~ Methods ================================================================
66  
67      public void setProviders(List newList) {
68          checkIfValidList(newList);
69  
70          Iterator iter = newList.iterator();
71  
72          while (iter.hasNext()) {
73              Object currentObject = null;
74  
75              try {
76                  currentObject = iter.next();
77  
78                  AfterInvocationProvider attemptToCast = (AfterInvocationProvider) currentObject;
79              } catch (ClassCastException cce) {
80                  throw new IllegalArgumentException("AfterInvocationProvider "
81                      + currentObject.getClass().getName()
82                      + " must implement AfterInvocationProvider");
83              }
84          }
85  
86          this.providers = newList;
87      }
88  
89      public List getProviders() {
90          return this.providers;
91      }
92  
93      public void afterPropertiesSet() throws Exception {
94          checkIfValidList(this.providers);
95      }
96  
97      public Object decide(Authentication authentication, Object object,
98          ConfigAttributeDefinition config, Object returnedObject)
99          throws AccessDeniedException {
100         Iterator iter = this.providers.iterator();
101 
102         Object result = returnedObject;
103 
104         while (iter.hasNext()) {
105             AfterInvocationProvider provider = (AfterInvocationProvider) iter
106                 .next();
107             result = provider.decide(authentication, object, config, result);
108         }
109 
110         return result;
111     }
112 
113     public boolean supports(ConfigAttribute attribute) {
114         Iterator iter = this.providers.iterator();
115 
116         while (iter.hasNext()) {
117             AfterInvocationProvider provider = (AfterInvocationProvider) iter
118                 .next();
119 
120             if (logger.isDebugEnabled()) {
121                 logger.debug("Evaluating " + attribute + " against " + provider);
122             }
123 
124             if (provider.supports(attribute)) {
125                 return true;
126             }
127         }
128 
129         return false;
130     }
131 
132     /***
133      * Iterates through all <code>AfterInvocationProvider</code>s and ensures
134      * each can support the presented class.
135      * 
136      * <p>
137      * If one or more providers cannot support the presented class,
138      * <code>false</code> is returned.
139      * </p>
140      *
141      * @param clazz the secure object class being queries
142      *
143      * @return if the <code>AfterInvocationProviderManager</code> can support
144      *         the secure object class, which requires every one of its
145      *         <code>AfterInvocationProvider</code>s to support the secure
146      *         object class
147      */
148     public boolean supports(Class clazz) {
149         Iterator iter = this.providers.iterator();
150 
151         while (iter.hasNext()) {
152             AfterInvocationProvider provider = (AfterInvocationProvider) iter
153                 .next();
154 
155             if (!provider.supports(clazz)) {
156                 return false;
157             }
158         }
159 
160         return true;
161     }
162 
163     private void checkIfValidList(List listToCheck) {
164         if ((listToCheck == null) || (listToCheck.size() == 0)) {
165             throw new IllegalArgumentException(
166                 "A list of AfterInvocationProviders is required");
167         }
168     }
169 }