KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > discRack > pres > screens > LoginScreen


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: LoginScreen.java,v 1.4 2004/02/05 10:24:50 slobodan Exp $
22  */

23 package org.enhydra.barracuda.discRack.pres.screens;
24
25 import java.io.*;
26 import java.util.*;
27 import java.net.*;
28 import javax.servlet.*;
29 import javax.servlet.http.*;
30
31 import org.w3c.dom.*;
32 import org.w3c.dom.html.*;
33
34 import com.lutris.appserver.server.Enhydra;
35 import com.lutris.logging.LogChannel;
36
37 import org.enhydra.xml.xmlc.*;
38
39 import org.enhydra.barracuda.core.comp.*;
40 import org.enhydra.barracuda.core.event.*;
41 import org.enhydra.barracuda.core.event.helper.*;
42 import org.enhydra.barracuda.core.forms.*;
43 import org.enhydra.barracuda.core.forms.validators.*;
44 import org.enhydra.barracuda.plankton.data.*;
45 import org.enhydra.barracuda.core.util.dom.*;
46 import org.enhydra.barracuda.core.util.http.*;
47 import org.enhydra.barracuda.plankton.http.ServletUtil;
48 import org.apache.log4j.*;
49
50 import org.enhydra.barracuda.discRack.biz.*;
51 import org.enhydra.barracuda.discRack.biz.person.*;
52 import org.enhydra.barracuda.discRack.pres.events.*;
53 import org.enhydra.barracuda.discRack.pres.services.*;
54 import org.enhydra.barracuda.discRack.pres.xmlc.*;
55
56
57 /**
58  * <p>Event handlers (both Controller and View) for the
59  * Login screen
60  *
61  * <p>We handle the following Control events:
62  * <ul>
63  * <li>GetLogin - if we are already logged in, fire a DoLogin
64  * event. Otherwise, just fire a RenderLogin event.</li>
65  * <li>DoLogin - create the login form, map the request to the
66  * form and then validate it. If there weren't any errors,
67  * fire a GetCatalog event. Otherwise, fire a GetLogin event
68  * (saving the form and any validation errors in the event
69  * context so that the RenderLogin can update the screen
70  * correctly.</li>
71  * <li>DoLogout - Fire a RenderLogout event</li>
72  * <li>ValidatedEvent - Whenever a ValidatedEvent is fired,
73  * we must ensure the user is actually logged in. If so,
74  * do nothing. If not, redirect the user to the login screen
75  * by firing a GetLogin event.</li>
76  * </ul>
77  *
78  * <p>We handle the following View events:
79  * <ul>
80  * <li>RenderLogin - Generate the Login screen. If the event context
81  * contains a LoginForm, we repopulate the screen from the form.
82  * If the context contains login errs, we will show those as well</li>
83  * <li>RenderLogout - Generate the Logout screen</li>
84  * <li>SampleError - Generate an error screen</li>
85  * </ul>
86  *
87  * <p>We define the following Forms:
88  * <ul>
89  * <li>LoginForm - contains 2 elements: USER and PASSWORD, both of
90  * which are Strings and take NotNullValidators. In addition,
91  * login form uses LoginValidator, which validates the form by
92  * making sure that the user record exists and the password entered
93  * matches the password for that user.</li>
94  * </ul>
95  *
96  * <p>You can <a HREF="sm_barracudaDiscRack_login.gif">click here to see a diagram...</a>
97  */

