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 */
017
018package org.opends.guitools.controlpanel.ui;
019
020import static org.opends.guitools.controlpanel.util.Utilities.*;
021import static org.opends.messages.AdminToolMessages.*;
022
023import java.awt.Component;
024import java.awt.GridBagConstraints;
025import java.awt.GridBagLayout;
026import java.awt.Insets;
027import java.awt.event.ActionEvent;
028import java.awt.event.ActionListener;
029import java.util.ArrayList;
030import java.util.Collection;
031import java.util.HashSet;
032import java.util.List;
033import java.util.Set;
034import java.util.TreeSet;
035
036import javax.naming.ldap.InitialLdapContext;
037import javax.swing.Box;
038import javax.swing.DefaultComboBoxModel;
039import javax.swing.JButton;
040import javax.swing.JLabel;
041import javax.swing.JPanel;
042import javax.swing.JScrollPane;
043import javax.swing.SwingConstants;
044import javax.swing.SwingUtilities;
045import javax.swing.border.EmptyBorder;
046import javax.swing.event.DocumentEvent;
047import javax.swing.event.DocumentListener;
048import javax.swing.event.ListDataEvent;
049import javax.swing.event.ListDataListener;
050
051import org.forgerock.i18n.LocalizableMessage;
052import org.forgerock.i18n.LocalizedIllegalArgumentException;
053import org.forgerock.opendj.config.server.ConfigException;
054import org.forgerock.opendj.ldap.DN;
055import org.forgerock.opendj.ldap.SearchScope;
056import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor;
057import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement;
058import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
059import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
060import org.opends.guitools.controlpanel.datamodel.VLVIndexDescriptor;
061import org.opends.guitools.controlpanel.datamodel.VLVSortOrder;
062import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
063import org.opends.guitools.controlpanel.event.ScrollPaneBorderListener;
064import org.opends.guitools.controlpanel.task.DeleteIndexTask;
065import org.opends.guitools.controlpanel.task.Task;
066import org.opends.guitools.controlpanel.util.ConfigReader;
067import org.opends.guitools.controlpanel.util.Utilities;
068import org.opends.server.admin.client.ManagementContext;
069import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
070import org.opends.server.admin.client.ldap.LDAPManagementContext;
071import org.opends.server.admin.std.client.BackendVLVIndexCfgClient;
072import org.opends.server.admin.std.client.PluggableBackendCfgClient;
073import org.opends.server.admin.std.client.RootCfgClient;
074import org.opends.server.core.DirectoryServer;
075import org.opends.server.types.OpenDsException;
076
077/**
078 * The panel that displays an existing VLV index (it appears on the right of the
079 * 'Manage Indexes' dialog).
080 */
081public class VLVIndexPanel extends AbstractVLVIndexPanel
082{
083  private static final long serialVersionUID = 6333337497315464283L;
084  private static final LocalizableMessage INDEX_MODIFIED = INFO_CTRL_PANEL_INDEX_MODIFIED_MESSAGE.get();
085
086  private final JButton deleteIndex = Utilities.createButton(INFO_CTRL_PANEL_DELETE_INDEX_LABEL.get());
087  private final JButton saveChanges = Utilities.createButton(INFO_CTRL_PANEL_SAVE_CHANGES_LABEL.get());
088  private final JLabel warning = Utilities.createDefaultLabel();
089
090  private ScrollPaneBorderListener scrollListener;
091
092  private ModifyVLVIndexTask newModifyTask;
093
094  private boolean ignoreCheckSave;
095
096  private VLVIndexDescriptor index;
097
098  /** Default constructor. */
099  public VLVIndexPanel()
100  {
101    super(null, null);
102    createLayout();
103  }
104
105  @Override
106  public LocalizableMessage getTitle()
107  {
108    return INFO_CTRL_PANEL_VLV_INDEX_PANEL_TITLE.get();
109  }
110
111  @Override
112  public Component getPreferredFocusComponent()
113  {
114    return baseDN;
115  }
116
117  @Override
118  public void configurationChanged(ConfigurationChangeEvent ev)
119  {
120    final ServerDescriptor desc = ev.getNewDescriptor();
121    if (updateLayout(desc))
122    {
123      LocalizableMessage msg = isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_VLV_INDEX_EDITING.get()
124                                         : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname());
125      updateErrorPaneIfAuthRequired(desc, msg);
126      SwingUtilities.invokeLater(new Runnable()
127      {
128        @Override
129        public void run()
130        {
131          checkSaveButton();
132          deleteIndex.setEnabled(!authenticationRequired(desc));
133        }
134      });
135    }
136  }
137
138  @Override
139  public void okClicked()
140  {
141  }
142
143  /**
144   * Method used to know if there are unsaved changes or not. It is used by the
145   * index selection listener when the user changes the selection.
146   *
147   * @return <CODE>true</CODE> if there are unsaved changes (and so the
148   *         selection of the index should be canceled) and <CODE>false</CODE>
149   *         otherwise.
150   */
151  public boolean mustCheckUnsavedChanges()
152  {
153    return index != null && saveChanges.isVisible() && saveChanges.isEnabled();
154  }
155
156  /**
157   * Tells whether the user chose to save the changes in the panel, to not save
158   * them or simply cancelled the selection in the tree.
159   *
160   * @return the value telling whether the user chose to save the changes in the
161   *         panel, to not save them or simply cancelled the selection change in
162   *         the tree.
163   */
164  public UnsavedChangesDialog.Result checkUnsavedChanges()
165  {
166    UnsavedChangesDialog.Result result;
167    final UnsavedChangesDialog unsavedChangesDlg = new UnsavedChangesDialog(getParentDialog(this), getInfo());
168    unsavedChangesDlg.setMessage(INFO_CTRL_PANEL_UNSAVED_CHANGES_SUMMARY.get(),
169                                 INFO_CTRL_PANEL_UNSAVED_INDEX_CHANGES_DETAILS.get(index.getName()));
170    centerGoldenMean(unsavedChangesDlg, getParentDialog(this));
171    unsavedChangesDlg.setVisible(true);
172    result = unsavedChangesDlg.getResult();
173    if (result == UnsavedChangesDialog.Result.SAVE)
174    {
175      saveIndex(false);
176      if (newModifyTask == null
177       || newModifyTask.getState() != Task.State.FINISHED_SUCCESSFULLY) // The user data is not valid
178      {
179        result = UnsavedChangesDialog.Result.CANCEL;
180      }
181    }
182
183    return result;
184  }
185
186  private void checkSaveButton()
187  {
188    if (!ignoreCheckSave && index != null)
189    {
190      saveChanges.setEnabled(!authenticationRequired(getInfo().getServerDescriptor()) && isModified());
191    }
192  }
193
194  /** {@inheritDoc} */
195  @Override
196  public GenericDialog.ButtonType getButtonType()
197  {
198    return GenericDialog.ButtonType.NO_BUTTON;
199  }
200
201  /**
202   * Creates the layout of the panel (but the contents are not populated here).
203   */
204  private void createLayout()
205  {
206    GridBagConstraints gbc = new GridBagConstraints();
207    final JPanel p = new JPanel(new GridBagLayout());
208    p.setOpaque(false);
209    super.createBasicLayout(p, gbc, true);
210    p.setBorder(new EmptyBorder(10, 10, 10, 10));
211    gbc = new GridBagConstraints();
212    gbc.weightx = 1.0;
213    gbc.weighty = 1.0;
214    gbc.fill = GridBagConstraints.BOTH;
215    gbc.gridx = 0;
216    gbc.gridy = 0;
217    final JScrollPane scroll = Utilities.createBorderLessScrollBar(p);
218    scrollListener = ScrollPaneBorderListener.createBottomBorderListener(scroll);
219    add(scroll, gbc);
220
221    gbc.gridy++;
222    gbc.gridx = 0;
223    gbc.weightx = 1.0;
224    gbc.weighty = 0.0;
225    gbc.insets.left = 0;
226    gbc.gridwidth = 2;
227    gbc.weighty = 0.0;
228    gbc.fill = GridBagConstraints.HORIZONTAL;
229    gbc.insets.top = 10;
230
231    gbc.gridwidth = 3;
232    gbc.insets = new Insets(10, 10, 0, 10);
233    add(warning, gbc);
234    Utilities.setWarningLabel(warning, INDEX_MODIFIED);
235
236    gbc.gridy++;
237    final JPanel buttonPanel = new JPanel(new GridBagLayout());
238    buttonPanel.setOpaque(false);
239    gbc.insets = new Insets(10, 10, 10, 10);
240    add(buttonPanel, gbc);
241
242    gbc.insets = new Insets(0, 0, 0, 0);
243    gbc.gridy = 0;
244    gbc.gridx = 0;
245    gbc.weightx = 0.0;
246    gbc.gridwidth = 1;
247    deleteIndex.setOpaque(false);
248    gbc.insets.left = 0;
249    buttonPanel.add(deleteIndex, gbc);
250    deleteIndex.addActionListener(new ActionListener()
251    {
252      @Override
253      public void actionPerformed(ActionEvent ev)
254      {
255        deleteIndex();
256      }
257    });
258    gbc.gridx = 2;
259    gbc.weightx = 1.0;
260    buttonPanel.add(Box.createHorizontalGlue(), gbc);
261    gbc.weightx = 0.0;
262    gbc.insets.left = 10;
263    saveChanges.setOpaque(false);
264    gbc.gridx = 3;
265    buttonPanel.add(saveChanges, gbc);
266    saveChanges.addActionListener(new ActionListener()
267    {
268      @Override
269      public void actionPerformed(ActionEvent ev)
270      {
271        saveIndex(false);
272      }
273    });
274
275    final DocumentListener documentListener = new DocumentListener()
276    {
277      @Override
278      public void insertUpdate(DocumentEvent ev)
279      {
280        checkSaveButton();
281      }
282
283      @Override
284      public void changedUpdate(DocumentEvent ev)
285      {
286        checkSaveButton();
287      }
288
289      @Override
290      public void removeUpdate(DocumentEvent ev)
291      {
292        checkSaveButton();
293      }
294    };
295
296    final ActionListener actionListener = new ActionListener()
297    {
298      @Override
299      public void actionPerformed(ActionEvent ev)
300      {
301        checkSaveButton();
302      }
303    };
304
305    baseDNs.addActionListener(actionListener);
306    baseObject.addActionListener(actionListener);
307    singleLevel.addActionListener(actionListener);
308    subordinateSubtree.addActionListener(actionListener);
309    wholeSubtree.addActionListener(actionListener);
310    attributes.addActionListener(actionListener);
311    sortOrder.getModel().addListDataListener(new ListDataListener()
312    {
313      @Override
314      public void contentsChanged(ListDataEvent e)
315      {
316        checkSaveButton();
317      }
318
319      @Override
320      public void intervalAdded(ListDataEvent e)
321      {
322        checkSaveButton();
323      }
324
325      @Override
326      public void intervalRemoved(ListDataEvent e)
327      {
328        checkSaveButton();
329      }
330    });
331
332    baseDN.getDocument().addDocumentListener(documentListener);
333    filter.getDocument().addDocumentListener(documentListener);
334    baseDN.getDocument().addDocumentListener(documentListener);
335  }
336
337  private void deleteIndex()
338  {
339    final List<LocalizableMessage> errors = new ArrayList<>();
340    final ProgressDialog dlg = new ProgressDialog(
341        createFrame(), getParentDialog(this), INFO_CTRL_PANEL_DELETE_VLV_INDEX_TITLE.get(), getInfo());
342    final List<AbstractIndexDescriptor> indexesToDelete = new ArrayList<>();
343    indexesToDelete.add(index);
344    final DeleteIndexTask newTask = new DeleteIndexTask(getInfo(), dlg, indexesToDelete);
345    for (final Task task : getInfo().getTasks())
346    {
347      task.canLaunch(newTask, errors);
348    }
349
350    if (errors.isEmpty())
351    {
352      final String indexName = index.getName();
353      final String backendName = index.getBackend().getBackendID();
354      if (displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
355                                    INFO_CTRL_PANEL_CONFIRMATION_VLV_INDEX_DELETE_DETAILS.get(indexName, backendName)))
356      {
357        launchOperation(newTask,
358                        INFO_CTRL_PANEL_DELETING_VLV_INDEX_SUMMARY.get(),
359                        INFO_CTRL_PANEL_DELETING_VLV_INDEX_COMPLETE.get(),
360                        INFO_CTRL_PANEL_DELETING_VLV_INDEX_SUCCESSFUL.get(indexName, backendName),
361                        ERR_CTRL_PANEL_DELETING_VLV_INDEX_ERROR_SUMMARY.get(),
362                        ERR_CTRL_PANEL_DELETING_VLV_INDEX_ERROR_DETAILS.get(indexName),
363                        null, dlg);
364        dlg.setVisible(true);
365      }
366    }
367    else
368    {
369      displayErrorDialog(errors);
370    }
371  }
372
373  private void saveIndex(boolean modal)
374  {
375    newModifyTask = null;
376    if (!isModified())
377    {
378      return;
379    }
380    final List<LocalizableMessage> errors = checkErrors(false);
381
382    if (errors.isEmpty())
383    {
384      final ProgressDialog dlg =
385          new ProgressDialog(getFrame(this), getFrame(this), INFO_CTRL_PANEL_MODIFYING_INDEX_TITLE.get(), getInfo());
386      dlg.setModal(modal);
387      newModifyTask = new ModifyVLVIndexTask(getInfo(), dlg);
388      for (final Task task : getInfo().getTasks())
389      {
390        task.canLaunch(newModifyTask, errors);
391      }
392      if (errors.isEmpty() && checkIndexRequired())
393      {
394        final String indexName = index.getName();
395        final String backendName = index.getBackend().getBackendID();
396        launchOperation(newModifyTask,
397                        INFO_CTRL_PANEL_MODIFYING_VLV_INDEX_SUMMARY.get(indexName),
398                        INFO_CTRL_PANEL_MODIFYING_VLV_INDEX_COMPLETE.get(),
399                        INFO_CTRL_PANEL_MODIFYING_VLV_INDEX_SUCCESSFUL.get(indexName, backendName),
400                        ERR_CTRL_PANEL_MODIFYING_VLV_INDEX_ERROR_SUMMARY.get(),
401                        ERR_CTRL_PANEL_MODIFYING_VLV_INDEX_ERROR_DETAILS.get(indexName),
402                        null, dlg);
403        saveChanges.setEnabled(false);
404        dlg.setVisible(true);
405      }
406    }
407
408    if (!errors.isEmpty())
409    {
410      displayErrorDialog(errors);
411    }
412  }
413
414  /**
415   * Updates the contents of the panel with the provided VLV index.
416   *
417   * @param index
418   *          the VLV index descriptor to be used to update the panel.
419   */
420  public void update(VLVIndexDescriptor index)
421  {
422    ignoreCheckSave = true;
423    readOnlyName.setText(index.getName());
424    titlePanel.setDetails(LocalizableMessage.raw(index.getName()));
425    if (index.getBackend() != null)
426    {
427      updateBaseDNCombo(index.getBackend());
428      backendName.setText(index.getBackend().getBackendID());
429    }
430    final String dn = Utilities.unescapeUtf8(index.getBaseDN().toString());
431    if (((DefaultComboBoxModel) baseDNs.getModel()).getIndexOf(dn) != -1)
432    {
433      baseDN.setText("");
434      baseDNs.setSelectedItem(dn);
435    }
436    else
437    {
438      baseDN.setText(dn);
439      baseDNs.setSelectedItem(OTHER_BASE_DN);
440    }
441
442    selectScopeRadioButton(index.getScope());
443    filter.setText(index.getFilter());
444
445    // Simulate a remove to update the attribute combo box and add them again.
446    final int indexes[] = new int[sortOrderModel.getSize()];
447    for (int i = 0; i < indexes.length; i++)
448    {
449      indexes[i] = i;
450    }
451    sortOrder.setSelectedIndices(indexes);
452    remove.doClick();
453
454    // The list is now empty and the attribute combo properly updated.
455    final DefaultComboBoxModel model = (DefaultComboBoxModel) attributes.getModel();
456    for (final VLVSortOrder s : index.getSortOrder())
457    {
458      sortOrderModel.addElement(s);
459      for (int i = 0; i < model.getSize(); i++)
460      {
461        final CategorizedComboBoxElement o = (CategorizedComboBoxElement) model.getElementAt(i);
462        if (o.getType() == CategorizedComboBoxElement.Type.REGULAR && o.getValue().equals(s.getAttributeName()))
463        {
464          model.removeElementAt(i);
465          break;
466        }
467      }
468    }
469    if (model.getSize() > 1)
470    {
471      attributes.setSelectedIndex(1);
472    }
473
474    if (getInfo() != null)
475    {
476      if (getInfo().mustReindex(index))
477      {
478        setWarningLabel(warning, INDEX_MODIFIED);
479        warning.setVisible(true);
480        warning.setVerticalTextPosition(SwingConstants.TOP);
481      }
482      else
483      {
484        warning.setVisible(false);
485      }
486    }
487    this.index = index;
488
489    ignoreCheckSave = false;
490    checkSaveButton();
491
492    scrollListener.updateBorder();
493  }
494
495  private void selectScopeRadioButton(final SearchScope indexScope)
496  {
497    switch (indexScope.asEnum())
498    {
499    case BASE_OBJECT:
500      baseObject.setSelected(true);
501      break;
502    case SINGLE_LEVEL:
503      singleLevel.setSelected(true);
504      break;
505    case SUBORDINATES:
506      subordinateSubtree.setSelected(true);
507      break;
508    case WHOLE_SUBTREE:
509      wholeSubtree.setSelected(true);
510      break;
511    default:
512      break;
513    }
514  }
515
516  private boolean isModified()
517  {
518    try
519    {
520      return !index.getBaseDN().equals(DN.valueOf(getBaseDN())) || !index.getScope().equals(getScope())
521          || !index.getFilter().equals(filter.getText().trim()) || !index.getSortOrder().equals(getSortOrder());
522    }
523    catch (final LocalizedIllegalArgumentException unused)
524    {
525      // The base DN is not valid.  This means that the index has been modified.
526      return true;
527    }
528  }
529
530  /**
531   * The task in charge of modifying the VLV index.
532   */
533  protected class ModifyVLVIndexTask extends Task
534  {
535    private final Set<String> backendSet;
536    private final String indexName;
537    private final String baseDN;
538    private final String filterValue;
539    private final SearchScope searchScope;
540    private final List<VLVSortOrder> sortOrder;
541    private final String backendID;
542    private final String sortOrderStringValue;
543    private final VLVIndexDescriptor indexToModify;
544    private VLVIndexDescriptor modifiedIndex;
545
546    /**
547     * The constructor of the task.
548     *
549     * @param info
550     *          the control panel info.
551     * @param dlg
552     *          the progress dialog that shows the progress of the task.
553     */
554    public ModifyVLVIndexTask(ControlPanelInfo info, ProgressDialog dlg)
555    {
556      super(info, dlg);
557      backendID = index.getBackend().getBackendID();
558      backendSet = new HashSet<>();
559      backendSet.add(backendID);
560      indexName = index.getName();
561      sortOrder = getSortOrder();
562      baseDN = getBaseDN();
563      filterValue = filter.getText().trim();
564      searchScope = getScope();
565      sortOrderStringValue = getSortOrderStringValue(sortOrder);
566      indexToModify = index;
567    }
568
569    @Override
570    public Type getType()
571    {
572      return Type.MODIFY_INDEX;
573    }
574
575    @Override
576    public Set<String> getBackends()
577    {
578      return backendSet;
579    }
580
581    @Override
582    public LocalizableMessage getTaskDescription()
583    {
584      return INFO_CTRL_PANEL_MODIFY_VLV_INDEX_TASK_DESCRIPTION.get(indexName, backendID);
585    }
586
587    @Override
588    public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons)
589    {
590      boolean canLaunch = true;
591      if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched))
592      {
593        // All the operations are incompatible if they apply to this
594        // backend for safety.  This is a short operation so the limitation
595        // has not a lot of impact.
596        final Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends());
597        backends.retainAll(getBackends());
598        if (!backends.isEmpty())
599        {
600          incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched));
601          canLaunch = false;
602        }
603      }
604      return canLaunch;
605    }
606
607    private void updateConfiguration() throws OpenDsException, ConfigException
608    {
609      boolean configHandlerUpdated = false;
610      try
611      {
612        if (!isServerRunning())
613        {
614          configHandlerUpdated = true;
615          getInfo().stopPooling();
616          if (getInfo().mustDeregisterConfig())
617          {
618            DirectoryServer.deregisterBaseDN(DN.valueOf("cn=config"));
619          }
620          DirectoryServer.getInstance().initializeConfiguration(
621              org.opends.server.extensions.ConfigFileHandler.class.getName(), ConfigReader.configFile);
622          getInfo().setMustDeregisterConfig(true);
623        }
624        else
625        {
626          SwingUtilities.invokeLater(new Runnable()
627          {
628            @Override
629            public void run()
630            {
631              final List<String> args = getObfuscatedCommandLineArguments(getDSConfigCommandLineArguments());
632              args.removeAll(getConfigCommandLineArguments());
633              printEquivalentCommandLine(getConfigCommandLineName(), args,
634                  INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_MODIFY_VLV_INDEX.get());
635            }
636          });
637        }
638        SwingUtilities.invokeLater(new Runnable()
639        {
640          @Override
641          public void run()
642          {
643            getProgressDialog().appendProgressHtml(
644                Utilities.getProgressWithPoints(INFO_CTRL_PANEL_MODIFYING_VLV_INDEX_PROGRESS.get(indexName),
645                    ColorAndFontConstants.progressFont));
646          }
647        });
648
649        if (isServerRunning())
650        {
651          modifyVLVIndexOnline(getInfo().getDirContext());
652        }
653        else
654        {
655          modifyVLVIndexOffline(backendID, indexName, indexToModify, DN.valueOf(baseDN), filterValue,
656              searchScope, sortOrder);
657        }
658        SwingUtilities.invokeLater(new Runnable()
659        {
660          /** {@inheritDoc} */
661          @Override
662          public void run()
663          {
664            getProgressDialog().appendProgressHtml(Utilities.getProgressDone(ColorAndFontConstants.progressFont));
665          }
666        });
667      }
668      finally
669      {
670        if (configHandlerUpdated)
671        {
672          DirectoryServer.getInstance().initializeConfiguration(ConfigReader.configClassName, ConfigReader.configFile);
673          getInfo().startPooling();
674        }
675      }
676    }
677
678    /**
679     * Modifies index using the provided connection.
680     *
681     * @param ctx
682     *          the connection to be used to update the index configuration.
683     * @throws OpenDsException
684     *           if there is an error updating the server.
685     */
686    private void modifyVLVIndexOnline(InitialLdapContext ctx) throws OpenDsException
687    {
688      final ManagementContext mCtx = LDAPManagementContext.createFromContext(JNDIDirContextAdaptor.adapt(ctx));
689      final RootCfgClient root = mCtx.getRootConfiguration();
690      modifyBackendVLVIndexOnline((PluggableBackendCfgClient) root.getBackend(backendID));
691    }
692
693    private void modifyBackendVLVIndexOnline(final PluggableBackendCfgClient backend) throws OpenDsException
694    {
695      final BackendVLVIndexCfgClient index = backend.getBackendVLVIndex(indexName);
696      final DN b = DN.valueOf(baseDN);
697      if (!indexToModify.getBaseDN().equals(b))
698      {
699        index.setBaseDN(b);
700      }
701
702      if (!indexToModify.getFilter().equals(filterValue))
703      {
704        index.setFilter(filterValue);
705      }
706
707      if (indexToModify.getScope() != searchScope)
708      {
709        index.setScope(VLVIndexDescriptor.getBackendVLVIndexScope(searchScope));
710      }
711
712      if (!indexToModify.getSortOrder().equals(sortOrder))
713      {
714        index.setSortOrder(sortOrderStringValue);
715      }
716      index.commit();
717    }
718
719    @Override
720    protected String getCommandLinePath()
721    {
722      return null;
723    }
724
725    @Override
726    protected ArrayList<String> getCommandLineArguments()
727    {
728      return new ArrayList<>();
729    }
730
731    private String getConfigCommandLineName()
732    {
733      if (isServerRunning() && isModified())
734      {
735        return getCommandLinePath("dsconfig");
736      }
737      return null;
738    }
739
740    @Override
741    public void runTask()
742    {
743      state = State.RUNNING;
744      lastException = null;
745
746      try
747      {
748        updateConfiguration();
749        modifiedIndex = new VLVIndexDescriptor(
750            indexName, indexToModify.getBackend(), DN.valueOf(baseDN), searchScope, filterValue, sortOrder);
751        getInfo().registerModifiedIndex(modifiedIndex);
752        state = State.FINISHED_SUCCESSFULLY;
753      }
754      catch (final Throwable t)
755      {
756        lastException = t;
757        state = State.FINISHED_WITH_ERROR;
758      }
759    }
760
761    @Override
762    public void postOperation()
763    {
764      if (lastException == null && state == State.FINISHED_SUCCESSFULLY)
765      {
766        rebuildIndexIfNecessary(modifiedIndex, getProgressDialog());
767      }
768    }
769
770    private List<String> getDSConfigCommandLineArguments()
771    {
772      final List<String> args = new ArrayList<>();
773      args.add("set-backend-vlv-index-prop");
774      args.add("--backend-name");
775      args.add(backendID);
776
777      args.add("--index-name");
778      args.add(indexName);
779
780      if (!indexToModify.getBaseDN().equals(DN.valueOf(baseDN)))
781      {
782        args.add("--set");
783        args.add("base-dn:" + baseDN);
784      }
785
786      if (indexToModify.getScope() != searchScope)
787      {
788        args.add("--set");
789        args.add("scope:" + VLVIndexDescriptor.getBackendVLVIndexScope(searchScope));
790      }
791      if (!indexToModify.getFilter().equals(filterValue))
792      {
793        args.add("--set");
794        args.add("filter:" + filterValue);
795      }
796
797      if (!indexToModify.getSortOrder().equals(sortOrder))
798      {
799        args.add("--set");
800        args.add("sort-order:" + sortOrderStringValue);
801      }
802
803      args.addAll(getConnectionCommandLineArguments());
804      args.add(getNoPropertiesFileArgument());
805      args.add("--no-prompt");
806
807      return args;
808    }
809  }
810}