/*
* $RCSfile: AbstractInstall.java,v $
* @modification $Date: 2005/05/12 22:13:02 $
* @version $Id: AbstractInstall.java,v 1.18 2005/05/12 22:13:02 deniger Exp $
*
*/
/**
* This is an abstract base class that defines some methods an
* installer/uninstaller need to implement. It has some concrete helper methods.
*
* Both the Setup and the Uninstall class is a kind of installation.
*
* This first version have some methods copied from the Setup class that should
* not be in this class. The goal is to create a more clean class.
*
* @see com.memoire.vainstall.Setup
* @see com.memoire.vainstall.Uninstall
*
* @author Henrik Falk
* @version $Id: AbstractInstall.java,v 1.18 2005/05/12 22:13:02 deniger Exp $
*/
package com.memoire.vainstall;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.util.Arrays;
import java.util.Vector;
public abstract class AbstractInstall {
public static final int CANCEL = 0x01;
public static final int BACK = 0x02;
public static final int NEXT = 0x04;
public static final int FINISH = 0x08;
public static final boolean IS_WIN = System.getProperty("os.name")
.startsWith("Win");
//MAC_OS X
public static final boolean IS_MAC_OS_X = System.getProperty("os.name")
.startsWith("Mac OS X");
public static final boolean IS_MAC = System.getProperty("os.name")
.startsWith("Mac")
&& !IS_MAC_OS_X;
public static final boolean IS_UNIX = !IS_WIN && !IS_MAC || IS_MAC_OS_X;
public static final boolean IS_ROOT = (IS_UNIX && "root".equals(System
.getProperty("user.name")))
|| (IS_WIN && new File("C:\\").canWrite());
protected VAStep step_;
protected boolean dirty_;
/**
*
*/
protected VAStepFactory ui_;
/**
*
*/
protected VAStats stats_;
protected static final int LANGUAGE = 0;
protected static final int START = 1;
protected static final int WELCOME = 2;
protected static final int LICENSE = 3;
protected static final int README = 4;
protected static final int LICENSE_KEY = 5;
protected static final int UPGRADE = 6;
protected static final int DIRECTORY = 7;
protected static final int INSTALL = 8;
protected static final int SHORTCUTS = 9;
protected static final int END = 10;
protected int state_;
protected int actionEnabled_;
protected File sharedDir_;
protected File classloaderTempDir_;
protected UpgradeInfo uInfo_;
/**
* The current language that is choosen
*/
protected String language;
public AbstractInstall() {
super();
if (IS_WIN) {
extractJniDll("/JNIWinShortcut.dll",true);
extractJniDll("/ICE_JNIRegistry.dll",false);
}
actionEnabled_ = 0;
stats_ = new VAStats();
sharedDir_ = null;
uInfo_ = null;
dirty_ = false;
state_ = START;
}
/**
* This method deletes all files in a directory and updates failures to the
* 'stats_' variable This method should moved to a support class and thats
* why I made it public.
*
* @author Henrik Falk
* @param dir
* File Directory to delete
* @return void
*/
public void deleteDirRecursive(File dir) {
// verify parameter
if (dir == null || dir.exists() == false) {
return;
}
// get list of files in directory if any
File[] filelist = dir.listFiles();
for (int i = 0; i < filelist.length; i++) {
boolean isdir = filelist[i].isDirectory();
if (isdir == true) {
// delete everything in the directory
deleteDirRecursive(filelist[i]);
} else {
// delete the file
if (filelist[i].delete() == false) {
stats_.addFile(filelist[i], VAStats.FAILURE);
filelist[i].deleteOnExit();
VAGlobals.printDebug("F " + filelist[i] + " not deleted");
} // endif
} // endif
} // endfor
// delete the directory
if (dir.delete() == false) {
dir.deleteOnExit();
stats_.addDirectory(dir, VAStats.FAILURE);
VAGlobals.printDebug("D " + dir + " not deleted");
} // endif
}
public boolean cleanShortcuts(File shortcutLogDir) throws IOException {
boolean value;
File logFile;
Vector directories;
logFile = new File(shortcutLogDir, "shortcuts.vai");
value = false;
if (logFile.exists()) {
value = true;
directories = deleteFiles(logFile);
deleteDirectories(directories);
}
return value;
}
protected Vector deleteFiles(File log) throws IOException {
Vector dirs = new Vector();
LineNumberReader logReader = new LineNumberReader(new FileReader(log));
String line = logReader.readLine();
while (line != null) {
File del = new File(line);
if (del.isDirectory()) {
dirs.add(del);
} else if (del.delete()) {
stats_.addFile(del, VAStats.SUCCESS);
} else {
del.deleteOnExit();
stats_.addFile(del, VAStats.FAILURE);
VAGlobals.printDebug("F " + del + " not deleted");
}
line = logReader.readLine();
}
logReader.close();
return dirs;
}
protected void deleteDirectories(Vector directories) throws IOException {
Object[] dirs = directories.toArray();
Arrays.sort(dirs);
for (int i = dirs.length - 1; i >= 0; i--) {
File del = (File) dirs[i];
if (del.delete()) {
stats_.addDirectory(del, VAStats.SUCCESS);
} else {
del.deleteOnExit();
stats_.addDirectory(del, VAStats.FAILURE);
VAGlobals.printDebug("D " + del + " not deleted");
}
}
}
private void restoreLastVersion(File sharedDir, UpgradeInfo uInfo) {
File destPath = new File(sharedDir, "vai_" + VAGlobals.APP_NAME + "_"
+ VAGlobals.APP_VERSION);
// eliminate new install info
if (destPath.exists())
deleteDirRecursive(destPath);
if ((uInfo == null) || (!uInfo.upgrade))
return;
File lastVerPath = new File(sharedDir, "vai_" + VAGlobals.APP_NAME
+ "_" + uInfo.lastVersion());
// restore old install info if versions are the same
if (destPath.equals(lastVerPath)) {
lastVerPath = new File(destPath.getAbsolutePath() + ".bak");
lastVerPath.renameTo(destPath);
}
}
public void setActionEnabled(int a) {
actionEnabled_ = a;
ui_.setActionEnabled(a);
}
public void cancel() {
cleanInstall(sharedDir_, uInfo_);
quit();
}
protected void cleanInstall(File sharedDir, UpgradeInfo uInfo) {
if ((!dirty_) || (sharedDir == null) || (!sharedDir.exists())) {
VAGlobals.printDebug("No cleaning needed");
return;
}
File uninstDir = new File(sharedDir.getAbsolutePath() + File.separator
+ "vai_" + VAGlobals.APP_NAME + "_" + VAGlobals.APP_VERSION);
if (!uninstDir.exists()) {
VAGlobals.printDebug("No cleaning needed");
return;
}
VAGlobals.printDebug("Deleting uninstall files...");
if ((uInfo != null) && (uInfo.upgrade)) {
restoreLastVersion(sharedDir, uInfo);
} else {
// delete all in the uninstall directory
deleteDirRecursive(uninstDir);
}
VAGlobals.printDebug("All cleaned OK");
}
protected void checkUpgrade(File sharedDir, UpgradeInfo uInfo) {
VAUpgradeStep step = (VAUpgradeStep) step_;
step.status(VAGlobals.i18n("Setup_LookPreviousVersions"));
ui_.uiSleep(2000);
checkVersions(sharedDir, uInfo);
if (uInfo.upgrade) {
VAGlobals.printDebug("Previous version found : "
+ uInfo.lastVersion());
step.status(VAGlobals.i18n("Setup_PreviousVersionFound") + " "
+ uInfo.lastVersion());
step.version(uInfo.lastVersion());
step.directory(uInfo.lastPath().getAbsolutePath());
} else {
VAGlobals.printDebug("No previous version found");
step.status(VAGlobals.i18n("Setup_NoPreviousVersionFound"));
step.version(VAGlobals.i18n("Setup_None"));
step.directory(VAGlobals.i18n("Setup_None"));
}
}
private void checkVersions(File sharedDir, UpgradeInfo uInfo) {
String[] ls = sharedDir.list(new SetupFileFilter("vai_"
+ VAGlobals.APP_NAME + "_", SetupFileFilter.STARTS_WITH,
SetupFileFilter.FILTER));
if ((ls != null) && (ls.length > 0)) {
Arrays.sort(ls);
uInfo.versions = new String[ls.length];
uInfo.paths = new File[ls.length];
for (int i = 0; i < ls.length; i++) {
uInfo.versions[i] = ls[i].substring(ls[i].lastIndexOf('_') + 1);
try {
LineNumberReader log = new LineNumberReader(new FileReader(
new File(new File(sharedDir, ls[i]),
"uninstall.vai")));
String f = log.readLine();
if (f != null)
uInfo.paths[i] = new File(f);
log.close();
} catch (IOException ex) {
System.err.println(ex.getMessage());
uInfo.paths[i] = null;
}
}
}
uInfo.upgrade = (uInfo.lastVersion() != null)
&& (uInfo.lastPath() != null);
}
/**
* @param entryName
* the name of the dll file
* @param isWinShortcut
* true if it's the dll for the JNIWindowsShortcut
*/
private void extractJniDll(String entryName, boolean isWinShortcut) {
try {
InputStream dll = getClass().getResourceAsStream(entryName);
File dllFile = new File(System.getProperty("java.io.tmpdir")
+ File.separator
+ entryName.substring(entryName.lastIndexOf('/') + 1));
VAGlobals.printDebug("Extracting library " + dllFile);
System.out.println(dllFile.getAbsolutePath());
FileOutputStream dllout = new FileOutputStream(dllFile);
byte[] data = new byte[512];
int read = dll.read(data, 0, data.length);
while (read > 0) {
dllout.write(data, 0, read);
read = dll.read(data, 0, data.length);
}
dll.close();
dllout.close();
VAGlobals.printDebug(" library extracted");
if (isWinShortcut) {
JNIWindowsShortcut.LIB_NAME = dllFile.getAbsolutePath();;
} else
VAGlobals.JNI_DLL_FILE = dllFile.getAbsolutePath();
dllFile.deleteOnExit();
} catch (IOException e) {
exitOnError(e);
}
}
protected void exitOnError(Throwable e) {
if (ui_ != null)
ui_.showFatalError(e);
else
e.printStackTrace();
deleteTmpFile();
System.exit(1);
}
private void deleteTmpFile(){
if (classloaderTempDir_ != null) {
VAGlobals.printDebug("Temporary directory deleted: "
+ classloaderTempDir_.getAbsolutePath());
deleteDirRecursive(classloaderTempDir_);
}
}
protected void quit() {
// delete classloader
//File classloaderDir = new
// File(System.getProperty("user.dir")+File.separator+"com");
deleteTmpFile();
ui_ = null;
VAGlobals.printDebug("Exiting");
System.exit(0);
}
/**
* The next step in an install/uninstall
*
* @return void
*/
public abstract void nextStep();
/**
* A previous step in an install/uninstall
*
* @return void
*/
public abstract void previousStep();
/**
* A redo step in an install/uninstall This is conceptually an 'again' step.
* Only 'tui' uses the redo feature at the moment.
*
* @return void
*/
public abstract void redoStep();
}
|