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 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.uninstaller; 028 029import java.awt.event.WindowEvent; 030import java.io.File; 031import java.io.FileFilter; 032import java.io.PrintStream; 033import java.net.InetAddress; 034import java.net.URI; 035import java.security.cert.X509Certificate; 036import java.util.*; 037 038import javax.naming.Context; 039import javax.naming.NamingException; 040import javax.naming.ldap.InitialLdapContext; 041import javax.swing.JFrame; 042import javax.swing.SwingUtilities; 043 044import org.forgerock.i18n.LocalizableMessage; 045import org.forgerock.i18n.LocalizableMessageBuilder; 046import org.forgerock.i18n.slf4j.LocalizedLogger; 047import org.opends.admin.ads.ADSContext; 048import org.opends.admin.ads.ADSContextException; 049import org.opends.admin.ads.ReplicaDescriptor; 050import org.opends.admin.ads.ServerDescriptor; 051import org.opends.admin.ads.TopologyCache; 052import org.opends.admin.ads.TopologyCacheException; 053import org.opends.admin.ads.util.ApplicationTrustManager; 054import org.opends.admin.ads.util.ConnectionUtils; 055import org.opends.admin.ads.util.PreferredConnection; 056import org.opends.guitools.uninstaller.ui.ConfirmUninstallPanel; 057import org.opends.guitools.uninstaller.ui.LoginDialog; 058import org.opends.quicksetup.*; 059import org.opends.quicksetup.ui.*; 060import org.opends.quicksetup.util.BackgroundTask; 061import org.opends.quicksetup.util.ServerController; 062import org.opends.quicksetup.util.UIKeyStore; 063import org.opends.quicksetup.util.Utils; 064import org.opends.server.admin.AttributeTypePropertyDefinition; 065import org.opends.server.admin.ClassLoaderProvider; 066import org.opends.server.admin.ClassPropertyDefinition; 067import org.opends.server.admin.ManagedObjectNotFoundException; 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.ReplicationDomainCfgClient; 072import org.opends.server.admin.std.client.ReplicationServerCfgClient; 073import org.opends.server.admin.std.client.ReplicationSynchronizationProviderCfgClient; 074import org.opends.server.admin.std.client.RootCfgClient; 075import org.opends.server.core.DirectoryServer; 076import org.opends.server.util.DynamicConstants; 077import org.opends.server.util.StaticUtils; 078 079import com.forgerock.opendj.cli.ClientException; 080 081import static com.forgerock.opendj.cli.ArgumentConstants.*; 082import static com.forgerock.opendj.cli.Utils.*; 083import static com.forgerock.opendj.util.OperatingSystem.*; 084 085import static org.forgerock.util.Utils.*; 086import static org.opends.messages.AdminToolMessages.*; 087import static org.opends.messages.QuickSetupMessages.*; 088import static org.opends.quicksetup.Step.*; 089import static org.opends.quicksetup.util.Utils.*; 090import static org.opends.server.tools.ConfigureWindowsService.*; 091 092/** 093 * This class is in charge of performing the uninstallation of Open DS. 094 */ 095public class Uninstaller extends GuiApplication implements CliApplication { 096 097 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 098 private ProgressStep status = UninstallProgressStep.NOT_STARTED; 099 private boolean runStarted; 100 private boolean errorOnRemoteOccurred; 101 private boolean errorDeletingOccurred; 102 103 private UninstallerArgumentParser parser; 104 105 private Map<ProgressStep, Integer> hmRatio = new HashMap<>(); 106 private Map<ProgressStep, LocalizableMessage> hmSummary = new HashMap<>(); 107 108 private ApplicationException ue; 109 private Boolean isWindowsServiceEnabled; 110 private UninstallCliHelper cliHelper = new UninstallCliHelper(); 111 112 private LoginDialog loginDialog; 113 private ProgressDialog startProgressDlg; 114 private LocalizableMessageBuilder startProgressDetails = new LocalizableMessageBuilder(); 115 private UninstallData conf; 116 117 /** Default constructor. */ 118 public Uninstaller() 119 { 120 super(); 121 122 /* Do some initialization required to use the administration framework 123 * classes. Note that this is not done in the uninstaller code because 124 * when the basic configuration of the server is performed (using 125 * ConfigureDS) this initialization is done. 126 */ 127 DirectoryServer.bootstrapClient(); 128 // Bootstrap definition classes. 129 try 130 { 131 if (!ClassLoaderProvider.getInstance().isEnabled()) 132 { 133 ClassLoaderProvider.getInstance().enable(); 134 } 135 } 136 catch (Throwable t) 137 { 138 logger.warn(LocalizableMessage.raw("Error enabling admin framework class loader: "+t, 139 t)); 140 } 141 142 // Switch off class name validation in client. 143 ClassPropertyDefinition.setAllowClassValidation(false); 144 145 // Switch off attribute type name validation in client. 146 AttributeTypePropertyDefinition.setCheckSchema(false); 147 148 logger.info(LocalizableMessage.raw("Uninstaller is created.")); 149 } 150 /** {@inheritDoc} */ 151 @Override 152 public LocalizableMessage getFrameTitle() { 153 LocalizableMessage defaultVal = INFO_FRAME_UNINSTALL_TITLE.get(DynamicConstants.PRODUCT_NAME); 154 return Utils.getCustomizedObject("INFO_FRAME_UNINSTALL_TITLE", defaultVal, LocalizableMessage.class); 155 } 156 157 /** {@inheritDoc} */ 158 @Override 159 public UserData createUserData() { 160 UninstallUserData data = new UninstallUserData(); 161 data.setTrustManager(super.getTrustManager()); 162 return data; 163 } 164 165 /** {@inheritDoc} */ 166 @Override 167 public WizardStep getFirstWizardStep() { 168 return Step.CONFIRM_UNINSTALL; 169 } 170 171 /** {@inheritDoc} */ 172 @Override 173 public WizardStep getNextWizardStep(WizardStep step) { 174 Step nextStep = null; 175 if (step != null && step.equals(Step.CONFIRM_UNINSTALL)) { 176 nextStep = Step.PROGRESS; 177 } 178 else if (Step.PROGRESS.equals(step)) 179 { 180 nextStep = Step.FINISHED; 181 } 182 return nextStep; 183 } 184 185 /** {@inheritDoc} */ 186 @Override 187 public WizardStep getPreviousWizardStep(WizardStep step) { 188 Step prevStep = null; 189 if (step != null && step.equals(Step.PROGRESS)) { 190 prevStep = Step.CONFIRM_UNINSTALL; 191 } 192 else if (Step.FINISHED.equals(step)) 193 { 194 prevStep = Step.PROGRESS; 195 } 196 return prevStep; 197 } 198 199 /** {@inheritDoc} */ 200 @Override 201 public WizardStep getFinishedStep() { 202 return Step.FINISHED; 203 } 204 205 /** {@inheritDoc} */ 206 @Override 207 public boolean finishOnLeft() 208 { 209 return false; 210 } 211 212 /** {@inheritDoc} */ 213 @Override 214 public boolean canGoBack(WizardStep step) { 215 return false; 216 } 217 218 /** {@inheritDoc} */ 219 @Override 220 public boolean canGoForward(WizardStep step) { 221 return false; 222 } 223 224 /** {@inheritDoc} */ 225 @Override 226 public boolean canFinish(WizardStep step) { 227 return step == Step.CONFIRM_UNINSTALL; 228 } 229 230 /** 231 * Whether the provided wizard step allow to quit. 232 * 233 * @param step the wizard step 234 * @return true if the provided wizard step allow to quit, false otherwise 235 */ 236 public boolean canQuit(WizardStep step) { 237 return step == Step.CONFIRM_UNINSTALL; 238 } 239 240 /** {@inheritDoc} */ 241 @Override 242 public void nextClicked(WizardStep cStep, QuickSetup qs) { 243 if (cStep == PROGRESS) { 244 throw new IllegalStateException("Cannot click on next from progress step"); 245 } else if (cStep == REVIEW) { 246 throw new IllegalStateException("Cannot click on next from review step"); 247 } else if (cStep == FINISHED) { 248 throw new IllegalStateException("Cannot click on next from finished step"); 249 } 250 } 251 252 /** {@inheritDoc} */ 253 @Override 254 public void closeClicked(WizardStep cStep, QuickSetup qs) { 255 if (cStep == PROGRESS) { 256 if (isFinished() 257 || qs.displayConfirmation(INFO_CONFIRM_CLOSE_UNINSTALL_MSG.get(), 258 INFO_CONFIRM_CLOSE_UNINSTALL_TITLE.get())) 259 { 260 qs.quit(); 261 } 262 } 263 else if (cStep == FINISHED) 264 { 265 qs.quit(); 266 } else { 267 throw new IllegalStateException( 268 "Close only can be clicked on PROGRESS step"); 269 } 270 } 271 272 /** 273 * Update the UserData object according to the content of the review 274 * panel. 275 */ 276 private void updateUserUninstallDataForConfirmUninstallPanel(QuickSetup qs) 277 throws UserDataException { 278 UninstallUserData uud = getUninstallUserData(); 279 uud.setRemoveLibrariesAndTools( 280 (Boolean) qs.getFieldValue(FieldName.REMOVE_LIBRARIES_AND_TOOLS)); 281 uud.setRemoveDatabases( 282 (Boolean) qs.getFieldValue(FieldName.REMOVE_DATABASES)); 283 uud.setRemoveConfigurationAndSchema( 284 (Boolean) qs.getFieldValue( 285 FieldName.REMOVE_CONFIGURATION_AND_SCHEMA)); 286 uud.setRemoveBackups( 287 (Boolean) qs.getFieldValue(FieldName.REMOVE_BACKUPS)); 288 uud.setRemoveLDIFs( 289 (Boolean) qs.getFieldValue(FieldName.REMOVE_LDIFS)); 290 uud.setRemoveLogs( 291 (Boolean) qs.getFieldValue(FieldName.REMOVE_LOGS)); 292 // This is updated on the method handleTopologyCache 293 uud.setUpdateRemoteReplication(false); 294 295 Set<String> dbs = new HashSet<>(); 296 Set<?> s = (Set<?>) qs.getFieldValue(FieldName.EXTERNAL_DB_DIRECTORIES); 297 for (Object v : s) { 298 dbs.add((String) v); 299 } 300 301 Set<String> logs = new HashSet<>(); 302 s = (Set<?>) qs.getFieldValue(FieldName.EXTERNAL_LOG_FILES); 303 for (Object v : s) { 304 logs.add((String) v); 305 } 306 307 uud.setExternalDbsToRemove(dbs); 308 uud.setExternalLogsToRemove(logs); 309 310 if (dbs.isEmpty() && 311 logs.isEmpty() && 312 !uud.getRemoveLibrariesAndTools() && 313 !uud.getRemoveDatabases() && 314 !uud.getRemoveConfigurationAndSchema() && 315 !uud.getRemoveBackups() && 316 !uud.getRemoveLDIFs() && 317 !uud.getRemoveLogs()) { 318 throw new UserDataException(Step.CONFIRM_UNINSTALL, 319 INFO_NOTHING_SELECTED_TO_UNINSTALL.get()); 320 } 321 } 322 323 324 /** {@inheritDoc} */ 325 @Override 326 public void quitClicked(WizardStep step, QuickSetup qs) { 327 if (step == Step.PROGRESS) { 328 throw new IllegalStateException( 329 "Cannot click on quit from progress step"); 330 } 331 else if (step == Step.FINISHED) { 332 throw new IllegalStateException( 333 "Cannot click on quit from finished step"); 334 } 335 qs.quit(); 336 } 337 338 /** {@inheritDoc} */ 339 @Override 340 public LocalizableMessage getCloseButtonToolTip() { 341 return INFO_CLOSE_BUTTON_UNINSTALL_TOOLTIP.get(); 342 } 343 344 /** {@inheritDoc} */ 345 @Override 346 public LocalizableMessage getFinishButtonToolTip() { 347 return INFO_FINISH_BUTTON_UNINSTALL_TOOLTIP.get(); 348 } 349 350 /** {@inheritDoc} */ 351 @Override 352 public LocalizableMessage getFinishButtonLabel() { 353 return INFO_FINISH_BUTTON_UNINSTALL_LABEL.get(); 354 } 355 356 /** {@inheritDoc} */ 357 @Override 358 public void previousClicked(WizardStep cStep, QuickSetup qs) { 359 if (cStep == PROGRESS) { 360 throw new IllegalStateException( 361 "Cannot click on previous from progress step"); 362 } 363 else if (cStep == FINISHED) { 364 throw new IllegalStateException( 365 "Cannot click on previous from finished step"); 366 } 367 } 368 369 /** {@inheritDoc} */ 370 @Override 371 public void notifyListeners(Integer ratio, LocalizableMessage currentPhaseSummary, 372 final LocalizableMessage newLogDetail) 373 { 374 if (runStarted) 375 { 376 super.notifyListeners(ratio, currentPhaseSummary, newLogDetail); 377 } 378 else 379 { 380 SwingUtilities.invokeLater(new Runnable() 381 { 382 @Override 383 public void run() 384 { 385 if (startProgressDlg != null && newLogDetail != null) 386 { 387 startProgressDetails.append(newLogDetail); 388 startProgressDlg.setDetails(startProgressDetails.toMessage()); 389 } 390 } 391 }); 392 } 393 } 394 395 /** {@inheritDoc} */ 396 @Override 397 public boolean finishClicked(final WizardStep cStep, final QuickSetup qs) { 398 if (cStep == Step.CONFIRM_UNINSTALL) { 399 BackgroundTask<UninstallData> worker = 400 new BackgroundTask<UninstallData>() { 401 @Override 402 public UninstallData processBackgroundTask() throws UserDataException { 403 try { 404 updateUserUninstallDataForConfirmUninstallPanel(qs); 405 return new UninstallData(Installation.getLocal()); 406 } 407 catch (UserDataException uude) { 408 throw uude; 409 } catch (Throwable t) { 410 logger.warn(LocalizableMessage.raw("Error processing task: "+t, t)); 411 throw new UserDataException(Step.CONFIRM_UNINSTALL, 412 getThrowableMsg(INFO_BUG_MSG.get(), t)); 413 } 414 } 415 416 @Override 417 public void backgroundTaskCompleted(UninstallData returnValue, 418 Throwable throwable) { 419 qs.getDialog().workerFinished(); 420 if (throwable != null) { 421 if (throwable instanceof UserDataException) 422 { 423 qs.displayError(LocalizableMessage.raw(throwable.getLocalizedMessage()), 424 INFO_ERROR_TITLE.get()); 425 } 426 else 427 { 428 logger.warn(LocalizableMessage.raw("Error processing task: "+throwable, 429 throwable)); 430 qs.displayError(LocalizableMessage.raw(throwable.toString()), 431 INFO_ERROR_TITLE.get()); 432 } 433 } else { 434 conf = returnValue; 435 if (conf.isADS() && conf.isReplicationServer()) 436 { 437 if (conf.isServerRunning()) 438 { 439 if (qs.displayConfirmation( 440 INFO_CONFIRM_UNINSTALL_REPLICATION_SERVER_RUNNING_MSG.get(), 441 INFO_CONFIRM_UNINSTALL_REPLICATION_SERVER_RUNNING_TITLE 442 .get())) 443 { 444 askForAuthenticationAndLaunch(qs); 445 } 446 else if (qs.displayConfirmation( 447 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_MSG.get(), 448 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_TITLE.get())) 449 { 450 getUserData().setStopServer(true); 451 qs.launch(); 452 qs.setCurrentStep(getNextWizardStep(Step.CONFIRM_UNINSTALL)); 453 } else { 454 getUserData().setStopServer(false); 455 } 456 } 457 else if (qs.displayConfirmation( 458 INFO_CONFIRM_UNINSTALL_REPLICATION_SERVER_NOT_RUNNING_MSG.get(), 459 INFO_CONFIRM_UNINSTALL_REPLICATION_SERVER_NOT_RUNNING_TITLE.get())) 460 { 461 boolean startWorked = startServer(qs.getDialog().getFrame()); 462 if (startWorked) 463 { 464 askForAuthenticationAndLaunch(qs); 465 } 466 else 467 { 468 getUserData().setStopServer(false); 469 if (qs.displayConfirmation( 470 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_MSG.get(), 471 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_TITLE.get())) 472 { 473 qs.launch(); 474 qs.setCurrentStep( 475 getNextWizardStep(Step.CONFIRM_UNINSTALL)); 476 } 477 } 478 } 479 else 480 { 481 getUserData().setStopServer(false); 482 if (qs.displayConfirmation( 483 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_MSG.get(), 484 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_TITLE.get())) 485 { 486 qs.launch(); 487 qs.setCurrentStep( 488 getNextWizardStep(Step.CONFIRM_UNINSTALL)); 489 } 490 } 491 } 492 else if (!conf.isServerRunning()) 493 { 494 getUserData().setStopServer(false); 495 if (qs.displayConfirmation( 496 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_MSG.get(), 497 INFO_CONFIRM_UNINSTALL_SERVER_NOT_RUNNING_TITLE.get())) 498 { 499 qs.launch(); 500 qs.setCurrentStep(getNextWizardStep(Step.CONFIRM_UNINSTALL)); 501 } 502 } 503 else if (qs.displayConfirmation( 504 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_MSG.get(), 505 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_TITLE.get())) { 506 getUserData().setStopServer(true); 507 qs.launch(); 508 qs.setCurrentStep(getNextWizardStep(Step.CONFIRM_UNINSTALL)); 509 } else { 510 getUserData().setStopServer(false); 511 } 512 } 513 } 514 }; 515 qs.getDialog().workerStarted(); 516 worker.startBackgroundTask(); 517 } 518 // Uninstaller is responsible for updating user data and launching 519 return false; 520 } 521 522 /** {@inheritDoc} */ 523 @Override 524 public void updateUserData(WizardStep step, QuickSetup qs) { 525 // do nothing; 526 } 527 528 /** {@inheritDoc} */ 529 @Override 530 public void setWizardDialogState(QuickSetupDialog dlg, 531 UserData userData, 532 WizardStep step) { 533 if (step == Step.CONFIRM_UNINSTALL) { 534 dlg.setDefaultButton(ButtonName.FINISH); 535 dlg.setFocusOnButton(ButtonName.FINISH); 536 } else if (step == PROGRESS || step == FINISHED) { 537 dlg.setDefaultButton(ButtonName.CLOSE); 538 dlg.setFocusOnButton(ButtonName.CLOSE); 539 dlg.setButtonEnabled(ButtonName.CLOSE, false); 540 } 541 } 542 543 /** {@inheritDoc} */ 544 @Override 545 public UserData createUserData(Launcher launcher) throws UserDataException, 546 ApplicationException, ClientException 547 { 548 parser = (UninstallerArgumentParser) launcher.getArgumentParser(); 549 return cliHelper.createUserData(parser, launcher.getArguments()); 550 } 551 552 /** {@inheritDoc} */ 553 @Override 554 public String getInstallationPath() { 555 return getInstallPathFromClasspath(); 556 } 557 558 /** {@inheritDoc} */ 559 @Override 560 public String getInstancePath() { 561 return getInstancePathFromInstallPath(getInstallPathFromClasspath()); 562 } 563 564 /** 565 * Returns the ApplicationException that might occur during installation or 566 * <CODE>null</CODE> if no exception occurred. 567 * 568 * @return the ApplicationException that might occur during installation or 569 * <CODE>null</CODE> if no exception occurred. 570 */ 571 @Override 572 public ApplicationException getRunError() { 573 return ue; 574 } 575 576 /** {@inheritDoc} */ 577 @Override 578 public ReturnCode getReturnCode() { 579 return null; 580 } 581 582 /** 583 * Initialize the different map used in this class. 584 */ 585 private void initMaps() { 586 hmSummary.put(UninstallProgressStep.NOT_STARTED, 587 getFormattedSummary(INFO_SUMMARY_UNINSTALL_NOT_STARTED.get())); 588 hmSummary.put(UninstallProgressStep.STOPPING_SERVER, 589 getFormattedSummary(INFO_SUMMARY_STOPPING.get())); 590 hmSummary.put(UninstallProgressStep.UNCONFIGURING_REPLICATION, 591 getFormattedSummary(INFO_SUMMARY_UNCONFIGURING_REPLICATION.get())); 592 hmSummary.put(UninstallProgressStep.DISABLING_WINDOWS_SERVICE, 593 getFormattedSummary(INFO_SUMMARY_DISABLING_WINDOWS_SERVICE.get())); 594 hmSummary.put(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES, 595 getFormattedSummary(INFO_SUMMARY_DELETING_EXTERNAL_DB_FILES.get())); 596 hmSummary.put(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES, 597 getFormattedSummary( 598 INFO_SUMMARY_DELETING_EXTERNAL_LOG_FILES.get())); 599 hmSummary.put(UninstallProgressStep.REMOVING_EXTERNAL_REFERENCES, 600 getFormattedSummary( 601 INFO_SUMMARY_DELETING_EXTERNAL_REFERENCES.get())); 602 hmSummary.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, 603 getFormattedSummary( 604 INFO_SUMMARY_DELETING_INSTALLATION_FILES.get())); 605 606 LocalizableMessage successMsg; 607 Installation installation = getInstallation(); 608 String libPath = getPath(installation.getLibrariesDirectory()); 609 String resourcesPath = getPath(installation.getResourcesDirectory()); 610 String classesPath = getPath(installation.getClassesDirectory()); 611 boolean resourcesDefined = 612 Utils.directoryExistsAndIsNotEmpty(resourcesPath); 613 boolean classesDefined = 614 Utils.directoryExistsAndIsNotEmpty(classesPath); 615 ArrayList<String> paths = new ArrayList<>(); 616 paths.add(libPath); 617 if (resourcesDefined) 618 { 619 paths.add(resourcesPath); 620 } 621 if (classesDefined) 622 { 623 paths.add(classesPath); 624 } 625 if (isCli()) { 626 if (getUninstallUserData().getRemoveLibrariesAndTools()) { 627 String arg; 628 if (isWindows()) { 629 arg = installation.getUninstallBatFile() + getLineBreak().toString() + 630 getTab() + joinAsString(getLineBreak().toString(), paths); 631 } else { 632 arg = joinAsString(getLineBreak().toString(), paths); 633 } 634 successMsg = INFO_SUMMARY_UNINSTALL_FINISHED_SUCCESSFULLY_REMOVE_JARFILES_CLI.get(arg); 635 } else { 636 successMsg = INFO_SUMMARY_UNINSTALL_FINISHED_SUCCESSFULLY_CLI.get(); 637 } 638 } else if (getUninstallUserData().getRemoveLibrariesAndTools()) { 639 String formattedPath = 640 addWordBreaks(joinAsString(getLineBreak().toString(), paths), 60, 5); 641 successMsg = INFO_SUMMARY_UNINSTALL_FINISHED_SUCCESSFULLY_REMOVE_JARFILES.get(formattedPath); 642 } else { 643 successMsg = INFO_SUMMARY_UNINSTALL_FINISHED_SUCCESSFULLY.get(); 644 } 645 hmSummary.put(UninstallProgressStep.FINISHED_SUCCESSFULLY, 646 getFormattedSuccess(successMsg)); 647 648 LocalizableMessage nonCriticalMsg; 649 if (!isCli()) 650 { 651 nonCriticalMsg = 652 INFO_SUMMARY_UNINSTALL_FINISHED_WITH_ERROR_ON_REMOTE.get(); 653 } 654 else 655 { 656 nonCriticalMsg = 657 INFO_SUMMARY_UNINSTALL_FINISHED_WITH_ERROR_ON_REMOTE_CLI.get(); 658 } 659 hmSummary.put(UninstallProgressStep.FINISHED_WITH_ERROR_ON_REMOTE, 660 getFormattedWarning(nonCriticalMsg)); 661 if (!isCli()) 662 { 663 nonCriticalMsg = 664 INFO_SUMMARY_UNINSTALL_FINISHED_WITH_ERROR_DELETING.get(); 665 } 666 else 667 { 668 nonCriticalMsg = 669 INFO_SUMMARY_UNINSTALL_FINISHED_WITH_ERROR_DELETING_CLI.get(); 670 } 671 hmSummary.put(UninstallProgressStep.FINISHED_WITH_ERROR_DELETING, 672 getFormattedWarning(nonCriticalMsg)); 673 hmSummary.put(UninstallProgressStep.FINISHED_WITH_ERROR, 674 getFormattedError( 675 INFO_SUMMARY_UNINSTALL_FINISHED_WITH_ERROR.get())); 676 677 /* 678 * hmTime contains the relative time that takes for each task to be 679 * accomplished. For instance if stopping takes twice the time of 680 * deleting files, the value for downloading will be the double of the 681 * value for extracting. 682 */ 683 Map<UninstallProgressStep, Integer> hmTime = new HashMap<>(); 684 hmTime.put(UninstallProgressStep.UNCONFIGURING_REPLICATION, 5); 685 hmTime.put(UninstallProgressStep.STOPPING_SERVER, 15); 686 hmTime.put(UninstallProgressStep.DISABLING_WINDOWS_SERVICE, 5); 687 hmTime.put(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES, 30); 688 hmTime.put(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES, 5); 689 hmTime.put(UninstallProgressStep.REMOVING_EXTERNAL_REFERENCES, 5); 690 hmTime.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, 10); 691 692 int totalTime = 0; 693 List<UninstallProgressStep> steps = new ArrayList<>(); 694 if (getUninstallUserData().getUpdateRemoteReplication()) { 695 totalTime += hmTime.get(UninstallProgressStep.UNCONFIGURING_REPLICATION); 696 steps.add(UninstallProgressStep.UNCONFIGURING_REPLICATION); 697 } 698 if (getUserData().getStopServer()) { 699 totalTime += hmTime.get(UninstallProgressStep.STOPPING_SERVER); 700 steps.add(UninstallProgressStep.STOPPING_SERVER); 701 } 702 if (isWindowsServiceEnabled()) { 703 totalTime += hmTime.get(UninstallProgressStep.DISABLING_WINDOWS_SERVICE); 704 steps.add(UninstallProgressStep.DISABLING_WINDOWS_SERVICE); 705 } 706 totalTime += hmTime.get(UninstallProgressStep.DELETING_INSTALLATION_FILES); 707 steps.add(UninstallProgressStep.DELETING_INSTALLATION_FILES); 708 709 if (getUninstallUserData().getExternalDbsToRemove().size() > 0) { 710 totalTime += hmTime.get( 711 UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES); 712 steps.add(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES); 713 } 714 715 if (getUninstallUserData().getExternalLogsToRemove().size() > 0) { 716 totalTime += hmTime.get( 717 UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES); 718 steps.add(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES); 719 } 720 721 int cumulatedTime = 0; 722 for (UninstallProgressStep s : steps) { 723 Integer statusTime = hmTime.get(s); 724 hmRatio.put(s, (100 * cumulatedTime) / totalTime); 725 if (statusTime != null) { 726 cumulatedTime += statusTime; 727 } 728 } 729 730 hmRatio.put(UninstallProgressStep.FINISHED_SUCCESSFULLY, 100); 731 hmRatio.put(UninstallProgressStep.FINISHED_WITH_ERROR_ON_REMOTE, 100); 732 hmRatio.put(UninstallProgressStep.FINISHED_WITH_ERROR, 100); 733 } 734 735 /** 736 * Actually performs the uninstall in this thread. The thread is blocked. 737 */ 738 @Override 739 public void run() { 740 runStarted = true; 741 logger.info(LocalizableMessage.raw("run of the Uninstaller started")); 742 743 initMaps(); 744 PrintStream origErr = System.err; 745 PrintStream origOut = System.out; 746 try { 747 PrintStream err = new ErrorPrintStream(); 748 PrintStream out = new OutputPrintStream(); 749 if (!isCli()) { 750 System.setErr(err); 751 System.setOut(out); 752 } 753 754 boolean displaySeparator = false; 755 756 logger.info(LocalizableMessage.raw("Update remote replication? "+ 757 getUninstallUserData().getUpdateRemoteReplication())); 758 if (getUninstallUserData().getUpdateRemoteReplication()) 759 { 760 status = UninstallProgressStep.UNCONFIGURING_REPLICATION; 761 removeRemoteServerReferences(); 762 displaySeparator = true; 763 } 764 765 logger.info(LocalizableMessage.raw("Stop server? "+getUserData().getStopServer())); 766 if (getUserData().getStopServer()) { 767 status = UninstallProgressStep.STOPPING_SERVER; 768 if (displaySeparator && isVerbose()) { 769 notifyListeners(getTaskSeparator()); 770 } 771 if (!isVerbose()) 772 { 773 notifyListeners(getFormattedWithPoints( 774 INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 775 } 776 // In case of uninstall, the server stop has to run locally. 777 // In order to bypass the tools.properties mechanism, if any, 778 // we systematically add the --noPropertiesFile flag 779 // when we run the stop-ds command. This is done 780 // by setting the parameter "noPropertiesFile" to 'true' 781 // in the following call. 782 new ServerController(this).stopServer(!isVerbose(),true); 783 if (!isVerbose()) 784 { 785 notifyListeners(getFormattedDoneWithLineBreak()); 786 } 787 displaySeparator = true; 788 } 789 logger.info(LocalizableMessage.raw("Is Windows Service Enabled? "+ 790 isWindowsServiceEnabled())); 791 if (isWindowsServiceEnabled()) { 792 status = UninstallProgressStep.DISABLING_WINDOWS_SERVICE; 793 if (displaySeparator && isVerbose()) { 794 notifyListeners(getTaskSeparator()); 795 } 796 disableWindowsService(); 797 displaySeparator = true; 798 } 799 800 Set<String> dbsToDelete = getUninstallUserData().getExternalDbsToRemove(); 801 if (!dbsToDelete.isEmpty()) { 802 status = UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES; 803 if (displaySeparator && isVerbose()) { 804 notifyListeners(getTaskSeparator()); 805 } 806 807 try 808 { 809 deleteExternalDatabaseFiles(dbsToDelete); 810 displaySeparator = true; 811 } 812 catch (ApplicationException ae) 813 { 814 if (ae.getType() == ReturnCode.FILE_SYSTEM_ACCESS_ERROR) 815 { 816 errorDeletingOccurred = true; 817 LocalizableMessage msg = getFormattedWarning(ae.getMessageObject()); 818 notifyListeners(msg); 819 } 820 else 821 { 822 throw ae; 823 } 824 } 825 } 826 827 Set<String> logsToDelete = getUninstallUserData().getExternalLogsToRemove(); 828 if (!logsToDelete.isEmpty()) { 829 status = UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES; 830 831 if (displaySeparator && isVerbose()) { 832 notifyListeners(getTaskSeparator()); 833 } 834 835 try 836 { 837 deleteExternalLogFiles(logsToDelete); 838 displaySeparator = true; 839 } 840 catch (ApplicationException ae) 841 { 842 if (ae.getType() == ReturnCode.FILE_SYSTEM_ACCESS_ERROR) 843 { 844 errorDeletingOccurred = true; 845 LocalizableMessage msg = getFormattedWarning(ae.getMessageObject()); 846 notifyListeners(msg); 847 } 848 else 849 { 850 throw ae; 851 } 852 } 853 } 854 855 UninstallUserData userData = getUninstallUserData(); 856 boolean somethingToDelete = userData.getRemoveBackups() || 857 userData.getRemoveConfigurationAndSchema() || 858 userData.getRemoveDatabases() || 859 userData.getRemoveLDIFs() || 860 userData.getRemoveLibrariesAndTools() || 861 userData.getRemoveLogs(); 862 if (displaySeparator && somethingToDelete && isVerbose()) { 863 notifyListeners(getTaskSeparator()); 864 } 865 866 if (somethingToDelete) { 867 status = UninstallProgressStep.DELETING_INSTALLATION_FILES; 868 try 869 { 870 deleteInstallationFiles(getRatio(status), 871 getRatio(UninstallProgressStep.FINISHED_SUCCESSFULLY)); 872 } 873 catch (ApplicationException ae) 874 { 875 if (ae.getType() == ReturnCode.FILE_SYSTEM_ACCESS_ERROR) 876 { 877 errorDeletingOccurred = true; 878 LocalizableMessage msg = getFormattedWarning(ae.getMessageObject()); 879 notifyListeners(msg); 880 } 881 else 882 { 883 throw ae; 884 } 885 } 886 } 887 if (errorOnRemoteOccurred) 888 { 889 status = UninstallProgressStep.FINISHED_WITH_ERROR_ON_REMOTE; 890 } 891 else if (errorDeletingOccurred) 892 { 893 status = UninstallProgressStep.FINISHED_WITH_ERROR_DELETING; 894 } 895 else 896 { 897 status = UninstallProgressStep.FINISHED_SUCCESSFULLY; 898 } 899 if (isCli()) { 900 notifyListeners(new LocalizableMessageBuilder(getLineBreak()) 901 .append(getLineBreak()).append(getSummary(status)) 902 .toMessage()); 903 } else { 904 notifyListeners(null); 905 } 906 907 } catch (ApplicationException ex) { 908 logger.error(LocalizableMessage.raw("Error: "+ex, ex)); 909 ue = ex; 910 status = UninstallProgressStep.FINISHED_WITH_ERROR; 911 LocalizableMessage msg = getFormattedError(ex, true); 912 notifyListeners(msg); 913 } 914 catch (Throwable t) { 915 logger.error(LocalizableMessage.raw("Error: "+t, t)); 916 ue = new ApplicationException( 917 ReturnCode.BUG, 918 getThrowableMsg(INFO_BUG_MSG.get(), t), t); 919 status = UninstallProgressStep.FINISHED_WITH_ERROR; 920 LocalizableMessage msg = getFormattedError(ue, true); 921 notifyListeners(msg); 922 } 923 if (!isCli()) { 924 System.setErr(origErr); 925 System.setOut(origOut); 926 } 927 } 928 929 /** {@inheritDoc} */ 930 @Override 931 public ProgressStep getCurrentProgressStep() { 932 return status; 933 } 934 935 /** 936 * Returns an integer that specifies which percentage of the whole 937 * installation has been completed. 938 * 939 * @param step the UninstallProgressStep for which we want to get the ratio. 940 * @return an integer that specifies which percentage of the whole 941 * uninstallation has been completed. 942 */ 943 @Override 944 public Integer getRatio(ProgressStep step) { 945 return hmRatio.get(step); 946 } 947 948 /** 949 * Returns an formatted representation of the summary for the specified 950 * UninstallProgressStep. 951 * 952 * @param step the UninstallProgressStep for which we want to get the summary. 953 * @return an formatted representation of the summary for the specified 954 * UninstallProgressStep. 955 */ 956 @Override 957 public LocalizableMessage getSummary(ProgressStep step) { 958 return hmSummary.get(step); 959 } 960 961 /** {@inheritDoc} */ 962 @Override 963 public boolean isFinished() { 964 return getCurrentProgressStep() == 965 UninstallProgressStep.FINISHED_SUCCESSFULLY 966 || getCurrentProgressStep() == 967 UninstallProgressStep.FINISHED_WITH_ERROR 968 || getCurrentProgressStep() == 969 UninstallProgressStep.FINISHED_WITH_ERROR_ON_REMOTE 970 || getCurrentProgressStep() == 971 UninstallProgressStep.FINISHED_WITH_ERROR_DELETING; 972 } 973 974 /** {@inheritDoc} */ 975 @Override 976 public boolean isCancellable() { 977 return false; 978 } 979 980 /** {@inheritDoc} */ 981 @Override 982 public void cancel() { 983 // do nothing; not cancellable 984 } 985 986 /** {@inheritDoc} */ 987 @Override 988 public void windowClosing(QuickSetupDialog dlg, WindowEvent evt) { 989 if (dlg.getDisplayedStep() == PROGRESS || 990 dlg.getDisplayedStep() == FINISHED) { 991 // Simulate a close button event 992 dlg.notifyButtonEvent(ButtonName.CLOSE); 993 } else { 994 // Simulate a quit button event 995 dlg.notifyButtonEvent(ButtonName.QUIT); 996 } 997 } 998 999 /** {@inheritDoc} */ 1000 @Override 1001 public ButtonName getInitialFocusButtonName() { 1002 return ButtonName.FINISH; 1003 } 1004 1005 /** {@inheritDoc} */ 1006 @Override 1007 public Set<? extends WizardStep> getWizardSteps() { 1008 Set<WizardStep> setSteps = new HashSet<>(); 1009 setSteps.add(Step.CONFIRM_UNINSTALL); 1010 setSteps.add(Step.PROGRESS); 1011 setSteps.add(Step.FINISHED); 1012 return Collections.unmodifiableSet(setSteps); 1013 } 1014 1015 /** {@inheritDoc} */ 1016 @Override 1017 public QuickSetupStepPanel createWizardStepPanel(WizardStep step) { 1018 if (step == Step.CONFIRM_UNINSTALL) { 1019 return new ConfirmUninstallPanel(this, installStatus); 1020 } else if (step == Step.PROGRESS) { 1021 return new ProgressPanel(this); 1022 } else if (step == Step.FINISHED) { 1023 return new FinishedPanel(this); 1024 } 1025 return null; 1026 } 1027 1028 /** 1029 * Deletes the external database files specified in the provided Set. 1030 * 1031 * @param dbFiles the database directories to be deleted. 1032 * @throws ApplicationException if something goes wrong. 1033 */ 1034 private void deleteExternalDatabaseFiles(Set<String> dbFiles) 1035 throws ApplicationException { 1036 if (isVerbose()) 1037 { 1038 notifyListeners(getFormattedProgressWithLineBreak( 1039 INFO_PROGRESS_DELETING_EXTERNAL_DB_FILES.get())); 1040 } 1041 else 1042 { 1043 notifyListeners(getFormattedWithPoints( 1044 INFO_PROGRESS_DELETING_EXTERNAL_DB_FILES_NON_VERBOSE.get())); 1045 } 1046 for (String path : dbFiles) { 1047 deleteRecursively(new File(path)); 1048 } 1049 if (!isVerbose()) 1050 { 1051 notifyListeners(getFormattedDoneWithLineBreak()); 1052 } 1053 } 1054 1055 /** 1056 * Deletes the external database files specified in the provided Set. 1057 * 1058 * @param logFiles the log files to be deleted. 1059 * @throws ApplicationException if something goes wrong. 1060 */ 1061 private void deleteExternalLogFiles(Set<String> logFiles) 1062 throws ApplicationException { 1063 if (isVerbose()) 1064 { 1065 notifyListeners(getFormattedProgressWithLineBreak( 1066 INFO_PROGRESS_DELETING_EXTERNAL_LOG_FILES.get())); 1067 } 1068 else 1069 { 1070 notifyListeners(getFormattedWithPoints( 1071 INFO_PROGRESS_DELETING_EXTERNAL_LOG_FILES_NON_VERBOSE.get())); 1072 } 1073 for (String path : logFiles) { 1074 deleteRecursively(new File(path)); 1075 } 1076 if (!isVerbose()) 1077 { 1078 notifyListeners(getFormattedDoneWithLineBreak()); 1079 } 1080 } 1081 1082 /** 1083 * Deletes the files under the installation path. 1084 * 1085 * @throws ApplicationException if something goes wrong. 1086 */ 1087 private void deleteInstallationFiles(int minRatio, int maxRatio) 1088 throws ApplicationException { 1089 if (isVerbose()) 1090 { 1091 notifyListeners(getFormattedProgressWithLineBreak( 1092 INFO_PROGRESS_DELETING_INSTALLATION_FILES.get())); 1093 } 1094 else 1095 { 1096 notifyListeners(getFormattedWithPoints( 1097 INFO_PROGRESS_DELETING_INSTALLATION_FILES_NON_VERBOSE.get())); 1098 } 1099 1100 String installPath = getInstallPathFromClasspath(); 1101 File installFile = new File(installPath); 1102 try 1103 { 1104 installPath = installFile.getCanonicalPath(); 1105 } 1106 catch(Exception e) 1107 { 1108 installPath = getInstallPathFromClasspath(); 1109 } 1110 1111 String instancePath = 1112 Utils.getInstancePathFromInstallPath(installFile.getAbsolutePath()); 1113 File instanceFile = new File(instancePath); 1114 try 1115 { 1116 instancePath = instanceFile.getCanonicalPath(); 1117 } catch (Exception e) 1118 { 1119 instancePath = 1120 Utils.getInstancePathFromInstallPath(installFile.getAbsolutePath()); 1121 } 1122 1123 InstallationFilesToDeleteFilter filter = 1124 new InstallationFilesToDeleteFilter(); 1125 1126 File[] installFiles = installFile.listFiles(); 1127 File[] instanceFiles = null ; 1128 if (! installPath.equals(instancePath)) 1129 { 1130 instanceFiles = new File(instancePath).listFiles(); 1131 } 1132 1133 File[] rootFiles = null; 1134 1135 if (installFiles == null) 1136 { 1137 rootFiles = new File(instancePath).listFiles(); 1138 } 1139 else 1140 if (instanceFiles == null) 1141 { 1142 rootFiles = installFiles; 1143 } 1144 else 1145 { 1146 // both installFiles and instanceFiles are not null 1147 rootFiles = new File[installFiles.length + instanceFiles.length]; 1148 System.arraycopy(installFiles, 0, rootFiles, 0, installFiles.length); 1149 System.arraycopy(instanceFiles, 0, rootFiles, installFiles.length, 1150 instanceFiles.length); 1151 } 1152 1153 if (rootFiles != null) { 1154 /* The following is done to have a moving progress bar when we delete 1155 * the installation files. 1156 */ 1157 int totalRatio = 0; 1158 ArrayList<Integer> cumulatedRatio = new ArrayList<>(); 1159 for (File f : rootFiles) { 1160 if (filter.accept(f)) { 1161 Installation installation = getInstallation(); 1162 int relativeRatio; 1163 if (equalsOrDescendant(f, installation.getLibrariesDirectory())) { 1164 relativeRatio = 10; 1165 } else 1166 if (equalsOrDescendant(f, installation.getBinariesDirectory())) { 1167 relativeRatio = 5; 1168 } else 1169 if (equalsOrDescendant(f, installation.getConfigurationDirectory())) { 1170 relativeRatio = 5; 1171 } else 1172 if (equalsOrDescendant(f, installation.getBackupDirectory())) { 1173 relativeRatio = 20; 1174 } else 1175 if (equalsOrDescendant(f, installation.getLdifDirectory())) { 1176 relativeRatio = 20; 1177 } else if (equalsOrDescendant(f, installation.getDatabasesDirectory())) { 1178 relativeRatio = 50; 1179 } else 1180 if (equalsOrDescendant(f, installation.getLogsDirectory())) { 1181 relativeRatio = 30; 1182 } else { 1183 relativeRatio = 2; 1184 } 1185 cumulatedRatio.add(totalRatio); 1186 totalRatio += relativeRatio; 1187 } else { 1188 cumulatedRatio.add(totalRatio); 1189 } 1190 } 1191 Iterator<Integer> it = cumulatedRatio.iterator(); 1192 for (File rootFile : rootFiles) 1193 { 1194 int beforeRatio = minRatio + 1195 (it.next() * (maxRatio - minRatio)) / totalRatio; 1196 hmRatio.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, beforeRatio); 1197 deleteRecursively(rootFile, filter); 1198 } 1199 hmRatio.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, maxRatio); 1200 } 1201 if (!isVerbose()) 1202 { 1203 notifyListeners(getFormattedDone()); 1204 } 1205 } 1206 1207 /** 1208 * Deletes everything below the specified file. 1209 * 1210 * @param file the path to be deleted. 1211 * @throws ApplicationException if something goes wrong. 1212 */ 1213 private void deleteRecursively(File file) throws ApplicationException { 1214 deleteRecursively(file, null); 1215 } 1216 1217 /** 1218 * Deletes everything below the specified file. 1219 * 1220 * @param file the path to be deleted. 1221 * @param filter the filter of the files to know if the file can be deleted 1222 * directly or not. 1223 * @throws ApplicationException if something goes wrong. 1224 */ 1225 private void deleteRecursively(File file, FileFilter filter) 1226 throws ApplicationException { 1227 File cfile ; 1228 try 1229 { 1230 cfile = file.getCanonicalFile(); 1231 } 1232 catch (Exception e) 1233 { 1234 cfile = file ; 1235 } 1236 if (cfile.exists()) { 1237 if (cfile.isFile()) { 1238 if (filter != null) { 1239 if (filter.accept(cfile)) { 1240 delete(cfile); 1241 } 1242 } else { 1243 delete(cfile); 1244 } 1245 } else { 1246 File[] children = cfile.listFiles(); 1247 if (children != null) { 1248 for (File element : children) 1249 { 1250 deleteRecursively(element, filter); 1251 } 1252 } 1253 if (filter != null) { 1254 if (filter.accept(cfile)) { 1255 delete(cfile); 1256 } 1257 } else { 1258 delete(cfile); 1259 } 1260 } 1261 } else { 1262 // Just tell that the file/directory does not exist. 1263 notifyListeners(getFormattedWarning( 1264 INFO_PROGRESS_DELETING_FILE_DOES_NOT_EXIST.get(cfile))); 1265 } 1266 } 1267 1268 /** 1269 * Deletes the specified file. 1270 * 1271 * @param file the file to be deleted. 1272 * @throws ApplicationException if something goes wrong. 1273 */ 1274 private void delete(File file) throws ApplicationException { 1275 boolean isFile = file.isFile(); 1276 1277 if (isVerbose()) 1278 { 1279 if (isFile) { 1280 notifyListeners(getFormattedWithPoints( 1281 INFO_PROGRESS_DELETING_FILE.get(file.getAbsolutePath()))); 1282 } else { 1283 notifyListeners(getFormattedWithPoints( 1284 INFO_PROGRESS_DELETING_DIRECTORY.get(file.getAbsolutePath()))); 1285 } 1286 } 1287 1288 boolean delete = false; 1289 /* 1290 * Sometimes the server keeps some locks on the files. 1291 * This is dependent on the OS so there is no much we can do here. 1292 */ 1293 int nTries = 5; 1294 for (int i = 0; i < nTries && !delete; i++) { 1295 delete = file.delete(); 1296 if (!delete) { 1297 try { 1298 Thread.sleep(1000); 1299 } 1300 catch (Exception ex) { 1301 } 1302 } 1303 } 1304 1305 if (!delete) { 1306 LocalizableMessage errMsg; 1307 if (isFile) { 1308 errMsg = INFO_ERROR_DELETING_FILE.get(file.getAbsolutePath()); 1309 } else { 1310 errMsg = INFO_ERROR_DELETING_DIRECTORY.get(file.getAbsolutePath()); 1311 } 1312 throw new ApplicationException( 1313 ReturnCode.FILE_SYSTEM_ACCESS_ERROR, 1314 errMsg, null); 1315 } 1316 1317 if (isVerbose()) 1318 { 1319 notifyListeners(getFormattedDoneWithLineBreak()); 1320 } 1321 } 1322 1323 private boolean equalsOrDescendant(File file, File directory) { 1324 return file.equals(directory) || isDescendant(file, directory); 1325 } 1326 1327 /** 1328 * This class is used to get the files that are not binaries. This is 1329 * required to know which are the files that can be deleted directly and which 1330 * not. 1331 */ 1332 private class InstallationFilesToDeleteFilter implements FileFilter { 1333 private Installation installation = getInstallation(); 1334 private File quicksetupFile = installation.getQuicksetupJarFile(); 1335 private File openDSFile = installation.getOpenDSJarFile(); 1336 private File librariesFile = installation.getLibrariesDirectory(); 1337 private File resourcesDir = installation.getResourcesDirectory(); 1338 private File classesDir = installation.getClassesDirectory(); 1339 private File uninstallBatFile = installation.getUninstallBatFile(); 1340 1341 private boolean canDeleteResourcesDir = 1342 !Utils.directoryExistsAndIsNotEmpty(resourcesDir.getAbsolutePath()); 1343 private boolean canDeleteClassesDir = 1344 !Utils.directoryExistsAndIsNotEmpty(classesDir.getAbsolutePath()); 1345 1346 1347 private File installationPath = installation.getRootDirectory(); 1348 1349 /** {@inheritDoc} */ 1350 @Override 1351 public boolean accept(File file) { 1352 UninstallUserData userData = getUninstallUserData(); 1353 boolean[] uData = { 1354 userData.getRemoveLibrariesAndTools(), 1355 userData.getRemoveLibrariesAndTools(), 1356 userData.getRemoveLibrariesAndTools(), 1357 userData.getRemoveLibrariesAndTools(), 1358 userData.getRemoveDatabases(), 1359 userData.getRemoveLogs(), 1360 userData.getRemoveConfigurationAndSchema(), 1361 userData.getRemoveBackups(), 1362 userData.getRemoveLDIFs() 1363 }; 1364 1365 Installation installation = getInstallation(); 1366 File[] parentFiles ; 1367 try { 1368 File[] tmp = { 1369 installation.getLibrariesDirectory().getCanonicalFile(), 1370 installation.getBinariesDirectory().getCanonicalFile(), 1371 installation.getResourcesDirectory().getCanonicalFile(), 1372 installation.getClassesDirectory().getCanonicalFile(), 1373 installation.getDatabasesDirectory().getCanonicalFile(), 1374 installation.getLogsDirectory().getCanonicalFile(), 1375 installation.getConfigurationDirectory().getCanonicalFile(), 1376 installation.getBackupDirectory().getCanonicalFile(), 1377 installation.getLdifDirectory().getCanonicalFile() 1378 }; 1379 parentFiles = tmp ; 1380 } 1381 catch (Exception e) 1382 { 1383 return true; 1384 } 1385 1386 boolean accept = 1387 !installationPath.equals(file) 1388 && !equalsOrDescendant(file, librariesFile) 1389 && (canDeleteClassesDir || !equalsOrDescendant(file, classesDir)) 1390 && (canDeleteResourcesDir || !equalsOrDescendant(file, resourcesDir)) 1391 && !quicksetupFile.equals(file) 1392 && !openDSFile.equals(file); 1393 1394 if (accept && isWindows() && isCli()) { 1395 accept = !uninstallBatFile.equals(file); 1396 } 1397 1398 for (int i = 0; i < uData.length && accept; i++) { 1399 File parent = parentFiles[i]; 1400 accept &= uData[i] || 1401 !equalsOrDescendant(file, parent); 1402 } 1403 1404 logger.info(LocalizableMessage.raw("accept for :"+file+" is: "+accept)); 1405 return accept; 1406 } 1407 } 1408 1409 private boolean isWindowsServiceEnabled() { 1410 if (isWindowsServiceEnabled == null) { 1411 isWindowsServiceEnabled = serviceState() == SERVICE_STATE_ENABLED; 1412 } 1413 return isWindowsServiceEnabled.booleanValue(); 1414 } 1415 1416 /** {@inheritDoc} */ 1417 @Override 1418 public ApplicationTrustManager getTrustManager() 1419 { 1420 return getUninstallUserData().getTrustManager(); 1421 } 1422 1423 /** 1424 * This methods disables this server as a Windows service. 1425 * 1426 * @throws ApplicationException if something goes wrong. 1427 */ 1428 protected void disableWindowsService() throws ApplicationException { 1429 notifyListeners(getFormattedWithPoints( 1430 INFO_PROGRESS_DISABLING_WINDOWS_SERVICE.get())); 1431 int code = disableService(System.out, System.err); 1432 1433 LocalizableMessage errorMessage = INFO_ERROR_DISABLING_WINDOWS_SERVICE.get( 1434 getInstallationPath()); 1435 1436 switch (code) { 1437 case SERVICE_DISABLE_SUCCESS: 1438 break; 1439 case SERVICE_ALREADY_DISABLED: 1440 break; 1441 default: 1442 throw new ApplicationException(ReturnCode.WINDOWS_SERVICE_ERROR, errorMessage, null); 1443 } 1444 notifyListeners(getLineBreak()); 1445 } 1446 1447 private UninstallUserData getUninstallUserData() { 1448 return (UninstallUserData) getUserData(); 1449 } 1450 1451 /** 1452 * Tries to start the server and launches a progress dialog. This method 1453 * assumes that is being called from the event thread. 1454 * @return <CODE>true</CODE> if the server could be started and <CODE> 1455 * false</CODE> otherwise. 1456 * @param frame the JFrame to be used as parent of the progress dialog. 1457 */ 1458 private boolean startServer(JFrame frame) 1459 { 1460 startProgressDetails = new LocalizableMessageBuilder(); 1461 startProgressDlg = new ProgressDialog(frame); 1462 startProgressDlg.setSummary( 1463 getFormattedSummary(INFO_SUMMARY_STARTING.get())); 1464 startProgressDlg.setDetails(LocalizableMessage.EMPTY); 1465 startProgressDlg.setCloseButtonEnabled(false); 1466 final Boolean[] returnValue = new Boolean[] {Boolean.FALSE}; 1467 Thread t = new Thread(new Runnable() 1468 { 1469 @Override 1470 public void run() 1471 { 1472 try 1473 { 1474 new ServerController(Uninstaller.this).startServer(); 1475 final boolean isServerRunning = 1476 Installation.getLocal().getStatus().isServerRunning(); 1477 returnValue[0] = isServerRunning; 1478 SwingUtilities.invokeLater(new Runnable() 1479 { 1480 @Override 1481 public void run() 1482 { 1483 if (isServerRunning) 1484 { 1485 startProgressDlg.setSummary(getFormattedSuccess( 1486 INFO_SUMMARY_START_SUCCESS.get())); 1487 } 1488 else 1489 { 1490 startProgressDlg.setSummary(getFormattedError( 1491 INFO_SUMMARY_START_ERROR.get())); 1492 } 1493 startProgressDlg.setCloseButtonEnabled(true); 1494 } 1495 }); 1496 } 1497 catch (Throwable t) 1498 { 1499 LocalizableMessage msg = getFormattedError(t, true); 1500 notifyListeners(msg); 1501 } 1502 } 1503 }); 1504 t.start(); 1505 startProgressDlg.pack(); 1506 Utilities.centerOnComponent(startProgressDlg, frame); 1507 startProgressDlg.setModal(true); 1508 startProgressDlg.setVisible(true); 1509 startProgressDlg = null; 1510 return returnValue[0]; 1511 } 1512 1513 /** 1514 * This method displays a login dialog message, asking the user to provide 1515 * authentication to retrieve information from the ADS and update the 1516 * remote servers. Then it tries to connect to the remote servers. 1517 * 1518 * @param qs the QuickSetup object. 1519 */ 1520 private void askForAuthenticationAndLaunch(final QuickSetup qs) 1521 { 1522 if (loginDialog == null) 1523 { 1524 loginDialog = new LoginDialog(qs.getDialog().getFrame(), 1525 getTrustManager(), getConnectTimeout()); 1526 loginDialog.pack(); 1527 } 1528 Utilities.centerOnComponent(loginDialog, qs.getDialog().getFrame()); 1529 loginDialog.setModal(true); 1530 loginDialog.setVisible(true); 1531 if (!loginDialog.isCanceled()) 1532 { 1533 getUninstallUserData().setAdminUID(loginDialog.getAdministratorUid()); 1534 getUninstallUserData().setAdminPwd(loginDialog.getAdministratorPwd()); 1535 final InitialLdapContext ctx = loginDialog.getContext(); 1536 try 1537 { 1538 getUninstallUserData().setLocalServerUrl( 1539 (String)ctx.getEnvironment().get(Context.PROVIDER_URL)); 1540 } 1541 catch (NamingException ne) 1542 { 1543 logger.warn(LocalizableMessage.raw("Could not find local server: "+ne, ne)); 1544 getUninstallUserData().setLocalServerUrl("ldap://localhost:389"); 1545 } 1546 getUninstallUserData().setReplicationServer( 1547 loginDialog.getHostName() + ":" + 1548 conf.getReplicationServerPort()); 1549 getUninstallUserData().setReferencedHostName(loginDialog.getHostName()); 1550 1551 BackgroundTask<TopologyCache> worker = new BackgroundTask<TopologyCache>() 1552 { 1553 @Override 1554 public TopologyCache processBackgroundTask() throws Throwable 1555 { 1556 logger.info(LocalizableMessage.raw("Loading Topology Cache in askForAuthentication")); 1557 ADSContext adsContext = new ADSContext(ctx); 1558 TopologyCache cache = new TopologyCache(adsContext, 1559 getTrustManager(), getConnectTimeout()); 1560 cache.getFilter().setSearchMonitoringInformation(false); 1561 cache.reloadTopology(); 1562 return cache; 1563 } 1564 @Override 1565 public void backgroundTaskCompleted(TopologyCache returnValue, 1566 Throwable throwable) { 1567 qs.getDialog().workerFinished(); 1568 if (throwable != null) 1569 { 1570 logger.warn(LocalizableMessage.raw("Throwable: "+throwable, throwable)); 1571 if (throwable instanceof TopologyCacheException) 1572 { 1573 qs.displayError( 1574 getMessage( 1575 (TopologyCacheException)throwable), 1576 INFO_ERROR_TITLE.get()); 1577 } 1578 else 1579 { 1580 qs.displayError( 1581 getThrowableMsg(INFO_BUG_MSG.get(), throwable), 1582 INFO_ERROR_TITLE.get()); 1583 } 1584 logger.info(LocalizableMessage.raw("Error was displayed")); 1585 } 1586 else 1587 { 1588 TopologyCache cache = returnValue; 1589 handleTopologyCache(qs, cache); 1590 } 1591 } 1592 }; 1593 1594 qs.getDialog().workerStarted(); 1595 worker.startBackgroundTask(); 1596 } 1597 else if (qs.displayConfirmation( 1598 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_MSG.get(), 1599 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_TITLE.get())) 1600 { 1601 getUserData().setStopServer(true); 1602 qs.launch(); 1603 qs.setCurrentStep(getNextWizardStep(Step.CONFIRM_UNINSTALL)); 1604 } else { 1605 getUserData().setStopServer(false); 1606 } 1607 } 1608 1609 /** 1610 * Method that interacts with the user depending on what errors where 1611 * encountered in the TopologyCache object. This method assumes that the 1612 * TopologyCache has been reloaded. 1613 * Note: this method assumes that is being called from the event thread. 1614 * @param qs the QuickSetup object for the application. 1615 * @param cache the TopologyCache. 1616 */ 1617 private void handleTopologyCache(QuickSetup qs, TopologyCache cache) 1618 { 1619 logger.info(LocalizableMessage.raw("Handling TopologyCache")); 1620 boolean stopProcessing = false; 1621 Set<TopologyCacheException> exceptions = new HashSet<>(); 1622 /* Analyze if we had any exception while loading servers. For the moment 1623 * only throw the exception found if the user did not provide the 1624 * Administrator DN and this caused a problem authenticating in one server 1625 * or if there is a certificate problem. 1626 */ 1627 for (ServerDescriptor server : cache.getServers()) 1628 { 1629 TopologyCacheException e = server.getLastException(); 1630 if (e != null) 1631 { 1632 exceptions.add(e); 1633 } 1634 } 1635 Set<LocalizableMessage> exceptionMsgs = new LinkedHashSet<>(); 1636 /* Check the exceptions and see if we throw them or not. */ 1637 for (TopologyCacheException e : exceptions) 1638 { 1639 logger.info(LocalizableMessage.raw("Analyzing exception: "+e, e)); 1640 if (stopProcessing) 1641 { 1642 break; 1643 } 1644 switch (e.getType()) 1645 { 1646 case NOT_GLOBAL_ADMINISTRATOR: 1647 LocalizableMessage errorMsg = INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get(); 1648 qs.displayError(errorMsg, INFO_ERROR_TITLE.get()); 1649 stopProcessing = true; 1650 break; 1651 case GENERIC_CREATING_CONNECTION: 1652 if (isCertificateException(e.getCause())) 1653 { 1654 ApplicationTrustManager.Cause cause = null; 1655 if (e.getTrustManager() != null) 1656 { 1657 cause = e.getTrustManager().getLastRefusedCause(); 1658 } 1659 logger.info(LocalizableMessage.raw("Certificate exception cause: "+cause)); 1660 UserDataCertificateException.Type excType = getCertificateExceptionType(cause); 1661 if (excType != null) 1662 { 1663 String h; 1664 int p; 1665 try 1666 { 1667 URI uri = new URI(e.getLdapUrl()); 1668 h = uri.getHost(); 1669 p = uri.getPort(); 1670 } 1671 catch (Throwable t) 1672 { 1673 logger.warn(LocalizableMessage.raw( 1674 "Error parsing ldap url of TopologyCacheException.", t)); 1675 h = INFO_NOT_AVAILABLE_LABEL.get().toString(); 1676 p = -1; 1677 } 1678 UserDataCertificateException exc = 1679 new UserDataCertificateException(Step.REPLICATION_OPTIONS, 1680 INFO_CERTIFICATE_EXCEPTION.get(h, p), 1681 e.getCause(), h, p, 1682 e.getTrustManager().getLastRefusedChain(), 1683 e.getTrustManager().getLastRefusedAuthType(), excType); 1684 handleCertificateException(qs, exc, cache); 1685 stopProcessing = true; 1686 } 1687 } 1688 } 1689 exceptionMsgs.add(getMessage(e)); 1690 } 1691 if (!stopProcessing && !exceptionMsgs.isEmpty()) 1692 { 1693 LocalizableMessage confirmationMsg = 1694 ERR_UNINSTALL_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.get( 1695 getMessageFromCollection(exceptionMsgs, "\n")); 1696 stopProcessing = !qs.displayConfirmation(confirmationMsg, 1697 INFO_CONFIRMATION_TITLE.get()); 1698 } 1699 if (!stopProcessing) 1700 { 1701 stopProcessing = !qs.displayConfirmation( 1702 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_MSG.get(), 1703 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_TITLE.get()); 1704 } 1705 if (!stopProcessing) 1706 { 1707 // Launch everything 1708 getUninstallUserData().setUpdateRemoteReplication(true); 1709 getUninstallUserData().setRemoteServers(cache.getServers()); 1710 getUserData().setStopServer(true); 1711 qs.launch(); 1712 qs.setCurrentStep(getNextWizardStep(Step.CONFIRM_UNINSTALL)); 1713 } 1714 } 1715 1716 private UserDataCertificateException.Type getCertificateExceptionType(ApplicationTrustManager.Cause cause) 1717 { 1718 if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) 1719 { 1720 return UserDataCertificateException.Type.NOT_TRUSTED; 1721 } 1722 else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) 1723 { 1724 return UserDataCertificateException.Type.HOST_NAME_MISMATCH; 1725 } 1726 else 1727 { 1728 return null; 1729 } 1730 } 1731 1732 /** 1733 * Displays a dialog asking the user to accept a certificate if the user 1734 * accepts it, we update the trust manager and call again to the method that 1735 * handles the action of clicking on "Finish". 1736 * This method assumes that we are being called from the event thread. 1737 */ 1738 private void handleCertificateException(final QuickSetup qs, 1739 UserDataCertificateException ce, final TopologyCache cache) 1740 { 1741 CertificateDialog dlg = 1742 new CertificateDialog(qs.getDialog().getFrame(), ce); 1743 dlg.pack(); 1744 dlg.setVisible(true); 1745 if (dlg.getUserAnswer() != CertificateDialog.ReturnType.NOT_ACCEPTED) 1746 { 1747 X509Certificate[] chain = ce.getChain(); 1748 String authType = ce.getAuthType(); 1749 String host = ce.getHost(); 1750 1751 if (chain != null && authType != null && host != null) 1752 { 1753 logger.info(LocalizableMessage.raw("Accepting certificate presented by host "+host)); 1754 getTrustManager().acceptCertificate(chain, authType, host); 1755 BackgroundTask<TopologyCache> worker = 1756 new BackgroundTask<TopologyCache>() 1757 { 1758 @Override 1759 public TopologyCache processBackgroundTask() throws Throwable 1760 { 1761 logger.info(LocalizableMessage.raw("Reloading topology")); 1762 cache.getFilter().setSearchMonitoringInformation(false); 1763 cache.reloadTopology(); 1764 return cache; 1765 } 1766 @Override 1767 public void backgroundTaskCompleted(TopologyCache returnValue, 1768 Throwable throwable) { 1769 qs.getDialog().workerFinished(); 1770 if (throwable != null) 1771 { 1772 if (throwable instanceof TopologyCacheException) 1773 { 1774 qs.displayError(getMessage((TopologyCacheException)throwable), 1775 INFO_ERROR_TITLE.get()); 1776 } 1777 else 1778 { 1779 qs.displayError( 1780 getThrowableMsg(INFO_BUG_MSG.get(), throwable), 1781 INFO_ERROR_TITLE.get()); 1782 } 1783 } 1784 else 1785 { 1786 handleTopologyCache(qs, cache); 1787 } 1788 } 1789 }; 1790 1791 qs.getDialog().workerStarted(); 1792 worker.startBackgroundTask(); 1793 } 1794 else 1795 { 1796 if (chain == null) 1797 { 1798 logger.warn(LocalizableMessage.raw( 1799 "The chain is null for the UserDataCertificateException")); 1800 } 1801 if (authType == null) 1802 { 1803 logger.warn(LocalizableMessage.raw( 1804 "The auth type is null for the UserDataCertificateException")); 1805 } 1806 if (host == null) 1807 { 1808 logger.warn(LocalizableMessage.raw( 1809 "The host is null for the UserDataCertificateException")); 1810 } 1811 } 1812 } 1813 if (dlg.getUserAnswer() == 1814 CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY) 1815 { 1816 X509Certificate[] chain = ce.getChain(); 1817 if (chain != null) 1818 { 1819 try 1820 { 1821 UIKeyStore.acceptCertificate(chain); 1822 } 1823 catch (Throwable t) 1824 { 1825 logger.warn(LocalizableMessage.raw("Error accepting certificate: "+t, t)); 1826 } 1827 } 1828 } 1829 } 1830 1831 /** 1832 * This method updates the replication in the remote servers. It does 1833 * throw ApplicationException if we are working on the force on error mode. 1834 * It also tries to delete the server registration entry from the remote ADS 1835 * servers. 1836 * @throws ApplicationException if we are not working on force on error mode 1837 * and there is an error. 1838 */ 1839 private void removeRemoteServerReferences() throws ApplicationException 1840 { 1841 Set<ServerDescriptor> servers = getUninstallUserData().getRemoteServers(); 1842 Map<ADSContext.ServerProperty, Object> serverADSProperties = null; 1843 for (ServerDescriptor server : servers) 1844 { 1845 if (isServerToUninstall(server)) 1846 { 1847 serverADSProperties = server.getAdsProperties(); 1848 break; 1849 } 1850 } 1851 if (serverADSProperties == null) 1852 { 1853 logger.warn(LocalizableMessage.raw("The server ADS properties for the server to "+ 1854 "uninstall could not be found.")); 1855 } 1856 1857 for (ServerDescriptor server : servers) 1858 { 1859 if (server.getAdsProperties() != serverADSProperties) 1860 { 1861 removeReferences(server, serverADSProperties); 1862 } 1863 } 1864 } 1865 1866 /** 1867 * This method updates the replication in the remote server represented by 1868 * a given ServerProperty object. 1869 * It also tries to delete the server registration entry from the remote ADS 1870 * servers if the serverADSProperties object passed is not null. 1871 * @param server the ServerDescriptor object representing the server where 1872 * we want to remove references to the server that we are trying to uninstall. 1873 * @param serverADSProperties the Map with the ADS properties of the server 1874 * that we are trying to uninstall. 1875 * @throws ApplicationException if we are not working on force on error mode 1876 * and there is an error. 1877 */ 1878 private void removeReferences(ServerDescriptor server, 1879 Map<ADSContext.ServerProperty, Object> serverADSProperties) 1880 throws ApplicationException 1881 { 1882 /* First check if the server must be updated based in the contents of the 1883 * ServerDescriptor object. */ 1884 boolean hasReferences = false; 1885 1886 Object v = server.getServerProperties().get( 1887 ServerDescriptor.ServerProperty.IS_REPLICATION_SERVER); 1888 if (Boolean.TRUE.equals(v)) 1889 { 1890 Set<?> replicationServers = (Set<?>)server.getServerProperties().get( 1891 ServerDescriptor.ServerProperty.EXTERNAL_REPLICATION_SERVERS); 1892 if (replicationServers != null) 1893 { 1894 for (Object o : replicationServers) 1895 { 1896 if (getUninstallUserData().getReplicationServer().equalsIgnoreCase( 1897 (String)o)) 1898 { 1899 hasReferences = true; 1900 break; 1901 } 1902 } 1903 } 1904 } 1905 1906 if (!hasReferences) 1907 { 1908 for (ReplicaDescriptor replica : server.getReplicas()) 1909 { 1910 if (replica.isReplicated()) 1911 { 1912 for (Object o : replica.getReplicationServers()) 1913 { 1914 if (getUninstallUserData().getReplicationServer().equalsIgnoreCase( 1915 (String)o)) 1916 { 1917 hasReferences = true; 1918 break; 1919 } 1920 } 1921 } 1922 if (hasReferences) 1923 { 1924 break; 1925 } 1926 } 1927 } 1928 1929 if (!hasReferences) 1930 { 1931 logger.info(LocalizableMessage.raw("No references in: "+ server.getHostPort(true))); 1932 } 1933 if (hasReferences) 1934 { 1935 logger.info(LocalizableMessage.raw("Updating references in: "+ server.getHostPort(true))); 1936 notifyListeners(getFormattedWithPoints( 1937 INFO_PROGRESS_REMOVING_REFERENCES.get(server.getHostPort(true)))); 1938 InitialLdapContext ctx = null; 1939 try 1940 { 1941 String dn = ADSContext.getAdministratorDN( 1942 getUninstallUserData().getAdminUID()); 1943 String pwd = getUninstallUserData().getAdminPwd(); 1944 ctx = getRemoteConnection(server, dn, pwd, getTrustManager(), 1945 getConnectTimeout(), 1946 new LinkedHashSet<PreferredConnection>()); 1947 1948 // Update replication servers and domains. If the domain 1949 // is an ADS, then remove it from there. 1950 removeReferences(ctx, server.getHostPort(true), serverADSProperties); 1951 1952 notifyListeners(getFormattedDoneWithLineBreak()); 1953 } 1954 catch (ApplicationException ae) 1955 { 1956 errorOnRemoteOccurred = true; 1957 logger.info(LocalizableMessage.raw("Error updating replication references in: "+ 1958 server.getHostPort(true), ae)); 1959 1960 if (!getUninstallUserData().isForceOnError()) 1961 { 1962 LocalizableMessage msg = 1963 ERR_UNINSTALL_ERROR_UPDATING_REMOTE_NO_FORCE.get( 1964 "--"+ 1965 parser.getSecureArgsList().adminUidArg.getLongIdentifier(), 1966 "--"+OPTION_LONG_BINDPWD, 1967 "--"+OPTION_LONG_BINDPWD_FILE, 1968 "--"+parser.forceOnErrorArg.getLongIdentifier(), 1969 ae.getMessageObject()); 1970 throw new ApplicationException(ae.getType(), msg, ae); 1971 } 1972 else 1973 { 1974 LocalizableMessage html = getFormattedError(ae, true); 1975 notifyListeners(html); 1976 } 1977 } 1978 finally 1979 { 1980 StaticUtils.close(ctx); 1981 } 1982 } 1983 } 1984 1985 /** 1986 * This method updates the replication in the remote server using the 1987 * provided InitialLdapContext. 1988 * It also tries to delete the server registration entry from the remote ADS 1989 * servers if the serverADSProperties object passed is not null. 1990 * @param ctx the connection to the remote server where we want to remove 1991 * references to the server that we are trying to uninstall. 1992 * @param serverDisplay an String representation that is used to identify 1993 * the remote server in the log messages we present to the user. 1994 * @param serverADSProperties the Map with the ADS properties of the server 1995 * that we are trying to uninstall. 1996 * @throws ApplicationException if an error occurs while updating the remote 1997 * OpenDS server configuration. 1998 */ 1999 private void removeReferences(InitialLdapContext ctx, String serverDisplay, 2000 Map<ADSContext.ServerProperty, Object> serverADSProperties) 2001 throws ApplicationException 2002 { 2003 try 2004 { 2005 ManagementContext mCtx = LDAPManagementContext.createFromContext( 2006 JNDIDirContextAdaptor.adapt(ctx)); 2007 RootCfgClient root = mCtx.getRootConfiguration(); 2008 ReplicationSynchronizationProviderCfgClient sync = 2009 (ReplicationSynchronizationProviderCfgClient) 2010 root.getSynchronizationProvider("Multimaster Synchronization"); 2011 if (sync.hasReplicationServer()) 2012 { 2013 ReplicationServerCfgClient replicationServer = 2014 sync.getReplicationServer(); 2015 Set<String> replServers = replicationServer.getReplicationServer(); 2016 if (replServers != null) 2017 { 2018 String replServer = null; 2019 for (String o : replServers) 2020 { 2021 if (getUninstallUserData().getReplicationServer().equalsIgnoreCase( 2022 o)) 2023 { 2024 replServer = o; 2025 break; 2026 } 2027 } 2028 if (replServer != null) 2029 { 2030 logger.info(LocalizableMessage.raw("Updating references in replication server on "+ 2031 serverDisplay+".")); 2032 replServers.remove(replServer); 2033 if (!replServers.isEmpty()) 2034 { 2035 replicationServer.setReplicationServer(replServers); 2036 replicationServer.commit(); 2037 } 2038 else 2039 { 2040 sync.removeReplicationServer(); 2041 sync.commit(); 2042 } 2043 } 2044 } 2045 } 2046 String[] domainNames = sync.listReplicationDomains(); 2047 if (domainNames != null) 2048 { 2049 for (String domainName : domainNames) 2050 { 2051 ReplicationDomainCfgClient domain = 2052 sync.getReplicationDomain(domainName); 2053 Set<String> replServers = domain.getReplicationServer(); 2054 if (replServers != null) 2055 { 2056 String replServer = null; 2057 for (String o : replServers) 2058 { 2059 if (getUninstallUserData().getReplicationServer(). 2060 equalsIgnoreCase(o)) 2061 { 2062 replServer = o; 2063 break; 2064 } 2065 } 2066 if (replServer != null) 2067 { 2068 logger.info(LocalizableMessage.raw("Updating references in domain " + 2069 domain.getBaseDN()+" on " + serverDisplay + ".")); 2070 replServers.remove(replServer); 2071 if (!replServers.isEmpty()) 2072 { 2073 domain.setReplicationServer(replServers); 2074 domain.commit(); 2075 } 2076 else 2077 { 2078 sync.removeReplicationDomain(domainName); 2079 sync.commit(); 2080 } 2081 } 2082 } 2083 } 2084 } 2085 } 2086 catch (ManagedObjectNotFoundException monfe) 2087 { 2088 // It does not exist. 2089 logger.info(LocalizableMessage.raw("No synchronization found on "+ serverDisplay+".", 2090 monfe)); 2091 } 2092 catch (Throwable t) 2093 { 2094 logger.warn(LocalizableMessage.raw( 2095 "Error removing references in replication server on "+ 2096 serverDisplay+": "+t, t)); 2097 LocalizableMessage errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get( 2098 serverDisplay, t); 2099 throw new ApplicationException( 2100 ReturnCode.CONFIGURATION_ERROR, errorMessage, t); 2101 } 2102 ADSContext adsContext = new ADSContext(ctx); 2103 2104 try 2105 { 2106 if (adsContext.hasAdminData() && serverADSProperties != null) 2107 { 2108 logger.info(LocalizableMessage.raw("Unregistering server on ADS of server "+ 2109 ConnectionUtils.getHostPort(ctx)+". Properties: "+ 2110 serverADSProperties)); 2111 adsContext.unregisterServer(serverADSProperties); 2112 } 2113 } 2114 catch (ADSContextException ace) 2115 { 2116 if (ace.getError() != 2117 ADSContextException.ErrorType.NOT_YET_REGISTERED) 2118 { 2119 throw new ApplicationException( 2120 ReturnCode.CONFIGURATION_ERROR, 2121 INFO_REMOTE_ADS_EXCEPTION.get(serverDisplay, ace), 2122 ace); 2123 } 2124 else 2125 { 2126 // Nothing to do: this may occur if the new server has been 2127 // unregistered on another server and the modification has 2128 // been already propagated by replication. 2129 } 2130 } 2131 } 2132 2133 /** 2134 * Tells whether this ServerDescriptor object represents the server that we 2135 * are trying to uninstall or not. 2136 * @param server the ServerDescriptor object to analyze. 2137 * @return <CODE>true</CODE> if the ServerDescriptor object represents the 2138 * server that we are trying to uninstall and <CODE>false</CODE> otherwise. 2139 */ 2140 private boolean isServerToUninstall(ServerDescriptor server) 2141 { 2142 boolean isServerToUninstall = false; 2143 String path = (String)server.getAdsProperties().get( 2144 ADSContext.ServerProperty.INSTANCE_PATH); 2145 if (path == null) 2146 { 2147 // Compare the port of the URL we used. 2148 try 2149 { 2150 String usedUrl = getUninstallUserData().getLocalServerUrl(); 2151 boolean isSecure = usedUrl.toLowerCase().startsWith("ldaps"); 2152 URI uri = new URI(usedUrl); 2153 int port = uri.getPort(); 2154 ServerDescriptor.ServerProperty property; 2155 if (isSecure) 2156 { 2157 property = ServerDescriptor.ServerProperty.ADMIN_PORT; 2158 } 2159 else 2160 { 2161 property = ServerDescriptor.ServerProperty.LDAP_PORT; 2162 } 2163 ArrayList<?> ports = 2164 (ArrayList<?>)server.getServerProperties().get(property); 2165 if (ports != null) 2166 { 2167 isServerToUninstall = ports.contains(port); 2168 } 2169 else 2170 { 2171 // This occurs if the instance could not be loaded. 2172 ADSContext.ServerProperty adsProperty; 2173 if (isSecure) 2174 { 2175 adsProperty = ADSContext.ServerProperty.ADMIN_PORT; 2176 } 2177 else 2178 { 2179 adsProperty = ADSContext.ServerProperty.LDAP_PORT; 2180 } 2181 String v = (String)server.getAdsProperties().get(adsProperty); 2182 if (v != null) 2183 { 2184 isServerToUninstall = v.equals(String.valueOf(port)); 2185 } 2186 } 2187 } 2188 catch (Throwable t) 2189 { 2190 logger.warn(LocalizableMessage.raw("Failing checking the port: "+t, t)); 2191 } 2192 } 2193 else 2194 { 2195 File f = new File(path); 2196 isServerToUninstall = 2197 f.equals(Installation.getLocal().getRootDirectory()); 2198 } 2199 2200 if (isServerToUninstall) 2201 { 2202 // TODO: the host name comparison made here does not necessarily work in 2203 // all environments... 2204 String hostName = server.getHostName(); 2205 boolean hostNameEquals = 2206 getUninstallUserData().getReferencedHostName().equals(hostName); 2207 try 2208 { 2209 InetAddress localAddress = InetAddress.getLocalHost(); 2210 InetAddress[] addresses = InetAddress.getAllByName(hostName); 2211 for (int i=0; i<addresses.length && !hostNameEquals; i++) 2212 { 2213 hostNameEquals = localAddress.equals(addresses[i]); 2214 } 2215 if (!hostNameEquals) 2216 { 2217 hostNameEquals = 2218 localAddress.getHostName().equalsIgnoreCase(hostName) || 2219 localAddress.getCanonicalHostName().equalsIgnoreCase(hostName); 2220 } 2221 } 2222 catch (Throwable t) 2223 { 2224 logger.warn(LocalizableMessage.raw("Failing checking host names: "+t, t)); 2225 } 2226 isServerToUninstall = hostNameEquals; 2227 } 2228 return isServerToUninstall; 2229 } 2230 2231 /** 2232 * Returns the timeout to be used to connect in milliseconds. 2233 * @return the timeout to be used to connect in milliseconds. Returns 2234 * {@code 0} if there is no timeout. 2235 */ 2236 private int getConnectTimeout() 2237 { 2238 return getUserData().getConnectTimeout(); 2239 } 2240} 2241