I have a jar file (say app.jar) in a certain location available as a file/stream from an http server. The problem is that app.jar is itself a frequently updated jar file being
OK. Before I put the link to the szegedi article into my previous answer (honest), I prototyped a jar-launcher that could handle URLs. Like the author said, it wasn't hard, probably isn't complete. Attached below. I think this is 1/3 of what you need. Your user says (something like):
java -jar load.jar http://localhost:8080/app.jar
load.jar has two roles: (1) invoke JarLauncher (below) as its main class (2) serve app.jar on a localhost port (before invoking the JarLauncher). load.jar therefore reads its arguments to figure out which app to run.
Finally (the hard bit): you have to make URLClassLoader not hit the temporary disk. As the szegedi article said, that isn't easy. Alternatively, you can write your own network-aware classloader that doesn't disk-cache, like my first suggestion loading the URL into memory as a byte-stream from a URL connection, decoding it as a JarInputStream, and satisfying calls to loadClass/findResource from that in-memory stream.
You have quite a lot of work ahead of you. Good luck.
Apologies for the size of the license text, but it lets you do what you like with the code as long as you don't blame me (BSD).
--simon.
/* * One-JAR(TM) (http://www.simontuffs.com/one-jar). Copyright (c) 2004-2010, * P. Simon Tuffs (simon@simontuffs.com). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of P. Simon Tuffs, nor the names of any contributors, * nor the name One-JAR may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Including this file inside the built One-JAR file conforms with these terms. */ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.jar.JarInputStream; /** * Programmatic equivalent of what happens when you say "java -jar". * A better solution to debugging/running Jar files inside an IDE. * @author simon * */ public class JarLauncher { public static URL getURL(String string) throws MalformedURLException { try { return new URL(string); } catch (MalformedURLException x) { return new URL("file:" + string); } } public static void main(String args[]) throws Exception { if (args.length < 1) { System.out.println("Usage: java [-Dkey=value...] JarLauncher "); System.exit(1); } String jar = args[0]; args = Arrays.copyOfRange(args, 1, args.length); List urls = new ArrayList (); // Main jar on the URL path. // Dig out the main class. urls.add(getURL(jar)); URL jarurl = urls.get(0); JarInputStream jis = new JarInputStream(jarurl.openStream()); String main = jis.getManifest().getMainAttributes().getValue("Main-Class"); // OK to split on space, because embedded space is %20 String classpaths[] = jis.getManifest().getMainAttributes().getValue("Class-Path").split(" "); for (String classpath: classpaths) { urls.add(getURL(classpath)); } URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[0])); Class> cls = loader.loadClass(main); Thread.currentThread().setContextClassLoader(loader); Method m = cls.getMethod("main", new Class[]{new String[0].getClass()}); m.invoke(null, new Object[]{args}); } }