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