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 }