001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2015 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.ui; 018 019import static org.opends.messages.AdminToolMessages.*; 020import static org.opends.server.util.StaticUtils.isOEMVersion; 021 022import java.awt.Component; 023import java.awt.Dimension; 024import java.awt.GridBagConstraints; 025import java.awt.GridBagLayout; 026import java.awt.Insets; 027import java.awt.Window; 028import java.util.HashMap; 029 030import javax.swing.ImageIcon; 031import javax.swing.JPanel; 032import javax.swing.JScrollPane; 033import javax.swing.JSplitPane; 034import javax.swing.JTree; 035import javax.swing.SwingUtilities; 036import javax.swing.border.EmptyBorder; 037import javax.swing.event.TreeSelectionEvent; 038import javax.swing.event.TreeSelectionListener; 039import javax.swing.tree.DefaultMutableTreeNode; 040import javax.swing.tree.DefaultTreeModel; 041import javax.swing.tree.TreePath; 042 043import org.opends.guitools.controlpanel.browser.IconPool; 044import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 045import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 046import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 047import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 048import org.opends.guitools.controlpanel.ui.components.TreePanel; 049import org.opends.guitools.controlpanel.ui.nodes.GeneralMonitoringTreeNode; 050import org.opends.guitools.controlpanel.ui.renderer.TreeCellRenderer; 051import org.opends.guitools.controlpanel.util.Utilities; 052import org.opends.guitools.controlpanel.util.ViewPositions; 053import org.forgerock.i18n.LocalizableMessage; 054import org.forgerock.i18n.LocalizableMessageBuilder; 055 056/** 057 * The pane that is displayed when the user clicks on 'General Monitoring'. 058 * 059 */ 060public class BrowseGeneralMonitoringPanel extends StatusGenericPanel 061{ 062 private static final long serialVersionUID = 6462914563746678830L; 063 064 /** 065 * The panel containing the tree. 066 */ 067 private TreePanel treePane; 068 069 private JScrollPane treeScroll; 070 071 private ServerDescriptor lastServer; 072 073 private String lastServerName; 074 075 private boolean ignoreSelectionEvents; 076 077 private LocalizableMessage NO_ELEMENT_SELECTED = 078 INFO_CTRL_PANEL_GENERAL_MONITORING_NO_ITEM_SELECTED.get(); 079 private LocalizableMessage MULTIPLE_ITEMS_SELECTED = 080 INFO_CTRL_PANEL_MULTIPLE_ITEMS_SELECTED_LABEL.get(); 081 082 /** 083 * The enumeration used to define the different static nodes of the tree. 084 * 085 */ 086 protected enum NodeType 087 { 088 /** Root node. */ 089 ROOT, 090 /** System information node. */ 091 SYSTEM_INFORMATION, 092 /** Java information node. */ 093 JAVA_INFORMATION, 094 /** Work queue node. */ 095 WORK_QUEUE, 096 /** Entry caches node. */ 097 ENTRY_CACHES, 098 /** JE Databases information node. */ 099 JE_DATABASES_INFORMATION, 100 /** PDB databases information node. */ 101 PDB_DATABASES_INFORMATION 102 } 103 104 /** 105 * The panel displaying the informations about the selected node. 106 */ 107 protected GeneralMonitoringRightPanel entryPane; 108 109 /** 110 * Default constructor. 111 * 112 */ 113 public BrowseGeneralMonitoringPanel() 114 { 115 super(); 116 createLayout(); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public boolean requiresBorder() 122 { 123 return false; 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public boolean requiresScroll() 129 { 130 return false; 131 } 132 133 /** {@inheritDoc} */ 134 @Override 135 public boolean callConfigurationChangedInBackground() 136 { 137 return true; 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 public void toBeDisplayed(boolean visible) 143 { 144 Window w = Utilities.getParentDialog(this); 145 if (w instanceof GenericDialog) 146 { 147 ((GenericDialog)w).getRootPane().setDefaultButton(null); 148 } 149 else if (w instanceof GenericFrame) 150 { 151 ((GenericFrame)w).getRootPane().setDefaultButton(null); 152 } 153 } 154 155 /** 156 * Creates the layout of the panel (but the contents are not populated here). 157 */ 158 private void createLayout() 159 { 160 setBackground(ColorAndFontConstants.greyBackground); 161 GridBagConstraints gbc = new GridBagConstraints(); 162 gbc.anchor = GridBagConstraints.WEST; 163 gbc.gridx = 0; 164 gbc.gridy = 0; 165 gbc.gridwidth = 1; 166 gbc.weightx = 1.0; 167 gbc.fill = GridBagConstraints.BOTH; 168 addErrorPane(gbc); 169 170 gbc.insets = new Insets(10, 0, 0, 0); 171 gbc.gridx = 0; 172 gbc.gridy ++; 173 gbc.weightx = 1.0; 174 gbc.weighty = 1.0; 175 gbc.fill = GridBagConstraints.BOTH; 176 gbc.gridwidth = 7; 177 add(createSplitPane(), gbc); 178 } 179 180 /** {@inheritDoc} */ 181 @Override 182 public LocalizableMessage getTitle() 183 { 184 return INFO_CTRL_PANEL_GENERAL_MONITORING_TITLE.get(); 185 } 186 187 /** {@inheritDoc} */ 188 @Override 189 public Component getPreferredFocusComponent() 190 { 191 return treePane; 192 } 193 194 /** {@inheritDoc} */ 195 @Override 196 public void okClicked() 197 { 198 // No ok button 199 } 200 201 /** {@inheritDoc} */ 202 @Override 203 public GenericDialog.ButtonType getButtonType() 204 { 205 return GenericDialog.ButtonType.CLOSE; 206 } 207 208 /** 209 * Creates the browser right panel. 210 * @return the created browser right panel. 211 */ 212 private GeneralMonitoringRightPanel createBrowserRightPanel() 213 { 214 return new GeneralMonitoringRightPanel(); 215 } 216 217 private Component createSplitPane() 218 { 219 treePane = new TreePanel(); 220 221 entryPane = createBrowserRightPanel(); 222 223 JPanel p = new JPanel(new GridBagLayout()); 224 p.setBackground(ColorAndFontConstants.background); 225 GridBagConstraints gbc = new GridBagConstraints(); 226 gbc.gridx = 0; 227 gbc.gridy = 0; 228 gbc.gridwidth = 1; 229 gbc.anchor = GridBagConstraints.NORTHWEST; 230 gbc.fill = GridBagConstraints.BOTH; 231 gbc.weightx = 1.0; 232 gbc.weighty = 1.0; 233 Utilities.setBorder(treePane, new EmptyBorder(10, 0, 10, 0)); 234 p.add(treePane, gbc); 235 treeScroll = Utilities.createScrollPane(p); 236 237 treePane.getTree().addTreeSelectionListener(new TreeSelectionListener() 238 { 239 /** {@inheritDoc} */ 240 public void valueChanged(TreeSelectionEvent ev) 241 { 242 if (!ignoreSelectionEvents) 243 { 244 ignoreSelectionEvents = true; 245 updateEntryPane(); 246 ignoreSelectionEvents = false; 247 } 248 } 249 }); 250 JTree tree = treePane.getTree(); 251 repopulateTree(tree, true); 252 tree.setRootVisible(true); 253 tree.setVisibleRowCount(20); 254 tree.expandPath(new TreePath(getRoot(tree))); 255 tree.setCellRenderer(new GeneralMonitoringTreeCellRenderer()); 256 treeScroll.setPreferredSize( 257 new Dimension(treeScroll.getPreferredSize().width + 30, 258 3 * treeScroll.getPreferredSize().height)); 259 entryPane.displayMessage(NO_ELEMENT_SELECTED); 260 entryPane.setBorder(getRightPanelBorder()); 261 entryPane.setPreferredSize( 262 new Dimension(treeScroll.getPreferredSize().width * 2, 263 treeScroll.getPreferredSize().height)); 264 JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); 265 pane.setOpaque(true); //content panes must be opaque 266 pane.setLeftComponent(treeScroll); 267 pane.setRightComponent(entryPane); 268 pane.setResizeWeight(0.0); 269 pane.setDividerLocation(treeScroll.getPreferredSize().width); 270 return pane; 271 } 272 273 /** {@inheritDoc} */ 274 @Override 275 public void setInfo(ControlPanelInfo info) 276 { 277 super.setInfo(info); 278 treePane.setInfo(info); 279 entryPane.setInfo(info); 280 } 281 282 /** {@inheritDoc} */ 283 public void configurationChanged(ConfigurationChangeEvent ev) 284 { 285 ServerDescriptor server = ev.getNewDescriptor(); 286 if (serverChanged(server)) 287 { 288 final boolean firstTimeCalled = lastServer == null; 289 lastServer = server; 290 291 SwingUtilities.invokeLater(new Runnable() 292 { 293 public void run() 294 { 295 String serverName = getServerName(lastServer); 296 // Repopulate the tree to display a root node with server information 297 if (!serverName.equals(lastServerName)) 298 { 299 repopulateTree(treePane.getTree(), false); 300 lastServerName = serverName; 301 } 302 if (firstTimeCalled) 303 { 304 // Select the root 305 treePane.getTree().setSelectionInterval(0, 0); 306 } 307 else 308 { 309 // Reselect 310 updateEntryPane(); 311 } 312 } 313 }); 314 } 315 else 316 { 317 lastServer = server; 318 } 319 320 boolean displayErrorPane = false; 321 LocalizableMessage errorTitle = LocalizableMessage.EMPTY; 322 LocalizableMessage errorDetails = LocalizableMessage.EMPTY; 323 ServerDescriptor.ServerStatus status = server.getStatus(); 324 if (status == ServerDescriptor.ServerStatus.STARTED) 325 { 326 if (!server.isAuthenticated()) 327 { 328 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 329 mb.append( 330 INFO_CTRL_PANEL_AUTH_REQUIRED_TO_BROWSE_MONITORING_SUMMARY. 331 get()); 332 mb.append("<br><br>").append(getAuthenticateHTML()); 333 errorDetails = mb.toMessage(); 334 errorTitle = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); 335 336 displayErrorPane = true; 337 } 338 } 339 else if (status == ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE) 340 { 341 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 342 mb.append(INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get( 343 server.getHostname())); 344 mb.append("<br><br>").append(getAuthenticateHTML()); 345 errorDetails = mb.toMessage(); 346 errorTitle = INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_SUMMARY.get(); 347 displayErrorPane = true; 348 } 349 else 350 { 351 errorTitle = INFO_CTRL_PANEL_SERVER_NOT_RUNNING_SUMMARY.get(); 352 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 353 mb.append( 354 INFO_CTRL_PANEL_SERVER_MUST_RUN_TO_BROWSE_MONITORING_SUMMARY. 355 get()); 356 mb.append("<br><br>"); 357 mb.append(getStartServerHTML()); 358 errorDetails = mb.toMessage(); 359 displayErrorPane = true; 360 } 361 final boolean fDisplayErrorPane = displayErrorPane; 362 final LocalizableMessage fErrorTitle = errorTitle; 363 final LocalizableMessage fErrorDetails = errorDetails; 364 SwingUtilities.invokeLater(new Runnable() 365 { 366 /** {@inheritDoc} */ 367 public void run() 368 { 369 errorPane.setVisible(fDisplayErrorPane); 370 if (fDisplayErrorPane) 371 { 372 updateErrorPane(errorPane, fErrorTitle, 373 ColorAndFontConstants.errorTitleFont, fErrorDetails, 374 ColorAndFontConstants.defaultFont); 375 } 376 } 377 }); 378 } 379 380 /** 381 * Populates the tree. Should be called only once since the tree in this 382 * panel is static. 383 * @param tree the tree to be repopulated. 384 * @param forceScroll whether the scroll must be reset or not. 385 */ 386 private void repopulateTree(JTree tree, boolean forceScroll) 387 { 388 ignoreSelectionEvents = true; 389 390 ViewPositions pos = Utilities.getViewPositions(treeScroll); 391 392 ServerDescriptor server = null; 393 if (getInfo() != null) 394 { 395 server = getInfo().getServerDescriptor(); 396 } 397 GeneralMonitoringTreeNode root; 398 if (server == null) 399 { 400 root = 401 new GeneralMonitoringTreeNode( 402 INFO_CTRL_PANEL_GENERAL_MONITORING_ROOT.get().toString(), 403 NodeType.ROOT, 404 true); 405 } 406 else 407 { 408 root = 409 new GeneralMonitoringTreeNode( 410 getServerName(server), 411 NodeType.ROOT, 412 true); 413 } 414 415 LocalizableMessage[] messages = getNodeMessages(); 416 NodeType[] identifiers = getNodeTypes(); 417 for (int i=0; i < messages.length; i++) 418 { 419 if (isVisible(identifiers[i])) 420 { 421 root.add(new GeneralMonitoringTreeNode(messages[i].toString(), identifiers[i], false)); 422 } 423 } 424 425 DefaultTreeModel model = new DefaultTreeModel(root); 426 tree.setModel(model); 427 428 Utilities.updateViewPositions(pos); 429 ignoreSelectionEvents = false; 430 } 431 432 /** 433 * Updates the right entry panel. 434 * 435 */ 436 private void updateEntryPane() 437 { 438 ViewPositions pos = Utilities.getViewPositions(entryPane); 439 boolean canDisplayMonitorInformation = true; 440 if (getInfo() == null) 441 { 442 return; 443 } 444 ServerDescriptor server = getInfo().getServerDescriptor(); 445 ServerDescriptor.ServerStatus status = server.getStatus(); 446 if (status == ServerDescriptor.ServerStatus.STARTED) 447 { 448 if (!server.isAuthenticated()) 449 { 450 canDisplayMonitorInformation = false; 451 entryPane.displayMessage( 452 INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get()); 453 } 454 } 455 else 456 { 457 canDisplayMonitorInformation = false; 458 entryPane.displayMessage( 459 INFO_CTRL_PANEL_SERVER_NOT_RUNNING_SUMMARY.get()); 460 } 461 462 if (canDisplayMonitorInformation) 463 { 464 TreePath[] paths = treePane.getTree().getSelectionPaths(); 465 TreePath path = null; 466 if (paths != null && paths.length == 1) 467 { 468 path = paths[0]; 469 } 470 if (path != null) 471 { 472 GeneralMonitoringTreeNode node = 473 (GeneralMonitoringTreeNode)path.getLastPathComponent(); 474 NodeType type = (NodeType)node.getIdentifier(); 475 switch (type) 476 { 477 case ROOT: 478 entryPane.updateRoot(); 479 break; 480 case SYSTEM_INFORMATION: 481 entryPane.updateSystemInformation(); 482 break; 483 case WORK_QUEUE: 484 entryPane.updateWorkQueue(); 485 break; 486 case ENTRY_CACHES: 487 entryPane.updateEntryCaches(); 488 break; 489 case JE_DATABASES_INFORMATION: 490 entryPane.updateJEDatabaseInformation(); 491 break; 492 case PDB_DATABASES_INFORMATION: 493 entryPane.updatePDBDatbaseInformation(); 494 break; 495 case JAVA_INFORMATION: 496 entryPane.updateJavaInformation(); 497 break; 498 default: 499 throw new RuntimeException("Unknown node type: "+type); 500 } 501 } 502 else 503 { 504 if (paths != null && paths.length > 1) 505 { 506 entryPane.displayMessage(MULTIPLE_ITEMS_SELECTED); 507 } 508 else 509 { 510 entryPane.displayMessage(NO_ELEMENT_SELECTED); 511 } 512 } 513 } 514 Utilities.updateViewPositions(pos); 515 } 516 517 private DefaultMutableTreeNode getRoot(JTree tree) 518 { 519 return (DefaultMutableTreeNode)tree.getModel().getRoot(); 520 } 521 522 private boolean serverChanged(ServerDescriptor desc) 523 { 524 boolean changed = false; 525 if (lastServer != null) 526 { 527 // Just compare the elements interesting for this panel 528 changed = 529 !desc.getBackends().equals(lastServer.getBackends()); 530 if (!changed) 531 { 532 CustomSearchResult[] monitor1 = 533 { 534 lastServer.getEntryCachesMonitor(), 535 lastServer.getJvmMemoryUsageMonitor(), 536 lastServer.getRootMonitor(), 537 lastServer.getSystemInformationMonitor(), 538 lastServer.getWorkQueueMonitor() 539 }; 540 CustomSearchResult[] monitor2 = 541 { 542 desc.getEntryCachesMonitor(), 543 desc.getJvmMemoryUsageMonitor(), 544 desc.getRootMonitor(), 545 desc.getSystemInformationMonitor(), 546 desc.getWorkQueueMonitor() 547 }; 548 for (int i=0; i<monitor1.length && !changed; i++) 549 { 550 if (monitor1[i] == null) 551 { 552 changed = monitor2[i] != null; 553 } 554 else 555 { 556 changed = !monitor1[i].equals(monitor2[i]); 557 } 558 } 559 } 560 } 561 else 562 { 563 changed = true; 564 } 565 return changed; 566 } 567 568 private HashMap<Object, ImageIcon> hmImages = new HashMap<>(); 569 { 570 NodeType[] identifiers = { 571 NodeType.ROOT, 572 NodeType.SYSTEM_INFORMATION, 573 NodeType.JAVA_INFORMATION, 574 NodeType.WORK_QUEUE, 575 NodeType.ENTRY_CACHES, 576 NodeType.JE_DATABASES_INFORMATION, 577 NodeType.PDB_DATABASES_INFORMATION 578 }; 579 LocalizableMessage[] ocPaths = { 580 INFO_CTRL_PANEL_GENERAL_MONITORING_ROOT_TREE_NODE.get(), 581 INFO_CTRL_PANEL_SYSTEM_INFORMATION_TREE_NODE.get(), 582 INFO_CTRL_PANEL_JVM_MEMORY_USAGE_TREE_NODE.get(), 583 INFO_CTRL_PANEL_WORK_QUEUE_TREE_NODE.get(), 584 INFO_CTRL_PANEL_ENTRY_CACHES_TREE_NODE.get(), 585 INFO_CTRL_PANEL_DB_ENVIRONMENT_TREE_NODE.get(), 586 INFO_CTRL_PANEL_DB_ENVIRONMENT_TREE_NODE.get() 587 }; 588 for (int i=0; i<identifiers.length; i++) 589 { 590 hmImages.put(identifiers[i], 591 Utilities.createImageIcon(IconPool.IMAGE_PATH+"/"+ocPaths[i], 592 getClass().getClassLoader())); 593 } 594 } 595 596 private String getServerName(ServerDescriptor server) 597 { 598 String serverName = server.getHostname(); 599 if (server.getAdminConnector() != null) 600 { 601 serverName +=":"+server.getAdminConnector().getPort(); 602 } 603 return serverName; 604 } 605 606 /** 607 * Specific class used to render the nodes in the tree. It uses specific 608 * icons for the nodes. 609 * 610 */ 611 protected class GeneralMonitoringTreeCellRenderer extends TreeCellRenderer 612 { 613 private static final long serialVersionUID = -3390566664259441766L; 614 615 /** {@inheritDoc} */ 616 @Override 617 public Component getTreeCellRendererComponent(JTree tree, Object value, 618 boolean isSelected, boolean isExpanded, boolean isLeaf, int row, 619 boolean hasFocus) 620 { 621 super.getTreeCellRendererComponent(tree, value, isSelected, isExpanded, 622 isLeaf, row, hasFocus); 623 setIcon(getIcon(value)); 624 return this; 625 } 626 627 private ImageIcon getIcon(Object value) 628 { 629 ImageIcon icon = null; 630 if (value instanceof GeneralMonitoringTreeNode) 631 { 632 icon = hmImages.get( 633 ((GeneralMonitoringTreeNode)value).getIdentifier()); 634 } 635 else 636 { 637 throw new RuntimeException("Unexpected tree node: "+value); 638 } 639 return icon; 640 } 641 } 642 643 /** 644 * Returns the labels of the nodes to be displayed. 645 * @return the labels of the nodes to be displayed. 646 */ 647 protected LocalizableMessage[] getNodeMessages() 648 { 649 return new LocalizableMessage[] { 650 INFO_CTRL_PANEL_SYSTEM_INFORMATION.get(), 651 INFO_CTRL_PANEL_JAVA_INFORMATION.get(), 652 INFO_CTRL_PANEL_WORK_QUEUE.get(), 653 INFO_CTRL_PANEL_ENTRY_CACHES.get(), 654 INFO_CTRL_PANEL_JE_DB_INFO.get(), 655 INFO_CTRL_PANEL_PDB_DB_INFO.get() 656 }; 657 } 658 659 /** 660 * Returns the node types to be displayed. 661 * @return the node types to be displayed. 662 */ 663 protected NodeType[] getNodeTypes() 664 { 665 return new NodeType[] { 666 NodeType.SYSTEM_INFORMATION, 667 NodeType.JAVA_INFORMATION, 668 NodeType.WORK_QUEUE, 669 NodeType.ENTRY_CACHES, 670 NodeType.JE_DATABASES_INFORMATION, 671 NodeType.PDB_DATABASES_INFORMATION 672 }; 673 } 674 675 private boolean isVisible(NodeType nodetype) 676 { 677 return !(isOEMVersion() && nodetype == NodeType.JE_DATABASES_INFORMATION); 678 } 679} 680