Index: C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/AutomatedInstaller.java =================================================================== --- C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/AutomatedInstaller.java (revision 2153) +++ C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/AutomatedInstaller.java (working copy) @@ -73,7 +73,7 @@ /** The result of the installation. */ private boolean result = false; - + /** * Constructing an instance triggers the install. * @@ -90,11 +90,17 @@ loadInstallData(this.idata); // Loads the xml data - this.idata.xmlData = getXMLData(input); + this.idata.xmlData = InstallScriptLocator.locateInstallationScript(inputFilename); + if (this.idata.xmlData == null) + { + throw new InstallScriptNotFoundException(inputFilename); + } + // Loads the langpack this.idata.localeISO3 = this.idata.xmlData.getAttribute("langpack", "eng"); - InputStream in = getClass().getResourceAsStream("/langpacks/" + this.idata.localeISO3 + ".xml"); + InputStream in = getClass().getResourceAsStream( + "/langpacks/" + this.idata.localeISO3 + ".xml"); this.idata.langpack = new LocaleDatabase(in); this.idata.setVariable(ScriptParser.ISO3_LANG, this.idata.localeISO3); @@ -107,7 +113,6 @@ this.panelInstanceCount = new TreeMap(); } - /** * Writes the uninstalldata. * @@ -125,8 +130,7 @@ List files = udata.getUninstalableFilesList(); ZipOutputStream outJar = this.idata.uninstallOutJar; - if (outJar == null) - return true; // it is allowed not to have an installer + if (outJar == null) return true; // it is allowed not to have an installer System.out.println("[ Writing the uninstaller data ... ]"); @@ -166,8 +170,8 @@ execStream.flush(); outJar.closeEntry(); - // *** ADDED code bellow - // Write out additional uninstall data + // *** ADDED code bellow + // Write out additional uninstall data // Do not "kill" the installation if there is a problem // with custom uninstall data. Therefore log it to Debug, // but do not throw. @@ -294,7 +298,7 @@ rootStream.flush(); outJar.closeEntry(); - // *** ADDED to this point + // *** ADDED to this point // Cleanup outJar.flush(); @@ -323,78 +327,79 @@ { // assume that installation will succeed this.result = true; - + // walk the panels in order Iterator panelsIterator = this.idata.panelsOrder.iterator(); while (panelsIterator.hasNext()) { Panel p = (Panel) panelsIterator.next(); - + String praefix = "com.izforge.izpack.panels."; if (p.className.compareTo(".") > -1) // Full qualified class name praefix = ""; if (!OsConstraint.oneMatchesCurrentSystem(p.osConstraints)) continue; - + String panelClassName = p.className; String automationHelperClassName = praefix + panelClassName + "AutomationHelper"; Class automationHelperClass = null; - - Debug.log( "AutomationHelper:" + automationHelperClassName ); + + Debug.log("AutomationHelper:" + automationHelperClassName); // determine if the panel supports automated install try { - - automationHelperClass = (Class) Class.forName(automationHelperClassName); - + + automationHelperClass = (Class) Class + .forName(automationHelperClassName); + } catch (ClassNotFoundException e) { // this is OK - not all panels have/need automation support. - Debug.log( "ClassNotFoundException-skip :" + automationHelperClassName ); + Debug.log("ClassNotFoundException-skip :" + automationHelperClassName); continue; } - + // instantiate the automation logic for the panel PanelAutomation automationHelperInstance = null; if (automationHelperClass != null) { try { - Debug.log( "Instantiate :" + automationHelperClassName ); - automationHelperInstance = automationHelperClass - .newInstance(); + Debug.log("Instantiate :" + automationHelperClassName); + automationHelperInstance = automationHelperClass.newInstance(); } catch (Exception e) { - Debug.log("ERROR: no default constructor for " - + automationHelperClassName + ", skipping..."); + Debug.log("ERROR: no default constructor for " + automationHelperClassName + + ", skipping..."); continue; } } - + // We get the panels root xml markup Vector panelRoots = this.idata.xmlData.getChildrenNamed(panelClassName); int panelRootNo = 0; - + if (this.panelInstanceCount.containsKey(panelClassName)) { // get number of panel instance to process panelRootNo = this.panelInstanceCount.get(panelClassName); } - + XMLElement panelRoot = panelRoots.elementAt(panelRootNo); - + this.panelInstanceCount.put(panelClassName, panelRootNo + 1); - + // execute the installation logic for the current panel, if it has // any: if (automationHelperInstance != null) { try { - Debug.log( "automationHelperInstance.runAutomated :" + automationHelperClassName + " entered." ); - if (! automationHelperInstance.runAutomated(this.idata, panelRoot)) + Debug.log("automationHelperInstance.runAutomated :" + + automationHelperClassName + " entered."); + if (!automationHelperInstance.runAutomated(this.idata, panelRoot)) { // make installation fail instantly this.result = false; @@ -402,24 +407,25 @@ } else { - Debug.log( "automationHelperInstance.runAutomated :" + automationHelperClassName + " successfully done." ); + Debug.log("automationHelperInstance.runAutomated :" + + automationHelperClassName + " successfully done."); } } catch (Exception e) { - Debug.log( "ERROR: automated installation failed for panel " - + panelClassName ); + Debug.log("ERROR: automated installation failed for panel " + + panelClassName); e.printStackTrace(); this.result = false; } - + } - + } - + // this does nothing if the uninstaller was not included writeUninstallData(); - + if (this.result) System.out.println("[ Automated installation done ]"); else @@ -433,7 +439,7 @@ System.out.println("[ Automated installation FAILED! ]"); } finally - { + { // Bye Housekeeper.getInstance().shutDown(this.result ? 0 : 1); } @@ -463,7 +469,7 @@ return rtn; } - + /** * Get the result of the installation. * Index: C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptNotFoundException.java =================================================================== --- C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptNotFoundException.java (revision 0) +++ C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptNotFoundException.java (revision 0) @@ -0,0 +1,18 @@ +package com.izforge.izpack.installer; + +/** + * Thrown by the automated installer when it could not find the installation + * script. + * + * @author J. Chris Folsom + * @see com.izforge.izpack.installer.AutomatedInstaller + */ +public class InstallScriptNotFoundException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public InstallScriptNotFoundException(String message) + { + super(message); + } +} \ No newline at end of file Index: C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/HTTPInstallScriptLocator.java =================================================================== --- C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/HTTPInstallScriptLocator.java (revision 0) +++ C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/HTTPInstallScriptLocator.java (revision 0) @@ -0,0 +1,41 @@ +package com.izforge.izpack.installer; + +import java.io.IOException; + +import net.n3.nanoxml.XMLElement; +import net.n3.nanoxml.XMLException; + +/** + * Attempts to download an install script using HTTP or HTTPS. + * + * @author J. Chris Folsom + * @see com.izforge.izpack.installer.AutomatedInstaller + */ +public class HTTPInstallScriptLocator extends InstallScriptLocator +{ + /* + * (non-Javadoc) + * + * @see com.izforge.izpack.installer.InstallScriptLocator#getInstallationScriptData(java.lang.String) + */ + public XMLElement getInstallationScript(String installationScript) + throws IOException, XMLException + { + XMLElement results = null; + + if (installationScript.startsWith("http://") + || installationScript.startsWith("https://")) + { + StringBuffer msg = new StringBuffer(); + msg.append("[ Attempting to download install script from: "); + msg.append(installationScript); + msg.append(" ]"); + + System.out.println(msg); + + // TODO download using java.net or commons http client + } + + return results; + } +} \ No newline at end of file Index: C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptLocator.java =================================================================== --- C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptLocator.java (revision 0) +++ C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/InstallScriptLocator.java (revision 0) @@ -0,0 +1,142 @@ +package com.izforge.izpack.installer; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + +import net.n3.nanoxml.NonValidator; +import net.n3.nanoxml.StdXMLParser; +import net.n3.nanoxml.StdXMLReader; +import net.n3.nanoxml.XMLBuilderFactory; +import net.n3.nanoxml.XMLElement; +import net.n3.nanoxml.XMLException; + +/** + * Abstract class for retrieving installation scripts for the + * AutomatedInstaller. + * + * @author J. Chris Folsom + * + * @see com.izforge.izpack.installer.AutomatedInstaller + */ +public abstract class InstallScriptLocator +{ + private static Collection locators; + + static + { + locators = new ArrayList(2); + + registerLocator(new HTTPInstallScriptLocator()); + registerLocator(new LocalInstallScriptLocator()); + } + + /** + * Get the list of currently registered locators. + * + * @return The list of currently registered locators. + */ + public static Collection getLocators() + { + return Collections.unmodifiableCollection(locators); + } + + /** + * Register a locator. + * + * @param locator The locator to add. + */ + public static synchronized void registerLocator(InstallScriptLocator locator) + { + locators.add(locator); + } + + /** + * Remove a registered locator. + * + * @param locator The locator to remove. + * @return true If a locator was removed. + */ + public static synchronized boolean unregisterLocator( + InstallScriptLocator locator) + { + return locators.remove(locator); + } + + /** + * Load an installation script. + * + * @param installationScript + * The name of the script to load. + * @return The XMLElement representing the installation script. + * @throws IOException + * If there is a problem loading the script. + * @throws XMLException + * If there is a problem parsing the script. + */ + public abstract XMLElement getInstallationScript( + String installationScript) throws IOException, XMLException; + + /** + * Parse the stream and return an XML element representing the installation + * script. + * + * @param in + * The stream to parse. + * @return An XML representation of the stream. + * + * @throws IOException + * If an error occurs while reading from the stream. + * @throws XMLException + * If an error occurs while attempting to parse the XML + * document. + */ + public XMLElement getInstallationScript(InputStream in) throws IOException, + XMLException + { + // Initializes the parser + StdXMLParser parser = new StdXMLParser(); + parser.setBuilder(XMLBuilderFactory.createXMLBuilder()); + parser.setReader(new StdXMLReader(in)); + parser.setValidator(new NonValidator()); + + XMLElement rtn = (XMLElement) parser.parse(); + in.close(); + + return rtn; + } + + /** + * Find the installation script using the built in locators. + * + * @param installationScript + * The installation script location + * @return An installation script or null if none of the registered locators + * could find the script. + * @throws IOException + * If an error occurs while reading from the stream. + * @throws XMLException + * If an error occurs while attempting to parse the XML + * document. + */ + public static XMLElement locateInstallationScript(String installationScript) + throws IOException, XMLException + { + XMLElement results = null; + + for (Iterator i = locators.iterator(); i.hasNext();) + { + InstallScriptLocator locator = (InstallScriptLocator) i.next(); + + results = locator.getInstallationScript(installationScript); + + if (results != null) + break; + } + + return results; + } +} \ No newline at end of file Index: C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/LocalInstallScriptLocator.java =================================================================== --- C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/LocalInstallScriptLocator.java (revision 0) +++ C:/Documents and Settings/folsom-1/workspace/IzPack/src/lib/com/izforge/izpack/installer/LocalInstallScriptLocator.java (revision 0) @@ -0,0 +1,119 @@ +package com.izforge.izpack.installer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; + +import net.n3.nanoxml.XMLElement; +import net.n3.nanoxml.XMLException; + +/** + * This class attempts to load an installation script from a resource on the + * local machine. It will try to locate an installation script based on the name + * given in the following order: + * + *
+ *
+ * + *
    + *
  1. As a file.
  2. + *
  3. As a resource on the classpath.
  4. + *
+ * + * @author J. Chris Folsom + * + * @see com.izforge.izpack.installer.AutomatedInstaller + */ +public class LocalInstallScriptLocator extends InstallScriptLocator +{ + /* + * (non-Javadoc) + * + * @see com.izforge.izpack.installer.InstallationScriptLocator#getInstallationScriptData() + */ + public XMLElement getInstallationScript(String installationScript) throws IOException, XMLException + { + //TODO i18n + XMLElement installationData = null; + + //Try to load from file first + File input = new File(installationScript); + + if (input.exists()) + { + StringBuffer msg = new StringBuffer(); + msg.append("[ Loading file: "); + msg.append(installationScript); + msg.append(" ]"); + + System.out.println(msg.toString()); + + installationData = this.getInstallationScript(new FileInputStream( + input)); + } else //Try to load from classpath + { + StringBuffer msg = new StringBuffer(); + msg.append("[ Could not find file: "); + msg.append(installationScript); + msg.append(" ]"); + + System.out.println(msg); + System.out.println("[ Attempting to load from classpath... ]"); + + Thread currentThread = Thread.currentThread(); + + ClassLoader classLoader = currentThread.getContextClassLoader(); + + //Build a list of matching resources on the classpath + List urls = new LinkedList(); + for (Enumeration resources = classLoader + .getResources(installationScript); resources.hasMoreElements();) + { + URL resourceURL = (URL) resources.nextElement(); + + msg = new StringBuffer(); + msg.append("[ Found resource: "); + msg.append(resourceURL); + msg.append(" ]"); + + System.out.println(msg); + + urls.add(resourceURL); + } + + if (urls.size() < 1) + { + msg = new StringBuffer(); + msg.append("[ Could not find classpath resource: "); + msg.append(installationScript); + msg.append("]"); + + System.out.println(msg); + } else + { + if (urls.size() > 1) + { + System.out.println("[ Resource is ambiguous! ]"); + } + + URL configurationURL = (URL) urls.get(0); + + msg = new StringBuffer(); + msg.append("[ Loading installation script: "); + msg.append(configurationURL); + msg.append(" ]"); + + System.out.println(msg); + + installationData = this.getInstallationScript(configurationURL + .openStream()); + } + } + + return installationData; + } +} \ No newline at end of file