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 * Portions Copyright 2013-2015 ForgeRock AS 025 */ 026package org.opends.server.tools.upgrade; 027 028import java.io.File; 029import java.io.IOException; 030import java.util.Arrays; 031import java.util.HashSet; 032import java.util.LinkedList; 033import java.util.List; 034import java.util.Set; 035 036import javax.security.auth.callback.TextOutputCallback; 037 038import org.forgerock.i18n.LocalizableMessage; 039import org.forgerock.i18n.slf4j.LocalizedLogger; 040import org.forgerock.opendj.ldap.Filter; 041import org.opends.server.tools.JavaPropertiesTool; 042import org.opends.server.tools.RebuildIndex; 043import org.opends.server.util.BuildVersion; 044import org.opends.server.util.ChangeOperationType; 045 046import com.forgerock.opendj.cli.ClientException; 047import com.forgerock.opendj.cli.ReturnCode; 048 049import static javax.security.auth.callback.ConfirmationCallback.*; 050import static org.opends.messages.ToolMessages.*; 051import static org.opends.server.tools.upgrade.FileManager.*; 052import static org.opends.server.tools.upgrade.Installation.*; 053import static org.opends.server.tools.upgrade.UpgradeUtils.*; 054 055/** 056 * Factory methods for create new upgrade tasks. 057 */ 058public final class UpgradeTasks 059{ 060 /** Logger for the upgrade. */ 061 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 062 063 /** An errors counter in case of ignore errors mode. */ 064 static int countErrors; 065 066 /** Contains all the indexes to rebuild. */ 067 static Set<String> indexesToRebuild = new HashSet<>(); 068 069 /** A flag to avoid rebuild single indexes if 'rebuild all' is selected. */ 070 static boolean isRebuildAllIndexesIsPresent; 071 072 /** A flag for marking 'rebuild all' task accepted by user. */ 073 static boolean isRebuildAllIndexesTaskAccepted; 074 075 /** 076 * Returns a new upgrade task which adds a config entry to the underlying 077 * config file. 078 * 079 * @param summary 080 * The summary of this upgrade task. 081 * @param ldif 082 * The LDIF record which will be applied to matching entries. 083 * @return A new upgrade task which applies an LDIF record to all 084 * configuration entries matching the provided filter. 085 */ 086 public static UpgradeTask addConfigEntry(final LocalizableMessage summary, 087 final String... ldif) 088 { 089 return updateConfigEntry(summary, null, ChangeOperationType.ADD, ldif); 090 } 091 092 /** 093 * This task copies the file placed in parameter within the config / schema 094 * folder. If the file already exists, it's overwritten. 095 * 096 * @param fileName 097 * The name of the file which need to be copied. 098 * @return A task which copy the the file placed in parameter within the 099 * config / schema folder. If the file already exists, it's 100 * overwritten. 101 */ 102 public static UpgradeTask copySchemaFile(final String fileName) 103 { 104 return new AbstractUpgradeTask() 105 { 106 @Override 107 public void perform(final UpgradeContext context) throws ClientException 108 { 109 final LocalizableMessage msg = INFO_UPGRADE_TASK_REPLACE_SCHEMA_FILE.get(fileName); 110 logger.debug(msg); 111 112 final ProgressNotificationCallback pnc = 113 new ProgressNotificationCallback(0, msg, 0); 114 115 final File schemaFileTemplate = 116 new File(templateConfigSchemaDirectory, fileName); 117 118 try 119 { 120 context.notifyProgress(pnc.setProgress(20)); 121 if (!schemaFileTemplate.exists() || schemaFileTemplate.length() == 0) 122 { 123 throw new IOException(ERR_UPGRADE_CORRUPTED_TEMPLATE 124 .get(schemaFileTemplate.getPath()).toString()); 125 } 126 copy(schemaFileTemplate, configSchemaDirectory, true); 127 context.notifyProgress(pnc.setProgress(100)); 128 } 129 catch (final IOException e) 130 { 131 manageTaskException(context, ERR_UPGRADE_COPYSCHEMA_FAILS.get( 132 schemaFileTemplate.getName(), e.getMessage()), pnc); 133 } 134 } 135 }; 136 } 137 138 /** 139 * This task copies the file placed in parameter within the config folder. If 140 * the file already exists, it's overwritten. 141 * 142 * @param fileName 143 * The name of the file which need to be copied. 144 * @return A task which copy the the file placed in parameter within the 145 * config folder. If the file already exists, it's overwritten. 146 */ 147 public static UpgradeTask addConfigFile(final String fileName) 148 { 149 return new AbstractUpgradeTask() 150 { 151 @Override 152 public void perform(final UpgradeContext context) throws ClientException 153 { 154 final LocalizableMessage msg = INFO_UPGRADE_TASK_ADD_CONFIG_FILE.get(fileName); 155 logger.debug(msg); 156 157 final ProgressNotificationCallback pnc = 158 new ProgressNotificationCallback(0, msg, 0); 159 160 final File configFile = new File(templateConfigDirectory, fileName); 161 162 try 163 { 164 context.notifyProgress(pnc.setProgress(20)); 165 166 copy(configFile, configDirectory, true); 167 context.notifyProgress(pnc.setProgress(100)); 168 } 169 catch (final IOException e) 170 { 171 manageTaskException(context, ERR_UPGRADE_ADD_CONFIG_FILE_FAILS.get( 172 configFile.getName(), e.getMessage()), pnc); 173 } 174 } 175 }; 176 } 177 178 /** 179 * Returns a new upgrade task which deletes a config entry from the underlying 180 * config file. 181 * 182 * @param summary 183 * The summary of this upgrade task. 184 * @param dnInLDIF 185 * The dn to delete in the form of LDIF. 186 * @return A new upgrade task which applies an LDIF record to all 187 * configuration entries matching the provided filter. 188 */ 189 public static UpgradeTask deleteConfigEntry(final LocalizableMessage summary, 190 final String dnInLDIF) 191 { 192 return updateConfigEntry(summary, null, ChangeOperationType.DELETE, dnInLDIF); 193 } 194 195 /** 196 * Returns a new upgrade task which applies an LDIF record to all 197 * configuration entries matching the provided filter. 198 * 199 * @param summary 200 * The summary of this upgrade task. 201 * @param filter 202 * The LDAP filter which configuration entries must match. 203 * @param ldif 204 * The LDIF record which will be applied to matching entries. 205 * @return A new upgrade task which applies an LDIF record to all 206 * configuration entries matching the provided filter. 207 */ 208 public static UpgradeTask modifyConfigEntry(final LocalizableMessage summary, 209 final String filter, final String... ldif) 210 { 211 return updateConfigEntry(summary, filter, ChangeOperationType.MODIFY, ldif); 212 } 213 214 /** 215 * This task adds a new attribute type (must exists in the original file) to 216 * the specified file placed in parameter. The destination must be a file 217 * contained in the config/schema folder. E.g : This example adds a new 218 * attribute type named 'etag' in the 00.core.ldif. The 'etag' attribute 219 * already exists in the 00-core.ldif template schema file. 220 * 221 * <pre> 222 * register("2.5.0.7192", 223 * newAttributeTypes(LocalizableMessage.raw("New attribute etag"), 224 * false, "00-core.ldif", 225 * "1.3.6.1.4.1.36733.2.1.1.59")); 226 * </pre> 227 * 228 * @param summary 229 * The summary of the task. 230 * @param fileName 231 * The file where to add the new attribute types. This file must be 232 * contained in the configuration/schema folder. 233 * @param attributeOids 234 * The OIDs of the new attributes to add to. 235 * @return An upgrade task which adds new attribute types, defined previously 236 * in the configuration template files, reads the definition 237 * and adds it onto the specified file in parameter. 238 */ 239 public static UpgradeTask newAttributeTypes(final LocalizableMessage summary, 240 final String fileName, final String... attributeOids) 241 { 242 return new AbstractUpgradeTask() 243 { 244 @Override 245 public void perform(final UpgradeContext context) throws ClientException 246 { 247 logger.debug(summary); 248 249 final ProgressNotificationCallback pnc = 250 new ProgressNotificationCallback(0, summary, 20); 251 context.notifyProgress(pnc); 252 253 final File schemaFileTemplate = 254 new File(templateConfigSchemaDirectory, fileName); 255 256 final File pathDestination = new File(configSchemaDirectory, fileName); 257 try 258 { 259 final int changeCount = 260 updateSchemaFile(schemaFileTemplate, pathDestination, 261 attributeOids, null); 262 263 displayChangeCount(pathDestination.getPath(), changeCount); 264 265 context.notifyProgress(pnc.setProgress(100)); 266 } 267 catch (final IOException | IllegalStateException e) 268 { 269 manageTaskException(context, ERR_UPGRADE_ADDATTRIBUTE_FAILS.get( 270 schemaFileTemplate.getName(), e.getMessage()), pnc); 271 } 272 } 273 }; 274 } 275 276 /** 277 * This task adds a new object class (must exists in the original file) to the 278 * specified file placed in parameter. The destination must be a file 279 * contained in the config/schema folder. 280 * 281 * @param summary 282 * The summary of the task. 283 * @param fileName 284 * The file where to add the new object classes. This file must be 285 * contained in the configuration/schema folder. 286 * @param objectClassesOids 287 * The OIDs of the new object classes to add to. 288 * @return An upgrade task which adds new object classes, defined previously 289 * in the configuration template files, 290 * reads the definition and adds it onto the specified file in 291 * parameter. 292 */ 293 public static UpgradeTask newObjectClasses(final LocalizableMessage summary, 294 final String fileName, final String... objectClassesOids) 295 { 296 return new AbstractUpgradeTask() 297 { 298 @Override 299 public void perform(final UpgradeContext context) throws ClientException 300 { 301 logger.debug(summary); 302 303 final ProgressNotificationCallback pnc = 304 new ProgressNotificationCallback(0, summary, 20); 305 context.notifyProgress(pnc); 306 307 final File schemaFileTemplate = 308 new File(templateConfigSchemaDirectory, fileName); 309 310 final File pathDestination = new File(configSchemaDirectory, fileName); 311 312 context.notifyProgress(pnc.setProgress(20)); 313 314 try 315 { 316 final int changeCount = 317 updateSchemaFile(schemaFileTemplate, pathDestination, 318 null, objectClassesOids); 319 320 displayChangeCount(pathDestination.getPath(), changeCount); 321 322 context.notifyProgress(pnc.setProgress(100)); 323 } 324 catch (final IOException e) 325 { 326 manageTaskException(context, ERR_UPGRADE_ADDOBJECTCLASS_FAILS.get( 327 schemaFileTemplate.getName(), e.getMessage()), pnc); 328 } 329 catch (final IllegalStateException e) 330 { 331 manageTaskException(context, ERR_UPGRADE_ADDATTRIBUTE_FAILS.get( 332 schemaFileTemplate.getName(), e.getMessage()), pnc); 333 } 334 } 335 }; 336 } 337 338 /** 339 * Re-run the dsjavaproperties tool to rewrite the set-java-home script/batch file. 340 * 341 * @param summary 342 * The summary of the task. 343 * @return An upgrade task which runs dsjavaproperties. 344 */ 345 public static UpgradeTask rerunJavaPropertiesTool(final LocalizableMessage summary) 346 { 347 return new AbstractUpgradeTask() 348 { 349 @Override 350 public void perform(UpgradeContext context) throws ClientException 351 { 352 logger.debug(summary); 353 354 final ProgressNotificationCallback pnc = new ProgressNotificationCallback(0, summary, 50); 355 context.notifyProgress(pnc); 356 357 int returnValue = JavaPropertiesTool.mainCLI("--quiet"); 358 context.notifyProgress(pnc.setProgress(100)); 359 360 if (JavaPropertiesTool.ErrorReturnCode.SUCCESSFUL.getReturnCode() != returnValue && 361 JavaPropertiesTool.ErrorReturnCode.SUCCESSFUL_NOP.getReturnCode() != returnValue) { 362 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, ERR_UPGRADE_DSJAVAPROPERTIES_FAILED.get()); 363 } 364 } 365 }; 366 } 367 368 /** 369 * Creates a group of tasks which will only be invoked if the current version 370 * is more recent than the provided version. This may be useful in cases where 371 * a regression was introduced in version X and resolved in a later version Y. 372 * In this case, the provided upgrade tasks will only be invoked if the 373 * current version is between X (inclusive) and Y (exclusive). 374 * 375 * @param versionString 376 * The lower bound version. The upgrade tasks will not be applied if 377 * the current version is older than this version. 378 * @param tasks 379 * The group of tasks to invoke if the current version is equal to or 380 * more recent than {@code versionString}. 381 * @return An upgrade task which will only be invoked if the current version 382 * is more recent than the provided version. 383 */ 384 public static UpgradeTask regressionInVersion(final String versionString, final UpgradeTask... tasks) 385 { 386 final BuildVersion version = BuildVersion.valueOf(versionString); 387 return conditionalUpgradeTasks(new UpgradeCondition() 388 { 389 @Override 390 public boolean shouldPerformUpgradeTasks(final UpgradeContext context) throws ClientException 391 { 392 return context.getFromVersion().compareTo(version) >= 0; 393 } 394 }, tasks); 395 } 396 397 /** 398 * Creates a group of tasks which will only be invoked if the user confirms agreement. This may be 399 * useful in cases where a feature is deprecated and the upgrade is capable of migrating the 400 * configuration to the new replacement feature. 401 * 402 * @param message 403 * The confirmation message. 404 * @param tasks 405 * The group of tasks to invoke if the user agrees. 406 * @return An upgrade task which will only be invoked if the user confirms agreement. 407 */ 408 public static UpgradeTask requireConfirmation(final LocalizableMessage message, final UpgradeTask... tasks) 409 { 410 return conditionalUpgradeTasks(new UpgradeCondition() 411 { 412 @Override 413 public boolean shouldPerformUpgradeTasks(final UpgradeContext context) throws ClientException 414 { 415 return context.confirmYN(INFO_UPGRADE_TASK_NEEDS_USER_CONFIRM.get(message), YES) == YES; 416 } 417 }, tasks); 418 } 419 420 /** 421 * Determines whether conditional tasks should be performed. 422 */ 423 private static interface UpgradeCondition 424 { 425 boolean shouldPerformUpgradeTasks(final UpgradeContext context) throws ClientException; 426 } 427 428 private static UpgradeTask conditionalUpgradeTasks(final UpgradeCondition condition, final UpgradeTask... tasks) 429 { 430 return new AbstractUpgradeTask() 431 { 432 private boolean shouldPerformUpgradeTasks = true; 433 434 @Override 435 public void prepare(final UpgradeContext context) throws ClientException 436 { 437 shouldPerformUpgradeTasks = condition.shouldPerformUpgradeTasks(context); 438 if (shouldPerformUpgradeTasks) 439 { 440 for (UpgradeTask task : tasks) 441 { 442 task.prepare(context); 443 } 444 } 445 } 446 447 @Override 448 public void perform(final UpgradeContext context) throws ClientException 449 { 450 if (shouldPerformUpgradeTasks) 451 { 452 for (UpgradeTask task : tasks) 453 { 454 task.perform(context); 455 } 456 } 457 } 458 459 @Override 460 public void postUpgrade(UpgradeContext context) throws ClientException 461 { 462 if (shouldPerformUpgradeTasks) 463 { 464 boolean isOk = true; 465 for (final UpgradeTask task : tasks) 466 { 467 if (isOk) 468 { 469 try 470 { 471 task.postUpgrade(context); 472 } 473 catch (ClientException e) 474 { 475 logger.error(LocalizableMessage.raw(e.getMessage())); 476 isOk = false; 477 } 478 } 479 else 480 { 481 task.postponePostUpgrade(context); 482 } 483 } 484 } 485 } 486 487 }; 488 } 489 490 /** 491 * Creates a rebuild all indexes task. 492 * 493 * @param summary 494 * The summary of this upgrade task. 495 * @return An Upgrade task which rebuild all the indexes. 496 */ 497 public static UpgradeTask rebuildAllIndexes(final LocalizableMessage summary) 498 { 499 return new AbstractUpgradeTask() 500 { 501 private boolean isATaskToPerform = false; 502 503 @Override 504 public void prepare(UpgradeContext context) throws ClientException 505 { 506 Upgrade.setHasPostUpgradeTask(true); 507 // Requires answer from the user. 508 isATaskToPerform = context.confirmYN(summary, NO) == YES; 509 isRebuildAllIndexesIsPresent = true; 510 isRebuildAllIndexesTaskAccepted = isATaskToPerform; 511 } 512 513 @Override 514 public void postUpgrade(final UpgradeContext context) throws ClientException 515 { 516 if (!isATaskToPerform) 517 { 518 postponePostUpgrade(context); 519 } 520 } 521 522 @Override 523 public void postponePostUpgrade(UpgradeContext context) throws ClientException 524 { 525 context.notify(INFO_UPGRADE_ALL_REBUILD_INDEX_DECLINED.get(), TextOutputCallback.WARNING); 526 } 527 }; 528 } 529 530 531 532 /** 533 * Creates a rebuild index task for a given single index. As this task is 534 * possibly lengthy, it's considered as a post upgrade task. This task is not 535 * mandatory; e.g not require user interaction, but could be required to get a 536 * fully functional server. <br /> 537 * The post upgrade task just register the task. The rebuild indexes tasks are 538 * completed at the end of the upgrade process. 539 * 540 * @param summary 541 * A message describing why the index needs to be rebuilt and asking 542 * them whether or not they wish to perform this task after the 543 * upgrade. 544 * @param index 545 * The index to rebuild. 546 * @return The rebuild index task. 547 */ 548 public static UpgradeTask rebuildSingleIndex(final LocalizableMessage summary, 549 final String index) 550 { 551 return new AbstractUpgradeTask() 552 { 553 private boolean isATaskToPerform = false; 554 555 @Override 556 public void prepare(UpgradeContext context) throws ClientException 557 { 558 Upgrade.setHasPostUpgradeTask(true); 559 // Requires answer from the user. 560 isATaskToPerform = context.confirmYN(summary, NO) == YES; 561 } 562 563 @Override 564 public void postUpgrade(final UpgradeContext context) throws ClientException 565 { 566 if (isATaskToPerform) 567 { 568 indexesToRebuild.add(index); 569 } 570 else 571 { 572 postponePostUpgrade(context); 573 } 574 } 575 576 @Override 577 public void postponePostUpgrade(UpgradeContext context) throws ClientException 578 { 579 if (!isRebuildAllIndexesIsPresent) 580 { 581 context.notify(INFO_UPGRADE_REBUILD_INDEX_DECLINED.get(index), TextOutputCallback.WARNING); 582 } 583 } 584 }; 585 } 586 587 /** 588 * This task is processed at the end of the upgrade, rebuilding indexes. If a 589 * rebuild all indexes has been registered before, it takes the flag 590 * relatively to single rebuild index. 591 * 592 * @return The post upgrade rebuild indexes task. 593 */ 594 public static UpgradeTask postUpgradeRebuildIndexes() 595 { 596 return new AbstractUpgradeTask() 597 { 598 @Override 599 public void postUpgrade(final UpgradeContext context) throws ClientException 600 { 601 LocalizableMessage message = null; 602 final List<String> args = new LinkedList<>(); 603 604 if (isRebuildAllIndexesIsPresent && isRebuildAllIndexesTaskAccepted) 605 { 606 args.add("--rebuildAll"); 607 message = INFO_UPGRADE_REBUILD_ALL.get(); 608 } 609 else if (!indexesToRebuild.isEmpty() 610 && !isRebuildAllIndexesTaskAccepted) 611 { 612 message = INFO_UPGRADE_REBUILD_INDEX_STARTS.get(indexesToRebuild); 613 614 // Adding all requested indexes. 615 for (final String indexToRebuild : indexesToRebuild) 616 { 617 args.add("-i"); 618 args.add(indexToRebuild); 619 } 620 } 621 else 622 { 623 return; 624 } 625 // Startup message. 626 ProgressNotificationCallback pnc = 627 new ProgressNotificationCallback(0, message, 25); 628 logger.debug(message); 629 context.notifyProgress(pnc); 630 631 // Sets the arguments like the rebuild index command line. 632 args.addAll(Arrays.asList( 633 "-f", 634 new File(configDirectory, CURRENT_CONFIG_FILE_NAME).getAbsolutePath())); 635 636 /* 637 * Index(es) could be contained in several backends or none, If none, 638 * the post upgrade tasks succeed and a message is printed in the 639 * upgrade log file. 640 */ 641 final List<String> backends = UpgradeUtils.getLocalBackendsFromConfig(); 642 if (!backends.isEmpty()) 643 { 644 for (final String be : backends) 645 { 646 args.add("-b"); 647 args.add(be); 648 } 649 650 // Displays info about command line args for log only. 651 logger.debug(INFO_UPGRADE_REBUILD_INDEX_ARGUMENTS, args); 652 653 /* 654 * The rebuild-index process just display a status ok / fails. The 655 * logger stream contains all the log linked to this process. The 656 * complete process is not displayed in the upgrade console. 657 */ 658 final String[] commandLineArgs = args.toArray(new String[args.size()]); 659 final int result = new RebuildIndex().rebuildIndexesWithinMultipleBackends( 660 true, UpgradeLog.getPrintStream(), commandLineArgs); 661 662 if (result == 0) 663 { 664 logger.debug(INFO_UPGRADE_REBUILD_INDEX_ENDS); 665 context.notifyProgress(pnc.setProgress(100)); 666 } 667 else 668 { 669 final LocalizableMessage msg = ERR_UPGRADE_PERFORMING_POST_TASKS_FAIL.get(); 670 context.notifyProgress(pnc.setProgress(-100)); 671 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, msg); 672 } 673 } 674 else 675 { 676 logger.debug(INFO_UPGRADE_REBUILD_INDEX_NO_BACKEND_FOUND); 677 logger.debug(INFO_UPGRADE_REBUILD_INDEX_DECLINED, indexesToRebuild); 678 context.notifyProgress(pnc.setProgress(100)); 679 } 680 } 681 }; 682 } 683 684 /** 685 * Creates a file object representing config/upgrade/schema.ldif.current which 686 * the server creates the first time it starts if there are schema 687 * customizations. 688 * 689 * @return An upgrade task which upgrade the config/upgrade folder, creating a 690 * new schema.ldif.rev which is needed after schema customization for 691 * starting correctly the server. 692 */ 693 public static UpgradeTask updateConfigUpgradeFolder() 694 { 695 return new AbstractUpgradeTask() 696 { 697 @Override 698 public void perform(final UpgradeContext context) throws ClientException 699 { 700 final LocalizableMessage msg = INFO_UPGRADE_TASK_REFRESH_UPGRADE_DIRECTORY.get(); 701 logger.debug(msg); 702 703 final ProgressNotificationCallback pnc = new ProgressNotificationCallback(0, msg, 20); 704 context.notifyProgress(pnc); 705 706 try 707 { 708 String toRevision = String.valueOf(context.getToVersion().getRevisionNumber()); 709 updateConfigUpgradeSchemaFile(configSchemaDirectory, toRevision); 710 711 context.notifyProgress(pnc.setProgress(100)); 712 } 713 catch (final Exception ex) 714 { 715 manageTaskException(context, ERR_UPGRADE_CONFIG_ERROR_UPGRADE_FOLDER.get(ex.getMessage()), pnc); 716 } 717 } 718 }; 719 } 720 721 /** 722 * Renames the SNMP security config file if it exists. Since 2.5.0.7466 this 723 * file has been renamed. 724 * 725 * @param summary 726 * The summary of this upgrade task. 727 * @return An upgrade task which renames the old SNMP security config file if 728 * it exists. 729 */ 730 public static UpgradeTask renameSnmpSecurityConfig(final LocalizableMessage summary) 731 { 732 return new AbstractUpgradeTask() 733 { 734 @Override 735 public void perform(final UpgradeContext context) throws ClientException 736 { 737 /* 738 * Snmp config file contains old name in old version(like 2.4.5), in 739 * order to make sure the process will still work after upgrade, we need 740 * to rename it - only if it exists. 741 */ 742 final File snmpDir = UpgradeUtils.configSnmpSecurityDirectory; 743 if (snmpDir.exists()) 744 { 745 ProgressNotificationCallback pnc = 746 new ProgressNotificationCallback(0, summary, 0); 747 try 748 { 749 final File oldSnmpConfig = new File(snmpDir, "opends-snmp.security"); 750 if (oldSnmpConfig.exists()) 751 { 752 context.notifyProgress(pnc.setProgress(20)); 753 logger.debug(summary); 754 755 final File snmpConfig = new File(snmpDir, "opendj-snmp.security"); 756 FileManager.rename(oldSnmpConfig, snmpConfig); 757 758 context.notifyProgress(pnc.setProgress(100)); 759 } 760 } 761 catch (final Exception ex) 762 { 763 LocalizableMessage msg = ERR_UPGRADE_RENAME_SNMP_SECURITY_CONFIG_FILE.get(ex.getMessage()); 764 manageTaskException(context, msg, pnc); 765 } 766 } 767 } 768 }; 769 } 770 771 /** 772 * Removes the specified file from the file-system. 773 * 774 * @param file 775 * The file to be removed. 776 * @return An upgrade task which removes the specified file from the file-system. 777 */ 778 public static UpgradeTask deleteFile(final File file) 779 { 780 return new AbstractUpgradeTask() 781 { 782 @Override 783 public void perform(UpgradeContext context) throws ClientException 784 { 785 LocalizableMessage msg = UPGRADE_TASK_DELETE_FILE.get(file); 786 ProgressNotificationCallback pnc = new ProgressNotificationCallback(0, msg, 0); 787 context.notifyProgress(pnc); 788 try 789 { 790 FileManager.deleteRecursively(file); 791 context.notifyProgress(pnc.setProgress(100)); 792 } 793 catch (Exception e) 794 { 795 logger.error(LocalizableMessage.raw(e.getMessage())); 796 context.notifyProgress(pnc.setProgress(-1)); 797 } 798 } 799 }; 800 } 801 802 private static void displayChangeCount(final String fileName, 803 final int changeCount) 804 { 805 if (changeCount != 0) 806 { 807 logger.debug(INFO_UPGRADE_CHANGE_DONE_IN_SPECIFIC_FILE, fileName, changeCount); 808 } 809 else 810 { 811 logger.debug(INFO_UPGRADE_NO_CHANGE_DONE_IN_SPECIFIC_FILE, fileName); 812 } 813 } 814 815 private static void displayTaskLogInformation(final String summary, 816 final String filter, final String... ldif) 817 { 818 logger.debug(LocalizableMessage.raw(summary)); 819 if (filter != null) 820 { 821 logger.debug(LocalizableMessage.raw(filter)); 822 } 823 if (ldif != null) 824 { 825 logger.debug(LocalizableMessage.raw(Arrays.toString(ldif))); 826 } 827 } 828 829 private static void manageTaskException(final UpgradeContext context, 830 final LocalizableMessage message, final ProgressNotificationCallback pnc) 831 throws ClientException 832 { 833 countErrors++; 834 context.notifyProgress(pnc.setProgress(-100)); 835 logger.error(message); 836 if (!context.isIgnoreErrorsMode()) 837 { 838 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message); 839 } 840 } 841 842 private static UpgradeTask updateConfigEntry(final LocalizableMessage summary, final String filter, 843 final ChangeOperationType changeOperationType, final String... ldif) 844 { 845 return new AbstractUpgradeTask() 846 { 847 @Override 848 public void perform(final UpgradeContext context) throws ClientException 849 { 850 performConfigFileUpdate(summary, filter, changeOperationType, context, ldif); 851 } 852 }; 853 } 854 855 private static void performConfigFileUpdate(final LocalizableMessage summary, final String filter, 856 final ChangeOperationType changeOperationType, 857 final UpgradeContext context, final String... ldif) 858 throws ClientException 859 { 860 displayTaskLogInformation(summary.toString(), filter, ldif); 861 862 final ProgressNotificationCallback pnc = 863 new ProgressNotificationCallback(0, summary, 20); 864 865 context.notifyProgress(pnc); 866 867 try 868 { 869 final File configFile = 870 new File(configDirectory, Installation.CURRENT_CONFIG_FILE_NAME); 871 872 final Filter filterVal = filter != null ? Filter.valueOf(filter) : null; 873 final int changeCount = updateConfigFile( 874 configFile.getPath(), filterVal, changeOperationType, ldif); 875 876 displayChangeCount(configFile.getPath(), changeCount); 877 878 context.notifyProgress(pnc.setProgress(100)); 879 } 880 catch (final Exception e) 881 { 882 manageTaskException(context, LocalizableMessage.raw(e.getMessage()), pnc); 883 } 884 } 885 886 /** Prevent instantiation. */ 887 private UpgradeTasks() 888 { 889 // Do nothing. 890 } 891}