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