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