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.afterinvocation;
017:
018: import org.acegisecurity.AccessDeniedException;
019: import org.acegisecurity.AfterInvocationManager;
020: import org.acegisecurity.Authentication;
021: import org.acegisecurity.ConfigAttribute;
022: import org.acegisecurity.ConfigAttributeDefinition;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import org.springframework.beans.factory.InitializingBean;
028:
029: import java.util.Iterator;
030: import java.util.List;
031:
032: /**
033: * Provider-based implementation of {@link AfterInvocationManager}.<p>Handles configuration of a bean context
034: * defined list of {@link AfterInvocationProvider}s.</p>
035: * <p>Every <code>AfterInvocationProvider</code> will be polled when the {@link #decide(Authentication, Object,
036: * ConfigAttributeDefinition, Object)} method is called. The <code>Object</code> returned from each provider will be
037: * presented to the successive provider for processing. This means each provider <b>must</b> ensure they return the
038: * <code>Object</code>, even if they are not interested in the "after invocation" decision (perhaps as the secure
039: * object invocation did not include a configuration attribute a given provider is configured to respond to).</p>
040: *
041: * @author Ben Alex
042: * @version $Id: AfterInvocationProviderManager.java 1496 2006-05-23 13:38:33Z benalex $
043: */
044: public class AfterInvocationProviderManager implements
045: AfterInvocationManager, InitializingBean {
046: //~ Static fields/initializers =====================================================================================
047:
048: protected static final Log logger = LogFactory
049: .getLog(AfterInvocationProviderManager.class);
050:
051: //~ Instance fields ================================================================================================
052:
053: private List providers;
054:
055: //~ Methods ========================================================================================================
056:
057: public void afterPropertiesSet() throws Exception {
058: checkIfValidList(this .providers);
059: }
060:
061: private void checkIfValidList(List listToCheck) {
062: if ((listToCheck == null) || (listToCheck.size() == 0)) {
063: throw new IllegalArgumentException(
064: "A list of AfterInvocationProviders is required");
065: }
066: }
067:
068: public Object decide(Authentication authentication, Object object,
069: ConfigAttributeDefinition config, Object returnedObject)
070: throws AccessDeniedException {
071: Iterator iter = this .providers.iterator();
072:
073: Object result = returnedObject;
074:
075: while (iter.hasNext()) {
076: AfterInvocationProvider provider = (AfterInvocationProvider) iter
077: .next();
078: result = provider.decide(authentication, object, config,
079: result);
080: }
081:
082: return result;
083: }
084:
085: public List getProviders() {
086: return this .providers;
087: }
088:
089: public void setProviders(List newList) {
090: checkIfValidList(newList);
091:
092: Iterator iter = newList.iterator();
093:
094: while (iter.hasNext()) {
095: Object currentObject = null;
096:
097: try {
098: currentObject = iter.next();
099:
100: AfterInvocationProvider attemptToCast = (AfterInvocationProvider) currentObject;
101: } catch (ClassCastException cce) {
102: throw new IllegalArgumentException(
103: "AfterInvocationProvider "
104: + currentObject.getClass().getName()
105: + " must implement AfterInvocationProvider");
106: }
107: }
108:
109: this .providers = newList;
110: }
111:
112: public boolean supports(ConfigAttribute attribute) {
113: Iterator iter = this .providers.iterator();
114:
115: while (iter.hasNext()) {
116: AfterInvocationProvider provider = (AfterInvocationProvider) iter
117: .next();
118:
119: if (logger.isDebugEnabled()) {
120: logger.debug("Evaluating " + attribute + " against "
121: + 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 each can support the presented
134: * class.<p>If one or more providers cannot support the presented class, <code>false</code> is returned.</p>
135: *
136: * @param clazz the secure object class being queries
137: *
138: * @return if the <code>AfterInvocationProviderManager</code> can support the secure object class, which requires
139: * every one of its <code>AfterInvocationProvider</code>s to support the secure object class
140: */
141: public boolean supports(Class clazz) {
142: Iterator iter = this .providers.iterator();
143:
144: while (iter.hasNext()) {
145: AfterInvocationProvider provider = (AfterInvocationProvider) iter
146: .next();
147:
148: if (!provider.supports(clazz)) {
149: return false;
150: }
151: }
152:
153: return true;
154: }
155: }
|