98 public class LoginScreen extends DefaultEventGateway {
99
100     //public constants
101
// public static int showDebug = 0;
102
protected static Logger logger = Logger.getLogger(LoginScreen.class.getName());
103
104     //private constants
105
private static final String JavaDoc LOGIN_FORM = LoginScreen.class.getName()+".LoginForm"; //LoginForm
106
private static final String JavaDoc LOGIN_ERR = LoginScreen.class.getName()+".LoginErr"; //ValidationException
107

108     //this defines the various event handlers
109
private ListenerFactory getLoginFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new GetLoginHandler();} public String JavaDoc getListenerID() {return getID(GetLoginHandler.class);}};
110     private ListenerFactory doLoginFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new DoLoginHandler();} public String JavaDoc getListenerID() {return getID(DoLoginHandler.class);}};
111     private ListenerFactory doLogoutFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new DoLogoutHandler();} public String JavaDoc getListenerID() {return getID(DoLogoutHandler.class);}};
112     private ListenerFactory validateLoginFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new ValidateLoginHandler();} public String JavaDoc getListenerID() {return getID(ValidateLoginHandler.class);}};
113     private ListenerFactory renderLoginFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new RenderLoginHandler();} public String JavaDoc getListenerID() {return getID(RenderLoginHandler.class);}};
114     private ListenerFactory renderLogoutFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new RenderLogoutHandler();} public String JavaDoc getListenerID() {return getID(RenderLogoutHandler.class);}};
115     private ListenerFactory renderSampleErrorFactory = new DefaultListenerFactory() {public BaseEventListener getInstance() {return new RenderSampleErrorHandler();} public String JavaDoc getListenerID() {return getID(RenderSampleErrorHandler.class);}};
116
117     //private vars
118

119
120     //-------------------- DefaultEventGateway -------------------
121
/**
122      * Public constructor
123      */

124     public LoginScreen() {
125         //specify who's interested in what
126
specifyLocalEventInterests(getLoginFactory, GetLogin.class);
127         specifyLocalEventInterests(doLoginFactory, DoLogin.class);
128         specifyLocalEventInterests(doLogoutFactory, DoLogout.class);
129         specifyLocalEventInterests(validateLoginFactory, ValidatedEvent.class);
130         specifyLocalEventInterests(renderLoginFactory, RenderLogin.class);
131         specifyLocalEventInterests(renderLogoutFactory, RenderLogout.class);
132         specifyLocalEventInterests(renderSampleErrorFactory, SampleError.class);
133     }
134
135
136     //------------------------------------------------------------
137
// Model 2 - Controller Event Handlers
138
//------------------------------------------------------------
139
/**
140      * GetLoginHandler - this is where we handle any GetLogin event
141      * requests. If they are already logged in, just redirect on.
142      */

143     class GetLoginHandler extends DefaultBaseEventListener {
144         public void handleControlEvent(ControlEventContext context) throws EventException, ServletException, IOException {
145             //unpack the necessary entities from the context
146
DispatchQueue queue = context.getQueue();
147
148             //if it looks like we are already logged in, try and auto-login
149
//otherwise, just render the login screen
150
if (LoginServices.isLoggedIn(SessionServices.getSession(context.getRequest()))) {
151                 if (logger.isDebugEnabled()) logger.debug("Adding DoLogin to Queue (Auto-login)");
152                 queue.addEvent(new DoLogin(context.getEvent()));
153             } else {
154                 if (logger.isDebugEnabled()) logger.debug("Adding RenderLogin to Queue");
155                 queue.addEvent(new RenderLogin(context.getEvent()));
156             }
157         }
158     }
159
160     /**
161      * DoLoginHandler - this is where we handle any AttemptLogin
162      * events. Validate and then redirect accordingly.
163      */

