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