/* * 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.LDAPModify; 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 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 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 sortedBackends = new TreeSet<>(); for (BackendDescriptor backend : desc.getBackends()) { if (!backend.isConfigBackend()) { sortedBackends.add(backend.getBackendID()); } } List newElements = new ArrayList(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 errors = new LinkedHashSet<>(); final ServerDescriptor desc = getInfo().getServerDescriptor(); final Set 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 existingBackends, final Set 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 existingBackends, final Set 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 errors) { errors.add(errorMsg); setPrimaryInvalid(lDirectoryBaseDN); return dn; } private void validateImportLDIFFilePath(final Set 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 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 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 incompatibilityReasons) { boolean canLaunch = true; if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) { // All the operations are incompatible if they apply to this backend. Set 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 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 getDataCommandLineArguments(String ldifFile, boolean useTemplate) { List 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("-a"); 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 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 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 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 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 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) + "

"); } }); } 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> argsArray = new ArrayList<>(); for (CreateIndex index : BackendCreationHelper.DEFAULT_INDEXES) { argsArray.add(getCreateIndexCommandLineArguments(index)); } final StringBuilder sb = new StringBuilder(); for (List args : argsArray) { sb.append(getEquivalentCommandLine(getCommandLinePath("dsconfig"), getObfuscatedCommandLineArguments(args))); sb.append("

"); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getProgressDialog().appendProgressHtml(Utilities.applyFont( INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CREATE_ADDITIONAL_INDEXES.get() + "

" + sb + "", ColorAndFontConstants.progressFont)); getProgressDialog().appendProgressHtml(Utilities.getProgressWithPoints( INFO_CTRL_PANEL_CREATING_ADDITIONAL_INDEXES_PROGRESS.get(), ColorAndFontConstants.progressFont)); } }); } private List getCreateIndexCommandLineArguments(final CreateIndex index) { final List 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:
" + cmdLine + "

", 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) + "
"); } 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 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()) { if (isLocal() || importLDIF) { returnCode = ImportLDIF.mainImportLDIF(args, false, outPrintStream, errorPrintStream); } else { returnCode = LDAPModify.mainModify(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.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 getCommandLineArguments() { return new ArrayList<>(); } private String getConfigCommandLineFullPath() { return isServerRunning() ? getCommandLinePath("dsconfig") : null; } private List getDSConfigCommandLineArguments() { List 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 getBackends() { return backendSet; } } }