001 /* 002 * $Id: LoginService.java 3360 2009-06-14 20:29:45Z kschaefe $ 003 * 004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021 package org.jdesktop.swingx.auth; 022 023 import java.awt.EventQueue; 024 import java.util.logging.Logger; 025 026 import javax.swing.SwingUtilities; 027 import javax.swing.SwingWorker; 028 import javax.swing.event.EventListenerList; 029 030 import org.jdesktop.beans.AbstractBean; 031 032 /** 033 * <b>LoginService</b> is the abstract base class for all classes implementing 034 * a login mechanism. It allows you to customize the threading behaviour used to 035 * perform the login. Subclasses need to override the <b>authenticate</b> 036 * method. Subclasses may implement the getUserRoles() method to return a 037 * meaningful value this method will be called once upon a successful login to 038 * determine the user roles. It is not defined as abstract to simplify the task 039 * of implementing a login service for those who do not require this 040 * functionality. 041 * 042 * @author Bino George 043 * @author Shai Almog 044 * @author Karl Schaefer 045 */ 046 public abstract class LoginService extends AbstractBean { 047 private Logger LOG = Logger.getLogger(LoginService.class.getName()); 048 049 private EventListenerList listenerList = new EventListenerList(); 050 051 private SwingWorker<Boolean, Void> loginWorker; 052 053 /* 054 * Controls the authentication behaviour to be either synchronous or 055 * asynchronous 056 */ 057 private boolean synchronous; 058 059 private String server; 060 061 public LoginService() { 062 } 063 064 public LoginService(String server) { 065 setServer(server); 066 } 067 068 /** 069 * This method is intended to be implemented by clients wishing to 070 * authenticate a user with a given password. Clients should implement the 071 * authentication in a manner that the authentication can be cancelled at 072 * any time. 073 * 074 * @param name 075 * username 076 * @param password 077 * password 078 * @param server 079 * server (optional) 080 * 081 * @return <code>true</code> on authentication success 082 * @throws Exception 083 */ 084 public abstract boolean authenticate(String name, char[] password, 085 String server) throws Exception; 086 087 /** 088 * Called immediately after a successful authentication. This method should 089 * return an array of user roles or null if role based permissions are not 090 * used. 091 * 092 * @return per default <code>null</code> 093 */ 094 public String[] getUserRoles() { 095 return null; 096 } 097 098 /** 099 * Notifies the LoginService that an already running authentication request 100 * should be cancelled. This method is intended to be used by clients who 101 * want to provide user with control over cancelling a long running 102 * authentication request. 103 */ 104 public void cancelAuthentication() { 105 if (loginWorker != null) { 106 loginWorker.cancel(true); 107 } 108 } 109 110 /** 111 * This method starts the authentication process and is either synchronous 112 * or asynchronous based on the synchronous property 113 * 114 * @param user 115 * user 116 * @param password 117 * password 118 * @param server 119 * server 120 * @throws Exception 121 */ 122 public void startAuthentication(final String user, final char[] password, 123 final String server) throws Exception { 124 if (getSynchronous()) { 125 try { 126 if (authenticate(user, password, server)) { 127 fireLoginSucceeded(new LoginEvent(this)); 128 } else { 129 fireLoginFailed(new LoginEvent(this)); 130 } 131 } catch (Throwable e) { 132 fireLoginFailed(new LoginEvent(this, e)); 133 } 134 } else { 135 loginWorker = new SwingWorker<Boolean, Void>() { 136 protected Boolean doInBackground() throws Exception { 137 try { 138 final boolean result = authenticate(user, password, 139 server); 140 if (isCancelled()) { 141 EventQueue.invokeLater(new Runnable() { 142 public void run() { 143 fireLoginCanceled(new LoginEvent(this)); 144 } 145 }); 146 return false; 147 } 148 EventQueue.invokeLater(new Runnable() { 149 public void run() { 150 if (result) { 151 fireLoginSucceeded(new LoginEvent( 152 LoginService.this)); 153 } else { 154 fireLoginFailed(new LoginEvent( 155 LoginService.this)); 156 } 157 } 158 }); 159 return result; 160 } catch (final Throwable failed) { 161 if (!isCancelled()) { 162 SwingUtilities.invokeLater(new Runnable() { 163 public void run() { 164 fireLoginFailed(new LoginEvent( 165 LoginService.this, failed)); 166 } 167 }); 168 } else { 169 EventQueue.invokeLater(new Runnable() { 170 public void run() { 171 fireLoginCanceled(new LoginEvent(this)); 172 } 173 }); 174 } 175 return false; 176 } 177 } 178 }; 179 loginWorker.execute(); 180 fireLoginStarted(new LoginEvent(this)); 181 } 182 } 183 184 /** 185 * Get the synchronous property 186 * 187 * @return the synchronous property 188 */ 189 public boolean getSynchronous() { 190 return synchronous; 191 } 192 193 /** 194 * Sets the synchronous property 195 * 196 * @param synchronous 197 * synchronous property 198 */ 199 public void setSynchronous(boolean synchronous) { 200 boolean old = getSynchronous(); 201 this.synchronous = synchronous; 202 firePropertyChange("synchronous", old, getSynchronous()); 203 } 204 205 /** 206 * Adds a <strong>LoginListener</strong> to the list of listeners 207 * 208 * @param listener 209 * listener 210 */ 211 212 public void addLoginListener(LoginListener listener) { 213 listenerList.add(LoginListener.class, listener); 214 } 215 216 /** 217 * Removes a <strong>LoginListener</strong> from the list of listeners 218 * 219 * @param listener 220 * listener 221 */ 222 public void removeLoginListener(LoginListener listener) { 223 listenerList.remove(LoginListener.class, listener); 224 } 225 226 void fireLoginStarted(final LoginEvent source) { 227 // Guaranteed to return a non-null array 228 Object[] listeners = listenerList.getListenerList(); 229 // Process the listeners last to first, notifying 230 // those that are interested in this event 231 for (int i = listeners.length-2; i>=0; i-=2) { 232 if (listeners[i] == LoginListener.class) { 233 ((LoginListener) listeners[i+1]).loginStarted(source); 234 } 235 } 236 } 237 238 void fireLoginSucceeded(final LoginEvent source) { 239 // Guaranteed to return a non-null array 240 Object[] listeners = listenerList.getListenerList(); 241 // Process the listeners last to first, notifying 242 // those that are interested in this event 243 for (int i = listeners.length-2; i>=0; i-=2) { 244 if (listeners[i] == LoginListener.class) { 245 ((LoginListener) listeners[i+1]).loginSucceeded(source); 246 } 247 } 248 } 249 250 void fireLoginFailed(final LoginEvent source) { 251 // Guaranteed to return a non-null array 252 Object[] listeners = listenerList.getListenerList(); 253 // Process the listeners last to first, notifying 254 // those that are interested in this event 255 for (int i = listeners.length-2; i>=0; i-=2) { 256 if (listeners[i] == LoginListener.class) { 257 ((LoginListener) listeners[i+1]).loginFailed(source); 258 } 259 } 260 } 261 262 void fireLoginCanceled(final LoginEvent source) { 263 // Guaranteed to return a non-null array 264 Object[] listeners = listenerList.getListenerList(); 265 // Process the listeners last to first, notifying 266 // those that are interested in this event 267 for (int i = listeners.length-2; i>=0; i-=2) { 268 if (listeners[i] == LoginListener.class) { 269 ((LoginListener) listeners[i+1]).loginCanceled(source); 270 } 271 } 272 } 273 274 /** 275 * @return Returns the server. 276 */ 277 public String getServer() { 278 return server; 279 } 280 281 /** 282 * @param server 283 * The server to set. 284 */ 285 public void setServer(String server) { 286 String old = getServer(); 287 this.server = server; 288 firePropertyChange("server", old, getServer()); 289 } 290 }