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