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 2008-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS. 026 */ 027package org.opends.guitools.controlpanel.ui; 028 029import java.awt.CardLayout; 030import java.awt.Color; 031import java.awt.Component; 032import java.awt.Container; 033import java.awt.Dimension; 034import java.awt.Font; 035import java.awt.GridBagConstraints; 036import java.awt.GridBagLayout; 037import java.awt.Insets; 038import java.awt.Window; 039import java.awt.event.ActionEvent; 040import java.awt.event.ActionListener; 041import java.awt.event.ItemEvent; 042import java.awt.event.ItemListener; 043import java.text.DateFormat; 044import java.text.SimpleDateFormat; 045import java.util.ArrayList; 046import java.util.Collection; 047import java.util.Comparator; 048import java.util.Date; 049import java.util.HashMap; 050import java.util.HashSet; 051import java.util.LinkedHashSet; 052import java.util.List; 053import java.util.Map; 054import java.util.Set; 055import java.util.SortedSet; 056import java.util.TreeSet; 057 058import javax.naming.NamingEnumeration; 059import javax.naming.directory.SearchControls; 060import javax.naming.directory.SearchResult; 061import javax.swing.Box; 062import javax.swing.ComboBoxModel; 063import javax.swing.DefaultComboBoxModel; 064import javax.swing.JComboBox; 065import javax.swing.JComponent; 066import javax.swing.JEditorPane; 067import javax.swing.JLabel; 068import javax.swing.JMenuBar; 069import javax.swing.JPanel; 070import javax.swing.SwingUtilities; 071import javax.swing.border.Border; 072 073import org.forgerock.i18n.LocalizableMessage; 074import org.forgerock.i18n.LocalizableMessageBuilder; 075import org.forgerock.i18n.LocalizableMessageDescriptor; 076import org.forgerock.i18n.slf4j.LocalizedLogger; 077import org.forgerock.opendj.ldap.schema.ObjectClassType; 078import org.opends.admin.ads.util.ConnectionUtils; 079import org.opends.guitools.controlpanel.browser.BrowserController; 080import org.opends.guitools.controlpanel.browser.IconPool; 081import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 082import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 083import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; 084import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; 085import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 086import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 087import org.opends.guitools.controlpanel.datamodel.MonitoringAttributes; 088import org.opends.guitools.controlpanel.datamodel.ScheduleType; 089import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 090import org.opends.guitools.controlpanel.datamodel.SortableListModel; 091import org.opends.guitools.controlpanel.event.ConfigChangeListener; 092import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 093import org.opends.guitools.controlpanel.event.ConfigurationElementCreatedListener; 094import org.opends.guitools.controlpanel.task.RebuildIndexTask; 095import org.opends.guitools.controlpanel.task.RestartServerTask; 096import org.opends.guitools.controlpanel.task.StartServerTask; 097import org.opends.guitools.controlpanel.task.StopServerTask; 098import org.opends.guitools.controlpanel.task.Task; 099import org.opends.guitools.controlpanel.ui.components.AddRemovePanel; 100import org.opends.guitools.controlpanel.util.BackgroundTask; 101import org.opends.guitools.controlpanel.util.LowerCaseComparator; 102import org.opends.guitools.controlpanel.util.Utilities; 103import org.opends.quicksetup.ui.CustomHTMLEditorKit; 104import org.opends.server.schema.SchemaConstants; 105import org.opends.server.types.ObjectClass; 106import org.opends.server.types.OpenDsException; 107import org.opends.server.util.ServerConstants; 108import org.opends.server.util.StaticUtils; 109 110import static org.opends.guitools.controlpanel.ui.ControlCenterMainPane.*; 111import static org.opends.messages.AdminToolMessages.*; 112 113/** 114 * An abstract class that contains a number of methods that are shared by all 115 * the inheriting classes. In general a StatusGenericPanel is contained in a 116 * GenericDialog and specifies the kind of buttons that this dialog has. The 117 * StatusGenericPanel is also notified when the dialog is displayed (through the 118 * toBeDisplayed method) 119 */ 120public abstract class StatusGenericPanel extends JPanel implements ConfigChangeListener 121{ 122 private static final long serialVersionUID = -9123358652232556732L; 123 124 /** 125 * The string to be used as combo separator. 126 */ 127 public static final String COMBO_SEPARATOR = "----------"; 128 129 /** 130 * The not applicable message. 131 */ 132 protected static final LocalizableMessage NOT_APPLICABLE = INFO_NOT_APPLICABLE_LABEL.get(); 133 134 private static final LocalizableMessage AUTHENTICATE = INFO_AUTHENTICATE_BUTTON_LABEL.get(); 135 private static final LocalizableMessage START = INFO_START_BUTTON_LABEL.get(); 136 137 private ControlPanelInfo info; 138 139 private final boolean enableClose = true; 140 private boolean enableCancel = true; 141 private boolean enableOK = true; 142 143 private boolean disposeOnClose; 144 145 private final JPanel cardPanel; 146 private final JPanel mainPanel; 147 private final JEditorPane message; 148 149 private final CardLayout cardLayout; 150 151 private static final String MAIN_PANEL = "mainPanel"; 152 private static final String MESSAGE_PANEL = "messagePanel"; 153 154 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 155 156 /** The error pane. */ 157 protected JEditorPane errorPane; 158 159 /** The last displayed message in the error pane. */ 160 private String lastDisplayedError; 161 162 private final List<ConfigurationElementCreatedListener> confListeners = new ArrayList<>(); 163 164 private boolean sizeSet; 165 private boolean focusSet; 166 167 private static final DateFormat taskDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 168 169 /** 170 * Returns the title that will be used as title of the dialog. 171 * 172 * @return the title that will be used as title of the dialog. 173 */ 174 public abstract LocalizableMessage getTitle(); 175 176 /** 177 * Returns the buttons that the dialog where this panel is contained should 178 * display. 179 * 180 * @return the buttons that the dialog where this panel is contained should 181 * display. 182 */ 183 public GenericDialog.ButtonType getButtonType() 184 { 185 return GenericDialog.ButtonType.OK_CANCEL; 186 } 187 188 /** 189 * Returns the component that should get the focus when the dialog that 190 * contains this panel is displayed. 191 * 192 * @return the component that should get the focus. 193 */ 194 public abstract Component getPreferredFocusComponent(); 195 196 /** 197 * Returns <CODE>true</CODE> if this panel requires some bordering (in general 198 * an EmptyBorder with some insets) and <CODE>false</CODE> otherwise. 199 * 200 * @return <CODE>true</CODE> if this panel requires some bordering (in general 201 * an EmptyBorder with some insets) and <CODE>false</CODE> otherwise. 202 */ 203 public boolean requiresBorder() 204 { 205 return true; 206 } 207 208 /** 209 * Returns the menu bar that the panel might have. Returns <CODE>null</CODE> 210 * if the panel has no menu bar associated. 211 * 212 * @return the menu bar that the panel might have. 213 */ 214 public JMenuBar getMenuBar() 215 { 216 return null; 217 } 218 219 /** 220 * This method is called to indicate that the configuration changes should be 221 * called in the background. In the case of panels which require some time to 222 * be updated with the new configuration this method returns <CODE>true</CODE> 223 * and the operation will be performed in the background while a message of 224 * type 'Loading...' is displayed on the panel. 225 * 226 * @return <CODE>true</CODE> if changes should be loaded in the background and 227 * <CODE>false</CODE> otherwise. 228 */ 229 public boolean callConfigurationChangedInBackground() 230 { 231 return false; 232 } 233 234 /** 235 * The panel is notified that the dialog is going to be visible or invisible. 236 * 237 * @param visible 238 * whether is going to be visible or not. 239 */ 240 public void toBeDisplayed(final boolean visible) 241 { 242 } 243 244 /** 245 * Tells whether this panel should be contained in a scroll pane or not. 246 * 247 * @return <CODE>true</CODE> if this panel should be contained in a scroll 248 * pane and <CODE>false</CODE> otherwise. 249 */ 250 public boolean requiresScroll() 251 { 252 return true; 253 } 254 255 /** 256 * Constructor. 257 */ 258 protected StatusGenericPanel() 259 { 260 super(new GridBagLayout()); 261 setBackground(ColorAndFontConstants.background); 262 263 cardLayout = new CardLayout(); 264 cardPanel = new JPanel(cardLayout); 265 cardPanel.setOpaque(false); 266 267 mainPanel = new JPanel(new GridBagLayout()); 268 mainPanel.setOpaque(false); 269 270 message = Utilities.makeHtmlPane("", ColorAndFontConstants.progressFont); 271 272 GridBagConstraints gbc = new GridBagConstraints(); 273 gbc.gridx = 0; 274 gbc.gridy = 0; 275 gbc.fill = GridBagConstraints.BOTH; 276 gbc.weightx = 1.0; 277 gbc.weighty = 1.0; 278 super.add(cardPanel, gbc); 279 280 cardPanel.add(mainPanel, MAIN_PANEL); 281 282 JPanel messagePanel = new JPanel(new GridBagLayout()); 283 messagePanel.setOpaque(false); 284 gbc.fill = GridBagConstraints.NONE; 285 gbc.anchor = GridBagConstraints.CENTER; 286 messagePanel.add(message, gbc); 287 cardPanel.add(messagePanel, MESSAGE_PANEL); 288 289 cardLayout.show(cardPanel, MAIN_PANEL); 290 } 291 292 /** 293 * The components are not added directly to the panel but to the main panel. 294 * This is done to be able to display a message that takes the whole panel (of 295 * type 'Loading...') when we are doing long operations. 296 * 297 * @param comp 298 * the Component to be added. 299 * @param constraints 300 * the constraints. 301 */ 302 @Override 303 public void add(final Component comp, final Object constraints) 304 { 305 mainPanel.add(comp, constraints); 306 } 307 308 /** 309 * Adds a bottom glue to the main panel with the provided constraints. 310 * 311 * @param gbc 312 * the constraints. 313 */ 314 protected void addBottomGlue(final GridBagConstraints gbc) 315 { 316 GridBagConstraints gbc2 = (GridBagConstraints) gbc.clone(); 317 gbc2.insets = new Insets(0, 0, 0, 0); 318 gbc2.gridy++; 319 gbc2.gridwidth = GridBagConstraints.REMAINDER; 320 gbc2.weighty = 1.0; 321 gbc2.fill = GridBagConstraints.VERTICAL; 322 add(Box.createVerticalGlue(), gbc2); 323 gbc.gridy++; 324 } 325 326 /** 327 * Returns a label with text 'Required Field' and an icon (used as legend in 328 * some panels). 329 * 330 * @return a label with text 'Required Field' and an icon (used as legend in 331 * some panels). 332 */ 333 protected JLabel createRequiredLabel() 334 { 335 JLabel requiredLabel = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_INDICATES_REQUIRED_FIELD_LABEL.get()); 336 requiredLabel.setIcon(Utilities.createImageIcon(IconPool.IMAGE_PATH + "/required.gif")); 337 338 return requiredLabel; 339 } 340 341 /** 342 * Creates and adds an error pane. Is up to the caller to set the proper 343 * gridheight, gridwidth, gridx and gridy on the provided GridBagConstraints. 344 * 345 * @param baseGbc 346 * the GridBagConstraints to be used. 347 */ 348 protected void addErrorPane(final GridBagConstraints baseGbc) 349 { 350 addErrorPane(this, baseGbc); 351 } 352 353 /** 354 * Adds an error pane to the provided container. Is up to the caller to set 355 * the proper gridheight, gridwidth, gridx and gridy on the provided 356 * GridBagConstraints. 357 * 358 * @param baseGbc 359 * the GridBagConstraints to be used. 360 * @param p 361 * the container. 362 */ 363 protected void addErrorPane(final Container p, final GridBagConstraints baseGbc) 364 { 365 GridBagConstraints gbc = new GridBagConstraints(); 366 gbc.gridx = baseGbc.gridx; 367 gbc.gridy = baseGbc.gridy; 368 gbc.gridwidth = baseGbc.gridwidth; 369 gbc.gridheight = baseGbc.gridheight; 370 gbc.weightx = 1.0; 371 gbc.fill = GridBagConstraints.BOTH; 372 if (requiresBorder()) 373 { 374 gbc.insets = new Insets(0, 0, 10, 0); 375 } 376 else 377 { 378 gbc.insets = new Insets(20, 20, 0, 20); 379 } 380 createErrorPane(); 381 p.add(errorPane, gbc); 382 } 383 384 /** 385 * Creates the error pane. 386 */ 387 protected void createErrorPane() 388 { 389 errorPane = Utilities.makeHtmlPane("", ColorAndFontConstants.progressFont); 390 errorPane.setOpaque(false); 391 errorPane.setEditable(false); 392 errorPane.setVisible(false); 393 CustomHTMLEditorKit htmlEditor = new CustomHTMLEditorKit(); 394 htmlEditor.addActionListener(new ActionListener() 395 { 396 @Override 397 public void actionPerformed(final ActionEvent ev) 398 { 399 if (AUTHENTICATE.toString().equals(ev.getActionCommand())) 400 { 401 authenticate(); 402 } 403 else if (START.toString().equals(ev.getActionCommand())) 404 { 405 startServer(); 406 } 407 } 408 }); 409 errorPane.setEditorKit(htmlEditor); 410 } 411 412 /** 413 * Commodity method used to add lines, where each line contains a label, a 414 * component and an inline help label. 415 * 416 * @param labels 417 * the labels. 418 * @param comps 419 * the components. 420 * @param inlineHelp 421 * the inline help labels. 422 * @param panel 423 * the panel where we will add the lines. 424 * @param gbc 425 * the grid bag constraints. 426 */ 427 protected void add(final JLabel[] labels, final Component[] comps, final JLabel[] inlineHelp, final Container panel, 428 final GridBagConstraints gbc) 429 { 430 int i = 0; 431 for (Component comp : comps) 432 { 433 gbc.insets.left = 0; 434 gbc.weightx = 0.0; 435 gbc.gridx = 0; 436 if (labels[i] != null) 437 { 438 panel.add(labels[i], gbc); 439 } 440 gbc.insets.left = 10; 441 gbc.weightx = 1.0; 442 gbc.gridx = 1; 443 panel.add(comp, gbc); 444 if (inlineHelp[i] != null) 445 { 446 gbc.insets.top = 3; 447 gbc.gridy++; 448 panel.add(inlineHelp[i], gbc); 449 } 450 gbc.insets.top = 10; 451 gbc.gridy++; 452 i++; 453 } 454 } 455 456 /** 457 * Enables the OK button in the parent dialog. 458 * 459 * @param enable 460 * whether to enable or disable the button. 461 */ 462 protected void setEnabledOK(final boolean enable) 463 { 464 Window w = Utilities.getParentDialog(this); 465 if (w instanceof GenericDialog) 466 { 467 ((GenericDialog) w).setEnabledOK(enable); 468 } 469 else if (w instanceof GenericFrame) 470 { 471 ((GenericFrame) w).setEnabledOK(enable); 472 } 473 enableOK = enable; 474 } 475 476 /** 477 * Enables the Cancel button in the parent dialog. 478 * 479 * @param enable 480 * whether to enable or disable the button. 481 */ 482 protected void setEnabledCancel(final boolean enable) 483 { 484 Window w = Utilities.getParentDialog(this); 485 if (w instanceof GenericDialog) 486 { 487 ((GenericDialog) w).setEnabledCancel(enable); 488 } 489 else if (w instanceof GenericFrame) 490 { 491 ((GenericFrame) w).setEnabledCancel(enable); 492 } 493 enableCancel = enable; 494 } 495 496 /** 497 * Updates the font type and color of the component to be invalid and primary. 498 * 499 * @param comp 500 * the component to update. 501 */ 502 protected void setPrimaryInvalid(final JComponent comp) 503 { 504 comp.setFont(ColorAndFontConstants.primaryInvalidFont); 505 comp.setForeground(ColorAndFontConstants.invalidFontColor); 506 } 507 508 /** 509 * Updates the font type and color of the component to be valid and primary. 510 * 511 * @param comp 512 * the component to update. 513 */ 514 protected void setPrimaryValid(final JComponent comp) 515 { 516 comp.setForeground(ColorAndFontConstants.validFontColor); 517 comp.setFont(ColorAndFontConstants.primaryFont); 518 } 519 520 /** 521 * Updates the font type and color of the component to be invalid and 522 * secondary. 523 * 524 * @param comp 525 * the component to update. 526 */ 527 protected void setSecondaryInvalid(final JComponent comp) 528 { 529 comp.setForeground(ColorAndFontConstants.invalidFontColor); 530 comp.setFont(ColorAndFontConstants.invalidFont); 531 } 532 533 /** 534 * Updates the font type and color of the component to be valid and secondary. 535 * 536 * @param comp 537 * the component to update. 538 */ 539 protected void setSecondaryValid(final JComponent comp) 540 { 541 comp.setForeground(ColorAndFontConstants.validFontColor); 542 comp.setFont(ColorAndFontConstants.defaultFont); 543 } 544 545 /** 546 * Packs the parent dialog. 547 */ 548 protected void packParentDialog() 549 { 550 Window dlg = Utilities.getParentDialog(this); 551 if (dlg != null) 552 { 553 invalidate(); 554 dlg.invalidate(); 555 dlg.pack(); 556 if (!SwingUtilities.isEventDispatchThread()) 557 { 558 Thread.dumpStack(); 559 } 560 } 561 } 562 563 /** 564 * Notification that the ok button has been clicked, the panel is in charge of 565 * doing whatever is required (close the dialog, launch a task, etc.). 566 */ 567 public abstract void okClicked(); 568 569 /** 570 * Adds a configuration element created listener. 571 * 572 * @param listener 573 * the listener. 574 */ 575 public void addConfigurationElementCreatedListener(final ConfigurationElementCreatedListener listener) 576 { 577 getConfigurationElementCreatedListeners().add(listener); 578 } 579 580 /** 581 * Removes a configuration element created listener. 582 * 583 * @param listener 584 * the listener. 585 */ 586 public void removeConfigurationElementCreatedListener(final ConfigurationElementCreatedListener listener) 587 { 588 getConfigurationElementCreatedListeners().remove(listener); 589 } 590 591 /** 592 * Returns the list of configuration listeners. 593 * 594 * @return the list of configuration listeners. 595 */ 596 protected List<ConfigurationElementCreatedListener> getConfigurationElementCreatedListeners() 597 { 598 return confListeners; 599 } 600 601 /** 602 * Notification that cancel was clicked, the panel is in charge of doing 603 * whatever is required (close the dialog, etc.). 604 */ 605 public void cancelClicked() 606 { 607 // Default implementation 608 Utilities.getParentDialog(this).setVisible(false); 609 if (isDisposeOnClose()) 610 { 611 Utilities.getParentDialog(this).dispose(); 612 } 613 } 614 615 /** 616 * Whether the dialog should be disposed when the user closes it. 617 * 618 * @return <CODE>true</CODE> if the dialog should be disposed when the user 619 * closes it or <CODE>true</CODE> otherwise. 620 */ 621 public boolean isDisposeOnClose() 622 { 623 return disposeOnClose; 624 } 625 626 /** 627 * Sets whether the dialog should be disposed when the user closes it or not. 628 * 629 * @param disposeOnClose 630 * <CODE>true</CODE> if the dialog should be disposed when the user 631 * closes it or <CODE>true</CODE> otherwise. 632 */ 633 public void setDisposeOnClose(final boolean disposeOnClose) 634 { 635 this.disposeOnClose = disposeOnClose; 636 } 637 638 /** 639 * Notification that close was clicked, the panel is in charge of doing 640 * whatever is required (close the dialog, etc.). 641 */ 642 public void closeClicked() 643 { 644 // Default implementation 645 Utilities.getParentDialog(this).setVisible(false); 646 if (isDisposeOnClose()) 647 { 648 Utilities.getParentDialog(this).dispose(); 649 } 650 } 651 652 /** 653 * Displays a dialog with the provided list of error messages. 654 * 655 * @param errors 656 * the error messages. 657 */ 658 protected void displayErrorDialog(final Collection<LocalizableMessage> errors) 659 { 660 Utilities.displayErrorDialog(Utilities.getParentDialog(this), errors); 661 } 662 663 /** 664 * Displays a confirmation message. 665 * 666 * @param title 667 * the title/summary of the message. 668 * @param msg 669 * the description of the confirmation. 670 * @return <CODE>true</CODE> if the user confirms and <CODE>false</CODE> 671 * otherwise. 672 */ 673 protected boolean displayConfirmationDialog(final LocalizableMessage title, final LocalizableMessage msg) 674 { 675 return Utilities.displayConfirmationDialog(Utilities.getParentDialog(this), title, msg); 676 } 677 678 /** 679 * If the index must be rebuilt, asks the user for confirmation. If the user 680 * confirms launches a task that will rebuild the indexes. The progress will 681 * be displayed in the provided progress dialog. 682 * 683 * @param index 684 * the index. 685 * @param progressDialog 686 * the progress dialog. 687 */ 688 protected void rebuildIndexIfNecessary(final AbstractIndexDescriptor index, final ProgressDialog progressDialog) 689 { 690 progressDialog.setTaskIsOver(false); 691 boolean rebuildIndexes; 692 String backendName = index.getBackend().getBackendID(); 693 LocalizableMessage summary = INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_SUMMARY.get(); 694 if (!isServerRunning()) 695 { 696 rebuildIndexes = Utilities.displayConfirmationDialog( progressDialog, summary, 697 INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_OFFLINE_DETAILS.get(index.getName(), backendName)); 698 } 699 else if (isLocal()) 700 { 701 rebuildIndexes = Utilities.displayConfirmationDialog(progressDialog, summary, 702 INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_ONLINE_DETAILS.get(index.getName(), backendName, backendName)); 703 } 704 else 705 { 706 Utilities.displayWarningDialog(progressDialog, summary, 707 INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_REMOTE_DETAILS.get(index.getName(), backendName)); 708 rebuildIndexes = false; 709 } 710 if (rebuildIndexes) 711 { 712 SortedSet<AbstractIndexDescriptor> indexes = new TreeSet<>(); 713 indexes.add(index); 714 SortedSet<String> baseDNs = new TreeSet<>(); 715 for (BaseDNDescriptor b : index.getBackend().getBaseDns()) 716 { 717 baseDNs.add(Utilities.unescapeUtf8(b.getDn().toString())); 718 } 719 720 RebuildIndexTask newTask = new RebuildIndexTask(getInfo(), progressDialog, baseDNs, indexes); 721 List<LocalizableMessage> errors = new ArrayList<>(); 722 for (Task task : getInfo().getTasks()) 723 { 724 task.canLaunch(newTask, errors); 725 } 726 if (errors.isEmpty()) 727 { 728 progressDialog.appendProgressHtml("<br><br>"); 729 launchOperation(newTask, INFO_CTRL_PANEL_REBUILDING_INDEXES_SUMMARY.get(backendName), 730 INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_SUMMARY.get(), 731 INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_DETAILS.get(), 732 ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_SUMMARY.get(), null, 733 ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_DETAILS, progressDialog, false); 734 if (progressDialog.isModal()) 735 { 736 progressDialog.toFront(); 737 } 738 progressDialog.setVisible(true); 739 if (!progressDialog.isModal()) 740 { 741 progressDialog.toFront(); 742 } 743 } 744 if (!errors.isEmpty()) 745 { 746 displayErrorDialog(errors); 747 } 748 } 749 else 750 { 751 progressDialog.setTaskIsOver(true); 752 if (progressDialog.isVisible()) 753 { 754 progressDialog.toFront(); 755 } 756 } 757 } 758 759 /** 760 * A class used to avoid the possibility a certain type of objects in a combo 761 * box. This is used for instance in the combo box that contains base DNs 762 * where the base DNs are separated in backends, so the combo box displays 763 * both the backends (~ categories) and base DNs (~ values) and we do not 764 * allow to select the backends (~ categories). 765 */ 766 protected class IgnoreItemListener implements ItemListener 767 { 768 private Object selectedItem; 769 private final JComboBox combo; 770 771 /** 772 * Constructor. 773 * 774 * @param combo 775 * the combo box. 776 */ 777 public IgnoreItemListener(final JComboBox combo) 778 { 779 this.combo = combo; 780 selectedItem = combo.getSelectedItem(); 781 if (isCategory(selectedItem)) 782 { 783 selectedItem = null; 784 } 785 } 786 787 @Override 788 public void itemStateChanged(final ItemEvent ev) 789 { 790 Object o = combo.getSelectedItem(); 791 if (isCategory(o)) 792 { 793 if (selectedItem == null) 794 { 795 selectedItem = firstNonCategoryItem(combo.getModel()); 796 } 797 if (selectedItem != null) 798 { 799 combo.setSelectedItem(selectedItem); 800 } 801 } 802 else if (COMBO_SEPARATOR.equals(o)) 803 { 804 combo.setSelectedItem(selectedItem); 805 } 806 else 807 { 808 selectedItem = o; 809 } 810 } 811 812 private Object firstNonCategoryItem(ComboBoxModel model) 813 { 814 for (int i = 0; i < model.getSize(); i++) 815 { 816 Object item = model.getElementAt(i); 817 if (item instanceof CategorizedComboBoxElement && !isCategory(item)) 818 { 819 return item; 820 } 821 } 822 return null; 823 } 824 } 825 826 /** 827 * Returns the HTML required to render an Authenticate button in HTML. 828 * 829 * @return the HTML required to render an Authenticate button in HTML. 830 */ 831 protected String getAuthenticateHTML() 832 { 833 return "<INPUT type=\"submit\" value=\"" + AUTHENTICATE + "\"></INPUT>"; 834 } 835 836 /** 837 * Returns the HTML required to render an Start button in HTML. 838 * 839 * @return the HTML required to render an Start button in HTML. 840 */ 841 protected String getStartServerHTML() 842 { 843 return "<INPUT type=\"submit\" value=\"" + START + "\"></INPUT>"; 844 } 845 846 /** 847 * Updates the error panel and enables/disables the OK button depending on the 848 * status of the server. 849 * 850 * @param desc 851 * the Server Descriptor. 852 * @param details 853 * the message to be displayed if authentication has not been 854 * provided and the server is running. 855 */ 856 protected void updateErrorPaneAndOKButtonIfAuthRequired( 857 final ServerDescriptor desc, final LocalizableMessage details) 858 { 859 if (authenticationRequired(desc)) 860 { 861 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 862 mb.append(details); 863 mb.append("<br><br>").append(getAuthenticateHTML()); 864 LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); 865 updateErrorPane( 866 errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); 867 SwingUtilities.invokeLater(new Runnable() 868 { 869 @Override 870 public void run() 871 { 872 errorPane.setVisible(true); 873 packParentDialog(); 874 setEnabledOK(false); 875 } 876 }); 877 } 878 else 879 { 880 SwingUtilities.invokeLater(new Runnable() 881 { 882 @Override 883 public void run() 884 { 885 errorPane.setVisible(false); 886 checkOKButtonEnable(); 887 } 888 }); 889 } 890 } 891 892 /** 893 * Returns <CODE>true</CODE> if the server is running and the user did not 894 * provide authentication and <CODE>false</CODE> otherwise. 895 * 896 * @param desc 897 * the server descriptor. 898 * @return <CODE>true</CODE> if the server is running and the user did not 899 * provide authentication and <CODE>false</CODE> otherwise. 900 */ 901 protected boolean authenticationRequired(final ServerDescriptor desc) 902 { 903 ServerDescriptor.ServerStatus status = desc.getStatus(); 904 return (status == ServerDescriptor.ServerStatus.STARTED && !desc.isAuthenticated()) 905 || status == ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE; 906 } 907 908 /** 909 * Updates the error panel depending on the status of the server. 910 * 911 * @param desc 912 * the Server Descriptor. 913 * @param details 914 * the message to be displayed if authentication has not been 915 * provided and the server is running. 916 */ 917 protected void updateErrorPaneIfAuthRequired(final ServerDescriptor desc, final LocalizableMessage details) 918 { 919 if (authenticationRequired(desc)) 920 { 921 LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); 922 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 923 mb.append(details); 924 mb.append("<br><br>").append(getAuthenticateHTML()); 925 updateErrorPane(errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), 926 ColorAndFontConstants.defaultFont); 927 SwingUtilities.invokeLater(new Runnable() 928 { 929 @Override 930 public void run() 931 { 932 errorPane.setVisible(true); 933 packParentDialog(); 934 } 935 }); 936 } 937 else 938 { 939 SwingUtilities.invokeLater(new Runnable() 940 { 941 @Override 942 public void run() 943 { 944 errorPane.setVisible(false); 945 } 946 }); 947 } 948 } 949 950 /** 951 * Updates the error panel depending on the status of the server. This method 952 * will display an error message in the error pane if the server is not 953 * running and another message if the server is running but authentication has 954 * not been provided. 955 * 956 * @param desc 957 * the Server Descriptor. 958 * @param detailsServerNotRunning 959 * the message to be displayed if the server is not running. 960 * @param authRequired 961 * the message to be displayed if authentication has not been 962 * provided and the server is running. 963 */ 964 protected void updateErrorPaneIfServerRunningAndAuthRequired(final ServerDescriptor desc, 965 final LocalizableMessage detailsServerNotRunning, final LocalizableMessage authRequired) 966 { 967 ServerDescriptor.ServerStatus status = desc.getStatus(); 968 if (status != ServerDescriptor.ServerStatus.STARTED 969 && status != ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE) 970 { 971 LocalizableMessage title = INFO_CTRL_PANEL_SERVER_NOT_RUNNING_SUMMARY.get(); 972 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 973 mb.append(detailsServerNotRunning); 974 mb.append("<br><br>").append(getStartServerHTML()); 975 updateErrorPane( 976 errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); 977 SwingUtilities.invokeLater(new Runnable() 978 { 979 /** {@inheritDoc} */ 980 @Override 981 public void run() 982 { 983 errorPane.setVisible(true); 984 packParentDialog(); 985 } 986 }); 987 } 988 else if (authenticationRequired(desc)) 989 { 990 LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); 991 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 992 mb.append(authRequired); 993 mb.append("<br><br>").append(getAuthenticateHTML()); 994 updateErrorPane( 995 errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); 996 SwingUtilities.invokeLater(new Runnable() 997 { 998 @Override 999 public void run() 1000 { 1001 errorPane.setVisible(true); 1002 packParentDialog(); 1003 } 1004 }); 1005 } 1006 else 1007 { 1008 SwingUtilities.invokeLater(new Runnable() 1009 { 1010 @Override 1011 public void run() 1012 { 1013 errorPane.setVisible(false); 1014 } 1015 }); 1016 } 1017 } 1018 1019 /** 1020 * Updates the enabling/disabling of the OK button. The code assumes that the 1021 * error pane has already been updated. 1022 */ 1023 protected void checkOKButtonEnable() 1024 { 1025 setEnabledOK(!errorPane.isVisible()); 1026 } 1027 1028 /** 1029 * Returns <CODE>true</CODE> if the provided object is a category object in a 1030 * combo box. 1031 * 1032 * @param o 1033 * the item in the combo box. 1034 * @return <CODE>true</CODE> if the provided object is a category object in a 1035 * combo box. 1036 */ 1037 protected boolean isCategory(final Object o) 1038 { 1039 if (o instanceof CategorizedComboBoxElement) 1040 { 1041 CategorizedComboBoxElement desc = (CategorizedComboBoxElement) o; 1042 return desc.getType() == CategorizedComboBoxElement.Type.CATEGORY; 1043 } 1044 return false; 1045 } 1046 1047 /** 1048 * Returns the control panel info object. 1049 * 1050 * @return the control panel info object. 1051 */ 1052 public ControlPanelInfo getInfo() 1053 { 1054 return info; 1055 } 1056 1057 /** 1058 * Sets the control panel info object. 1059 * 1060 * @param info 1061 * the control panel info object. 1062 */ 1063 public void setInfo(final ControlPanelInfo info) 1064 { 1065 if (!info.equals(this.info)) 1066 { 1067 if (this.info != null) 1068 { 1069 this.info.removeConfigChangeListener(this); 1070 } 1071 this.info = info; 1072 this.info.addConfigChangeListener(this); 1073 if (SwingUtilities.isEventDispatchThread() && callConfigurationChangedInBackground()) 1074 { 1075 final Color savedBackground = getBackground(); 1076 setBackground(ColorAndFontConstants.background); 1077 if (!sizeSet) 1078 { 1079 setPreferredSize(mainPanel.getPreferredSize()); 1080 sizeSet = true; 1081 } 1082 // Do it outside the event thread if the panel requires it. 1083 BackgroundTask<Void> worker = new BackgroundTask<Void>() 1084 { 1085 @Override 1086 public Void processBackgroundTask() throws Throwable 1087 { 1088 StaticUtils.sleep(1000); 1089 configurationChanged(new ConfigurationChangeEvent(StatusGenericPanel.this.info, 1090 StatusGenericPanel.this.info.getServerDescriptor())); 1091 return null; 1092 } 1093 1094 @Override 1095 public void backgroundTaskCompleted(final Void returnValue, final Throwable t) 1096 { 1097 setBackground(savedBackground); 1098 displayMainPanel(); 1099 if (!focusSet) 1100 { 1101 focusSet = true; 1102 Component comp = getPreferredFocusComponent(); 1103 if (comp != null) 1104 { 1105 comp.requestFocusInWindow(); 1106 } 1107 } 1108 } 1109 }; 1110 displayMessage(INFO_CTRL_PANEL_LOADING_PANEL_SUMMARY.get()); 1111 worker.startBackgroundTask(); 1112 } 1113 else if (info.getServerDescriptor() != null) 1114 { 1115 configurationChanged(new ConfigurationChangeEvent(this.info, this.info.getServerDescriptor())); 1116 } 1117 } 1118 } 1119 1120 /** Displays the main panel. */ 1121 protected void displayMainPanel() 1122 { 1123 cardLayout.show(cardPanel, MAIN_PANEL); 1124 } 1125 1126 /** 1127 * Displays a message and hides the main panel. 1128 * 1129 * @param msg 1130 * the message to be displayed. 1131 */ 1132 protected void displayMessage(final LocalizableMessage msg) 1133 { 1134 message.setText(Utilities.applyFont(msg.toString(), ColorAndFontConstants.defaultFont)); 1135 cardLayout.show(cardPanel, MESSAGE_PANEL); 1136 message.requestFocusInWindow(); 1137 } 1138 1139 /** 1140 * Displays an error message and hides the main panel. 1141 * 1142 * @param title 1143 * the title of the message to be displayed. 1144 * @param msg 1145 * the message to be displayed. 1146 */ 1147 protected void displayErrorMessage(final LocalizableMessage title, final LocalizableMessage msg) 1148 { 1149 updateErrorPane(message, title, ColorAndFontConstants.errorTitleFont, msg, ColorAndFontConstants.defaultFont); 1150 cardLayout.show(cardPanel, MESSAGE_PANEL); 1151 message.requestFocusInWindow(); 1152 } 1153 1154 /** 1155 * Updates the contents of an editor pane using the error format. 1156 * 1157 * @param pane 1158 * the editor pane to be updated. 1159 * @param title 1160 * the title. 1161 * @param titleFont 1162 * the font to be used for the title. 1163 * @param details 1164 * the details message. 1165 * @param detailsFont 1166 * the font to be used for the details. 1167 */ 1168 protected void updateErrorPane(final JEditorPane pane, final LocalizableMessage title, final Font titleFont, 1169 final LocalizableMessage details, final Font detailsFont) 1170 { 1171 updatePane(pane, title, titleFont, details, detailsFont, PanelType.ERROR); 1172 } 1173 1174 /** 1175 * Updates the contents of an editor pane using the confirmation format. 1176 * 1177 * @param pane 1178 * the editor pane to be updated. 1179 * @param title 1180 * the title. 1181 * @param titleFont 1182 * the font to be used for the title. 1183 * @param details 1184 * the details message. 1185 * @param detailsFont 1186 * the font to be used for the details. 1187 */ 1188 protected void updateConfirmationPane(final JEditorPane pane, final LocalizableMessage title, final Font titleFont, 1189 final LocalizableMessage details, final Font detailsFont) 1190 { 1191 updatePane(pane, title, titleFont, details, detailsFont, PanelType.CONFIRMATION); 1192 } 1193 1194 /** The different types of error panels that are handled. */ 1195 private enum PanelType 1196 { 1197 /** The message in the panel is an error. */ 1198 ERROR, 1199 /** The message in the panel is a confirmation. */ 1200 CONFIRMATION, 1201 /** The message in the panel is an information message. */ 1202 INFORMATION, 1203 /** The message in the panel is a warning message. */ 1204 WARNING 1205 } 1206 1207 /** 1208 * Updates the contents of an editor pane using the provided format. 1209 * 1210 * @param pane 1211 * the editor pane to be updated. 1212 * @param title 1213 * the title. 1214 * @param titleFont 1215 * the font to be used for the title. 1216 * @param details 1217 * the details message. 1218 * @param detailsFont 1219 * the font to be used for the details. 1220 * @param type 1221 * the type of panel. 1222 */ 1223 private void updatePane(final JEditorPane pane, final LocalizableMessage title, final Font titleFont, 1224 final LocalizableMessage details, final Font detailsFont, final PanelType type) 1225 { 1226 String text = getText(type, title, titleFont, details, detailsFont); 1227 if (!text.equals(lastDisplayedError)) 1228 { 1229 LocalizableMessage wrappedTitle = Utilities.wrapHTML(title, 80); 1230 LocalizableMessage wrappedDetails = Utilities.wrapHTML(details, 90); 1231 1232 JEditorPane wrappedPane = Utilities.makeHtmlPane(null, pane.getFont()); 1233 String wrappedText; 1234 switch (type) 1235 { 1236 case ERROR: 1237 wrappedText = Utilities.getFormattedError(wrappedTitle, titleFont, wrappedDetails, detailsFont); 1238 break; 1239 default: 1240 wrappedText = Utilities.getFormattedSuccess(wrappedTitle, titleFont, wrappedDetails, detailsFont); 1241 break; 1242 } 1243 wrappedPane.setText(wrappedText); 1244 Dimension d = wrappedPane.getPreferredSize(); 1245 1246 pane.setText(text); 1247 pane.setPreferredSize(d); 1248 1249 lastDisplayedError = text; 1250 } 1251 final Window window = Utilities.getParentDialog(StatusGenericPanel.this); 1252 if (window != null) 1253 { 1254 SwingUtilities.invokeLater(new Runnable() 1255 { 1256 @Override 1257 public void run() 1258 { 1259 pane.invalidate(); 1260 window.validate(); 1261 } 1262 }); 1263 } 1264 } 1265 1266 private String getText( 1267 PanelType type, LocalizableMessage title, Font titleFont, LocalizableMessage details, Font detailsFont) 1268 { 1269 switch (type) 1270 { 1271 case ERROR: 1272 return Utilities.getFormattedError(title, titleFont, details, detailsFont); 1273 case CONFIRMATION: 1274 return Utilities.getFormattedConfirmation(title, titleFont, details, detailsFont); 1275 case WARNING: 1276 return Utilities.getFormattedWarning(title, titleFont, details, detailsFont); 1277 default: 1278 return Utilities.getFormattedSuccess(title, titleFont, details, detailsFont); 1279 } 1280 } 1281 1282 /** 1283 * Commodity method used to update the elements of a combo box that contains 1284 * the different user backends. If no backends are found the combo box will be 1285 * made invisible and a label will be made visible. This method does not 1286 * update the label's text nor creates any layout. 1287 * 1288 * @param combo 1289 * the combo to be updated. 1290 * @param lNoBackendsFound 1291 * the label that must be shown if no user backends are found. 1292 * @param desc 1293 * the server descriptor that contains the configuration. 1294 */ 1295 protected void updateSimpleBackendComboBoxModel(final JComboBox combo, final JLabel lNoBackendsFound, 1296 final ServerDescriptor desc) 1297 { 1298 final SortedSet<String> newElements = new TreeSet<>(new LowerCaseComparator()); 1299 for (BackendDescriptor backend : desc.getBackends()) 1300 { 1301 if (!backend.isConfigBackend()) 1302 { 1303 newElements.add(backend.getBackendID()); 1304 } 1305 } 1306 DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel(); 1307 updateComboBoxModel(newElements, model); 1308 SwingUtilities.invokeLater(new Runnable() 1309 { 1310 @Override 1311 public void run() 1312 { 1313 boolean noElems = newElements.isEmpty(); 1314 combo.setVisible(!noElems); 1315 lNoBackendsFound.setVisible(noElems); 1316 } 1317 }); 1318 } 1319 1320 /** 1321 * Method that says if a backend must be displayed. Only non-config backends 1322 * are displayed. 1323 * 1324 * @param backend 1325 * the backend. 1326 * @return <CODE>true</CODE> if the backend must be displayed and 1327 * <CODE>false</CODE> otherwise. 1328 */ 1329 protected boolean displayBackend(final BackendDescriptor backend) 1330 { 1331 return !backend.isConfigBackend(); 1332 } 1333 1334 /** 1335 * Commodity method to update a combo box model with the backends of a server. 1336 * 1337 * @param model 1338 * the combo box model to be updated. 1339 * @param desc 1340 * the server descriptor containing the configuration. 1341 */ 1342 protected void updateBaseDNComboBoxModel(final DefaultComboBoxModel model, final ServerDescriptor desc) 1343 { 1344 Set<CategorizedComboBoxElement> newElements = new LinkedHashSet<>(); 1345 SortedSet<String> backendIDs = new TreeSet<>(new LowerCaseComparator()); 1346 Map<String, SortedSet<String>> hmBaseDNs = new HashMap<>(); 1347 1348 for (BackendDescriptor backend : desc.getBackends()) 1349 { 1350 if (displayBackend(backend)) 1351 { 1352 String backendID = backend.getBackendID(); 1353 backendIDs.add(backendID); 1354 SortedSet<String> baseDNs = new TreeSet<>(new LowerCaseComparator()); 1355 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 1356 { 1357 try 1358 { 1359 baseDNs.add(Utilities.unescapeUtf8(baseDN.getDn().toString())); 1360 } 1361 catch (Throwable t) 1362 { 1363 throw new RuntimeException("Unexpected error: " + t, t); 1364 } 1365 } 1366 hmBaseDNs.put(backendID, baseDNs); 1367 } 1368 } 1369 1370 for (String backendID : backendIDs) 1371 { 1372 newElements.add(new CategorizedComboBoxElement(backendID, CategorizedComboBoxElement.Type.CATEGORY)); 1373 SortedSet<String> baseDNs = hmBaseDNs.get(backendID); 1374 for (String baseDN : baseDNs) 1375 { 1376 newElements.add(new CategorizedComboBoxElement(baseDN, CategorizedComboBoxElement.Type.REGULAR)); 1377 } 1378 } 1379 updateComboBoxModel(newElements, model); 1380 } 1381 1382 /** 1383 * Updates a combo box model with a number of items. 1384 * 1385 * @param newElements 1386 * the new items for the combo box model. 1387 * @param model 1388 * the combo box model to be updated. 1389 */ 1390 protected void updateComboBoxModel(final Collection<?> newElements, final DefaultComboBoxModel model) 1391 { 1392 updateComboBoxModel(newElements, model, null); 1393 } 1394 1395 /** 1396 * Updates a combo box model with a number of items. The method assumes that 1397 * is called outside the event thread. 1398 * 1399 * @param newElements 1400 * the new items for the combo box model. 1401 * @param model 1402 * the combo box model to be updated. 1403 * @param comparator 1404 * the object that will be used to compare the objects in the model. 1405 * If <CODE>null</CODE>, the equals method will be used. 1406 */ 1407 private void updateComboBoxModel(final Collection<?> newElements, final DefaultComboBoxModel model, 1408 final Comparator<Object> comparator) 1409 { 1410 SwingUtilities.invokeLater(new Runnable() 1411 { 1412 @Override 1413 public void run() 1414 { 1415 Utilities.updateComboBoxModel(newElements, model, comparator); 1416 } 1417 }); 1418 } 1419 1420 /** 1421 * Updates a map, so that the keys are the base DN where the indexes are 1422 * defined and the values are a sorted set of indexes. 1423 * 1424 * @param desc 1425 * the server descriptor containing the index configuration. 1426 * @param hmIndexes 1427 * the map to be updated. 1428 */ 1429 protected void updateIndexMap( 1430 final ServerDescriptor desc, final Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes) 1431 { 1432 synchronized (hmIndexes) 1433 { 1434 Set<String> dns = new HashSet<>(); 1435 for (BackendDescriptor backend : desc.getBackends()) 1436 { 1437 if (backend.getType() == BackendDescriptor.Type.LOCAL_DB 1438 || backend.getType() == BackendDescriptor.Type.PLUGGABLE) 1439 { 1440 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 1441 { 1442 String dn; 1443 try 1444 { 1445 dn = Utilities.unescapeUtf8(baseDN.getDn().toString()); 1446 } 1447 catch (Throwable t) 1448 { 1449 throw new RuntimeException("Unexpected error: " + t, t); 1450 } 1451 dns.add(dn); 1452 SortedSet<AbstractIndexDescriptor> indexes = new TreeSet<AbstractIndexDescriptor>(backend.getIndexes()); 1453 indexes.addAll(backend.getVLVIndexes()); 1454 SortedSet<AbstractIndexDescriptor> currentIndexes = hmIndexes.get(dn); 1455 if (currentIndexes != null) 1456 { 1457 if (!currentIndexes.equals(indexes)) 1458 { 1459 hmIndexes.put(dn, indexes); 1460 } 1461 } 1462 else 1463 { 1464 hmIndexes.put(dn, indexes); 1465 } 1466 } 1467 } 1468 } 1469 for (String dn : new HashSet<String>(hmIndexes.keySet())) 1470 { 1471 if (!dns.contains(dn)) 1472 { 1473 hmIndexes.remove(dn); 1474 } 1475 } 1476 } 1477 } 1478 1479 /** 1480 * Updates and addremove panel with the contents of the provided item. The 1481 * selected item represents a base DN. 1482 * 1483 * @param hmIndexes 1484 * the map that contains the indexes definitions as values and the 1485 * base DNs as keys. 1486 * @param selectedItem 1487 * the selected item. 1488 * @param addRemove 1489 * the add remove panel to be updated. 1490 */ 1491 protected void comboBoxSelected(final Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes, 1492 final CategorizedComboBoxElement selectedItem, final AddRemovePanel<AbstractIndexDescriptor> addRemove) 1493 { 1494 synchronized (hmIndexes) 1495 { 1496 String selectedDn = null; 1497 if (selectedItem != null) 1498 { 1499 selectedDn = (String) selectedItem.getValue(); 1500 } 1501 if (selectedDn != null) 1502 { 1503 SortedSet<AbstractIndexDescriptor> indexes = hmIndexes.get(selectedDn); 1504 if (indexes != null) 1505 { 1506 boolean availableChanged = false; 1507 boolean selectedChanged = false; 1508 SortableListModel<AbstractIndexDescriptor> availableListModel = addRemove.getAvailableListModel(); 1509 SortableListModel<AbstractIndexDescriptor> selectedListModel = addRemove.getSelectedListModel(); 1510 SortedSet<AbstractIndexDescriptor> availableIndexes = availableListModel.getData(); 1511 SortedSet<AbstractIndexDescriptor> selectedIndexes = selectedListModel.getData(); 1512 availableChanged = availableIndexes.retainAll(indexes); 1513 selectedChanged = selectedIndexes.retainAll(indexes); 1514 1515 for (AbstractIndexDescriptor index : indexes) 1516 { 1517 if (!availableIndexes.contains(index) && !selectedIndexes.contains(index)) 1518 { 1519 availableIndexes.add(index); 1520 availableChanged = true; 1521 } 1522 } 1523 if (availableChanged) 1524 { 1525 availableListModel.clear(); 1526 availableListModel.addAll(availableIndexes); 1527 availableListModel.fireContentsChanged(availableListModel, 0, availableListModel.getSize()); 1528 } 1529 if (selectedChanged) 1530 { 1531 selectedListModel.clear(); 1532 selectedListModel.addAll(selectedIndexes); 1533 selectedListModel.fireContentsChanged(selectedListModel, 0, selectedListModel.getSize()); 1534 } 1535 } 1536 } 1537 } 1538 } 1539 1540 /** 1541 * Returns <CODE>true</CODE> if the cancel button is enabled and 1542 * <CODE>false</CODE> otherwise. 1543 * 1544 * @return <CODE>true</CODE> if the cancel button is enabled and 1545 * <CODE>false</CODE> otherwise. 1546 */ 1547 public boolean isEnableCancel() 1548 { 1549 return enableCancel; 1550 } 1551 1552 /** 1553 * Returns <CODE>true</CODE> if the close button is enabled and 1554 * <CODE>false</CODE> otherwise. 1555 * 1556 * @return <CODE>true</CODE> if the close button is enabled and 1557 * <CODE>false</CODE> otherwise. 1558 */ 1559 public boolean isEnableClose() 1560 { 1561 return enableClose; 1562 } 1563 1564 /** 1565 * Returns <CODE>true</CODE> if the ok button is enabled and 1566 * <CODE>false</CODE> otherwise. 1567 * 1568 * @return <CODE>true</CODE> if the ok button is enabled and 1569 * <CODE>false</CODE> otherwise. 1570 */ 1571 public boolean isEnableOK() 1572 { 1573 return enableOK; 1574 } 1575 1576 /** 1577 * Returns <CODE>true</CODE> if the server is running and <CODE>false</CODE> 1578 * otherwise. 1579 * 1580 * @return <CODE>true</CODE> if the server is running and <CODE>false</CODE> 1581 * otherwise. 1582 */ 1583 protected boolean isServerRunning() 1584 { 1585 return getInfo().getServerDescriptor().getStatus() == ServerDescriptor.ServerStatus.STARTED; 1586 } 1587 1588 /** 1589 * Returns <CODE>true</CODE> if the managed server is the local installation 1590 * (where the control panel is installed) <CODE>false</CODE> otherwise. 1591 * 1592 * @return <CODE>true</CODE> if the managed server is the local installation 1593 * (where the control panel is installed) <CODE>false</CODE> 1594 * otherwise. 1595 */ 1596 protected boolean isLocal() 1597 { 1598 return getInfo().getServerDescriptor().isLocal(); 1599 } 1600 1601 /** 1602 * Launch an task. 1603 * 1604 * @param task 1605 * the task to be launched. 1606 * @param initialSummary 1607 * the initial summary to be displayed in the progress dialog. 1608 * @param successSummary 1609 * the success summary to be displayed in the progress dialog if the 1610 * task is successful. 1611 * @param successDetail 1612 * the success details to be displayed in the progress dialog if the 1613 * task is successful. 1614 * @param errorSummary 1615 * the error summary to be displayed in the progress dialog if the 1616 * task ended with error. 1617 * @param errorDetail 1618 * error details to be displayed in the progress dialog if the task 1619 * ended with error. 1620 * @param errorDetailCode 1621 * error detail message to be displayed in the progress dialog if the 1622 * task ended with error and we have an exit error code (for instance 1623 * if the error occurred when launching a script we will have an 1624 * error code). 1625 * @param dialog 1626 * the progress dialog. 1627 */ 1628 protected void launchOperation(final Task task, final LocalizableMessage initialSummary, 1629 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1630 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1631 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog) 1632 { 1633 launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, 1634 dialog, true); 1635 } 1636 1637 /** 1638 * Launch an task. 1639 * 1640 * @param task 1641 * the task to be launched. 1642 * @param initialSummary 1643 * the initial summary to be displayed in the progress dialog. 1644 * @param successSummary 1645 * the success summary to be displayed in the progress dialog if the 1646 * task is successful. 1647 * @param successDetail 1648 * the success details to be displayed in the progress dialog if the 1649 * task is successful. 1650 * @param errorSummary 1651 * the error summary to be displayed in the progress dialog if the 1652 * task ended with error. 1653 * @param errorDetail 1654 * error details to be displayed in the progress dialog if the task 1655 * ended with error. 1656 * @param errorDetailCode 1657 * error detail message to be displayed in the progress dialog if the 1658 * task ended with error and we have an exit error code (for instance 1659 * if the error occurred when launching a script we will have an 1660 * error code). 1661 * @param dialog 1662 * the progress dialog. 1663 * @param resetLogs 1664 * whether the contents of the progress dialog should be reset or 1665 * not. 1666 */ 1667 private void launchOperation(final Task task, final LocalizableMessage initialSummary, 1668 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1669 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1670 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog, 1671 final boolean resetLogs) 1672 { 1673 launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, 1674 dialog, resetLogs, getInfo()); 1675 } 1676 1677 /** 1678 * Launch an task. 1679 * 1680 * @param task 1681 * the task to be launched. 1682 * @param initialSummary 1683 * the initial summary to be displayed in the progress dialog. 1684 * @param successSummary 1685 * the success summary to be displayed in the progress dialog if the 1686 * task is successful. 1687 * @param successDetail 1688 * the success details to be displayed in the progress dialog if the 1689 * task is successful. 1690 * @param errorSummary 1691 * the error summary to be displayed in the progress dialog if the 1692 * task ended with error. 1693 * @param errorDetail 1694 * error details to be displayed in the progress dialog if the task 1695 * ended with error. 1696 * @param errorDetailCode 1697 * error detail message to be displayed in the progress dialog if the 1698 * task ended with error and we have an exit error code (for instance 1699 * if the error occurred when launching a script we will have an 1700 * error code). 1701 * @param dialog 1702 * the progress dialog. 1703 * @param resetLogs 1704 * whether the contents of the progress dialog should be reset or 1705 * not. 1706 * @param info 1707 * the ControlPanelInfo. 1708 */ 1709 public static void launchOperation(final Task task, final LocalizableMessage initialSummary, 1710 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1711 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1712 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog, 1713 final boolean resetLogs, final ControlPanelInfo info) 1714 { 1715 dialog.setTaskIsOver(false); 1716 dialog.getProgressBar().setIndeterminate(true); 1717 dialog.addPrintStreamListeners(task.getOutPrintStream(), task.getErrorPrintStream()); 1718 if (resetLogs) 1719 { 1720 dialog.resetProgressLogs(); 1721 } 1722 String cmdLine = task.getCommandLineToDisplay(); 1723 if (cmdLine != null) 1724 { 1725 dialog.appendProgressHtml(Utilities.applyFont(INFO_CTRL_PANEL_EQUIVALENT_COMMAND_LINE.get() + "<br><b>" + cmdLine 1726 + "</b><br><br>", ColorAndFontConstants.progressFont)); 1727 } 1728 dialog.setEnabledClose(false); 1729 dialog.setSummary(LocalizableMessage.raw(Utilities.applyFont(initialSummary.toString(), 1730 ColorAndFontConstants.defaultFont))); 1731 dialog.getProgressBar().setVisible(true); 1732 BackgroundTask<Task> worker = new BackgroundTask<Task>() 1733 { 1734 @Override 1735 public Task processBackgroundTask() throws Throwable 1736 { 1737 task.runTask(); 1738 if (task.regenerateDescriptor()) 1739 { 1740 info.regenerateDescriptor(); 1741 } 1742 return task; 1743 } 1744 1745 @Override 1746 public void backgroundTaskCompleted(final Task returnValue, Throwable t) 1747 { 1748 String summaryMsg; 1749 if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) 1750 { 1751 summaryMsg = 1752 Utilities.getFormattedSuccess(successSummary, ColorAndFontConstants.errorTitleFont, successDetail, 1753 ColorAndFontConstants.defaultFont); 1754 } 1755 else 1756 { 1757 if (t == null) 1758 { 1759 t = task.getLastException(); 1760 } 1761 1762 if (t != null) 1763 { 1764 logger.warn(LocalizableMessage.raw("Error occurred running task: " + t, t)); 1765 if (task.getReturnCode() != null && errorDetailCode != null) 1766 { 1767 String sThrowable; 1768 if (t instanceof OpenDsException) 1769 { 1770 sThrowable = ((OpenDsException) t).getMessageObject().toString(); 1771 } 1772 else if (t.getMessage() != null) 1773 { 1774 sThrowable = t.getMessage(); 1775 } 1776 else 1777 { 1778 sThrowable = t.toString(); 1779 } 1780 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1781 mb.append(errorDetailCode.get(task.getReturnCode())); 1782 mb.append(" ").append(INFO_CTRL_PANEL_DETAILS_THROWABLE.get(sThrowable)); 1783 summaryMsg = 1784 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), 1785 ColorAndFontConstants.defaultFont); 1786 } 1787 else if (errorDetail != null) 1788 { 1789 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1790 mb.append(errorDetail); 1791 mb.append(INFO_CTRL_PANEL_DETAILS_THROWABLE.get(t)); 1792 summaryMsg = 1793 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), 1794 ColorAndFontConstants.defaultFont); 1795 } 1796 else 1797 { 1798 summaryMsg = null; 1799 } 1800 } 1801 else if (task.getReturnCode() != null && errorDetailCode != null) 1802 { 1803 summaryMsg = 1804 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetailCode 1805 .get(task.getReturnCode()), ColorAndFontConstants.defaultFont); 1806 } 1807 else if (errorDetail != null) 1808 { 1809 summaryMsg = 1810 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetail, 1811 ColorAndFontConstants.defaultFont); 1812 } 1813 else 1814 { 1815 summaryMsg = null; 1816 } 1817 } 1818 if (summaryMsg != null) 1819 { 1820 dialog.setSummary(LocalizableMessage.raw(summaryMsg)); 1821 } 1822 dialog.setEnabledClose(true); 1823 dialog.getProgressBar().setVisible(false); 1824 if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) 1825 { 1826 dialog.setTaskIsOver(true); 1827 } 1828 task.postOperation(); 1829 } 1830 }; 1831 info.registerTask(task); 1832 worker.startBackgroundTask(); 1833 } 1834 1835 /** 1836 * Checks that the provided string value is a valid integer and if it is not 1837 * updates a list of error messages with an error. 1838 * 1839 * @param errors 1840 * the list of error messages to be updated. 1841 * @param stringValue 1842 * the string value to analyze. 1843 * @param minValue 1844 * the minimum integer value accepted. 1845 * @param maxValue 1846 * the maximum integer value accepted. 1847 * @param errMsg 1848 * the error message to use to update the error list if the provided 1849 * value is not valid. 1850 * @return {@code true} if the provided string value is a valid integer and if 1851 * it is not updates a list of error messages with an error. 1852 */ 1853 protected boolean checkIntValue(final Collection<LocalizableMessage> errors, final String stringValue, 1854 final int minValue, final int maxValue, final LocalizableMessage errMsg) 1855 { 1856 try 1857 { 1858 int n = Integer.parseInt(stringValue); 1859 if (minValue <= n && n <= maxValue) 1860 { 1861 return true; 1862 } 1863 } 1864 catch (NumberFormatException ignored) 1865 { 1866 } 1867 1868 errors.add(errMsg); 1869 return false; 1870 } 1871 1872 /** 1873 * Starts the server. This method will launch a task and open a progress 1874 * dialog that will start the server. This method must be called from the 1875 * event thread. 1876 */ 1877 protected void startServer() 1878 { 1879 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1880 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1881 INFO_CTRL_PANEL_START_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1882 StartServerTask newTask = new StartServerTask(getInfo(), progressDialog); 1883 for (Task task : getInfo().getTasks()) 1884 { 1885 task.canLaunch(newTask, errors); 1886 } 1887 if (errors.isEmpty()) 1888 { 1889 launchOperation(newTask, 1890 INFO_CTRL_PANEL_STARTING_SERVER_SUMMARY.get(), 1891 INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_SUMMARY.get(), 1892 INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_DETAILS.get(), 1893 ERR_CTRL_PANEL_STARTING_SERVER_ERROR_SUMMARY.get(), null, 1894 ERR_CTRL_PANEL_STARTING_SERVER_ERROR_DETAILS, progressDialog); 1895 progressDialog.setVisible(true); 1896 } 1897 else 1898 { 1899 displayErrorDialog(errors); 1900 } 1901 } 1902 1903 /** 1904 * Stops the server. This method will launch a task and open a progress dialog 1905 * that will stop the server. This method must be called from the event 1906 * thread. 1907 */ 1908 protected void stopServer() 1909 { 1910 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1911 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1912 INFO_CTRL_PANEL_STOP_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1913 StopServerTask newTask = new StopServerTask(getInfo(), progressDialog); 1914 for (Task task : getInfo().getTasks()) 1915 { 1916 task.canLaunch(newTask, errors); 1917 } 1918 boolean confirmed = true; 1919 if (errors.isEmpty()) 1920 { 1921 confirmed = displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 1922 INFO_CTRL_PANEL_CONFIRM_STOP_SERVER_DETAILS.get()); 1923 } 1924 if (errors.isEmpty() && confirmed) 1925 { 1926 launchOperation(newTask, 1927 INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), 1928 INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_SUMMARY.get(), 1929 INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_DETAILS.get(), 1930 ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_SUMMARY.get(), null, 1931 ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_DETAILS, progressDialog); 1932 progressDialog.setVisible(true); 1933 } 1934 if (!errors.isEmpty()) 1935 { 1936 displayErrorDialog(errors); 1937 } 1938 } 1939 1940 /** 1941 * Restarts the server. This method will launch a task and open a progress 1942 * dialog that will restart the server. This method must be called from the 1943 * event thread. 1944 */ 1945 protected void restartServer() 1946 { 1947 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1948 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1949 INFO_CTRL_PANEL_RESTART_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1950 RestartServerTask newTask = new RestartServerTask(getInfo(), progressDialog); 1951 for (Task task : getInfo().getTasks()) 1952 { 1953 task.canLaunch(newTask, errors); 1954 } 1955 boolean confirmed = true; 1956 if (errors.isEmpty()) 1957 { 1958 confirmed = displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 1959 INFO_CTRL_PANEL_CONFIRM_RESTART_SERVER_DETAILS.get()); 1960 } 1961 if (errors.isEmpty() && confirmed) 1962 { 1963 launchOperation(newTask, 1964 INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), 1965 INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_SUMMARY.get(), 1966 INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_DETAILS.get(), 1967 ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_SUMMARY.get(), null, 1968 ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_DETAILS, progressDialog); 1969 progressDialog.setVisible(true); 1970 } 1971 if (!errors.isEmpty()) 1972 { 1973 displayErrorDialog(errors); 1974 } 1975 } 1976 1977 /** 1978 * Displays a dialog asking for authentication. This method must be called 1979 * from the event thread. 1980 */ 1981 private void authenticate() 1982 { 1983 if (!getLoginDialog().isVisible()) 1984 { 1985 getLoginDialog().setVisible(true); 1986 } 1987 getLoginDialog().toFront(); 1988 } 1989 1990 /** 1991 * Returns the login dialog that is displayed when the method authenticate is 1992 * called. 1993 * 1994 * @return the login dialog that is displayed when the method authenticate is 1995 * called. 1996 */ 1997 protected GenericDialog getLoginDialog() 1998 { 1999 GenericDialog dialog = isLocal() ? getLocalServerLoginDialog(getInfo()) : getLocalOrRemoteDialog(getInfo()); 2000 Utilities.centerGoldenMean(dialog, Utilities.getFrame(this)); 2001 dialog.setModal(true); 2002 return dialog; 2003 } 2004 2005 /** 2006 * Tells whether an entry exists or not. Actually it tells if we could find a 2007 * given entry or not. 2008 * 2009 * @param dn 2010 * the DN of the entry to look for. 2011 * @return <CODE>true</CODE> if the entry with the provided DN could be found 2012 * and <CODE>false</CODE> otherwise. 2013 */ 2014 protected boolean entryExists(final String dn) 2015 { 2016 boolean entryExists = false; 2017 try 2018 { 2019 SearchControls ctls = new SearchControls(); 2020 ctls.setSearchScope(SearchControls.OBJECT_SCOPE); 2021 ctls.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES }); 2022 String filter = BrowserController.ALL_OBJECTS_FILTER; 2023 NamingEnumeration<SearchResult> result = 2024 getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); 2025 2026 try 2027 { 2028 while (result.hasMore()) 2029 { 2030 SearchResult sr = result.next(); 2031 entryExists = sr != null; 2032 } 2033 } 2034 finally 2035 { 2036 result.close(); 2037 } 2038 } 2039 catch (Throwable t) 2040 { 2041 } 2042 return entryExists; 2043 } 2044 2045 /** 2046 * Tells whether a given entry exists and contains one of the specified object 2047 * classes. 2048 * 2049 * @param dn 2050 * the DN of the entry. 2051 * @param objectClasses 2052 * the object classes to check. 2053 * @return <CODE>true</CODE> if the entry exists and contains one of the 2054 * specified object classes and <CODE>false</CODE> otherwise. 2055 */ 2056 protected boolean hasObjectClass(final String dn, final String... objectClasses) 2057 { 2058 try 2059 { 2060 SearchControls ctls = new SearchControls(); 2061 ctls.setSearchScope(SearchControls.OBJECT_SCOPE); 2062 ctls.setReturningAttributes(new String[] { ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME }); 2063 String filter = BrowserController.ALL_OBJECTS_FILTER; 2064 NamingEnumeration<SearchResult> result = 2065 getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); 2066 2067 try 2068 { 2069 while (result.hasMore()) 2070 { 2071 SearchResult sr = result.next(); 2072 Set<String> values = ConnectionUtils.getValues(sr, ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME); 2073 if (values != null) 2074 { 2075 for (String s : values) 2076 { 2077 for (String objectClass : objectClasses) 2078 { 2079 if (s.equalsIgnoreCase(objectClass)) 2080 { 2081 return true; 2082 } 2083 } 2084 } 2085 } 2086 } 2087 } 2088 finally 2089 { 2090 result.close(); 2091 } 2092 } 2093 catch (Throwable t) 2094 { 2095 } 2096 return false; 2097 } 2098 2099 /** 2100 * Returns the border to be used in the right panel of the dialog with a tree 2101 * on the left (for instance the schema browser, entry browser and index 2102 * browser). 2103 * 2104 * @return the border to be used in the right panel. 2105 */ 2106 protected Border getRightPanelBorder() 2107 { 2108 return ColorAndFontConstants.textAreaBorder; 2109 } 2110 2111 /** 2112 * Returns the monitoring value in a String form to be displayed to the user. 2113 * 2114 * @param attr 2115 * the attribute to analyze. 2116 * @param monitoringEntry 2117 * the monitoring entry. 2118 * @return the monitoring value in a String form to be displayed to the user. 2119 */ 2120 public static String getMonitoringValue(final MonitoringAttributes attr, final CustomSearchResult monitoringEntry) 2121 { 2122 return Utilities.getMonitoringValue(attr, monitoringEntry); 2123 } 2124 2125 /** 2126 * Updates the monitoring information writing it to a list of labels. 2127 * 2128 * @param monitoringAttrs 2129 * the monitoring operations whose information we want to update. 2130 * @param monitoringLabels 2131 * the monitoring labels to be updated. 2132 * @param monitoringEntry 2133 * the monitoring entry containing the information to be displayed. 2134 */ 2135 protected void updateMonitoringInfo(final List<MonitoringAttributes> monitoringAttrs, 2136 final List<JLabel> monitoringLabels, final CustomSearchResult monitoringEntry) 2137 { 2138 for (int i = 0; i < monitoringAttrs.size(); i++) 2139 { 2140 String value = getMonitoringValue(monitoringAttrs.get(i), monitoringEntry); 2141 JLabel l = monitoringLabels.get(i); 2142 l.setText(value); 2143 } 2144 } 2145 2146 /** 2147 * Returns the label to be used in panels (with ':') based on the definition 2148 * of the monitoring attribute. 2149 * 2150 * @param attr 2151 * the monitoring attribute. 2152 * @return the label to be used in panels (with ':') based on the definition 2153 * of the monitoring attribute. 2154 */ 2155 protected static LocalizableMessage getLabel(final MonitoringAttributes attr) 2156 { 2157 return INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(attr.getMessage()); 2158 } 2159 2160 /** 2161 * Returns the command-line arguments associated with the provided schedule. 2162 * 2163 * @param schedule 2164 * the schedule. 2165 * @return the command-line arguments associated with the provided schedule. 2166 */ 2167 protected List<String> getScheduleArgs(final ScheduleType schedule) 2168 { 2169 List<String> args = new ArrayList<>(2); 2170 switch (schedule.getType()) 2171 { 2172 case LAUNCH_LATER: 2173 args.add("--start"); 2174 args.add(getStartTimeForTask(schedule.getLaunchLaterDate())); 2175 break; 2176 case LAUNCH_PERIODICALLY: 2177 args.add("--recurringTask"); 2178 args.add(schedule.getCronValue()); 2179 break; 2180 } 2181 return args; 2182 } 2183 2184 /** 2185 * Checks whether the server is running or not and depending on the schedule 2186 * updates the list of errors with the errors found. 2187 * 2188 * @param schedule 2189 * the schedule. 2190 * @param errors 2191 * the list of errors. 2192 * @param label 2193 * the label to be marked as invalid if errors where encountered. 2194 */ 2195 protected void addScheduleErrors(final ScheduleType schedule, final Collection<LocalizableMessage> errors, 2196 final JLabel label) 2197 { 2198 if (!isServerRunning()) 2199 { 2200 ScheduleType.Type type = schedule.getType(); 2201 if (type == ScheduleType.Type.LAUNCH_LATER) 2202 { 2203 errors.add(ERR_CTRL_PANEL_LAUNCH_LATER_REQUIRES_SERVER_RUNNING.get()); 2204 setPrimaryInvalid(label); 2205 } 2206 else if (type == ScheduleType.Type.LAUNCH_PERIODICALLY) 2207 { 2208 errors.add(ERR_CTRL_PANEL_LAUNCH_SCHEDULE_REQUIRES_SERVER_RUNNING.get()); 2209 setPrimaryInvalid(label); 2210 } 2211 } 2212 } 2213 2214 private String getStartTimeForTask(final Date date) 2215 { 2216 return taskDateFormat.format(date); 2217 } 2218 2219 /** 2220 * Checks whether the provided superior object classes are compatible with the 2221 * provided object class type. If not, the method updates the provided list of 2222 * error messages with a message describing the incompatibility. 2223 * 2224 * @param objectClassSuperiors 2225 * the superior object classes. 2226 * @param objectClassType 2227 * the object class type. 2228 * @param errors 2229 * the list of error messages. 2230 */ 2231 protected void checkCompatibleSuperiors(final Set<ObjectClass> objectClassSuperiors, 2232 final ObjectClassType objectClassType, final List<LocalizableMessage> errors) 2233 { 2234 SortedSet<String> notCompatibleClasses = new TreeSet<>(new LowerCaseComparator()); 2235 for (ObjectClass oc : objectClassSuperiors) 2236 { 2237 if (oc.getObjectClassType() == ObjectClassType.ABSTRACT) 2238 { 2239 // Nothing to do. 2240 } 2241 else if (oc.getObjectClassType() != objectClassType) 2242 { 2243 notCompatibleClasses.add(oc.getNameOrOID()); 2244 } 2245 } 2246 if (!notCompatibleClasses.isEmpty()) 2247 { 2248 String arg = Utilities.getStringFromCollection(notCompatibleClasses, ", "); 2249 if (objectClassType == ObjectClassType.STRUCTURAL) 2250 { 2251 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_STRUCTURAL.get(arg)); 2252 } 2253 else if (objectClassType == ObjectClassType.AUXILIARY) 2254 { 2255 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_AUXILIARY.get(arg)); 2256 } 2257 else if (objectClassType == ObjectClassType.ABSTRACT) 2258 { 2259 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_ABSTRACT.get(arg)); 2260 } 2261 } 2262 } 2263}