001/* 002 * $Id: LoginService.java 3661 2010-04-13 13:19:47Z kleopatra $ 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 */ 021package org.jdesktop.swingx.auth; 022 023import java.awt.EventQueue; 024import java.util.logging.Logger; 025 026import javax.swing.SwingUtilities; 027import javax.swing.SwingWorker; 028import javax.swing.event.EventListenerList; 029 030import 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 */ 046public abstract class LoginService extends AbstractBean { 047 @SuppressWarnings("unused") 048 private Logger LOG = Logger.getLogger(LoginService.class.getName()); 049 050 private EventListenerList listenerList = new EventListenerList(); 051 052 private SwingWorker<Boolean, Void> loginWorker; 053 054 /* 055 * Controls the authentication behaviour to be either synchronous or 056 * asynchronous 057 */ 058 private boolean synchronous; 059 060 private String server; 061 062 public LoginService() { 063 } 064 065 public LoginService(String server) { 066 setServer(server); 067 } 068 069 /** 070 * This method is intended to be implemented by clients wishing to 071 * authenticate a user with a given password. Clients should implement the 072 * authentication in a manner that the authentication can be cancelled at 073 * any time. 074 * 075 * @param name 076 * username 077 * @param password 078 * password 079 * @param server 080 * server (optional) 081 * 082 * @return <code>true</code> on authentication success 083 * @throws Exception 084 */ 085 public abstract boolean authenticate(String name, char[] password, 086 String server) throws Exception; 087 088 /** 089 * Called immediately after a successful authentication. This method should 090 * return an array of user roles or null if role based permissions are not 091 * used. 092 * 093 * @return per default <code>null</code> 094 */ 095 public String[] getUserRoles() { 096 return null; 097 } 098 099 /** 100 * Notifies the LoginService that an already running authentication request 101 * should be cancelled. This method is intended to be used by clients who 102 * want to provide user with control over cancelling a long running 103 * authentication request. 104 */ 105 public void cancelAuthentication() { 106 if (loginWorker != null) { 107 loginWorker.cancel(true); 108 } 109 } 110 111 /** 112 * This method starts the authentication process and is either synchronous 113 * or asynchronous based on the synchronous property 114 * 115 * @param user 116 * user 117 * @param password 118 * password 119 * @param server 120 * server 121 * @throws Exception 122 */ 123 public void startAuthentication(final String user, final char[] password, 124 final String server) throws Exception { 125 if (getSynchronous()) { 126 try { 127 if (authenticate(user, password, server)) { 128 fireLoginSucceeded(new LoginEvent(this)); 129 } else { 130 fireLoginFailed(new LoginEvent(this)); 131 } 132 } catch (Throwable e) { 133 fireLoginFailed(new LoginEvent(this, e)); 134 } 135 } else { 136 loginWorker = new SwingWorker<Boolean, Void>() { 137 @Override 138 protected Boolean doInBackground() throws Exception { 139 try { 140 final boolean result = authenticate(user, password, 141 server); 142 if (isCancelled()) { 143 EventQueue.invokeLater(new Runnable() { 144 public void run() { 145 fireLoginCanceled(new LoginEvent(this)); 146 } 147 }); 148 return false; 149 } 150 EventQueue.invokeLater(new Runnable() { 151 public void run() { 152 if (result) { 153 fireLoginSucceeded(new LoginEvent( 154 LoginService.this)); 155 } else { 156 fireLoginFailed(new LoginEvent( 157 LoginService.this)); 158 } 159 } 160 }); 161 return result; 162 } catch (final Throwable failed) { 163 if (!isCancelled()) { 164 SwingUtilities.invokeLater(new Runnable() { 165 public void run() { 166 fireLoginFailed(new LoginEvent( 167 LoginService.this, failed)); 168 } 169 }); 170 } else { 171 EventQueue.invokeLater(new Runnable() { 172 public void run() { 173 fireLoginCanceled(new LoginEvent(this)); 174 } 175 }); 176 } 177 return false; 178 } 179 } 180 }; 181 loginWorker.execute(); 182 fireLoginStarted(new LoginEvent(this)); 183 } 184 } 185 186 /** 187 * Get the synchronous property 188 * 189 * @return the synchronous property 190 */ 191 public boolean getSynchronous() { 192 return synchronous; 193 } 194 195 /** 196 * Sets the synchronous property 197 * 198 * @param synchronous 199 * synchronous property 200 */ 201 public void setSynchronous(boolean synchronous) { 202 boolean old = getSynchronous(); 203 this.synchronous = synchronous; 204 firePropertyChange("synchronous", old, getSynchronous()); 205 } 206 207 /** 208 * Adds a <strong>LoginListener</strong> to the list of listeners 209 * 210 * @param listener 211 * listener 212 */ 213 214 public void addLoginListener(LoginListener listener) { 215 listenerList.add(LoginListener.class, listener); 216 } 217 218 /** 219 * Removes a <strong>LoginListener</strong> from the list of listeners 220 * 221 * @param listener 222 * listener 223 */ 224 public void removeLoginListener(LoginListener listener) { 225 listenerList.remove(LoginListener.class, listener); 226 } 227 228 void fireLoginStarted(final LoginEvent source) { 229 // Guaranteed to return a non-null array 230 Object[] listeners = listenerList.getListenerList(); 231 // Process the listeners last to first, notifying 232 // those that are interested in this event 233 for (int i = listeners.length-2; i>=0; i-=2) { 234 if (listeners[i] == LoginListener.class) { 235 ((LoginListener) listeners[i+1]).loginStarted(source); 236 } 237 } 238 } 239 240 void fireLoginSucceeded(final LoginEvent source) { 241 // Guaranteed to return a non-null array 242 Object[] listeners = listenerList.getListenerList(); 243 // Process the listeners last to first, notifying 244 // those that are interested in this event 245 for (int i = listeners.length-2; i>=0; i-=2) { 246 if (listeners[i] == LoginListener.class) { 247 ((LoginListener) listeners[i+1]).loginSucceeded(source); 248 } 249 } 250 } 251 252 void fireLoginFailed(final LoginEvent source) { 253 // Guaranteed to return a non-null array 254 Object[] listeners = listenerList.getListenerList(); 255 // Process the listeners last to first, notifying 256 // those that are interested in this event 257 for (int i = listeners.length-2; i>=0; i-=2) { 258 if (listeners[i] == LoginListener.class) { 259 ((LoginListener) listeners[i+1]).loginFailed(source); 260 } 261 } 262 } 263 264 void fireLoginCanceled(final LoginEvent source) { 265 // Guaranteed to return a non-null array 266 Object[] listeners = listenerList.getListenerList(); 267 // Process the listeners last to first, notifying 268 // those that are interested in this event 269 for (int i = listeners.length-2; i>=0; i-=2) { 270 if (listeners[i] == LoginListener.class) { 271 ((LoginListener) listeners[i+1]).loginCanceled(source); 272 } 273 } 274 } 275 276 /** 277 * @return Returns the server. 278 */ 279 public String getServer() { 280 return server; 281 } 282 283 /** 284 * @param server 285 * The server to set. 286 */ 287 public void setServer(String server) { 288 String old = getServer(); 289 this.server = server; 290 firePropertyChange("server", old, getServer()); 291 } 292}