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    }