001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2011-2016 ForgeRock AS.
016 */
017package org.opends.guitools.controlpanel.ui;
018
019import static org.opends.messages.AdminToolMessages.*;
020import static org.opends.messages.QuickSetupMessages.*;
021
022import java.awt.Component;
023import java.awt.GridBagConstraints;
024import java.awt.GridBagLayout;
025import java.awt.event.ItemEvent;
026import java.awt.event.ItemListener;
027import java.io.File;
028import java.io.IOException;
029import java.util.ArrayList;
030import java.util.Collection;
031import java.util.Collections;
032import java.util.Enumeration;
033import java.util.HashSet;
034import java.util.LinkedHashSet;
035import java.util.LinkedList;
036import java.util.List;
037import java.util.Set;
038import java.util.SortedSet;
039import java.util.TreeSet;
040
041import javax.swing.AbstractButton;
042import javax.swing.Box;
043import javax.swing.ButtonGroup;
044import javax.swing.DefaultComboBoxModel;
045import javax.swing.JButton;
046import javax.swing.JComboBox;
047import javax.swing.JComponent;
048import javax.swing.JLabel;
049import javax.swing.JPanel;
050import javax.swing.JRadioButton;
051import javax.swing.JTextField;
052import javax.swing.SwingUtilities;
053import javax.swing.event.ChangeEvent;
054import javax.swing.event.ChangeListener;
055import javax.swing.event.DocumentEvent;
056import javax.swing.event.DocumentListener;
057
058import org.forgerock.i18n.LocalizableMessage;
059import org.forgerock.i18n.LocalizedIllegalArgumentException;
060import org.forgerock.opendj.config.LDAPProfile;
061import org.forgerock.opendj.ldap.DN;
062import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
063import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
064import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
065import org.opends.guitools.controlpanel.datamodel.IndexTypeDescriptor;
066import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
067import org.opends.guitools.controlpanel.event.BrowseActionListener;
068import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
069import org.opends.guitools.controlpanel.task.OfflineUpdateException;
070import org.opends.guitools.controlpanel.task.OnlineUpdateException;
071import org.opends.guitools.controlpanel.task.Task;
072import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer;
073import org.opends.guitools.controlpanel.util.ConfigReader;
074import org.opends.guitools.controlpanel.util.Utilities;
075import org.opends.quicksetup.Installation;
076import org.opends.quicksetup.installer.InstallerHelper;
077import org.opends.quicksetup.util.Utils;
078import org.opends.server.admin.AdminException;
079import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
080import org.opends.server.admin.client.ldap.LDAPManagementContext;
081import org.opends.server.admin.std.client.BackendCfgClient;
082import org.opends.server.admin.std.client.BackendIndexCfgClient;
083import org.opends.server.admin.std.client.PluggableBackendCfgClient;
084import org.opends.server.admin.std.client.RootCfgClient;
085import org.opends.server.admin.std.meta.BackendCfgDefn;
086import org.opends.server.admin.std.meta.BackendIndexCfgDefn;
087import org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType;
088import org.opends.server.core.DirectoryServer;
089import org.opends.server.extensions.ConfigFileHandler;
090import org.opends.server.tools.BackendCreationHelper;
091import org.opends.server.tools.BackendCreationHelper.DefaultIndex;
092import org.opends.server.tools.BackendTypeHelper;
093import org.opends.server.tools.BackendTypeHelper.BackendTypeUIAdapter;
094import org.opends.server.tools.ImportLDIF;
095import org.opends.server.tools.LDAPModify;
096import org.opends.server.tools.makeldif.MakeLDIF;
097import org.opends.server.types.OpenDsException;
098import org.opends.server.util.RemoveOnceNewConfigFrameworkIsUsed;
099import org.opends.server.util.SetupUtils;
100
101import com.forgerock.opendj.cli.CommandBuilder;
102
103/** The class that appears when the user clicks on 'New Base DN'. */
104public class NewBaseDNPanel extends StatusGenericPanel
105{
106  private static final int MAX_ENTRIES_NUMBER_GENERATED = 1000;
107  private static final int MAX_ENTRIES_NUMBER_GENERATED_LOCAL = 20000;
108  private static final long serialVersionUID = -2680821576362341119L;
109  private static final LocalizableMessage NEW_BACKEND_TEXT = INFO_CTRL_PANEL_NEW_BACKEND_LABEL.get();
110
111  private JComboBox<?> backends;
112  private JComboBox<BackendTypeUIAdapter> backendTypes;
113  private JTextField newBackend;
114  private JTextField baseDN;
115  private JRadioButton onlyCreateBaseEntry;
116  private JRadioButton leaveDatabaseEmpty;
117  private JRadioButton importDataFromLDIF;
118  private JRadioButton importAutomaticallyGenerated;
119  private JTextField path;
120  private JTextField numberOfEntries;
121  private JLabel lRemoteFileHelp;
122  private JButton browseImportPath;
123
124  private JLabel lBackend;
125  private JLabel lDirectoryBaseDN;
126  private JLabel lPath;
127  private JLabel lNumberOfEntries;
128  private JLabel lDirectoryData;
129  private JLabel lNewBackendType;
130
131  private DocumentListener documentListener;
132
133  /** Default constructor. */
134  public NewBaseDNPanel()
135  {
136    super();
137    createLayout();
138  }
139
140  @Override
141  public LocalizableMessage getTitle()
142  {
143    return INFO_CTRL_PANEL_NEW_BASE_DN_TITLE.get();
144  }
145
146  @Override
147  public Component getPreferredFocusComponent()
148  {
149    return baseDN;
150  }
151
152  @Override
153  public void toBeDisplayed(boolean visible)
154  {
155    if (visible)
156    {
157      documentListener.changedUpdate(null);
158    }
159  }
160
161  /** Creates the layout of the panel (but the contents are not populated here). */
162  private void createLayout()
163  {
164    GridBagConstraints gbc = new GridBagConstraints();
165    addErrorPanel(gbc);
166    addBackendLabel(gbc);
167    addBackendNamesComboBox(gbc);
168    addNewBackendName(gbc);
169    addNewBackendTypeLabel(gbc);
170    addNewBackendTypeComboBox(gbc);
171    addBaseDNLabel(gbc);
172    addBaseDNTextField(gbc);
173    addBaseDNInlineHelp(gbc);
174    addDirectoryDataLabel(gbc);
175    addImportDataChoiceSection(gbc);
176    addBottomGlue(gbc);
177  }
178
179  private void addErrorPanel(GridBagConstraints gbc)
180  {
181    gbc.gridx = 0;
182    gbc.gridy = 0;
183    gbc.gridwidth = 3;
184    addErrorPane(gbc);
185  }
186
187  private void addBackendLabel(GridBagConstraints gbc)
188  {
189    gbc.anchor = GridBagConstraints.WEST;
190    gbc.weightx = 0.0;
191    gbc.gridwidth = 1;
192    gbc.gridy++;
193    gbc.fill = GridBagConstraints.NONE;
194    lBackend = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BACKEND_LABEL.get());
195    add(lBackend, gbc);
196  }
197
198  @SuppressWarnings({ "unchecked", "rawtypes" })
199  private void addBackendNamesComboBox(GridBagConstraints gbc)
200  {
201    gbc.insets.left = 10;
202    gbc.gridx = 1;
203    backends = Utilities.createComboBox();
204    backends.setModel(new DefaultComboBoxModel(new Object[] { "bogus", NEW_BACKEND_TEXT }));
205    backends.setRenderer(new CustomListCellRenderer(backends));
206    backends.addItemListener(new IgnoreItemListener(backends));
207    gbc.gridwidth = 1;
208    add(backends, gbc);
209  }
210
211  private void addNewBackendTypeLabel(GridBagConstraints gbc)
212  {
213    gbc.insets.top = 10;
214    gbc.gridx = 0;
215    gbc.gridy++;
216    gbc.insets.left = 0;
217    gbc.gridwidth = 1;
218    lNewBackendType = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_NEW_BACKEND_TYPE_LABEL.get());
219    add(lNewBackendType, gbc);
220    addBackendNameChangeListener(lNewBackendType);
221  }
222
223  @SuppressWarnings("unchecked")
224  private void addNewBackendTypeComboBox(GridBagConstraints gbc)
225  {
226    gbc.insets.left = 10;
227    gbc.gridx = 1;
228    gbc.gridwidth = 1;
229    final BackendTypeHelper backendTypeHelper = new BackendTypeHelper();
230    backendTypes = Utilities.createComboBox();
231    backendTypes.setModel(new DefaultComboBoxModel<>(backendTypeHelper.getBackendTypeUIAdaptors()));
232    backendTypes.setRenderer(new CustomListCellRenderer(backendTypes));
233    backendTypes.addItemListener(new IgnoreItemListener(backendTypes));
234    add(backendTypes, gbc);
235    addBackendNameChangeListener(backendTypes);
236  }
237
238  private void addNewBackendName(GridBagConstraints gbc)
239  {
240    gbc.gridx = 2;
241    newBackend = Utilities.createTextField();
242    newBackend.setColumns(18);
243    add(newBackend, gbc);
244    addBackendNameChangeListener(newBackend);
245  }
246
247  private void addBackendNameChangeListener(final JComponent component)
248  {
249    ItemListener comboListener = new ItemListener()
250    {
251      @Override
252      public void itemStateChanged(ItemEvent ev)
253      {
254        Object o = backends.getSelectedItem();
255        component.setVisible(NEW_BACKEND_TEXT.equals(o));
256      }
257    };
258    backends.addItemListener(comboListener);
259    comboListener.itemStateChanged(null);
260  }
261
262  private void addBaseDNLabel(GridBagConstraints gbc)
263  {
264    gbc.insets.top = 10;
265    gbc.gridx = 0;
266    gbc.gridy++;
267    gbc.insets.left = 0;
268    gbc.gridwidth = 1;
269    lDirectoryBaseDN = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BASE_DN_LABEL.get());
270    add(lDirectoryBaseDN, gbc);
271  }
272
273  private void addBaseDNTextField(GridBagConstraints gbc)
274  {
275    gbc.gridx = 1;
276    gbc.insets.left = 10;
277    gbc.gridwidth = 2;
278    baseDN = Utilities.createTextField();
279    documentListener = new DocumentListener()
280    {
281      @Override
282      public void changedUpdate(DocumentEvent ev)
283      {
284        String text = baseDN.getText().trim();
285        setEnabledOK(text != null && text.length() > 0 && !errorPane.isVisible());
286      }
287
288      @Override
289      public void removeUpdate(DocumentEvent ev)
290      {
291        changedUpdate(ev);
292      }
293
294      @Override
295      public void insertUpdate(DocumentEvent ev)
296      {
297        changedUpdate(ev);
298      }
299    };
300    baseDN.getDocument().addDocumentListener(documentListener);
301    gbc.weightx = 1.0;
302    gbc.fill = GridBagConstraints.HORIZONTAL;
303    add(baseDN, gbc);
304  }
305
306  private void addBaseDNInlineHelp(GridBagConstraints gbc)
307  {
308    gbc.gridy++;
309    gbc.anchor = GridBagConstraints.EAST;
310    gbc.insets.top = 3;
311    JLabel inlineHelp = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_BASE_DN_EXAMPLE.get());
312    add(inlineHelp, gbc);
313  }
314
315  private void addDirectoryDataLabel(GridBagConstraints gbc)
316  {
317    gbc.gridx = 0;
318    gbc.gridy++;
319    gbc.insets.left = 0;
320    gbc.insets.top = 10;
321    gbc.gridwidth = 1;
322    gbc.weightx = 0.0;
323    lDirectoryData = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DIRECTORY_DATA_LABEL.get());
324    add(lDirectoryData, gbc);
325  }
326
327  private void addImportDataChoiceSection(GridBagConstraints gbc)
328  {
329    onlyCreateBaseEntry = Utilities.createRadioButton(INFO_CTRL_PANEL_ONLY_CREATE_BASE_ENTRY_LABEL.get());
330    onlyCreateBaseEntry.setSelected(false);
331
332    gbc.insets.left = 10;
333    gbc.gridx = 1;
334    gbc.gridwidth = 2;
335    add(onlyCreateBaseEntry, gbc);
336
337    leaveDatabaseEmpty = Utilities.createRadioButton(INFO_CTRL_PANEL_LEAVE_DATABASE_EMPTY_LABEL.get());
338    leaveDatabaseEmpty.setSelected(false);
339
340    gbc.gridy++;
341    gbc.gridwidth = 2;
342    gbc.insets.top = 5;
343    add(leaveDatabaseEmpty, gbc);
344
345    importDataFromLDIF = Utilities.createRadioButton(INFO_CTRL_PANEL_IMPORT_FROM_LDIF_LABEL.get());
346    importDataFromLDIF.setSelected(false);
347
348    gbc.gridy++;
349    gbc.gridwidth = 2;
350    add(importDataFromLDIF, gbc);
351
352    gbc.gridy++;
353    gbc.gridwidth = 2;
354    gbc.insets.left = 30;
355    add(createPathPanel(), gbc);
356
357    importAutomaticallyGenerated =
358        Utilities.createRadioButton(INFO_CTRL_PANEL_IMPORT_AUTOMATICALLY_GENERATED_LABEL.get());
359    importAutomaticallyGenerated.setOpaque(false);
360    importAutomaticallyGenerated.setSelected(false);
361
362    gbc.gridy++;
363    gbc.gridwidth = 2;
364    gbc.insets.left = 10;
365    add(importAutomaticallyGenerated, gbc);
366
367    gbc.gridy++;
368    gbc.gridwidth = 2;
369    gbc.insets.left = 30;
370    add(createNumberOfUsersPanel(), gbc);
371
372    ButtonGroup group = new ButtonGroup();
373    group.add(onlyCreateBaseEntry);
374    group.add(leaveDatabaseEmpty);
375    group.add(importDataFromLDIF);
376    group.add(importAutomaticallyGenerated);
377
378    ChangeListener listener = new ChangeListener()
379    {
380      @Override
381      public void stateChanged(ChangeEvent ev)
382      {
383        browseImportPath.setEnabled(importDataFromLDIF.isSelected());
384        lPath.setEnabled(importDataFromLDIF.isSelected());
385        lRemoteFileHelp.setEnabled(importDataFromLDIF.isSelected());
386        numberOfEntries.setEnabled(importAutomaticallyGenerated.isSelected());
387        lNumberOfEntries.setEnabled(importAutomaticallyGenerated.isSelected());
388      }
389    };
390
391    Enumeration<AbstractButton> buttons = group.getElements();
392    while (buttons.hasMoreElements())
393    {
394      buttons.nextElement().addChangeListener(listener);
395    }
396    onlyCreateBaseEntry.setSelected(true);
397    listener.stateChanged(null);
398  }
399
400  @Override
401  public void configurationChanged(ConfigurationChangeEvent ev)
402  {
403    ServerDescriptor desc = ev.getNewDescriptor();
404    final SortedSet<String> sortedBackends = new TreeSet<>();
405    for (BackendDescriptor backend : desc.getBackends())
406    {
407      if (!backend.isConfigBackend())
408      {
409        sortedBackends.add(backend.getBackendID());
410      }
411    }
412
413    List<Object> newElements = new ArrayList<Object>(sortedBackends);
414    if (!sortedBackends.isEmpty())
415    {
416      newElements.add(COMBO_SEPARATOR);
417    }
418    newElements.add(NEW_BACKEND_TEXT);
419    super.updateComboBoxModel(newElements, (DefaultComboBoxModel<?>) backends.getModel());
420    updateErrorPaneAndOKButtonIfAuthRequired(desc,
421        isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_CREATE_BASE_DN.get()
422                  : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
423    SwingUtilities.invokeLater(new Runnable()
424    {
425      @Override
426      public void run()
427      {
428        lRemoteFileHelp.setVisible(!isLocal());
429        browseImportPath.setVisible(isLocal());
430      }
431    });
432  }
433
434  private JPanel createPathPanel()
435  {
436    JPanel panel = new JPanel(new GridBagLayout());
437    panel.setOpaque(false);
438    GridBagConstraints gbc = new GridBagConstraints();
439    gbc.gridwidth = 1;
440    gbc.gridy = 0;
441    gbc.gridx = 0;
442    lPath = Utilities.createDefaultLabel(INFO_CTRL_PANEL_IMPORT_LDIF_PATH_LABEL.get());
443    panel.add(lPath, gbc);
444
445    gbc.gridx = 1;
446    gbc.insets.left = 10;
447    path = Utilities.createTextField();
448    gbc.weightx = 1.0;
449    gbc.fill = GridBagConstraints.HORIZONTAL;
450    panel.add(path, gbc);
451    browseImportPath = Utilities.createButton(INFO_CTRL_PANEL_BROWSE_BUTTON_LABEL.get());
452    browseImportPath.addActionListener(
453        new BrowseActionListener(path, BrowseActionListener.BrowseType.OPEN_LDIF_FILE, this));
454    gbc.gridx = 2;
455    gbc.weightx = 0.0;
456    panel.add(browseImportPath, gbc);
457
458    gbc.gridy++;
459    gbc.gridx = 1;
460    lRemoteFileHelp = Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_REMOTE_SERVER_PATH.get());
461    gbc.insets.top = 3;
462    gbc.insets.left = 10;
463    panel.add(lRemoteFileHelp, gbc);
464
465    return panel;
466  }
467
468  private JPanel createNumberOfUsersPanel()
469  {
470    JPanel panel = new JPanel(new GridBagLayout());
471    panel.setOpaque(false);
472    GridBagConstraints gbc = new GridBagConstraints();
473    gbc.weightx = 0.0;
474    gbc.fill = GridBagConstraints.HORIZONTAL;
475    lNumberOfEntries = Utilities.createDefaultLabel(INFO_CTRL_PANEL_NUMBER_OF_USER_ENTRIES_LABEL.get());
476    panel.add(lNumberOfEntries, gbc);
477
478    gbc.gridx = 1;
479    gbc.insets.left = 10;
480    numberOfEntries = Utilities.createTextField("2000", 6);
481    panel.add(numberOfEntries, gbc);
482
483    gbc.gridx = 2;
484    gbc.insets.left = 0;
485    gbc.weightx = 1.0;
486    panel.add(Box.createHorizontalGlue(), gbc);
487
488    return panel;
489  }
490
491  @Override
492  public void cancelClicked()
493  {
494    resetLabelAsValid();
495    super.cancelClicked();
496  }
497
498  private void resetLabelAsValid()
499  {
500    setPrimaryValid(lBackend);
501    setPrimaryValid(lDirectoryBaseDN);
502    setPrimaryValid(lDirectoryData);
503    setSecondaryValid(lPath);
504    setSecondaryValid(lNumberOfEntries);
505  }
506
507  @Override
508  protected void checkOKButtonEnable()
509  {
510    documentListener.changedUpdate(null);
511  }
512
513  @Override
514  public void okClicked()
515  {
516    resetLabelAsValid();
517
518    final Set<LocalizableMessage> errors = new LinkedHashSet<>();
519    final ServerDescriptor desc = getInfo().getServerDescriptor();
520    final Set<BackendDescriptor> existingBackends = desc.getBackends();
521
522    final String backendName = validateBackendName(existingBackends, errors);
523    final String dn = validateBaseDN(backendName, existingBackends, errors);
524    validateImportLDIFFilePath(errors);
525    validateAutomaticallyGenerated(errors);
526
527    if (errors.isEmpty())
528    {
529      final ProgressDialog progressDialog = new ProgressDialog(
530          Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo());
531      final NewBaseDNTask newTask = new NewBaseDNTask(getInfo(), progressDialog);
532      for (Task task : getInfo().getTasks())
533      {
534        task.canLaunch(newTask, errors);
535      }
536
537      if (errors.isEmpty())
538      {
539        launchOperation(newTask,
540            INFO_CTRL_PANEL_CREATING_BASE_DN_SUMMARY.get(dn),
541            INFO_CTRL_PANEL_CREATING_BASE_DN_COMPLETE.get(),
542            INFO_CTRL_PANEL_CREATING_BASE_DN_SUCCESSFUL.get(dn),
543            ERR_CTRL_PANEL_CREATING_BASE_DN_ERROR_SUMMARY.get(dn),
544            null,
545            ERR_CTRL_PANEL_CREATING_BASE_DN_ERROR_DETAILS,
546            progressDialog);
547        progressDialog.setVisible(true);
548        baseDN.setText("");
549        baseDN.grabFocus();
550        Utilities.getParentDialog(this).setVisible(false);
551      }
552    }
553
554    if (!errors.isEmpty())
555    {
556      displayErrorDialog(errors);
557    }
558  }
559
560  /** Returns the existing or the new backend name, once user have clicked on 'OK' button. */
561  private String validateBackendName(
562      final Set<BackendDescriptor> existingBackends, final Set<LocalizableMessage> errors)
563  {
564    final Object selectedItem = backends.getSelectedItem();
565    if (!selectedItem.equals(NEW_BACKEND_TEXT))
566    {
567      return selectedItem.toString();
568    }
569
570    final String backendName = newBackend.getText().trim();
571    if (backendName.length() == 0)
572    {
573      errors.add(ERR_NEW_BACKEND_NAME_REQUIRED.get());
574      setPrimaryInvalid(lBackend);
575      return backendName;
576    }
577
578    // Check that the backend is not already defined.
579    for (BackendDescriptor backend : existingBackends)
580    {
581      if (backendName.equalsIgnoreCase(backend.getBackendID()))
582      {
583        errors.add(ERR_BACKEND_ALREADY_EXISTS.get(backendName));
584        setPrimaryInvalid(lBackend);
585      }
586    }
587
588    return backendName;
589  }
590
591  private String validateBaseDN(final String backendName, final Set<BackendDescriptor> existingBackends,
592      final Set<LocalizableMessage> errors)
593  {
594    String dn = baseDN.getText();
595    if (dn.trim().length() == 0)
596    {
597      errors.add(ERR_NEW_BASE_DN_VALUE_REQUIRED.get());
598      setPrimaryInvalid(lDirectoryBaseDN);
599      return dn;
600    }
601
602    try
603    {
604      final DN theDN = DN.valueOf(dn);
605      for (final BackendDescriptor backend : existingBackends)
606      {
607        for (final BaseDNDescriptor baseDN : backend.getBaseDns())
608        {
609          if (baseDN.getDn().equals(theDN))
610          {
611            return invalidBaseDNValue(dn, ERR_BASE_DN_ALREADY_EXISTS.get(dn), errors);
612          }
613          else if (baseDN.getDn().isSuperiorOrEqualTo(theDN) && backendName.equalsIgnoreCase(backend.getBackendID()))
614          {
615            return invalidBaseDNValue(dn, ERR_BASE_DN_ANCESTOR_EXISTS.get(baseDN.getDn()), errors);
616          }
617          else if (theDN.isSuperiorOrEqualTo(baseDN.getDn()) && backendName.equalsIgnoreCase(backend.getBackendID()))
618          {
619            return invalidBaseDNValue(dn, ERR_BASE_DN_DN_IS_ANCESTOR_OF.get(baseDN.getDn()), errors);
620          }
621        }
622      }
623    }
624    catch (LocalizedIllegalArgumentException e)
625    {
626      errors.add(INFO_CTRL_PANEL_INVALID_DN_DETAILS.get(dn, e.getMessageObject()));
627      setPrimaryInvalid(lDirectoryBaseDN);
628    }
629
630    return dn;
631  }
632
633  /** Mark the provided base DN as invalid with the provided reason and return it. */
634  private String invalidBaseDNValue(final String dn, final LocalizableMessage errorMsg,
635      final Set<LocalizableMessage> errors)
636  {
637    errors.add(errorMsg);
638    setPrimaryInvalid(lDirectoryBaseDN);
639    return dn;
640  }
641
642  private void validateImportLDIFFilePath(final Set<LocalizableMessage> errors)
643  {
644    // TODO: what happens with sub-suffixes?
645    if (importDataFromLDIF.isSelected())
646    {
647      String ldifPath = path.getText();
648      if (ldifPath == null || "".equals(ldifPath.trim()))
649      {
650        errors.add(INFO_NO_LDIF_PATH.get());
651        setSecondaryInvalid(lPath);
652      }
653      else if (isLocal() && !Utils.fileExists(ldifPath))
654      {
655        errors.add(INFO_LDIF_FILE_DOES_NOT_EXIST.get());
656        setSecondaryInvalid(lPath);
657      }
658    }
659  }
660
661  private void validateAutomaticallyGenerated(final Set<LocalizableMessage> errors)
662  {
663    if (importAutomaticallyGenerated.isSelected())
664    {
665      final int minValue = 1;
666      final int maxValue = isLocal() ? MAX_ENTRIES_NUMBER_GENERATED_LOCAL : MAX_ENTRIES_NUMBER_GENERATED;
667      final LocalizableMessage errorMsg = ERR_NUMBER_OF_ENTRIES_INVALID.get(minValue, maxValue);
668      if (!checkIntValue(errors, numberOfEntries.getText(), minValue, maxValue, errorMsg))
669      {
670        setSecondaryInvalid(lNumberOfEntries);
671      }
672    }
673  }
674
675  private String getBackendName()
676  {
677    Object backendName = backends.getSelectedItem();
678    if (NEW_BACKEND_TEXT.equals(backendName))
679    {
680      return newBackend.getText().trim();
681    }
682    else if (backendName != null)
683    {
684      return backendName.toString();
685    }
686
687    return null;
688  }
689
690  private BackendTypeUIAdapter getSelectedBackendType()
691  {
692    return (BackendTypeUIAdapter) backendTypes.getSelectedItem();
693  }
694
695  private boolean isNewBackend()
696  {
697    return NEW_BACKEND_TEXT.equals(backends.getSelectedItem());
698  }
699
700  /** The task in charge of creating the base DN (and if required, the backend). */
701  protected class NewBaseDNTask extends Task
702  {
703    private final Set<String> backendSet;
704    private final String newBaseDN;
705    private int progressAfterConfigurationUpdate = -1;
706
707    /**
708     * The constructor of the task.
709     *
710     * @param info
711     *          the control panel info.
712     * @param dlg
713     *          the progress dialog that shows the progress of the task.
714     */
715    public NewBaseDNTask(ControlPanelInfo info, ProgressDialog dlg)
716    {
717      super(info, dlg);
718      backendSet = new HashSet<>();
719      backendSet.add(getBackendName());
720      newBaseDN = baseDN.getText();
721
722      if (onlyCreateBaseEntry.isSelected())
723      {
724        progressAfterConfigurationUpdate = 40;
725      }
726      else if (leaveDatabaseEmpty.isSelected())
727      {
728        progressAfterConfigurationUpdate = 90;
729      }
730      else if (importAutomaticallyGenerated.isSelected())
731      {
732        int nEntries = Integer.parseInt(numberOfEntries.getText().trim());
733        if (nEntries < 500)
734        {
735          progressAfterConfigurationUpdate = 30;
736        }
737        else if (nEntries < 3000)
738        {
739          progressAfterConfigurationUpdate = 15;
740        }
741        else
742        {
743          progressAfterConfigurationUpdate = 5;
744        }
745      }
746    }
747
748    @Override
749    public Type getType()
750    {
751      return Type.NEW_BASEDN;
752    }
753
754    @Override
755    public LocalizableMessage getTaskDescription()
756    {
757      return INFO_CTRL_PANEL_NEW_BASE_DN_TASK_DESCRIPTION.get(newBaseDN, backendSet.iterator().next());
758    }
759
760    @Override
761    public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons)
762    {
763      boolean canLaunch = true;
764      if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched))
765      {
766        // All the operations are incompatible if they apply to this backend.
767        Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends());
768        backends.retainAll(getBackends());
769        if (!backends.isEmpty())
770        {
771          incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched));
772          canLaunch = false;
773        }
774      }
775      return canLaunch;
776    }
777
778    private String getDataCommandLineToDisplay()
779    {
780      StringBuilder sb = new StringBuilder();
781      sb.append(getDataCommandLineName());
782      Collection<String> args = getObfuscatedCommandLineArguments(getDataCommandLineArguments(path.getText(), false));
783      args.removeAll(getConfigCommandLineArguments());
784      for (String arg : args)
785      {
786        sb.append(" ").append(CommandBuilder.escapeValue(arg));
787      }
788      return sb.toString();
789    }
790
791    private String getDataCommandLineName()
792    {
793      if (!leaveDatabaseEmpty.isSelected())
794      {
795        return getCommandLinePath(isLocal() ? "import-ldif" : "ldapmodify");
796      }
797
798      return null;
799    }
800
801    /**
802     * Returns the arguments of the command-line that can be used to generate
803     * the data.
804     *
805     * @param ldifFile
806     *          the LDIF file.
807     * @param useTemplate
808     *          whether to use a template or not.
809     * @return the arguments of the command-line that can be used to generate
810     *         the data.
811     */
812    private List<String> getDataCommandLineArguments(String ldifFile, boolean useTemplate)
813    {
814      List<String> args = new ArrayList<>();
815      if (!leaveDatabaseEmpty.isSelected())
816      {
817        if (isLocal())
818        {
819          if (!useTemplate)
820          {
821            args.add("--ldifFile");
822            args.add(ldifFile);
823          }
824          else
825          {
826            args.add("--templateFile");
827            args.add(ldifFile);
828            args.add("--randomSeed");
829            args.add("0");
830          }
831          args.add("--backendID");
832          args.add(getBackendName());
833        }
834        else
835        {
836          // If we are not local, we use ldapmodify to update the contents.
837          args.add("-a");
838          args.add("-f");
839          args.add(ldifFile);
840        }
841        args.addAll(getConnectionCommandLineArguments(true, !isLocal()));
842
843        if (isServerRunning() && isLocal())
844        {
845          args.addAll(getConfigCommandLineArguments());
846        }
847
848        args.add(getNoPropertiesFileArgument());
849      }
850
851      return args;
852    }
853
854    private void updateConfigurationOnline() throws OpenDsException
855    {
856      SwingUtilities.invokeLater(new Runnable()
857      {
858        @Override
859        public void run()
860        {
861          List<String> args = getObfuscatedCommandLineArguments(getDSConfigCommandLineArguments());
862          args.removeAll(getConfigCommandLineArguments());
863          printEquivalentCommandLine(
864              getConfigCommandLineFullPath(), args, INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CREATE_BASE_DN.get());
865        }
866      });
867
868      performTask();
869      printTaskDone();
870      if (isNewBackend())
871      {
872        createAdditionalIndexes();
873      }
874      refreshProgressBar();
875    }
876
877    private void updateConfigurationOffline() throws OpenDsException
878    {
879      boolean configHandlerUpdated = false;
880      try
881      {
882        getInfo().stopPooling();
883        if (getInfo().mustDeregisterConfig())
884        {
885          DirectoryServer.deregisterBaseDN(DN.valueOf("cn=config"));
886        }
887        DirectoryServer.getInstance().initializeConfiguration(
888            ConfigFileHandler.class.getName(), ConfigReader.configFile);
889        getInfo().setMustDeregisterConfig(true);
890        configHandlerUpdated = true;
891
892        performTask();
893        printTaskDone();
894        refreshProgressBar();
895      }
896      finally
897      {
898        if (configHandlerUpdated)
899        {
900          DirectoryServer.getInstance().initializeConfiguration(ConfigReader.configClassName, ConfigReader.configFile);
901          getInfo().startPooling();
902        }
903      }
904    }
905
906    private void printCreateNewBackendProgress(final String backendName) throws OpenDsException
907    {
908      SwingUtilities.invokeLater(new Runnable()
909      {
910        @Override
911        public void run()
912        {
913          LocalizableMessage message = INFO_CTRL_PANEL_CREATING_BACKEND_PROGRESS.get(backendName, newBaseDN);
914          getProgressDialog().appendProgressHtml(
915              Utilities.getProgressWithPoints(message, ColorAndFontConstants.progressFont));
916        }
917      });
918    }
919
920    private void performTask() throws OpenDsException
921    {
922      final String backendName = getBackendName();
923      if (isNewBackend())
924      {
925        printCreateNewBackendProgress(backendName);
926        createBackend(backendName);
927      }
928      else
929      {
930        printCreateNewBaseDNProgress(backendName);
931        addNewBaseDN(backendName);
932      }
933    }
934
935    private void createBackend(String backendName) throws OpenDsException
936    {
937      if (!isServerRunning())
938      {
939        createBackendOffline(backendName);
940        return;
941      }
942
943      createBackendOnline(backendName);
944    }
945
946    private void createBackendOffline(String backendName) throws OpenDsException
947    {
948      try
949      {
950        Set<DN> baseDN = Collections.singleton(DN.valueOf(newBaseDN));
951        BackendCreationHelper.createBackendOffline(backendName, baseDN, getSelectedBackendType().getBackend());
952      }
953      catch (Exception e)
954      {
955        throw new OfflineUpdateException(ERROR_CTRL_PANEL_CREATE_NEW_BACKEND.get(backendName, e.getMessage()), e);
956      }
957    }
958
959    @RemoveOnceNewConfigFrameworkIsUsed("Use BackendCreationHelper.createBackend(...)")
960    private void createBackendOnline(String backendName) throws OpenDsException
961    {
962      final RootCfgClient root = getRootConfigurationClient();
963      final BackendCfgClient backend =
964          root.createBackend(getSelectedBackendType().getLegacyConfigurationFrameworkBackend(), backendName, null);
965      backend.setEnabled(true);
966      backend.setBaseDN(Collections.singleton(DN.valueOf(newBaseDN)));
967      backend.setBackendId(backendName);
968      backend.setWritabilityMode(BackendCfgDefn.WritabilityMode.ENABLED);
969      backend.commit();
970    }
971
972    private RootCfgClient getRootConfigurationClient()
973    {
974      final JNDIDirContextAdaptor jndiContext = JNDIDirContextAdaptor.adapt(getInfo().getDirContext());
975      return LDAPManagementContext.createFromContext(jndiContext).getRootConfiguration();
976    }
977
978    private void addNewBaseDN(String backendName) throws OpenDsException
979    {
980      if (!isServerRunning())
981      {
982        addNewBaseDNOffline(backendName);
983        return;
984      }
985
986      final BackendCfgClient backend = getRootConfigurationClient().getBackend(backendName);
987      final Set<DN> baseDNs = backend.getBaseDN();
988      baseDNs.add(DN.valueOf(newBaseDN));
989      backend.setBaseDN(baseDNs);
990      backend.commit();
991    }
992
993    private void addNewBaseDNOffline(String backendName) throws OpenDsException
994    {
995      try
996      {
997        getInfo().initializeConfigurationFramework();
998        final File config = Installation.getLocal().getCurrentConfigurationFile();
999        final LDAPProfile profile = LDAPProfile.getInstance();
1000        try (org.forgerock.opendj.config.client.ManagementContext context =
1001            org.forgerock.opendj.config.client.ldap.LDAPManagementContext.newLDIFManagementContext(config, profile))
1002        {
1003          final org.forgerock.opendj.server.config.client.BackendCfgClient backend =
1004              context.getRootConfiguration().getBackend(backendName);
1005          final SortedSet<DN> baseDNs = backend.getBaseDN();
1006          baseDNs.add(DN.valueOf(newBaseDN));
1007          backend.setBaseDN(baseDNs);
1008          backend.commit();
1009        }
1010      }
1011      catch (Exception e)
1012      {
1013        throw new OfflineUpdateException(LocalizableMessage.raw(e.getMessage()), e);
1014      }
1015    }
1016
1017    private void createAdditionalIndexes() throws OpenDsException
1018    {
1019      final String backendName = getBackendName();
1020      displayCreateAdditionalIndexesDsConfigCmdLine();
1021      final RootCfgClient root = getRootConfigurationClient();
1022      addBackendDefaultIndexes((PluggableBackendCfgClient) root.getBackend(backendName));
1023      displayCreateAdditionalIndexesDone();
1024    }
1025
1026    private void addBackendDefaultIndexes(PluggableBackendCfgClient backendCfgClient) throws AdminException
1027    {
1028      for (DefaultIndex defaultIndex : BackendCreationHelper.DEFAULT_INDEXES)
1029      {
1030        final BackendIndexCfgClient index = backendCfgClient.createBackendIndex(
1031            BackendIndexCfgDefn.getInstance(), defaultIndex.getName(), null);
1032
1033        final List<IndexType> indexTypes = new LinkedList<>();
1034        indexTypes.add(IndexType.EQUALITY);
1035        if (defaultIndex.shouldCreateSubstringIndex())
1036        {
1037          indexTypes.add(IndexType.SUBSTRING);
1038        }
1039        index.setIndexType(indexTypes);
1040        index.commit();
1041      }
1042    }
1043
1044    private void printCreateNewBaseDNProgress(final String backendName) throws OpenDsException
1045    {
1046      SwingUtilities.invokeLater(new Runnable()
1047      {
1048        @Override
1049        public void run()
1050        {
1051          LocalizableMessage message = INFO_CTRL_PANEL_CREATING_BASE_DN_PROGRESS.get(newBaseDN, backendName);
1052          getProgressDialog().appendProgressHtml(
1053              Utilities.getProgressWithPoints(message, ColorAndFontConstants.progressFont));
1054        }
1055      });
1056    }
1057
1058    private void printTaskDone()
1059    {
1060      SwingUtilities.invokeLater(new Runnable()
1061      {
1062        @Override
1063        public void run()
1064        {
1065          getProgressDialog().appendProgressHtml(
1066              Utilities.getProgressDone(ColorAndFontConstants.progressFont) + "<br><br>");
1067        }
1068      });
1069    }
1070
1071    private void refreshProgressBar()
1072    {
1073      if (progressAfterConfigurationUpdate > 0)
1074      {
1075        SwingUtilities.invokeLater(new Runnable()
1076        {
1077          @Override
1078          public void run()
1079          {
1080            getProgressDialog().getProgressBar().setIndeterminate(false);
1081            getProgressDialog().getProgressBar().setValue(progressAfterConfigurationUpdate);
1082          }
1083        });
1084      }
1085    }
1086
1087    private void displayCreateAdditionalIndexesDsConfigCmdLine()
1088    {
1089      final List<List<String>> argsArray = new ArrayList<>();
1090      for (DefaultIndex defaultIndex : BackendCreationHelper.DEFAULT_INDEXES)
1091      {
1092        argsArray.add(getCreateIndexCommandLineArguments(defaultIndex));
1093      }
1094
1095      final StringBuilder sb = new StringBuilder();
1096      for (List<String> args : argsArray)
1097      {
1098        sb.append(getEquivalentCommandLine(getCommandLinePath("dsconfig"), getObfuscatedCommandLineArguments(args)));
1099        sb.append("<br><br>");
1100      }
1101
1102      SwingUtilities.invokeLater(new Runnable()
1103      {
1104        @Override
1105        public void run()
1106        {
1107          getProgressDialog().appendProgressHtml(Utilities.applyFont(
1108              INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CREATE_ADDITIONAL_INDEXES.get()
1109              + "<br><br><b>" + sb + "</b>", ColorAndFontConstants.progressFont));
1110          getProgressDialog().appendProgressHtml(Utilities.getProgressWithPoints(
1111              INFO_CTRL_PANEL_CREATING_ADDITIONAL_INDEXES_PROGRESS.get(), ColorAndFontConstants.progressFont));
1112        }
1113      });
1114    }
1115
1116    private List<String> getCreateIndexCommandLineArguments(final DefaultIndex defaultIndex)
1117    {
1118      final List<String> args = new ArrayList<>();
1119      args.add("create-backend-index");
1120      args.add("--backend-name");
1121      args.add(getBackendName());
1122      args.add("--type");
1123      args.add("generic");
1124      args.add("--index-name");
1125      args.add(defaultIndex.getName());
1126      args.add("--set");
1127      args.add("index-type:" + IndexTypeDescriptor.EQUALITY.toBackendIndexType());
1128      if (defaultIndex.shouldCreateSubstringIndex())
1129      {
1130        args.add("--set");
1131        args.add("index-type:" + IndexTypeDescriptor.SUBSTRING.toBackendIndexType());
1132      }
1133      args.addAll(getConnectionCommandLineArguments());
1134      args.add(getNoPropertiesFileArgument());
1135      args.add("--no-prompt");
1136
1137      return args;
1138    }
1139
1140    private void displayCreateAdditionalIndexesDone()
1141    {
1142      SwingUtilities.invokeLater(new Runnable()
1143      {
1144        @Override
1145        public void run()
1146        {
1147          getProgressDialog().appendProgressHtml(
1148              Utilities.getProgressDone(ColorAndFontConstants.progressFont) + "<br><br>");
1149        }
1150      });
1151    }
1152
1153    /**
1154     * Creates the data in the new base DN.
1155     *
1156     * @throws OpenDsException
1157     *           if there is an error importing contents.
1158     * @throws IOException
1159     *           if there is an err
1160     */
1161    private void updateData() throws OpenDsException, IOException
1162    {
1163      final boolean leaveEmpty = leaveDatabaseEmpty.isSelected();
1164      final boolean createBaseEntry = onlyCreateBaseEntry.isSelected();
1165      final boolean importLDIF = importDataFromLDIF.isSelected();
1166      final boolean generateData = !leaveEmpty && !createBaseEntry && !importLDIF;
1167      final String nEntries = numberOfEntries.getText();
1168      final String ldif = path.getText();
1169
1170      if (leaveEmpty)
1171      {
1172        state = State.FINISHED_SUCCESSFULLY;
1173      }
1174      else
1175      {
1176        final ProgressDialog progressDialog = getProgressDialog();
1177        String ldifFile;
1178        if (importLDIF)
1179        {
1180          ldifFile = ldif;
1181          final String cmdLine = getDataCommandLineToDisplay();
1182          SwingUtilities.invokeLater(new Runnable()
1183          {
1184            @Override
1185            public void run()
1186            {
1187              progressDialog.appendProgressHtml(Utilities.applyFont("Equivalent command line:<br><b>" + cmdLine
1188                  + "</b><br><br>", ColorAndFontConstants.progressFont));
1189            }
1190          });
1191        }
1192        else if (createBaseEntry)
1193        {
1194          SwingUtilities.invokeLater(new Runnable()
1195          {
1196            @Override
1197            public void run()
1198            {
1199              progressDialog.appendProgressHtml(Utilities.getProgressWithPoints(
1200                  INFO_PROGRESS_CREATING_BASE_ENTRY.get(newBaseDN), ColorAndFontConstants.progressFont));
1201            }
1202          });
1203          InstallerHelper helper = new InstallerHelper();
1204          File f = helper.createBaseEntryTempFile(newBaseDN);
1205          ldifFile = f.getAbsolutePath();
1206        }
1207        else
1208        {
1209          SwingUtilities.invokeLater(new Runnable()
1210          {
1211            @Override
1212            public void run()
1213            {
1214              if (isLocal())
1215              {
1216                progressDialog.appendProgressHtml(Utilities.applyFont(
1217                    INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED.get(nEntries).toString(),
1218                    ColorAndFontConstants.progressFont) + "<br>");
1219              }
1220              else
1221              {
1222                getProgressDialog().appendProgressHtml(Utilities.getProgressWithPoints(
1223                    INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED_REMOTE.get(nEntries),
1224                    ColorAndFontConstants.progressFont));
1225              }
1226            }
1227          });
1228
1229          File f = SetupUtils.createTemplateFile(newBaseDN, Integer.parseInt(nEntries));
1230          if (!isLocal())
1231          {
1232            File tempFile = File.createTempFile("opendj-control-panel", ".ldif");
1233            tempFile.deleteOnExit();
1234            ldifFile = tempFile.getAbsolutePath();
1235
1236            // Create the LDIF file locally using make-ldif
1237            List<String> makeLDIFArgs = new ArrayList<>();
1238            makeLDIFArgs.add("--templateFile");
1239            makeLDIFArgs.add(f.getAbsolutePath());
1240            makeLDIFArgs.add("--ldifFile");
1241            makeLDIFArgs.add(ldifFile);
1242            makeLDIFArgs.add("--randomSeed");
1243            makeLDIFArgs.add("0");
1244            makeLDIFArgs.add("--resourcePath");
1245
1246            File makeLDIFPath = new File(Installation.getLocal().getConfigurationDirectory(), "MakeLDIF");
1247            makeLDIFArgs.add(makeLDIFPath.getAbsolutePath());
1248            makeLDIFArgs.addAll(getConfigCommandLineArguments());
1249
1250            MakeLDIF makeLDIF = new MakeLDIF();
1251            String[] array = new String[makeLDIFArgs.size()];
1252            makeLDIFArgs.toArray(array);
1253            returnCode = makeLDIF.makeLDIFMain(array, false, false, outPrintStream, errorPrintStream);
1254            f.delete();
1255
1256            if (returnCode != 0)
1257            {
1258              throw new OnlineUpdateException(ERR_CTRL_PANEL_ERROR_CREATING_NEW_DATA_LDIF.get(returnCode), null);
1259            }
1260          }
1261          else
1262          {
1263            ldifFile = f.getAbsolutePath();
1264          }
1265        }
1266
1267        List<String> arguments = getDataCommandLineArguments(ldifFile, generateData);
1268        String[] args = new String[arguments.size()];
1269        arguments.toArray(args);
1270        if (createBaseEntry || !isLocal())
1271        {
1272          outPrintStream.setNotifyListeners(false);
1273          errorPrintStream.setNotifyListeners(false);
1274        }
1275        try
1276        {
1277          if (isServerRunning())
1278          {
1279            if (isLocal() || importLDIF)
1280            {
1281              returnCode = ImportLDIF.mainImportLDIF(args, false, outPrintStream, errorPrintStream);
1282            }
1283            else
1284            {
1285              returnCode = LDAPModify.mainModify(args, false, outPrintStream, errorPrintStream);
1286            }
1287          }
1288          else
1289          {
1290            returnCode = executeCommandLine(getDataCommandLineName(), args);
1291          }
1292        }
1293        finally
1294        {
1295          outPrintStream.setNotifyListeners(true);
1296          errorPrintStream.setNotifyListeners(true);
1297        }
1298
1299        if (returnCode != 0)
1300        {
1301          state = State.FINISHED_WITH_ERROR;
1302        }
1303        else
1304        {
1305          if (createBaseEntry || (!isLocal() && generateData))
1306          {
1307            SwingUtilities.invokeLater(new Runnable()
1308            {
1309              @Override
1310              public void run()
1311              {
1312                progressDialog.appendProgressHtml(Utilities.getProgressDone(ColorAndFontConstants.progressFont));
1313              }
1314            });
1315          }
1316          state = State.FINISHED_SUCCESSFULLY;
1317        }
1318      }
1319    }
1320
1321    @Override
1322    protected String getCommandLinePath()
1323    {
1324      return null;
1325    }
1326
1327    @Override
1328    protected List<String> getCommandLineArguments()
1329    {
1330      return new ArrayList<>();
1331    }
1332
1333    private String getConfigCommandLineFullPath()
1334    {
1335      return isServerRunning() ? getCommandLinePath("dsconfig") : null;
1336    }
1337
1338    private List<String> getDSConfigCommandLineArguments()
1339    {
1340      List<String> args = new ArrayList<>();
1341      if (isServerRunning())
1342      {
1343        if (isNewBackend())
1344        {
1345          args.add("create-backend");
1346          args.add("--backend-name");
1347          args.add(getBackendName());
1348          args.add("--set");
1349          args.add("base-dn:" + newBaseDN);
1350          args.add("--set");
1351          args.add("enabled:true");
1352          args.add("--type");
1353          args.add(BackendTypeHelper.filterSchemaBackendName(getSelectedBackendType().getBackend().getName()));
1354        }
1355        else
1356        {
1357          args.add("set-backend-prop");
1358          args.add("--backend-name");
1359          args.add(getBackendName());
1360          args.add("--add");
1361          args.add("base-dn:" + newBaseDN);
1362        }
1363        args.addAll(getConnectionCommandLineArguments());
1364        args.add(getNoPropertiesFileArgument());
1365        args.add("--no-prompt");
1366      }
1367      return args;
1368    }
1369
1370    @Override
1371    public void runTask()
1372    {
1373      state = State.RUNNING;
1374      lastException = null;
1375
1376      try
1377      {
1378        if (isServerRunning())
1379        {
1380          updateConfigurationOnline();
1381        }
1382        else
1383        {
1384          updateConfigurationOffline();
1385        }
1386        updateData();
1387      }
1388      catch (Throwable t)
1389      {
1390        lastException = t;
1391        state = State.FINISHED_WITH_ERROR;
1392      }
1393    }
1394
1395    @Override
1396    public Set<String> getBackends()
1397    {
1398      return backendSet;
1399    }
1400  }
1401}