View Javadoc

    1   /*
    2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    * http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package edu.internet2.middleware.shibboleth.idp.profile;
    18
    19  import java.util.HashMap;
    20  import java.util.Map;
    21  import java.util.concurrent.locks.Lock;
    22
    23  import javax.servlet.ServletRequest;
    24  import javax.servlet.http.HttpServletRequest;
    25
    26  import org.slf4j.Logger;
    27  import org.slf4j.LoggerFactory;
    28  import org.springframework.context.ApplicationContext;
    29
    30  import edu.internet2.middleware.shibboleth.common.config.BaseReloadableService;
    31  import edu.internet2.middleware.shibboleth.common.profile.AbstractErrorHandler;
    32  import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
    33  import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
    34  import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractRequestURIMappedProfileHandler;
    35  import edu.internet2.middleware.shibboleth.common.service.ServiceException;
    36  import edu.internet2.middleware.shibboleth.idp.authn.LoginHandler;
    37
    38  /**
    39   * Implementation of a {@link ProfileHandlerManager} that maps the request path, without the servlet context, to a
    40   * profile handler and adds support for authentication handlers.
    41   */
    42  public class IdPProfileHandlerManager extends BaseReloadableService implements ProfileHandlerManager {
    43
    44      /** Class logger. */
    45      private final Logger log = LoggerFactory.getLogger(IdPProfileHandlerManager.class);
    46
    47      /** Handler used for errors. */
    48      private AbstractErrorHandler errorHandler;
    49
    50      /** Map of request paths to profile handlers. */
    51      private Map<String, AbstractRequestURIMappedProfileHandler> profileHandlers;
    52
    53      /** Map of authentication methods to login handlers. */
    54      private Map<String, LoginHandler> loginHandlers;
    55
    56      /** Constructor. */
    57      public IdPProfileHandlerManager() {
    58          super();
    59          profileHandlers = new HashMap<String, AbstractRequestURIMappedProfileHandler>();
    60          loginHandlers = new HashMap<String, LoginHandler>();
    61      }
    62
    63      /** {@inheritDoc} */
    64      public AbstractErrorHandler getErrorHandler() {
    65          return errorHandler;
    66      }
    67
    68      /**
    69       * Sets the error handler.
    70       *
    71       * @param handler error handler
    72       */
    73      public void setErrorHandler(AbstractErrorHandler handler) {
    74          if (handler == null) {
    75              throw new IllegalArgumentException("Error handler may not be null");
    76          }
    77          errorHandler = handler;
    78      }
    79
    80      /** {@inheritDoc} */
    81      public ProfileHandler getProfileHandler(ServletRequest request) {
    82          ProfileHandler handler;
    83
    84          String requestPath = ((HttpServletRequest) request).getPathInfo();
    85          log.debug("{}: Looking up profile handler for request path: {}", getId(), requestPath);
    86
    87          Lock readLock = getReadWriteLock().readLock();
    88          readLock.lock();
    89          try{
    90              handler = profileHandlers.get(requestPath);
    91          }finally{
    92              readLock.unlock();
    93          }
    94
    95          if (handler != null) {
    96              log.debug("{}: Located profile handler of the following type for the request path: {}", getId(), handler
    97                      .getClass().getName());
    98          } else {
    99              log.debug("{}: No profile handler registered for request path {}", getId(), requestPath);
    100         }
    101         return handler;
    102     }
    103
    104     /**
    105      * Gets the registered profile handlers.
    106      *
    107      * @return registered profile handlers
    108      */
    109     public Map<String, AbstractRequestURIMappedProfileHandler> getProfileHandlers() {
    110         return profileHandlers;
    111     }
    112
    113     /**
    114      * Gets the registered authentication handlers.
    115      *
    116      * @return registered authentication handlers
    117      */
    118     public Map<String, LoginHandler> getLoginHandlers() {
    119         return loginHandlers;
    120     }
    121
    122     /** {@inheritDoc} */
    123     protected void onNewContextCreated(ApplicationContext newServiceContext) throws ServiceException {
    124         log.debug("{}: Loading new configuration into service", getId());
    125         AbstractErrorHandler oldErrorHandler = errorHandler;
    126         Map<String, AbstractRequestURIMappedProfileHandler> oldProfileHandlers = profileHandlers;
    127         Map<String, LoginHandler> oldLoginHandlers = loginHandlers;
    128
    129         try {
    130             loadNewErrorHandler(newServiceContext);
    131             loadNewProfileHandlers(newServiceContext);
    132             loadNewLoginHandlers(newServiceContext);
    133         } catch (Exception e) {
    134             errorHandler = oldErrorHandler;
    135             profileHandlers = oldProfileHandlers;
    136             loginHandlers = oldLoginHandlers;
    137             throw new ServiceException(getId() + " configuration is not valid, retaining old configuration", e);
    138         }
    139     }
    140
    141     /**
    142      * Reads the new error handler from the newly created application context and loads it into this manager.
    143      *
    144      * @param newServiceContext newly created application context
    145      */
    146     protected void loadNewErrorHandler(ApplicationContext newServiceContext) {
    147         String[] errorBeanNames = newServiceContext.getBeanNamesForType(AbstractErrorHandler.class);
    148         log.debug("{}: Loading {} new error handler.", getId(), errorBeanNames.length);
    149
    150         errorHandler = (AbstractErrorHandler) newServiceContext.getBean(errorBeanNames[0]);
    151         log.debug("{}: Loaded new error handler of type: {}", getId(), errorHandler.getClass().getName());
    152     }
    153
    154     /**
    155      * Reads the new profile handlers from the newly created application context and loads it into this manager.
    156      *
    157      * @param newServiceContext newly created application context
    158      */
    159     protected void loadNewProfileHandlers(ApplicationContext newServiceContext) {
    160         String[] profileBeanNames = newServiceContext.getBeanNamesForType(AbstractRequestURIMappedProfileHandler.class);
    161         log.debug("{}: Loading {} new profile handlers.", getId(), profileBeanNames.length);
    162
    163         Map<String, AbstractRequestURIMappedProfileHandler> newProfileHandlers = new HashMap<String, AbstractRequestURIMappedProfileHandler>();
    164         AbstractRequestURIMappedProfileHandler<?, ?> profileHandler;
    165         for (String profileBeanName : profileBeanNames) {
    166             profileHandler = (AbstractRequestURIMappedProfileHandler) newServiceContext.getBean(profileBeanName);
    167             for (String requestPath : profileHandler.getRequestPaths()) {
    168                 newProfileHandlers.put(requestPath, profileHandler);
    169                 log.debug("{}: Loaded profile handler for handling requests to request path {}", getId(), requestPath);
    170             }
    171         }
    172         profileHandlers = newProfileHandlers;
    173     }
    174
    175     /**
    176      * Reads the new authentication handlers from the newly created application context and loads it into this manager.
    177      *
    178      * @param newServiceContext newly created application context
    179      */
    180     protected void loadNewLoginHandlers(ApplicationContext newServiceContext) {
    181         String[] authnBeanNames = newServiceContext.getBeanNamesForType(LoginHandler.class);
    182         log.debug("{}: Loading {} new authentication handlers.", getId(), authnBeanNames.length);
    183
    184         Map<String, LoginHandler> newLoginHandlers = new HashMap<String, LoginHandler>();
    185         LoginHandler authnHandler;
    186         for (String authnBeanName : authnBeanNames) {
    187             authnHandler = (LoginHandler) newServiceContext.getBean(authnBeanName);
    188             log.debug("{}: Loading authentication handler of type supporting authentication methods: {}", getId(),
    189                     authnHandler.getSupportedAuthenticationMethods());
    190
    191             for (String authnMethod : authnHandler.getSupportedAuthenticationMethods()) {
    192                 newLoginHandlers.put(authnMethod, authnHandler);
    193             }
    194         }
    195         loginHandlers = newLoginHandlers;
    196     }
    197 }