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