001 /*
002 * $Id: LoginService.java,v 1.9 2005/11/30 05:21:56 rbair Exp $
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.Iterator;
025 import java.util.Vector;
026 import java.util.logging.Logger;
027
028 import javax.swing.SwingUtilities;
029 import org.jdesktop.swingx.util.SwingWorker;
030
031 /**
032 * <b>LoginService</b> is the abstract base class for all classes implementing
033 * a login mechanism. It allows you to customize the threading behaviour
034 * used to perform the login. Subclasses need to override the <b>authenticate</b>
035 * method.
036 * Subclasses may implement the getUserRoles() method to return a meaningful value
037 * this method will be called once upon a successful login to determine the user roles.
038 * It is not defined as abstract to simplify the task of implementing a login service
039 * for those who do not require this functionality.
040 *
041 * @author Bino George
042 * @author Shai Almog
043 */
044 public abstract class LoginService {
045 private Logger LOG = Logger.getLogger(LoginService.class.getName());
046 private Vector<LoginListener> listenerList = new Vector<LoginListener>();
047 private SwingWorker loginWorker;
048
049 /*
050 * Controls the authentication behaviour to be either
051 * synchronous or asynchronous
052 */
053 private boolean synchronous;
054 private String server;
055
056 public LoginService() {
057 }
058
059 public LoginService(String server) {
060 setServer(server);
061 }
062
063 /**
064 * This method is intended to be implemented by clients
065 * wishing to authenticate a user with a given password.
066 * Clients should implement the authentication in a
067 * manner that the authentication can be cancelled at
068 * any time.
069 *
070 * @param name username
071 * @param password password
072 * @param server server (optional)
073 *
074 * @return <code>true</code> on authentication success
075 * @throws Exception
076 */
077 public abstract boolean authenticate(String name, char[] password, String server) throws Exception;
078
079 /**
080 * Called immediately after a successful authentication. This method should return an array
081 * of user roles or null if role based permissions are not used.
082 *
083 * @return per default <code>null</code>
084 */
085 public String[] getUserRoles() {
086 return null;
087 }
088
089 /**
090 * Notifies the LoginService that an already running
091 * authentication request should be cancelled. This
092 * method is intended to be used by clients who want
093 * to provide user with control over cancelling a long
094 * running authentication request.
095 */
096 public void cancelAuthentication() {
097 if (loginWorker != null) {
098 loginWorker.cancel(true);
099 }
100 }
101
102 /**
103 * This method starts the authentication process and is either
104 * synchronous or asynchronous based on the synchronous property
105 *
106 * @param user user
107 * @param password password
108 * @param server server
109 * @throws Exception
110 */
111 public void startAuthentication(final String user, final char[] password, final String server) throws Exception {
112 if (getSynchronous()) {
113 try {
114 if (authenticate(user,password,server)) {
115 fireLoginSucceeded(new LoginEvent(this));
116 } else {
117 fireLoginFailed(new LoginEvent(this));
118 }
119 } catch (Throwable e) {
120 fireLoginFailed(new LoginEvent(this, e));
121 }
122 } else {
123 loginWorker = new SwingWorker() {
124 protected Object doInBackground() throws Exception {
125 try {
126 final boolean result = authenticate(user,password,server);
127 if (isCancelled()) {
128 EventQueue.invokeLater(new Runnable() {
129 public void run() {
130 fireLoginCanceled(new LoginEvent(this));
131 }
132 });
133 return false;
134 }
135 EventQueue.invokeLater(new Runnable() {
136 public void run() {
137 if (result) {
138 fireLoginSucceeded(new LoginEvent(LoginService.this));
139 } else {
140 fireLoginFailed(new LoginEvent(LoginService.this));
141 }
142 }
143 });
144 return result;
145 } catch (final Throwable failed) {
146 if (!isCancelled()) {
147 SwingUtilities.invokeLater(new Runnable() {
148 public void run() {
149 fireLoginFailed(new LoginEvent(LoginService.this, failed));
150 }
151 });
152 } else {
153 EventQueue.invokeLater(new Runnable() {
154 public void run() {
155 fireLoginCanceled(new LoginEvent(this));
156 }
157 });
158 }
159 return false;
160 }
161 }
162 };
163 loginWorker.execute();
164 fireLoginStarted(new LoginEvent(this));
165 }
166 }
167
168 /**
169 * Get the synchronous property
170 * @return the synchronous property
171 */
172 public boolean getSynchronous() {
173 return synchronous;
174 }
175 /**
176 * Sets the synchronous property
177 *
178 * @param synchronous synchronous property
179 */
180 public void setSynchronous(boolean synchronous) {
181 this.synchronous = synchronous;
182 }
183
184 /**
185 * Adds a <strong>LoginListener</strong> to the list of listeners
186 *
187 * @param listener listener
188 */
189
190 public void addLoginListener(LoginListener listener) {
191 listenerList.add(listener);
192 }
193
194 /**
195 * Removes a <strong>LoginListener</strong> from the list of listeners
196 *
197 * @param listener listener
198 */
199 public void removeLoginListener(LoginListener listener) {
200 listenerList.remove(listener);
201 }
202
203
204 void fireLoginStarted(final LoginEvent source) {
205 Iterator iter = listenerList.iterator();
206 while (iter.hasNext()) {
207 LoginListener listener = (LoginListener) iter.next();
208 listener.loginStarted(source);
209 }
210 }
211
212 void fireLoginSucceeded(final LoginEvent source) {
213 Iterator iter = listenerList.iterator();
214 while (iter.hasNext()) {
215 LoginListener listener = (LoginListener) iter.next();
216 listener.loginSucceeded(source);
217 }
218 }
219
220 void fireLoginFailed(final LoginEvent source) {
221 Iterator iter = listenerList.iterator();
222 while (iter.hasNext()) {
223 LoginListener listener = (LoginListener) iter.next();
224 listener.loginFailed(source);
225 }
226 }
227
228 void fireLoginCanceled(final LoginEvent source) {
229 Iterator iter = listenerList.iterator();
230 while (iter.hasNext()) {
231 LoginListener listener = (LoginListener) iter.next();
232 listener.loginCanceled(source);
233 }
234 }
235
236
237 /**
238 * @return Returns the server.
239 */
240 public String getServer() {
241 return server;
242 }
243 /**
244 * @param server The server to set.
245 */
246 public void setServer(String server) {
247 this.server = server;
248 }
249 }