KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > webapps > authentication > components > DefaultAuthenticationManager


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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 package org.apache.cocoon.webapps.authentication.components;
17
18 import java.io.IOException JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.apache.avalon.framework.activity.Disposable;
25 import org.apache.avalon.framework.component.Component;
26 import org.apache.avalon.framework.configuration.ConfigurationException;
27 import org.apache.avalon.framework.container.ContainerUtil;
28 import org.apache.avalon.framework.context.Context;
29 import org.apache.avalon.framework.context.ContextException;
30 import org.apache.avalon.framework.context.Contextualizable;
31 import org.apache.avalon.framework.logger.AbstractLogEnabled;
32 import org.apache.avalon.framework.service.ServiceException;
33 import org.apache.avalon.framework.service.ServiceManager;
34 import org.apache.avalon.framework.service.Serviceable;
35 import org.apache.avalon.framework.thread.ThreadSafe;
36 import org.apache.cocoon.ProcessingException;
37 import org.apache.cocoon.components.ContextHelper;
38 import org.apache.cocoon.components.SitemapConfigurable;
39 import org.apache.cocoon.components.SitemapConfigurationHolder;
40 import org.apache.cocoon.environment.Redirector;
41 import org.apache.cocoon.environment.Request;
42 import org.apache.cocoon.environment.Session;
43 import org.apache.cocoon.util.ClassUtils;
44 import org.apache.cocoon.webapps.authentication.AuthenticationConstants;
45 import org.apache.cocoon.webapps.authentication.AuthenticationManager;
46 import org.apache.cocoon.webapps.authentication.configuration.ApplicationConfiguration;
47 import org.apache.cocoon.webapps.authentication.configuration.HandlerConfiguration;
48 import org.apache.cocoon.webapps.authentication.context.AuthenticationContext;
49 import org.apache.cocoon.webapps.authentication.user.RequestState;
50 import org.apache.cocoon.webapps.authentication.user.UserHandler;
51 import org.apache.cocoon.webapps.authentication.user.UserState;
52 import org.apache.cocoon.webapps.session.ContextManager;
53 import org.apache.cocoon.webapps.session.SessionConstants;
54 import org.apache.cocoon.webapps.session.SessionManager;
55 import org.apache.cocoon.webapps.session.context.SessionContext;
56 import org.apache.excalibur.source.SourceParameters;
57 import org.apache.excalibur.source.SourceResolver;
58 import org.apache.excalibur.source.SourceUtil;
59 import org.apache.excalibur.xml.xpath.XPathProcessor;
60 import org.w3c.dom.DocumentFragment JavaDoc;
61 import org.w3c.dom.Node JavaDoc;
62 import org.xml.sax.SAXException JavaDoc;
63
64 /**
65  * This is the basis authentication component.
66  *
67  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
68  * @version CVS $Id: DefaultAuthenticationManager.java 153483 2005-02-12 04:04:48Z antonio $
69 */

