First pass to clean up config and fix multi serivce instance bug
[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.List;
21 import java.util.Map;
22 import java.util.Timer;
23 import java.util.concurrent.locks.Lock;
24
25 import javax.servlet.ServletRequest;
26 import javax.servlet.http.HttpServletRequest;
27
28 import org.opensaml.util.resource.Resource;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.springframework.context.ApplicationContext;
32
33 import edu.internet2.middleware.shibboleth.common.config.BaseReloadableService;
34 import edu.internet2.middleware.shibboleth.common.profile.AbstractErrorHandler;
35 import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
36 import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
37 import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractRequestURIMappedProfileHandler;
38 import edu.internet2.middleware.shibboleth.idp.authn.LoginHandler;
39
40 /**
41  * Implementation of a {@link ProfileHandlerManager} that maps the request path, without the servlet context, to a
42  * profile handler and adds support for authentication handlers.
43  */
44 public class IdPProfileHandlerManager extends BaseReloadableService implements ProfileHandlerManager {
45
46     /** Class logger. */
47     private final Logger log = LoggerFactory.getLogger(IdPProfileHandlerManager.class);
48
49     /** Handler used for errors. */
50     private AbstractErrorHandler errorHandler;
51
52     /** Map of request paths to profile handlers. */
53     private Map<String, AbstractRequestURIMappedProfileHandler> profileHandlers;
54
55     /** Map of authentication methods to login handlers. */
56     private Map<String, LoginHandler> loginHandlers;
57
58     /**
59      * Constructor. Configuration resources are not monitored for changes.
60      * 
61      * @param configurations configuration resources for this service
62      */
63     public IdPProfileHandlerManager(List<Resource> configurations) {
64         super(configurations);
65         profileHandlers = new HashMap<String, AbstractRequestURIMappedProfileHandler>();
66         loginHandlers = new HashMap<String, LoginHandler>();
67     }
68
69     /**
70      * Constructor.
71      * 
72      * @param timer timer resource polling tasks are scheduled with
73      * @param configurations configuration resources for this service
74      * @param pollingFrequency the frequency, in milliseconds, to poll the policy resources for changes, must be greater
75      *            than zero
76      */
77     public IdPProfileHandlerManager(List<Resource> configurations, Timer timer, long pollingFrequency) {
78         super(timer, configurations, pollingFrequency);
79         profileHandlers = new HashMap<String, AbstractRequestURIMappedProfileHandler>();
80         loginHandlers = new HashMap<String, LoginHandler>();
81     }
82
83     /** {@inheritDoc} */
84     public AbstractErrorHandler getErrorHandler() {
85         return errorHandler;
86     }
87
88     /**
89      * Sets the error handler.
90      * 
91      * @param handler error handler
92      */
93     public void setErrorHandler(AbstractErrorHandler handler) {
94         if (handler == null) {
95             throw new IllegalArgumentException("Error handler may not be null");
96         }
97         errorHandler = handler;
98     }
99
100     /** {@inheritDoc} */
101     public ProfileHandler getProfileHandler(ServletRequest request) {
102         ProfileHandler handler;
103
104         String requestPath = ((HttpServletRequest) request).getPathInfo();
105         log.debug("{}: Looking up profile handler for request path: {}", getId(), requestPath);
106
107         Lock readLock = getReadWriteLock().readLock();
108         readLock.lock();
109         handler = profileHandlers.get(requestPath);
110         readLock.unlock();
111
112         if (handler != null) {
113             log.debug("{}: Located profile handler of the following type for the request path: {}", getId(), handler
114                     .getClass().getName());
115         } else {
116             log.debug("{}: No profile handler registered for request path {}", getId(), requestPath);
117         }
118         return handler;
119     }
120
121     /**
122      * Gets the registered profile handlers.
123      * 
124      * @return registered profile handlers
125      */
126     public Map<String, AbstractRequestURIMappedProfileHandler> getProfileHandlers() {
127         return profileHandlers;
128     }
129
130     /**
131      * Gets the registered authentication handlers.
132      * 
133      * @return registered authentication handlers
134      */
135     public Map<String, LoginHandler> getLoginHandlers() {
136         return loginHandlers;
137     }
138
139     /** {@inheritDoc} */
140     protected void onNewContextCreated(ApplicationContext newServiceContext) {
141         log.debug("{}: Loading new configuration into service", getId());
142         Lock writeLock = getReadWriteLock().writeLock();
143         writeLock.lock();
144         loadNewErrorHandler(newServiceContext);
145         loadNewProfileHandlers(newServiceContext);
146         loadNewAuthenticationHandlers(newServiceContext);
147         writeLock.unlock();
148     }
149
150     /**
151      * Reads the new error handler from the newly created application context and loads it into this manager.
152      * 
153      * @param newServiceContext newly created application context
154      */
155     protected void loadNewErrorHandler(ApplicationContext newServiceContext) {
156         String[] errorBeanNames = newServiceContext.getBeanNamesForType(AbstractErrorHandler.class);
157         log.debug("{}: Loading {} new error handler.", getId(), errorBeanNames.length);
158
159         errorHandler = (AbstractErrorHandler) newServiceContext.getBean(errorBeanNames[0]);
160         log.debug("{}: Loaded new error handler of type: {}", getId(), errorHandler.getClass().getName());
161     }
162
163     /**
164      * Reads the new profile handlers from the newly created application context and loads it into this manager.
165      * 
166      * @param newServiceContext newly created application context
167      */
168     protected void loadNewProfileHandlers(ApplicationContext newServiceContext) {
169         String[] profileBeanNames = newServiceContext.getBeanNamesForType(AbstractRequestURIMappedProfileHandler.class);
170         log.debug("{}: Loading {} new profile handlers.", getId(), profileBeanNames.length);
171
172         profileHandlers.clear();
173         AbstractRequestURIMappedProfileHandler<?, ?> profileHandler;
174         for (String profileBeanName : profileBeanNames) {
175             profileHandler = (AbstractRequestURIMappedProfileHandler) newServiceContext.getBean(profileBeanName);
176             for (String requestPath : profileHandler.getRequestPaths()) {
177                 profileHandlers.put(requestPath, profileHandler);
178                 log.debug("{}: Loaded profile handler for handling requests to request path {}", getId(), requestPath);
179             }
180         }
181     }
182
183     /**
184      * Reads the new authentication handlers from the newly created application context and loads it into this manager.
185      * 
186      * @param newServiceContext newly created application context
187      */
188     protected void loadNewAuthenticationHandlers(ApplicationContext newServiceContext) {
189         String[] authnBeanNames = newServiceContext.getBeanNamesForType(LoginHandler.class);
190         log.debug("{}: Loading {} new authentication handlers.", getId(), authnBeanNames.length);
191
192         loginHandlers.clear();
193         LoginHandler authnHandler;
194         for (String authnBeanName : authnBeanNames) {
195             authnHandler = (LoginHandler) newServiceContext.getBean(authnBeanName);
196             log.debug("{}: Loading authentication handler of type supporting authentication methods: {}", getId(),
197                     authnHandler.getSupportedAuthenticationMethods());
198
199             for (String authnMethod : authnHandler.getSupportedAuthenticationMethods()) {
200                 loginHandlers.put(authnMethod, authnHandler);
201             }
202         }
203     }
204 }