001 /* 002 Copyright (C) 2003 Adam Olsen 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU General Public License as published by 006 the Free Software Foundation; either version 1, or (at your option) 007 any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU General Public License for more details. 013 014 You should have received a copy of the GNU General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 017 */ 018 019 package com.valhalla.jbother; 020 021 import javax.swing.SwingUtilities; 022 import java.awt.event.*; 023 024 import org.jivesoftware.smack.*; 025 import org.jivesoftware.smack.filter.*; 026 import org.jivesoftware.smack.packet.*; 027 import org.jivesoftware.smackx.packet.*; 028 029 import java.util.*; 030 import java.lang.reflect.*; 031 032 import com.valhalla.gui.*; 033 import com.valhalla.jbother.*; 034 import com.valhalla.jbother.jabber.smack.*; 035 import org.jivesoftware.smack.provider.ProviderManager; 036 037 import com.valhalla.jbother.jabber.smack.provider.*; 038 import com.valhalla.jbother.jabber.*; 039 import com.valhalla.settings.Settings; 040 041 /** 042 * Attempts to connect to the server. 043 * If the connection is made successfully, it sets up the various packet listeners 044 * and displays the BuddyList 045 * 046 * @author Adam Olsen 047 * @version 1.0 048 */ 049 public class ConnectorThread implements Runnable 050 { 051 private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() ); 052 private String server, username, password, resource; 053 private boolean ssl; 054 private int port = 0; 055 private String errorMessage = null; 056 private XMPPConnection connection = null; 057 private static boolean hasHadError = false; 058 private static com.valhalla.jbother.jabber.smack.ConnectionListener conListener = 059 new com.valhalla.jbother.jabber.smack.ConnectionListener(); 060 private static com.valhalla.jbother.jabber.smack.RosterListener rosterListener = 061 new com.valhalla.jbother.jabber.smack.RosterListener(); 062 private Presence.Mode connectMode = Presence.Mode.AVAILABLE; 063 private String statusString = null; 064 private boolean persistent = false; 065 private static boolean cancelled = false; 066 private boolean away = false; 067 068 /** 069 * Sets up the connector thread 070 * @param box the Object that contains all the required login information 071 */ 072 public ConnectorThread( Presence.Mode connectMode, String statusString, boolean away ) 073 { 074 this.server = Settings.getInstance().getProperty( "defaultServer" ); 075 this.username = Settings.getInstance().getProperty( "username" ); 076 this.password = Settings.getInstance().getProperty( "password" ); 077 this.resource = Settings.getInstance().getProperty( "resource" ); 078 this.ssl = Settings.getInstance().getBoolean( "useSSL" ); 079 080 String p = Settings.getInstance().getProperty( "port" ); 081 if( p != null ) 082 { 083 try { 084 port = Integer.parseInt( p ); 085 } 086 catch( NumberFormatException ex ) { } 087 } 088 089 hasHadError = false; 090 this.connectMode = connectMode; 091 this.statusString = statusString; 092 this.away = away; 093 } 094 095 public static void setCancelled( boolean c ) 096 { 097 cancelled = c; 098 } 099 100 /** 101 * Sets whether or not this thread should try to reconnect if there is a connection error 102 * 103 * @param perisisten set to <tt>true</tt> if you want the thread to continue to try and connect even if there's an error 104 */ 105 public void setPersistent( boolean persistent ) { this.persistent = persistent; } 106 107 /** 108 * Returns the ConnectionListener 109 * @return the connection listener 110 */ 111 public static com.valhalla.jbother.jabber.smack.ConnectionListener getConnectionListener() { return conListener; } 112 113 /** 114 * Sets whether or not a connection error has already been thrown for this connection 115 * @param has true if an error has already been thrown 116 **/ 117 public static void setHasHadError( boolean has ) { hasHadError = has; } 118 119 /** 120 * Called when the Threads .start() method is called 121 */ 122 public void run() 123 { 124 if( !BuddyList.getInstance().isVisible() ) BuddyList.getInstance().setVisible( true ); 125 if( !BuddyList.getInstance().getTopMenu().getStatusMenu().blinkTimerIsRunning() ) 126 { 127 BuddyList.getInstance().getTopMenu().getStatusMenu().startBlinkTimer(); 128 } 129 130 if( cancelled ) 131 { 132 BuddyList.getInstance().getTopMenu().getStatusMenu().stopBlinkTimer(); 133 cancelled = false; 134 return; 135 } 136 137 try { 138 if( com.valhalla.settings.Arguments.getInstance().getProperty( "smackdebug" ) != null ) XMPPConnection.DEBUG_ENABLED = true; 139 140 int port = this.port; 141 if( port == 0 && ssl ) port = 5223; 142 else if( port == 0 && !ssl ) port = 5222; 143 144 // set up the connection 145 if( !ssl ) connection = connection = new XMPPConnection( server, port ); 146 else connection = new SSLXMPPConnection( server, port ); 147 BuddyList.getInstance().clearTree(); 148 BuddyList.getInstance().init( connection ); 149 150 } 151 catch( Exception ex ) 152 { 153 errorMessage = ex.getMessage(); 154 } 155 156 if( cancelled ) 157 { 158 BuddyList.getInstance().getTopMenu().getStatusMenu().stopBlinkTimer(); 159 cancelled = false; 160 161 return; 162 } 163 164 // get the resource from the login box 165 String tmp = resource; 166 if( tmp == null || tmp.equals( "" ) ) tmp = "JBother"; 167 final String resource = tmp; 168 169 if( errorMessage == null && connection != null ) 170 { 171 // sets up the various packet listeners 172 PacketFilter filter = new PacketTypeFilter( Presence.class ); 173 connection.addPacketListener( new PresencePacketListener(), filter ); 174 filter = new PacketTypeFilter( Message.class ); 175 connection.addPacketListener( new MessagePacketListener(), filter ); 176 connection.addConnectionListener( conListener ); 177 filter = new PacketTypeFilter( Version.class ); 178 connection.addPacketListener( new VersionListener(), filter ); 179 filter = new PacketTypeFilter( Time.class ); 180 connection.addPacketListener( new TimeListener(), filter ); 181 182 ProviderManager.addIQProvider( "query", "jabber:iq:version", new VersionProvider() ); 183 ProviderManager.addIQProvider( "query", "jabber:iq:time", new TimeProvider() ); 184 185 // attempts to connect 186 try { 187 connection.login( username, password, resource ); 188 connection.getRoster().setSubscriptionMode( Roster.SUBSCRIPTION_MANUAL ); 189 connection.getRoster().addRosterListener( rosterListener ); 190 } 191 catch( XMPPException e ) 192 { 193 errorMessage = e.getMessage(); 194 } 195 196 } 197 198 // if there was an error, display it, and then redisplay a LoginDialog 199 if( errorMessage != null || connection == null ) 200 { 201 BuddyList.getInstance().getTopMenu().getStatusMenu().setModeChecked( null ); 202 203 if( persistent ) 204 { 205 try { 206 Thread.sleep( 3000 ); 207 } 208 catch( InterruptedException ex ) { } 209 errorMessage = null; 210 211 if( cancelled ) 212 { 213 cancelled = false; 214 215 BuddyList.getInstance().getTopMenu().getStatusMenu().stopBlinkTimer(); 216 return; 217 } 218 219 run(); 220 return; 221 } 222 223 BuddyList.getInstance().getTopMenu().getStatusMenu().stopBlinkTimer(); 224 225 226 if( errorMessage == null ) errorMessage = resources.getString( "connectionError" ); 227 if( errorMessage.equals( "Unauthorized" ) ) 228 errorMessage = new String( resources.getString( "invalidPassword" ) ); 229 230 Standard.warningMessage( null, resources.getString( "couldNotConnect" ), errorMessage ); 231 232 return; 233 } 234 235 BuddyList.getInstance().getTopMenu().getStatusMenu().stopBlinkTimer(); 236 237 // otherwise, set up and display the buddy list 238 com.valhalla.Logger.debug( "Connected" ); 239 240 BuddyList.getInstance().startTimer(); 241 BuddyList.getInstance().getTopMenu().getStatusMenu().setModeChecked( connectMode ); 242 BuddyList.getInstance().initBuddies(); // display the buddies 243 BuddyList.getInstance().setStatus( connectMode, statusString, false ); 244 245 if( away ) 246 { 247 BuddyList.getInstance().getAwayHandler().actionPerformed( new ActionEvent( BuddyList.getInstance(), 1, "away" ) ); 248 } 249 250 return; 251 } 252 }