164     class DoLoginHandler extends DefaultBaseEventListener {
165         public void handleControlEvent(ControlEventContext context) throws EventException, ServletException, IOException {
166             //unpack the necessary entities from the context
167
HttpServletRequest req = context.getRequest();
168
169             //create the login form
170
ValidationException ve = null;
171             if (logger.isDebugEnabled()) logger.debug("Creating login form");
172             LoginForm lf = new LoginForm(SessionServices.getSession(req));
173             try {
174                 //map/validate the form
175
if (logger.isDebugEnabled()) logger.debug("Mapping/Validating login form");
176                 lf.map(req).validate(true);
177             } catch (ValidationException e) {
178                 LoginServices.logOut(SessionServices.getSession(req));
179                 if (logger.isDebugEnabled()) logger.debug("Validation Exception: "+e);
180                 if (logger.isDebugEnabled()) CollectionsUtil.printStackTrace(e.getExceptionList(), 0, logger, null);
181                 ve = e;
182             }
183
184             //store a copy of the form and any errors in the queue
185
if (logger.isDebugEnabled()) logger.debug("Saving form, errors");
186             context.putState(LOGIN_FORM, lf);
187             context.putState(LOGIN_ERR, ve);
188
189             //redirect to the Main screen
190
if (ve==null) {
191                 if (logger.isDebugEnabled()) logger.debug("Redirecting to GetCatalog");
192                 throw new ClientSideRedirectException(new GetCatalog());
193             } else {
194                 if (logger.isDebugEnabled()) logger.debug("InterruptDispatch to GetLogin");
195                 throw new InterruptDispatchException(new GetLogin());
196             }
197         }
198     }
199
200     /**
201      * ValidateLoginHandler - make sure the user is actually logged in
202      * if they try and fire any event that extends from ValidateEvent. If
203      * they're not logged in, redirect to the Login screen.
204      */

205     class ValidateLoginHandler extends DefaultBaseEventListener {
206         public void handleControlEvent(ControlEventContext context) throws EventException, ServletException, IOException {
207             //if it looks like we are already logged in, try and auto-login
208
//otherwise, just render the login screen
209
if (!LoginServices.isLoggedIn(SessionServices.getSession(context.getRequest()))) {
210                 if (logger.isDebugEnabled()) logger.debug("InterruptDispatch to GetLogin");
211                 throw new ClientSideRedirectException(new GetLogin(context.getEvent()));
212             }
213         }
214     }
215
216     /**
217      * DoLogoutHandler - this is where we handle any Logout requests
218      */

219     class DoLogoutHandler extends DefaultBaseEventListener {
220         public void handleControlEvent(ControlEventContext context) throws EventException, ServletException, IOException {
221             //unpack the necessary entities from the context
222
DispatchQueue queue = context.getQueue();
223
224             //log the user out and forward control onto the logout screen
225
if (logger.isDebugEnabled()) logger.debug("Logging out");
226             LoginServices.logOut(SessionServices.getSession(context.getRequest()));
227             queue.addEvent(new RenderLogout(context.getEvent()));
228         }
229     }
230
231     //------------------------------------------------------------
232
// Model 2 - View Event Handlers
233
//------------------------------------------------------------
234
/**
235      * RenderLoginHandler -
236      */

