/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2008-2009 Sun Microsystems, Inc.
|
* Portions Copyright 2011-2016 ForgeRock AS.
|
*/
|
package org.opends.guitools.controlpanel.ui;
|
|
import static org.opends.messages.AdminToolMessages.*;
|
import static org.opends.messages.QuickSetupMessages.*;
|
import static org.opends.messages.ToolMessages.ERR_MAKELDIF_CANNOT_WRITE_ENTRY;
|
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
|
|
import java.awt.Component;
|
import java.awt.GridBagConstraints;
|
import java.awt.GridBagLayout;
|
import java.awt.event.ItemEvent;
|
import java.awt.event.ItemListener;
|
import java.io.File;
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.Collection;
|
import java.util.Collections;
|
import java.util.Enumeration;
|
import java.util.HashSet;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Random;
|
import java.util.Set;
|
import java.util.SortedSet;
|
import java.util.TreeSet;
|
|
import javax.swing.AbstractButton;
|
import javax.swing.Box;
|
import javax.swing.ButtonGroup;
|
import javax.swing.DefaultComboBoxModel;
|
import javax.swing.JButton;
|
import javax.swing.JComboBox;
|
import javax.swing.JComponent;
|
import javax.swing.JLabel;
|
import javax.swing.JPanel;
|
import javax.swing.JRadioButton;
|
import javax.swing.JTextField;
|
import javax.swing.SwingUtilities;
|
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeListener;
|
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentListener;
|
|
import org.forgerock.i18n.LocalizableMessage;
|
import org.forgerock.i18n.LocalizedIllegalArgumentException;
|
import org.forgerock.opendj.config.client.ManagementContext;
|
import org.forgerock.opendj.config.client.ldap.LDAPManagementContext;
|
import org.forgerock.opendj.ldap.DN;
|
import org.forgerock.opendj.ldap.LdapException;
|
import org.forgerock.opendj.server.config.client.BackendCfgClient;
|
import org.forgerock.opendj.server.config.client.RootCfgClient;
|
import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn.IndexType;
|
import org.opends.admin.ads.util.ConnectionWrapper;
|
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
|
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
|
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
|
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
|
import org.opends.guitools.controlpanel.event.BrowseActionListener;
|
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
|
import org.opends.guitools.controlpanel.task.OfflineUpdateException;
|
import org.opends.guitools.controlpanel.task.OnlineUpdateException;
|
import org.opends.guitools.controlpanel.task.Task;
|
import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer;
|
import org.opends.guitools.controlpanel.util.Utilities;
|
import org.opends.quicksetup.Installation;
|
import org.opends.quicksetup.installer.InstallerHelper;
|
import org.opends.quicksetup.util.Utils;
|
import org.opends.server.tools.BackendCreationHelper;
|
import org.opends.server.tools.BackendCreationHelper.CreateIndex;
|
import org.opends.server.tools.BackendTypeHelper;
|
import org.opends.server.tools.BackendTypeHelper.BackendTypeUIAdapter;
|
import org.opends.server.tools.ImportLDIF;
|
import org.opends.server.tools.makeldif.EntryWriter;
|
import org.opends.server.tools.makeldif.MakeLDIFException;
|
import org.opends.server.tools.makeldif.TemplateEntry;
|
import org.opends.server.tools.makeldif.TemplateFile;
|
import org.opends.server.types.ExistingFileBehavior;
|
import org.opends.server.types.InitializationException;
|
import org.opends.server.types.LDIFExportConfig;
|
import org.opends.server.types.OpenDsException;
|
import org.opends.server.util.LDIFException;
|
import org.opends.server.util.LDIFWriter;
|
import org.opends.server.util.SetupUtils;
|
|
import com.forgerock.opendj.cli.CommandBuilder;
|
|
/** The class that appears when the user clicks on 'New Base DN'. */
|
public class NewBaseDNPanel extends StatusGenericPanel
|
{
|
private static final int MAX_ENTRIES_NUMBER_GENERATED = 1000;
|
private static final int MAX_ENTRIES_NUMBER_GENERATED_LOCAL = 20000;
|
private static final long serialVersionUID = -2680821576362341119L;
|
private static final LocalizableMessage NEW_BACKEND_TEXT = INFO_CTRL_PANEL_NEW_BACKEND_LABEL.get();
|
|
private JComboBox<?> backends;
|
private JComboBox<BackendTypeUIAdapter> backendTypes;
|
private JTextField newBackend;
|
private JTextField baseDN;
|
private JRadioButton onlyCreateBaseEntry;
|
private JRadioButton leaveDatabaseEmpty;
|
private JRadioButton importDataFromLDIF;
|
private JRadioButton importAutomaticallyGenerated;
|
private JTextField path;
|
private JTextField numberOfEntries;
|
private JLabel lRemoteFileHelp;
|
private JButton browseImportPath;
|
|
private JLabel lBackend;
|
private JLabel lDirectoryBaseDN;
|
private JLabel lPath;
|
private JLabel lNumberOfEntries;
|
private JLabel lDirectoryData;
|
private JLabel lNewBackendType;
|
|
private DocumentListener documentListener;
|
|
/** Default constructor. */
|
public NewBaseDNPanel()
|
{
|
super();
|
createLayout();
|
}
|
|
@Override
|
public LocalizableMessage getTitle()
|
{
|
return INFO_CTRL_PANEL_NEW_BASE_DN_TITLE.get();
|
}
|
|
@Override
|
public Component getPreferredFocusComponent()
|
{
|
return baseDN;
|
}
|
|
@Override
|
public void toBeDisplayed(boolean visible)
|
{
|
if (visible)
|
{
|
documentListener.changedUpdate(null);
|
}
|
}
|
|
/** Creates the layout of the panel (but the contents are not populated here). */
|
private void createLayout()
|
{
|
GridBagConstraints gbc = new GridBagConstraints();
|
addErrorPanel(gbc);
|
addBackendLabel(gbc);
|
addBackendNamesComboBox(gbc);
|
addNewBackendName(gbc);
|
addNewBackendTypeLabel(gbc);
|
addNewBackendTypeComboBox(gbc);
|
addBaseDNLabel(gbc);
|
addBaseDNTextField(gbc);
|
addBaseDNInlineHelp(gbc);
|
addDirectoryDataLabel(gbc);
|
addImportDataChoiceSection(gbc);
|
addBottomGlue(gbc);
|
}
|
|
private void addErrorPanel(GridBagConstraints gbc)
|
{
|
gbc.gridx = 0;
|
gbc.gridy = 0;
|
gbc.gridwidth = 3;
|
addErrorPane(gbc);
|
}
|
|
private void addBackendLabel(GridBagConstraints gbc)
|
{
|
gbc.anchor = GridBagConstraints.WEST;
|
gbc.weightx = 0.0;
|
gbc.gridwidth = 1;
|
gbc.gridy++;
|
gbc.fill = GridBagConstraints.NONE;
|
lBackend = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BACKEND_LABEL.get());
|
add(lBackend, gbc);
|
}
|
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
private void addBackendNamesComboBox(GridBagConstraints gbc)
|
{
|
gbc.insets.left = 10;
|
gbc.gridx = 1;
|
backends = Utilities.createComboBox();
|
backends.setModel(new DefaultComboBoxModel(new Object[] { "bogus", NEW_BACKEND_TEXT }));
|
backends.setRenderer(new CustomListCellRenderer(backends));
|
backends.addItemListener(new IgnoreItemListener(backends));
|
gbc.gridwidth = 1;
|
add(backends, gbc);
|
}
|
|
private void addNewBackendTypeLabel(GridBagConstraints gbc)
|
{
|
gbc.insets.top = 10;
|
gbc.gridx = 0;
|
gbc.gridy++;
|
gbc.insets.left = 0;
|
gbc.gridwidth = 1;
|
lNewBackendType = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_NEW_BACKEND_TYPE_LABEL.get());
|
add(lNewBackendType, gbc);
|
addBackendNameChangeListener(lNewBackendType);
|
}
|
|
@SuppressWarnings("unchecked")
|
private void addNewBackendTypeComboBox(GridBagConstraints gbc)
|
{
|
gbc.insets.left = 10;
|
gbc.gridx = 1;
|
gbc.gridwidth = 1;
|
final BackendTypeHelper backendTypeHelper = new BackendTypeHelper();
|
backendTypes = Utilities.createComboBox();
|
backendTypes.setModel(new DefaultComboBoxModel<>(backendTypeHelper.getBackendTypeUIAdaptors()));
|
backendTypes.setRenderer(new CustomListCellRenderer(backendTypes));
|
backendTypes.addItemListener(new IgnoreItemListener(backendTypes));
|
add(backendTypes, gbc);
|
addBackendNameChangeListener(backendTypes);
|
}
|
|
private void addNewBackendName(GridBagConstraints gbc)
|
{
|
gbc.gridx = 2;
|
newBackend = Utilities.createTextField();
|
newBackend.setColumns(18);
|
add(newBackend, gbc);
|
addBackendNameChangeListener(newBackend);
|
}
|
|
private void addBackendNameChangeListener(final JComponent component)
|
{
|
ItemListener comboListener = new ItemListener()
|
{
|
@Override
|
public void itemStateChanged(ItemEvent ev)
|
{
|
Object o = backends.getSelectedItem();
|
component.setVisible(NEW_BACKEND_TEXT.equals(o));
|
}
|
};
|
backends.addItemListener(comboListener);
|
comboListener.itemStateChanged(null);
|
}
|
|
private void addBaseDNLabel(GridBagConstraints gbc)
|
{
|
gbc.insets.top = 10;
|
gbc.gridx = 0;
|
gbc.gridy++;
|
gbc.insets.left = 0;
|
gbc.gridwidth = 1;
|
lDirectoryBaseDN = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_LABEL.get());
|
add(lDirectoryBaseDN, gbc);
|
}
|
|
private void addBaseDNTextField(GridBagConstraints gbc)
|
{
|
gbc.gridx = 1;
|
gbc.insets.left = 10;
|
gbc.gridwidth = 2;
|
baseDN = Utilities.createTextField();
|
documentListener = new DocumentListener()
|
{
|
@Override
|
public void changedUpdate(DocumentEvent ev)
|
{
|
String text = baseDN.getText().trim();
|
setEnabledOK(text != null && text.length() > 0 && !errorPane.isVisible());
|
}
|
|
@Override
|
public void removeUpdate(DocumentEvent ev)
|
{
|
changedUpdate(ev);
|
}
|
|
@Override
|
public void insertUpdate(DocumentEvent ev)
|
{
|
changedUpdate(ev);
|
}
|
};
|
baseDN.getDocument().addDocumentListener(documentListener);
|
gbc.weightx = 1.0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
add(baseDN, gbc);
|
}
|
|
private void addBaseDNInlineHelp(GridBagConstraints gbc)
|
{
|
gbc.gridy++;
|
gbc.anchor = GridBagConstraints.EAST;
|
gbc.insets.top = 3;
|
JLabel inlineHelp = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_BASE_DN_EXAMPLE.get());
|
add(inlineHelp, gbc);
|
}
|
|
private void addDirectoryDataLabel(GridBagConstraints gbc)
|
{
|
gbc.gridx = 0;
|
gbc.gridy++;
|
gbc.insets.left = 0;
|
gbc.insets.top = 10;
|
gbc.gridwidth = 1;
|
gbc.weightx = 0.0;
|
lDirectoryData = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DIRECTORY_DATA_LABEL.get());
|
add(lDirectoryData, gbc);
|
}
|
|
private void addImportDataChoiceSection(GridBagConstraints gbc)
|
{
|
onlyCreateBaseEntry = Utilities.createRadioButton(INFO_CTRL_PANEL_ONLY_CREATE_BASE_ENTRY_LABEL.get());
|
onlyCreateBaseEntry.setSelected(false);
|
|
gbc.insets.left = 10;
|
gbc.gridx = 1;
|
gbc.gridwidth = 2;
|
add(onlyCreateBaseEntry, gbc);
|
|
leaveDatabaseEmpty = Utilities.createRadioButton(INFO_CTRL_PANEL_LEAVE_DATABASE_EMPTY_LABEL.get());
|
leaveDatabaseEmpty.setSelected(false);
|
|
gbc.gridy++;
|
gbc.gridwidth = 2;
|
gbc.insets.top = 5;
|
add(leaveDatabaseEmpty, gbc);
|
|
importDataFromLDIF = Utilities.createRadioButton(INFO_CTRL_PANEL_IMPORT_FROM_LDIF_LABEL.get());
|
importDataFromLDIF.setSelected(false);
|
|
gbc.gridy++;
|
gbc.gridwidth = 2;
|
add(importDataFromLDIF, gbc);
|
|
gbc.gridy++;
|
gbc.gridwidth = 2;
|
gbc.insets.left = 30;
|
add(createPathPanel(), gbc);
|
|
importAutomaticallyGenerated =
|
Utilities.createRadioButton(INFO_CTRL_PANEL_IMPORT_AUTOMATICALLY_GENERATED_LABEL.get());
|
importAutomaticallyGenerated.setOpaque(false);
|
importAutomaticallyGenerated.setSelected(false);
|
|
gbc.gridy++;
|
gbc.gridwidth = 2;
|
gbc.insets.left = 10;
|
add(importAutomaticallyGenerated, gbc);
|
|
gbc.gridy++;
|
gbc.gridwidth = 2;
|
gbc.insets.left = 30;
|
add(createNumberOfUsersPanel(), gbc);
|
|
ButtonGroup group = new ButtonGroup();
|
group.add(onlyCreateBaseEntry);
|
group.add(leaveDatabaseEmpty);
|
group.add(importDataFromLDIF);
|
group.add(importAutomaticallyGenerated);
|
|
ChangeListener listener = new ChangeListener()
|
{
|
@Override
|
public void stateChanged(ChangeEvent ev)
|
{
|
browseImportPath.setEnabled(importDataFromLDIF.isSelected());
|
lPath.setEnabled(importDataFromLDIF.isSelected());
|
lRemoteFileHelp.setEnabled(importDataFromLDIF.isSelected());
|
numberOfEntries.setEnabled(importAutomaticallyGenerated.isSelected());
|
lNumberOfEntries.setEnabled(importAutomaticallyGenerated.isSelected());
|
}
|
};
|
|
Enumeration<AbstractButton> buttons = group.getElements();
|
while (buttons.hasMoreElements())
|
{
|
buttons.nextElement().addChangeListener(listener);
|
}
|
onlyCreateBaseEntry.setSelected(true);
|
listener.stateChanged(null);
|
}
|
|
@Override
|
public void configurationChanged(ConfigurationChangeEvent ev)
|
{
|
ServerDescriptor desc = ev.getNewDescriptor();
|
final SortedSet<String> sortedBackends = new TreeSet<>();
|
for (BackendDescriptor backend : desc.getBackends())
|
{
|
if (!backend.isConfigBackend())
|
{
|
sortedBackends.add(backend.getBackendID());
|
}
|
}
|
|
List<Object> newElements = new ArrayList<Object>(sortedBackends);
|
if (!sortedBackends.isEmpty())
|
{
|
newElements.add(COMBO_SEPARATOR);
|
}
|
newElements.add(NEW_BACKEND_TEXT);
|
super.updateComboBoxModel(newElements, (DefaultComboBoxModel<?>) backends.getModel());
|
updateErrorPaneAndOKButtonIfAuthRequired(desc,
|
isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_CREATE_BASE_DN.get()
|
: INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
lRemoteFileHelp.setVisible(!isLocal());
|
browseImportPath.setVisible(isLocal());
|
}
|
});
|
}
|
|
private JPanel createPathPanel()
|
{
|
JPanel panel = new JPanel(new GridBagLayout());
|
panel.setOpaque(false);
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.gridwidth = 1;
|
gbc.gridy = 0;
|
gbc.gridx = 0;
|
lPath = Utilities.createDefaultLabel(INFO_CTRL_PANEL_IMPORT_LDIF_PATH_LABEL.get());
|
panel.add(lPath, gbc);
|
|
gbc.gridx = 1;
|
gbc.insets.left = 10;
|
path = Utilities.createTextField();
|
gbc.weightx = 1.0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
panel.add(path, gbc);
|
browseImportPath = Utilities.createButton(INFO_CTRL_PANEL_BROWSE_BUTTON_LABEL.get());
|
browseImportPath.addActionListener(
|
new BrowseActionListener(path, BrowseActionListener.BrowseType.OPEN_LDIF_FILE, this));
|
gbc.gridx = 2;
|
gbc.weightx = 0.0;
|
panel.add(browseImportPath, gbc);
|
|
gbc.gridy++;
|
gbc.gridx = 1;
|
lRemoteFileHelp = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_REMOTE_SERVER_PATH.get());
|
gbc.insets.top = 3;
|
gbc.insets.left = 10;
|
panel.add(lRemoteFileHelp, gbc);
|
|
return panel;
|
}
|
|
private JPanel createNumberOfUsersPanel()
|
{
|
JPanel panel = new JPanel(new GridBagLayout());
|
panel.setOpaque(false);
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.weightx = 0.0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
lNumberOfEntries = Utilities.createDefaultLabel(INFO_CTRL_PANEL_NUMBER_OF_USER_ENTRIES_LABEL.get());
|
panel.add(lNumberOfEntries, gbc);
|
|
gbc.gridx = 1;
|
gbc.insets.left = 10;
|
numberOfEntries = Utilities.createTextField("2000", 6);
|
panel.add(numberOfEntries, gbc);
|
|
gbc.gridx = 2;
|
gbc.insets.left = 0;
|
gbc.weightx = 1.0;
|
panel.add(Box.createHorizontalGlue(), gbc);
|
|
return panel;
|
}
|
|
@Override
|
public void cancelClicked()
|
{
|
resetLabelAsValid();
|
super.cancelClicked();
|
}
|
|
private void resetLabelAsValid()
|
{
|
setPrimaryValid(lBackend);
|
setPrimaryValid(lDirectoryBaseDN);
|
setPrimaryValid(lDirectoryData);
|
setSecondaryValid(lPath);
|
setSecondaryValid(lNumberOfEntries);
|
}
|
|
@Override
|
protected void checkOKButtonEnable()
|
{
|
documentListener.changedUpdate(null);
|
}
|
|
@Override
|
public void okClicked()
|
{
|
resetLabelAsValid();
|
|
final Set<LocalizableMessage> errors = new LinkedHashSet<>();
|
final ServerDescriptor desc = getInfo().getServerDescriptor();
|
final Set<BackendDescriptor> existingBackends = desc.getBackends();
|
|
final String backendName = validateBackendName(existingBackends, errors);
|
final String dn = validateBaseDN(backendName, existingBackends, errors);
|
validateImportLDIFFilePath(errors);
|
validateAutomaticallyGenerated(errors);
|
|
if (errors.isEmpty())
|
{
|
final ProgressDialog progressDialog = new ProgressDialog(
|
Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo());
|
final NewBaseDNTask newTask = new NewBaseDNTask(getInfo(), progressDialog);
|
for (Task task : getInfo().getTasks())
|
{
|
task.canLaunch(newTask, errors);
|
}
|
|
if (errors.isEmpty())
|
{
|
launchOperation(newTask,
|
INFO_CTRL_PANEL_CREATING_BASE_DN_SUMMARY.get(dn),
|
INFO_CTRL_PANEL_CREATING_BASE_DN_COMPLETE.get(),
|
INFO_CTRL_PANEL_CREATING_BASE_DN_SUCCESSFUL.get(dn),
|
ERR_CTRL_PANEL_CREATING_BASE_DN_ERROR_SUMMARY.get(dn),
|
null,
|
ERR_CTRL_PANEL_CREATING_BASE_DN_ERROR_DETAILS,
|
progressDialog);
|
progressDialog.setVisible(true);
|
baseDN.setText("");
|
baseDN.grabFocus();
|
Utilities.getParentDialog(this).setVisible(false);
|
}
|
}
|
|
if (!errors.isEmpty())
|
{
|
displayErrorDialog(errors);
|
}
|
}
|
|
/** Returns the existing or the new backend name, once user have clicked on 'OK' button. */
|
private String validateBackendName(
|
final Set<BackendDescriptor> existingBackends, final Set<LocalizableMessage> errors)
|
{
|
final Object selectedItem = backends.getSelectedItem();
|
if (!selectedItem.equals(NEW_BACKEND_TEXT))
|
{
|
return selectedItem.toString();
|
}
|
|
final String backendName = newBackend.getText().trim();
|
if (backendName.length() == 0)
|
{
|
errors.add(ERR_NEW_BACKEND_NAME_REQUIRED.get());
|
setPrimaryInvalid(lBackend);
|
return backendName;
|
}
|
|
// Check that the backend is not already defined.
|
for (BackendDescriptor backend : existingBackends)
|
{
|
if (backendName.equalsIgnoreCase(backend.getBackendID()))
|
{
|
errors.add(ERR_BACKEND_ALREADY_EXISTS.get(backendName));
|
setPrimaryInvalid(lBackend);
|
}
|
}
|
|
return backendName;
|
}
|
|
private String validateBaseDN(final String backendName, final Set<BackendDescriptor> existingBackends,
|
final Set<LocalizableMessage> errors)
|
{
|
String dn = baseDN.getText();
|
if (dn.trim().length() == 0)
|
{
|
errors.add(ERR_NEW_BASE_DN_VALUE_REQUIRED.get());
|
setPrimaryInvalid(lDirectoryBaseDN);
|
return dn;
|
}
|
|
try
|
{
|
final DN theDN = DN.valueOf(dn);
|
for (final BackendDescriptor backend : existingBackends)
|
{
|
for (final BaseDNDescriptor baseDNDescriptor : backend.getBaseDns())
|
{
|
DN baseDN = baseDNDescriptor.getDn();
|
if (baseDN.equals(theDN))
|
{
|
return invalidBaseDNValue(dn, ERR_BASE_DN_ALREADY_EXISTS.get(dn), errors);
|
}
|
else if (baseDN.isSuperiorOrEqualTo(theDN) && backendName.equalsIgnoreCase(backend.getBackendID()))
|
{
|
return invalidBaseDNValue(dn, ERR_BASE_DN_ANCESTOR_EXISTS.get(baseDN), errors);
|
}
|
else if (theDN.isSuperiorOrEqualTo(baseDN) && backendName.equalsIgnoreCase(backend.getBackendID()))
|
{
|
return invalidBaseDNValue(dn, ERR_BASE_DN_DN_IS_ANCESTOR_OF.get(baseDN), errors);
|
}
|
}
|
}
|
}
|
catch (LocalizedIllegalArgumentException e)
|
{
|
errors.add(INFO_CTRL_PANEL_INVALID_DN_DETAILS.get(dn, e.getMessageObject()));
|
setPrimaryInvalid(lDirectoryBaseDN);
|
}
|
|
return dn;
|
}
|
|
/** Mark the provided base DN as invalid with the provided reason and return it. */
|
private String invalidBaseDNValue(final String dn, final LocalizableMessage errorMsg,
|
final Set<LocalizableMessage> errors)
|
{
|
errors.add(errorMsg);
|
setPrimaryInvalid(lDirectoryBaseDN);
|
return dn;
|
}
|
|
private void validateImportLDIFFilePath(final Set<LocalizableMessage> errors)
|
{
|
// TODO: what happens with sub-suffixes?
|
if (importDataFromLDIF.isSelected())
|
{
|
String ldifPath = path.getText();
|
if (ldifPath == null || "".equals(ldifPath.trim()))
|
{
|
errors.add(INFO_NO_LDIF_PATH.get());
|
setSecondaryInvalid(lPath);
|
}
|
else if (isLocal() && !Utils.fileExists(ldifPath))
|
{
|
errors.add(INFO_LDIF_FILE_DOES_NOT_EXIST.get());
|
setSecondaryInvalid(lPath);
|
}
|
}
|
}
|
|
private void validateAutomaticallyGenerated(final Set<LocalizableMessage> errors)
|
{
|
if (importAutomaticallyGenerated.isSelected())
|
{
|
final int minValue = 1;
|
final int maxValue = isLocal() ? MAX_ENTRIES_NUMBER_GENERATED_LOCAL : MAX_ENTRIES_NUMBER_GENERATED;
|
final LocalizableMessage errorMsg = ERR_NUMBER_OF_ENTRIES_INVALID.get(minValue, maxValue);
|
if (!checkIntValue(errors, numberOfEntries.getText(), minValue, maxValue, errorMsg))
|
{
|
setSecondaryInvalid(lNumberOfEntries);
|
}
|
}
|
}
|
|
private String getBackendName()
|
{
|
Object backendName = backends.getSelectedItem();
|
if (NEW_BACKEND_TEXT.equals(backendName))
|
{
|
return newBackend.getText().trim();
|
}
|
else if (backendName != null)
|
{
|
return backendName.toString();
|
}
|
return null;
|
}
|
|
private BackendTypeUIAdapter getSelectedBackendType()
|
{
|
return (BackendTypeUIAdapter) backendTypes.getSelectedItem();
|
}
|
|
private boolean isNewBackend()
|
{
|
return NEW_BACKEND_TEXT.equals(backends.getSelectedItem());
|
}
|
|
/** The task in charge of creating the base DN (and if required, the backend). */
|
private class NewBaseDNTask extends Task
|
{
|
private final Set<String> backendSet;
|
private final String newBaseDN;
|
private final int progressAfterConfigurationUpdate;
|
|
/**
|
* The constructor of the task.
|
*
|
* @param info
|
* the control panel info.
|
* @param dlg
|
* the progress dialog that shows the progress of the task.
|
*/
|
private NewBaseDNTask(ControlPanelInfo info, ProgressDialog dlg)
|
{
|
super(info, dlg);
|
backendSet = new HashSet<>();
|
backendSet.add(getBackendName());
|
newBaseDN = baseDN.getText();
|
progressAfterConfigurationUpdate = computeProgress();
|
}
|
|
private int computeProgress()
|
{
|
if (onlyCreateBaseEntry.isSelected())
|
{
|
return 40;
|
}
|
else if (leaveDatabaseEmpty.isSelected())
|
{
|
return 90;
|
}
|
else if (importAutomaticallyGenerated.isSelected())
|
{
|
int nEntries = Integer.parseInt(numberOfEntries.getText().trim());
|
if (nEntries < 500)
|
{
|
return 30;
|
}
|
else if (nEntries < 3000)
|
{
|
return 15;
|
}
|
else
|
{
|
return 5;
|
}
|
}
|
return -1;
|
}
|
|
@Override
|
public Type getType()
|
{
|
return Type.NEW_BASEDN;
|
}
|
|
@Override
|
public LocalizableMessage getTaskDescription()
|
{
|
return INFO_CTRL_PANEL_NEW_BASE_DN_TASK_DESCRIPTION.get(newBaseDN, backendSet.iterator().next());
|
}
|
|
@Override
|
public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons)
|
{
|
boolean canLaunch = true;
|
if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched))
|
{
|
// All the operations are incompatible if they apply to this backend.
|
Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends());
|
backends.retainAll(getBackends());
|
if (!backends.isEmpty())
|
{
|
incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched));
|
canLaunch = false;
|
}
|
}
|
return canLaunch;
|
}
|
|
private String getDataCommandLineToDisplay()
|
{
|
StringBuilder sb = new StringBuilder();
|
sb.append(getDataCommandLineName());
|
Collection<String> args = getObfuscatedCommandLineArguments(getDataCommandLineArguments(path.getText(), false));
|
args.removeAll(getConfigCommandLineArguments());
|
for (String arg : args)
|
{
|
sb.append(" ").append(CommandBuilder.escapeValue(arg));
|
}
|
return sb.toString();
|
}
|
|
private String getDataCommandLineName()
|
{
|
if (!leaveDatabaseEmpty.isSelected())
|
{
|
return getCommandLinePath(isLocal() ? "import-ldif" : "ldapmodify");
|
}
|
return null;
|
}
|
|
/**
|
* Returns the arguments of the command-line that can be used to generate
|
* the data.
|
*
|
* @param ldifFile
|
* the LDIF file.
|
* @param useTemplate
|
* whether to use a template or not.
|
* @return the arguments of the command-line that can be used to generate
|
* the data.
|
*/
|
private List<String> getDataCommandLineArguments(String ldifFile, boolean useTemplate)
|
{
|
List<String> args = new ArrayList<>();
|
if (!leaveDatabaseEmpty.isSelected())
|
{
|
if (isLocal())
|
{
|
if (!useTemplate)
|
{
|
args.add("--ldifFile");
|
args.add(ldifFile);
|
}
|
else
|
{
|
args.add("--templateFile");
|
args.add(ldifFile);
|
args.add("--randomSeed");
|
args.add("0");
|
}
|
args.add("--backendID");
|
args.add(getBackendName());
|
}
|
else
|
{
|
// If we are not local, we use ldapmodify to update the contents.
|
args.add("-f");
|
args.add(ldifFile);
|
}
|
args.addAll(getConnectionCommandLineArguments(true, !isLocal()));
|
|
if (isServerRunning() && isLocal())
|
{
|
args.addAll(getConfigCommandLineArguments());
|
}
|
|
args.add(getNoPropertiesFileArgument());
|
}
|
|
return args;
|
}
|
|
private void updateConfigurationOnline() throws Exception
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
List<String> args = getObfuscatedCommandLineArguments(getDSConfigCommandLineArguments());
|
args.removeAll(getConfigCommandLineArguments());
|
printEquivalentCommandLine(
|
getConfigCommandLineFullPath(), args, INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CREATE_BASE_DN.get());
|
}
|
});
|
|
performTask();
|
}
|
|
private void updateConfigurationOffline() throws Exception
|
{
|
stopPoolingAndInitializeConfiguration();
|
try
|
{
|
performTask();
|
}
|
finally
|
{
|
startPoolingAndInitializeConfiguration();
|
}
|
}
|
|
private void printCreateNewBackendProgress(final String backendName) throws OpenDsException
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
LocalizableMessage message = INFO_CTRL_PANEL_CREATING_BACKEND_PROGRESS.get(backendName, newBaseDN);
|
getProgressDialog().appendProgressHtml(
|
Utilities.getProgressWithPoints(message, ColorAndFontConstants.progressFont));
|
}
|
});
|
}
|
|
private void performTask() throws Exception
|
{
|
final String backendName = getBackendName();
|
if (isNewBackend())
|
{
|
printCreateNewBackendProgress(backendName);
|
createBackend(backendName);
|
printTaskDone();
|
displayCreateAdditionalIndexesDsConfigCmdLine();
|
printTaskDone();
|
}
|
else
|
{
|
printCreateNewBaseDNProgress(backendName);
|
addNewBaseDN(backendName);
|
printTaskDone();
|
}
|
refreshProgressBar();
|
}
|
|
private void createBackend(String backendName) throws Exception
|
{
|
if (!isServerRunning())
|
{
|
createBackendOffline(backendName);
|
}
|
else
|
{
|
createBackendOnline(backendName, getInfo().getConnection());
|
}
|
}
|
|
private void createBackendOffline(String backendName) throws OpenDsException
|
{
|
try
|
{
|
Set<DN> baseDNs = Collections.singleton(DN.valueOf(newBaseDN));
|
BackendCreationHelper.createBackendOffline(backendName, baseDNs, getSelectedBackendType().getBackend());
|
}
|
catch (Exception e)
|
{
|
throw new OfflineUpdateException(ERROR_CTRL_PANEL_CREATE_NEW_BACKEND.get(backendName, e.getMessage()), e);
|
}
|
}
|
|
private void createBackendOnline(String backendName, ConnectionWrapper conn) throws Exception
|
{
|
Set<DN> baseDNs = Collections.singleton(DN.valueOf(newBaseDN));
|
BackendCreationHelper.createBackendOnline(backendName, baseDNs, getSelectedBackendType().getBackend(), conn);
|
}
|
|
private RootCfgClient getRootConfigurationClient() throws LdapException
|
{
|
return getInfo().getConnection().getRootConfiguration();
|
}
|
|
private void addNewBaseDN(String backendName) throws Exception
|
{
|
if (!isServerRunning())
|
{
|
addNewBaseDNOffline(backendName);
|
return;
|
}
|
|
final BackendCfgClient backend = getRootConfigurationClient().getBackend(backendName);
|
final Set<DN> baseDNs = backend.getBaseDN();
|
baseDNs.add(DN.valueOf(newBaseDN));
|
backend.setBaseDN(baseDNs);
|
backend.commit();
|
}
|
|
private void addNewBaseDNOffline(String backendName) throws OpenDsException
|
{
|
try
|
{
|
getInfo().initializeConfigurationFramework();
|
final File config = Installation.getLocal().getCurrentConfigurationFile();
|
try (ManagementContext context = LDAPManagementContext.newLDIFManagementContext(config))
|
{
|
final BackendCfgClient backend = context.getRootConfiguration().getBackend(backendName);
|
final SortedSet<DN> baseDNs = backend.getBaseDN();
|
baseDNs.add(DN.valueOf(newBaseDN));
|
backend.setBaseDN(baseDNs);
|
backend.commit();
|
}
|
}
|
catch (Exception e)
|
{
|
throw new OfflineUpdateException(LocalizableMessage.raw(e.getMessage()), e);
|
}
|
}
|
|
private void printCreateNewBaseDNProgress(final String backendName) throws OpenDsException
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
LocalizableMessage message = INFO_CTRL_PANEL_CREATING_BASE_DN_PROGRESS.get(newBaseDN, backendName);
|
getProgressDialog().appendProgressHtml(
|
Utilities.getProgressWithPoints(message, ColorAndFontConstants.progressFont));
|
}
|
});
|
}
|
|
private void printTaskDone()
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
getProgressDialog().appendProgressHtml(
|
Utilities.getProgressDone(ColorAndFontConstants.progressFont) + "<br><br>");
|
}
|
});
|
}
|
|
private void refreshProgressBar()
|
{
|
if (progressAfterConfigurationUpdate > 0)
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
getProgressDialog().getProgressBar().setIndeterminate(false);
|
getProgressDialog().getProgressBar().setValue(progressAfterConfigurationUpdate);
|
}
|
});
|
}
|
}
|
|
private void displayCreateAdditionalIndexesDsConfigCmdLine()
|
{
|
final List<List<String>> argsArray = new ArrayList<>();
|
for (CreateIndex index : BackendCreationHelper.DEFAULT_INDEXES)
|
{
|
argsArray.add(getCreateIndexCommandLineArguments(index));
|
}
|
|
final StringBuilder sb = new StringBuilder();
|
for (List<String> args : argsArray)
|
{
|
sb.append(getEquivalentCommandLine(getCommandLinePath("dsconfig"), getObfuscatedCommandLineArguments(args)));
|
sb.append("<br><br>");
|
}
|
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
getProgressDialog().appendProgressHtml(Utilities.applyFont(
|
INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CREATE_ADDITIONAL_INDEXES.get()
|
+ "<br><br><b>" + sb + "</b>", ColorAndFontConstants.progressFont));
|
getProgressDialog().appendProgressHtml(Utilities.getProgressWithPoints(
|
INFO_CTRL_PANEL_CREATING_ADDITIONAL_INDEXES_PROGRESS.get(), ColorAndFontConstants.progressFont));
|
}
|
});
|
}
|
|
private List<String> getCreateIndexCommandLineArguments(final CreateIndex index)
|
{
|
final List<String> args = new ArrayList<>();
|
args.add("create-backend-index");
|
args.add("--backend-name");
|
args.add(getBackendName());
|
args.add("--type");
|
args.add("generic");
|
args.add("--index-name");
|
args.add(index.getName());
|
args.add("--set");
|
args.add("index-type:" + IndexType.EQUALITY);
|
if (index.shouldCreateSubstringIndex())
|
{
|
args.add("--set");
|
args.add("index-type:" + IndexType.SUBSTRING);
|
}
|
args.addAll(getConnectionCommandLineArguments());
|
args.add(getNoPropertiesFileArgument());
|
args.add("--no-prompt");
|
|
return args;
|
}
|
|
/**
|
* Creates the data in the new base DN.
|
*
|
* @throws OpenDsException
|
* if there is an error importing contents.
|
* @throws IOException
|
* if there is an err
|
*/
|
private void updateData() throws OpenDsException, IOException
|
{
|
final boolean leaveEmpty = leaveDatabaseEmpty.isSelected();
|
final boolean createBaseEntry = onlyCreateBaseEntry.isSelected();
|
final boolean importLDIF = importDataFromLDIF.isSelected();
|
final boolean generateData = !leaveEmpty && !createBaseEntry && !importLDIF;
|
final String nEntries = numberOfEntries.getText();
|
final String ldif = path.getText();
|
|
if (leaveEmpty)
|
{
|
state = State.FINISHED_SUCCESSFULLY;
|
}
|
else
|
{
|
final ProgressDialog progressDialog = getProgressDialog();
|
String ldifFile;
|
if (importLDIF)
|
{
|
ldifFile = ldif;
|
final String cmdLine = getDataCommandLineToDisplay();
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
progressDialog.appendProgressHtml(Utilities.applyFont("Equivalent command line:<br><b>" + cmdLine
|
+ "</b><br><br>", ColorAndFontConstants.progressFont));
|
}
|
});
|
}
|
else if (createBaseEntry)
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
progressDialog.appendProgressHtml(Utilities.getProgressWithPoints(
|
INFO_PROGRESS_CREATING_BASE_ENTRY.get(newBaseDN), ColorAndFontConstants.progressFont));
|
}
|
});
|
InstallerHelper helper = new InstallerHelper();
|
File f = helper.createBaseEntryTempFile(newBaseDN);
|
ldifFile = f.getAbsolutePath();
|
}
|
else
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
if (isLocal())
|
{
|
progressDialog.appendProgressHtml(Utilities.applyFont(
|
INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED.get(nEntries).toString(),
|
ColorAndFontConstants.progressFont) + "<br>");
|
}
|
else
|
{
|
getProgressDialog().appendProgressHtml(Utilities.getProgressWithPoints(
|
INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED_REMOTE.get(nEntries),
|
ColorAndFontConstants.progressFont));
|
}
|
}
|
});
|
|
final File templateFile = SetupUtils.createTemplateFile(newBaseDN, Integer.parseInt(nEntries));
|
if (!isLocal())
|
{
|
try
|
{
|
ldifFile = generateLdifFile(templateFile);
|
}
|
catch (IOException | OnlineUpdateException | InitializationException | MakeLDIFException e)
|
{
|
throw new OnlineUpdateException(
|
ERR_CTRL_PANEL_ERROR_CREATING_NEW_DATA_LDIF.get(e.getLocalizedMessage()), null);
|
}
|
finally
|
{
|
templateFile.delete();
|
}
|
}
|
else
|
{
|
ldifFile = templateFile.getAbsolutePath();
|
}
|
}
|
|
List<String> arguments = getDataCommandLineArguments(ldifFile, generateData);
|
String[] args = new String[arguments.size()];
|
arguments.toArray(args);
|
if (createBaseEntry || !isLocal())
|
{
|
outPrintStream.setNotifyListeners(false);
|
errorPrintStream.setNotifyListeners(false);
|
}
|
try
|
{
|
if (isServerRunning() && (isLocal() || importLDIF))
|
{
|
returnCode = ImportLDIF.mainImportLDIF(args, false, outPrintStream, errorPrintStream);
|
}
|
else
|
{
|
returnCode = executeCommandLine(getDataCommandLineName(), args);
|
}
|
}
|
finally
|
{
|
outPrintStream.setNotifyListeners(true);
|
errorPrintStream.setNotifyListeners(true);
|
}
|
|
if (returnCode != 0)
|
{
|
state = State.FINISHED_WITH_ERROR;
|
}
|
else
|
{
|
if (createBaseEntry || (!isLocal() && generateData))
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
progressDialog.appendProgressHtml(Utilities.getProgressDone(ColorAndFontConstants.progressFont));
|
}
|
});
|
}
|
state = State.FINISHED_SUCCESSFULLY;
|
}
|
}
|
}
|
|
private String generateLdifFile(final File templateFile)
|
throws IOException, OnlineUpdateException, MakeLDIFException, InitializationException
|
{
|
final File resourceDir = new File(Installation.getLocal().getConfigurationDirectory(), "MakeLDIF");
|
final TemplateFile generator = new TemplateFile(resourceDir.getAbsolutePath(), new Random(0));
|
generator.parse(templateFile.getAbsolutePath(), Collections.<LocalizableMessage>emptyList());
|
|
final File tempFile = File.createTempFile("opendj-control-panel", ".ldif");
|
tempFile.deleteOnExit();
|
final String generatedLdifFilePath = tempFile.getAbsolutePath();
|
|
|
try (final LDIFWriter ldifWriter = new LDIFWriter(
|
new LDIFExportConfig(generatedLdifFilePath, ExistingFileBehavior.OVERWRITE));)
|
{
|
generator.generateLDIF(new EntryWriter()
|
{
|
@Override
|
public boolean writeEntry(final TemplateEntry entry) throws IOException, MakeLDIFException
|
{
|
try
|
{
|
if (entry.getDN() != null)
|
{
|
return ldifWriter.writeTemplateEntry(entry);
|
}
|
return true;
|
}
|
catch (final LDIFException e)
|
{
|
throw new MakeLDIFException(
|
ERR_MAKELDIF_CANNOT_WRITE_ENTRY.get(entry.getDN(), stackTraceToSingleLineString(e)), e);
|
}
|
}
|
|
@Override public void closeEntryWriter()
|
{
|
// Nothing to do in this implementation.
|
}
|
});
|
}
|
return generatedLdifFilePath;
|
}
|
|
@Override
|
protected String getCommandLinePath()
|
{
|
return null;
|
}
|
|
@Override
|
protected List<String> getCommandLineArguments()
|
{
|
return new ArrayList<>();
|
}
|
|
private String getConfigCommandLineFullPath()
|
{
|
return isServerRunning() ? getCommandLinePath("dsconfig") : null;
|
}
|
|
private List<String> getDSConfigCommandLineArguments()
|
{
|
List<String> args = new ArrayList<>();
|
if (isServerRunning())
|
{
|
if (isNewBackend())
|
{
|
args.add("create-backend");
|
args.add("--backend-name");
|
args.add(getBackendName());
|
args.add("--set");
|
args.add("base-dn:" + newBaseDN);
|
args.add("--set");
|
args.add("enabled:true");
|
args.add("--type");
|
args.add(BackendTypeHelper.filterSchemaBackendName(getSelectedBackendType().getBackend().getName()));
|
}
|
else
|
{
|
args.add("set-backend-prop");
|
args.add("--backend-name");
|
args.add(getBackendName());
|
args.add("--add");
|
args.add("base-dn:" + newBaseDN);
|
}
|
args.addAll(getConnectionCommandLineArguments());
|
args.add(getNoPropertiesFileArgument());
|
args.add("--no-prompt");
|
}
|
return args;
|
}
|
|
@Override
|
public void runTask()
|
{
|
state = State.RUNNING;
|
lastException = null;
|
|
try
|
{
|
if (isServerRunning())
|
{
|
updateConfigurationOnline();
|
}
|
else
|
{
|
updateConfigurationOffline();
|
}
|
updateData();
|
}
|
catch (Throwable t)
|
{
|
lastException = t;
|
state = State.FINISHED_WITH_ERROR;
|
}
|
}
|
|
@Override
|
public Set<String> getBackends()
|
{
|
return backendSet;
|
}
|
}
|
}
|