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 static org.opends.guitools.controlpanel.ui.ControlCenterMainPane.*; 030import static org.opends.messages.AdminToolMessages.*; 031 032import java.awt.CardLayout; 033import java.awt.Color; 034import java.awt.Component; 035import java.awt.Container; 036import java.awt.Dimension; 037import java.awt.Font; 038import java.awt.GridBagConstraints; 039import java.awt.GridBagLayout; 040import java.awt.Insets; 041import java.awt.Window; 042import java.awt.event.ActionEvent; 043import java.awt.event.ActionListener; 044import java.awt.event.ItemEvent; 045import java.awt.event.ItemListener; 046import java.text.DateFormat; 047import java.text.SimpleDateFormat; 048import java.util.ArrayList; 049import java.util.Collection; 050import java.util.Comparator; 051import java.util.Date; 052import java.util.HashMap; 053import java.util.HashSet; 054import java.util.LinkedHashSet; 055import java.util.List; 056import java.util.Map; 057import java.util.Set; 058import java.util.SortedSet; 059import java.util.TreeSet; 060 061import javax.naming.NamingEnumeration; 062import javax.naming.directory.SearchControls; 063import javax.naming.directory.SearchResult; 064import javax.swing.Box; 065import javax.swing.ComboBoxModel; 066import javax.swing.DefaultComboBoxModel; 067import javax.swing.JComboBox; 068import javax.swing.JComponent; 069import javax.swing.JEditorPane; 070import javax.swing.JLabel; 071import javax.swing.JMenuBar; 072import javax.swing.JPanel; 073import javax.swing.SwingUtilities; 074import javax.swing.border.Border; 075 076import org.forgerock.i18n.LocalizableMessage; 077import org.forgerock.i18n.LocalizableMessageBuilder; 078import org.forgerock.i18n.LocalizableMessageDescriptor; 079import org.forgerock.i18n.slf4j.LocalizedLogger; 080import org.forgerock.opendj.ldap.schema.ObjectClassType; 081import org.opends.admin.ads.util.ConnectionUtils; 082import org.opends.guitools.controlpanel.browser.BrowserController; 083import org.opends.guitools.controlpanel.browser.IconPool; 084import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 085import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 086import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; 087import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; 088import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 089import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 090import org.opends.guitools.controlpanel.datamodel.MonitoringAttributes; 091import org.opends.guitools.controlpanel.datamodel.ScheduleType; 092import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 093import org.opends.guitools.controlpanel.datamodel.SortableListModel; 094import org.opends.guitools.controlpanel.event.ConfigChangeListener; 095import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 096import org.opends.guitools.controlpanel.event.ConfigurationElementCreatedListener; 097import org.opends.guitools.controlpanel.task.RebuildIndexTask; 098import org.opends.guitools.controlpanel.task.RestartServerTask; 099import org.opends.guitools.controlpanel.task.StartServerTask; 100import org.opends.guitools.controlpanel.task.StopServerTask; 101import org.opends.guitools.controlpanel.task.Task; 102import org.opends.guitools.controlpanel.ui.components.AddRemovePanel; 103import org.opends.guitools.controlpanel.util.BackgroundTask; 104import org.opends.guitools.controlpanel.util.LowerCaseComparator; 105import org.opends.guitools.controlpanel.util.Utilities; 106import org.opends.quicksetup.ui.CustomHTMLEditorKit; 107import org.opends.server.schema.SchemaConstants; 108import org.opends.server.types.ObjectClass; 109import org.opends.server.types.OpenDsException; 110import org.opends.server.util.ServerConstants; 111import org.opends.server.util.StaticUtils; 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.PLUGGABLE) 1438 { 1439 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 1440 { 1441 String dn; 1442 try 1443 { 1444 dn = Utilities.unescapeUtf8(baseDN.getDn().toString()); 1445 } 1446 catch (Throwable t) 1447 { 1448 throw new RuntimeException("Unexpected error: " + t, t); 1449 } 1450 dns.add(dn); 1451 SortedSet<AbstractIndexDescriptor> indexes = new TreeSet<AbstractIndexDescriptor>(backend.getIndexes()); 1452 indexes.addAll(backend.getVLVIndexes()); 1453 SortedSet<AbstractIndexDescriptor> currentIndexes = hmIndexes.get(dn); 1454 if (currentIndexes != null) 1455 { 1456 if (!currentIndexes.equals(indexes)) 1457 { 1458 hmIndexes.put(dn, indexes); 1459 } 1460 } 1461 else 1462 { 1463 hmIndexes.put(dn, indexes); 1464 } 1465 } 1466 } 1467 } 1468 for (String dn : new HashSet<String>(hmIndexes.keySet())) 1469 { 1470 if (!dns.contains(dn)) 1471 { 1472 hmIndexes.remove(dn); 1473 } 1474 } 1475 } 1476 } 1477 1478 /** 1479 * Updates and addremove panel with the contents of the provided item. The 1480 * selected item represents a base DN. 1481 * 1482 * @param hmIndexes 1483 * the map that contains the indexes definitions as values and the 1484 * base DNs as keys. 1485 * @param selectedItem 1486 * the selected item. 1487 * @param addRemove 1488 * the add remove panel to be updated. 1489 */ 1490 protected void comboBoxSelected(final Map<String, SortedSet<AbstractIndexDescriptor>> hmIndexes, 1491 final CategorizedComboBoxElement selectedItem, final AddRemovePanel<AbstractIndexDescriptor> addRemove) 1492 { 1493 synchronized (hmIndexes) 1494 { 1495 String selectedDn = null; 1496 if (selectedItem != null) 1497 { 1498 selectedDn = (String) selectedItem.getValue(); 1499 } 1500 if (selectedDn != null) 1501 { 1502 SortedSet<AbstractIndexDescriptor> indexes = hmIndexes.get(selectedDn); 1503 if (indexes != null) 1504 { 1505 boolean availableChanged = false; 1506 boolean selectedChanged = false; 1507 SortableListModel<AbstractIndexDescriptor> availableListModel = addRemove.getAvailableListModel(); 1508 SortableListModel<AbstractIndexDescriptor> selectedListModel = addRemove.getSelectedListModel(); 1509 SortedSet<AbstractIndexDescriptor> availableIndexes = availableListModel.getData(); 1510 SortedSet<AbstractIndexDescriptor> selectedIndexes = selectedListModel.getData(); 1511 availableChanged = availableIndexes.retainAll(indexes); 1512 selectedChanged = selectedIndexes.retainAll(indexes); 1513 1514 for (AbstractIndexDescriptor index : indexes) 1515 { 1516 if (!availableIndexes.contains(index) && !selectedIndexes.contains(index)) 1517 { 1518 availableIndexes.add(index); 1519 availableChanged = true; 1520 } 1521 } 1522 if (availableChanged) 1523 { 1524 availableListModel.clear(); 1525 availableListModel.addAll(availableIndexes); 1526 availableListModel.fireContentsChanged(availableListModel, 0, availableListModel.getSize()); 1527 } 1528 if (selectedChanged) 1529 { 1530 selectedListModel.clear(); 1531 selectedListModel.addAll(selectedIndexes); 1532 selectedListModel.fireContentsChanged(selectedListModel, 0, selectedListModel.getSize()); 1533 } 1534 } 1535 } 1536 } 1537 } 1538 1539 /** 1540 * Returns <CODE>true</CODE> if the cancel button is enabled and 1541 * <CODE>false</CODE> otherwise. 1542 * 1543 * @return <CODE>true</CODE> if the cancel button is enabled and 1544 * <CODE>false</CODE> otherwise. 1545 */ 1546 public boolean isEnableCancel() 1547 { 1548 return enableCancel; 1549 } 1550 1551 /** 1552 * Returns <CODE>true</CODE> if the close button is enabled and 1553 * <CODE>false</CODE> otherwise. 1554 * 1555 * @return <CODE>true</CODE> if the close button is enabled and 1556 * <CODE>false</CODE> otherwise. 1557 */ 1558 public boolean isEnableClose() 1559 { 1560 return enableClose; 1561 } 1562 1563 /** 1564 * Returns <CODE>true</CODE> if the ok button is enabled and 1565 * <CODE>false</CODE> otherwise. 1566 * 1567 * @return <CODE>true</CODE> if the ok button is enabled and 1568 * <CODE>false</CODE> otherwise. 1569 */ 1570 public boolean isEnableOK() 1571 { 1572 return enableOK; 1573 } 1574 1575 /** 1576 * Returns <CODE>true</CODE> if the server is running and <CODE>false</CODE> 1577 * otherwise. 1578 * 1579 * @return <CODE>true</CODE> if the server is running and <CODE>false</CODE> 1580 * otherwise. 1581 */ 1582 protected boolean isServerRunning() 1583 { 1584 return getInfo().getServerDescriptor().getStatus() == ServerDescriptor.ServerStatus.STARTED; 1585 } 1586 1587 /** 1588 * Returns <CODE>true</CODE> if the managed server is the local installation 1589 * (where the control panel is installed) <CODE>false</CODE> otherwise. 1590 * 1591 * @return <CODE>true</CODE> if the managed server is the local installation 1592 * (where the control panel is installed) <CODE>false</CODE> 1593 * otherwise. 1594 */ 1595 protected boolean isLocal() 1596 { 1597 return getInfo().getServerDescriptor().isLocal(); 1598 } 1599 1600 /** 1601 * Launch an task. 1602 * 1603 * @param task 1604 * the task to be launched. 1605 * @param initialSummary 1606 * the initial summary to be displayed in the progress dialog. 1607 * @param successSummary 1608 * the success summary to be displayed in the progress dialog if the 1609 * task is successful. 1610 * @param successDetail 1611 * the success details to be displayed in the progress dialog if the 1612 * task is successful. 1613 * @param errorSummary 1614 * the error summary to be displayed in the progress dialog if the 1615 * task ended with error. 1616 * @param errorDetail 1617 * error details to be displayed in the progress dialog if the task 1618 * ended with error. 1619 * @param errorDetailCode 1620 * error detail message to be displayed in the progress dialog if the 1621 * task ended with error and we have an exit error code (for instance 1622 * if the error occurred when launching a script we will have an 1623 * error code). 1624 * @param dialog 1625 * the progress dialog. 1626 */ 1627 protected void launchOperation(final Task task, final LocalizableMessage initialSummary, 1628 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1629 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1630 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog) 1631 { 1632 launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, 1633 dialog, true); 1634 } 1635 1636 /** 1637 * Launch an task. 1638 * 1639 * @param task 1640 * the task to be launched. 1641 * @param initialSummary 1642 * the initial summary to be displayed in the progress dialog. 1643 * @param successSummary 1644 * the success summary to be displayed in the progress dialog if the 1645 * task is successful. 1646 * @param successDetail 1647 * the success details to be displayed in the progress dialog if the 1648 * task is successful. 1649 * @param errorSummary 1650 * the error summary to be displayed in the progress dialog if the 1651 * task ended with error. 1652 * @param errorDetail 1653 * error details to be displayed in the progress dialog if the task 1654 * ended with error. 1655 * @param errorDetailCode 1656 * error detail message to be displayed in the progress dialog if the 1657 * task ended with error and we have an exit error code (for instance 1658 * if the error occurred when launching a script we will have an 1659 * error code). 1660 * @param dialog 1661 * the progress dialog. 1662 * @param resetLogs 1663 * whether the contents of the progress dialog should be reset or 1664 * not. 1665 */ 1666 private void launchOperation(final Task task, final LocalizableMessage initialSummary, 1667 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1668 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1669 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog, 1670 final boolean resetLogs) 1671 { 1672 launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, 1673 dialog, resetLogs, getInfo()); 1674 } 1675 1676 /** 1677 * Launch an task. 1678 * 1679 * @param task 1680 * the task to be launched. 1681 * @param initialSummary 1682 * the initial summary to be displayed in the progress dialog. 1683 * @param successSummary 1684 * the success summary to be displayed in the progress dialog if the 1685 * task is successful. 1686 * @param successDetail 1687 * the success details to be displayed in the progress dialog if the 1688 * task is successful. 1689 * @param errorSummary 1690 * the error summary to be displayed in the progress dialog if the 1691 * task ended with error. 1692 * @param errorDetail 1693 * error details to be displayed in the progress dialog if the task 1694 * ended with error. 1695 * @param errorDetailCode 1696 * error detail message to be displayed in the progress dialog if the 1697 * task ended with error and we have an exit error code (for instance 1698 * if the error occurred when launching a script we will have an 1699 * error code). 1700 * @param dialog 1701 * the progress dialog. 1702 * @param resetLogs 1703 * whether the contents of the progress dialog should be reset or 1704 * not. 1705 * @param info 1706 * the ControlPanelInfo. 1707 */ 1708 public static void launchOperation(final Task task, final LocalizableMessage initialSummary, 1709 final LocalizableMessage successSummary, final LocalizableMessage successDetail, 1710 final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, 1711 final LocalizableMessageDescriptor.Arg1<Number> errorDetailCode, final ProgressDialog dialog, 1712 final boolean resetLogs, final ControlPanelInfo info) 1713 { 1714 dialog.setTaskIsOver(false); 1715 dialog.getProgressBar().setIndeterminate(true); 1716 dialog.addPrintStreamListeners(task.getOutPrintStream(), task.getErrorPrintStream()); 1717 if (resetLogs) 1718 { 1719 dialog.resetProgressLogs(); 1720 } 1721 String cmdLine = task.getCommandLineToDisplay(); 1722 if (cmdLine != null) 1723 { 1724 dialog.appendProgressHtml(Utilities.applyFont(INFO_CTRL_PANEL_EQUIVALENT_COMMAND_LINE.get() + "<br><b>" + cmdLine 1725 + "</b><br><br>", ColorAndFontConstants.progressFont)); 1726 } 1727 dialog.setEnabledClose(false); 1728 dialog.setSummary(LocalizableMessage.raw(Utilities.applyFont(initialSummary.toString(), 1729 ColorAndFontConstants.defaultFont))); 1730 dialog.getProgressBar().setVisible(true); 1731 BackgroundTask<Task> worker = new BackgroundTask<Task>() 1732 { 1733 @Override 1734 public Task processBackgroundTask() throws Throwable 1735 { 1736 task.runTask(); 1737 if (task.regenerateDescriptor()) 1738 { 1739 info.regenerateDescriptor(); 1740 } 1741 return task; 1742 } 1743 1744 @Override 1745 public void backgroundTaskCompleted(final Task returnValue, Throwable t) 1746 { 1747 String summaryMsg; 1748 if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) 1749 { 1750 summaryMsg = 1751 Utilities.getFormattedSuccess(successSummary, ColorAndFontConstants.errorTitleFont, successDetail, 1752 ColorAndFontConstants.defaultFont); 1753 } 1754 else 1755 { 1756 if (t == null) 1757 { 1758 t = task.getLastException(); 1759 } 1760 1761 if (t != null) 1762 { 1763 logger.warn(LocalizableMessage.raw("Error occurred running task: " + t, t)); 1764 if (task.getReturnCode() != null && errorDetailCode != null) 1765 { 1766 String sThrowable; 1767 if (t instanceof OpenDsException) 1768 { 1769 sThrowable = ((OpenDsException) t).getMessageObject().toString(); 1770 } 1771 else if (t.getMessage() != null) 1772 { 1773 sThrowable = t.getMessage(); 1774 } 1775 else 1776 { 1777 sThrowable = t.toString(); 1778 } 1779 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1780 mb.append(errorDetailCode.get(task.getReturnCode())); 1781 mb.append(" ").append(INFO_CTRL_PANEL_DETAILS_THROWABLE.get(sThrowable)); 1782 summaryMsg = 1783 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), 1784 ColorAndFontConstants.defaultFont); 1785 } 1786 else if (errorDetail != null) 1787 { 1788 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1789 mb.append(errorDetail); 1790 mb.append(INFO_CTRL_PANEL_DETAILS_THROWABLE.get(t)); 1791 summaryMsg = 1792 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), 1793 ColorAndFontConstants.defaultFont); 1794 } 1795 else 1796 { 1797 summaryMsg = null; 1798 } 1799 } 1800 else if (task.getReturnCode() != null && errorDetailCode != null) 1801 { 1802 summaryMsg = 1803 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetailCode 1804 .get(task.getReturnCode()), ColorAndFontConstants.defaultFont); 1805 } 1806 else if (errorDetail != null) 1807 { 1808 summaryMsg = 1809 Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetail, 1810 ColorAndFontConstants.defaultFont); 1811 } 1812 else 1813 { 1814 summaryMsg = null; 1815 } 1816 } 1817 if (summaryMsg != null) 1818 { 1819 dialog.setSummary(LocalizableMessage.raw(summaryMsg)); 1820 } 1821 dialog.setEnabledClose(true); 1822 dialog.getProgressBar().setVisible(false); 1823 if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) 1824 { 1825 dialog.setTaskIsOver(true); 1826 } 1827 task.postOperation(); 1828 } 1829 }; 1830 info.registerTask(task); 1831 worker.startBackgroundTask(); 1832 } 1833 1834 /** 1835 * Checks that the provided string value is a valid integer and if it is not 1836 * updates a list of error messages with an error. 1837 * 1838 * @param errors 1839 * the list of error messages to be updated. 1840 * @param stringValue 1841 * the string value to analyze. 1842 * @param minValue 1843 * the minimum integer value accepted. 1844 * @param maxValue 1845 * the maximum integer value accepted. 1846 * @param errMsg 1847 * the error message to use to update the error list if the provided 1848 * value is not valid. 1849 * @return {@code true} if the provided string value is a valid integer and if 1850 * it is not updates a list of error messages with an error. 1851 */ 1852 protected boolean checkIntValue(final Collection<LocalizableMessage> errors, final String stringValue, 1853 final int minValue, final int maxValue, final LocalizableMessage errMsg) 1854 { 1855 try 1856 { 1857 int n = Integer.parseInt(stringValue); 1858 if (minValue <= n && n <= maxValue) 1859 { 1860 return true; 1861 } 1862 } 1863 catch (NumberFormatException ignored) 1864 { 1865 } 1866 1867 errors.add(errMsg); 1868 return false; 1869 } 1870 1871 /** 1872 * Starts the server. This method will launch a task and open a progress 1873 * dialog that will start the server. This method must be called from the 1874 * event thread. 1875 */ 1876 protected void startServer() 1877 { 1878 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1879 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1880 INFO_CTRL_PANEL_START_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1881 StartServerTask newTask = new StartServerTask(getInfo(), progressDialog); 1882 for (Task task : getInfo().getTasks()) 1883 { 1884 task.canLaunch(newTask, errors); 1885 } 1886 if (errors.isEmpty()) 1887 { 1888 launchOperation(newTask, 1889 INFO_CTRL_PANEL_STARTING_SERVER_SUMMARY.get(), 1890 INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_SUMMARY.get(), 1891 INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_DETAILS.get(), 1892 ERR_CTRL_PANEL_STARTING_SERVER_ERROR_SUMMARY.get(), null, 1893 ERR_CTRL_PANEL_STARTING_SERVER_ERROR_DETAILS, progressDialog); 1894 progressDialog.setVisible(true); 1895 } 1896 else 1897 { 1898 displayErrorDialog(errors); 1899 } 1900 } 1901 1902 /** 1903 * Stops the server. This method will launch a task and open a progress dialog 1904 * that will stop the server. This method must be called from the event 1905 * thread. 1906 */ 1907 protected void stopServer() 1908 { 1909 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1910 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1911 INFO_CTRL_PANEL_STOP_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1912 StopServerTask newTask = new StopServerTask(getInfo(), progressDialog); 1913 for (Task task : getInfo().getTasks()) 1914 { 1915 task.canLaunch(newTask, errors); 1916 } 1917 boolean confirmed = true; 1918 if (errors.isEmpty()) 1919 { 1920 confirmed = displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 1921 INFO_CTRL_PANEL_CONFIRM_STOP_SERVER_DETAILS.get()); 1922 } 1923 if (errors.isEmpty() && confirmed) 1924 { 1925 launchOperation(newTask, 1926 INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), 1927 INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_SUMMARY.get(), 1928 INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_DETAILS.get(), 1929 ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_SUMMARY.get(), null, 1930 ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_DETAILS, progressDialog); 1931 progressDialog.setVisible(true); 1932 } 1933 if (!errors.isEmpty()) 1934 { 1935 displayErrorDialog(errors); 1936 } 1937 } 1938 1939 /** 1940 * Restarts the server. This method will launch a task and open a progress 1941 * dialog that will restart the server. This method must be called from the 1942 * event thread. 1943 */ 1944 protected void restartServer() 1945 { 1946 Set<LocalizableMessage> errors = new LinkedHashSet<>(); 1947 ProgressDialog progressDialog = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this), 1948 INFO_CTRL_PANEL_RESTART_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); 1949 RestartServerTask newTask = new RestartServerTask(getInfo(), progressDialog); 1950 for (Task task : getInfo().getTasks()) 1951 { 1952 task.canLaunch(newTask, errors); 1953 } 1954 boolean confirmed = true; 1955 if (errors.isEmpty()) 1956 { 1957 confirmed = displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 1958 INFO_CTRL_PANEL_CONFIRM_RESTART_SERVER_DETAILS.get()); 1959 } 1960 if (errors.isEmpty() && confirmed) 1961 { 1962 launchOperation(newTask, 1963 INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), 1964 INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_SUMMARY.get(), 1965 INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_DETAILS.get(), 1966 ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_SUMMARY.get(), null, 1967 ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_DETAILS, progressDialog); 1968 progressDialog.setVisible(true); 1969 } 1970 if (!errors.isEmpty()) 1971 { 1972 displayErrorDialog(errors); 1973 } 1974 } 1975 1976 /** 1977 * Displays a dialog asking for authentication. This method must be called 1978 * from the event thread. 1979 */ 1980 private void authenticate() 1981 { 1982 if (!getLoginDialog().isVisible()) 1983 { 1984 getLoginDialog().setVisible(true); 1985 } 1986 getLoginDialog().toFront(); 1987 } 1988 1989 /** 1990 * Returns the login dialog that is displayed when the method authenticate is 1991 * called. 1992 * 1993 * @return the login dialog that is displayed when the method authenticate is 1994 * called. 1995 */ 1996 protected GenericDialog getLoginDialog() 1997 { 1998 GenericDialog dialog = isLocal() ? getLocalServerLoginDialog(getInfo()) : getLocalOrRemoteDialog(getInfo()); 1999 Utilities.centerGoldenMean(dialog, Utilities.getFrame(this)); 2000 dialog.setModal(true); 2001 return dialog; 2002 } 2003 2004 /** 2005 * Tells whether an entry exists or not. Actually it tells if we could find a 2006 * given entry or not. 2007 * 2008 * @param dn 2009 * the DN of the entry to look for. 2010 * @return <CODE>true</CODE> if the entry with the provided DN could be found 2011 * and <CODE>false</CODE> otherwise. 2012 */ 2013 protected boolean entryExists(final String dn) 2014 { 2015 boolean entryExists = false; 2016 try 2017 { 2018 SearchControls ctls = new SearchControls(); 2019 ctls.setSearchScope(SearchControls.OBJECT_SCOPE); 2020 ctls.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES }); 2021 String filter = BrowserController.ALL_OBJECTS_FILTER; 2022 NamingEnumeration<SearchResult> result = 2023 getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); 2024 2025 try 2026 { 2027 while (result.hasMore()) 2028 { 2029 SearchResult sr = result.next(); 2030 entryExists = sr != null; 2031 } 2032 } 2033 finally 2034 { 2035 result.close(); 2036 } 2037 } 2038 catch (Throwable t) 2039 { 2040 } 2041 return entryExists; 2042 } 2043 2044 /** 2045 * Tells whether a given entry exists and contains one of the specified object 2046 * classes. 2047 * 2048 * @param dn 2049 * the DN of the entry. 2050 * @param objectClasses 2051 * the object classes to check. 2052 * @return <CODE>true</CODE> if the entry exists and contains one of the 2053 * specified object classes and <CODE>false</CODE> otherwise. 2054 */ 2055 protected boolean hasObjectClass(final String dn, final String... objectClasses) 2056 { 2057 try 2058 { 2059 SearchControls ctls = new SearchControls(); 2060 ctls.setSearchScope(SearchControls.OBJECT_SCOPE); 2061 ctls.setReturningAttributes(new String[] { ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME }); 2062 String filter = BrowserController.ALL_OBJECTS_FILTER; 2063 NamingEnumeration<SearchResult> result = 2064 getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); 2065 2066 try 2067 { 2068 while (result.hasMore()) 2069 { 2070 SearchResult sr = result.next(); 2071 Set<String> values = ConnectionUtils.getValues(sr, ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME); 2072 if (values != null) 2073 { 2074 for (String s : values) 2075 { 2076 for (String objectClass : objectClasses) 2077 { 2078 if (s.equalsIgnoreCase(objectClass)) 2079 { 2080 return true; 2081 } 2082 } 2083 } 2084 } 2085 } 2086 } 2087 finally 2088 { 2089 result.close(); 2090 } 2091 } 2092 catch (Throwable t) 2093 { 2094 } 2095 return false; 2096 } 2097 2098 /** 2099 * Returns the border to be used in the right panel of the dialog with a tree 2100 * on the left (for instance the schema browser, entry browser and index 2101 * browser). 2102 * 2103 * @return the border to be used in the right panel. 2104 */ 2105 protected Border getRightPanelBorder() 2106 { 2107 return ColorAndFontConstants.textAreaBorder; 2108 } 2109 2110 /** 2111 * Returns the monitoring value in a String form to be displayed to the user. 2112 * 2113 * @param attr 2114 * the attribute to analyze. 2115 * @param monitoringEntry 2116 * the monitoring entry. 2117 * @return the monitoring value in a String form to be displayed to the user. 2118 */ 2119 public static String getMonitoringValue(final MonitoringAttributes attr, final CustomSearchResult monitoringEntry) 2120 { 2121 return Utilities.getMonitoringValue(attr, monitoringEntry); 2122 } 2123 2124 /** 2125 * Updates the monitoring information writing it to a list of labels. 2126 * 2127 * @param monitoringAttrs 2128 * the monitoring operations whose information we want to update. 2129 * @param monitoringLabels 2130 * the monitoring labels to be updated. 2131 * @param monitoringEntry 2132 * the monitoring entry containing the information to be displayed. 2133 */ 2134 protected void updateMonitoringInfo(final List<MonitoringAttributes> monitoringAttrs, 2135 final List<JLabel> monitoringLabels, final CustomSearchResult monitoringEntry) 2136 { 2137 for (int i = 0; i < monitoringAttrs.size(); i++) 2138 { 2139 String value = getMonitoringValue(monitoringAttrs.get(i), monitoringEntry); 2140 JLabel l = monitoringLabels.get(i); 2141 l.setText(value); 2142 } 2143 } 2144 2145 /** 2146 * Returns the label to be used in panels (with ':') based on the definition 2147 * of the monitoring attribute. 2148 * 2149 * @param attr 2150 * the monitoring attribute. 2151 * @return the label to be used in panels (with ':') based on the definition 2152 * of the monitoring attribute. 2153 */ 2154 protected static LocalizableMessage getLabel(final MonitoringAttributes attr) 2155 { 2156 return INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(attr.getMessage()); 2157 } 2158 2159 /** 2160 * Returns the command-line arguments associated with the provided schedule. 2161 * 2162 * @param schedule 2163 * the schedule. 2164 * @return the command-line arguments associated with the provided schedule. 2165 */ 2166 protected List<String> getScheduleArgs(final ScheduleType schedule) 2167 { 2168 List<String> args = new ArrayList<>(2); 2169 switch (schedule.getType()) 2170 { 2171 case LAUNCH_LATER: 2172 args.add("--start"); 2173 args.add(getStartTimeForTask(schedule.getLaunchLaterDate())); 2174 break; 2175 case LAUNCH_PERIODICALLY: 2176 args.add("--recurringTask"); 2177 args.add(schedule.getCronValue()); 2178 break; 2179 } 2180 return args; 2181 } 2182 2183 /** 2184 * Checks whether the server is running or not and depending on the schedule 2185 * updates the list of errors with the errors found. 2186 * 2187 * @param schedule 2188 * the schedule. 2189 * @param errors 2190 * the list of errors. 2191 * @param label 2192 * the label to be marked as invalid if errors where encountered. 2193 */ 2194 protected void addScheduleErrors(final ScheduleType schedule, final Collection<LocalizableMessage> errors, 2195 final JLabel label) 2196 { 2197 if (!isServerRunning()) 2198 { 2199 ScheduleType.Type type = schedule.getType(); 2200 if (type == ScheduleType.Type.LAUNCH_LATER) 2201 { 2202 errors.add(ERR_CTRL_PANEL_LAUNCH_LATER_REQUIRES_SERVER_RUNNING.get()); 2203 setPrimaryInvalid(label); 2204 } 2205 else if (type == ScheduleType.Type.LAUNCH_PERIODICALLY) 2206 { 2207 errors.add(ERR_CTRL_PANEL_LAUNCH_SCHEDULE_REQUIRES_SERVER_RUNNING.get()); 2208 setPrimaryInvalid(label); 2209 } 2210 } 2211 } 2212 2213 private String getStartTimeForTask(final Date date) 2214 { 2215 return taskDateFormat.format(date); 2216 } 2217 2218 /** 2219 * Checks whether the provided superior object classes are compatible with the 2220 * provided object class type. If not, the method updates the provided list of 2221 * error messages with a message describing the incompatibility. 2222 * 2223 * @param objectClassSuperiors 2224 * the superior object classes. 2225 * @param objectClassType 2226 * the object class type. 2227 * @param errors 2228 * the list of error messages. 2229 */ 2230 protected void checkCompatibleSuperiors(final Set<ObjectClass> objectClassSuperiors, 2231 final ObjectClassType objectClassType, final List<LocalizableMessage> errors) 2232 { 2233 SortedSet<String> notCompatibleClasses = new TreeSet<>(new LowerCaseComparator()); 2234 for (ObjectClass oc : objectClassSuperiors) 2235 { 2236 if (oc.getObjectClassType() == ObjectClassType.ABSTRACT) 2237 { 2238 // Nothing to do. 2239 } 2240 else if (oc.getObjectClassType() != objectClassType) 2241 { 2242 notCompatibleClasses.add(oc.getNameOrOID()); 2243 } 2244 } 2245 if (!notCompatibleClasses.isEmpty()) 2246 { 2247 String arg = Utilities.getStringFromCollection(notCompatibleClasses, ", "); 2248 if (objectClassType == ObjectClassType.STRUCTURAL) 2249 { 2250 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_STRUCTURAL.get(arg)); 2251 } 2252 else if (objectClassType == ObjectClassType.AUXILIARY) 2253 { 2254 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_AUXILIARY.get(arg)); 2255 } 2256 else if (objectClassType == ObjectClassType.ABSTRACT) 2257 { 2258 errors.add(ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_ABSTRACT.get(arg)); 2259 } 2260 } 2261 } 2262}