237     class RenderLoginHandler extends DefaultBaseEventListener {
238         public void handleViewEvent(ViewEventContext context) throws EventException, ServletException, IOException {
239             //unpack the necessary entities from the context
240
HttpServletRequest req = context.getRequest();
241             ServletUtil.showParams(req, logger);
242
243             //check to see if we need to generate a sample err (for demo purposes)
244
if (logger.isDebugEnabled()) logger.debug("Handling RenderLogin Request");
245             if (new Boolean JavaDoc(req.getParameter("generateSampleError")).booleanValue()) {
246                 throw new InterruptDispatchException(new SampleError(new Exception JavaDoc("Look, here's an error!")));
247             }
248
249             //get the XMLC object
250
// XMLCFactory factory = XMLCServices.getXMLCFactory(context.getConfig());
251
// LoginHTML page = (LoginHTML) factory.create(LoginHTML.class);
252
LoginHTML page = (LoginHTML) DefaultDOMLoader.getGlobalInstance().getDOM(LoginHTML.class);
253
254 // // Swap in our real run-time JavaScript to replace the storyboard JavaScript
255
// HTMLScriptElement script = new LoginScriptHTML().getElementRealScript();
256
// XMLCUtil.replaceNode(script, page.getElementDummyScript());
257

258 /*
259             //repopulate the form (if possible)
260             LoginForm lf = (LoginForm) context.get(LOGIN_FORM);
261             if (lf!=null) {
262                 if (logger.isDebugEnabled()) logger.debug("Repopulating Form");
263                 page.getElementLogin().setValue(lf.getStringValDefault(LoginForm.USER, ""));
264                 page.getElementPassword().setValue(lf.getStringValDefault(LoginForm.PASSWORD, ""));
265             }
266
267             //check for errors
268             if (logger.isDebugEnabled()) logger.debug("Checking for errors");
269             ValidationException ve = (ValidationException) context.get(LOGIN_ERR);
270             if (ve==null) {
271                 if (showDebug>2) Debug.println (this, 2, "No errors found");
272                 page.getElementErrorText().getParentNode().removeChild(page.getElementErrorText());
273             } else {
274                 List errlist = ve.getExceptionList();
275                 if (showDebug>2) Debug.println (this, 2, errlist.size()+"error(s) found");
276                 StringBuffer sb = new StringBuffer(errlist.size()>1 ? "There were several errors:" : "");
277                 Iterator it = errlist.iterator();
278                 while (it.hasNext()) {
279                     sb.append(" "+((ValidationException) it.next()).getMessage());
280                 }
281                 page.setTextErrorText(sb.toString());
282             }
283 */

284
285             //create a template component and render it
286
if (logger.isDebugEnabled()) logger.debug("Creating template component");
287             Node node = page.getDocument().getElementById("LoginForm");
288             BTemplate templateComp = new BTemplate(new LoginModel(context));
289             templateComp.setView(new DefaultTemplateView(node));
290             try {templateComp.render(new DefaultViewContext(context));}
291             catch (RenderException re) {logger.warn("Render err:"+re);}
292
293             //now actually render the page (the DOMWriter will take care of actually
294
//setting the content type)
295
if (logger.isDebugEnabled()) logger.debug("Rendering document");
296             new DefaultDOMWriter().write(page, context.getResponse());
297         }
298     }
299
300     /**
301      * RenderLogoutHandler -
302      */

303 /*
304     class RenderLogoutHandler extends DefaultBaseEventListener {
305         public void handleViewEvent(ViewEventContext context) throws EventException, ServletException, IOException {
306             //get the XMLC object
307 // XMLCFactory factory = XMLCServices.getXMLCFactory(context.getConfig());
308 // ExitHTML page = (ExitHTML) factory.create(ExitHTML.class);
309             ExitHTML page = (ExitHTML) DefaultDOMLoader.getGlobalInstance().getDOM(ExitHTML.class);
310
311             //now actually render it (the DOMWriter will take care of actually
312             //setting the content type)
313             if (logger.isDebugEnabled()) logger.debug("Rendering document");
314             new DefaultDOMWriter().write(page, context.getResponse());
315         }
316     }
317 */

318     class RenderLogoutHandler extends BTemplateViewHandler {
319         //public TemplateModel getTemplateModel() {return new LogoutModel();}
320
public Object JavaDoc getTemplateModels() {return new LogoutModel();}
321         public Class JavaDoc getTemplateClass() {return ExitHTML.class;}
322     }
323
324     /**
325      * RenderSampleErrorHandler - render a SampleError screen
326      */

