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 com.valhalla.jbother.jabber.*;
022    import com.valhalla.jbother.jabber.smack.*;
023    
024    import java.util.*;
025    import org.jivesoftware.smack.*;
026    import org.jivesoftware.smack.packet.*;
027    import org.jivesoftware.smackx.packet.*;
028    import org.jivesoftware.smack.filter.*;
029    import com.valhalla.gui.*;
030    import javax.swing.*;
031    import java.awt.*;
032    import java.awt.event.*;
033    import java.lang.reflect.*;
034    import javax.swing.border.*;
035    import com.valhalla.jbother.*;
036    
037    /**
038     * A dialog that collects and shows information about a Jabber user
039     * Shows a dialog with several fields and starts an information collecting field for each one.
040     * As each piece of information is found it fills out the fields
041     *
042     * @author Adam Olsen
043     * @version 1.0
044    */
045    public class InformationViewerDialog extends JDialog
046    {
047            private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() );
048            private ArrayList values = new ArrayList();
049            private JButton okButton = new JButton( resources.getString( "okButton" ) );
050            private String user;
051            private JPanel mainPanel;
052            private JPanel rightInner = new JPanel();
053            private JPanel leftInner = new JPanel();
054            private JPanel innerPanel = new JPanel();
055            private InformationViewerDialog thisPointer = this;
056    
057            /**
058             * Default constructor
059             * @param user the user you want to collect information about
060             */
061            public InformationViewerDialog( String user )
062            {
063                    this.user = user;
064                    setTitle( resources.getString( "information" ) + " " + user );
065    
066                    mainPanel = (JPanel)getContentPane();
067                    innerPanel.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
068                    innerPanel.setLayout( new BoxLayout( innerPanel, BoxLayout.X_AXIS ) );
069    
070                    rightInner = new JPanel();
071                    rightInner.setLayout( new BoxLayout( rightInner, BoxLayout.Y_AXIS ) );
072                    leftInner = new JPanel();
073                    leftInner.setLayout( new BoxLayout( leftInner, BoxLayout.Y_AXIS ) );
074                    innerPanel.add( leftInner );
075                    innerPanel.add( rightInner );
076    
077                    mainPanel.setLayout( new BorderLayout() );
078                    mainPanel.setBorder( BorderFactory.createTitledBorder( user ) );
079                    mainPanel.add( innerPanel, BorderLayout.CENTER );
080    
081                    JPanel buttonPanel = new JPanel();
082                    buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.X_AXIS ) );
083                    buttonPanel.add( Box.createHorizontalGlue() );
084                    buttonPanel.add( okButton );
085                    buttonPanel.add( Box.createHorizontalGlue() );
086                    buttonPanel.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
087    
088                    mainPanel.add( buttonPanel, BorderLayout.SOUTH );
089    
090                    addItems();
091                    pack();
092    
093                    Dimension dim = getSize();
094                    setSize( new Dimension( 500, (int)dim.getHeight() ) );
095    
096                    setLocationRelativeTo( null );
097                    DialogTracker.addDialog( this, false, true );
098    
099                    okButton.addActionListener( new ActionListener()
100                    {
101                            public void actionPerformed( ActionEvent e )
102                            {
103                                    DialogTracker.removeDialog( thisPointer );
104                            }
105                    } );
106            }
107    
108            /**
109             * Adds the different fields to the displayed form
110            */
111            private void addItems()
112            {
113                    /* gets jabber:iq:version information */
114                    addItem( resources.getString( "clientInformation" ), VersionCollector.class );
115                    addItem( resources.getString( "timeInformation" ), TimeCollector.class );
116            }
117    
118            /**
119             * Adds a field and starts the thread that will collect it's information
120             * @param key the name of the field
121             * @param informationThread the thread that will collect the information
122             */
123            private void addItem( String key, Class informationThread )
124            {
125                    UIDefaults ui = UIManager.getDefaults();
126                    Font newFont = (Font)ui.get( "Label.font" );
127    
128                    JLabel label = new JLabel( key + ":  " );
129                    label.setFont( new Font( newFont.getName(), Font.BOLD, newFont.getSize() ) );
130                    leftInner.add( label );
131    
132                    JLabel valueLabel = new JLabel( resources.getString( "fetchingInfo" ) );
133                    rightInner.add( valueLabel );
134    
135                    try {
136                            // start the information collector thread
137                            Class[] thisArgsClass = new Class[] { InformationViewerDialog.class, Integer.class };
138                            Object[] args = new Object[] { this, new Integer( values.size() ) };
139    
140                            Constructor con = informationThread.getConstructor( thisArgsClass );
141                            InformationCollector col = (InformationCollector)con.newInstance( args );
142                            Thread thread = new Thread( col );
143                            thread.start();
144                    }
145                    catch( Exception e )
146                    {
147                            com.valhalla.Logger.logException( e );
148                    }
149    
150                    values.add( valueLabel );
151            }
152    
153            /**
154             * Gets the different field names
155             * @return The ArrayList containing all the field names
156            */
157            protected ArrayList getValues() { return values; }
158    
159            /**
160             * Gets the user that the InformationDialog was instantiated for
161             * @return the user
162            */
163            protected String getUser() { return user; }
164    }
165    
166    /**
167     * Abstract information thread
168     * Each subclass of this class is to collect the information for a specific field
169     * @author Adam Olsen
170     * @version 1.0
171    */
172    abstract class InformationCollector implements Runnable
173    {
174            protected Integer id;
175            protected InformationViewerDialog dialog;
176    
177            /**
178             * The default constructor
179             * @param dialog the InformationViewerDialog that called this thread
180             * @param id the field id
181            */
182            public InformationCollector( InformationViewerDialog dialog,  Integer id ) { this.dialog = dialog; this.id = id; }
183    
184            /**
185             * Called by the enclosing <code>java.util.Thread</code>
186            */
187            abstract public void run();
188    }
189    
190    /**
191     * An <code>InformationCollector</code> that collects jabbber:iq:version information
192     * @author Adam Olsen
193     * @version 1.0
194    */
195    class VersionCollector extends InformationCollector
196    {
197            /**
198             * The default constructor
199             * @param dialog the InformationViewerDialog that called this thread
200             * @param id the field id
201            */
202            public VersionCollector( InformationViewerDialog dialog, Integer id ) { super( dialog, id ); }
203    
204            /**
205             * Called by the enclosing <code>java.util.Thread</code>
206             * The run() method is responsible for collecting the requested information
207             * and setting the field in the InformationViewerDialog
208            */
209            public void run()
210            {
211                    XMPPConnection con = BuddyList.getInstance().getConnection();
212    
213                    Version request = new Version();
214                    request.setType( IQ.Type.GET );
215                    request.setTo( dialog.getUser() );
216    
217                    // Create a packet collector to listen for a response.
218                    PacketCollector collector = con.createPacketCollector(
219                            new PacketIDFilter( request.getPacketID() ) );
220    
221                    con.sendPacket( request );
222    
223                    // Wait up to 5 seconds for a result.
224                    IQ result = (IQ)collector.nextResult( 3000 );
225                    JLabel label = (JLabel)dialog.getValues().get( id.intValue() );
226    
227                    if( result != null && result.getType() == IQ.Type.RESULT )
228                    {
229                            Version v = (Version)result;
230    
231                            label.setText( v.getName() + " " + v.getVersion() + " / " + v.getOs() );
232                    }
233                    else {
234                            label.setText( "N/A" );
235                    }
236    
237                    label.repaint();
238                    dialog.validate();
239            }
240    }
241    
242    /**
243     * @author Adam Olsen
244     * @version 1.0
245    */
246    class TimeCollector extends InformationCollector
247    {
248            /**
249             * The default constructor
250             * @param dialog the InformationViewerDialog that called this thread
251             * @param id the field id
252            */
253            public TimeCollector( InformationViewerDialog dialog, Integer id ) { super( dialog, id ); }
254    
255            /**
256             * Called by the enclosing <code>java.util.Thread</code>
257             * The run() method is responsible for collecting the requested information
258             * and setting the field in the InformationViewerDialog
259            */
260            public void run()
261            {
262                    XMPPConnection con = BuddyList.getInstance().getConnection();
263    
264                    Time request = new Time();
265                    request.setType( IQ.Type.GET );
266                    request.setTo( dialog.getUser() );
267    
268                    // Create a packet collector to listen for a response.
269                    PacketCollector collector = con.createPacketCollector(
270                            new PacketIDFilter( request.getPacketID() ) );
271    
272                    con.sendPacket( request );
273    
274                    // Wait up to 5 seconds for a result.
275                    IQ result = (IQ)collector.nextResult( 3000 );
276                    JLabel label = (JLabel)dialog.getValues().get( id.intValue() );
277    
278                    if( result != null && result.getType() == IQ.Type.RESULT )
279                    {
280                            Time t = (Time)result;
281    
282                            label.setText( t.getDisplay() );
283                    }
284                    else {
285                            label.setText( "N/A" );
286                    }
287    
288                    label.repaint();
289                    dialog.validate();
290            }
291    }