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 2006-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools; 018 019import static org.opends.messages.ToolMessages.*; 020import static org.opends.server.config.ConfigConstants.*; 021import static org.opends.server.util.StaticUtils.*; 022 023import static com.forgerock.opendj.cli.Utils.*; 024import static com.forgerock.opendj.cli.CommonArguments.*; 025 026import java.io.OutputStream; 027import java.io.PrintStream; 028import java.util.ArrayList; 029import java.util.List; 030import java.util.logging.Level; 031 032import org.forgerock.i18n.LocalizableMessage; 033import org.forgerock.i18n.LocalizableMessageDescriptor.Arg1; 034import org.forgerock.i18n.slf4j.LocalizedLogger; 035import org.forgerock.opendj.config.server.ConfigException; 036import org.opends.server.admin.std.server.BackendCfg; 037import org.opends.server.api.Backend; 038import org.opends.server.api.Backend.BackendOperation; 039import org.opends.server.backends.RebuildConfig; 040import org.opends.server.backends.RebuildConfig.RebuildMode; 041import org.opends.server.core.CoreConfigManager; 042import org.opends.server.core.DirectoryServer; 043import org.opends.server.core.LockFileManager; 044import org.opends.server.extensions.ConfigFileHandler; 045import org.opends.server.loggers.DebugLogger; 046import org.opends.server.loggers.ErrorLogPublisher; 047import org.opends.server.loggers.ErrorLogger; 048import org.opends.server.loggers.JDKLogging; 049import org.opends.server.loggers.TextErrorLogPublisher; 050import org.opends.server.loggers.TextWriter; 051import org.opends.server.protocols.ldap.LDAPAttribute; 052import org.opends.server.tasks.RebuildTask; 053import org.opends.server.tools.tasks.TaskTool; 054import org.forgerock.opendj.ldap.DN; 055import org.opends.server.types.InitializationException; 056import org.opends.server.types.NullOutputStream; 057import org.opends.server.types.RawAttribute; 058import org.opends.server.util.StaticUtils; 059import org.opends.server.util.cli.LDAPConnectionArgumentParser; 060 061import com.forgerock.opendj.cli.ArgumentException; 062import com.forgerock.opendj.cli.BooleanArgument; 063import com.forgerock.opendj.cli.StringArgument; 064 065/** 066 * This program provides a utility to rebuild the contents of the indexes of a 067 * Directory Server backend. This will be a process that is intended to run 068 * separate from Directory Server and not internally within the server process 069 * (e.g., via the tasks interface). 070 */ 071public class RebuildIndex extends TaskTool 072{ 073 074 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 075 076 private StringArgument configClass; 077 private StringArgument configFile; 078 private StringArgument baseDNString; 079 private StringArgument indexList; 080 private StringArgument tmpDirectory; 081 private BooleanArgument rebuildAll; 082 private BooleanArgument rebuildDegraded; 083 private BooleanArgument clearDegradedState; 084 085 private final LDAPConnectionArgumentParser argParser = createArgParser( 086 "org.opends.server.tools.RebuildIndex", 087 INFO_REBUILDINDEX_TOOL_DESCRIPTION.get()); 088 089 private RebuildConfig rebuildConfig = new RebuildConfig(); 090 private Backend<?> currentBackend; 091 092 /** 093 * Processes the command-line arguments and invokes the rebuild process. 094 * 095 * @param args 096 * The command-line arguments provided to this program. 097 */ 098 public static void main(final String[] args) 099 { 100 final int retCode = 101 mainRebuildIndex(args, true, System.out, System.err); 102 if (retCode != 0) 103 { 104 System.exit(filterExitCode(retCode)); 105 } 106 } 107 108 /** 109 * Processes the command-line arguments and invokes the rebuild process. 110 * 111 * @param args 112 * The command-line arguments provided to this program. 113 * @param initializeServer 114 * Indicates whether to initialize the server. 115 * @param outStream 116 * The output stream to use for standard output, or {@code null} if 117 * standard output is not needed. 118 * @param errStream 119 * The output stream to use for standard error, or {@code null} if 120 * standard error is not needed. 121 * @return The error code. 122 */ 123 public static int mainRebuildIndex(final String[] args, 124 final boolean initializeServer, final OutputStream outStream, 125 final OutputStream errStream) 126 { 127 final RebuildIndex tool = new RebuildIndex(); 128 return tool.process(args, initializeServer, outStream, errStream); 129 } 130 131 private int process(final String[] args, final boolean initializeServer, 132 final OutputStream outStream, final OutputStream errStream ) 133 { 134 final PrintStream out = NullOutputStream.wrapOrNullStream(outStream); 135 final PrintStream err = NullOutputStream.wrapOrNullStream(errStream); 136 JDKLogging.enableConsoleLoggingForOpenDJ(Level.FINE); 137 138 // Initialize all the command-line argument types and register them with the 139 // parser. 140 try 141 { 142 initializeArguments(false); 143 } 144 catch (ArgumentException ae) 145 { 146 printWrappedText(err, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 147 return 1; 148 } 149 150 // Parse the command-line arguments provided to this program. 151 try 152 { 153 argParser.parseArguments(args); 154 } 155 catch (ArgumentException ae) 156 { 157 argParser.displayMessageAndUsageReference(err, ERR_ERROR_PARSING_ARGS.get(ae.getMessage())); 158 return 1; 159 } 160 161 // If we should just display usage or version information, 162 // then print it and exit. 163 if (argParser.usageOrVersionDisplayed()) 164 { 165 return 0; 166 } 167 168 if (indexList.getValues().isEmpty() 169 && !rebuildAll.isPresent() 170 && !rebuildDegraded.isPresent()) 171 { 172 argParser.displayMessageAndUsageReference(err, ERR_REBUILDINDEX_REQUIRES_AT_LEAST_ONE_INDEX.get()); 173 return 1; 174 } 175 176 if (rebuildAll.isPresent() && indexList.isPresent()) 177 { 178 argParser.displayMessageAndUsageReference(err, ERR_REBUILDINDEX_REBUILD_ALL_ERROR.get()); 179 return 1; 180 } 181 182 if (rebuildDegraded.isPresent() && indexList.isPresent()) 183 { 184 argParser.displayMessageAndUsageReference(err, ERR_REBUILDINDEX_REBUILD_DEGRADED_ERROR.get("index")); 185 return 1; 186 } 187 188 if (rebuildDegraded.isPresent() && clearDegradedState.isPresent()) 189 { 190 argParser.displayMessageAndUsageReference(err, ERR_REBUILDINDEX_REBUILD_DEGRADED_ERROR.get("clearDegradedState")); 191 return 1; 192 } 193 194 if (rebuildAll.isPresent() && rebuildDegraded.isPresent()) 195 { 196 argParser.displayMessageAndUsageReference(err, 197 ERR_REBUILDINDEX_REBUILD_ALL_DEGRADED_ERROR.get("rebuildDegraded")); 198 return 1; 199 } 200 201 if (rebuildAll.isPresent() && clearDegradedState.isPresent()) 202 { 203 argParser.displayMessageAndUsageReference(err, 204 ERR_REBUILDINDEX_REBUILD_ALL_DEGRADED_ERROR.get("clearDegradedState")); 205 return 1; 206 } 207 208 // Checks the version - if upgrade required, the tool is unusable 209 try 210 { 211 checkVersion(); 212 } 213 catch (InitializationException e) 214 { 215 printWrappedText(err, e.getMessage()); 216 return 1; 217 } 218 return process(argParser, initializeServer, out, err); 219 } 220 221 /** 222 * Initializes the arguments for the rebuild index tool. 223 * 224 * @param isMultipleBackends 225 * {@code true} if the tool is used as internal. 226 * @throws ArgumentException 227 * If the initialization fails. 228 */ 229 private void initializeArguments(final boolean isMultipleBackends) 230 throws ArgumentException 231 { 232 argParser.setShortToolDescription(REF_SHORT_DESC_REBUILD_INDEX.get()); 233 234 configClass = 235 StringArgument.builder("configClass") 236 .shortIdentifier('C') 237 .description(INFO_DESCRIPTION_CONFIG_CLASS.get()) 238 .hidden() 239 .required() 240 .defaultValue(ConfigFileHandler.class.getName()) 241 .valuePlaceholder(INFO_CONFIGCLASS_PLACEHOLDER.get()) 242 .buildAndAddToParser(argParser); 243 configFile = 244 StringArgument.builder("configFile") 245 .shortIdentifier('f') 246 .description(INFO_DESCRIPTION_CONFIG_FILE.get()) 247 .hidden() 248 .required() 249 .valuePlaceholder(INFO_CONFIGFILE_PLACEHOLDER.get()) 250 .buildAndAddToParser(argParser); 251 252 final StringArgument.Builder builder = 253 StringArgument.builder("baseDN") 254 .shortIdentifier('b') 255 .description(INFO_REBUILDINDEX_DESCRIPTION_BASE_DN.get()) 256 .required() 257 .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get()); 258 if (isMultipleBackends) { 259 builder.multiValued(); 260 } 261 baseDNString = builder.buildAndAddToParser(argParser); 262 263 indexList = 264 StringArgument.builder("index") 265 .shortIdentifier('i') 266 .description(INFO_REBUILDINDEX_DESCRIPTION_INDEX_NAME.get()) 267 .multiValued() 268 .valuePlaceholder(INFO_INDEX_PLACEHOLDER.get()) 269 .buildAndAddToParser(argParser); 270 rebuildAll = 271 BooleanArgument.builder("rebuildAll") 272 .description(INFO_REBUILDINDEX_DESCRIPTION_REBUILD_ALL.get()) 273 .buildAndAddToParser(argParser); 274 rebuildDegraded = 275 BooleanArgument.builder("rebuildDegraded") 276 .description(INFO_REBUILDINDEX_DESCRIPTION_REBUILD_DEGRADED.get()) 277 .buildAndAddToParser(argParser); 278 clearDegradedState = 279 BooleanArgument.builder("clearDegradedState") 280 .description(INFO_REBUILDINDEX_DESCRIPTION_CLEAR_DEGRADED_STATE.get()) 281 .buildAndAddToParser(argParser); 282 tmpDirectory = 283 StringArgument.builder("tmpdirectory") 284 .description(INFO_REBUILDINDEX_DESCRIPTION_TEMP_DIRECTORY.get()) 285 .defaultValue("import-tmp") 286 .valuePlaceholder(INFO_REBUILDINDEX_TEMP_DIR_PLACEHOLDER.get()) 287 .buildAndAddToParser(argParser); 288 289 final BooleanArgument displayUsage = showUsageArgument(); 290 argParser.addArgument(displayUsage); 291 argParser.setUsageArgument(displayUsage); 292 } 293 294 /** {@inheritDoc} */ 295 @Override 296 protected int processLocal(final boolean initializeServer, 297 final PrintStream out, final PrintStream err) 298 { 299 // Performs the initial bootstrap of the Directory Server and processes the 300 // configuration. 301 final DirectoryServer directoryServer = DirectoryServer.getInstance(); 302 if (initializeServer) 303 { 304 final int init = initializeServer(directoryServer, out, err); 305 if (init != 0) 306 { 307 return init; 308 } 309 setErrorAndDebugLogPublisher(out, err); 310 } 311 312 if (!configureRebuildProcess(baseDNString.getValue())) 313 { 314 return 1; 315 } 316 317 return rebuildIndex(currentBackend, rebuildConfig); 318 } 319 320 /** 321 * Configures the rebuild index process. i.e.: decodes the selected DN and 322 * retrieves the backend which holds it. Finally, initializes and sets the 323 * rebuild configuration. 324 * 325 * @param dn 326 * User selected base DN. 327 * @return A boolean representing the result of the process. 328 */ 329 private boolean configureRebuildProcess(final String dn) { 330 // Decodes the base DN provided by the user. 331 DN rebuildBaseDN = null; 332 try 333 { 334 rebuildBaseDN = DN.valueOf(dn); 335 } 336 catch (Exception e) 337 { 338 logger.error(ERR_CANNOT_DECODE_BASE_DN, dn, 339 getExceptionMessage(e)); 340 return false; 341 } 342 343 // Retrieves the backend which holds the selected base DN. 344 try 345 { 346 setCurrentBackend(retrieveBackend(rebuildBaseDN)); 347 } 348 catch (Exception e) 349 { 350 logger.error(LocalizableMessage.raw(e.getMessage())); 351 return false; 352 } 353 354 setRebuildConfig(initializeRebuildIndexConfiguration(rebuildBaseDN)); 355 return true; 356 } 357 358 /** 359 * Defines the error and the debug log publisher used in this tool. 360 * 361 * @param out 362 * The output stream to use for standard output, or {@code null} if 363 * standard output is not needed. 364 * @param err 365 * The output stream to use for standard error, or {@code null} if 366 * standard error is not needed. 367 */ 368 private void setErrorAndDebugLogPublisher(final PrintStream out, 369 final PrintStream err) 370 { 371 try 372 { 373 final ErrorLogPublisher errorLogPublisher = 374 TextErrorLogPublisher 375 .getToolStartupTextErrorPublisher(new TextWriter.STREAM(out)); 376 ErrorLogger.getInstance().addLogPublisher(errorLogPublisher); 377 DebugLogger.getInstance().addPublisherIfRequired(new TextWriter.STREAM(out)); 378 } 379 catch (Exception e) 380 { 381 err.println("Error installing the custom error logger: " 382 + stackTraceToSingleLineString(e)); 383 } 384 } 385 386 /** 387 * Initializes the directory server.<br /> 388 * Processes to : 389 * - bootstrapClient 390 * - initializeJMX 391 * - initializeConfiguration 392 * - initializeSchema 393 * - coreConfigManager.initializeCoreConfig() 394 * - initializeCryptoManager 395 * 396 * @param directoryServer 397 * The current instance. 398 * @param out 399 * The output stream to use for standard output, or {@code null} if 400 * standard output is not needed. 401 * @param err 402 * The output stream to use for standard error, or {@code null} if 403 * standard error is not needed. 404 * @return The result code. 405 */ 406 private int initializeServer(final DirectoryServer directoryServer, 407 final PrintStream out, final PrintStream err) 408 { 409 try 410 { 411 DirectoryServer.bootstrapClient(); 412 DirectoryServer.initializeJMX(); 413 } 414 catch (Exception e) 415 { 416 printWrappedText(err, ERR_SERVER_BOOTSTRAP_ERROR.get(getExceptionMessage(e))); 417 return 1; 418 } 419 420 try 421 { 422 directoryServer.initializeConfiguration(configClass.getValue(), 423 configFile.getValue()); 424 } 425 catch (Exception ex) 426 { 427 printWrappedText(err, toErrorMsg(ERR_CANNOT_LOAD_CONFIG, ex)); 428 return 1; 429 } 430 431 // Initializes the Directory Server schema elements. 432 try 433 { 434 directoryServer.initializeSchema(); 435 } 436 catch (Exception e) 437 { 438 printWrappedText(err, toErrorMsg(ERR_CANNOT_LOAD_SCHEMA, e)); 439 return 1; 440 } 441 442 // Initializes the Directory Server core configuration. 443 try 444 { 445 final CoreConfigManager coreConfigManager = new CoreConfigManager(directoryServer.getServerContext()); 446 coreConfigManager.initializeCoreConfig(); 447 } 448 catch (Exception ex) 449 { 450 printWrappedText(err, toErrorMsg(ERR_CANNOT_INITIALIZE_CORE_CONFIG, ex)); 451 return 1; 452 } 453 454 // Initializes the Directory Server crypto manager. 455 try 456 { 457 directoryServer.initializeCryptoManager(); 458 } 459 catch (Exception ex) 460 { 461 printWrappedText(err, toErrorMsg(ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER, ex)); 462 return 1; 463 } 464 465 return 0; 466 } 467 468 private String toErrorMsg(Arg1<Object> errorMsg, Exception ex) 469 { 470 final LocalizableMessage message = getErrorMsg(ex, errorMsg); 471 return wrapText(message, MAX_LINE_WIDTH); 472 } 473 474 private LocalizableMessage getErrorMsg(Exception ex, Arg1<Object> errorMsg) 475 { 476 if (ex instanceof ConfigException || ex instanceof InitializationException) 477 { 478 return errorMsg.get(ex.getMessage()); 479 } 480 return errorMsg.get(getExceptionMessage(ex)); 481 } 482 483 /** 484 * Initializes and sets the rebuild index configuration. 485 * 486 * @param rebuildBaseDN 487 * The selected base DN. 488 * @return A rebuild configuration. 489 */ 490 private RebuildConfig initializeRebuildIndexConfiguration( 491 final DN rebuildBaseDN) 492 { 493 final RebuildConfig config = new RebuildConfig(); 494 config.setBaseDN(rebuildBaseDN); 495 for (final String s : indexList.getValues()) 496 { 497 config.addRebuildIndex(s); 498 } 499 500 if (rebuildAll.isPresent()) 501 { 502 config.setRebuildMode(RebuildMode.ALL); 503 } 504 else if (rebuildDegraded.isPresent()) 505 { 506 config.setRebuildMode(RebuildMode.DEGRADED); 507 } 508 else 509 { 510 if (clearDegradedState.isPresent()) 511 { 512 config.isClearDegradedState(true); 513 } 514 config.setRebuildMode(RebuildMode.USER_DEFINED); 515 } 516 517 config.setTmpDirectory(tmpDirectory.getValue()); 518 return config; 519 } 520 521 /** 522 * Launches the rebuild index process. 523 * 524 * @param backend 525 * The directory server backend. 526 * @param rebuildConfig 527 * The configuration which is going to be used by the rebuild index 528 * process. 529 * @return An integer representing the result of the process. 530 */ 531 private int rebuildIndex(final Backend<?> backend, final RebuildConfig rebuildConfig) 532 { 533 // Acquire an exclusive lock for the backend. 534 //TODO: Find a way to do this with the server online. 535 try 536 { 537 final String lockFile = LockFileManager.getBackendLockFileName(backend); 538 final StringBuilder failureReason = new StringBuilder(); 539 if (!LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 540 { 541 logger.error(ERR_REBUILDINDEX_CANNOT_EXCLUSIVE_LOCK_BACKEND, backend.getBackendID(), failureReason); 542 return 1; 543 } 544 } 545 catch (Exception e) 546 { 547 logger.error(ERR_REBUILDINDEX_CANNOT_EXCLUSIVE_LOCK_BACKEND, backend 548 .getBackendID(), getExceptionMessage(e)); 549 return 1; 550 } 551 552 int returnCode = 0; 553 try 554 { 555 backend.rebuildBackend(rebuildConfig, DirectoryServer.getInstance().getServerContext()); 556 } 557 catch (InitializationException e) 558 { 559 logger.error(ERR_REBUILDINDEX_ERROR_DURING_REBUILD, e.getMessage()); 560 returnCode = 1; 561 } 562 catch (Exception e) 563 { 564 logger.error(ERR_REBUILDINDEX_ERROR_DURING_REBUILD, getExceptionMessage(e)); 565 returnCode = 1; 566 } 567 finally 568 { 569 // Release the shared lock on the backend. 570 try 571 { 572 final String lockFile = LockFileManager.getBackendLockFileName(backend); 573 final StringBuilder failureReason = new StringBuilder(); 574 if (!LockFileManager.releaseLock(lockFile, failureReason)) 575 { 576 logger.warn(WARN_REBUILDINDEX_CANNOT_UNLOCK_BACKEND, backend.getBackendID(), failureReason); 577 } 578 } 579 catch (Exception e) 580 { 581 logger.error(WARN_REBUILDINDEX_CANNOT_UNLOCK_BACKEND, backend.getBackendID(), getExceptionMessage(e)); 582 } 583 } 584 585 return returnCode; 586 } 587 588 /** 589 * Gets information about the backends defined in the server. Iterates through 590 * them, finding the one that holds the base DN. 591 * 592 * @param selectedDN 593 * The user selected DN. 594 * @return The backend which holds the selected base DN. 595 * @throws ConfigException 596 * If the backend is poorly configured. 597 * @throws Exception 598 * If an exception occurred during the backend search. 599 */ 600 private Backend<?> retrieveBackend(final DN selectedDN) throws ConfigException, Exception 601 { 602 final ArrayList<Backend> backendList = new ArrayList<>(); 603 final ArrayList<BackendCfg> entryList = new ArrayList<>(); 604 final ArrayList<List<DN>> dnList = new ArrayList<>(); 605 BackendToolUtils.getBackends(backendList, entryList, dnList); 606 607 Backend<?> backend = null; 608 final int numBackends = backendList.size(); 609 for (int i = 0; i < numBackends; i++) 610 { 611 final Backend<?> b = backendList.get(i); 612 final List<DN> baseDNs = dnList.get(i); 613 if (baseDNs.contains(selectedDN)) 614 { 615 if (backend != null) 616 { 617 throw new ConfigException(ERR_MULTIPLE_BACKENDS_FOR_BASE.get(baseDNString.getValue())); 618 } 619 backend = b; 620 } 621 } 622 623 if (backend == null) 624 { 625 throw new ConfigException(ERR_NO_BACKENDS_FOR_BASE.get(baseDNString.getValue())); 626 } 627 if (!backend.supports(BackendOperation.INDEXING)) 628 { 629 throw new ConfigException(ERR_BACKEND_NO_INDEXING_SUPPORT.get()); 630 } 631 return backend; 632 } 633 634 /** 635 * This function allow internal use of the rebuild index tools. This function 636 * rebuilds indexes shared by multiple backends. 637 * 638 * @param initializeServer 639 * Indicates whether to initialize the server. 640 * @param out 641 * The print stream which is used to display errors/debug lines. 642 * Usually redirected into a logger if the tool is used as external. 643 * @param args 644 * The arguments used to launch the rebuild index process. 645 * @return An integer indicating the result of this action. 646 */ 647 public int rebuildIndexesWithinMultipleBackends( 648 final boolean initializeServer, final PrintStream out, 649 final String... args) 650 { 651 try 652 { 653 setErrorAndDebugLogPublisher(out, out); 654 655 try 656 { 657 initializeArguments(true); 658 } 659 catch (ArgumentException ae) 660 { 661 printWrappedText(out, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 662 return 1; 663 } 664 665 try 666 { 667 argParser.parseArguments(args); 668 } 669 catch (ArgumentException ae) 670 { 671 argParser.displayMessageAndUsageReference(out, ERR_ERROR_PARSING_ARGS.get(ae.getMessage())); 672 return 1; 673 } 674 675 final DirectoryServer directoryServer = DirectoryServer.getInstance(); 676 if (initializeServer) 677 { 678 final int init = initializeServer(directoryServer, out, out); 679 if (init != 0) 680 { 681 return init; 682 } 683 } 684 685 for (final String dn : baseDNString.getValues()) 686 { 687 if (!configureRebuildProcess(dn)) 688 { 689 return 1; 690 } 691 692 final int result = 693 rebuildIndex(getCurrentBackend(), getRebuildConfig()); 694 // If the rebuild index is going bad, process is stopped. 695 if (result != 0) 696 { 697 out.println(String.format( 698 "An error occurs during the rebuild index process" + 699 " in %s, rebuild index(es) aborted.", 700 dn)); 701 return 1; 702 } 703 } 704 } 705 finally 706 { 707 StaticUtils.close(out); 708 } 709 return 0; 710 } 711 712 /** {@inheritDoc} */ 713 @Override 714 public String getTaskId() 715 { 716 // NYI. 717 return null; 718 } 719 720 /** {@inheritDoc} */ 721 @Override 722 public void addTaskAttributes(List<RawAttribute> attributes) 723 { 724 // Required attributes 725 addLdapAttribute(attributes, ATTR_REBUILD_BASE_DN, baseDNString.getValue()); 726 727 attributes.add(new LDAPAttribute(ATTR_REBUILD_INDEX, indexList.getValues())); 728 729 if (hasNonDefaultValue(tmpDirectory)) 730 { 731 addLdapAttribute(attributes, ATTR_REBUILD_TMP_DIRECTORY, tmpDirectory.getValue()); 732 } 733 734 if (hasNonDefaultValue(rebuildAll)) 735 { 736 addLdapAttribute(attributes, ATTR_REBUILD_INDEX, REBUILD_ALL); 737 } 738 739 if (hasNonDefaultValue(rebuildDegraded)) 740 { 741 addLdapAttribute(attributes, ATTR_REBUILD_INDEX, REBUILD_DEGRADED); 742 } 743 744 if (hasNonDefaultValue(clearDegradedState)) 745 { 746 addLdapAttribute(attributes, ATTR_REBUILD_INDEX_CLEARDEGRADEDSTATE, "true"); 747 } 748 } 749 750 private void addLdapAttribute(List<RawAttribute> attributes, String attrType, String attrValue) 751 { 752 attributes.add(new LDAPAttribute(attrType, attrValue)); 753 } 754 755 private boolean hasNonDefaultValue(BooleanArgument arg) 756 { 757 return arg.getValue() != null 758 && !arg.getValue().equals(arg.getDefaultValue()); 759 } 760 761 private boolean hasNonDefaultValue(StringArgument arg) 762 { 763 return arg.getValue() != null 764 && !arg.getValue().equals(arg.getDefaultValue()); 765 } 766 767 /** {@inheritDoc} */ 768 @Override 769 public String getTaskObjectclass() 770 { 771 return "ds-task-rebuild"; 772 } 773 774 /** {@inheritDoc} */ 775 @Override 776 public Class<?> getTaskClass() 777 { 778 return RebuildTask.class; 779 } 780 781 /** 782 * Returns the rebuild configuration. 783 * 784 * @return The rebuild configuration. 785 */ 786 public RebuildConfig getRebuildConfig() 787 { 788 return rebuildConfig; 789 } 790 791 /** 792 * Sets the rebuild configuration. 793 * 794 * @param rebuildConfig 795 * The rebuild configuration to set. 796 */ 797 public void setRebuildConfig(RebuildConfig rebuildConfig) 798 { 799 this.rebuildConfig = rebuildConfig; 800 } 801 802 /** 803 * Returns the current backend. 804 * 805 * @return The current backend. 806 */ 807 public Backend<?> getCurrentBackend() 808 { 809 return currentBackend; 810 } 811 812 /** 813 * Sets the current backend. 814 * 815 * @param currentBackend 816 * The current backend to set. 817 */ 818 public void setCurrentBackend(Backend<?> currentBackend) 819 { 820 this.currentBackend = currentBackend; 821 } 822}