1 import java.awt.*; 2 import java.awt.event.*; 3 import java.awt.image.ImageObserver ; 4 import java.io.*; 5 import java.util.*; 6 import javax.swing.*; 7 import javax.swing.border.EmptyBorder ; 8 import javax.swing.event.*; 9 import javax.accessibility.Accessible ; 10 import org.jivesoftware.smack.*; 11 import org.jivesoftware.smackx.*; 12 import org.jivesoftware.smackx.packet.*; 13 import org.jivesoftware.smack.util.StringUtils; 15 16 17 18 public final class DISCOWindow extends JFrame implements Accessible , ImageObserver , MenuContainer, RootPaneContainer, Serializable, WindowConstants{ 19 20 final static private int GAP=10; 21 22 public static final String VCARD_TEMP="vcard-temp"; 24 public static final String REGISTER="jabber:iq:register"; 25 public static final String SEARCH="jabber:iq:search"; 26 public static final ImageIcon SERVICE_ICON=Icons.get("img/service.gif"); 28 public static final ImageIcon SERVICE_OFFLINE_ICON=Icons.get("img/service_offline.gif"); 29 public static final ImageIcon JUD_ICON=Icons.get("img/jud.gif"); 30 public static final ImageIcon MUC_SERVICE_ICON=Icons.get("img/room_service.gif"); 31 public static final ImageIcon MUC_ROOM_ICON=Icons.get("img/room.gif"); 32 public static final ImageIcon JABBER_ICON=Icons.get("img/jabber.gif"); 33 public static final ImageIcon AIM_ICON=Icons.get("img/aim.gif"); 34 public static final ImageIcon ICQ_ICON=Icons.get("img/icq.gif"); 35 public static final ImageIcon IRC_ICON=Icons.get("img/irq.gif"); 36 public static final ImageIcon MSN_ICON=Icons.get("img/msn.gif"); 37 public static final ImageIcon YAHOO_ICON=Icons.get("img/yahoo.gif"); 38 39 41 final static private Hashtable infoCache=new Hashtable(); 42 43 45 final static private Hashtable itemsCache=new Hashtable(); 46 47 final Vector results=new Vector(); 48 49 private static final int HISTORY_SIZE=9; 50 final private String [] history=new String [HISTORY_SIZE+1]; 51 private int currentHistory=-1; 52 53 final BorderLayout layout=new BorderLayout(GAP,GAP); 54 final JPanel panel=new JPanel(layout); 55 final EmptyBorder border=new EmptyBorder (GAP,GAP,GAP,GAP); 56 57 final Box topPanel=new Box(BoxLayout.X_AXIS); 58 final JLabel hostLbl=new JLabel(Lang.gs("host")); 59 final JTextField host=new JTextField(25); 60 final JButton browseBtn=new JButton("",Icons.DISCO); 61 final JButton refreshBtn=new JButton("",Icons.REFRESH); 62 final JButton backBtn=new JButton("",Icons.BACK); 63 final JButton homeBtn=new JButton("",Icons.HOME); 64 65 final JPanel middlePanel=new JPanel(new BorderLayout(GAP,GAP)); 66 final JPanel cmdBtnPanel=new JPanel(new FlowLayout(FlowLayout.LEFT,GAP,GAP)); 67 final JButton joinBtn=new JButton("",Icons.GROUP_CHAT); 68 final JButton searchBtn=new JButton("",Icons.SEARCH); 69 final JButton registerBtn=new JButton("",Icons.REGISTER); 70 final JButton addBtn=new JButton("",Icons.ADD_CONTACT); 71 final JButton profileBtn=new JButton("",Icons.PROFILE); 72 73 final JList list=new JList(results); 74 final JScrollPane listSP=new JScrollPane(list); 75 76 final JPanel btnPanel=new JPanel(new FlowLayout(FlowLayout.RIGHT,GAP,0)); 77 final JButton closeBtn=new JButton(Lang.gs("close"),Icons.CLOSE); 78 79 final BtnClick click=new BtnClick(); 80 final MouseClickListener mouseListener=new MouseClickListener(); 81 82 private BrowseThread browseThread; 83 84 final JFrame thisWindow=this; 85 86 public DISCOWindow(){ 87 super(Lang.gs("menu_tools_disco")); 88 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 89 setIconImage(Icons.DISCO.getImage()); 90 Container cp=getContentPane(); 91 panel.setBorder(border); 92 cp.add(panel); 93 94 topPanel.add(hostLbl); 95 topPanel.add(topPanel.createHorizontalStrut(GAP)); 96 host.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),"disco_browse"); 97 host.getActionMap().put("disco_browse", new EnterAction()); 98 topPanel.add(host); 99 host.setText(WhisperIM.accountSettings.JabberServer); 100 topPanel.add(topPanel.createGlue()); 101 102 browseBtn.setActionCommand("disco_browse"); 103 browseBtn.addActionListener(click); 104 browseBtn.setMargin(new Insets(0,0,0,0)); 105 browseBtn.setToolTipText(Lang.gs("browse_tt")); 106 topPanel.add(browseBtn); 107 108 refreshBtn.setActionCommand("disco_refresh"); 109 refreshBtn.addActionListener(click); 110 refreshBtn.setMargin(new Insets(0,0,0,0)); 111 refreshBtn.setToolTipText(Lang.gs("refresh")); 112 topPanel.add(topPanel.createHorizontalStrut(GAP)); 113 topPanel.add(refreshBtn); 114 115 backBtn.setActionCommand("disco_back"); 116 backBtn.addActionListener(click); 117 backBtn.setMargin(new Insets(0,0,0,0)); 118 backBtn.setEnabled(false); 119 backBtn.setToolTipText(Lang.gs("DISCO_back")); 120 topPanel.add(topPanel.createHorizontalStrut(GAP)); 121 topPanel.add(backBtn); 122 123 homeBtn.setActionCommand("disco_home"); 124 homeBtn.addActionListener(click); 125 homeBtn.setMargin(new Insets(0,0,0,0)); 126 homeBtn.setToolTipText(Lang.gs("DISCO_home")); 127 topPanel.add(topPanel.createHorizontalStrut(GAP)); 128 topPanel.add(homeBtn); 129 130 panel.add(topPanel,BorderLayout.NORTH); 131 132 joinBtn.setActionCommand("DISCO_join"); 133 joinBtn.addActionListener(click); 134 joinBtn.setMargin(new Insets(0,0,0,0)); 135 joinBtn.setToolTipText(Lang.gs("menu_chat_groupchat")); 136 cmdBtnPanel.add(joinBtn); 137 138 searchBtn.setActionCommand("DISCO_search"); 139 searchBtn.addActionListener(click); 140 searchBtn.setMargin(new Insets(0,0,0,0)); 141 searchBtn.setToolTipText(Lang.gs("DISCO_search")); 142 cmdBtnPanel.add(searchBtn); 143 144 registerBtn.setActionCommand("DISCO_register"); 145 registerBtn.addActionListener(click); 146 registerBtn.setMargin(new Insets(0,0,0,0)); 147 registerBtn.setToolTipText(Lang.gs("DISCO_register")); 148 cmdBtnPanel.add(registerBtn); 149 150 profileBtn.setActionCommand("DISCO_profile"); 151 profileBtn.addActionListener(click); 152 profileBtn.setMargin(new Insets(0,0,0,0)); 153 profileBtn.setToolTipText(Lang.gs("pu profile")); 154 cmdBtnPanel.add(profileBtn); 155 156 addBtn.setActionCommand("DISCO_add"); 157 addBtn.addActionListener(click); 158 addBtn.setMargin(new Insets(0,0,0,0)); 159 addBtn.setToolTipText(Lang.gs("DISCO_add to contacts")); 160 cmdBtnPanel.add(addBtn); 161 162 joinBtn.setEnabled(false); 163 searchBtn.setEnabled(false); 164 registerBtn.setEnabled(false); 165 profileBtn.setEnabled(false); 166 addBtn.setEnabled(false); 167 168 middlePanel.add(cmdBtnPanel,BorderLayout.NORTH); 169 list.addListSelectionListener(new SelectionListener()); 170 list.addMouseListener(mouseListener); 171 list.setLayoutOrientation(JList.VERTICAL); 172 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 173 list.setCellRenderer(new CellRenderer()); 174 GUI.setScrollBars(listSP); 175 middlePanel.add(listSP,BorderLayout.CENTER); 176 panel.add(middlePanel,BorderLayout.CENTER); 177 178 closeBtn.setMnemonic(Lang.s2k("close_mn")); 179 closeBtn.addActionListener(click); 180 btnPanel.add(closeBtn); 181 panel.add(btnPanel,BorderLayout.SOUTH); 182 183 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); getRootPane().getActionMap().put("help",new HelpAction(this,"tools.html#DISCO")); 185 186 pack(); 187 addKeyListener(new KeyAction()); 188 addMouseListener(new MouseAction()); 189 } 190 191 public void setLang(){ 192 setTitle(Lang.gs("menu_tools_disco")); 193 hostLbl.setText(Lang.gs("host")); 194 browseBtn.setToolTipText(Lang.gs("browse_tt")); 195 refreshBtn.setToolTipText(Lang.gs("refresh")); 196 backBtn.setToolTipText(Lang.gs("DISCO_back")); 197 homeBtn.setToolTipText(Lang.gs("DISCO_home")); 198 joinBtn.setToolTipText(Lang.gs("menu_chat_groupchat")); 199 searchBtn.setToolTipText(Lang.gs("DISCO_search")); 200 registerBtn.setToolTipText(Lang.gs("DISCO_register")); 201 profileBtn.setToolTipText(Lang.gs("pu profile")); 202 addBtn.setToolTipText(Lang.gs("DISCO_add to contacts")); 203 closeBtn.setMnemonic(Lang.s2k("close_mn")); 204 list.repaint(); 205 } 206 207 public void setHost(String value){ 208 host.setText(value); 209 } 210 211 public void show(){ 212 if(!isVisible()){ 213 setLocationRelativeTo(WhisperIM.MainWindow); 214 } 215 setCursor(GUI.NORMAL); 216 super.show(); 217 } 218 219 public void dispose(){ 220 if(browseThread!=null && browseThread.isAlive()){ 221 browseThread.interrupt(); 222 } 223 setCursor(GUI.NORMAL); 224 super.dispose(); 225 } 226 227 public void doBrowse(boolean useCache){ 228 if(host.getText().equals("")){ 229 host.requestFocus(); 230 return; 231 } 232 host.setEnabled(false); 233 if(browseThread!=null && browseThread.isAlive()){ 234 browseThread.interrupt(); 235 } 236 setCursor(GUI.WAIT); 237 browseThread=new BrowseThread(useCache); 238 browseThread.start(); 239 } 240 241 242 private void doGoBack(){ 243 if(currentHistory<1){ 244 return; } 246 host.setText(history[currentHistory-1]); 247 currentHistory--; 248 if(currentHistory<1){ 249 backBtn.setEnabled(false); 250 } 251 doBrowse(true); 252 } 253 254 private void addHistory(String jid){ 255 if(currentHistory!=-1 && jid.equals(history[currentHistory])){ 256 return; } 258 if(currentHistory==(HISTORY_SIZE)){ 259 for(int i=0;i<(HISTORY_SIZE-1);i++){ 261 history[i]=history[i+1]; 262 } 263 } 264 else{ 265 currentHistory++; 266 } 267 history[currentHistory]=jid; 268 if(currentHistory>0){ 269 backBtn.setEnabled(true); 270 } 271 } 272 273 279 private static DISCOInfo getInfo(String jid, boolean useCache) throws XMPPException, Exception { 280 DISCOInfo result; 281 if(useCache){ 282 result=(DISCOInfo)infoCache.get(jid); if(result!=null){ 284 return result; 285 } 286 } 287 DiscoverInfo discoInfo=WhisperIM.MainWindow.SDM.discoverInfo(jid); 288 Iterator i=discoInfo.getIdentities(); 290 DiscoverInfo.Identity identity=null; 291 if(i.hasNext()){ 293 identity=(DiscoverInfo.Identity) i.next(); 294 } 295 if(identity==null){ 296 result=new DISCOInfo(jid,jid); 297 } 298 else{ 299 result=new DISCOInfo(jid,identity.getName()); 300 result.addInfo(identity.getCategory()+"/"+identity.getType()); 301 result.setType(DISCOInfo.determineType(identity,jid)); 302 } 303 result.setSupportsVcard(discoInfo.containsFeature(VCARD_TEMP)); 305 result.setSupportsRegister(discoInfo.containsFeature(REGISTER)); 306 result.setSupportsSearch(discoInfo.containsFeature(SEARCH)); 307 while (i.hasNext()){ 309 identity=(DiscoverInfo.Identity) i.next(); 310 result.addInfo(identity.getCategory()+"/"+identity.getType()); 311 } 312 infoCache.put(jid,result); 313 return result; 314 } 315 316 317 318 private static DiscoverItems getItems(String jid, boolean useCache) throws XMPPException, Exception { 319 DiscoverItems result; 320 if(useCache){ 321 result=(DiscoverItems)itemsCache.get(jid); if(result!=null){ 323 return result; 324 } 325 } 326 result=WhisperIM.MainWindow.SDM.discoverItems(jid); 327 if(result!=null){ 328 itemsCache.put(jid,result); 329 } 330 return result; 331 } 332 333 final class BtnClick implements ActionListener{ 334 public void actionPerformed(ActionEvent ae){ 335 String b=ae.getActionCommand(); 337 if(b.equals(closeBtn.getText())){ 339 dispose(); 340 return; 341 } 342 if(b.equals("disco_browse")){ 343 doBrowse(true); 344 addHistory(host.getText()); 345 return; 346 } 347 if(b.equals("disco_refresh")){ 348 doBrowse(false); 349 return; 350 } 351 if(b.equals("disco_home")){ 352 host.setText(WhisperIM.accountSettings.JabberServer); 353 doBrowse(true); 354 addHistory(host.getText()); 355 return; 356 } 357 if(b.equals("disco_back")){ 358 doGoBack(); 359 return; 360 } 361 DISCOInfo di=(DISCOInfo)list.getSelectedValue(); 363 if(di==null){ 364 return; 365 } 366 if(b.equals("DISCO_profile")){ 367 ProfileWindow pw=new ProfileWindow(di.getJID(),thisWindow); return; 369 } 370 if(b.equals("DISCO_add")){ 371 AddContactDialog acd=new AddContactDialog(thisWindow); 372 acd.setID(di.getJID()); 373 acd.setName(di.getName()); 374 acd.show(); 375 thisWindow.dispose(); 376 return; 377 } 378 if(b.equals("DISCO_join")){ 379 JoinMUCDialog jmd=new JoinMUCDialog(); 380 if(di.getType()==DISCOInfo.MUC_SERVICE){ 381 jmd.setHost(di.getJID()); 382 jmd.show(thisWindow); 383 thisWindow.dispose(); 384 return; 385 } 386 else{ jmd.setRoom(StringUtils.parseName(di.getJID())); 388 jmd.setHost(StringUtils.parseServer(di.getJID())); 389 jmd.show(thisWindow); 390 jmd.doJoin(); 391 thisWindow.dispose(); 392 return; 393 } 394 } 395 if(b.equals("DISCO_search")){ 396 Form searchForm=new Form(Form.SEARCH_FORM,di.getJID()); 397 searchForm.show(thisWindow); 398 thisWindow.dispose(); 399 return; 400 } 401 if(b.equals("DISCO_register")){ 402 Form searchForm=new Form(Form.REGISTRATION_FORM,di.getJID()); 403 searchForm.show(thisWindow); 404 thisWindow.dispose(); 405 return; 406 } 407 } 408 } 409 410 final class CellRenderer extends JLabel implements ListCellRenderer { 411 412 public Component getListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasFocus){ 413 DISCOInfo di=(DISCOInfo) value; 414 if(index==0){ 415 this.setText("<html><b>"+di.getName()+"</b></html>"); 416 this.setHorizontalAlignment(SwingConstants.CENTER); 417 418 } 419 else{ 420 this.setText("<html>"+di.getName()+"</html>"); 421 this.setHorizontalAlignment(SwingConstants.LEFT); 422 } 423 String ttt="<html><b>"+di.getJID()+"</b><br>"; 424 switch (di.getType()) { 425 case DISCOInfo.OTHER : this.setIcon(SERVICE_ICON); ttt=ttt+Lang.gs("disco_other"); break; 426 case DISCOInfo.JUD : this.setIcon(JUD_ICON); ttt=ttt+Lang.gs("disco_jud"); break; 427 case DISCOInfo.JABBER_SERVER : this.setIcon(JABBER_ICON); ttt=ttt+Lang.gs("disco_jabber_server"); break; 428 case DISCOInfo.MUC_SERVICE : this.setIcon(MUC_SERVICE_ICON); ttt=ttt+Lang.gs("disco_muc_service"); break; 429 case DISCOInfo.MUC_ROOM : this.setIcon(MUC_ROOM_ICON); ttt=ttt+Lang.gs("disco_muc_room"); break; 430 case DISCOInfo.AIM_GATEWAY : this.setIcon(AIM_ICON); ttt=ttt+Lang.gs("disco_aim_gateway"); break; 431 case DISCOInfo.ICQ_GATEWAY : this.setIcon(ICQ_ICON); ttt=ttt+Lang.gs("disco_icq_gateway"); break; 432 case DISCOInfo.IRC_GATEWAY : this.setIcon(IRC_ICON); ttt=ttt+Lang.gs("disco_irc_gateway"); break; 433 case DISCOInfo.MSN_GATEWAY : this.setIcon(MSN_ICON); ttt=ttt+Lang.gs("disco_msn_gateway"); break; 434 case DISCOInfo.YAHOO_GATEWAY : this.setIcon(YAHOO_ICON); ttt=ttt+Lang.gs("disco_yahoo_gateway"); break; 435 case DISCOInfo.OTHER_GATEWAY : this.setIcon(SERVICE_ICON); ttt=ttt+Lang.gs("disco_gateway"); break; 436 default: this.setIcon(SERVICE_ICON); ttt=ttt+Lang.gs("disco_other"); break; 437 } 438 this.setToolTipText(ttt+"<br><i>"+di.getInfo()+"</i></html>"); 439 if(isSelected){ 440 setBackground(list.getSelectionBackground()); 441 setForeground(list.getSelectionForeground()); 442 } 443 else { 444 setBackground(list.getBackground()); 445 setForeground(list.getForeground()); 446 } 447 setEnabled(list.isEnabled()); 448 setFont(list.getFont()); 449 setOpaque(true); 450 return this; 451 } 452 } 453 454 final class EnterAction extends AbstractAction{ 455 public void actionPerformed(ActionEvent e) { 456 doBrowse(true); 457 addHistory(host.getText()); 458 } 459 } 460 461 final class BrowseThread extends Thread { 462 463 private boolean useCache; 464 465 public BrowseThread(boolean usecache){ 466 super("MUC Send Encrypted Message"); 467 this.useCache=usecache; 468 setDaemon(true); 469 setPriority(Thread.MIN_PRIORITY); 470 } 471 472 public void run(){ 473 try{ 474 DISCOInfo first=getInfo(host.getText(),useCache); 475 476 if(isInterrupted()){ 477 return; 478 } 479 results.clear(); 480 results.add(first); 481 482 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 483 public void run(){ 484 list.repaint(); 485 } 486 }); 487 488 DiscoverItems di=getItems(host.getText(),useCache); 489 if(isInterrupted()){ 490 return; 491 } 492 Iterator i=di.getItems(); 493 DiscoverItems.Item item; 494 int c=0; 495 while(i.hasNext()){ 496 c++; 497 item=(DiscoverItems.Item) i.next(); 498 if(isInterrupted()){ 499 return; 500 } 501 try{ 502 results.add(getInfo(item.getEntityID(),useCache)); 503 } 504 catch(XMPPException xe){ 505 int e=0; 506 if(xe.getXMPPError()!=null){ 507 e=xe.getXMPPError().getCode(); 508 } 509 if(e==501){ DISCOInfo ddi=new DISCOInfo(item.getEntityID(),item.getName()); 511 ddi.setSupportsBrowse(false); 512 if(item.getEntityID().startsWith("jud.") && WhisperIM.UserPref.getProperty("assume_jud").equals("true")){ 513 ddi.setType(DISCOInfo.JUD); 515 ddi.setSupportsRegister(true); 516 ddi.setSupportsSearch(true); 517 } 518 results.add(ddi); 519 if(useCache){ 520 infoCache.put(item.getEntityID(),ddi); 521 } 522 } 523 else{ 524 if(xe.getMessage()!=null && xe.getMessage().equals("No response from the server.")){ 525 results.add(new DISCOInfo(item.getEntityID(),item.getName())); 530 } 532 else{ 533 throw xe; 534 } 535 } 536 } 537 if( (c % 3)==0){ 538 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 539 public void run(){ 540 list.repaint(); 541 } 542 }); 543 } 544 } if(isInterrupted()){ 546 return; 547 } 548 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 549 public void run(){ 550 setCursor(GUI.NORMAL); 551 host.setEnabled(true); 552 list.setListData(results); 553 if(results.size()>0){ 554 list.setSelectedIndex(0); 555 } 556 } 557 }); 558 } catch (final XMPPException xe2){ 560 if(!isInterrupted()){ 561 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 562 public void run(){ 563 setCursor(GUI.NORMAL); 564 host.setEnabled(true); 565 GUI.showError(thisWindow,"menu_tools_disco", null ,host.getText(),xe2); 566 } 567 }); 568 } 569 } 570 catch(final Exception e){ 571 e.printStackTrace(); 572 if(!isInterrupted()){ 573 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 574 public void run(){ 575 list.repaint(); 576 setCursor(GUI.NORMAL); 577 host.setEnabled(true); 578 GUI.showError(thisWindow,"menu_tools_disco", null ,host.getText()+"\r\n"+e.getMessage()); 579 } 580 }); 581 } 582 } 583 } 584 585 } 586 587 588 final class MouseClickListener extends MouseAdapter{ 589 590 public void mousePressed(MouseEvent e){ 591 if(e.getClickCount()==2){ 592 int index=list.getUI().locationToIndex(list,e.getPoint()); 593 if(index==-1){ return; 595 } 596 DISCOInfo di=(DISCOInfo) results.elementAt(index); 597 if(di==null){ System.err.println("Debug: null DISCOInfo from results in MouseClickListener"); 599 return; 600 } 601 if(!di.supportsBrowse()){ 602 return; 603 } 604 host.setText(di.getJID()); 605 if(index==0){ 606 doBrowse(false); } 608 else{ 609 doBrowse(true); 610 addHistory(host.getText()); 611 } 612 } 613 } 614 } 615 616 617 final class SelectionListener implements ListSelectionListener{ 618 public void valueChanged(ListSelectionEvent e){ 619 DISCOInfo di=(DISCOInfo)list.getSelectedValue(); 620 if(di==null){ 621 joinBtn.setEnabled(false); 622 searchBtn.setEnabled(false); 623 registerBtn.setEnabled(false); 624 profileBtn.setEnabled(false); 625 addBtn.setEnabled(false); 626 return; 627 } 628 addBtn.setEnabled(true); 629 registerBtn.setEnabled(di.supportsRegister() && di.getType()!=DISCOInfo.JABBER_SERVER); searchBtn.setEnabled(di.supportsSearch()); 631 joinBtn.setEnabled(di.getType()==DISCOInfo.MUC_ROOM || di.getType()==DISCOInfo.MUC_SERVICE); 632 profileBtn.setEnabled(di.supportsVcard()); 633 } 634 } 635 } | Popular Tags |