327     class RenderSampleErrorHandler extends DefaultBaseEventListener {
328         public void handleViewEvent(ViewEventContext context) throws EventException, ServletException, IOException {
329             //unpack the necessary entities from the context
330
BaseEvent event = context.getEvent();
331
332             //get the XMLC object
333
// XMLCFactory factory = XMLCServices.getXMLCFactory(context.getConfig());
334
// ErrorHTML page = (ErrorHTML) factory.create(ErrorHTML.class);
335
ErrorHTML page = (ErrorHTML) DefaultDOMLoader.getGlobalInstance().getDOM(ErrorHTML.class);
336             Object JavaDoc source = event.getSource();
337             if (source instanceof Throwable JavaDoc) {
338                 //get the error
339
Throwable JavaDoc th = (Throwable JavaDoc) source;
340                 StringWriter writer = new StringWriter();
341                 th.printStackTrace(new PrintWriter(writer));
342                 String JavaDoc err = writer.toString();
343
344                 //log it
345
LogChannel logChannel = Enhydra.getLogChannel();
346                 int level = logChannel.getLevel("DEBUG");
347                 logChannel.write(level, this.getClass().getName()+" stack trace = ");
348                 logChannel.write(level, err);
349
350                 //dump it to the error page as well
351
page.setTextStackTrace(err);
352                 page.setTextErrorMessage(th.getMessage());
353             }
354
355             //now actually render it (the DOMWriter will take care of actually
356
//setting the content type)
357
if (logger.isDebugEnabled()) logger.debug("Rendering document");
358             new DefaultDOMWriter().write(page, context.getResponse());
359         }
360     }
361
362     //------------------------------------------------------------
363
// Template Models
364
//------------------------------------------------------------
365
/**
366      * LoginModel
367      */

368     class LoginModel extends AbstractTemplateModel {
369
370         LoginForm fm = null;
371         ValidationException ve = null;
372
373         //constructor (extract form, exception from context)
374
public LoginModel(EventContext ec) {
375             fm = (LoginForm) ec.getState(LOGIN_FORM);
376             ve = (ValidationException) ec.getState(LOGIN_ERR);
377         }
378
379         //register the model by name
380
public String JavaDoc getName() {return "Login";}
381
382         //provide items by key
383
public Object JavaDoc getItem(String JavaDoc key) {
384             ViewContext vc = getViewContext();
385             if (key.equals("Username")) {
386                 return (fm!=null ? fm.getStringVal(LoginForm.USER, "") : "");
387             } else if (key.equals("Password")) {
388                 return (fm!=null ? fm.getStringVal(LoginForm.PASSWORD, "") : "");
389             } else if (key.equals("LoginButton")) {
390                 BAction baComp = new BAction(new DoLogin());
391                 baComp.setDisableBackButton(true);
392                 return baComp;
393             } else if (key.equals("RegisterButton")) {
394                 BAction baComp = new BAction(new GetRegister());
395                 baComp.setDisableBackButton(true);
396                 return baComp;
397             } else if (key.equals("ExceptionButton")) {
398                 BAction baComp = new BAction(new GetLogin());
399                 baComp.setParam("generateSampleError","true");
400                 baComp.setDisableBackButton(true);
401                 return baComp;
402             } else if (key.equals("Errors")) {
403 // if (ve==null) return "";
404
if (ve==null) return null;
405                 List errlist = ve.getExceptionList();
406                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc(errlist.size()>1 ? "There were several errors:" : "");
407                 Iterator it = errlist.iterator();
408                 while (it.hasNext()) {
409                     sb.append(" "+((ValidationException) it.next()).getMessage());
410                 }
411                 return sb.toString();
412             } else {
413                 return super.getItem(key);
414             }
415         }
416     }
417
418     /**
419      * LogoutModel
420      */

421     class LogoutModel extends AbstractTemplateModel {
422
423         //register the model by name
424
public String JavaDoc getName() {return "Logout";}
425
426         //provide items by key
427
public Object JavaDoc getItem(String JavaDoc key) {
428             ViewContext vc = getViewContext();
429             if (key.equals("LoginButton")) {
430                 BAction baComp = new BAction(new GetLogin());
431                 baComp.setDisableBackButton(true);
432                 return baComp;
433             } else {
434                 return super.getItem(key);
435             }
436         }
437     }
438
439
440     //------------------------------------------------------------
441
// HTML Form Mappings, Validators
442
//------------------------------------------------------------
443
/**
444      * Login form - define the login form
445      */

