/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
*/
/**
* The class used to provide some CLI interface in the uninstall.
*
* This class basically is in charge of parsing the data provided by the user
* in the command line and displaying messages asking the user for information.
*
* Once the user has provided all the required information it calls Uninstaller
* and launches it.
*
*/
private boolean forceNonInteractive;
// This CLI is always using the administration connector with SSL
private final boolean alwaysSSL = true;
private boolean useSSL = true;
private boolean useStartTLS = false;
/**
* Default constructor.
*/
public UninstallCliHelper()
{
}
/**
* Creates a UserData based in the arguments provided. It asks
* user for additional information if what is provided in the arguments is not
* enough.
* @param args the ArgumentParser with the allowed arguments of the command
* line. The code assumes that the arguments have already been parsed.
* @param rawArguments the arguments provided in the command line.
* @return the UserData object with what the user wants to uninstall
* and null if the user cancels the uninstallation.
* @throws UserDataException if there is an error with the data
* in the arguments.
* @throws ApplicationException if there is an error processing data in
* non-interactive mode and an error must be thrown (not in force on error
* mode).
*/
{
try
{
boolean isInteractive;
boolean isQuiet;
boolean isVerbose;
boolean isCanceled = false;
/* Step 1: analyze the arguments.
*/
/*
* Step 2: check that the provided parameters are compatible.
*/
{
}
/* Step 3: If this is an interactive uninstall ask for confirmation to
* delete the different parts of the installation if the user did not
* specify anything to delete. If we are not in interactive mode
* check that the user specified something to be deleted.
*/
try {
} catch (IOException ioe) {
}
try {
} catch (IOException ioe) {
}
boolean somethingSpecifiedToDelete =
args.removeBackupFiles() ||
args.removeDatabases() ||
args.removeLDIFFiles() ||
args.removeLogFiles() ||
{
}
else
{
if (!isInteractive)
{
throw new UserDataException(null,
}
else
{
}
}
{
}
{
}
try
{
}
catch (Throwable t)
{
referencedHostName+":8989");
}
if (adminConnectorUrl == null)
{
"Error retrieving a valid LDAP URL in conf file.");
if (!parser.isInteractive())
{
null);
}
}
/*
* Step 4: check if server is running. Depending if it is running and the
* OS we are running, ask for authentication information.
*/
if (!isCanceled)
{
}
{
}
{
println();
}
}
catch (Throwable t)
{
if (t instanceof UserDataException)
{
throw (UserDataException)t;
}
else if (t instanceof ApplicationException)
{
throw (ApplicationException)t;
}
else
{
throw new IllegalStateException("Unexpected error: "+t, t);
}
}
return userData;
}
/**
* Commodity method used to ask the user to confirm the deletion of certain
* parts of the server. It updates the provided UserData object
* accordingly. Returns <CODE>true</CODE> if the user cancels and <CODE>
* false</CODE> otherwise.
* @param userData the UserData object to be updated.
* @param outsideDbs the set of relative paths of databases located outside
* the installation path of the server.
* @param outsideLogs the set of relative paths of log files located outside
* the installation path of the server.
* @return <CODE>true</CODE> if the user cancels and <CODE>false</CODE>
* otherwise.
*/
{
boolean cancelled = false;
final int REMOVE_ALL = 1;
final int SPECIFY_TO_REMOVE = 2;
};
{
}
int choice;
try
{
if (m.isSuccess())
{
}
else if (m.isQuit())
{
choice = REMOVE_ALL;
cancelled = true;
}
else
{
// Should never happen.
throw new RuntimeException();
}
}
catch (CLIException ce)
{
}
if (cancelled)
{
// Nothing to do
}
else if (choice == REMOVE_ALL)
{
userData.setRemoveBackups(true);
userData.setRemoveDatabases(true);
userData.setRemoveLDIFs(true);
userData.setRemoveLogs(true);
}
else
{
boolean somethingSelected = false;
while (!somethingSelected && !cancelled)
{
println();
// Ask for confirmation for the different items
)
};
try
{
{
if (!ignore)
{
}
else
{
answers[i] = false;
}
}
}
catch (CLIException ce)
{
}
if (!cancelled)
{
{
switch (i)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
if (answers[i])
{
}
break;
case 7:
if (answers[i])
{
}
break;
}
}
!userData.getRemoveDatabases() &&
!userData.getRemoveBackups() &&
!userData.getRemoveLDIFs() &&
{
somethingSelected = false;
println();
}
else
{
somethingSelected = true;
}
}
}
}
return cancelled;
}
/**
* Commodity method used to ask the user (when necessary) if the server must
* be stopped or not. It also prompts (if required) for authentication.
* @param userData the UserData object to be updated with the
* authentication of the user.
* @return <CODE>true</CODE> if the user wants to continue with uninstall and
* <CODE>false</CODE> otherwise.
* @throws UserDataException if there is a problem with the data
* provided by the user (in the particular case where we are on
* non-interactive uninstall and some data is missing or not valid).
* @throws ApplicationException if there is an error processing data in
* non-interactive mode and an error must be thrown (not in force on error
* mode).
*/
{
boolean cancelled = false;
try
{
}
catch (Throwable t)
{
}
{
if (conf.isServerRunning())
{
if (interactive)
{
try
{
if (confirmToUpdateRemote())
{
println();
if (cancelled)
{
/* Ask for confirmation to stop server */
println();
cancelled = !confirmToStopServer();
}
else
{
if (cancelled)
{
println();
/* Ask for confirmation to stop server */
cancelled = !confirmToStopServer();
}
}
}
else
{
println();
/* Ask for confirmation to stop server */
cancelled = !confirmToStopServer();
}
}
catch (CLIException ce)
{
}
}
else
{
boolean errorWithRemote =
}
}
else
{
if (interactive)
{
println();
try
{
{
// Ask for authentication if needed, etc.
if (startWorked)
{
if (cancelled)
{
println();
/* Ask for confirmation to stop server */
cancelled = !confirmToStopServer();
}
else
{
if (cancelled)
{
println();
/* Ask for confirmation to stop server */
cancelled = !confirmToStopServer();
}
}
userData.setStopServer(true);
}
else
{
userData.setStopServer(false);
println();
/* Ask for confirmation to delete files */
cancelled = !confirmDeleteFiles();
}
}
else
{
println();
/* Ask for confirmation to delete files */
cancelled = !confirmDeleteFiles();
}
}
catch (CLIException ce)
{
}
}
else
{
// Ask for authentication if needed, etc.
if (startWorked)
{
userData.setStopServer(true);
boolean errorWithRemote =
}
else
{
userData.setStopServer(false);
}
}
}
{
/* During all the confirmations, the server might be stopped. */
}
}
else
{
if (conf.isServerRunning())
{
try
{
if (interactive)
{
println();
/* Ask for confirmation to stop server */
cancelled = !confirmToStopServer();
}
if (!cancelled)
{
/* During all the confirmations, the server might be stopped. */
}
}
catch (CLIException ce)
{
}
}
else
{
userData.setStopServer(false);
if (interactive)
{
println();
/* Ask for confirmation to delete files */
try
{
cancelled = !confirmDeleteFiles();
}
catch (CLIException ce)
{
}
}
}
}
return cancelled;
}
/**
* Ask for confirmation to stop server.
* @return <CODE>true</CODE> if the user wants to continue and stop the
* server. <CODE>false</CODE> otherwise.
* @throws CLIException if the user reached the confirmation limit.
*/
{
}
/**
* Ask for confirmation to delete files.
* @return <CODE>true</CODE> if the user wants to continue and delete the
* files. <CODE>false</CODE> otherwise.
* @throws CLIException if the user reached the confirmation limit.
*/
{
LOG);
}
/**
* Ask for confirmation to update configuration on remote servers.
* @return <CODE>true</CODE> if the user wants to continue and stop the
* server. <CODE>false</CODE> otherwise.
* @throws CLIException if the user reached the confirmation limit.
*/
{
LOG);
}
/**
* Ask for confirmation to update configuration on remote servers.
* @return <CODE>true</CODE> if the user wants to continue and stop the
* server. <CODE>false</CODE> otherwise.
* @throws CLIException if the user reached the confirmation limit.
*/
{
return askConfirmation(
}
/**
* Ask for confirmation to provide again authentication.
* @return <CODE>true</CODE> if the user wants to provide authentication
* again. <CODE>false</CODE> otherwise.
* @throws CLIException if the user reached the confirmation limit.
*/
{
return askConfirmation(
}
/**
* Ask for data required to update configuration on remote servers. If
* all the data is provided and validated, we assume that the user wants
* to update the remote servers.
* @return <CODE>true</CODE> if the user wants to continue and update the
* remote servers. <CODE>false</CODE> otherwise.
* @throws UserDataException if there is a problem with the information
* provided by the user.
* @throws ApplicationException if there is an error processing data.
*/
{
boolean accepted = true;
boolean couldConnect = false;
while (!couldConnect && accepted)
{
// This is done because we do not need to ask the user about these
// parameters. If we force their presence the class
// LDAPConnectionConsoleInteraction will not prompt the user for
// them.
{
}
else
{
}
{
}
else
{
}
{
ci =
}
try
{
if (adminConnectorUrl == null)
{
"Error retrieving a valid Administration Connector URL in conf file.");
null);
}
try
{
}
catch (Throwable t)
{
}
if (adminConnectorUrl == null)
{
"Error retrieving a valid Administration Connector URL in conf file.");
null);
}
couldConnect = true;
}
catch (ArgumentException e) {
println();
}
catch (ClientException e) {
println();
}
finally
{
{
try
{
}
catch (Throwable t)
{
}
}
}
if (!couldConnect)
{
try
{
if (accepted)
{
}
}
catch (CLIException ce)
{
}
}
}
if (accepted)
{
while (referencedHostName == null)
{
println();
}
try
{
}
catch (Throwable t)
{
}
}
return accepted;
}
{
String s = defaultHostName;
try
{
}
catch (CLIException ce)
{
}
return s;
}
{
boolean serverStarted = false;
{
/**
* {@inheritDoc}
*/
public String getInstallationPath()
{
}
/**
* {@inheritDoc}
*/
public String getInstancePath()
{
// look for <installPath>/lib/resource.loc
if (! f.exists())
{
return installPath;
}
try
{
}
catch (Exception e)
{
return installPath;
}
// Read the first line and close the file.
try
{
}
catch (Exception e)
{
return installPath;
}
finally
{
try
{
} catch (Exception e) {}
}
}
/**
* {@inheritDoc}
*/
public ProgressStep getCurrentProgressStep()
{
return UninstallProgressStep.NOT_STARTED;
}
/**
* {@inheritDoc}
*/
{
return 0;
}
/**
* {@inheritDoc}
*/
{
return null;
}
/**
* {@inheritDoc}
*/
public boolean isFinished()
{
return false;
}
/**
* {@inheritDoc}
*/
public boolean isCancellable()
{
return false;
}
/**
* {@inheritDoc}
*/
public void cancel()
{
}
/**
* {@inheritDoc}
*/
public void run()
{
}
};
if (!supressOutput)
{
new ProgressUpdateListener() {
}
});
}
Installation.getLocal());
try
{
if (!supressOutput)
{
}
if (!supressOutput)
{
}
}
catch (ApplicationException ae)
{
if (!supressOutput)
{
}
}
catch (Throwable t)
{
throw new IllegalStateException("Unexpected error: "+t, t);
}
return serverStarted;
}
/**
* Updates the contents of the UninstallUserData while trying to connect
* to the remote servers. It returns <CODE>true</CODE> if we could connect
* to the remote servers and all the presented certificates were accepted and
* <CODE>false</CODE> otherwise.
* continue if
* @param userData the user data to be updated.
* @return <CODE>true</CODE> if we could connect
* to the remote servers and all the presented certificates were accepted and
* <CODE>false</CODE> otherwise.
* @throws UserDataException if were are not in interactive mode and not in
* force on error mode and the operation must be stopped.
* @throws ApplicationException if there is an error processing data in
* non-interactive mode and an error must be thrown (not in force on error
* mode).
*/
private boolean updateUserUninstallDataWithRemoteServers(
{
boolean accepted = false;
boolean exceptionOccurred = true;
try
{
int port = 389;
try
{
}
catch (Throwable t)
{
}
pwd, getConnectTimeout(),
{
// This is required when the user did connect to the server using SSL
// or Start TLS in interactive mode. In this case
// LDAPConnectionInteraction.run does not initialize the keystore and
// the trust manager is null.
}
exceptionOccurred = false;
}
catch (NamingException ne)
{
{
}
else
{
}
} catch (TopologyCacheException te)
{
} catch (ApplicationException ae)
{
throw ae;
} catch (Throwable t)
{
}
finally
{
{
try
{
}
catch (Throwable t)
{
}
}
}
if (exceptionOccurred)
{
if (!interactive)
{
if (forceOnError)
{
println();
}
else
{
println();
throw new UserDataException(null,
"--"+
}
}
else
{
try
{
false, LOG);
}
catch (CLIException ce)
{
}
}
}
return accepted;
}
/**
* Method that interacts with the user depending on what errors where
* encountered in the TopologyCache object. This method assumes that the
* TopologyCache has been reloaded.
* Returns <CODE>true</CODE> if the user accepts all the problems encountered
* and <CODE>false</CODE> otherwise.
* @param userData the user data.
* @throws UserDataException if there is an error with the information
* provided by the user when we are in non-interactive mode.
* @throws ApplicationException if there is an error processing data in
* non-interactive mode and an error must be thrown (not in force on error
* mode).
*/
{
boolean returnValue;
boolean stopProcessing = false;
boolean reloadTopologyCache = false;
new HashSet<TopologyCacheException>();
/* Analyze if we had any exception while loading servers. For the moment
* only throw the exception found if the user did not provide the
* Administrator DN and this caused a problem authenticating in one server
* or if there is a certificate problem.
*/
{
if (e != null)
{
exceptions.add(e);
}
}
/* Check the exceptions and see if we throw them or not. */
for (TopologyCacheException e : exceptions)
{
if (stopProcessing)
{
break;
}
switch (e.getType())
{
case NOT_GLOBAL_ADMINISTRATOR:
println();
stopProcessing = true;
break;
{
if (interactive)
{
println();
{
stopProcessing = true;
reloadTopologyCache = true;
}
else
{
stopProcessing = true;
}
}
else
{
}
}
else
{
}
break;
default:
}
}
if (interactive)
{
{
println();
try
{
}
catch (CLIException ce)
{
}
}
else if (reloadTopologyCache)
{
}
else
{
}
}
else
{
{
if (parser.isForceOnError())
{
println();
returnValue = false;
}
else
{
"--"+
null);
}
}
else
{
returnValue = true;
}
}
return returnValue;
}
/**
* {@inheritDoc}
*/
public boolean isAdvancedMode() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isInteractive() {
if (forceNonInteractive)
{
return false;
}
else
{
return parser.isInteractive();
}
}
/**
* {@inheritDoc}
*/
public boolean isMenuDrivenMode() {
return true;
}
/**
* {@inheritDoc}
*/
public boolean isQuiet() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isScriptFriendly() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isVerbose() {
return true;
}
/**
* Commodity method to update the user data with the trust manager in the
* LDAPConnectionConsoleInteraction object.
* @param userData the user data to be updated.
* @param ci the LDAPConnectionConsoleInteraction object to be used to update
* the user data object.
*/
{
if (t != null)
{
if (t instanceof ApplicationTrustManager)
{
trust = (ApplicationTrustManager)t;
}
else
{
}
}
}
/**
* Forces the initialization of the trust manager in the
* LDAPConnectionInteraction object.
*/
private void forceTrustManagerInitialization()
{
forceNonInteractive = true;
try
{
}
catch (ArgumentException ae)
{
}
forceNonInteractive = false;
}
{
}
/**
* Returns the timeout to be used to connect in milliseconds. The method
* must be called after parsing the arguments.
* @return the timeout to be used to connect in milliseconds. Returns
* {@code 0} if there is no timeout.
* @throw {@code IllegalStateException} if the method is called before
* parsing the arguments.
*/
private int getConnectTimeout()
{
try
{
}
catch (ArgumentException ae)
{
ae);
}
}
}