From 997f66665bd15353b7ccb8dd867ebcb67832edc6 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Thu, 22 May 2008 07:49:24 +0000 Subject: [PATCH] Added LoginForm component, fixes #1362 svn changeset:4612/svn branch:trunk --- src/com/itmill/toolkit/ui/LoginForm.java | 230 +++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/com/itmill/toolkit/ui/LoginForm.java diff --git a/src/com/itmill/toolkit/ui/LoginForm.java b/src/com/itmill/toolkit/ui/LoginForm.java new file mode 100644 index 0000000000..4451c8fa4d --- /dev/null +++ b/src/com/itmill/toolkit/ui/LoginForm.java @@ -0,0 +1,230 @@ +package com.itmill.toolkit.ui; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.itmill.toolkit.Application; +import com.itmill.toolkit.terminal.ApplicationResource; +import com.itmill.toolkit.terminal.DownloadStream; +import com.itmill.toolkit.terminal.ParameterHandler; +import com.itmill.toolkit.terminal.URIHandler; + +/** + * LoginForm is a Toolkit component to handle common problem among Ajax + * applications: browsers password managers don't fill dynamically created forms + * like all those UI elements created by IT Mill Toolkit. + * + * For developer it is easy to use: add component to a desired place in you UI + * and add LoginListener to validate form input. Behind the curtain LoginForm + * creates an iframe with static html that browsers detect. + * + * Login page html can be overridden by replacing protected getLoginHTML method. + * As the login page is actually an iframe, styles must be handled manually. By + * default component tries to guess the right place for theme css. + * + * Note, this is a new Ajax terminal specific component and is likely to change. + * + * @since 5.3 + */ +public class LoginForm extends CustomComponent { + + private Embedded iframe = new Embedded(); + + private ApplicationResource loginPage = new ApplicationResource() { + + public Application getApplication() { + return LoginForm.this.getApplication(); + } + + public int getBufferSize() { + return getLoginHTML().length; + } + + public long getCacheTime() { + return 0; + } + + public String getFilename() { + return "login.html"; + } + + public DownloadStream getStream() { + return new DownloadStream(new ByteArrayInputStream(getLoginHTML()), + getMIMEType(), getFilename()); + } + + public String getMIMEType() { + return "text/html"; + } + }; + + private ParameterHandler paramHandler = new ParameterHandler() { + + public void handleParameters(Map parameters) { + if (parameters.containsKey("username")) { + getWindow().addURIHandler(uriHandler); + + HashMap params = new HashMap(); + // expecting single params + for (Iterator it = parameters.keySet().iterator(); it.hasNext();) { + String key = (String) it.next(); + String value = ((String[]) parameters.get(key))[0]; + params.put(key, value); + } + LoginEvent event = new LoginEvent(params); + fireEvent(event); + } + } + }; + + private URIHandler uriHandler = new URIHandler() { + private final String responce = "Login form handeled." + + ""; + + public DownloadStream handleURI(URL context, String relativeUri) { + if (window != null) { + window.removeURIHandler(this); + } + return new DownloadStream(new ByteArrayInputStream(responce + .getBytes()), "text/html", "loginSuccesfull.html"); + } + }; + + private Window window; + + public LoginForm() { + iframe.setType(Embedded.TYPE_BROWSER); + iframe.setSizeFull(); + setCompositionRoot(iframe); + } + + /** + * Returns byte array containing login page html. If you need to override + * the login html, use the default html as basis. Login page sets its target + * with javascript. + * + * @return byte array containing login page html + */ + protected byte[] getLoginHTML() { + + String theme = getApplication().getMainWindow().getTheme(); + String guessedThemeUri = getApplication().getURL() + "ITMILL/themes/" + + (theme == null ? "default" : theme) + "/styles.css"; + String guessedThemeUri2 = getApplication().getURL() + + "../ITMILL/themes/" + (theme == null ? "default" : theme) + + "/styles.css"; + + return ("" + + "" + + "" + + "" + + "" + + "" + + "
" + + "Username

" + + "Password

" + + "
" + + "") + .getBytes(); + } + + public void attach() { + super.attach(); + getApplication().addResource(loginPage); + getWindow().addParameterHandler(paramHandler); + iframe.setSource(loginPage); + } + + public void detach() { + getApplication().removeResource(loginPage); + getWindow().removeParameterHandler(paramHandler); + // store window temporary to properly remove uri handler once + // response is handled. (May happen if login handler removes login + // form + window = getWindow(); + super.detach(); + } + + /** + * This event is sent when login form is submitted. + */ + public class LoginEvent extends Event { + + private Map params; + + private LoginEvent(Map params) { + super(LoginForm.this); + this.params = params; + } + + /** + * Access method to form values by field names. + * + * @param name + * @return value in given field + */ + public String getLoginParameter(String name) { + if (params.containsKey(name)) { + return (String) params.get(name); + } else { + return null; + } + } + } + + /** + * Login listener is a class capable to listen LoginEvents sent from + * LoginBox + */ + public interface LoginListener { + /** + * This method is fired on each login form post. + * + * @param event + */ + public void onLogin(LoginForm.LoginEvent event); + } + + private static final Method ON_LOGIN_METHOD; + + static { + try { + ON_LOGIN_METHOD = LoginListener.class.getDeclaredMethod("onLogin", + new Class[] { LoginEvent.class }); + } catch (final java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /** + * Adds LoginListener to handle login logic + * + * @param listener + */ + public void addListener(LoginListener listener) { + addListener(LoginEvent.class, listener, ON_LOGIN_METHOD); + } + + /** + * Removes LoginListener + * + * @param listener + */ + public void removeListener(LoginListener listener) { + removeListener(LoginEvent.class, listener, ON_LOGIN_METHOD); + } + +} -- 2.39.5