从另一个罐子里运行一个罐子

时间:2012-11-12 21:21:34

标签: java jar runnable auto-update bootstrapping

为了清晰起见,重新写这个是为了清楚:

我想要做的是为已经以(可执行的)jar形式制作的程序创建一个bootstrap加载器。这个引导程序在运行时会有三个简单的目标:

  1. 将目标程序的本地xml文件与托管在服务器上的文件进行比较(以确保它们是相同的版本)

  2. 如果版本不同,在线版本较新,请下载较新版本。

  3. 重写xml文件以反映此更改。

  4. 执行第二个jar文件(就像启动可执行文件一样启动它)。

  5. 我遇到的问题是第4步。我发现自己很难找到一种可靠的方法从我的引导程序中启动一个jar,尽管你看过UrlClassLoader和其他库。

    由于一些外部问题,JNLP / Web-start不适用于此案例。

    TL; DR:我需要找到一种从jar中下载/启动jar的方法,以便在运行bootstrap时更新程序。

    谢谢!

4 个答案:

答案 0 :(得分:0)

调用Runtime.getRuntime()。EXEC()

如果您的MyApp.jar有任何输出,那么这里有一些陷阱。

检查文档以了解如何正确使用exec的详细信息...

http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html

看到这篇关于一些陷阱的SO帖子......

Java Runtime.exec()

答案 1 :(得分:0)

当您说'执行新jar'时,您的意思是启动独立应用程序吗? 一种可能性是简单地从Updater.jar引导逻辑执行一个新的Java进程,然后退出自己。

答案 2 :(得分:0)

换句话说,您希望实现可自我更新的应用程序。这是可能的,甚至不是那么困难。

您的程序应设计为2个部分。加载器(和更新程序)和业务逻辑。 Loader应该使用单独的类加载器启动业务逻辑。您可以使用UrlClassLoader。加载程序将转到在线服务并检查版本。如果需要,它将创建URLConnection,下载新的jar并将其存储在filesytem中的某个位置(例如,在用户主目录中)。然后它将使用已经提到的类加载器运行业务逻辑,该加载器从刚刚下载的jar文件加载类。

这实际上模仿了JNLP的行为。

答案 3 :(得分:0)

我讨厌回答我自己的问题,但在这种情况下,我觉得有必要这样做......

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如下所示:

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

Sidenote-我没有自动更新version.xml,你可以编辑那里的数字来匹配,或者只是拉一下你检查的数字来替换它。