package net.sourceforge.cruisecontrol.distributed.core.jnlputil;
import org.apache.log4j.Logger;
import javax.jnlp.ExtensionInstallerService;
import javax.jnlp.ServiceManager;
import javax.jnlp.UnavailableServiceException;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import net.sourceforge.cruisecontrol.builders.AntScript;
/**
* Installs {@link AntScript#LIBNAME_PROGRESS_LOGGER cruisecontrol-antprogresslogger.jar} (required by AntBuilder)
* in webstart environment of webstart deployed Build Agents.
*
* @author Dan Rollo
* Date: Sep 9, 2007
* Time: 12:13:06 AM
*/
public final class AntProgressLoggerInstaller {
// @todo Add installer support for logging via Log4J
private static final Logger LOG = Logger.getLogger(AntProgressLoggerInstaller.class);
// @todo Add installer support for logging via Log4J
private static void log(final String msg) {
System.out.println(msg);
LOG.info(msg);
}
private static void log(final String msg, final Throwable thrown) {
System.out.println(msg);
thrown.printStackTrace();
LOG.info(msg, thrown);
}
private static final String JNLP_MUFFIN_ANT_PROGRESS_LOGGER_PATH = "JNLPMuffinAntProgressLoggerPath";
private AntProgressLoggerInstaller() {
}
public static void main(String[] args) {
if ((args.length > 0) && (args[0].equalsIgnoreCase("install"))) {
log("Installing Ant Progress Logger...");
install();
} else {
log("Installer called without install arg, uninstalling Ant Progress Logger...");
uninstall();
}
}
private static void installTo(final URL urlResource, final File toFile) {
final InputStream is;
try {
is = urlResource.openStream();
} catch (IOException e) {
final RuntimeException re = new RuntimeException("I/O Exception reading url: " + urlResource + ", " + e, e);
log(re.getMessage(), e);
throw re;
}
try {
toFile.createNewFile();
} catch (IOException e) {
final RuntimeException re = new RuntimeException("I/O Exception creating file: "
+ toFile.getAbsolutePath() + ", " + e, e);
log(re.getMessage(), e);
throw re;
}
final OutputStream os;
byte[] buf = new byte[255];
try {
os = new FileOutputStream(toFile);
try {
int len;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
} finally {
os.close();
}
} catch (IOException e) {
final RuntimeException re = new RuntimeException("I/O Exception writing file: "
+ toFile.getAbsolutePath() + ", " + e, e);
log(re.getMessage(), e);
throw re;
} finally {
try {
is.close();
} catch (IOException ioe) {
// ignore
}
}
}
private static File getExtPath(final ExtensionInstallerService extensionInstallerService) {
// get service recommended install dir (with jar file name appended).
final String path = extensionInstallerService.getInstallPath();
return new File(path, AntScript.LIBNAME_PROGRESS_LOGGER);
}
/**
* Attempt to fix possible race condition when creating directories on
* WinXP, also Windows2000. If the mkdirs does not work, wait a little and
* try again.
* Taken from Ant Mkdir taskdef.
*
* @param f the path for which directories are to be created
* @return <code>true</code> if and only if the directory was created,
* along with all necessary parent directories; <code>false</code>
* otherwise
*/
private static boolean doMkDirs(File f) {
// @todo Remove this method if CruiseControl jar is ever added to installer classpath
if (!f.mkdirs()) {
try {
Thread.sleep(10);
return f.mkdirs();
} catch (InterruptedException ex) {
return f.mkdirs();
}
}
return true;
}
private static void install() {
final ExtensionInstallerService extensionInstallerService = getExtensionInstallerService();
// get and create install dir
final File extPath = getExtPath(extensionInstallerService);
if (extPath.exists()) {
extPath.delete();
} else {
final File extDir = extPath.getParentFile();
if (!extDir.exists()) {
// @todo Replace if CruiseControl jar is ever added to installer classpath
//if (!Util.doMkDirs(extDir)) {
if (!doMkDirs(extDir)) {
throw new RuntimeException("Error creating install dir: " + extDir.getAbsolutePath());
}
}
}
log("extPath: " + extPath.getAbsolutePath());
// Write the native library
final URL u = AntProgressLoggerInstaller.class.getClassLoader().getResource(AntScript.LIBNAME_PROGRESS_LOGGER);
log("url: " + u);
try {
installTo(u, extPath);
} catch (Exception e) {
final RuntimeException re = new RuntimeException("Exception install url: " + u
+ " to file: " + extPath.getAbsolutePath() + e, e);
log(re.getMessage(), e);
extensionInstallerService.installFailed();
throw re;
}
// store location of jar in JNLP muffin
JNLPServiceUtil.save(JNLP_MUFFIN_ANT_PROGRESS_LOGGER_PATH, extPath.getAbsolutePath());
extensionInstallerService.installSucceeded(false);
log("End of Installation.");
}
private static void uninstall() {
final ExtensionInstallerService extensionInstallerService = getExtensionInstallerService();
final File extPath = getExtPath(extensionInstallerService);
if (!extPath.exists()) {
log("Doing nothing because expected file to remove does not exist: " + extPath.getAbsolutePath());
return;
}
extPath.delete();
extPath.deleteOnExit();
log("Deleted file: " + extPath.getAbsolutePath());
extPath.getParentFile().delete();
extPath.getParentFile().deleteOnExit();
log("Deleted parent dir: " + extPath.getParentFile().getAbsolutePath());
JNLPServiceUtil.delete(JNLP_MUFFIN_ANT_PROGRESS_LOGGER_PATH);
log("Unistall completed.");
}
private static ExtensionInstallerService getExtensionInstallerService() {
final ExtensionInstallerService extensionInstallerService;
try {
extensionInstallerService
= (ExtensionInstallerService) ServiceManager.lookup("javax.jnlp.ExtensionInstallerService");
} catch (UnavailableServiceException e) {
final RuntimeException re = new RuntimeException("Error getting jnlp install service.", e);
log(re.getMessage(), e);
throw re;
}
return extensionInstallerService;
}
public static String getJNLPMuffinAntProgressLoggerPath() {
return JNLPServiceUtil.load(JNLP_MUFFIN_ANT_PROGRESS_LOGGER_PATH);
}
}