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}