001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2015 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029package edu.wisc.ssec.mcidasv.chooser.adde; 030 031import static edu.wisc.ssec.mcidasv.servermanager.AddeEntry.DEFAULT_ACCOUNT; 032import static edu.wisc.ssec.mcidasv.util.CollectionHelpers.arrList; 033import static edu.wisc.ssec.mcidasv.McIDASV.isLoopback; 034 035import static javax.swing.GroupLayout.DEFAULT_SIZE; 036import static javax.swing.GroupLayout.Alignment.BASELINE; 037import static javax.swing.GroupLayout.Alignment.LEADING; 038import static javax.swing.GroupLayout.Alignment.TRAILING; 039import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 040import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED; 041 042import java.awt.Component; 043import java.awt.event.ActionEvent; 044import java.awt.event.ActionListener; 045import java.awt.event.ItemEvent; 046import java.awt.event.ItemListener; 047import java.awt.event.KeyEvent; 048import java.awt.event.KeyListener; 049import java.awt.event.MouseAdapter; 050import java.awt.event.MouseEvent; 051import java.io.EOFException; 052import java.io.InputStream; 053import java.net.ConnectException; 054import java.net.URL; 055import java.net.URLConnection; 056import java.util.ArrayList; 057import java.util.Arrays; 058import java.util.Collections; 059import java.util.Comparator; 060import java.util.Enumeration; 061import java.util.HashMap; 062import java.util.Hashtable; 063import java.util.LinkedHashMap; 064import java.util.List; 065import java.util.Map; 066import java.util.Objects; 067import java.util.Vector; 068 069import javax.swing.GroupLayout; 070import javax.swing.JButton; 071import javax.swing.JCheckBox; 072import javax.swing.JComboBox; 073import javax.swing.JComponent; 074import javax.swing.JLabel; 075import javax.swing.JMenu; 076import javax.swing.JMenuItem; 077import javax.swing.JPanel; 078import javax.swing.JPopupMenu; 079import javax.swing.JTabbedPane; 080import javax.swing.JTextField; 081import javax.swing.SwingUtilities; 082 083import org.bushe.swing.event.annotation.AnnotationProcessor; 084import org.bushe.swing.event.annotation.EventSubscriber; 085import org.slf4j.Logger; 086import org.slf4j.LoggerFactory; 087import org.w3c.dom.Element; 088 089import edu.wisc.ssec.mcidas.adde.AddeURLException; 090import edu.wisc.ssec.mcidas.adde.DataSetInfo; 091 092import visad.DateTime; 093 094import ucar.unidata.idv.chooser.IdvChooser; 095import ucar.unidata.idv.chooser.IdvChooserManager; 096import ucar.unidata.idv.chooser.adde.AddeServer; 097import ucar.unidata.idv.chooser.adde.AddeServer.Group; 098import ucar.unidata.util.DatedThing; 099import ucar.unidata.util.GuiUtils; 100import ucar.unidata.util.LogUtil; 101import ucar.unidata.util.Misc; 102import ucar.unidata.util.PreferenceList; 103import ucar.unidata.util.StringUtil; 104import ucar.unidata.xml.XmlObjectStore; 105 106import edu.wisc.ssec.mcidasv.Constants; 107import edu.wisc.ssec.mcidasv.McIDASV; 108import edu.wisc.ssec.mcidasv.ParameterSet; 109import edu.wisc.ssec.mcidasv.PersistenceManager; 110import edu.wisc.ssec.mcidasv.servermanager.AddeAccount; 111import edu.wisc.ssec.mcidasv.servermanager.AddeEntry; 112import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EditorAction; 113import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntryType; 114import edu.wisc.ssec.mcidasv.servermanager.EntryStore; 115import edu.wisc.ssec.mcidasv.servermanager.EntryTransforms; 116import edu.wisc.ssec.mcidasv.servermanager.LocalEntryEditor; 117import edu.wisc.ssec.mcidasv.servermanager.RemoteAddeEntry; 118import edu.wisc.ssec.mcidasv.servermanager.RemoteEntryEditor; 119import edu.wisc.ssec.mcidasv.servermanager.TabbedAddeManager; 120import edu.wisc.ssec.mcidasv.ui.ParameterTree; 121import edu.wisc.ssec.mcidasv.ui.UIManager; 122import edu.wisc.ssec.mcidasv.util.CollectionHelpers; 123import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 124import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position; 125import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor; 126import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 127 128/** 129 * 130 * @version $Revision$ 131 */ 132public class AddeChooser extends ucar.unidata.idv.chooser.adde.AddeChooser implements Constants { 133 134 private static final Logger logger = LoggerFactory.getLogger(AddeChooser.class); 135 136 private JComboBox serverSelector; 137 138 /** List of descriptors */ 139 private PreferenceList descList; 140 141 /** Descriptor/name hashtable */ 142 protected Hashtable descriptorTable; 143 144 /** List of available descriptors. */ 145 protected List<String> descriptorList; 146 147 /** List of comments associated with list of descriptors. */ 148 protected List<String> commentList; 149 150 /** Property for the descriptor table */ 151 public static final String DESCRIPTOR_TABLE = "DESCRIPTOR_TABLE"; 152 153 /** Connect button--we need to be able to disable this */ 154 JButton connectButton = McVGuiUtils.makeImageTextButton(ICON_CONNECT_SMALL, "Connect"); 155 156 /** Parameter button--we need to be able to disable this */ 157 JButton parameterButton = 158 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/document-open22.png", 159 this, "doParameters", null, "Load parameter set"); 160 161 /** Manage button */ 162 JButton manageButton = 163 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/preferences-system22.png", 164 this, "doManager", null, "Manage servers"); 165 166 /** Public button--we need to draw a menu from this */ 167 JButton publicButton = 168 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/show-layer-controls22.png", 169 this, "showGroups", null, "List public datasets"); 170 171 /** descriptor label */ 172 protected JLabel descriptorLabel = new JLabel(getDescriptorLabel()+":"); 173 174 /** A widget for the list of dataset descriptors */ 175 protected JComboBox descriptorComboBox = new JComboBox(); 176 177 /** The descriptor names */ 178 protected String[] descriptorNames; 179 180 /** Flag to keep from infinite looping */ 181 protected boolean ignoreDescriptorChange = false; 182 183 /** 184 * List of JComponent-s that depend on a descriptor being selected 185 * to be enabled 186 */ 187 protected ArrayList compsThatNeedDescriptor = new ArrayList(); 188 189 /** Selection label text */ 190 protected String LABEL_SELECT = " -- Select -- "; 191 192 /** Separator string */ 193 protected static String separator = "----------------"; 194 195 /** Name separator string */ 196 protected static String nameSeparator = " - "; 197 198 /** Reference back to the server manager */ 199 protected EntryStore serverManager; 200 201 public boolean allServersFlag; 202 203 /** Command for opening up the server manager */ 204 protected static final String CMD_MANAGER = "cmd.manager"; 205 206 private String lastBadServer = ""; 207 private String lastBadGroup = ""; 208 209 private String lastServerName = ""; 210 private String lastServerGroup = ""; 211 private String lastServerUser = ""; 212 private String lastServerProj = ""; 213 private AddeServer lastServer = new AddeServer(""); 214 215 private List<AddeServer> addeServers; 216 217 /** Used for parameter set restore */ 218 private static final String TAG_FOLDER = "folder"; 219 private static final String TAG_DEFAULT = "default"; 220 private static final String ATTR_NAME = "name"; 221 private static final String ATTR_SERVER = "server"; 222 private static final String ATTR_GROUP = "GROUP"; 223 private static final String ATTR_DESCRIPTOR = "DESCRIPTOR"; 224 private static final String ATTR_POS = "POS"; 225 private static final String ATTR_DAY = "DAY"; 226 private static final String ATTR_TIME = "TIME"; 227 private List restoreTimes = new ArrayList(); 228 public Element restoreElement; 229 private boolean shouldAddSource = false; 230 final JCheckBox cb = new JCheckBox("Add source",shouldAddSource); 231 232 /** Maps favorite type to the BundleTree that shows the Manage window for the type */ 233 private Hashtable parameterTrees = new Hashtable(); 234 235 /** 236 * Create an AddeChooser associated with an IdvChooser 237 * 238 * @param mgr The chooser manager 239 * @param root The chooser.xml node 240 */ 241 public AddeChooser(IdvChooserManager mgr, Element root) { 242 super(mgr, root); 243 AnnotationProcessor.process(this); 244 descriptorList = new ArrayList<String>(); 245 commentList = new ArrayList<String>(); 246 247 simpleMode = !getProperty(IdvChooser.ATTR_SHOWDETAILS, true); 248 249 loadButton = McVGuiUtils.makeImageTextButton(ICON_ACCEPT_SMALL, getLoadCommandName()); 250 loadButton.setActionCommand(getLoadCommandName()); 251 loadButton.addActionListener(this); 252 253 cancelButton = McVGuiUtils.makeImageButton(ICON_CANCEL, "Cancel"); 254 cancelButton.setActionCommand(GuiUtils.CMD_CANCEL); 255 cancelButton.addActionListener(this); 256 cancelButton.setEnabled(false); 257 258 serverSelector = getServerSelector(); 259 260 serverSelector.setToolTipText("Right click to manage servers"); 261 serverSelector.getEditor().getEditorComponent().addMouseListener( 262 new MouseAdapter() { 263 public void mouseReleased(MouseEvent e) { 264 if (!SwingUtilities.isRightMouseButton(e)) { 265 return; 266 } 267 268 AddeServer server = getAddeServer(); 269 if (server == null) { 270 return; 271 } 272 List<JMenuItem> items = new ArrayList<JMenuItem>(); 273 274 // Set the right-click behavior 275 if (isLocalServer()) { 276 items.add(GuiUtils.makeMenuItem("Manage local ADDE data", 277 AddeChooser.this, 278 "doManager", null)); 279 } 280 else { 281 items.add(GuiUtils.makeMenuItem("Manage ADDE servers", 282 AddeChooser.this, 283 "doManager", null)); 284 } 285 JPopupMenu popup = GuiUtils.makePopupMenu(items); 286 popup.show(serverSelector, e.getX(), e.getY()); 287 } 288 }); 289 serverSelector.setMaximumRowCount(16); 290 291 groupSelector.setToolTipText("Right click to manage servers"); 292 groupSelector.getEditor().getEditorComponent().addMouseListener( 293 new MouseAdapter() { 294 public void mouseReleased(MouseEvent e) { 295 if (!SwingUtilities.isRightMouseButton(e)) { 296 return; 297 } 298 299 AddeServer server = getAddeServer(); 300 if (server == null) { 301 return; 302 } 303 List<JMenuItem> items = new ArrayList<JMenuItem>(); 304 305 // Set the right-click behavior 306 if (isLocalServer()) { 307 items.add(GuiUtils.makeMenuItem("Manage local ADDE data", 308 AddeChooser.this, "doManager", null)); 309 } 310 else { 311 items.add(GuiUtils.makeMenuItem("Manage ADDE servers", 312 AddeChooser.this, "doManager", null)); 313 } 314 JPopupMenu popup = GuiUtils.makePopupMenu(items); 315 popup.show(groupSelector, e.getX(), e.getY()); 316 } 317 }); 318 groupSelector.setMaximumRowCount(16); 319 320 // serverManager = ((McIDASV)getIdv()).getServerManager(); 321 // serverManager.addManagedChooser(this); 322 addServerComp(descriptorLabel); 323 // addServerComp(descriptorComboBox); 324 325 descriptorComboBox.addItemListener(new ItemListener() { 326 public void itemStateChanged(ItemEvent e) { 327 if ( !ignoreDescriptorChange 328 && (e.getStateChange() == e.SELECTED)) { 329 descriptorChanged(); 330 } 331 } 332 }); 333 334 // Update the server list and load the saved state 335 updateServerList(); 336 loadServerState(); 337 338 // Default to no parameter button unless the overriding class wants one 339 hideParameterButton(); 340 } 341 342 /** 343 * Force a reload of the available servers and groups. 344 */ 345 public void updateServerList() { 346 updateServers(); 347 updateGroups(); 348 } 349 350 /** 351 * Returns a {@link java.util.Map Map} containing {@code user} and {@code proj} 352 * keys for the given {@code server/group} combination. 353 * 354 * <p>The values are either the specific ADDE account details for 355 * {@code server/group} or {@link edu.wisc.ssec.mcidasv.servermanager.AddeEntry#DEFAULT_ACCOUNT DEFAULT_ACCOUNT} 356 * values. 357 * 358 * @param server Server name. Should not be {@code null}. 359 * @param group Group name on {@code name}. Should not be {@code null}. 360 * 361 * @return {@code Map} containing the accounting details for {@code server/group}. 362 */ 363 protected Map<String, String> getAccounting(final String server, final String group) { 364 Map<String, String> acctInfo = new HashMap<String, String>(); 365 EntryStore entryStore = ((McIDASV)getIdv()).getServerManager(); 366 String strType = this.getDataType(); 367 EntryType type = EntryTransforms.strToEntryType(strType); 368 AddeAccount acct = entryStore.getAccountingFor(server, group, type); 369 acctInfo.put("user", acct.getUsername()); 370 acctInfo.put("proj", acct.getProject()); 371 return acctInfo; 372 } 373 374 /** 375 * Returns a {@link java.util.Map Map} containing {@code user} and {@code proj} 376 * keys for the given {@code server/group} combination. 377 * 378 * <p>The values are either the specific ADDE account details for 379 * {@code server/group} or {@link edu.wisc.ssec.mcidasv.servermanager.AddeEntry#DEFAULT_ACCOUNT DEFAULT_ACCOUNT} 380 * values. 381 * 382 * @param server Server name. Should not be {@code null}. 383 * @param group Group name on {@code name}. Should not be {@code null}. 384 * 385 * @return {@code Map} containing the accounting details for {@code server/group}. 386 */ 387 protected Map<String, String> getAccounting(final AddeServer server, final String group) { 388 return getAccounting(server.getName(), group); 389 } 390 391 private List<AddeServer> getManagedServers(final String type) { 392 EntryStore entryStore = ((McIDASV)getIdv()).getServerManager(); 393 return arrList(entryStore.getIdvStyleEntries(type)); 394 } 395 396 public void updateServers() { 397 Object selected = serverSelector.getSelectedItem(); 398 399 String type = getGroupType(); 400 List<AddeServer> managedServers = getManagedServers(type); 401 List<AddeServer> localList = arrList(); 402 List<AddeServer> remoteList = arrList(); 403 addeServers = CollectionHelpers.arrList(); 404 for (AddeServer server : managedServers) { 405 if (server.getIsLocal()) 406 localList.add(server); 407 else 408 remoteList.add(server); 409 } 410 411// logger.debug("{}: updateServers: local size={} contents={}", new Object[] { getDataType(), localList.size(), localList }); 412// logger.debug("{}: updateServers: remote size={} contents={}", new Object[] { getDataType(), remoteList.size(), remoteList }); 413 414 // server list doesn't need a separator if there's only remote servers 415 if (!localList.isEmpty()) { 416 addeServers.addAll(localList); 417 addeServers.add(new AddeServer(separator)); 418 } 419 Comparator<AddeServer> byServer = new ServerComparator(); 420 Collections.sort(remoteList, byServer); 421 addeServers.addAll(remoteList); 422 423 // always making this call helps to ensure the chooser stays up to date 424 // with the server manager. 425 GuiUtils.setListData(serverSelector, addeServers); 426 if (!addeServers.isEmpty()) { 427 if (selected == null || !containsServerName(addeServers, selected)) { 428 selected = serverSelector.getItemAt(0); 429// logger.debug("updateServers: selecting item at idx=0, item={} chooser={}", selected, this.getDataType()); 430 } 431 432 int index = getSelectorIndex(selected, serverSelector); 433 serverSelector.setSelectedIndex(index); 434 } 435 } 436 437 /** 438 * Searches the given {@link java.util.List List} of {@link ucar.unidata.idv.chooser.adde.AddeServer AddeServers} 439 * for {@code server}. 440 * 441 * @param servers Servers to search. {@code null} is permitted. 442 * @param server Server to search for within {@code servers}. {@code null} is permitted. 443 * 444 * @return {@code true} if {@code servers} contains {@code server} or {@code false} otherwise. 445 */ 446 protected static boolean containsServerName(final List<AddeServer> servers, final Object server) { 447 if (servers == null || server == null) { 448 return false; 449 } 450 String serverName = (server instanceof AddeServer) ? ((AddeServer)server).getName() : server.toString(); 451 for (AddeServer tmp : servers) { 452 if (tmp.getName().equals(serverName)) { 453 return true; 454 } 455 } 456 return false; 457 } 458 459 /** 460 * Searches the given {@link java.util.List List} of {@link ucar.unidata.idv.chooser.adde.AddeServer.Group Groups} 461 * for {@code group}. 462 * 463 * @param groups Groups to search. {@code null} is permitted. 464 * @param group Group to search for within {@code group}. {@code null} is permitted. 465 * 466 * @return {@code true} if {@code groups} contains {@code group} or {@code false} otherwise. 467 */ 468 protected static boolean containsGroupName(final List<Group> groups, final Object group) { 469 if (groups == null || group == null) { 470 return false; 471 } 472 String groupName = (group instanceof Group) ? ((Group)group).getName() : group.toString(); 473 for (Group tmp : groups) { 474 if (tmp.getName().equals(groupName)) { 475 return true; 476 } 477 } 478 return false; 479 } 480 481 /** 482 * Sort the groups alphabetically 483 */ 484 public void updateGroups() { 485 if (addingServer || groupSelector == null || getAddeServer() == null) 486 return; 487 488 Object selected = groupSelector.getSelectedItem(); 489 490 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 491 492 List<Group> groups = CollectionHelpers.arrList(); 493 if (isLocalServer()) { 494 groups.addAll(servManager.getIdvStyleLocalGroups()); 495 } else { 496 String sel = null; 497 Object obj = serverSelector.getSelectedItem(); 498 if (obj instanceof String) { 499 sel = (String)obj; 500// logger.debug("updateGroups: string={} chooser={}", sel, this.getDataType()); 501 } else if (obj instanceof AddeServer) { 502 sel = ((AddeServer)obj).getName(); 503// logger.debug("updateGroups: server selection={} chooser={}", sel, this.getDataType()); 504 } else { 505 sel = obj.toString(); 506// logger.debug("updateGroups: unknown type={}; toString={}", sel.getClass().getName(), sel); 507 } 508 509 EntryType selType = EntryTransforms.strToEntryType(getGroupType()); 510 groups.addAll(servManager.getIdvStyleRemoteGroups(sel, selType)); 511 } 512// logger.trace("updateGroups: selected={} (type={}) chooser={} contents={}", new Object[] { serverSelector.getSelectedItem(), serverSelector.getSelectedItem().getClass().getName(), this.getDataType(), groups}); 513 Comparator<Group> byGroup = new GroupComparator(); 514 Collections.sort(groups, byGroup); 515 GuiUtils.setListData(groupSelector, groups); 516 if (!groups.isEmpty()) { 517 if (selected == null || !containsGroupName(groups, selected)) { 518 selected = groupSelector.getItemAt(0); 519 } 520 groupSelector.setSelectedItem(selected); 521 } 522 } 523 524 /** 525 * Load any saved server state 526 */ 527 //TODO: Make loadServerState protected in IDV, remove from here 528 private void loadServerState() { 529 if (addeServers == null) { 530// logger.debug("loadServerState: addeServers == null chooser={}", this.getDataType()); 531 return; 532 } 533 String id = getId(); 534 String[] serverState = 535 (String[]) getIdv().getStore().get(Constants.PREF_SERVERSTATE + '.' + id); 536 if (serverState == null) { 537// serverState = Constants.DEFAULT_SERVERSTATE; 538// logger.debug("loadServerState: serverState == null chooser={}",this.getDataType()); 539 return; 540 } 541 AddeServer server = AddeServer.findServer(addeServers, serverState[0]); 542 if (server == null) { 543// logger.debug("loadServerState: server == null chooser={}",this.getDataType()); 544 return; 545 } 546// logger.debug("loadServerState: selecting server={} chooser={}", server, this.getDataType()); 547 serverSelector.setSelectedItem(server); 548 setGroups(); 549 updateGroups(); 550 if (serverState[1] != null) { 551 Group group = new Group(getDataType(), serverState[1], serverState[1]); 552 int index = getSelectorIndex(group, groupSelector); 553 if (index >= 0) { 554// logger.debug("loadServerState: selecting index={} group={} chooser={}", new Object[] { index, group, this.getDataType() }); 555 groupSelector.setSelectedIndex(index); 556 } else { 557// logger.debug("loadServerState: group == null chooser={}", this.getDataType()); 558 } 559 } else { 560// logger.debug("loadServerState: serverState[1] == null chooser={}", this.getDataType()); 561 } 562 } 563 564 /** 565 * Decide if the server you're asking about is actually a separator 566 */ 567 protected static boolean isSeparator(AddeServer checkServer) { 568 if (checkServer != null) { 569 if (checkServer.getName().equals(separator)) { 570 return true; 571 } 572 } 573 return false; 574 } 575 576 /** 577 * Decide if the server you're asking about is local 578 */ 579 protected boolean isLocalServer() { 580 return isLocalServer(getAddeServer()); 581 } 582 583 protected static boolean isLocalServer(AddeServer checkServer) { 584 if (checkServer != null) { 585 return checkServer.getIsLocal(); 586 } 587 return false; 588 } 589 590 private void setBadServer(String name, String group) { 591 if (name == null) { 592 name = ""; 593 } 594 if (group == null) { 595 group = ""; 596 } 597 598 lastBadServer = name; 599 lastBadGroup = group; 600 } 601 602 private boolean isBadServer(String name, String group) { 603 assert lastBadServer != null; 604 assert lastBadGroup != null; 605 return lastBadServer.equals(name) && lastBadGroup.equals(group); 606 } 607 608 private void setLastServer(String name, String group, AddeServer server) { 609// logger.trace("name='{}' group='{}' server='{}' old: name='{}' group='{}' server='{}'", new Object[] { name, group, server, lastServerName, lastServerGroup, lastServer }); 610 if (name == null) { 611 name = ""; 612 } 613 if (group == null) { 614 group = ""; 615 } 616 if (server == null) { 617 server = new AddeServer(name); 618 Group addeGroup = new Group(getDataType(), group, group); 619 server.addGroup(addeGroup); 620 } 621 lastServerName = name; 622 lastServerGroup = group; 623 lastServer = server; 624 } 625 626 private boolean isLastServer(String name, String group) { 627 assert lastServer != null; 628 assert lastServerName != null; 629 assert lastServerGroup != null; 630 return lastServerName.equals(name) && lastServerGroup.equals(group); 631 } 632 633 @EventSubscriber(eventClass=EntryStore.Event.class) 634 public void onServerManagerDataEvent(EntryStore.Event evt) { 635 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 636// logger.debug("onServerManagerDataEvent: evt={} server={}", evt, servManager.getLastAdded()); 637 this.updateServerList(); 638 } 639 640 @EventSubscriber(eventClass=TabbedAddeManager.Event.class) 641 public void onServerManagerWindowEvent(TabbedAddeManager.Event evt) { 642// logger.debug("onServerManagerWindowEvent: caught event bus obj"); 643 } 644 645 private boolean addingServer = false; 646 647 /** 648 * Search a given {@link JComboBox} for the index of a given object. Mostly 649 * useful for searching {@link #serverSelector} or {@link #groupSelector}. 650 * 651 * @param needle An object. {@code null} values are permitted. 652 * @param haystack {@code JComboBox} to search. {@code null} values are 653 * permitted, but return {@code -1}. 654 * 655 * @return Either the index of {@code needle} within {@code haystack}, or 656 * {@code -1} if {@code needle} could not be found (or {@code haystack} is 657 * {@code null}). 658 */ 659 protected static int getSelectorIndex(final Object needle, 660 final JComboBox haystack) 661 { 662 if (haystack == null) { 663 return -1; 664 } 665 666 String name = null; 667 if (needle instanceof AddeServer) { 668 name = ((AddeServer)needle).getName(); 669 } else if (needle instanceof Group) { 670 name = ((Group)needle).getName(); 671 } else if (needle instanceof AddeEntry) { 672 name = ((AddeEntry)needle).getAddress(); 673 } else { 674 name = needle.toString(); 675 } 676 677 if (isLoopback(name)) { 678 return 0; 679 } 680 681 for (int i = 0; i < haystack.getItemCount(); i++) { 682 Object item = haystack.getItemAt(i); 683 String tmpName; 684 if (item instanceof AddeServer) { 685 tmpName = ((AddeServer)item).getName(); 686 } else { 687 tmpName = item.toString(); 688 } 689 690 if (name.equals(tmpName)) { 691 return i; 692 } 693 } 694 return -1; 695 } 696 697 /** 698 * Get the selected AddeServer 699 * 700 * @return the server or null 701 */ 702 protected AddeServer getAddeServer() { 703 if (lastServerName != null && lastServerName.equals("unset")) { 704 return null; 705 } 706 707 Object selected = serverSelector.getSelectedItem(); 708 if ((selected != null) && (selected instanceof AddeServer)) { 709 AddeServer server = (AddeServer)selected; 710 String group = getGroup(true); 711 Map<String, String> accounting = getAccounting(server, group); 712// logger.trace("accounting: new: u='{}' p='{}' old: u='{}' p='{}'", new Object[] { accounting.get("user"), accounting.get("proj"), lastServerUser, lastServerProj }); 713 lastServerUser = accounting.get("user"); 714 lastServerProj = accounting.get("proj"); 715 setLastServer(server.getName(), group, server); 716 return (AddeServer)selected; 717 } else if ((selected != null) && (selected instanceof String)) { 718 719 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 720 String server = (String)selected; 721 String group = getGroup(true); 722 723 if (isBadServer(server, group)) { 724// logger.trace("getAddeServer: returning null; known bad server; server={} group={}", server, group); 725 return null; 726 } 727 728 if (isLastServer(server, group)) { 729// logger.trace("getAddeServer: returning last server name; server={} group={}", server, group); 730 return lastServer; 731 } 732 733 EditorAction editorAction = EditorAction.INVALID; 734 if (!isLoopback(server)) { 735 RemoteEntryEditor editor = new RemoteEntryEditor(servManager, server, ""); 736 editor.setVisible(true); 737 editorAction = editor.getEditorAction(); 738 } else { 739 LocalEntryEditor editor = new LocalEntryEditor(servManager, group); 740 editor.setVisible(true); 741 editorAction = editor.getEditorAction(); 742 } 743 744 int servIndex = 0; 745 int groupIndex = 0; 746 747 if (editorAction != EditorAction.CANCELLED && editorAction != EditorAction.INVALID) { 748 749 List<AddeServer> added = arrList(EntryTransforms.convertMcvServers(servManager.getLastAddedByType(EntryTransforms.strToEntryType(getDataType())))); 750 AddeServer first = null; 751 if (!added.isEmpty()) { 752 first = added.get(0); 753 servIndex = getSelectorIndex(first, serverSelector); 754 setLastServer(server, group, first); 755 } 756 757 serverSelector.setSelectedIndex(servIndex); 758 groupSelector.setSelectedIndex(groupIndex); 759// logger.trace("getAddeServer: serverIdx={} groupIdx={}", servIndex, groupIndex); 760 761 return first; 762 } else { 763// logger.trace("getAddeServer: returning null due to cancel request"); 764 setBadServer(server, group); 765 return null; 766 } 767 768 769 770 } else if (selected == null) { 771// logger.trace("getAddeServer: null object in selector; returning null"); 772 } else { 773// logger.debug("getAddeServer: unknown obj type={}; toString={}", selected.getClass().getName(), selected.toString()); 774 } 775 return null; 776 } 777 778 /** 779 * A utility to add a component to the list of components that 780 * need the descriptor 781 * 782 * @param comp The component 783 * @return The component 784 */ 785 protected JComponent addDescComp(JComponent comp) { 786 compsThatNeedDescriptor.add(comp); 787 return comp; 788 } 789 790 /** 791 * Set LABEL_SELECT from elsewhere 792 */ 793 protected void setSelectString(String string) { 794 LABEL_SELECT = string; 795 } 796 797 /** 798 * Reset the descriptor stuff 799 */ 800 protected void resetDescriptorBox() { 801 ignoreDescriptorChange = true; 802 descriptorComboBox.setSelectedItem(LABEL_SELECT); 803 ignoreDescriptorChange = false; 804 } 805 806 /** 807 * Handle when the user presses the connect button 808 * 809 * @throws Exception On badness 810 */ 811 public void handleConnect() throws Exception { 812 AddeServer server = getAddeServer(); 813 if (server == null) { 814 return; 815 } 816 setState(STATE_CONNECTING); 817 connectToServer(); 818 handleUpdate(); 819 } 820 821 /** 822 * Show the user a descriptive error message in a dialog (if in foreground 823 * mode) depending on the state of {@code e}. 824 * 825 * @param e Exception to handle. Cannot be {@code null}. 826 * 827 * @throws NullPointerException if {@code e} is {@code null}. 828 * 829 * @see #handleConnectionError(String, Exception) 830 */ 831 @Override protected void handleConnectionError(Exception e) { 832 handleConnectionError("", e); 833 } 834 835 /** 836 * Show the user a descriptive error message (with optional details) in a 837 * dialog. 838 * 839 * @param details Details about the context of {@code e}. {@code null} will 840 * be treated as an empty {@code String}. 841 * @param e Exception to handle. Cannot be {@code null}. 842 * 843 * @throws NullPointerException if {@code e} is {@code null}. 844 */ 845 protected void handleConnectionError(String details, Exception e) { 846 Objects.requireNonNull(e, "Cannot handle null exception"); 847 logger.error("attempting to handle connection error", e); 848 849 if ((details != null) && !details.isEmpty()) { 850 details = details+":\n"; 851 } else { 852 details = ""; 853 } 854 855 boolean isError = true; 856 if (e.getMessage() != null) { 857 String msg = e.getMessage(); 858 int msgPos = msg.indexOf("AddeURLException:"); 859 if ((msgPos >= 0) && (msg.length() > 18)) { 860 msg = msg.substring(msgPos + 18); 861 GuiUtils.showDialog("ADDE Error", new JLabel(details+msg)); 862 } else if (msg.indexOf("Connecting to server:localhost:") >= 0) { 863 GuiUtils.showDialog("ADDE Error", new JLabel("Local server is not responding.")); 864 } else if (msg.toLowerCase().contains("unknownhostexception")) { 865 LogUtil.userErrorMessage("Could not access server: " + getServer()); 866 } else if ((e instanceof AddeURLException) || msg.toLowerCase().contains("server unable to resolve this dataset")) { 867 handleUnknownDataSetError(); 868 } else if ((msg.toLowerCase().contains("no images satisfy")) 869 || (msg.toLowerCase().contains("error generating list of files"))) 870 { 871 LogUtil.userErrorMessage("No data available for the selection"); 872 isError = false; 873 } else { 874 LogUtil.logException("Encountered a problem (server: '" + getServer()+"'):\n"+details, e); 875 } 876 } else { 877 LogUtil.userErrorMessage("Encountered a problem (server: '" + getServer() + "'):\n" + details +e); 878 } 879 880 if (isError && (getState() == STATE_CONNECTED)) { 881 setHaveData(false); 882 resetDescriptorBox(); 883 updateStatus(); 884 setState(STATE_UNCONNECTED); 885 } 886 } 887 888 /** 889 * Handle unknown data set error 890 */ 891 @Override protected void handleUnknownDataSetError() { 892 String server = getServer(); 893 String group = getGroup(); 894 Map<String, String> acct = getAccounting(server, group); 895 String user = acct.get("user"); 896 String proj = acct.get("proj"); 897 898 StringBuilder msg = new StringBuilder("Could not connect to dataset \""); 899 msg.append(getGroup()).append("\" on server \"").append(getServer()).append("\"."); 900 if (DEFAULT_ACCOUNT.getUsername().equals(user) && DEFAULT_ACCOUNT.getProject().equals(proj)) { 901 msg.append("\n\nDataset may require ADDE accounting information."); 902 } else { 903 msg.append("\n\nAccounting information:\nusername: \"") 904 .append(user).append("\"\nproject: \"").append(proj).append('"'); 905 } 906 LogUtil.userErrorMessage(msg.toString()); 907 setState(STATE_UNCONNECTED); 908 } 909 910 /** 911 * Handle the event 912 * 913 * @param ae The event 914 */ 915 public void actionPerformed(ActionEvent ae) { 916 String cmd = ae.getActionCommand(); 917 if (cmd.equals(CMD_MANAGER)) { 918 doManager(); 919 } 920 else { 921 super.actionPerformed(ae); 922 } 923 } 924 925 /** 926 * Go directly to the Server Manager 927 */ 928 public void doManager() { 929// if (isLocalServer()) { 930// ((McIDASV)getIdv()).showAddeManager(); 931// return; 932// } 933 getIdv().getPreferenceManager().showTab(Constants.PREF_LIST_ADDE_SERVERS); 934 } 935 936 /** 937 * Show the parameter restore tree 938 */ 939 public void doParameters() { 940 JPopupMenu popup = new JPopupMenu(); 941 JMenuItem mi = new JMenuItem("Manage..."); 942 mi.addActionListener(new ActionListener() { 943 public void actionPerformed(ActionEvent ae) { 944 System.out.println(ae); 945 showParameterSetDialog(getParameterSetType()); 946 } 947 }); 948 popup.add(mi); 949 950 // Add the checkbox to automatically create a data source 951 cb.addActionListener(new ActionListener() { 952 public void actionPerformed(ActionEvent ae) { 953 shouldAddSource = cb.isSelected(); 954 } 955 }); 956 popup.addSeparator(); 957 popup.add(cb); 958 959 final PersistenceManager pm = (PersistenceManager)getIdv().getPersistenceManager(); 960 List<ParameterSet> parameterSets = pm.getAllParameterSets(getParameterSetType()); 961 962 for (int i=0; i<parameterSets.size(); i++) { 963 if (i==0) popup.addSeparator(); 964 final ParameterSet ps = parameterSets.get(i); 965 966 // Parameter set at root 967 if (ps.getCategories().size() == 0) { 968 mi = new JMenuItem(ps.getName()); 969 mi.addActionListener(new ActionListener() { 970 public void actionPerformed(ActionEvent ae) { 971 restoreParameterSet(ps.getElement()); 972 } 973 }); 974 popup.add(mi); 975 } 976 977 // Recurse into folders 978 else { 979 // Find or make the menu for the given parameter set 980 JMenu m = getPopupSubMenuForParameterSet(popup, ps); 981 // Create parameter set entry 982 mi = new JMenuItem(ps.getName()); 983 mi.addActionListener(new ActionListener() { 984 public void actionPerformed(ActionEvent ae) { 985 restoreParameterSet(ps.getElement()); 986 } 987 }); 988 m.add(mi); 989 } 990 991 } 992 993 popup.show(parameterButton, 0, (int) parameterButton.getBounds().getHeight()); 994 } 995 996 private JMenu getPopupSubMenuForParameterSet(JPopupMenu popup, final ParameterSet ps) { 997 List<String> menuNames = ps.getCategories(); 998 if (menuNames.size() < 1) return null; 999 1000 // Build the complete menu 1001 String menuName = menuNames.get(0); 1002 menuNames.remove(0); 1003 JMenu theMenu = new JMenu(); 1004 1005 // Look for the menu in popup 1006 boolean found = false; 1007 for (int i=0; i<popup.getComponentCount(); i++) { 1008 Component thisComponent = popup.getComponent(i); 1009 if (thisComponent instanceof JMenu && ((JMenu)thisComponent).getText().equals(menuName)) { 1010 theMenu = mergeMenuNames((JMenu)thisComponent, menuNames); 1011 found = true; 1012 } 1013 } 1014 1015 // Make a new menu, add the root, return the leaf 1016 if (!found) { 1017 JMenu theRoot = new JMenu(menuName); 1018 theMenu = makeMenuRecursive(theRoot, menuNames); 1019 popup.add(theRoot); 1020 } 1021 1022 return theMenu; 1023 } 1024 1025 /** 1026 * Make a new recursive menu 1027 * 1028 * @param rootMenu The root menu to add items to 1029 * @param menuNames List of string names for submenus 1030 * @return A new JMenu representing the leaf 1031 */ 1032 private JMenu makeMenuRecursive(JMenu rootMenu, List<String> menuNames) { 1033 if (menuNames.size() < 1) return rootMenu; 1034 JMenu newMenu = new JMenu(menuNames.get(0)); 1035 rootMenu.add(newMenu); 1036 menuNames.remove(0); 1037 return makeMenuRecursive(newMenu, menuNames); 1038 } 1039 1040 /** 1041 * Recurse into a menu, returning either a pointer to the designated names path 1042 * or a pointer to the leaf menu added by merging new names 1043 * 1044 * @param thisMenu The root menu to merge 1045 * @param menuNames List of string names to look for 1046 * @return A new JMenu representing the leaf matched by menuNames 1047 */ 1048 private JMenu mergeMenuNames(JMenu thisMenu, List<String> menuNames) { 1049 if (menuNames.size() < 1) return thisMenu; 1050 boolean found = false; 1051 String menuName = menuNames.get(0); 1052 for (int i=0; i<thisMenu.getItemCount(); i++) { 1053 JMenuItem mi = thisMenu.getItem(i); 1054 if (!(mi instanceof JMenu)) continue; 1055 if (mi.getText().equals(menuName)) { 1056 menuNames.remove(0); 1057 thisMenu = mergeMenuNames((JMenu)mi, menuNames); 1058 found = true; 1059 } 1060 } 1061 if (!found) { 1062 thisMenu = makeMenuRecursive(thisMenu, menuNames); 1063 } 1064 return thisMenu; 1065 } 1066 1067 /** 1068 * Return the parameter type associated with this chooser. Override! 1069 */ 1070 protected String getParameterSetType() { 1071 return "adde"; 1072 } 1073 1074 /** 1075 * Show the parameter set manager. 1076 */ 1077 private void showParameterSetDialog(final String parameterSetType) { 1078 ParameterTree tree = (ParameterTree) parameterTrees.get(parameterSetType); 1079 if (tree == null) { 1080 tree = new ParameterTree((UIManager)getIdv().getIdvUIManager() , parameterSetType); 1081 parameterTrees.put(parameterSetType, tree); 1082 } 1083 else { 1084 //DAVEP 1085 System.out.println("Should refresh the parameter tree here"); 1086 } 1087 tree.setVisible(true); 1088 } 1089 1090 /** 1091 * Clear the selected parameter set. 1092 */ 1093 protected void clearParameterSet() { 1094 restoreElement = null; 1095 restoreTimes = new ArrayList(); 1096 shouldAddSource = false; 1097 } 1098 1099 /** 1100 * Restore the selected parameter set using element attributes. 1101 * 1102 * @param restoreElement {@code Element} with the desired attributes. 1103 * {@code null} values are permitted. 1104 * 1105 * @return {@code true} if the parameter set was restored, {@code false} 1106 * otherwise. 1107 */ 1108 protected boolean restoreParameterSet(Element restoreElement) { 1109 if (restoreElement == null) return false; 1110 if (!restoreElement.getTagName().equals("default")) return false; 1111 1112 this.restoreElement = restoreElement; 1113 1114 boolean oldISCE = ignoreStateChangedEvents; 1115 ignoreStateChangedEvents = true; 1116 1117 // Restore server 1118 String server = restoreElement.getAttribute(ATTR_SERVER); 1119 if (server != null) serverSelector.setSelectedItem(new AddeServer(server)); 1120 1121 // Restore group 1122 String group = restoreElement.getAttribute(ATTR_GROUP); 1123 if (group != null) groupSelector.setSelectedItem(group); 1124 1125 // Act as though the user hit "connect" 1126 readFromServer(); 1127 1128 // Restore descriptor 1129 String descriptor = restoreElement.getAttribute(ATTR_DESCRIPTOR); 1130 if (descriptor != null) { 1131 Enumeration enumeration = descriptorTable.keys(); 1132 for (int i = 0; enumeration.hasMoreElements(); i++) { 1133 String key = enumeration.nextElement().toString(); 1134 Object val = descriptorTable.get(key); 1135 if (descriptor.equals(val)) { 1136 descriptorComboBox.setSelectedItem(val + nameSeparator + key); 1137 descriptorChanged(); 1138 break; 1139 } 1140 } 1141 } 1142 1143 // Restore date/time 1144 if (restoreElement.hasAttribute(ATTR_POS)) { 1145 setDoAbsoluteTimes(false); 1146 Integer pos = new Integer(restoreElement.getAttribute(ATTR_POS)); 1147 if (pos.intValue() >= 0) { 1148 getRelativeTimesList().setSelectedIndex(pos); 1149 } 1150 restoreTimes = new ArrayList(); 1151 } 1152 else if ((restoreElement.hasAttribute(ATTR_DAY)) && (restoreElement.hasAttribute(ATTR_TIME))) { 1153 setDoAbsoluteTimes(true); 1154 String dateStr = restoreElement.getAttribute(ATTR_DAY); 1155 String timeStr = restoreElement.getAttribute(ATTR_TIME); 1156 List dateS = StringUtil.split(dateStr, ","); 1157 List timeS = StringUtil.split(timeStr, ","); 1158 int numImages = timeS.size(); 1159 restoreTimes = new ArrayList(); 1160 try { 1161 DateTime dt = new DateTime(); 1162 dt.resetFormat(); 1163 String dtformat = dt.getFormatPattern(); 1164 for (int ix=0; ix<numImages; ix++) { 1165 DateTime restoreTime = dt.createDateTime((String)dateS.get(ix) + " " + (String)timeS.get(ix)); 1166 restoreTimes.add(restoreTime); 1167 } 1168 } catch (Exception e) { 1169 System.out.println("Exception e=" + e); 1170 return false; 1171 } 1172 } 1173 1174 System.out.println("Returning from AddeChooser.restoreParameterSet()"); 1175 1176 ignoreStateChangedEvents = oldISCE; 1177 return true; 1178 } 1179 1180 /** 1181 * Set the absolute times list. The times list can contain any of the object types 1182 * that makeDatedObjects knows how to handle, i.e., Date, visad.DateTime, DatedThing, AddeImageDescriptor, etc. 1183 * 1184 * @param times List of thinggs to put into absolute times list 1185 */ 1186 protected void setAbsoluteTimes(List times) { 1187 super.setAbsoluteTimes(times); 1188 restoreAbsoluteTimes(); 1189 } 1190 1191 protected void restoreAbsoluteTimes() { 1192 List allTimes = makeDatedObjects(super.getAbsoluteTimes()); 1193 if (restoreTimes.size() > 0 && allTimes.size() > 0) { 1194 int[] indices = new int[restoreTimes.size()]; 1195 try { 1196 DateTime rtdt; 1197 DateTime atdt; 1198 DatedThing at; 1199 for (int i = 0; i < restoreTimes.size(); i++) { 1200 rtdt = (DateTime)restoreTimes.get(i); 1201 for (int j = 0; j < allTimes.size(); j++) { 1202 at = (DatedThing)allTimes.get(j); 1203 atdt = new DateTime(at.getDate()); 1204 if (atdt.equals(rtdt)) { 1205 indices[i] = j; 1206 } 1207 } 1208 } 1209 } catch (Exception e) { 1210 System.out.println("Exception e=" + e); 1211 } 1212 setSelectedAbsoluteTimes(indices); 1213 } 1214 } 1215 1216 /** 1217 * show/hide the parameter restore button 1218 */ 1219 public void showParameterButton() { 1220 parameterButton.setVisible(true); 1221 } 1222 1223 public void hideParameterButton() { 1224 parameterButton.setVisible(false); 1225 } 1226 1227 /** 1228 * Override and simulate clicking Add Source if requested 1229 */ 1230 public void setHaveData(boolean have) { 1231 super.setHaveData(have); 1232 if (have && shouldAddSource) { 1233 // Even though setHaveData should mean we can go, we can't... wait a few jiffies 1234 Misc.runInABit(100, AddeChooser.this, "doClickLoad", null); 1235 } 1236 } 1237 1238 public void doClickLoad() { 1239 loadButton.doClick(); 1240 } 1241 1242 public void showServers() { 1243 allServersFlag = !allServersFlag; 1244 XmlObjectStore store = getIdv().getStore(); 1245 store.put(Constants.PREF_SYSTEMSERVERSIMG, allServersFlag); 1246 store.save(); 1247 updateServers(); 1248 updateGroups(); 1249 } 1250 1251 protected String getStateString() { 1252 int state = getState(); 1253 switch (state) { 1254 case STATE_CONNECTED: return "Connected to server"; 1255 case STATE_UNCONNECTED: return "Not connected to server"; 1256 case STATE_CONNECTING: return "Connecting to server"; 1257 default: return "Unknown state: " + state; 1258 } 1259 } 1260 1261 /** 1262 * Disable/enable any components that depend on the server. 1263 * Try to update the status label with what we know here. 1264 */ 1265 protected void updateStatus() { 1266 super.updateStatus(); 1267 if (getState() == STATE_CONNECTED) { 1268 lastServer = new AddeServer(""); 1269 lastServerGroup = ""; 1270 lastServerName = ""; 1271 lastServerProj = ""; 1272 lastServerUser = ""; 1273 1274 if (!haveDescriptorSelected()) { 1275 if (!usingStations() || haveStationSelected()) { 1276 // String name = getDataName().toLowerCase(); 1277 String name = getDescriptorLabel().toLowerCase(); 1278 if (StringUtil.startsWithVowel(name)) { 1279 setStatus("Please select an " + name); 1280 } else { 1281 setStatus("Please select a " + name); 1282 } 1283 } 1284 } 1285 } 1286 1287 GuiUtils.enableTree(connectButton, getState() != STATE_CONNECTING); 1288 } 1289 1290 /** 1291 * Get the data type ID 1292 * 1293 * @return the data type 1294 */ 1295 public String getDataType() { 1296 return "ANY"; 1297 } 1298 1299 /** 1300 * Check if the server is ok 1301 * 1302 * @return status code 1303 */ 1304 protected int checkIfServerIsOk() { 1305 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 1306 if (isLocalServer() && !servManager.checkLocalServer()) { 1307 LogUtil.userErrorMessage("Local servers are stopped.\n\nLocal servers can be restarted from the 'Tools' menu:\n Tools > Manage ADDE Datasets >\nLocal Servers > Start Local Servers"); 1308 logger.info("Local servers are stopped"); 1309 return STATUS_ERROR; 1310 } 1311 try { 1312 StringBuffer buff = getUrl(REQ_TEXT); 1313 appendKeyValue(buff, PROP_FILE, FILE_PUBLICSRV); 1314 URL url = new URL(buff.toString()); 1315 URLConnection urlc = url.openConnection(); 1316 InputStream is = urlc.getInputStream(); 1317 is.close(); 1318 return STATUS_OK; 1319 } catch (AddeURLException ae) { 1320 String aes = ae.toString(); 1321 if (aes.indexOf("Invalid project number") >= 0 || 1322 aes.indexOf("Invalid user id") >= 0 || 1323 aes.indexOf("Accounting data") >= 0) { 1324 LogUtil.userErrorMessage("Invalid login.\n\nPlease verify your username and password."); 1325 logger.info("Invalid login"); 1326 setState(STATE_UNCONNECTED); 1327 setHaveData(false); 1328 resetDescriptorBox(); 1329 return STATUS_NEEDSLOGIN; 1330 } 1331 if (aes.indexOf("cannot run server 'txtgserv'") >= 0) { 1332 return STATUS_OK; 1333 } 1334 LogUtil.userErrorMessage("Error connecting to server " + getServer() + ":\n" + ae.getMessage()); 1335 logger.info("Error connecting to server"); 1336 setState(STATE_UNCONNECTED); 1337 setHaveData(false); 1338 resetDescriptorBox(); 1339 return STATUS_ERROR; 1340 } catch (ConnectException exc) { 1341 setState(STATE_UNCONNECTED); 1342 setHaveData(false); 1343 resetDescriptorBox(); 1344 String message = "Error connecting to server " + getServer(); 1345 String info = "Error connecting to server"; 1346 if (isLocalServer()) { 1347 if (!servManager.checkLocalServer()) { 1348 message += "\n\nLocal servers can be restarted from the 'Tools' menu:\n Tools > Manage ADDE Datasets >\n Local Servers > Start Local Servers"; 1349 info += " (Local servers are stopped)"; 1350 } 1351 else { 1352 message += "\n\nLocal servers appear to be running.\nYour firewall may be preventing access."; 1353 info += " (Local servers are running)"; 1354 } 1355 } 1356 LogUtil.userErrorMessage(message); 1357 logger.info(info); 1358 return STATUS_ERROR; 1359 } catch (EOFException exc) { 1360 setState(STATE_UNCONNECTED); 1361 setHaveData(false); 1362 resetDescriptorBox(); 1363 LogUtil.userErrorMessage("Server " + getServer() + " is not responding"); 1364 logger.info("Server is not responding"); 1365 return STATUS_ERROR; 1366 } catch (Exception exc) { 1367 setState(STATE_UNCONNECTED); 1368 setHaveData(false); 1369 resetDescriptorBox(); 1370 logException("Connecting to server: " + getServer(), exc); 1371 logger.info("Error connecting to server"); 1372 return STATUS_ERROR; 1373 } 1374 } 1375 1376 public boolean canAccessServer() { 1377 return (checkIfServerIsOk() == STATUS_OK); 1378 } 1379 1380 public Map<String, String> getAccountingInfo() { 1381 AddeServer server = getAddeServer(); 1382 Map<String, String> map = new LinkedHashMap<String, String>(); 1383 if (server != null) { 1384 List<AddeServer.Group> groups = server.getGroups(); 1385 Map<String, String>acctInfo = getAccounting(server, groups.get(0).toString()); 1386 map.put("user", acctInfo.get("user")); 1387 map.put("proj", acctInfo.get("proj")); 1388 map.put("server", server.getName()); 1389 map.put("group", getGroup()); 1390 } else { 1391 map.put("user", RemoteAddeEntry.DEFAULT_ACCOUNT.getUsername()); 1392 map.put("proj", RemoteAddeEntry.DEFAULT_ACCOUNT.getUsername()); 1393 map.put("server", ""); 1394 map.put("group", ""); 1395 } 1396 return map; 1397 } 1398 1399 /** 1400 * Saves the currently selected server and group to a chooser-specific 1401 * preference. Preference ID is {@code PREF_SERVERSTATE+'.'+getId()}. 1402 */ 1403 @Override public void saveServerState() { 1404 String[] serverState = { getServer(), getGroup() }; 1405 getIdv().getStore().put(PREF_SERVERSTATE+'.'+getId(), serverState); 1406 getIdv().getStore().save(); 1407 } 1408 1409 /** 1410 * Connect to the server. 1411 */ 1412 protected void connectToServer() { 1413 clearParameterSet(); 1414 setDescriptors(null); 1415 setDoAbsoluteTimes(false); 1416 if (!canAccessServer()) { 1417 return; 1418 } 1419 readFromServer(); 1420 saveServerState(); 1421 ignoreStateChangedEvents = true; 1422 if (descList != null) { 1423 descList.saveState(groupSelector); 1424 } 1425 ignoreStateChangedEvents = false; 1426 } 1427 1428 /** 1429 * Do server connection stuff... override this with type-specific methods 1430 */ 1431 protected void readFromServer() { 1432 readDescriptors(); 1433 readTimes(); 1434 } 1435 1436// what the request needs to look like: 1437// adde://localhost:8112/imagedata?&PORT=112&COMPRES S=gzip&USER=idv&PROJ=0 1438// &VERSION=1&DEBUG=false&TRAC E=0&GROUP=MYDATA&DESCRIPTOR=ENTRY4&BAND=1 1439// &LATLON= 30.37139 71.74912&PLACE=CENTER&SIZE=1000 1000&UNI T=BRIT 1440// &MAG=1 1&SPAC=1&NAV=X&AUX=YES&DOC=X&POS=0 1441 1442 /** 1443 * Generate a list of image descriptors for the descriptor list. 1444 */ 1445 protected void readDescriptors() { 1446 try { 1447 StringBuffer buff = getGroupUrl(REQ_DATASETINFO, getGroup()); 1448 buff.append("&type=").append(getDataType()); 1449 logger.debug("readDesc: buff={}", buff.toString()); 1450 DataSetInfo dsinfo = new DataSetInfo(buff.toString()); 1451 1452 descriptorTable = dsinfo.getDescriptionTable(); 1453 descriptorList.clear(); 1454 commentList.clear(); 1455 descriptorList.addAll(dsinfo.getDescriptorList()); 1456 commentList.addAll(dsinfo.getCommentList()); 1457 int count = commentList.size(); 1458 String[] names = new String[count]; 1459 for (int i = 0; i < count; i++) { 1460 if (!isLocalServer()) { 1461 names[i] = descriptorList.get(i) + nameSeparator + commentList.get(i); 1462 } else { 1463 names[i] = commentList.get(i); 1464 } 1465 } 1466 logger.debug("readDesc: names={}", names); 1467 Arrays.sort(names); 1468 setDescriptors(names); 1469 setState(STATE_CONNECTED); 1470 } catch (Exception e) { 1471 handleConnectionError(e); 1472 } 1473 } 1474 1475 /** 1476 * Initialize the descriptor list from a list of names 1477 * 1478 * @param names list of names 1479 */ 1480 protected void setDescriptors(String[] names) { 1481 synchronized (WIDGET_MUTEX) { 1482 ignoreDescriptorChange = true; 1483 descriptorComboBox.removeAllItems(); 1484 descriptorNames = names; 1485 if ((names == null) || (names.length == 0)) { 1486 return; 1487 } 1488 descriptorComboBox.addItem(LABEL_SELECT); 1489 for (int j = 0; j < names.length; j++) { 1490 logger.trace("adding names[{}]='{}' to combo box", j, names[j]); 1491 descriptorComboBox.addItem(names[j]); 1492 } 1493 ignoreDescriptorChange = false; 1494 } 1495 } 1496 1497 /** 1498 * Respond to a change in the descriptor list. 1499 */ 1500 protected void descriptorChanged() { 1501 readTimes(); 1502 updateStatus(); 1503 } 1504 1505 /** 1506 * Check if a descriptor (image type) has been chosen 1507 * 1508 * @return true if an image type has been chosen 1509 */ 1510 protected boolean haveDescriptorSelected() { 1511 if (!GuiUtils.anySelected(descriptorComboBox)) { 1512 return false; 1513 } 1514 return getDescriptor() != null; 1515 } 1516 1517 /** 1518 * Get the selected descriptor. 1519 * 1520 * @return the currently selected descriptor. 1521 */ 1522 protected String getDescriptor() { 1523 return getDescriptorFromSelection(getSelectedDescriptor()); 1524 } 1525 1526 /** 1527 * Get the descriptor relating to the selection. 1528 * 1529 * @param selection String name from the widget. Can be {@code null}. 1530 * 1531 * @return Either the descriptor associated with {@code selection} or {@code null} if {@link #descriptorTable} or 1532 * {@code selection} is {@code null}. 1533 */ 1534 protected String getDescriptorFromSelection(String selection) { 1535 if (descriptorTable == null) { 1536 return null; 1537 } 1538 if (selection == null) { 1539 return null; 1540 } 1541 1542 String descriptor = null; 1543 if (!selection.contains(nameSeparator)) { 1544 descriptor = (String)descriptorTable.get(selection); 1545 } else { 1546 String[] toks = selection.split(nameSeparator, 2); 1547 String firstToken = toks[0].trim(); 1548 if (descriptorList.contains(firstToken)) { 1549 descriptor = firstToken; 1550 } else { 1551 String key = toks[1].trim(); 1552 descriptor = (String)descriptorTable.get(key); 1553 } 1554 } 1555 return descriptor; 1556 } 1557 1558 /** 1559 * Get the selected descriptor. 1560 * 1561 * @return the selected descriptor 1562 */ 1563 public String getSelectedDescriptor() { 1564 String selection = (String)descriptorComboBox.getSelectedItem(); 1565 if (selection == null) { 1566 return null; 1567 } 1568 if (selection.equals(LABEL_SELECT)) { 1569 return null; 1570 } 1571 return selection; 1572 } 1573 1574 /** 1575 * Get the descriptor table for this chooser 1576 * 1577 * @return a Hashtable of descriptors and names 1578 */ 1579 public Hashtable getDescriptorTable() { 1580 return descriptorTable; 1581 } 1582 1583 /** 1584 * Get any extra key=value pairs that are appended to all requests. 1585 * 1586 * @param buff The buffer to append onto 1587 */ 1588 protected void appendMiscKeyValues(StringBuffer buff) { 1589 appendKeyValue(buff, PROP_COMPRESS, DEFAULT_COMPRESS); 1590 appendKeyValue(buff, PROP_PORT, DEFAULT_PORT); 1591 // appendKeyValue(buff, PROP_DEBUG, DEFAULT_DEBUG); 1592 appendKeyValue(buff, PROP_DEBUG, Boolean.toString(EntryStore.isAddeDebugEnabled(false))); 1593 appendKeyValue(buff, PROP_VERSION, DEFAULT_VERSION); 1594 appendKeyValue(buff, PROP_USER, getLastAddedUser()); 1595 appendKeyValue(buff, PROP_PROJ, getLastAddedProj()); 1596 } 1597 1598 public String getLastAddedUser() { 1599 if ((lastServerUser != null) && !lastServerUser.isEmpty()) { 1600 logger.debug("getLastAddedUser: using non-default {}", lastServerUser); 1601 return lastServerUser; 1602 } else { 1603 logger.debug("getLastAddedUser: using default {}", DEFAULT_USER); 1604 return DEFAULT_USER; 1605 } 1606 } 1607 1608 public String getLastAddedProj() { 1609 if ((lastServerProj != null) && !lastServerProj.isEmpty()) { 1610 logger.debug("getLastAddedProj: using non-default {}", lastServerProj); 1611 return lastServerProj; 1612 } else { 1613 logger.debug("getLastAddedProj: using default {}", DEFAULT_PROJ); 1614 return DEFAULT_PROJ; 1615 } 1616 } 1617 1618 /** 1619 * Show the groups dialog. This method is not meant to be called 1620 * but is public by reason of implementation (or insanity). 1621 */ 1622 public void showGroups() { 1623 JPopupMenu popup = new JPopupMenu(); 1624 popup.add(new JMenuItem("Reading public datasets...")); 1625 popup.show(publicButton, 0, (int) publicButton.getBounds().getHeight()); 1626 1627 List groups = readGroups(); 1628 popup.removeAll(); 1629 if ((groups == null) || (groups.isEmpty())) { 1630 popup.add(new JMenuItem("No public datasets available")); 1631 popup.setVisible(false); 1632 popup.setVisible(true); 1633 return; 1634 } 1635 1636 JMenuItem mi; 1637 for (int i = 0; i < groups.size(); i++) { 1638 final String group = groups.get(i).toString(); 1639 mi = new JMenuItem(group); 1640 mi.addActionListener(new ActionListener() { 1641 public void actionPerformed(ActionEvent ae) { 1642 groupSelector.setSelectedItem(group); 1643 doConnect(); 1644 } 1645 }); 1646 popup.add(mi); 1647 } 1648 popup.setVisible(false); 1649 popup.setVisible(true); 1650 } 1651 1652 /** 1653 * return the String id of the chosen server name 1654 * 1655 * @return the server name 1656 */ 1657 public String getServer() { 1658 AddeServer server = getAddeServer(); 1659 if (server != null) { 1660 return server.getName(); 1661 } else { 1662 return ""; 1663 } 1664 } 1665 1666 protected String getGroup() { 1667 return getGroup(false); 1668 } 1669 1670 /** 1671 * Is the group selector editable? 1672 * 1673 * @return Always returns {@code true}. 1674 */ 1675 protected boolean isGroupEditable() { 1676 return true; 1677 } 1678 1679 /** 1680 * Get the image group from the GUI. 1681 * 1682 * @return The image group. 1683 */ 1684 protected String getGroup(final boolean fromGetServer) { 1685 Object selected = groupSelector.getSelectedItem(); 1686 if (selected == null) { 1687 return null; 1688 } 1689 1690 if (selected instanceof AddeServer.Group) { 1691 AddeServer.Group group = (AddeServer.Group) selected; 1692 return group.getName(); 1693 } 1694 1695 if (selected instanceof String) { 1696 return (String)selected; 1697 } 1698 1699 String groupName = selected.toString().trim(); 1700 if (!fromGetServer && (!groupName.isEmpty())) { 1701 //Force the get in case they typed a server name 1702 getServer(); 1703 1704 AddeServer server = getAddeServer(); 1705 if (server != null) { 1706 AddeServer.Group group = 1707 getIdv().getIdvChooserManager().addAddeServerGroup( 1708 server, groupName, getGroupType()); 1709 if (!group.getActive()) { 1710 getIdv().getIdvChooserManager().activateAddeServerGroup( 1711 server, group); 1712 } 1713 //Now put the list of groups back in to the selector 1714 setGroups(); 1715 groupSelector.setSelectedItem(group); 1716 } 1717 } 1718 return groupName; 1719 } 1720 1721 /** 1722 * Get the server selector 1723 * @return The server selector 1724 */ 1725 public JComboBox getServerSelector() { 1726 if (serverSelector == null) 1727 serverSelector = super.getServerSelector(); 1728 1729 ItemListener[] ell = serverSelector.getItemListeners(); 1730 for (int i=0; i < ell.length; i++) { 1731 serverSelector.removeItemListener((ItemListener)ell[i]); 1732 } 1733 updateServers(); 1734 updateGroups(); 1735 serverSelector.addItemListener(new ItemListener() { 1736 public void itemStateChanged(ItemEvent e) { 1737 if (!ignoreStateChangedEvents) { 1738 Object selected = serverSelector.getSelectedItem(); 1739 if (selected instanceof AddeServer) { 1740 AddeServer selectedServer = (AddeServer)selected; 1741 if (selectedServer != null) { 1742 if (isSeparator(selectedServer)) { 1743 connectButton.setEnabled(false); 1744 return; 1745 } 1746 } 1747 } 1748 setState(STATE_UNCONNECTED); 1749 connectButton.setEnabled(true); 1750// setGroups(); 1751 resetDescriptorBox(); 1752 updateGroups(); 1753// System.err.println("itemStateChanged"); 1754 } 1755// else { 1756// System.out.println("Ignoring state change here..."); 1757// } 1758 } 1759 }); 1760 1761 serverSelector.getEditor().getEditorComponent().addKeyListener(new KeyListener() { 1762 public void keyTyped(final KeyEvent e) {} 1763 public void keyPressed(final KeyEvent e) {} 1764 public void keyReleased(final KeyEvent e) { 1765 JTextField field = (JTextField)serverSelector.getEditor().getEditorComponent(); 1766 boolean partialMatch = false; 1767 for (int i = 0; i < serverSelector.getItemCount(); i++) { 1768 String entry = serverSelector.getItemAt(i).toString(); 1769 if (entry.toLowerCase().startsWith(field.getText().toLowerCase())) 1770 partialMatch = true; 1771 } 1772 1773 if (!partialMatch && groupSelector != null) { 1774 logger.debug("aha! chooser=", getDataType()); 1775 ((JTextField)groupSelector.getEditor().getEditorComponent()).setText(""); 1776 } 1777 } 1778 }); 1779 1780 return serverSelector; 1781 } 1782 1783 /** 1784 * Enable or disable the GUI widgets based on what has been 1785 * selected. 1786 */ 1787 protected void enableWidgets() { 1788 synchronized (WIDGET_MUTEX) { 1789 boolean newEnabledState = (getState() == STATE_CONNECTED); 1790 for (int i = 0; i < compsThatNeedDescriptor.size(); i++) { 1791 JComponent comp = (JComponent) compsThatNeedDescriptor.get(i); 1792 if (comp.isEnabled() != newEnabledState) { 1793 GuiUtils.enableTree(comp, newEnabledState); 1794 } 1795 } 1796 if (drivercbx != null) { 1797 boolean descriptorState = newEnabledState && haveDescriptorSelected(); 1798// logger.trace("hrm set drivercbx={}", anyTimeDrivers() && descriptorState); 1799 drivercbx.setEnabled(anyTimeDrivers() && descriptorState); 1800 } 1801 } 1802 } 1803 1804 /** 1805 * Add a listener to the given combobox that will set the 1806 * state to unconnected 1807 * 1808 * @param box The box to listen to. 1809 */ 1810 protected void clearOnChange(final JComboBox box) { 1811 box.addItemListener(new ItemListener() { 1812 public void itemStateChanged(ItemEvent e) { 1813 if ( !ignoreStateChangedEvents) { 1814 setState(STATE_UNCONNECTED); 1815 GuiUtils.setListData(descriptorComboBox, new Vector()); 1816// System.err.println("clearOnChange"); 1817 } 1818// else { 1819// System.out.println("Ignoring state change in clearOnChange for: " + box.toString()); 1820// } 1821 } 1822 }); 1823 } 1824 1825 /** 1826 * Get the descriptor widget label 1827 * 1828 * @return label for the descriptor widget 1829 */ 1830 public String getDescriptorLabel() { 1831 return "Descriptor"; 1832 } 1833 1834 protected int getNumTimesToSelect() { 1835 return 5; 1836 } 1837 1838 /** 1839 * Get the default selected index for the relative times list. 1840 * 1841 * @return default index 1842 */ 1843 protected int getDefaultRelativeTimeIndex() { 1844 return 4; 1845 } 1846 1847 /** 1848 * Check the times lists 1849 */ 1850 protected void checkTimesLists() { 1851 super.checkTimesLists(); 1852 if (timesCardPanelExtra == null) { 1853 return; 1854 } 1855 if (getDoAbsoluteTimes()) { 1856 timesCardPanelExtra.show("absolute"); 1857 } else { 1858 timesCardPanelExtra.show("relative"); 1859 } 1860 } 1861 1862 /** Card panel to hold extra relative and absolute time components */ 1863 protected GuiUtils.CardLayoutPanel timesCardPanelExtra; 1864 1865 /** 1866 * Set the relative and absolute extra components. 1867 */ 1868 protected JPanel makeTimesPanel(JComponent relativeCard, JComponent absoluteCard) { 1869// JPanel timesPanel = super.makeTimesPanel(false, true); 1870 JPanel timesPanel = super.makeTimesPanel(false, true, getIdv().getUseTimeDriver()); 1871 1872 // Make a new timesPanel that has extra components tacked on the bottom, inside the tabs 1873 Component[] comps = timesPanel.getComponents(); 1874 1875// if (drivercbx != null) { 1876// drivercbx.setEnabled(anyTimeDrivers()); 1877// } 1878 1879 if ((comps.length == 1) && (comps[0] instanceof JTabbedPane)) { 1880 timesCardPanelExtra = new GuiUtils.CardLayoutPanel(); 1881 if (relativeCard == null) { 1882 relativeCard = new JPanel(); 1883 } 1884 if (absoluteCard == null) { 1885 absoluteCard = new JPanel(); 1886 } 1887 timesCardPanelExtra.add(relativeCard, "relative"); 1888 timesCardPanelExtra.add(absoluteCard, "absolute"); 1889 timesPanel = GuiUtils.centerBottom(comps[0], timesCardPanelExtra); 1890 } 1891 1892 return timesPanel; 1893 } 1894 1895 private JPanel innerPanel = new JPanel(); 1896 1897 private JLabel statusLabel = new JLabel("Status"); 1898 1899 /** 1900 * Super setStatus() takes a second string to enable "simple" mode 1901 * which highlights the required component. We don't really care 1902 * about that feature, and we don't want getStatusLabel() to 1903 * change the label background color. 1904 */ 1905 @Override 1906 public void setStatus(String statusString, String foo) { 1907 if (statusString == null) { 1908 statusString = ""; 1909 } 1910 statusLabel.setText(statusString); 1911 } 1912 1913 protected void setInnerPanel(JPanel newInnerPanel) { 1914 innerPanel = newInnerPanel; 1915 } 1916 1917 /** 1918 * Make the UI for this selector. 1919 * 1920 * Thank you NetBeans for helping with the layout! 1921 * 1922 * @return The GUI. 1923 */ 1924 protected JComponent doMakeContents() { 1925 JPanel outerPanel = new JPanel(); 1926 1927 JLabel serverLabelInner = new JLabel("Server:"); 1928 McVGuiUtils.setLabelPosition(serverLabelInner, Position.RIGHT); 1929 JPanel serverLabel = GuiUtils.leftRight(parameterButton, serverLabelInner); 1930 McVGuiUtils.setComponentWidth(serverLabel); 1931 1932 clearOnChange(serverSelector); 1933 McVGuiUtils.setComponentWidth(serverSelector, Width.DOUBLE); 1934 1935 JLabel groupLabel = McVGuiUtils.makeLabelRight("Dataset:"); 1936 1937 groupSelector.setEditable(isGroupEditable()); 1938 clearOnChange(groupSelector); 1939 McVGuiUtils.setComponentWidth(groupSelector, Width.DOUBLE); 1940 1941 McVGuiUtils.setComponentWidth(connectButton, Width.DOUBLE); 1942 connectButton.setActionCommand(CMD_CONNECT); 1943 connectButton.addActionListener(this); 1944 1945 /** Set the attributes for the descriptor label and combo box, even though 1946 * they are not used here. Extending classes can add them to the panel if 1947 * necessary. 1948 */ 1949 McVGuiUtils.setComponentWidth(descriptorLabel); 1950 McVGuiUtils.setLabelPosition(descriptorLabel, Position.RIGHT); 1951 1952 McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLEDOUBLE); 1953 1954 if (descriptorComboBox.getMinimumSize().getWidth() < ELEMENT_DOUBLE_WIDTH) { 1955 McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLE); 1956 } 1957 1958 JLabel statusLabelLabel = McVGuiUtils.makeLabelRight(""); 1959 1960 statusLabel.setText("Status"); 1961 McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT); 1962 McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS); 1963 1964 JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help"); 1965 helpButton.setActionCommand(GuiUtils.CMD_HELP); 1966 helpButton.addActionListener(this); 1967 1968 JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh"); 1969 refreshButton.setActionCommand(GuiUtils.CMD_UPDATE); 1970 refreshButton.addActionListener(this); 1971 1972 McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE); 1973 1974 GroupLayout layout = new GroupLayout(outerPanel); 1975 outerPanel.setLayout(layout); 1976 layout.setHorizontalGroup( 1977 layout.createParallelGroup(LEADING) 1978 .addGroup(TRAILING, layout.createSequentialGroup() 1979 .addGroup(layout.createParallelGroup(TRAILING) 1980 .addGroup(layout.createSequentialGroup() 1981 .addContainerGap() 1982 .addComponent(helpButton) 1983 .addGap(GAP_RELATED) 1984 .addComponent(refreshButton) 1985 .addGap(GAP_RELATED) 1986 .addComponent(cancelButton) 1987 .addPreferredGap(RELATED) 1988 .addComponent(loadButton)) 1989 .addGroup(LEADING, layout.createSequentialGroup() 1990 .addContainerGap() 1991 .addGroup(layout.createParallelGroup(LEADING) 1992 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1993 .addGroup(layout.createSequentialGroup() 1994 .addComponent(serverLabel) 1995 .addGap(GAP_RELATED) 1996 .addComponent(serverSelector) 1997 .addGap(GAP_RELATED) 1998 .addComponent(manageButton) 1999 .addGap(GAP_RELATED) 2000 .addComponent(groupLabel) 2001 .addGap(GAP_RELATED) 2002 .addComponent(groupSelector) 2003 .addGap(GAP_RELATED) 2004 .addComponent(publicButton) 2005 .addPreferredGap(RELATED, DEFAULT_SIZE, Short.MAX_VALUE) 2006 .addComponent(connectButton)) 2007 .addGroup(layout.createSequentialGroup() 2008 .addComponent(statusLabelLabel) 2009 .addGap(GAP_RELATED) 2010 .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))) 2011 .addContainerGap()) 2012 ); 2013 layout.setVerticalGroup( 2014 layout.createParallelGroup(LEADING) 2015 .addGroup(layout.createSequentialGroup() 2016 .addContainerGap() 2017 .addGroup(layout.createParallelGroup(BASELINE) 2018 .addComponent(serverLabel) 2019 .addComponent(serverSelector) 2020 .addComponent(manageButton) 2021 .addComponent(groupLabel) 2022 .addComponent(groupSelector) 2023 .addComponent(publicButton) 2024 .addComponent(connectButton)) 2025 .addPreferredGap(UNRELATED) 2026 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 2027 .addPreferredGap(UNRELATED) 2028 .addGroup(layout.createParallelGroup(BASELINE) 2029 .addComponent(statusLabelLabel) 2030 .addComponent(statusLabel)) 2031 .addPreferredGap(UNRELATED) 2032 .addGroup(layout.createParallelGroup(BASELINE) 2033 .addComponent(loadButton) 2034 .addComponent(cancelButton) 2035 .addComponent(refreshButton) 2036 .addComponent(helpButton)) 2037 .addContainerGap()) 2038 ); 2039 2040 return outerPanel; 2041 2042 } 2043 2044 public class ServerComparator implements Comparator<AddeServer> { 2045 public int compare(AddeServer server1, AddeServer server2) { 2046 return server1.getName().compareTo(server2.getName()); 2047 } 2048 } 2049 2050 public class GroupComparator implements Comparator<Group> { 2051 public int compare(Group group1, Group group2) { 2052 return group1.getName().compareTo(group2.getName()); 2053 } 2054 } 2055} 2056