70 public class DefaultAuthenticationManager
71         extends AbstractLogEnabled
72         implements AuthenticationManager,
73                    SitemapConfigurable,
74                    Serviceable,
75                    Disposable,
76                    ThreadSafe,
77                    Contextualizable,
78                    Component {
79
80     /** The name of the session attribute storing the user status */
81     public final static String JavaDoc SESSION_ATTRIBUTE_USER_STATUS = DefaultAuthenticationManager.class.getName() + "/UserStatus";
82
83     /** The manager for the authentication handlers */
84     protected SitemapConfigurationHolder holder;
85
86     /** The Service Manager */
87     protected ServiceManager manager;
88
89     /** The Source Resolver */
90     protected SourceResolver resolver;
91
92     /** The context */
93     protected Context context;
94
95     /** Instantiated authenticators */
96     protected Map JavaDoc authenticators = new HashMap JavaDoc();
97
98     /** The xpath processor */
99     protected XPathProcessor xpathProcessor;
100
101     /** This is the key used to store the current request state in the request object */
102     private static final String JavaDoc REQUEST_STATE_KEY = RequestState.class.getName();
103
104     /**
105      * Set the sitemap configuration containing the handlers
106      */

107     public void configure(SitemapConfigurationHolder holder)
108     throws ConfigurationException {
109         this.holder = holder;
110     }
111
112     /**
113      * Get the handler configuration for the current sitemap
114      */

115     private Map JavaDoc getHandlerConfigurations()
116     throws ProcessingException {
117         Map JavaDoc configs = (Map JavaDoc) this.holder.getPreparedConfiguration();
118         if ( null == configs ) {
119             try {
120                 configs = DefaultHandlerManager.prepareHandlerConfiguration(ContextHelper.getObjectModel(this.context),
121                                                                             this.holder);
122             } catch (ConfigurationException ce) {
123                 throw new ProcessingException("Configuration error.", ce);
124             }
125         }
126         return configs;
127     }
128
129     /**
130      * Get the handler configuration
131      * @param name The handler name
132      * @return The configuration or null.
133      */

134     private HandlerConfiguration getHandlerConfiguration(String JavaDoc name)
135     throws ProcessingException {
136         final Map JavaDoc configs = this.getHandlerConfigurations();
137         HandlerConfiguration c = null;
138         if ( configs != null) {
139             c = (HandlerConfiguration)configs.get( name );
140         }
141         return c;
142     }
143
144     private Request getRequest() {
145         return ContextHelper.getRequest(this.context);
146     }
147
148     private Session getSession(boolean create) {
149         return this.getRequest().getSession(create);
150     }
151
152     private UserState getUserState() {
153         final Session session = this.getSession( false );
154         UserState status = null;
155         if ( session != null) {
156             status = (UserState) session.getAttribute(SESSION_ATTRIBUTE_USER_STATUS);
157         }
158         return status;
159     }
160
161     private UserState createUserState() {
162         UserState status = this.getUserState();
163         if ( status == null ) {
164             final Session session = this.getSession(true);
165             status = new UserState();
166             session.setAttribute(SESSION_ATTRIBUTE_USER_STATUS, status);
167         }
168         return status;
169     }
170
171     private UserHandler getUserHandler(String JavaDoc name) {
172         final UserState status = this.getUserState();
173         if ( status != null ) {
174             return status.getHandler( name );
175         }
176         return null;
177     }
178
179     private void updateUserState() {
180         final Session session = this.getSession(true);
181         Object JavaDoc status = session.getAttribute(SESSION_ATTRIBUTE_USER_STATUS);
182         session.setAttribute(SESSION_ATTRIBUTE_USER_STATUS, status);
183     }
184
185     /* (non-Javadoc)
186      * @see org.apache.cocoon.webapps.authentication.components.Manager#authenticate(java.lang.String, java.lang.String, org.apache.excalibur.source.SourceParameters)
187      */

188     public UserHandler login(String JavaDoc handlerName,
189                              String JavaDoc applicationName,
190                              SourceParameters parameters)
191     throws ProcessingException {
192         HandlerConfiguration config = this.getHandlerConfiguration( handlerName );
193         if ( config == null ) {
194             throw new ProcessingException("Unknown handler to authenticate: " + handlerName);
195         }
196         // are we already logged in?
197
UserHandler handler = this.getUserHandler( handlerName );
198         if ( handler != null ) {
199             throw new ProcessingException("User is already authenticated using handler: " + handlerName);
200         }
201
202         Authenticator authenticator = this.lookupAuthenticator( config );
203         try {
204             Authenticator.AuthenticationResult result = authenticator.authenticate( config, parameters );
205             if (result != null) {
206                 if (result.valid) {
207                     AuthenticationContext authContext = new AuthenticationContext(this.context, this.xpathProcessor, this.resolver);
208                     handler = new UserHandler(config, authContext);
209                     // store the authentication data in the context
210
authContext.init(result.result);
211                 } else {
212                     // now set the failure information in the temporary context
213
ContextManager contextManager = null;
214                     try {
215                         contextManager = (ContextManager) this.manager.lookup( ContextManager.ROLE );
216                         SessionContext temp = contextManager.getContext( SessionConstants.TEMPORARY_CONTEXT );
217     
218                         final DocumentFragment JavaDoc fragment = result.result.createDocumentFragment();
219                         final Node JavaDoc root = result.result.getDocumentElement();
220                         root.normalize();
221                         Node JavaDoc child;
222                         boolean appendedNode = false;
223                         while (root.hasChildNodes() ) {
224                             child = root.getFirstChild();
225                             root.removeChild(child);
226                             // Leave out empty text nodes before any other node
227
if (appendedNode
228                                 || child.getNodeType() != Node.TEXT_NODE
229                                 || child.getNodeValue().trim().length() > 0) {
230                                 fragment.appendChild(child);
231                                 appendedNode = true;
232                             }
233                         }
234                         temp.appendXML("/", fragment);
235                     } catch ( ServiceException se ) {
236                         throw new ProcessingException("Unable to lookup session manager.", se);
237                     } finally {
238                         this.manager.release( contextManager );
239                     }
240                 }
241             }
242         } finally {
243             this.releaseAuthenticator( authenticator, config );
244         }
245
246         if ( handler != null ) {
247             // create UserStatus
248
final UserState status = this.createUserState();
249
250             status.addHandler( handler );
251             this.updateUserState();
252
253             // update RequestState
254
RequestState state = new RequestState( handler, applicationName);
255             this.setState( state );
256             state.initialize( this.resolver );
257
258             // And now load applications
259
Iterator JavaDoc applications = handler.getHandlerConfiguration().getApplications().values().iterator();
260
261             while ( applications.hasNext() ) {
262                 ApplicationConfiguration appHandler = (ApplicationConfiguration)applications.next();
263                 if ( !appHandler.getLoadOnDemand() ) {
264                     handler.getContext().loadApplicationXML( appHandler, this.resolver );
265                 }
266             }
267         }
268
269         return handler;
270     }
271
272     /**
273      * Release the used authenticator
274      */

275     protected void releaseAuthenticator(Authenticator authenticator, HandlerConfiguration config) {
276         // all authenticators are released on dispose
277
}
278
279     /**
280      * The authenticator used to authenticate a user
281      */

282     protected Authenticator lookupAuthenticator(HandlerConfiguration config)
283     throws ProcessingException {
284         final String JavaDoc name = config.getAuthenticatorClassName();
285         Authenticator authenticator = (Authenticator) this.authenticators.get(name);
286         if ( authenticator == null ) {
287             synchronized (this) {
288                 authenticator = (Authenticator) this.authenticators.get(name);
289                 if ( authenticator == null ) {
290                     try {
291                         authenticator = (Authenticator) ClassUtils.newInstance(name);
292                         ContainerUtil.enableLogging( authenticator, this.getLogger() );
293                         ContainerUtil.contextualize( authenticator, this.context);
294                         ContainerUtil.service( authenticator, this.manager );
295                         ContainerUtil.initialize( authenticator );
296                         this.authenticators.put(name, authenticator);
297
298                     } catch (Exception JavaDoc e ) {
299                         throw new ProcessingException("Unable to initialize authenticator from class " + name, e);
300                     }
301                 }
302             }
303         }
304         return authenticator;
305     }
306
307     /* (non-Javadoc)
308      * @see org.apache.cocoon.webapps.authentication.components.Manager#checkAuthentication(org.apache.cocoon.environment.Redirector, java.lang.String, java.lang.String)
309      */

310     public boolean checkAuthentication(Redirector redirector,
311                                        String JavaDoc handlerName,
312                                        String JavaDoc applicationName)
313     throws IOException JavaDoc, ProcessingException {
314         HandlerConfiguration config = this.getHandlerConfiguration( handlerName );
315         if ( config == null ) {
316             throw new ProcessingException("Unknown handler to check: " + handlerName);
317         }
318         // are we already logged in?
319
UserHandler handler = this.getUserHandler( handlerName );
320         final boolean authenticated = ( handler != null );
321         if ( !authenticated ) {
322             if (redirector != null) {
323                 // create parameters
324
SourceParameters parameters = config.getRedirectParameters();
325                 if (parameters == null) parameters = new SourceParameters();
326                 final Request request = this.getRequest();
327                 String JavaDoc resource = request.getRequestURI();
328                 if (request.getQueryString() != null) {
329                     resource += '?' + request.getQueryString();
330                 }
331
332                 parameters.setSingleParameterValue("resource", resource);
333                 final String JavaDoc redirectURI = config.getRedirectURI();
334                 redirector.globalRedirect(false, SourceUtil.appendParameters(redirectURI, parameters));
335             }
336         } else {
337             // update state
338
RequestState state = new RequestState( handler, applicationName );
339             this.setState( state );
340             state.initialize( this.resolver );
341         }
342
343         return authenticated;
344     }
345
346     public String JavaDoc getForwardingURI(String JavaDoc handlerName) throws ProcessingException {
347         HandlerConfiguration config = this.getHandlerConfiguration( handlerName );
348         SourceParameters parameters = config.getRedirectParameters();
349         if (parameters == null) parameters = new SourceParameters();
350         final Request request = this.getRequest();
351         String JavaDoc resource = request.getRequestURI();
352         if (request.getQueryString() != null) {
353             resource += '?' + request.getQueryString();
354         }
355
356         parameters.setSingleParameterValue("resource", resource);
357         final String JavaDoc redirectURI = config.getRedirectURI();
358         return SourceUtil.appendParameters(redirectURI, parameters);
359     }
360
361     /* (non-Javadoc)
362      * @see org.apache.cocoon.webapps.authentication.components.Manager#isAuthenticated(java.lang.String)
363      */

364     public UserHandler isAuthenticated(String JavaDoc handlerName)
365     throws ProcessingException {
366         return this.getUserHandler( handlerName );
367     }
368
369     /* (non-Javadoc)
370      * @see org.apache.cocoon.webapps.authentication.components.Manager#logout(java.lang.String, java.lang.String)
371      */

372     public void logout(String JavaDoc handlerName, int mode)
373     throws ProcessingException {
374         HandlerConfiguration config = this.getHandlerConfiguration( handlerName );
375         if ( config == null ) {
376             throw new ProcessingException("Unknown handler to logout: " + handlerName);
377         }
378         // are we logged in?
379
UserHandler handler = this.getUserHandler( handlerName );
380         // we don't throw an exception if we are already logged out!
381
if ( handler != null ) {
382
383             // Do we save something on logout?
384
/*
385
386             if ( config.saveOnLogout()
387                  && config.getSaveResource() != null) {
388                 final AuthenticationContext authContext = handler.getContext();
389                 try {
390                     // This might not work, because of the missing state
391                     authContext.saveXML("/authentication",
392                                     null,
393                                     ContextHelper.getObjectModel(this.context),
394                                     this.resolver, this.manager);
395                 } catch (Exception ignore) {
396                     // we don't want to stop the logout process
397                     // because of errors during save
398                     this.getLogger().error("Exception while saving authentication information.", ignore);
399                 }
400             }
401             // save applications (if configured)
402             Iterator iter = config.getApplications().values().iterator();
403             while ( iter.hasNext() ) {
404                 ApplicationConfiguration appConfig = (ApplicationConfiguration) iter.next();
405                 if ( appConfig.saveOnLogout()
406                      && appConfig.getSaveResource() != null ) {
407                      // ???
408                 }
409             }
410             */

411             // notify the authenticator
412
try {
413                 this.lookupAuthenticator(config).logout(handler);
414             } catch (Exception JavaDoc ignore) {
415                 // we really ignore any exception!
416
}
417
418             List JavaDoc applicationContexts = handler.getApplicationContexts();
419             if ( applicationContexts != null ) {
420                 ContextManager contextManager = null;
421
422                 try {
423                     contextManager = (ContextManager)this.manager.lookup(ContextManager.ROLE);
424
425                     Iterator JavaDoc i = applicationContexts.iterator();
426                     while ( i.hasNext() ) {
427                         final String JavaDoc current = (String JavaDoc)i.next();
428                         contextManager.deleteContext( current );
429                     }
430                 } catch (ServiceException ce) {
431                     throw new ProcessingException("Unable to create session context.", ce);
432                 } finally {
433                     this.manager.release( contextManager);
434                 }
435             }
436
437             UserState status = this.getUserState();
438             status.removeHandler( handlerName );
439             this.updateUserState();
440
441             // handling of session termination
442
SessionManager sessionManager = null;
443             try {
444                 sessionManager = (SessionManager)this.manager.lookup( SessionManager.ROLE );
445
446                 if ( mode == AuthenticationConstants.LOGOUT_MODE_IMMEDIATELY ) {
447                     sessionManager.terminateSession(true);
448                 } else if ( mode == AuthenticationConstants.LOGOUT_MODE_IF_UNUSED ) {
449                     if ( !status.hasHandler()) {
450                         sessionManager.terminateSession( false );
451                     }
452
453                 } else if ( mode == AuthenticationConstants.LOGOUT_MODE_IF_NOT_AUTHENTICATED) {
454                     if ( !status.hasHandler()) {
455                         sessionManager.terminateSession( true );
456                     }
457                 } else {
458                     throw new ProcessingException("Unknown logout mode: " + mode);
459                 }
460
461             } catch (ServiceException se) {
462                 throw new ProcessingException("Unable to lookup session manager.", se);
463             } finally {
464                 this.manager.release( sessionManager );
465             }
466         }
467     }
468
469     /**
470      * Serviceable
471      */

472     public void service(ServiceManager manager)
473     throws ServiceException {
474         this.manager = manager;
475         this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
476         this.xpathProcessor = (XPathProcessor)this.manager.lookup(XPathProcessor.ROLE);
477     }
478
479     /* (non-Javadoc)
480      * @see org.apache.avalon.framework.activity.Disposable#dispose()
481      */

482     public void dispose() {
483         Iterator JavaDoc iter = this.authenticators.values().iterator();
484         while ( iter.hasNext() ) {
485             final Authenticator authenticator = (Authenticator) iter.next();
486             ContainerUtil.dispose( authenticator );
487         }
488         if ( this.manager != null) {
489             this.manager.release( this.resolver );
490             this.manager.release(this.xpathProcessor);
491             this.resolver = null;
492             this.xpathProcessor = null;
493             this.manager = null;
494         }
495     }
496
497     /**
498      * Get the current state of authentication
499      */

500     public RequestState getState() {
501         return getRequestState(this.context);
502     }
503
504     public static RequestState getRequestState(Context context) {
505         final Request req = ContextHelper.getRequest(context);
506         return (RequestState)req.getAttribute( REQUEST_STATE_KEY);
507     }
508
509     /* (non-Javadoc)
510      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
511      */

512     public void contextualize(Context context) throws ContextException {
513         this.context = context;
514     }
515
516     protected void setState(RequestState status) {
517         final Request req = ContextHelper.getRequest(this.context);
518         if ( status != null ) {
519             req.setAttribute( REQUEST_STATE_KEY, status);
520         } else {
521             req.removeAttribute( REQUEST_STATE_KEY );
522         }
523     }
524
525     /**
526      * Create Application Context.
527      * This context is destroyed when the user logs out of the handler
528      */

529     public SessionContext createApplicationContext(String JavaDoc name,
530                                                    String JavaDoc loadURI,
531                                                    String JavaDoc saveURI)
532     throws ProcessingException {
533         RequestState state = this.getState();
534         UserHandler handler = state.getHandler();
535
536         SessionContext context = null;
537
538         if ( handler != null ) {
539             ContextManager contextManager = null;
540             try {
541                 contextManager = (ContextManager)this.manager.lookup(ContextManager.ROLE);
542                 // create new context
543
context = contextManager.createContext(name, loadURI, saveURI);
544                 handler.addApplicationContext( name );
545
546             } catch (ServiceException ce) {
547                 throw new ProcessingException("Unable to create session context.", ce);
548             } catch (IOException JavaDoc ioe) {
549                 throw new ProcessingException("Unable to create session context.", ioe);
550             } catch (SAXException JavaDoc saxe) {
551                 throw new ProcessingException("Unable to create session context.", saxe);
552             } finally {
553                 manager.release( contextManager);
554             }
555         } else {
556             throw new ProcessingException("No handler defined. Unable to create application context.");
557         }
558
559         return context;
560     }
561 }
562
Popular Tags