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 java.awt.Container; 022 import java.awt.GridBagConstraints; 023 import java.awt.GridBagLayout; 024 import java.awt.event.ActionEvent; 025 import java.awt.event.ActionListener; 026 import java.util.*; 027 import javax.swing.*; 028 029 import org.jivesoftware.smack.PacketCollector; 030 import org.jivesoftware.smack.filter.*; 031 import org.jivesoftware.smack.packet.IQ; 032 import org.jivesoftware.smack.packet.Registration; 033 034 import com.valhalla.gui.*; 035 import com.valhalla.jbother.*; 036 037 /** 038 * Displays a dynamic registration form 039 * A registration server is contacted and responds with the required 040 * fields that it needs in order for someone to register for it. This form 041 * will then dynamically display the required fields. Once the fields are filled out, 042 * this class will send the information back to the server. 043 * 044 * @author Adam Olsen 045 * @version 1.0 046 */ 047 public class RegistrationForm extends JDialog 048 { 049 protected ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() ); 050 protected String server; 051 protected ArrayList fieldListFields = new ArrayList(); 052 protected ArrayList fieldListNames = new ArrayList(); 053 protected WaitDialog wait; 054 protected JLabel instructions = new JLabel( resources.getString( "pleaseFillIn" ) ); 055 private String regKey = ""; 056 private JPanel container = new JPanel(); 057 058 private JButton okButton = new JButton( resources.getString( "okButton" ) ), 059 cancelButton = new JButton( resources.getString( "cancelButton" ) ); 060 061 private JPanel buttonPanel = new JPanel(); 062 private JPanel inputPanel = new JPanel(); 063 064 private Registration register = new Registration(); 065 private RegistrationForm thisPointer = this; 066 067 //this part is for laying out the rows for the dialog 068 private int row = 1; 069 private GridBagLayout grid = new GridBagLayout(); 070 private GridBagConstraints c = new GridBagConstraints(); 071 072 /** 073 * Default constructor 074 * @param server the server to register for 075 */ 076 public RegistrationForm( String server ) 077 { 078 super( (JFrame)null, "Registration", true ); 079 setTitle( resources.getString( "registration" ) ); 080 this.server = server; 081 thisPointer = this; 082 083 wait = new WaitDialog( resources.getString( "pleaseWait" ) ); 084 085 instructions.setBorder( BorderFactory.createEmptyBorder( 5, 0, 5, 0 ) ); 086 087 container.setLayout( new BoxLayout( container, BoxLayout.Y_AXIS ) ); 088 instructions.setAlignmentX( Container.CENTER_ALIGNMENT ); 089 container.add( instructions ); 090 container.setBorder( BorderFactory.createEmptyBorder( 5, 25, 5, 25 ) ); 091 092 inputPanel.setLayout( grid ); 093 094 setContentPane( container ); 095 096 c.gridx = 0; 097 c.gridy = 0; 098 c.gridwidth = 1; 099 100 createInputBox( "username" ); 101 createInputBox( "password" ); 102 103 container.add( inputPanel ); 104 //add the buttons 105 JPanel buttonPanel = new JPanel(); 106 buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.X_AXIS ) ); 107 buttonPanel.setBorder( BorderFactory.createEmptyBorder( 5, 0, 5, 0 ) ); 108 buttonPanel.add( okButton ); 109 buttonPanel.add( cancelButton ); 110 DialogTracker.addDialog( this, true, true ); 111 112 container.add( buttonPanel ); 113 initializeListeners(); 114 } 115 116 /** 117 * Sets up the different event listeners in the RegistrationForm 118 **/ 119 private void initializeListeners() 120 { 121 cancelButton.addActionListener( new ActionListener() 122 { 123 public void actionPerformed( ActionEvent e ) 124 { 125 closeHandler(); 126 } 127 } ); 128 129 okButton.addActionListener( new ActionListener() 130 { 131 public void actionPerformed( ActionEvent e ) { register(); } 132 } ); 133 } 134 135 /** 136 * Closes this dialog 137 **/ 138 public void closeHandler() 139 { 140 DialogTracker.removeDialog( thisPointer ); 141 } 142 143 /** 144 * Causes the registration thread to begin - sending the information 145 * in the form to the server 146 **/ 147 public void register() 148 { 149 setVisible( false ); 150 wait = new WaitDialog( resources.getString( "pleaseWait" ) ); 151 wait.setVisible( true ); 152 153 Thread thread = new Thread( new RegisterThread() ); 154 thread.start(); 155 } 156 157 /** 158 * Contacts the server to find out which fields are needed 159 */ 160 public void getRegistrationInfo() 161 { 162 wait.setVisible( true ); 163 164 Thread thread = new Thread( new GetRegistrationFormThread() ); 165 thread.start(); 166 } 167 168 /** 169 * Capitalizes the first letter of a string 170 * @param text the text to capitalize 171 * @return the capitalized text 172 */ 173 private String capitalize( String text ) 174 { 175 text = text.substring( 0, 1 ).toUpperCase() + text.substring( 1, text.length() ); 176 return text; 177 } 178 179 /** 180 * Creates a <code>Label</code> and a <code>JTextField</code> next to it 181 * and places it in the registration form after the last 182 * If the label param is "password", it creates a <code>JPasswordField</code> 183 * @param label the text to put in the label 184 **/ 185 protected void createInputBox( String label ) 186 { 187 JLabel labelBox = new JLabel( capitalize( label ) + ": " ); 188 189 fieldListNames.add( label ); 190 191 c.gridy = row++; 192 c.gridx = 0; 193 c.anchor = GridBagConstraints.EAST; 194 grid.setConstraints( labelBox, c ); 195 inputPanel.add( labelBox ); 196 197 JTextField box = new JTextField( 15 ); 198 if( label.equals( "password" ) ) 199 { 200 box = new JPasswordField( 15 ); 201 box.setFont( labelBox.getFont() ); 202 } 203 204 fieldListFields.add( box ); 205 206 c.gridx = 1; 207 c.anchor = GridBagConstraints.WEST; 208 grid.setConstraints( box, c ); 209 inputPanel.add( box ); 210 } 211 212 /** 213 * Submits the registration information to the server 214 * @author Adam Olsen 215 * @version 1.0 216 */ 217 class RegisterThread implements Runnable 218 { 219 private String errorMessage; 220 221 /** 222 * is called from the <code>Thread</code> enclosing this class 223 **/ 224 public void run() 225 { 226 if( !BuddyList.getInstance().checkConnection() ) 227 { 228 BuddyList.getInstance().connectionError(); 229 return; 230 } 231 232 register = new Registration(); 233 register.setType( IQ.Type.SET ); 234 register.setTo( server ); 235 236 Hashtable map = new Hashtable(); 237 map.put( "key", regKey ); 238 239 // set up the various attributes to be sent to the server 240 for( int i = 0; i < fieldListNames.size(); i++ ) 241 { 242 String name = (String)fieldListNames.get( i ); 243 JTextField field = (JTextField)fieldListFields.get( i ); 244 245 if( name.equals( "username" ) ) register.setUsername( field.getText() ); 246 else if( name.equals( "password" ) ) register.setPassword( field.getText() ); 247 else map.put( name, field.getText() ); 248 } 249 250 // send the packet 251 register.setAttributes( map ); 252 PacketFilter filter = new AndFilter( new PacketIDFilter( register.getPacketID() ), 253 new PacketTypeFilter( IQ.class ) ); 254 255 PacketCollector collector = BuddyList.getInstance().getConnection().createPacketCollector( filter ); 256 BuddyList.getInstance().getConnection().sendPacket( register ); 257 258 // collect the response 259 IQ result = (IQ)collector.nextResult( 30000 ); 260 wait.dispose(); 261 262 if( result == null ) 263 { 264 errorMessage = resources.getString( "unknownError" ); 265 } 266 else if( result.getType() == IQ.Type.ERROR ) 267 { 268 errorMessage = result.getError().getMessage(); 269 if( errorMessage == null ) errorMessage = resources.getString( "unknownError" ); 270 } 271 272 // display the error message if there was one 273 // otherwise just close 274 SwingUtilities.invokeLater( new Runnable() 275 { 276 public void run() 277 { 278 if( errorMessage != null ) 279 { 280 Standard.warningMessage( null, resources.getString( "registration" ), errorMessage ); 281 } 282 else { 283 NMOptionDialog.createMessageDialog( null, resources.getString( "registration" ), 284 resources.getString( "registrationSuccessful" ) ); 285 } 286 287 DialogTracker.removeDialog( thisPointer ); 288 } 289 } ); 290 } 291 } 292 293 /** 294 * Contacts the registration server and finds out what fields 295 * need to be sent back in order to register for the server 296 * @author Adam Olsen 297 * @version 1.0 298 */ 299 class GetRegistrationFormThread implements Runnable 300 { 301 private String errorMessage; 302 303 /** 304 * Called from the <code>Thread</code> enclosing this class 305 **/ 306 public void run() 307 { 308 if( !BuddyList.getInstance().checkConnection() ) 309 { 310 BuddyList.getInstance().connectionError(); 311 return; 312 } 313 314 register = new Registration(); 315 register.setType( IQ.Type.GET ); 316 register.setTo( server ); 317 PacketFilter filter = new AndFilter( new PacketIDFilter( register.getPacketID() ), 318 new PacketTypeFilter( IQ.class ) ); 319 320 PacketCollector collector = BuddyList.getInstance().getConnection().createPacketCollector( filter ); 321 322 // send the request 323 BuddyList.getInstance().getConnection().sendPacket( register ); 324 325 // collect the response 326 IQ result = (IQ)collector.nextResult( 20000 ); 327 328 if( result == null ) 329 { 330 errorMessage = resources.getString( "noResponse" ); 331 } 332 else if( result.getType() == IQ.Type.ERROR ) 333 { 334 errorMessage = result.getError().getMessage(); 335 if( errorMessage == null ) errorMessage = resources.getString( "unknownError" ); 336 } 337 338 339 wait.setVisible( false ); 340 341 // if there was no error, create the registration form and display it 342 if( errorMessage == null ) 343 { 344 register = (Registration)result; 345 346 instructions.setText( "<html><table width='300' border='0'><tr><td align='center'> " + 347 register.getInstructions() + "</td></tr></table></html>" ); 348 349 Map map = register.getAttributes(); 350 if( map != null ) 351 { 352 Iterator iterator = map.keySet().iterator(); 353 354 while( iterator.hasNext() ) 355 { 356 String key = (String)iterator.next(); 357 358 // build the registration form 359 String value = (String)map.get( key ); 360 if( key.equals( "key" ) ) regKey = value; // this field does not need to be displayed 361 else if( !key.equals( "username" ) && !key.equals( "password" ) && !key.equals( "instructions" ) ) createInputBox( key ); 362 } 363 } 364 365 } 366 367 // either display an error if there was one or 368 // display the registration dialog if there wasn't one 369 SwingUtilities.invokeLater( new Runnable() 370 { 371 public void run() 372 { 373 if( errorMessage != null ) 374 { 375 Standard.warningMessage( null, resources.getString( "registration" ), errorMessage ); 376 DialogTracker.removeDialog( thisPointer ); 377 } 378 else { 379 pack(); 380 381 setLocationRelativeTo( null ); 382 setVisible( true ); 383 } 384 } 385 } ); 386 } 387 } 388 }