1 /** 2 * Jin - a chess client for internet chess servers. 3 * More information is available at http://www.jinchess.com/. 4 * Copyright (C) 2003 Alexander Maryanovsky. 5 * All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 */ 21 22 package free.jin; 23 24 import java.util.List; 25 26 import free.jin.plugin.PluginStartException; 27 import free.jin.ui.LoginPanel; 28 import free.jin.ui.OptionPanel; 29 import free.jin.ui.ServerChoicePanel; 30 import free.util.EventListenerList; 31 import free.util.TextUtilities; 32 import free.util.Utilities; 33 34 35 /** 36 * Manages the creation, initiation and closing of the connection to the server. 37 */ 38 39 public class ConnectionManager{ 40 41 42 43 /** 44 * The current Session. Null when none. 45 */ 46 47 private Session session = null; 48 49 50 51 /** 52 * The model whose state matches whether a session is currently established. 53 */ 54 55 private final EventListenerList listenerList = new EventListenerList(); 56 57 58 59 /** 60 * Creates a new <code>ConnectionManager</code>. 61 */ 62 ConnectionManager()63 public ConnectionManager(){ 64 65 } 66 67 68 69 /** 70 * Displays UI which allows the user to login to one of the supported servers. 71 * This method is invoked (usually by the class responsible for the start-up 72 * of the application) when all the start up initialization (preferences, 73 * ui factory etc.) has finished and it's ok to start the normal flow of the 74 * application. 75 */ 76 start()77 public void start(){ 78 Server server = findLoginServer(); 79 if (server == null) 80 return; 81 82 User user = findLoginUser(server); 83 84 ConnectionDetails connDetails = findConnDetails(server, user); 85 if (connDetails == null){ 86 Jin.getInstance().quitIfNoUiVisible(); 87 return; 88 } 89 90 login(connDetails); 91 } 92 93 94 95 /** 96 * Determines and returns the server we should login to, based on 97 * (in that order): 98 * <ol> 99 * <li> Application parameters. 100 * <li> Last logged in user. 101 * <li> Sole supported server. 102 * <li> Server choice panel displayed to the user. 103 * </ol> 104 * Returns <code>null</code> if all the above methods fail (implies that 105 * the user canceled the server choice panel). 106 */ 107 findLoginServer()108 private Server findLoginServer(){ 109 Jin jin = Jin.getInstance(); 110 111 // Application parameters 112 String serverId = jin.getParameter("login.server"); 113 if (serverId != null){ 114 Server server = jin.getServerById(serverId); 115 if (server == null){ 116 I18n i18n = I18n.get(getClass()); 117 i18n.error("unknownServerParam", new Object[]{serverId}); 118 } 119 else 120 return server; 121 } 122 123 // Last logged in user 124 User lastUser = getLastUser(); 125 if (lastUser != null) 126 return lastUser.getServer(); 127 128 // Sole supported server 129 if (jin.getServers().length == 1) 130 return jin.getServers()[0]; 131 132 // Server choice panel 133 Server askedServer = new ServerChoicePanel().askServer(); 134 if (askedServer != null) 135 return askedServer; 136 137 return null; 138 } 139 140 141 142 /** 143 * Determines and returns the user account we should login with, based on 144 * (in that order): 145 * <ol> 146 * <li> Application parameters. 147 * <li> Last logged in user. 148 * <li> Sole known user for the server. 149 * </ol> 150 * Returns <code>null</code> if all the above methods fail. 151 */ 152 findLoginUser(Server server)153 private User findLoginUser(Server server){ 154 Jin jin = Jin.getInstance(); 155 156 // Application parameters 157 boolean isGuest = new Boolean(jin.getParameter("login.guest")).booleanValue(); 158 String username = jin.getParameter("login.username"); 159 if (isGuest) 160 return server.getGuest(); 161 else if (username != null){ 162 User user = jin.getUser(server, username); 163 if (user == null) // New user 164 return new User(server, username); 165 else 166 return user; 167 } 168 169 // Last logged in user 170 User lastUser = getLastUser(); 171 if ((lastUser != null) && (lastUser.getServer() == server)) 172 return lastUser; 173 174 // Only one known user on the server 175 List serverUsers = jin.getUsers(server); 176 if (serverUsers.size() == 1) 177 return (User)serverUsers.get(0); 178 179 return null; 180 } 181 182 183 184 /** 185 * Determines the connection details we should use when logging in, based on 186 * (in that order, for each connection detail): 187 * <ol> 188 * <li> Application parameters. 189 * <li> Specified user. 190 * <li> Specified server. 191 * </ol> 192 * Additionally, if the applications parameters allow displaying the login 193 * panel, any connection details modified by the user there override all 194 * others. 195 * Returns <code>null</code> if all the above methods fail (implies that the 196 * user canceled the login panel). 197 * The specified user may be <code>null</code>, but not the server. 198 */ 199 findConnDetails(Server server, User user)200 private ConnectionDetails findConnDetails(Server server, User user){ 201 if (user == null) 202 return new LoginPanel(server).askConnectionDetails(); 203 204 Jin jin = Jin.getInstance(); 205 ConnectionDetails connDetails = user.getPreferredConnDetails(); 206 207 String password = jin.getParameter("login.password"); 208 if (password == null) 209 password = connDetails.getPassword(); 210 211 String savePassString = jin.getParameter("login.savepassword"); 212 boolean savePassword = new Boolean(savePassString).booleanValue(); 213 if ((savePassString == null) && !connDetails.isGuest()) 214 savePassword = connDetails.isSavePassword(); 215 216 String hostname = jin.getParameter("login.hostname"); 217 if (hostname == null){ 218 hostname = connDetails.getHost(); 219 } 220 221 String portsString = jin.getParameter("login.ports"); 222 int [] ports; 223 if (portsString != null) 224 ports = TextUtilities.parseIntList(portsString, ","); 225 else 226 ports = connDetails.getPorts(); 227 228 229 if (user.isGuest()) 230 connDetails = ConnectionDetails.createGuest(server, user.getUsername(), hostname, ports); 231 else 232 connDetails = ConnectionDetails.create(server, user, user.getUsername(), password, savePassword, hostname, ports); 233 234 if (!(new Boolean(jin.getParameter("autologin")).booleanValue())) 235 connDetails = new LoginPanel(connDetails).askConnectionDetails(); 236 237 return connDetails; 238 } 239 240 241 242 /** 243 * Displays UI for creating a new connection (from scratch). 244 */ 245 displayNewConnUI()246 public void displayNewConnUI(){ 247 Server server; 248 249 Server [] servers = Jin.getInstance().getServers(); 250 // Sole supported server 251 if (servers.length == 1) 252 server = servers[0]; 253 else{ // Server choice panel 254 server = new ServerChoicePanel().askServer(); 255 if (server == null) 256 return; 257 } 258 259 ConnectionDetails connDetails = new LoginPanel(server).askConnectionDetails(); 260 261 if (connDetails == null){ // user canceled the dialog 262 Jin.getInstance().quitIfNoUiVisible(); 263 return; 264 } 265 266 login(connDetails); 267 } 268 269 270 271 /** 272 * Displays UI for connecting with the specified account. 273 */ 274 displayNewConnUI(User user)275 public void displayNewConnUI(User user){ 276 ConnectionDetails connDetails = 277 new LoginPanel(user.getPreferredConnDetails()).askConnectionDetails(); 278 279 if (connDetails == null){ // user canceled the dialog 280 Jin.getInstance().quitIfNoUiVisible(); 281 return; 282 } 283 284 login(connDetails); 285 } 286 287 288 289 290 /** 291 * Initiates login with the specified connection details. 292 */ 293 login(ConnectionDetails connDetails)294 private void login(ConnectionDetails connDetails){ 295 try{ 296 session = new Session(connDetails); 297 fireSessionEvent(new SessionEvent(this, SessionEvent.SESSION_ESTABLISHED, session)); 298 session.initiateLogin(); 299 } catch (PluginStartException e){ 300 e.printStackTrace(); 301 Exception reason = e.getReason(); 302 303 String errorMessage = e.getMessage() + "\n" + 304 (reason == null ? "" : reason.getClass().getName() + ": " + reason.getMessage()); 305 OptionPanel.error("Error", errorMessage); 306 } 307 } 308 309 310 311 /** 312 * Invoked by Session if login fails. 313 * 314 * @param message The message with which login failed. 315 */ 316 loginFailed(String message)317 void loginFailed(String message){ 318 I18n i18n = I18n.get(getClass()); 319 i18n.error("loginErrorDialog", new Object[]{message}); 320 321 // Reopen the connection UI 322 User user = session.getUser(); 323 closeSession(); 324 displayNewConnUI(user); 325 } 326 327 328 329 /** 330 * Closes the current session. The call is ignored if there is no current 331 * session. 332 */ 333 closeSession()334 public void closeSession(){ 335 if (session == null) 336 return; 337 338 // Close the session 339 session.close(); 340 341 User user = session.getUser(); 342 int connPort = session.getPort(); 343 344 if (connPort != -1){ // A connection really was established 345 346 // Set preferred connection details for this account 347 ConnectionDetails connDetails = session.getConnDetails().usePort(connPort); 348 user.setPreferredConnDetails(connDetails); 349 350 // Add the user to the known users list 351 if (!user.isGuest() && !Jin.getInstance().isKnownUser(user)){ 352 I18n i18n = I18n.get(getClass()); 353 354 boolean rememberUser = 355 !Jin.getInstance().isSavePrefsCapable() || 356 OptionPanel.YES == i18n.question(OptionPanel.YES, "rememberAccountDialog", new Object[]{user.getUsername()}); 357 358 if (rememberUser){ 359 Jin.getInstance().addUser(user); 360 saveLastUser(user); 361 } 362 } 363 else{ 364 user.markDirty(); 365 saveLastUser(user); 366 } 367 } 368 369 Session tempSession = session; 370 371 session = null; 372 373 fireSessionEvent(new SessionEvent(this, SessionEvent.SESSION_CLOSED, tempSession)); 374 } 375 376 377 378 /** 379 * Returns the current <code>Session</code>, or <code>null</code> if none. 380 */ 381 getSession()382 public Session getSession(){ 383 return session; 384 } 385 386 387 388 /** 389 * Adds a session listener. 390 */ 391 addSessionListener(SessionListener l)392 public void addSessionListener(SessionListener l){ 393 listenerList.add(SessionListener.class, l); 394 } 395 396 397 398 /** 399 * Removes a session listener. 400 */ 401 removeSessionListener(SessionListener l)402 public void removeSessionListener(SessionListener l){ 403 listenerList.remove(SessionListener.class, l); 404 } 405 406 407 408 /** 409 * Fires a session event. 410 */ 411 fireSessionEvent(SessionEvent evt)412 private void fireSessionEvent(SessionEvent evt){ 413 Object [] listeners = listenerList.getListenerList(); 414 for (int i = 0; i < listeners.length; i += 2){ 415 if (listeners[i] == SessionListener.class){ 416 SessionListener listener = (SessionListener)listeners[i+1]; 417 switch (evt.getId()){ 418 case SessionEvent.SESSION_ESTABLISHED: 419 listener.sessionEstablished(evt); 420 break; 421 case SessionEvent.SESSION_CLOSED: 422 listener.sessionClosed(evt); 423 break; 424 } 425 } 426 } 427 428 } 429 430 431 432 /** 433 * Returns the <code>User</code> object of the last account that logged on. 434 * Returns <code>null</code> if none. 435 */ 436 getLastUser()437 private User getLastUser(){ 438 Preferences prefs = Jin.getInstance().getPrefs(); 439 String serverId = prefs.getString("last-login.serverId", null); 440 String username = prefs.getString("last-login.username", null); 441 442 if (serverId == null) 443 return null; 444 445 Server server = Jin.getInstance().getServerById(serverId); 446 if (username == null) 447 return server.getGuest(); 448 else 449 return Jin.getInstance().getUser(server, username); 450 } 451 452 453 454 /** 455 * Saves the information about the last account that logged in into 456 * preferences. 457 */ 458 saveLastUser(User user)459 private void saveLastUser(User user){ 460 Preferences prefs = Jin.getInstance().getPrefs(); 461 String serverId = user.getServer().getId(); 462 String oldServerId = prefs.getString("last-login.serverId", null); 463 464 prefs.setString("last-login.serverId", serverId); 465 if (!Utilities.areEqual(serverId, oldServerId)) 466 prefs.setString("last-login.username", 467 user.isGuest() || !Jin.getInstance().isKnownUser(user) ? null : user.getUsername()); 468 else if (!user.isGuest()) 469 prefs.setString("last-login.username", user.getUsername()); 470 } 471 472 473 474 }