/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation", "Tapestry"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* or "Tapestry", nor may "Apache" or "Tapestry" appear in their
* name, without prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE TAPESTRY CONTRIBUTOR COMMUNITY
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.tapestry.vlib.pages;
import java.rmi.RemoteException;
import javax.servlet.http.Cookie;
import org.apache.tapestry.IEngine;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.callback.ICallback;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;
import org.apache.tapestry.form.IFormComponent;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.valid.IValidationDelegate;
import org.apache.tapestry.valid.ValidatorException;
import org.apache.tapestry.vlib.IErrorProperty;
import org.apache.tapestry.vlib.VirtualLibraryEngine;
import org.apache.tapestry.vlib.Visit;
import org.apache.tapestry.vlib.ejb.IOperations;
import org.apache.tapestry.vlib.ejb.LoginException;
import org.apache.tapestry.vlib.ejb.Person;
/**
* Allows the user to login, by providing email address and password.
* After succesfully logging in, a cookie is placed on the client browser
* that provides the default email address for future logins (the cookie
* persists for a week).
*
* @author Howard Lewis Ship
* @version $Id: Login.java,v 1.9 2003/04/21 15:39:58 hlship Exp $
*
**/
public abstract class Login extends BasePage implements IErrorProperty, PageRenderListener
{
/**
* The name of a cookie to store on the user's machine that will identify
* them next time they log in.
*
**/
private static final String COOKIE_NAME = "org.apache.tapestry.vlib.Login.email";
private final static int ONE_WEEK = 7 * 24 * 60 * 60;
public abstract void setEmail(String value);
public abstract String getEmail();
public abstract String getPassword();
public abstract void setPassword(String password);
protected IValidationDelegate getValidationDelegate()
{
return (IValidationDelegate) getBeans().getBean("delegate");
}
protected void setErrorField(String componentId, String message)
{
IFormComponent field = (IFormComponent) getComponent(componentId);
IValidationDelegate delegate = getValidationDelegate();
delegate.setFormComponent(field);
delegate.record(new ValidatorException(message));
}
public abstract void setCallback(ICallback value);
public abstract ICallback getCallback();
/**
* Attempts to login.
*
* <p>If the user name is not known, or the password is invalid, then an error
* message is displayed.
*
**/
public void attemptLogin(IRequestCycle cycle)
{
String password = getPassword();
// Do a little extra work to clear out the password.
setPassword(null);
IValidationDelegate delegate = getValidationDelegate();
delegate.setFormComponent((IFormComponent) getComponent("inputPassword"));
delegate.recordFieldInputValue(null);
// An error, from a validation field, may already have occured.
if (delegate.getHasErrors())
return;
VirtualLibraryEngine vengine = (VirtualLibraryEngine) getEngine();
int i = 0;
while (true)
{
try
{
IOperations operations = vengine.getOperations();
Person person = operations.login(getEmail(), password);
loginUser(person, cycle);
break;
}
catch (LoginException ex)
{
String fieldName = ex.isPasswordError() ? "inputPassword" : "inputEmail";
setErrorField(fieldName, ex.getMessage());
return;
}
catch (RemoteException ex)
{
vengine.rmiFailure("Remote exception validating user.", ex, i++);
}
}
}
/**
* Sets up the {@link Person} as the logged in user, creates
* a cookie for thier email address (for subsequent logins),
* and redirects to the appropriate page ({@link MyLibrary}, or
* a specified page).
*
**/
public void loginUser(Person person, IRequestCycle cycle) throws RemoteException
{
String email = person.getEmail();
// Get the visit object; this will likely force the
// creation of the visit object and an HttpSession.
Visit visit = (Visit) getVisit();
visit.setUser(person);
// After logging in, go to the MyLibrary page, unless otherwise
// specified.
ICallback callback = getCallback();
if (callback == null)
cycle.activate("Home");
else
callback.performCallback(cycle);
// I've found that failing to set a maximum age and a path means that
// the browser (IE 5.0 anyway) quietly drops the cookie.
IEngine engine = getEngine();
Cookie cookie = new Cookie(COOKIE_NAME, email);
cookie.setPath(engine.getServletPath());
cookie.setMaxAge(ONE_WEEK);
// Record the user's email address in a cookie
cycle.getRequestContext().addCookie(cookie);
engine.forgetPage(getPageName());
}
public void pageBeginRender(PageEvent event)
{
if (getEmail() == null)
setEmail(getRequestCycle().getRequestContext().getCookieValue(COOKIE_NAME));
}
}