Reverter.java revision bdb5a2eb7bfd1b7c4532654ab6d98f90e6ccd043
/*
* 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
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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
*
*
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
/**
* Reverts an installation from its current version to a prior version.
*/
private ReversionProgressStep currentProgressStep =
private ReverterUserData userData;
private ApplicationException runError;
private ApplicationException runWarning;
private Installation installation;
private Installation archiveInstallation;
private File tempBackupDir;
private long historicalOperationId;
private BuildInformation fromBuildInfo;
private BuildInformation archiveBuildInfo;
private boolean abort = false;
private boolean restartServer = false;
/**
* {@inheritDoc}
*/
if (launcher instanceof UpgradeLauncher) {
ud = new ReverterUserData();
if (rl.isInteractive()) {
if (rl.isNoPrompt()) {
.append("-")
.append("/--")
.append(", -")
.append("/--")
throw new UserDataException(null,
} else {
{
ud.setRevertMostRecent(true);
} else {
ud.setRevertMostRecent(false);
// Present a list of reversion archive choices to the user.
// In the future perhaps we might also allow them to type
// freehand.
// Print a wait message, this could take a while
}
}
try {
Installation i =
} catch (Exception e) {
"Error determining archive version for " + name);
}
try {
} catch (Exception e) {
}
}
Message[] raDirChoices =
{
}
int resp;
try
{
if (m.isSuccess())
{
}
else
{
// Should never happen.
throw new RuntimeException();
}
}
catch (CLIException ce)
{
resp = 1;
}
try {
} catch (UserDataException ude) {
}
} else {
throw new UserDataException(null,
}
} else {
throw new UserDataException(null,
}
}
}
} else if (rl.isRevertMostRecent()) {
ud.setRevertMostRecent(true);
} else {
}
if (ud.isRevertMostRecent()) {
if (historyDir.exists()) {
}
};
// The directories beneath 'history' are named according
// to the system time at which they were generated.
// Go through the directory names in order of most
// recent to oldest looking for the first one that
// looks like a backup directory
if (isReversionFilesDirectory(d)) {
break;
}
}
} else {
throw new UserDataException(null,
}
} else {
throw new UserDataException(null,
}
}
}
return ud;
}
/**
* {@inheritDoc}
*/
public UserData getUserData() {
return this.userData;
}
/**
* {@inheritDoc}
*/
if (userData instanceof ReverterUserData) {
}
}
/**
* {@inheritDoc}
*/
this.listenerDelegate = new ProgressUpdateListenerDelegate();
}
/**
* {@inheritDoc}
*/
public ApplicationException getRunError() {
return this.runError;
}
/**
* {@inheritDoc}
*/
public ReturnCode getReturnCode() {
return null;
}
/**
* {@inheritDoc}
*/
public void addProgressUpdateListener(ProgressUpdateListener l) {
}
/**
* {@inheritDoc}
*/
public void removeProgressUpdateListener(ProgressUpdateListener l) {
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
public String getInstallationPath() {
if (f.getParentFile() != null &&
LOCKS_PATH_RELATIVE).exists()) {
} else {
}
}
return installationPath;
}
/**
* {@inheritDoc}
*/
public ProgressStep getCurrentProgressStep() {
return this.currentProgressStep;
}
/**
* {@inheritDoc}
*/
if (step instanceof ReversionProgressStep) {
}
return ratio;
}
/**
* {@inheritDoc}
*/
// } else if (step == ReversionProgressStep.FINISHED_CANCELED) {
// txt = getFinalCanceledMessage();
// } else if (step == ReversionProgressStep.FINISHED_WITH_ERRORS) {
// txt = getFinalErrorMessage();
// } else if (step == ReversionProgressStep.FINISHED_WITH_WARNINGS) {
// txt = getFinalWarningMessage();
}
else {
}
return txt;
}
/**
* Returns the progress message for a given progress step.
* @param step the progress step.
* @return the progress message for the provided step.
*/
}
else
{
}
return txt;
}
/**
* {@inheritDoc}
*/
public boolean isFinished() {
return getCurrentProgressStep() ==
|| getCurrentProgressStep() ==
|| getCurrentProgressStep() ==
|| getCurrentProgressStep() ==
}
/**
* {@inheritDoc}
*/
public boolean isCancellable() {
return false;
}
/**
* {@inheritDoc}
*/
public void cancel() {
// not supported
}
/**
* Gets the OpenDS installation associated with the execution of this
* command.
* @return Installation object representing the current OpenDS installation
*/
public Installation getInstallation() {
if (installation == null) {
if (installPath != null) {
}
}
return installation;
}
/**
* {@inheritDoc}
*/
public void run() {
try {
// Get the user to confirm if possible
} else {
}
cont))) {
throw new ApplicationException(
}
}
// Stop the server if necessary. Task note as to whether the server
// is running since we will leave it in that state when we are done.
if (status.isServerRunning()) {
restartServer = true;
try {
if (isVerbose())
{
}
else
{
}
if (!isVerbose())
{
}
else
{
}
} catch (ApplicationException ae) {
}
}
try {
initialize();
} catch (ApplicationException ae) {
throw ae;
}
try {
} catch (ApplicationException ae) {
throw ae;
}
if (restartServer) {
try {
if (isVerbose())
{
}
else
{
}
if (!isVerbose())
{
}
else
{
}
} catch (ApplicationException ae) {
}
}
} catch (Throwable e) {
if (!(e instanceof ApplicationException)) {
runError = new ApplicationException(
} else {
runError = (ApplicationException)e;
((ApplicationException)e).getType());
}
} finally {
end();
}
}
this.currentProgressStep = step;
{
}
}
private void initialize() throws ApplicationException {
this.historicalOperationId =
}
private void backupCurrentInstallation() throws ApplicationException {
try {
// Replacing a Windows bat file while it is running with a different
// version leads to unpredictable behavior so we make a special case
// here and during the upgrade components step.
continue;
}
}
} catch (ApplicationException ae) {
throw ae;
} catch (Exception e) {
throw new ApplicationException(
e);
}
}
private void revertComponents() throws ApplicationException {
try {
// The bits should now be of the new version. Have
// the installation update the build information so
// that it is correct.
installation.getBuildInformation(false));
} catch (IOException e) {
}
}
private File getReversionFilesDirectory()
throws ApplicationException, IOException {
return userData.getReversionArchiveDirectory();
}
throws UserDataException
{
throw new UserDataException(null,
} else if (!filesDir.isDirectory()) {
throw new UserDataException(null,
} else if (!isReversionFilesDirectory(filesDir)) {
throw new UserDataException(null,
}
return filesDir;
}
boolean isFilesDir = false;
// TODO: more testing of file dir
}
return isFilesDir;
}
private void end() {
try {
// Since everything went OK, delete the archive
deleteBackup();
} else {
if (abort) {
} else {
}
// Abort the reversion and put things back like we found it
}
// Remove the lib directory temporarily created by the
// launch script with which the program is running
note);
new MessageBuilder(
try {
for (Message m : stageMessages) {
notifyListeners(m);
}
} catch (IOException e) {
}
} catch (ApplicationException e) {
}
// Decide final status based on presense of error
// WARNING: change this code at your own risk! The ordering
// of these statements is important. There are differences
// in how the CLI and GUI application's processes exit.
// Changing the ordering here may result in messages being
// skipped because the process has already exited by the time
// processing messages has finished. Need to resolve these
// issues.
if (abort) {
} else if (runWarning != null) {
// By design, the warnings are written as errors to the details section
// as errors. Warning markup is used surrounding the main message
// at the end of progress.
} else {
}
}
/**
* Abort this reversion and repair the installation.
*
* @param lastStep ProgressStep indicating how much work we will have to
* do to get the installation back like we left it
* @throws ApplicationException of something goes wrong
*/
// This can be used to bypass the aborted reversion cleanup
// process so that an autopsy can be performed on the
// crippled server.
return;
}
// Files were copied from the reversion directory to the current
// directory. Repair things by overwriting file in the
// root with those that were copied to the backup directory
// during revertFiles()
try {
boolean restoreError = false;
// Do our best to restore the filesystem like
// we found it. Just report potential problems
// to the user.
try {
} catch (Throwable t) {
restoreError = true;
}
}
if (!restoreError) {
}
} catch (IOException e) {
}
}
}
/**
* Deletes the archived backup to which we reverted.
*/
private void deleteArchive() {
try {
} catch (Exception e) {
// ignore; this is best effort
}
}
/**
* Deletes the backup of the current installation.
*/
private void deleteBackup() {
try {
} catch (Exception e) {
// ignore; this is best effort
}
}
/**
* Delete the library with which this reversion is currently
* running.
*/
private void deleteReversionLib() {
try {
} catch (Exception e) {
// ignore; this is best effort
}
}
/**
* Gets the directory that will be used to store the bits that this
* reversion operation will replace. The bits are stored in case there
* is a problem with this reversion in which case they can be restored.
*
* @return File directory where the unreverted bits will be stored.
* @throws java.io.IOException if something goes wrong
* @throws org.opends.quicksetup.ApplicationException if something goes wrong
*/
private File getTempBackupDirectory()
throws IOException, ApplicationException
{
if (tempBackupDir == null) {
if (tempBackupDir.exists()) {
}
if (!tempBackupDir.mkdirs()) {
throw new IOException("error creating files backup directory");
}
}
return tempBackupDir;
}
private BuildInformation getFromBuildInformation() {
if (fromBuildInfo == null) {
if (currentProgressStep.ordinal() <
try {
} catch (ApplicationException e) {
}
}
}
return fromBuildInfo;
}
private BuildInformation getArchiveBuildInformation() {
if (archiveBuildInfo == null) {
if (currentProgressStep.ordinal() >
try {
} catch (ApplicationException e) {
"from reverted files", e);
}
} else {
try {
} catch (Exception e) {
"from archived files", e);
}
}
}
return archiveBuildInfo;
}
private Message getFinalSuccessMessage() {
try {
} else {
}
} catch (ApplicationException e) {
}
return txt;
}
/**
* Given the current information, determines whether or not
* a reversion from the current version to the archived version
* is possible. Reversion may not be possible due to 'flag
* day' types of changes to the codebase.
* @throws org.opends.quicksetup.ApplicationException if revertability
* cannot be insured.
*/
private void insureRevertability() throws ApplicationException {
try {
} catch (ApplicationException e) {
"current installation", e);
}
try {
} catch (ApplicationException ae) {
throw ae;
} catch (Exception e) {
"staged installation", e);
}
uo.notifyUser();
if (uo.noServerStartFollowingOperation()) {
// Some issue dicatates that we don't try and restart the server
// after this operation. It may be that the databases are no
// longer readable after the reversion or something equally earth
// shattering.
getUserData().setStartServer(false);
}
} else {
"incomplete build information");
}
}
private Installation getArchiveInstallation()
throws ApplicationException, IOException
{
if (archiveInstallation == null) {
}
return archiveInstallation;
}
if (archiveDir != null) {
// Automatically append the 'filesDir' subdirectory if necessary
if (!archiveDir.getName().
}
}
return archiveDir;
}
}
return stage;
}
}