Search code examples
javajarrunnableauto-updatebootstrapping

Running a jar from within another jar


Re-writing this for clarity before I bounty it:

What I want to do is make a bootstrap loader for a program that is already made in (executable)jar form. This bootstrap program would have three simple goals during it's runtime:

  1. Compare a local xml file for the target program to one that's hosted on a server (to make sure that they are the same version)

  2. If they are not the same version, and the online version is newer, download the newer version.

  3. Re-write the xml file to reflect this change.

  4. Execute the second jar file (launch it as though you launched the executable).

The issue I'm having is with step number 4. I have found myself struggling to find a solid way to launch a jar from within my bootstrap program despite looking at UrlClassLoader and other libraries.

Due to some outside issues, JNLP / Web-start is not an option for this case.

TL;DR: I need to find a way to download / launch a jar from within a jar in order to update a program at the time the bootstrap is run.

Thanks!


Solution

  • I hate having to answer my own question, but in this case I feel like it needs to be done...

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.xpath.XPath;
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpression;
    import javax.xml.xpath.XPathFactory;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpConnectionParams;
    import org.apache.http.params.HttpParams;
    
    import org.w3c.dom.Document;
    
    
    public class updater {
    public static void main(String[] args) throws IOException {
        try{
            DefaultHttpClient httpclient = ClientMaker();
            HttpGet get = new HttpGet("http://encorpops04:8080/Updater-test/Version.xml");
            HttpResponse response = httpclient.execute(get);
            InputStream in = response.getEntity().getContent();
    
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse(in);
    
            //Parse the Xml.
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expr = xpath.compile("//version/number/text()");
            String result = (String) expr.evaluate(doc, XPathConstants.STRING);
            System.out.println(result);
    
            File f = new File(System.getProperty("user.dir")+ "\\Version.xml");
            in = new FileInputStream(f) ;
            doc = builder.parse(in);
            expr=xpath.compile("//version/number/text()");
            String result2 = (String) expr.evaluate(doc, XPathConstants.STRING);
            System.out.println(result2);
    
    
            if(Double.parseDouble(result2) < Double.parseDouble(result)){
                HttpGet get2 = new HttpGet("http://encorpops04:8080/Updater-test/MyOutput.jar"); 
                HttpResponse response2 = httpclient.execute(get2);
                InputStream in2 = response2.getEntity().getContent();
                File f2 = new File("MyOutput.jar");
                OutputStream fos = new FileOutputStream(f2);
                byte buf[] = new byte[1024];
                int len;
                while ((len = in2.read(buf)) > 0) {
                    fos.write(buf, 0, len);
                }
                fos.close();
                in.close();
            }
            System.out.println("cmd.exe /C  javaw -jar"  +System.getProperty("user.dir") + "\\MyOutput.jar");
            Process p = Runtime.getRuntime().exec("cmd.exe /C  javaw -jar "  +System.getProperty("user.dir") + "\\MyOutput.jar");
            p.waitFor();
            p.destroy();
        }catch(Exception e){ e.printStackTrace(); }
    
    
    }
    
    public static DefaultHttpClient ClientMaker() {
        int connectiontimeout = 30000; // 1 second int sockettimeout = 1000;
        HttpParams httpparameters = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpparameters,
                connectiontimeout);
        HttpConnectionParams.setSoTimeout(httpparameters, connectiontimeout);
        DefaultHttpClient httpclient = new DefaultHttpClient(httpparameters);
        return httpclient;
    }
    
    }
    

    Version.xml looks like this:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <version>
        <number>1.0</number>
    </version>
    

    Sidenote- I didn't make version.xml update automatically, you can either edit the number in there to match, or just pull the one that you check against to replace it.