446     class LoginForm extends DefaultFormMap {
447         //login form constants (these values correspond to the HTML param names)
448
static final String JavaDoc USER = "login";
449         static final String JavaDoc PASSWORD = "password";
450
451         HttpSession session = null;
452
453         public LoginForm(HttpSession isession) {
454             session = isession;
455
456             //define the elements
457
if (logger.isDebugEnabled()) logger.debug("Defining Login form elements");
458             this.defineElement(new DefaultFormElement(USER, FormType.STRING, null, new NotNullValidator("You must enter a Login.")));
459             this.defineElement(new DefaultFormElement(PASSWORD, FormType.STRING, null, new NotNullValidator("You must enter a Password.")));
460
461             //define a form validator
462
if (logger.isDebugEnabled()) logger.debug("Defining Registration form validator");
463             this.defineValidator(new LoginValidator(session));
464         }
465
466         /**
467          * we override this method because instead of using the default validation
468          * process (validate elements, then form), we don't want to validate at all
469          * if they are already logged in...we just assume they're valid and return.
470          */

471         public FormMap validate(boolean deferExceptions) throws ValidationException {
472             //see if they are already logged in. If so, just consider them valid
473
if (logger.isDebugEnabled()) logger.debug("Checking to see if already logged in (prevalidated)");
474             if (LoginServices.isLoggedIn(session)) {
475                 try {
476                     Person p = LoginServices.getCurrentUser(session);
477                     String JavaDoc fuser = this.getStringVal(LoginForm.USER);
478                     String JavaDoc fpassword = this.getStringVal(LoginForm.PASSWORD);
479                     if (fuser==null && fpassword==null) return this; //if user/pwd = null, just use the current settings
480
if (p.getLogin().equals(fuser) &&
481                         p.getPassword().equals(fpassword)) return this; //if they're != null, make sure they match, otherwise, we'll want to force a complete revalidate
482
} catch (DiscRackBusinessException e) {}
483             }
484
485             //if not, go ahead and validate
486
return super.validate(deferExceptions);
487         }
488     }
489
490     /**
491      * Login validator - define a custom form validator
492      */

493     class LoginValidator extends DefaultFormValidator {
494
495         HttpSession session = null;
496
497         public LoginValidator(HttpSession isession) {
498             session = isession;
499         }
500
501         public void validateForm(FormMap imap, boolean deferExceptions) throws ValidationException {
502             if (logger.isDebugEnabled()) logger.debug("Validating login form");
503
504             //validate the login information
505
if (logger.isDebugEnabled()) logger.debug("Validate the user/pwd info");
506             LoginForm map = (LoginForm) imap;
507             DeferredValidationException defValException = new DeferredValidationException();
508             String JavaDoc user = map.getStringVal(LoginForm.USER);
509             String JavaDoc password = map.getStringVal(LoginForm.PASSWORD);
510             String JavaDoc errMsg = "Invalid username or password. Please check your information and try again.";
511             if (user != null && password != null) {
512                 try {
513                     //make sure the login exists and the passwords match
514
Person person = PersonFactory.findPerson(user);
515 // if (person==null) defValException.addSubException(new DeferredValidationException(map.getElement(LoginForm.USER), errMsg));
516
// if (person != null && !person.getPassword().equals(password)) defValException.addSubException(new DeferredValidationException(map.getElement(LoginForm.PASSWORD), errMsg));
517
if (person==null) throw new ValidationException(map.getElement(LoginForm.USER), errMsg);
518                 if (!person.getPassword().equals(password)) throw new ValidationException(map.getElement(LoginForm.PASSWORD), errMsg);
519     
520                     //log them in
521
LoginServices.logIn(session, person);
522                 } catch (DiscRackBusinessException e) {
523                     LoginServices.logOut(session); //just to be sure we don't get stuck in a loop
524
defValException.addSubException(new DeferredValidationException(map.getElement(LoginForm.USER), "System error finding user: " + e.getMessage()+". Please try again. If the problem persists, contact your system administrator.", e));
525                 }
526             }
527             if (defValException.hasSubExceptions()) {
528                 throw defValException;
529             }
530         }
531     }
532 }
533
534
Popular Tags