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