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