Cleanup service interface, make it easier and less error prone when creating new...
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / IdPProfileHandlerManager.java
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.idp.authn.LoginHandler;
36
37 /**
38  * Implementation of a {@link ProfileHandlerManager} that maps the request path, without the servlet context, to a
39  * profile handler and adds support for authentication handlers.
40  */
41 public class IdPProfileHandlerManager extends BaseReloadableService implements ProfileHandlerManager {
42
43     /** Class logger. */
44     private final Logger log = LoggerFactory.getLogger(IdPProfileHandlerManager.class);
45
46     /** Handler used for errors. */
47     private AbstractErrorHandler errorHandler;
48
49     /** Map of request paths to profile handlers. */
50     private Map<String, AbstractRequestURIMappedProfileHandler> profileHandlers;
51
52     /** Map of authentication methods to login handlers. */
53     private Map<String, LoginHandler> loginHandlers;
54
55     /** Constructor. */
56     public IdPProfileHandlerManager() {
57         super();
58         profileHandlers = new HashMap<String, AbstractRequestURIMappedProfileHandler>();
59         loginHandlers = new HashMap<String, LoginHandler>();
60     }
61
62     /** {@inheritDoc} */
63     public AbstractErrorHandler getErrorHandler() {
64         return errorHandler;
65     }
66
67     /**
68      * Sets the error handler.
69      * 
70      * @param handler error handler
71      */
72     public void setErrorHandler(AbstractErrorHandler handler) {
73         if (handler == null) {
74             throw new IllegalArgumentException("Error handler may not be null");
75         }
76         errorHandler = handler;
77     }
78
79     /** {@inheritDoc} */
80     public ProfileHandler getProfileHandler(ServletRequest request) {
81         ProfileHandler handler;
82
83         String requestPath = ((HttpServletRequest) request).getPathInfo();
84         log.debug("{}: Looking up profile handler for request path: {}", getId(), requestPath);
85
86         Lock readLock = getReadWriteLock().readLock();
87         readLock.lock();
88         handler = profileHandlers.get(requestPath);
89         readLock.unlock();
90
91         if (handler != null) {
92             log.debug("{}: Located profile handler of the following type for the request path: {}", getId(), handler
93                     .getClass().getName());
94         } else {
95             log.debug("{}: No profile handler registered for request path {}", getId(), requestPath);
96         }
97         return handler;
98     }
99
100     /**
101      * Gets the registered profile handlers.
102      * 
103      * @return registered profile handlers
104      */
105     public Map<String, AbstractRequestURIMappedProfileHandler> getProfileHandlers() {
106         return profileHandlers;
107     }
108
109     /**
110      * Gets the registered authentication handlers.
111      * 
112      * @return registered authentication handlers
113      */
114     public Map<String, LoginHandler> getLoginHandlers() {
115         return loginHandlers;
116     }
117
118     /** {@inheritDoc} */
119     protected void onNewContextCreated(ApplicationContext newServiceContext) {
120         log.debug("{}: Loading new configuration into service", getId());
121         Lock writeLock = getReadWriteLock().writeLock();
122         writeLock.lock();
123         loadNewErrorHandler(newServiceContext);
124         loadNewProfileHandlers(newServiceContext);
125         loadNewAuthenticationHandlers(newServiceContext);
126         writeLock.unlock();
127     }
128
129     /**
130      * Reads the new error handler from the newly created application context and loads it into this manager.
131      * 
132      * @param newServiceContext newly created application context
133      */
134     protected void loadNewErrorHandler(ApplicationContext newServiceContext) {
135         String[] errorBeanNames = newServiceContext.getBeanNamesForType(AbstractErrorHandler.class);
136         log.debug("{}: Loading {} new error handler.", getId(), errorBeanNames.length);
137
138         errorHandler = (AbstractErrorHandler) newServiceContext.getBean(errorBeanNames[0]);
139         log.debug("{}: Loaded new error handler of type: {}", getId(), errorHandler.getClass().getName());
140     }
141
142     /**
143      * Reads the new profile handlers from the newly created application context and loads it into this manager.
144      * 
145      * @param newServiceContext newly created application context
146      */
147     protected void loadNewProfileHandlers(ApplicationContext newServiceContext) {
148         String[] profileBeanNames = newServiceContext.getBeanNamesForType(AbstractRequestURIMappedProfileHandler.class);
149         log.debug("{}: Loading {} new profile handlers.", getId(), profileBeanNames.length);
150
151         profileHandlers.clear();
152         AbstractRequestURIMappedProfileHandler<?, ?> profileHandler;
153         for (String profileBeanName : profileBeanNames) {
154             profileHandler = (AbstractRequestURIMappedProfileHandler) newServiceContext.getBean(profileBeanName);
155             for (String requestPath : profileHandler.getRequestPaths()) {
156                 profileHandlers.put(requestPath, profileHandler);
157                 log.debug("{}: Loaded profile handler for handling requests to request path {}", getId(), requestPath);
158             }
159         }
160     }
161
162     /**
163      * Reads the new authentication handlers from the newly created application context and loads it into this manager.
164      * 
165      * @param newServiceContext newly created application context
166      */
167     protected void loadNewAuthenticationHandlers(ApplicationContext newServiceContext) {
168         String[] authnBeanNames = newServiceContext.getBeanNamesForType(LoginHandler.class);
169         log.debug("{}: Loading {} new authentication handlers.", getId(), authnBeanNames.length);
170
171         loginHandlers.clear();
172         LoginHandler authnHandler;
173         for (String authnBeanName : authnBeanNames) {
174             authnHandler = (LoginHandler) newServiceContext.getBean(authnBeanName);
175             log.debug("{}: Loading authentication handler of type supporting authentication methods: {}", getId(),
176                     authnHandler.getSupportedAuthenticationMethods());
177
178             for (String authnMethod : authnHandler.getSupportedAuthenticationMethods()) {
179                 loginHandlers.put(authnMethod, authnHandler);
180             }
181         }
182     }
183 }