1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.caleigo.security;
20
21 import java.util.HashMap;
22
23 import org.caleigo.service.*;
24 import org.caleigo.toolkit.log.*;
25 import org.caleigo.toolkit.tunnel.*;
26
27 /***
28 *
29 * @author Mattias Hagstrand
30 * @version 1.00
31 *
32 *//*
33 *
34 * WHEN WHO WHY & WHAT
35 * -----------------------------------------------------------------------------
36 * 2002-10-18 Mattias Hagstrand Creation
37 */
38 public class LoginService implements ILoginService
39 {
40
41
42 protected Object mServiceIdentity;
43 protected transient IMessageConsumer mMessageConsumer;
44
45 protected ILoginInfoProvider mLoginInfoProvider;
46 protected transient HashMap mLoginHandlers = new HashMap();
47
48
49 public LoginService(Object serviceIdentity)
50 {
51 mServiceIdentity = serviceIdentity;
52 mMessageConsumer = new LoginServiceMessageConsumer();
53 }
54
55
56
57 public void setLoginInfoProvider(ILoginInfoProvider provider)
58 {
59 mLoginInfoProvider = provider;
60 }
61
62 public void addLoginHandler(Class loginInfoClass, ILoginHandler loginHandler)
63 {
64 mLoginHandlers.put(loginInfoClass, loginHandler);
65 }
66
67 public void removeLoginHandler(Class loginInfoClass)
68 {
69 mLoginHandlers.remove(loginInfoClass);
70 }
71
72
73 /*** Tries to log in a user without supplying any login information. This
74 * method preferably uses descendants of <I>ILoginInfoProvider</I> to
75 * figure out the login information for the user. Returns <code>null</code>
76 * if the login was canceled.
77 */
78 public UserInfo login()
79 {
80 ILoginHandler loginHandler = (ILoginHandler) mLoginHandlers.get(UserLoginInfo.class);
81 if (loginHandler == null)
82 throw new SecurityException("No login handler found for: " + UserLoginInfo.class);
83
84 if (mLoginInfoProvider == null)
85 throw new SecurityException("No login info provider found");
86
87 Object loginInfo = mLoginInfoProvider.getUserLoginInformation();
88
89 UserInfo userInfo = loginHandler.login(loginInfo);
90
91 if (userInfo == null)
92 return null;
93
94 SessionHandler.getInstance().createSession(userInfo);
95 return userInfo;
96 }
97
98 /*** This method takes login information supplied in the <I>loginInfo</I>
99 * object. There should be a corresponding <I>ILoginHandler</I> that
100 * is registered to handle the specific <I>loginInfo</I> class. Returns <code>null</code>
101 * if the login was canceled.
102 */
103 public UserInfo login(Object loginInfo)
104 {
105 Log.print(this, "Login in on a LoginService containing " + mLoginHandlers.size() + " login handlers ");
106
107 ILoginHandler loginHandler = (ILoginHandler) mLoginHandlers.get(loginInfo.getClass());
108 if (loginHandler == null)
109 {
110 String s = loginInfo.getClass().toString();
111 Log.printError(this, "No login handler found for: " + s);
112 Log.print(this, "You can choose between:");
113 java.util.Iterator results = mLoginHandlers.keySet().iterator();
114 while (results.hasNext() )
115 {
116 Log.print(this, results.toString());
117 }
118 throw new SecurityException("No login handler found for: " + s);
119 }
120
121 UserInfo userInfo = loginHandler.login(loginInfo);
122
123 if (userInfo == null)
124 return null;
125
126 SessionHandler.getInstance().createSession(userInfo);
127 return userInfo;
128 }
129
130 /*** This is a helper method that logs in a user based on the supplied
131 * username-password pair. Returns <code>null</code>
132 * if the login was canceled.
133 */
134 public UserInfo login(String username, String password)
135 {
136 UserLoginInfo userLoginInfo = new UserLoginInfo(username, password);
137 ILoginHandler loginHandler = (ILoginHandler) mLoginHandlers.get(userLoginInfo.getClass());
138 if (loginHandler == null)
139 throw new SecurityException("No login handler found for: " + userLoginInfo.getClass());
140
141 UserInfo userInfo = loginHandler.login(userLoginInfo);
142
143 if (userInfo == null)
144 return null;
145
146 SessionHandler.getInstance().createSession(userInfo);
147 return userInfo;
148 }
149
150 public boolean logout(UserInfo userInfo)
151 {
152 if (SessionHandler.getInstance().isValidSession(userInfo, userInfo.getSessionID()))
153 {
154 SessionHandler.getInstance().destroySession(userInfo.getSessionID());
155 return true;
156 }
157 return false;
158
159 }
160
161 /*** Updates an UserInfo object that represents an allready logged in user with
162 * relevante user information.
163 */
164 public void updateUserInfo(UserInfo userInfo)
165 {
166
167 }
168
169 public void handleError(String message)
170 {
171 mLoginInfoProvider.handleError(message);
172 }
173
174 /*** Returns the maximum number of times a user is allowed to try to login
175 * before the application exits.
176 */
177 public int getMaximumNumberOfLoginTries()
178 {
179 return mLoginInfoProvider.getMaximumNumberOfLoginTries();
180 }
181
182
183
184 /*** This method is always called by the ServiceManager before any other
185 * method in the service is called.
186 */
187 public void initializeService()
188 {
189 }
190
191 /*** This method is always called by the ServiceManager before the service
192 * is released. No other method calls will then be performed on this
193 * instance of the service.
194 */
195 public void finalizeService()
196 {
197 }
198
199 /*** Should return true if the service is online and reponding to calls.
200 * Note that initializeService() must be called prior to this method.
201 */
202 public boolean ping()
203 {
204
205 return (mLoginInfoProvider != null);
206 }
207
208 /*** Returns the service object that this service provides. This object
209 * should always implement the interface defined by the service interface
210 * class.
211 */
212 public Object getServiceInterface()
213 {
214 return this;
215 }
216
217 /*** Returns the class object the defines the service interface that all
218 * services with the same type provides.
219 */
220 public Class getServiceInterfaceClass()
221 {
222 return ILoginService.class;
223 }
224
225 /*** Returns a URI that defines the type of this service. Note that
226 * there can be multiple services implementing the same service type but
227 * implementations of a given type must implement the same service
228 * interface.
229 */
230 public Object getServiceType()
231 {
232 return ILoginService.class;
233 }
234
235 /*** Returns the URI defining the a unique individual service.
236 */
237 public Object getServiceIdentity()
238 {
239 return mServiceIdentity;
240 }
241
242 /*** If this method returns true then the method getCustomProxyService must
243 * not return <code>null</code>.
244 */
245 public boolean hasCustomProxyService()
246 {
247 return true;
248 }
249
250 /*** Returns an IProxyService that is responsible for handling remote invokations
251 * of this service.
252 */
253 public IProxyService getCustomProxyService(org.caleigo.toolkit.tunnel.ITunnel tunnel)
254 {
255 LoginProxyService proxyService = new LoginProxyService(mServiceIdentity, tunnel);
256 proxyService.setLoginInfoProvider(mLoginInfoProvider);
257 tunnel.addMessageConsumer(mMessageConsumer);
258 return proxyService;
259 }
260
261
262 protected static class LoginProxyService extends LoginService implements IProxyService
263 {
264
265 protected transient ITunnel mTunnel;
266
267
268 public LoginProxyService(Object serviceIdentity, ITunnel tunnel)
269 {
270 super(serviceIdentity);
271 mTunnel = tunnel;
272 }
273
274
275
276 /*** Tries to log in a user without supplying any login information. This
277 * method preferably uses descendants of <I>ILoginInfoProvider</I> to
278 * figure out the login information for the user.
279 */
280 public UserInfo login()
281 {
282
283
284
285
286
287
288 Object loginInfo = mLoginInfoProvider.getUserLoginInformation();
289 if (loginInfo == null)
290 return null;
291
292 if (!(loginInfo instanceof UserLoginInfo))
293 throw new SecurityException("The login information has to be of type org.caleigo.security.ILoginService.UserLoginInfo");
294
295 UserLoginInfo userLoginInfo = (UserLoginInfo) loginInfo;
296
297 LoginServiceReturnMessage returnMessage = null;
298 try
299 {
300 returnMessage = (LoginServiceReturnMessage) mTunnel.ask(
301 new LoginMessage(userLoginInfo.getUsername(), userLoginInfo.getPassword()));
302 }
303 catch (TunnelException te)
304 {
305 Log.printError(this, "Received exception from tunnel", te);
306 throw new SecurityException("Received exception from tunnel: " + te.getMessage());
307 }
308
309 if (returnMessage.getException() != null)
310 {
311 if (returnMessage.getException() instanceof SecurityException)
312 throw (SecurityException) returnMessage.getException();
313 else
314 {
315 Log.printError(this, "Unknown exception from login service", returnMessage.getException());
316 return null;
317 }
318 }
319
320 UserInfo userInfo = new UserInfo.DefaultUserInfo();
321 userInfo.copyFrom(returnMessage.getUserInfo());
322 return userInfo;
323 }
324
325 public boolean logout(UserInfo userInfo) throws SecurityException
326 {
327 LoginServiceReturnMessage returnMessage = null;
328 try
329 {
330 returnMessage = (LoginServiceReturnMessage) mTunnel.ask(new LogoutMessage(userInfo, userInfo.getSessionID()));
331 }
332 catch (TunnelException te)
333 {
334 Log.printError(this, "Received exception from tunnel", te);
335 throw new SecurityException("Received exception from tunnel: " + te.getMessage());
336 }
337
338 if (returnMessage.getException() != null)
339 if (returnMessage.getException() instanceof SecurityException)
340 throw (SecurityException) returnMessage.getException();
341 else
342 {
343 Log.printError(this, "Unknown exception from login service", returnMessage.getException());
344 return false;
345 }
346
347 return returnMessage.getResult();
348 }
349
350 public void handleError(String message)
351 {
352 mLoginInfoProvider.handleError(message);
353 }
354
355
356
357 /*** Returns <code>true</code> if this IProxyService can be reconnected to
358 * an IService.
359 */
360 public boolean isReconnectable()
361 {
362 return false;
363 }
364
365 /*** Tries to reconnect to the provided service. If the reconnection fails
366 * or if this IProxyService doesn't support reconnection an exception is
367 * thrown.
368 */
369 public void reconnect(org.caleigo.toolkit.tunnel.ITunnel tunnel) throws ServiceException
370 {
371 throw new ServiceException("Operation not supported");
372 }
373
374 /*** Sets the ITunnel that should be used by this IProxyService.
375 */
376 public void setServiceTunnel(org.caleigo.toolkit.tunnel.ITunnel tunnel)
377 {
378 mTunnel = tunnel;
379 }
380 }
381
382 protected class LoginServiceMessageConsumer implements IMessageConsumer
383 {
384
385 public LoginServiceMessageConsumer()
386 {
387 }
388
389
390
391 /***
392 * Returns <code>true</code> if this IMessageConsumer accepts the message.
393 * This method is allways called before <code>consumeMessage</code> for any
394 * given message.
395 */
396 public boolean acceptsMessage(Object message)
397 {
398 return (message instanceof LoginMessage || message instanceof LogoutMessage);
399 }
400
401 /***
402 * Tells the IMessageConsumer to consume a message.
403 */
404 public void consumeMessage(Object message)
405 {
406 }
407
408 /***
409 * Tells the IMessageConsumer to consume a message and returns a new message
410 * that will be delivered to the sender of the originial message.
411 */
412 public Object answerMessage(Object message)
413 {
414 try
415 {
416 if (message instanceof LoginMessage)
417 {
418 UserInfo userInfo = login(((LoginMessage) message).getUserID(),
419 ((LoginMessage) message).getPassword());
420 return new LoginServiceReturnMessage(userInfo, (userInfo != null), null);
421 }
422 else
423 {
424
425 }
426 }
427 catch (Throwable t)
428 {
429 return new LoginServiceReturnMessage(null, false, t);
430 }
431
432 return null;
433 }
434 }
435 }