View Javadoc

1   /*
2    * Copyright 2004-2005 OSOCO.org (Carsten Ziegeler)
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.osoco.cowarp.impl;
17  
18  import java.util.HashMap;
19  import java.util.Map;
20  
21  import org.apache.avalon.framework.CascadingRuntimeException;
22  import org.apache.avalon.framework.activity.Disposable;
23  import org.apache.avalon.framework.configuration.ConfigurationException;
24  import org.apache.avalon.framework.context.Context;
25  import org.apache.avalon.framework.context.ContextException;
26  import org.apache.avalon.framework.context.Contextualizable;
27  import org.apache.avalon.framework.logger.AbstractLogEnabled;
28  import org.apache.avalon.framework.service.ServiceException;
29  import org.apache.avalon.framework.service.ServiceManager;
30  import org.apache.avalon.framework.service.Serviceable;
31  import org.apache.avalon.framework.thread.ThreadSafe;
32  import org.apache.cocoon.components.ContextHelper;
33  import org.apache.cocoon.environment.ObjectModelHelper;
34  import org.apache.cocoon.environment.Request;
35  import org.apache.cocoon.environment.Session;
36  import org.apache.commons.lang.ObjectUtils;
37  import org.osoco.cowarp.Application;
38  import org.osoco.cowarp.ApplicationManager;
39  import org.osoco.cowarp.ApplicationUtil;
40  import org.osoco.cowarp.User;
41  
42  /***
43   * This is the default implementation of the
44   * {@link org.osoco.cowarp.ApplicationManager}.
45   *
46   * @author <a href="mailto:cziegeler.at.osoco.org">Carsten Ziegeler</a>
47   * @version $Id: StandardApplicationManager.java,v 1.8 2005/02/24 19:06:43 cziegeler Exp $
48  */
49  public class StandardApplicationManager
50      extends AbstractLogEnabled
51      implements ApplicationManager,
52                 Contextualizable,
53                 Serviceable,
54                 ThreadSafe,
55                 Disposable {
56  
57      /*** The key used to store the login information in the session. */
58      protected static final String LOGIN_INFO_KEY = StandardApplicationManager.class.getName() + "/logininfo";
59  
60      /*** The prefix used to store the application data object in the session. */
61      protected static final String APPLICATION_KEY_PREFIX = StandardApplicationManager.class.getName() + "/app:";
62  
63      /*** The component context. */
64      protected Context context;
65  
66      /*** The service manager. */
67      protected ServiceManager manager;
68  
69      /* (non-Javadoc)
70       * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
71       */
72      public void contextualize(final Context aContext) throws ContextException {
73          this.context = aContext;
74      }
75  
76      /* (non-Javadoc)
77       * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
78       */
79      public void service(final ServiceManager aManager) throws ServiceException {
80          this.manager = aManager;
81      }
82  
83      /* (non-Javadoc)
84       * @see org.apache.avalon.framework.activity.Disposable#dispose()
85       */
86      public void dispose() {
87          this.manager = null;
88      }
89  
90      protected Application getApplication(final String appName)
91      throws Exception {
92          final ServiceManager current = (ServiceManager)this.context.get(ContextHelper.CONTEXT_SITEMAP_SERVICE_MANAGER);
93          Object o = current.lookup(Application.class.getName() + '/' + appName);
94          if ( o == null ) {
95              throw new ConfigurationException("Application '" + appName + "' not found.");
96          }
97          // to avoid messy release stuff later on, we just release the app now
98          // as an application is thread safe this isn't really a problem
99          current.release(o);
100         return (Application)o;
101     }
102 
103     /* (non-Javadoc)
104      * @see org.osoco.cowarp.ApplicationManager#isLoggedIn(java.lang.String)
105      */
106     public boolean isLoggedIn(final String appName) {
107         Object appData = null;
108         final Map objectModel = ContextHelper.getObjectModel( this.context );
109         final Request req = ObjectModelHelper.getRequest(objectModel);
110         final Session session = req.getSession(false);
111         if ( session != null ) {
112             appData = session.getAttribute(APPLICATION_KEY_PREFIX + appName);
113 
114             // if the user is logged in, we set the current application, data and user
115             if ( appData != null ) {
116                 try {
117                     objectModel.put(ApplicationManager.APPLICATION, this.getApplication(appName));
118                     objectModel.put(ApplicationManager.APPLICATION_DATA, appData);
119                     objectModel.put(ApplicationManager.USER, session.getAttribute(USER + '-' + appName));
120                 } catch (Exception ignore) {
121                     throw new CascadingRuntimeException("Unable to get application " + appName, ignore);
122                 }
123             }
124         }
125 
126         return (appData != null);
127     }
128 
129     /* (non-Javadoc)
130      * @see org.osoco.cowarp.ApplicationManager#login(java.lang.String, java.util.Map)
131      */
132     public User login(final String appName, final Map loginContext) throws Exception {
133         User user = null;
134 
135         final Map objectModel = ContextHelper.getObjectModel( this.context );
136 
137         // first check, if we are already logged in
138         if ( this.isLoggedIn(appName) ) {
139             user = ApplicationUtil.getUser(objectModel);
140         } else {
141             final Request req = ObjectModelHelper.getRequest(objectModel);
142             Session session = req.getSession(false);
143 
144             final Application app = this.getApplication(appName);
145             LoginInfo info = null;
146             Map loginInfos = null;
147 
148             if ( session != null ) {
149                 // is the user already logged in on the security handler?
150                 loginInfos = (Map)session.getAttribute(LOGIN_INFO_KEY);
151                 if ( loginInfos != null && loginInfos.containsKey(app.getSecurityHandler()) ) {
152                     info = (LoginInfo)loginInfos.get(app.getSecurityHandler());
153                     user = info.user;
154                 }
155             }
156             if ( user == null ) {
157                 user = app.getSecurityHandler().login(loginContext);
158                 if ( user != null ) {
159                     // create new login info
160                     session = req.getSession();
161                     loginInfos = (Map)session.getAttribute(LOGIN_INFO_KEY);
162                     if ( loginInfos == null ) {
163                         loginInfos = new HashMap();
164                     }
165                     info = new LoginInfo(user);
166                     loginInfos.put(app.getSecurityHandler(), info);
167                 }
168             }
169             
170             // user can be nul, if login failed
171             if ( user != null ) {
172                 info.incUsageCounter();
173                 session.setAttribute(LOGIN_INFO_KEY, loginInfos);
174     
175                 // set the user in the session
176                 session.setAttribute(USER + '-' + appName, user);
177                 objectModel.put(ApplicationManager.USER, user);
178     
179                 // set the application in the object model
180                 objectModel.put(ApplicationManager.APPLICATION, app);
181     
182                 // notify the application
183                 app.userDidLogin(user);
184     
185                 // set the application data in the session
186                 Object data = ObjectUtils.NULL;
187                 if ( app.getApplicationStore() != null ) {
188                     data = app.getApplicationStore().loadApplicationData(user, app);
189                 }
190                 session.setAttribute(APPLICATION_KEY_PREFIX + appName, data);
191                 objectModel.put(ApplicationManager.APPLICATION_DATA, data);
192             }
193         }
194 
195         return user;
196     }
197 
198     /* (non-Javadoc)
199      * @see org.osoco.cowarp.ApplicationManager#logout(java.lang.String, java.util.Map)
200      */
201     public void logout(final String appName, final Map logoutContext) {
202         final Map objectModel = ContextHelper.getObjectModel( this.context );
203         final Request req = ObjectModelHelper.getRequest(objectModel);
204         final Session session = req.getSession(false);
205         if ( session != null ) {
206             Application app;
207 
208             try {
209                 app = this.getApplication(appName);
210             } catch (Exception ignore) {
211                 throw new CascadingRuntimeException("Unable to get application " + appName, ignore);
212             }
213 
214             // remove application data from session
215             session.removeAttribute(APPLICATION_KEY_PREFIX + appName);
216 
217             // remove application from object model
218             if ( app.equals( ApplicationUtil.getApplication(objectModel) ) ) { 
219                 objectModel.remove(ApplicationManager.APPLICATION);
220                 objectModel.remove(ApplicationManager.APPLICATION_DATA);
221                 objectModel.remove(ApplicationManager.USER);
222             }
223 
224             // remove user
225             session.removeAttribute(USER + '-' + appName);
226 
227             // decrement logininfo counter
228             final Map loginInfos = (Map)session.getAttribute(LOGIN_INFO_KEY);
229             if ( loginInfos != null ) {
230                 final LoginInfo info = (LoginInfo)loginInfos.get(app.getSecurityHandler());
231                 if ( info != null ) {
232                     // notify the application
233                     app.userWillLogout(info.user);
234 
235                     info.decUsageCounter();
236                     if ( info.isUsed() ) {
237                         session.setAttribute(LOGIN_INFO_KEY, loginInfos);
238                     } else {
239                         // logout from security handler
240                         app.getSecurityHandler().logout(logoutContext, info.user);
241                         // remove user info
242                         loginInfos.remove(app.getSecurityHandler());
243                         if ( loginInfos.size() > 0 ) {
244                             session.setAttribute(LOGIN_INFO_KEY, loginInfos);
245                         } else {
246                             session.removeAttribute(LOGIN_INFO_KEY);
247                             // the user has left all applications, test the mode:
248                             String mode = null;
249                             if ( logoutContext != null ) {
250                                 mode = (String)logoutContext.get(LOGOUT_CONTEXT_MODE_KEY);
251                             }
252                             if ( mode == null || mode.equals(LOGOUT_MODE_TERMINATE_SESSION_IF_UNUSED) ) {
253                                 session.invalidate();
254                             }
255                         }
256                     }
257                 }
258             }
259         }
260     }
261 }