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 }