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