/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2013-2014 ForgeRock AS. */ package org.opends.guitools.controlpanel.ui; import static org.opends.messages.AdminToolMessages.*; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; import javax.naming.NamingEnumeration; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.swing.Box; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JMenuBar; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.border.Border; import org.opends.admin.ads.util.ConnectionUtils; import org.opends.guitools.controlpanel.browser.BrowserController; import org.opends.guitools.controlpanel.browser.IconPool; import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; import org.opends.guitools.controlpanel.datamodel.MonitoringAttributes; import org.opends.guitools.controlpanel.datamodel.ScheduleType; import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; import org.opends.guitools.controlpanel.event.*; import org.opends.guitools.controlpanel.task.RebuildIndexTask; import org.opends.guitools.controlpanel.task.RestartServerTask; import org.opends.guitools.controlpanel.task.StartServerTask; import org.opends.guitools.controlpanel.task.StopServerTask; import org.opends.guitools.controlpanel.task.Task; import org.opends.guitools.controlpanel.ui.components.AddRemovePanel; import org.opends.guitools.controlpanel.util.BackgroundTask; import org.opends.guitools.controlpanel.util.LowerCaseComparator; import org.opends.guitools.controlpanel.util.Utilities; import org.forgerock.i18n.LocalizableMessageBuilder; import org.forgerock.i18n.LocalizableMessageDescriptor; import org.opends.quicksetup.ui.CustomHTMLEditorKit; import org.opends.server.schema.SchemaConstants; import org.opends.server.types.ObjectClass; import org.opends.server.types.ObjectClassType; import org.opends.server.types.OpenDsException; import org.opends.server.util.ServerConstants; /** * An abstract class that contains a number of methods that are shared by all * the inheriting classes. In general a StatusGenericPanel is contained in a * GenericDialog and specifies the kind of buttons that this dialog has. The * StatusGenericPanel is also notified when the dialog is displayed (through * the toBeDisplayed method) */ public abstract class StatusGenericPanel extends JPanel implements ConfigChangeListener { private static final long serialVersionUID = -9123358652232556732L; /** * The string to be used as combo separator. */ public static final String COMBO_SEPARATOR = "----------"; /** * The not applicable message. */ protected final static LocalizableMessage NOT_APPLICABLE = INFO_NOT_APPLICABLE_LABEL.get(); private LocalizableMessage AUTHENTICATE = INFO_AUTHENTICATE_BUTTON_LABEL.get(); private LocalizableMessage START = INFO_START_BUTTON_LABEL.get(); private ControlPanelInfo info; private boolean enableClose = true; private boolean enableCancel = true; private boolean enableOK = true; private boolean disposeOnClose = false; private JPanel cardPanel; private JPanel mainPanel; private JEditorPane message; private CardLayout cardLayout; private static final String MAIN_PANEL = "mainPanel"; private static final String MESSAGE_PANEL = "messagePanel"; private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The error pane. */ protected JEditorPane errorPane; /** * The last displayed message in the error pane. */ protected String lastDisplayedError = null; private ArrayList confListeners = new ArrayList(); private boolean sizeSet = false; private boolean focusSet = false; private static DateFormat taskDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); /** * Returns the title that will be used as title of the dialog. * @return the title that will be used as title of the dialog. */ public abstract LocalizableMessage getTitle(); /** * Returns the buttons that the dialog where this panel is contained should * display. * @return the buttons that the dialog where this panel is contained should * display. */ public GenericDialog.ButtonType getButtonType() { return GenericDialog.ButtonType.OK_CANCEL; } /** * Returns the component that should get the focus when the dialog that * contains this panel is displayed. * @return the component that should get the focus. */ public abstract Component getPreferredFocusComponent(); /** * Returns true if this panel requires some bordering (in general * an EmptyBorder with some insets) and false otherwise. * @return true if this panel requires some bordering (in general * an EmptyBorder with some insets) and false otherwise. */ public boolean requiresBorder() { return true; } /** * Returns the menu bar that the panel might have. Returns * null if the panel has no menu bar associated. * @return the menu bar that the panel might have. */ public JMenuBar getMenuBar() { return null; } /** * This method is called to indicate that the configuration changes should * be called in the background. In the case of panels which require some * time to be updated with the new configuration this method returns * true and the operation will be performed in the background * while a message of type 'Loading...' is displayed on the panel. * @return true if changes should be loaded in the background and * false otherwise. */ public boolean callConfigurationChangedInBackground() { return false; } /** * The panel is notified that the dialog is going to be visible or invisible. * @param visible whether is going to be visible or not. */ public void toBeDisplayed(boolean visible) { } /** * Tells whether this panel should be contained in a scroll pane or not. * @return true if this panel should be contained in a scroll * pane and false otherwise. */ public boolean requiresScroll() { return true; } /** * Constructor. * */ protected StatusGenericPanel() { super(new GridBagLayout()); setBackground(ColorAndFontConstants.background); cardLayout = new CardLayout(); cardPanel = new JPanel(cardLayout); cardPanel.setOpaque(false); mainPanel = new JPanel(new GridBagLayout()); mainPanel.setOpaque(false); message = Utilities.makeHtmlPane("", ColorAndFontConstants.progressFont); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1.0; gbc.weighty = 1.0; super.add(cardPanel, gbc); cardPanel.add(mainPanel, MAIN_PANEL); JPanel messagePanel = new JPanel(new GridBagLayout()); messagePanel.setOpaque(false); gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.CENTER; messagePanel.add(message, gbc); cardPanel.add(messagePanel, MESSAGE_PANEL); cardLayout.show(cardPanel, MAIN_PANEL); } /** * The components are not added directly to the panel but to the main panel. * This is done to be able to display a message that takes the whole panel * (of type 'Loading...') when we are doing long operations. * @param comp the Component to be added. * @param constraints the constraints. */ public void add(Component comp, Object constraints) { mainPanel.add(comp, constraints); } /** * Adds a bottom glue to the main panel with the provided constraints. * @param gbc the constraints. */ protected void addBottomGlue(GridBagConstraints gbc) { GridBagConstraints gbc2 = (GridBagConstraints)gbc.clone(); gbc2.insets = new Insets(0, 0, 0, 0); gbc2.gridy ++; gbc2.gridwidth = GridBagConstraints.REMAINDER; gbc2.weighty = 1.0; gbc2.fill = GridBagConstraints.VERTICAL; add(Box.createVerticalGlue(), gbc2); gbc.gridy ++; } /** * Returns a label with text 'Required Field' and an icon (used as legend in * some panels). * @return a label with text 'Required Field' and an icon (used as legend in * some panels). */ protected JLabel createRequiredLabel() { JLabel requiredLabel = Utilities.createInlineHelpLabel( INFO_CTRL_PANEL_INDICATES_REQUIRED_FIELD_LABEL.get()); requiredLabel.setIcon( Utilities.createImageIcon(IconPool.IMAGE_PATH+"/required.gif")); return requiredLabel; } /** * Creates and adds an error pane. Is up to the caller to set the proper * gridheight, gridwidth, gridx and gridy on the provided GridBagConstraints. * @param baseGbc the GridBagConstraints to be used. */ protected void addErrorPane(GridBagConstraints baseGbc) { addErrorPane(this, baseGbc); } /** * Adds an error pane to the provided container. * Is up to the caller to set the proper gridheight, gridwidth, gridx and * gridy on the provided GridBagConstraints. * @param baseGbc the GridBagConstraints to be used. * @param p the container. */ protected void addErrorPane(Container p, GridBagConstraints baseGbc) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = baseGbc.gridx; gbc.gridy = baseGbc.gridy; gbc.gridwidth = baseGbc.gridwidth; gbc.gridheight = baseGbc.gridheight; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.BOTH; if (requiresBorder()) { gbc.insets = new Insets(0, 0, 10, 0); } else { gbc.insets = new Insets(20, 20, 0, 20); } createErrorPane(); p.add(errorPane, gbc); } /** * Creates the error pane. */ protected void createErrorPane() { errorPane = Utilities.makeHtmlPane("", ColorAndFontConstants.progressFont); errorPane.setOpaque(false); errorPane.setEditable(false); errorPane.setVisible(false); CustomHTMLEditorKit htmlEditor = new CustomHTMLEditorKit(); htmlEditor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { if (AUTHENTICATE.toString().equals(ev.getActionCommand())) { authenticate(); } else if (START.toString().equals(ev.getActionCommand())) { startServer(); } } }); errorPane.setEditorKit(htmlEditor); } /** * Commodity method used to add lines, where each line contains a label, a * component and an inline help label. * @param labels the labels. * @param comps the components. * @param inlineHelp the inline help labels. * @param panel the panel where we will add the lines. * @param gbc the grid bag constraints. */ protected void add(JLabel[] labels, Component[] comps, JLabel[] inlineHelp, Container panel, GridBagConstraints gbc) { int i = 0; for (Component comp : comps) { gbc.insets.left = 0; gbc.weightx = 0.0; gbc.gridx = 0; if (labels[i] != null) { panel.add(labels[i], gbc); } gbc.insets.left = 10; gbc.weightx = 1.0; gbc.gridx = 1; panel.add(comp, gbc); if (inlineHelp[i] != null) { gbc.insets.top = 3; gbc.gridy ++; panel.add(inlineHelp[i], gbc); } gbc.insets.top = 10; gbc.gridy ++; i++; } } /** * Enables the OK button in the parent dialog. * @param enable whether to enable or disable the button. */ protected void setEnabledOK(boolean enable) { Window w = Utilities.getParentDialog(this); if (w instanceof GenericDialog) { ((GenericDialog)w).setEnabledOK(enable); } else if (w instanceof GenericFrame) { ((GenericFrame)w).setEnabledOK(enable); } enableOK = enable; } /** * Enables the Cancel button in the parent dialog. * @param enable whether to enable or disable the button. */ protected void setEnabledCancel(boolean enable) { Window w = Utilities.getParentDialog(this); if (w instanceof GenericDialog) { ((GenericDialog)w).setEnabledCancel(enable); } else if (w instanceof GenericFrame) { ((GenericFrame)w).setEnabledCancel(enable); } enableCancel = enable; } /** * Updates the font type and color of the component to be invalid and * primary. * @param comp the component to update. */ protected void setPrimaryInvalid(JComponent comp) { comp.setFont(ColorAndFontConstants.primaryInvalidFont); comp.setForeground(ColorAndFontConstants.invalidFontColor); } /** * Updates the font type and color of the component to be valid and * primary. * @param comp the component to update. */ protected void setPrimaryValid(JComponent comp) { comp.setForeground(ColorAndFontConstants.validFontColor); comp.setFont(ColorAndFontConstants.primaryFont); } /** * Updates the font type and color of the component to be invalid and * secondary. * @param comp the component to update. */ protected void setSecondaryInvalid(JComponent comp) { comp.setForeground(ColorAndFontConstants.invalidFontColor); comp.setFont(ColorAndFontConstants.invalidFont); } /** * Updates the font type and color of the component to be valid and * secondary. * @param comp the component to update. */ protected void setSecondaryValid(JComponent comp) { comp.setForeground(ColorAndFontConstants.validFontColor); comp.setFont(ColorAndFontConstants.defaultFont); } /** * Packs the parent dialog. * */ protected void packParentDialog() { Window dlg = Utilities.getParentDialog(this); if (dlg != null) { invalidate(); dlg.invalidate(); dlg.pack(); if (!SwingUtilities.isEventDispatchThread()) { Thread.dumpStack(); } } } /** * Notification that the ok button has been clicked, the panel is in charge * of doing whatever is required (close the dialog, launch a task, etc.). * */ abstract public void okClicked(); /** * Adds a configuration element created listener. * @param listener the listener. */ public void addConfigurationElementCreatedListener( ConfigurationElementCreatedListener listener) { getConfigurationElementCreatedListeners().add(listener); } /** * Removes a configuration element created listener. * @param listener the listener. */ public void removeConfigurationElementCreatedListener( ConfigurationElementCreatedListener listener) { getConfigurationElementCreatedListeners().remove(listener); } /** * Notifies the configuration element created listener that a new object has * been created. * @param configObject the created object. */ protected void notifyConfigurationElementCreated(Object configObject) { for (ConfigurationElementCreatedListener listener : getConfigurationElementCreatedListeners()) { listener.elementCreated( new ConfigurationElementCreatedEvent(this, configObject)); } } /** * Returns the list of configuration listeners. * @return the list of configuration listeners. */ protected List getConfigurationElementCreatedListeners() { return confListeners; } /** * Notification that cancel was clicked, the panel is in charge * of doing whatever is required (close the dialog, etc.). * */ public void cancelClicked() { // Default implementation Utilities.getParentDialog(this).setVisible(false); if (isDisposeOnClose()) { Utilities.getParentDialog(this).dispose(); } } /** * Whether the dialog should be disposed when the user closes it. * @return true if the dialog should be disposed when the user * closes it or true otherwise. */ public boolean isDisposeOnClose() { return disposeOnClose; } /** * Sets whether the dialog should be disposed when the user closes it or not. * @param disposeOnClose true if the dialog should be disposed * when the user closes it or true otherwise. */ public void setDisposeOnClose(boolean disposeOnClose) { this.disposeOnClose = disposeOnClose; } /** * Notification that close was clicked, the panel is in charge * of doing whatever is required (close the dialog, etc.). * */ public void closeClicked() { // Default implementation Utilities.getParentDialog(this).setVisible(false); if (isDisposeOnClose()) { Utilities.getParentDialog(this).dispose(); } } /** * Displays a dialog with the provided list of error messages. * @param errors the error messages. */ protected void displayErrorDialog(Collection errors) { Utilities.displayErrorDialog(Utilities.getParentDialog(this), errors); } /** * Displays a confirmation message. * @param title the title/summary of the message. * @param msg the description of the confirmation. * @return true if the user confirms and false * otherwise. */ protected boolean displayConfirmationDialog(LocalizableMessage title, LocalizableMessage msg) { return Utilities.displayConfirmationDialog(Utilities.getParentDialog(this), title, msg); } /** * If the index must be rebuilt, asks the user for confirmation. If the user * confirms launches a task that will rebuild the indexes. The progress will * be displayed in the provided progress dialog. * @param index the index. * @param progressDialog the progress dialog. */ protected void rebuildIndexIfNecessary(AbstractIndexDescriptor index, ProgressDialog progressDialog) { progressDialog.setTaskIsOver(false); boolean rebuildIndexes; String backendName = index.getBackend().getBackendID(); if (!isServerRunning()) { rebuildIndexes = Utilities.displayConfirmationDialog(progressDialog, INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_OFFLINE_DETAILS.get( index.getName(), backendName)); } else { if (isLocal()) { rebuildIndexes = Utilities.displayConfirmationDialog(progressDialog, INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_ONLINE_DETAILS.get( index.getName(), backendName, backendName)); } else { Utilities.displayWarningDialog(progressDialog, INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_INDEX_REBUILD_REQUIRED_REMOTE_DETAILS.get( index.getName(), backendName)); rebuildIndexes = false; } } if (rebuildIndexes) { SortedSet indexes = new TreeSet(); indexes.add(index); SortedSet baseDNs = new TreeSet(); for (BaseDNDescriptor b : index.getBackend().getBaseDns()) { String baseDN = Utilities.unescapeUtf8(b.getDn().toString()); baseDNs.add(baseDN); } RebuildIndexTask newTask = new RebuildIndexTask(getInfo(), progressDialog, baseDNs, indexes); ArrayList errors = new ArrayList(); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } if (errors.size() == 0) { progressDialog.appendProgressHtml("

"); launchOperation(newTask, INFO_CTRL_PANEL_REBUILDING_INDEXES_SUMMARY.get(backendName), INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_REBUILDING_INDEXES_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_REBUILDING_INDEXES_ERROR_DETAILS, progressDialog, false); if (progressDialog.isModal()) { progressDialog.toFront(); } progressDialog.setVisible(true); if (!progressDialog.isModal()) { progressDialog.toFront(); } } if (errors.size() > 0) { displayErrorDialog(errors); } } else { progressDialog.setTaskIsOver(true); if (progressDialog.isVisible()) { progressDialog.toFront(); } } } /** * A class used to avoid the possibility a certain type of objects in a combo * box. This is used for instance in the combo box that contains base DNs * where the base DNs are separated in backends, so the combo box displays * both the backends (~ categories) and base DNs (~ values) and we do not * allow to select the backends (~ categories). * */ protected class IgnoreItemListener implements ItemListener { private Object selectedItem; private JComboBox combo; /** * Constructor. * @param combo the combo box. */ public IgnoreItemListener(JComboBox combo) { this.combo = combo; selectedItem = combo.getSelectedItem(); if (isCategory(selectedItem)) { selectedItem = null; } } /** * {@inheritDoc} */ public void itemStateChanged(ItemEvent ev) { Object o = combo.getSelectedItem(); if (isCategory(o)) { if (selectedItem == null) { // Look for the first element that is not a category for (int i=0; i"; } /** * Returns the HTML required to render an Start button in HTML. * @return the HTML required to render an Start button in HTML. */ protected String getStartServerHTML() { return ""; } /** * Updates the error panel and enables/disables the OK button depending on * the status of the server. * @param desc the Server Descriptor. * @param details the message to be displayed if authentication has not been * provided and the server is running. */ protected void updateErrorPaneAndOKButtonIfAuthRequired(ServerDescriptor desc, LocalizableMessage details) { if (authenticationRequired(desc)) { LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(details); mb.append("

"+getAuthenticateHTML()); LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); updateErrorPane(errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(true); packParentDialog(); setEnabledOK(false); } }); } else { SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(false); checkOKButtonEnable(); } }); } } /** * Returns true if the server is running and the user did not * provide authentication and false otherwise. * @param desc the server descriptor. * @return true if the server is running and the user did not * provide authentication and false otherwise. */ protected boolean authenticationRequired(ServerDescriptor desc) { boolean returnValue; ServerDescriptor.ServerStatus status = desc.getStatus(); if (((status == ServerDescriptor.ServerStatus.STARTED) && !desc.isAuthenticated()) || (status == ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE)) { returnValue = true; } else { returnValue = false; } return returnValue; } /** * Updates the error panel depending on the status of the server. * @param desc the Server Descriptor. * @param details the message to be displayed if authentication has not been * provided and the server is running. */ protected void updateErrorPaneIfAuthRequired(ServerDescriptor desc, LocalizableMessage details) { if (authenticationRequired(desc)) { LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(details); mb.append("

"+getAuthenticateHTML()); updateErrorPane(errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(true); packParentDialog(); } }); } else { SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(false); } }); } } /** * Updates the error panel depending on the status of the server. This * method will display an error message in the error pane if the server is not * running and another message if the server is running but authentication * has not been provided. * @param desc the Server Descriptor. * @param detailsServerNotRunning the message to be displayed if the server is * not running. * @param authRequired the message to be displayed if authentication has not * been provided and the server is running. */ protected void updateErrorPaneIfServerRunningAndAuthRequired( ServerDescriptor desc, LocalizableMessage detailsServerNotRunning, LocalizableMessage authRequired) { ServerDescriptor.ServerStatus status = desc.getStatus(); if ((status != ServerDescriptor.ServerStatus.STARTED) && (status != ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE)) { LocalizableMessage title = INFO_CTRL_PANEL_SERVER_NOT_RUNNING_SUMMARY.get(); LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(detailsServerNotRunning); mb.append("

"+getStartServerHTML()); updateErrorPane(errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(true); packParentDialog(); } }); } else if (authenticationRequired(desc)) { LocalizableMessage title = INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_SUMMARY.get(); LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(authRequired); mb.append("

"+getAuthenticateHTML()); updateErrorPane(errorPane, title, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(true); packParentDialog(); } }); } else { SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { errorPane.setVisible(false); } }); } } /** * Updates the enabling/disabling of the OK button. The code assumes that * the error pane has already been updated. * */ protected void checkOKButtonEnable() { setEnabledOK(!errorPane.isVisible()); } /** * Returns true if the provided object is a category object in * a combo box. * @param o the item in the combo box. * @return true if the provided object is a category object in * a combo box. */ protected boolean isCategory(Object o) { boolean isCategory = false; if (o instanceof CategorizedComboBoxElement) { CategorizedComboBoxElement desc = (CategorizedComboBoxElement)o; isCategory = desc.getType() == CategorizedComboBoxElement.Type.CATEGORY; } return isCategory; } /** * Returns the control panel info object. * @return the control panel info object. */ public ControlPanelInfo getInfo() { return info; } /** * Sets the control panel info object. * @param info the control panel info object. */ public void setInfo(ControlPanelInfo info) { if (!info.equals(this.info)) { if (this.info != null) { this.info.removeConfigChangeListener(this); } this.info = info; this.info.addConfigChangeListener(this); if (SwingUtilities.isEventDispatchThread() && callConfigurationChangedInBackground()) { final Color savedBackground = getBackground(); setBackground(ColorAndFontConstants.background); if (!sizeSet) { setPreferredSize(mainPanel.getPreferredSize()); sizeSet = true; } // Do it outside the event thread if the panel requires it. BackgroundTask worker = new BackgroundTask() { public Void processBackgroundTask() throws Throwable { try { Thread.sleep(1000); } catch (Throwable t) { } configurationChanged(new ConfigurationChangeEvent( StatusGenericPanel.this.info, StatusGenericPanel.this.info.getServerDescriptor())); return null; } public void backgroundTaskCompleted(Void returnValue, Throwable t) { setBackground(savedBackground); displayMainPanel(); if (!focusSet) { focusSet = true; Component comp = getPreferredFocusComponent(); if (comp != null) { comp.requestFocusInWindow(); } } } }; displayMessage(INFO_CTRL_PANEL_LOADING_PANEL_SUMMARY.get()); worker.startBackgroundTask(); } else if (info.getServerDescriptor() != null) { configurationChanged(new ConfigurationChangeEvent( this.info, this.info.getServerDescriptor())); } } } /** * Displays the main panel. * */ protected void displayMainPanel() { cardLayout.show(cardPanel, MAIN_PANEL); } /** * Returns whether the main panel is visible or not. * @return whether the main panel is visible or not. */ protected boolean isMainPanelVisible() { return mainPanel.isVisible(); } /** * Displays a message and hides the main panel. * @param msg the message to be displayed. */ protected void displayMessage(LocalizableMessage msg) { message.setText(Utilities.applyFont(msg.toString(), ColorAndFontConstants.defaultFont)); cardLayout.show(cardPanel, MESSAGE_PANEL); message.requestFocusInWindow(); } /** * Displays an error message and hides the main panel. * @param title the title of the message to be displayed. * @param msg the message to be displayed. */ protected void displayErrorMessage(LocalizableMessage title, LocalizableMessage msg) { updateErrorPane(message, title, ColorAndFontConstants.errorTitleFont, msg, ColorAndFontConstants.defaultFont); cardLayout.show(cardPanel, MESSAGE_PANEL); message.requestFocusInWindow(); } /** * Returns whether the message is visible or not. * @return whether the message is visible or not. */ protected boolean isMessageVisible() { return message.isVisible(); } /** * Updates the contents of an editor pane using the error format. * @param pane the editor pane to be updated. * @param title the title. * @param titleFont the font to be used for the title. * @param details the details message. * @param detailsFont the font to be used for the details. */ protected void updateErrorPane(JEditorPane pane, LocalizableMessage title, Font titleFont, LocalizableMessage details, Font detailsFont) { updatePane(pane, title, titleFont, details, detailsFont, PanelType.ERROR); } /** * Updates the contents of an editor pane using the warning format. * @param pane the editor pane to be updated. * @param title the title. * @param titleFont the font to be used for the title. * @param details the details message. * @param detailsFont the font to be used for the details. */ protected void updateWarningPane(JEditorPane pane, LocalizableMessage title, Font titleFont, LocalizableMessage details, Font detailsFont) { updatePane(pane, title, titleFont, details, detailsFont, PanelType.WARNING); } /** * Updates the contents of an editor pane using the confirmation format. * @param pane the editor pane to be updated. * @param title the title. * @param titleFont the font to be used for the title. * @param details the details message. * @param detailsFont the font to be used for the details. */ protected void updateConfirmationPane(JEditorPane pane, LocalizableMessage title, Font titleFont, LocalizableMessage details, Font detailsFont) { updatePane(pane, title, titleFont, details, detailsFont, PanelType.CONFIRMATION); } /** * The different types of error panels that are handled. * */ protected enum PanelType { /** * The message in the panel is an error. */ ERROR, /** * The message in the panel is a confirmation. */ CONFIRMATION, /** * The message in the panel is an information message. */ INFORMATION, /** * The message in the panel is a warning message. */ WARNING }; /** * Updates the contents of an editor pane using the provided format. * @param pane the editor pane to be updated. * @param title the title. * @param titleFont the font to be used for the title. * @param details the details message. * @param detailsFont the font to be used for the details. * @param type the type of panel. */ private void updatePane(final JEditorPane pane, LocalizableMessage title, Font titleFont, LocalizableMessage details, Font detailsFont, PanelType type) { String text; switch (type) { case ERROR: text = Utilities.getFormattedError(title, titleFont, details, detailsFont); break; case CONFIRMATION: text = Utilities.getFormattedConfirmation(title, titleFont, details, detailsFont); break; case WARNING: text = Utilities.getFormattedWarning(title, titleFont, details, detailsFont); break; default: text = Utilities.getFormattedSuccess(title, titleFont, details, detailsFont); break; } if (!text.equals(lastDisplayedError)) { LocalizableMessage wrappedTitle = Utilities.wrapHTML(title, 80); LocalizableMessage wrappedDetails = Utilities.wrapHTML(details, 90); JEditorPane wrappedPane = Utilities.makeHtmlPane(null, pane.getFont()); String wrappedText; switch (type) { case ERROR: wrappedText = Utilities.getFormattedError(wrappedTitle, titleFont, wrappedDetails, detailsFont); break; default: wrappedText = Utilities.getFormattedSuccess(wrappedTitle, titleFont, wrappedDetails, detailsFont); break; } wrappedPane.setText(wrappedText); Dimension d = wrappedPane.getPreferredSize(); pane.setText(text); pane.setPreferredSize(d); lastDisplayedError = text; } final Window window = Utilities.getParentDialog(StatusGenericPanel.this); if (window != null) { SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { pane.invalidate(); window.validate(); } }); } } /** * Commodity method used to update the elements of a combo box that contains * the different user backends. If no backends are found the combo box will * be made invisible and a label will be made visible. This method does not * update the label's text nor creates any layout. * @param combo the combo to be updated. * @param lNoBackendsFound the label that must be shown if no user backends * are found. * @param desc the server descriptor that contains the configuration. */ protected void updateSimpleBackendComboBoxModel(final JComboBox combo, final JLabel lNoBackendsFound, ServerDescriptor desc) { final SortedSet newElements = new TreeSet(new LowerCaseComparator()); for (BackendDescriptor backend : desc.getBackends()) { if (!backend.isConfigBackend()) { newElements.add(backend.getBackendID()); } } DefaultComboBoxModel model = (DefaultComboBoxModel)combo.getModel(); updateComboBoxModel(newElements, model); SwingUtilities.invokeLater(new Runnable() { public void run() { combo.setVisible(newElements.size() > 0); lNoBackendsFound.setVisible(newElements.size() == 0); } }); } /** * Method that says if a backend must be displayed. Only non-config backends * are displayed. * @param backend the backend. * @return true if the backend must be displayed and * false otherwise. */ protected boolean displayBackend(BackendDescriptor backend) { return !backend.isConfigBackend(); } /** * Commodity method to update a combo box model with the backends of a server. * @param model the combo box model to be updated. * @param desc the server descriptor containing the configuration. */ protected void updateBaseDNComboBoxModel(DefaultComboBoxModel model, ServerDescriptor desc) { LinkedHashSet newElements = new LinkedHashSet(); SortedSet backendIDs = new TreeSet(new LowerCaseComparator()); HashMap> hmBaseDNs = new HashMap>(); for (BackendDescriptor backend : desc.getBackends()) { if (displayBackend(backend)) { String backendID = backend.getBackendID(); backendIDs.add(backendID); SortedSet baseDNs = new TreeSet(new LowerCaseComparator()); for (BaseDNDescriptor baseDN : backend.getBaseDns()) { try { baseDNs.add(Utilities.unescapeUtf8(baseDN.getDn().toString())); } catch (Throwable t) { throw new RuntimeException("Unexpected error: "+t, t); } } hmBaseDNs.put(backendID, baseDNs); } } for (String backendID : backendIDs) { newElements.add(new CategorizedComboBoxElement(backendID, CategorizedComboBoxElement.Type.CATEGORY)); SortedSet baseDNs = hmBaseDNs.get(backendID); for (String baseDN : baseDNs) { newElements.add(new CategorizedComboBoxElement(baseDN, CategorizedComboBoxElement.Type.REGULAR)); } } updateComboBoxModel(newElements, model); } /** * Updates a combo box model with a number of items. * @param newElements the new items for the combo box model. * @param model the combo box model to be updated. */ protected void updateComboBoxModel(Collection newElements, DefaultComboBoxModel model) { updateComboBoxModel(newElements, model, null); } /** * Updates a combo box model with a number of items. * The method assumes that is called outside the event thread. * @param newElements the new items for the combo box model. * @param model the combo box model to be updated. * @param comparator the object that will be used to compare the objects in * the model. If null, the equals method will be used. */ protected void updateComboBoxModel(final Collection newElements, final DefaultComboBoxModel model, final Comparator comparator) { SwingUtilities.invokeLater(new Runnable() { public void run() { Utilities.updateComboBoxModel(newElements, model, comparator); } }); } /** * Updates a map, so that the keys are the base DN where the indexes are * defined and the values are a sorted set of indexes. * @param desc the server descriptor containing the index configuration. * @param hmIndexes the map to be updated. */ protected void updateIndexMap(ServerDescriptor desc, HashMap> hmIndexes) { synchronized (hmIndexes) { HashSet dns = new HashSet(); for (BackendDescriptor backend : desc.getBackends()) { if (backend.getType() == BackendDescriptor.Type.LOCAL_DB) { for (BaseDNDescriptor baseDN : backend.getBaseDns()) { String dn; try { dn = Utilities.unescapeUtf8(baseDN.getDn().toString()); } catch (Throwable t) { throw new RuntimeException("Unexpected error: "+t, t); } dns.add(dn); SortedSet indexes = new TreeSet(); indexes.addAll(backend.getIndexes()); indexes.addAll(backend.getVLVIndexes()); SortedSet currentIndexes = hmIndexes.get(dn); if (currentIndexes != null) { if (!currentIndexes.equals(indexes)) { hmIndexes.put(dn, indexes); } } else { hmIndexes.put(dn, indexes); } } } } for (String dn : new HashSet(hmIndexes.keySet())) { if (!dns.contains(dn)) { hmIndexes.remove(dn); } } } } /** * Updates and addremove panel with the contents of the provided item. The * selected item represents a base DN. * @param hmIndexes the map that contains the indexes definitions as values * and the base DNs as keys. * @param selectedItem the selected item. * @param addRemove the add remove panel to be updated. */ protected void comboBoxSelected( HashMap> hmIndexes, CategorizedComboBoxElement selectedItem, AddRemovePanel addRemove) { synchronized (hmIndexes) { String selectedDn = null; if (selectedItem != null) { selectedDn = (String)selectedItem.getValue(); } if (selectedDn != null) { SortedSet indexes = hmIndexes.get(selectedDn); if (indexes != null) { boolean availableChanged = false; boolean selectedChanged = false; SortedSet availableIndexes = addRemove.getAvailableListModel().getData(); SortedSet selectedIndexes = addRemove.getSelectedListModel().getData(); availableChanged = availableIndexes.retainAll(indexes); selectedChanged = selectedIndexes.retainAll(indexes); for (AbstractIndexDescriptor index : indexes) { if (!availableIndexes.contains(index) && !selectedIndexes.contains(index)) { availableIndexes.add(index); availableChanged = true; } } if (availableChanged) { addRemove.getAvailableListModel().clear(); addRemove.getAvailableListModel().addAll(availableIndexes); addRemove.getAvailableListModel().fireContentsChanged( addRemove.getAvailableListModel(), 0, addRemove.getAvailableListModel().getSize()); } if (selectedChanged) { addRemove.getSelectedListModel().clear(); addRemove.getSelectedListModel().addAll(selectedIndexes); addRemove.getSelectedListModel().fireContentsChanged( addRemove.getSelectedListModel(), 0, addRemove.getSelectedListModel().getSize()); } } } } } /** * Returns true if the cancel button is enabled and * false otherwise. * @return true if the cancel button is enabled and * false otherwise. */ public boolean isEnableCancel() { return enableCancel; } /** * Returns true if the close button is enabled and * false otherwise. * @return true if the close button is enabled and * false otherwise. */ public boolean isEnableClose() { return enableClose; } /** * Returns true if the ok button is enabled and * false otherwise. * @return true if the ok button is enabled and * false otherwise. */ public boolean isEnableOK() { return enableOK; } /** * Returns true if the server is running and * false otherwise. * @return true if the server is running and * false otherwise. */ protected boolean isServerRunning() { return getInfo().getServerDescriptor().getStatus() == ServerDescriptor.ServerStatus.STARTED; } /** * Returns true if the managed server is the local installation * (where the control panel is installed) false otherwise. * @return true if the managed server is the local installation * (where the control panel is installed) false otherwise. */ protected boolean isLocal() { return getInfo().getServerDescriptor().isLocal(); } /** * Launch an task. * @param task the task to be launched. * @param initialSummary the initial summary to be displayed in the progress * dialog. * @param successSummary the success summary to be displayed in the progress * dialog if the task is successful. * @param successDetail the success details to be displayed in the progress * dialog if the task is successful. * @param errorSummary the error summary to be displayed in the progress * dialog if the task ended with error. * @param errorDetail error details to be displayed in the progress * dialog if the task ended with error. * @param errorDetailCode error detail message to be displayed in the progress * dialog if the task ended with error and we have an exit error code (for * instance if the error occurred when launching a script we will have an * error code). * @param dialog the progress dialog. */ protected void launchOperation(final Task task, LocalizableMessage initialSummary, final LocalizableMessage successSummary, final LocalizableMessage successDetail, final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, final LocalizableMessageDescriptor.Arg1 errorDetailCode, final ProgressDialog dialog) { launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, dialog, true); } /** * Launch an task. * @param task the task to be launched. * @param initialSummary the initial summary to be displayed in the progress * dialog. * @param successSummary the success summary to be displayed in the progress * dialog if the task is successful. * @param successDetail the success details to be displayed in the progress * dialog if the task is successful. * @param errorSummary the error summary to be displayed in the progress * dialog if the task ended with error. * @param errorDetail error details to be displayed in the progress * dialog if the task ended with error. * @param errorDetailCode error detail message to be displayed in the progress * dialog if the task ended with error and we have an exit error code (for * instance if the error occurred when launching a script we will have an * error code). * @param dialog the progress dialog. * @param resetLogs whether the contents of the progress dialog should be * reset or not. */ protected void launchOperation(final Task task, LocalizableMessage initialSummary, final LocalizableMessage successSummary, final LocalizableMessage successDetail, final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, final LocalizableMessageDescriptor.Arg1 errorDetailCode, final ProgressDialog dialog, boolean resetLogs) { launchOperation(task, initialSummary, successSummary, successDetail, errorSummary, errorDetail, errorDetailCode, dialog, resetLogs, getInfo()); } /** * Launch an task. * @param task the task to be launched. * @param initialSummary the initial summary to be displayed in the progress * dialog. * @param successSummary the success summary to be displayed in the progress * dialog if the task is successful. * @param successDetail the success details to be displayed in the progress * dialog if the task is successful. * @param errorSummary the error summary to be displayed in the progress * dialog if the task ended with error. * @param errorDetail error details to be displayed in the progress * dialog if the task ended with error. * @param errorDetailCode error detail message to be displayed in the progress * dialog if the task ended with error and we have an exit error code (for * instance if the error occurred when launching a script we will have an * error code). * @param dialog the progress dialog. * @param resetLogs whether the contents of the progress dialog should be * reset or not. * @param info the ControlPanelInfo. */ public static void launchOperation(final Task task, LocalizableMessage initialSummary, final LocalizableMessage successSummary, final LocalizableMessage successDetail, final LocalizableMessage errorSummary, final LocalizableMessage errorDetail, final LocalizableMessageDescriptor.Arg1 errorDetailCode, final ProgressDialog dialog, boolean resetLogs, final ControlPanelInfo info) { dialog.setTaskIsOver(false); dialog.getProgressBar().setIndeterminate(true); dialog.addPrintStreamListeners(task.getOutPrintStream(), task.getErrorPrintStream()); if (resetLogs) { dialog.resetProgressLogs(); } String cmdLine = task.getCommandLineToDisplay(); if (cmdLine != null) { dialog.appendProgressHtml(Utilities.applyFont( INFO_CTRL_PANEL_EQUIVALENT_COMMAND_LINE.get()+"
"+cmdLine+ "

", ColorAndFontConstants.progressFont)); } dialog.setEnabledClose(false); dialog.setSummary(LocalizableMessage.raw( Utilities.applyFont(initialSummary.toString(), ColorAndFontConstants.defaultFont))); dialog.getProgressBar().setVisible(true); BackgroundTask worker = new BackgroundTask() { /** * {@inheritDoc} */ public Task processBackgroundTask() throws Throwable { task.runTask(); if (task.regenerateDescriptor()) { info.regenerateDescriptor(); } return task; } /** * {@inheritDoc} */ public void backgroundTaskCompleted(Task returnValue, Throwable t) { String summaryMsg; if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) { summaryMsg = Utilities.getFormattedSuccess(successSummary, ColorAndFontConstants.errorTitleFont, successDetail, ColorAndFontConstants.defaultFont); } else { if (t == null) { t = task.getLastException(); } if (t != null) { logger.warn(LocalizableMessage.raw("Error occurred running task: "+t, t)); if ((task.getReturnCode() != null) && (errorDetailCode != null)) { String sThrowable; if (t instanceof OpenDsException) { sThrowable = ((OpenDsException)t).getMessageObject().toString(); } else { if (t.getMessage() != null) { sThrowable = t.getMessage(); } else { sThrowable = t.toString(); } } LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(errorDetailCode.get(task.getReturnCode())); mb.append( " "+INFO_CTRL_PANEL_DETAILS_THROWABLE.get(sThrowable)); summaryMsg = Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); } else if (errorDetail != null) { LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); mb.append(errorDetail); mb.append(INFO_CTRL_PANEL_DETAILS_THROWABLE.get(t)); summaryMsg = Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, mb.toMessage(), ColorAndFontConstants.defaultFont); } else { summaryMsg = null; } } else if ((task.getReturnCode() != null) && (errorDetailCode != null)) { summaryMsg = Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetailCode.get(task.getReturnCode()), ColorAndFontConstants.defaultFont); } else if (errorDetail != null) { summaryMsg = Utilities.getFormattedError(errorSummary, ColorAndFontConstants.errorTitleFont, errorDetail, ColorAndFontConstants.defaultFont); } else { summaryMsg = null; } } if (summaryMsg != null) { dialog.setSummary(LocalizableMessage.raw(summaryMsg)); } dialog.setEnabledClose(true); dialog.getProgressBar().setVisible(false); if (task.getState() == Task.State.FINISHED_SUCCESSFULLY) { dialog.setTaskIsOver(true); } task.postOperation(); } }; info.registerTask(task); worker.startBackgroundTask(); } /** * Checks that the provided string value is a valid integer and if it is not * updates a list of error messages with an error. * @param errors the list of error messages to be updated. * @param stringValue the string value to analyze. * @param minValue the minimum integer value accepted. * @param maxValue the maximum integer value accepted. * @param errMsg the error message to use to update the error list if the * provided value is not valid. */ protected void checkIntValue(Collection errors, String stringValue, int minValue, int maxValue, LocalizableMessage errMsg) { try { int n = Integer.parseInt(stringValue); if ((n > maxValue) || (n < minValue)) { throw new RuntimeException("Invalid value"); } } catch (Throwable t) { errors.add(errMsg); } } /** * Starts the server. This method will launch a task and open a progress * dialog that will start the server. This method must be called from the * event thread. * */ protected void startServer() { LinkedHashSet errors = new LinkedHashSet(); ProgressDialog progressDialog = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(this), INFO_CTRL_PANEL_START_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); StartServerTask newTask = new StartServerTask(getInfo(), progressDialog); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } if (errors.size() == 0) { launchOperation(newTask, INFO_CTRL_PANEL_STARTING_SERVER_SUMMARY.get(), INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_STARTING_SERVER_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_STARTING_SERVER_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_STARTING_SERVER_ERROR_DETAILS, progressDialog); progressDialog.setVisible(true); } else { displayErrorDialog(errors); } } /** * Stops the server. This method will launch a task and open a progress * dialog that will stop the server. This method must be called from the * event thread. * */ protected void stopServer() { LinkedHashSet errors = new LinkedHashSet(); ProgressDialog progressDialog = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(this), INFO_CTRL_PANEL_STOP_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); StopServerTask newTask = new StopServerTask(getInfo(), progressDialog); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } boolean confirmed = true; if (errors.size() == 0) { confirmed = displayConfirmationDialog( INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_CONFIRM_STOP_SERVER_DETAILS.get()); } if ((errors.size() == 0) && confirmed) { launchOperation(newTask, INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_STOPPING_SERVER_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_STOPPING_SERVER_ERROR_DETAILS, progressDialog); progressDialog.setVisible(true); } if (errors.size() > 0) { displayErrorDialog(errors); } } /** * Restarts the server. This method will launch a task and open a progress * dialog that will restart the server. This method must be called from the * event thread. * */ protected void restartServer() { LinkedHashSet errors = new LinkedHashSet(); ProgressDialog progressDialog = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(this), INFO_CTRL_PANEL_RESTART_SERVER_PROGRESS_DLG_TITLE.get(), getInfo()); RestartServerTask newTask = new RestartServerTask(getInfo(), progressDialog); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } boolean confirmed = true; if (errors.size() == 0) { confirmed = displayConfirmationDialog( INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_CONFIRM_RESTART_SERVER_DETAILS.get()); } if ((errors.size() == 0) && confirmed) { launchOperation(newTask, INFO_CTRL_PANEL_STOPPING_SERVER_SUMMARY.get(), INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_RESTARTING_SERVER_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_RESTARTING_SERVER_ERROR_DETAILS, progressDialog); progressDialog.setVisible(true); } if (errors.size() > 0) { displayErrorDialog(errors); } } /** * Displays a dialog asking for authentication. This method must be called * from the event thread. * */ protected void authenticate() { if (!getLoginDialog().isVisible()) { getLoginDialog().setVisible(true); } getLoginDialog().toFront(); } /** * Returns the login dialog that is displayed when the method authenticate * is called. * @return the login dialog that is displayed when the method authenticate * is called. */ protected GenericDialog getLoginDialog() { if (isLocal()) { GenericDialog loginDialog = ControlCenterMainPane.getLocalServerLoginDialog(getInfo()); Utilities.centerGoldenMean(loginDialog, Utilities.getFrame(this)); loginDialog.setModal(true); return loginDialog; } else { GenericDialog localOrRemoteDialog = ControlCenterMainPane.getLocalOrRemoteDialog(getInfo()); Utilities.centerGoldenMean(localOrRemoteDialog, Utilities.getFrame(this)); localOrRemoteDialog.setModal(true); return localOrRemoteDialog; } } /** * Tells whether an entry exists or not. Actually it tells if we could find * a given entry or not. * @param dn the DN of the entry to look for. * @return true if the entry with the provided DN could be found * and false otherwise. */ protected boolean entryExists(String dn) { boolean entryExists = false; try { SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); ctls.setReturningAttributes( new String[] { SchemaConstants.NO_ATTRIBUTES }); String filter = BrowserController.ALL_OBJECTS_FILTER; NamingEnumeration result = getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); try { while (result.hasMore()) { SearchResult sr = result.next(); entryExists = sr != null; } } finally { result.close(); } } catch (Throwable t) { } return entryExists; } /** * Tells whether a given entry exists and contains one of the specified object * classes. * @param dn the DN of the entry. * @param objectClasses the object classes to check. * @return true if the entry exists and contains one of the * specified object classes and false otherwise. */ protected boolean hasObjectClass(String dn, String... objectClasses) { try { SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); ctls.setReturningAttributes( new String[] { ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME }); String filter = BrowserController.ALL_OBJECTS_FILTER; NamingEnumeration result = getInfo().getDirContext().search(Utilities.getJNDIName(dn), filter, ctls); try { while (result.hasMore()) { SearchResult sr = result.next(); Set values = ConnectionUtils.getValues(sr, ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME); if (values != null) { for (String s : values) { for (String objectClass: objectClasses) { if (s.equalsIgnoreCase(objectClass)) { return true; } } } } } } finally { result.close(); } } catch (Throwable t) { } return false; } /** * Returns the border to be used in the right panel of the dialog with a tree * on the left (for instance the schema browser, entry browser and index * browser). * @return the border to be used in the right panel. */ protected Border getRightPanelBorder() { return ColorAndFontConstants.textAreaBorder; } /** * Returns the monitoring value in a String form to be displayed to the user. * @param attr the attribute to analyze. * @param monitoringEntry the monitoring entry. * @return the monitoring value in a String form to be displayed to the user. */ public static String getMonitoringValue(MonitoringAttributes attr, CustomSearchResult monitoringEntry) { return Utilities.getMonitoringValue(attr, monitoringEntry); } /** * Updates the monitoring information writing it to a list of labels. * @param monitoringAttrs the monitoring operations whose information we want * to update. * @param monitoringLabels the monitoring labels to be updated. * @param monitoringEntry the monitoring entry containing the information to * be displayed. */ protected void updateMonitoringInfo( List monitoringAttrs, List monitoringLabels, CustomSearchResult monitoringEntry) { for (int i=0 ; inull. * @param attrName the attribute name. * @return the first value for a given attribute in the provided entry. */ protected Object getFirstMonitoringValue(CustomSearchResult sr, String attrName) { return Utilities.getFirstMonitoringValue(sr, attrName); } /** * Returns the label to be used in panels (with ':') based on the definition * of the monitoring attribute. * @param attr the monitoring attribute. * @return the label to be used in panels (with ':') based on the definition * of the monitoring attribute. */ protected static LocalizableMessage getLabel(MonitoringAttributes attr) { return INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(attr.getMessage()); } /** * Returns the command-line arguments associated with the provided schedule. * @param schedule the schedule. * @return the command-line arguments associated with the provided schedule. */ protected List getScheduleArgs(ScheduleType schedule) { List args = new ArrayList(2); switch (schedule.getType()) { case LAUNCH_LATER: args.add("--start"); args.add(getStartTimeForTask(schedule.getLaunchLaterDate())); break; case LAUNCH_PERIODICALLY: args.add("--recurringTask"); args.add(schedule.getCronValue()); break; } return args; } /** * Checks whether the server is running or not and depending on the schedule * updates the list of errors with the errors found. * @param schedule the schedule. * @param errors the list of errors. * @param label the label to be marked as invalid if errors where encountered. */ protected void addScheduleErrors(ScheduleType schedule, Collection errors, JLabel label) { if (!isServerRunning()) { ScheduleType.Type type = schedule.getType(); if (type == ScheduleType.Type.LAUNCH_LATER) { errors.add(ERR_CTRL_PANEL_LAUNCH_LATER_REQUIRES_SERVER_RUNNING.get()); setPrimaryInvalid(label); } else if (type == ScheduleType.Type.LAUNCH_PERIODICALLY) { errors.add( ERR_CTRL_PANEL_LAUNCH_SCHEDULE_REQUIRES_SERVER_RUNNING.get()); setPrimaryInvalid(label); } } } private String getStartTimeForTask(Date date) { return taskDateFormat.format(date); } /** * Checks whether the provided superior object classes are compatible with * the provided object class type. If not, the method updates the provided * list of error messages with a message describing the incompatibility. * @param objectClassSuperiors the superior object classes. * @param objectClassType the object class type. * @param errors the list of error messages. */ protected void checkCompatibleSuperiors(Set objectClassSuperiors, ObjectClassType objectClassType, List errors) { SortedSet notCompatibleClasses = new TreeSet(new LowerCaseComparator()); for (ObjectClass oc : objectClassSuperiors) { if (oc.getObjectClassType() == ObjectClassType.ABSTRACT) { // Nothing to do. } else if (oc.getObjectClassType() != objectClassType) { notCompatibleClasses.add(oc.getNameOrOID()); } } if (!notCompatibleClasses.isEmpty()) { String arg = Utilities.getStringFromCollection(notCompatibleClasses, ", "); if (objectClassType == ObjectClassType.STRUCTURAL) { errors.add( ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_STRUCTURAL.get(arg)); } else if (objectClassType == ObjectClassType.AUXILIARY) { errors.add( ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_AUXILIARY.get(arg)); } else if (objectClassType == ObjectClassType.ABSTRACT) { errors.add( ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_ABSTRACT.get(arg)); } } } }