/* From http://java.sun.com/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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 Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.Attributes;
/**
* Runs a jar application from any url. Usage is 'java JarRunner url [args..]'
* where url is the url of the jar file and args is optional arguments to be
* passed to the application's main method.
*/
public class JarRunner {
public static void main(String[] args) {
if (args.length < 1) {
usage();
}
URL url = null;
try {
url = new URL(args[0]);
} catch (MalformedURLException e) {
fatal("Invalid URL: " + args[0]);
}
// Create the class loader for the application jar file
JarClassLoader cl = new JarClassLoader(url);
// Get the application's main class name
String name = null;
try {
name = cl.getMainClassName();
} catch (IOException e) {
System.err.println("I/O error while loading JAR file:");
e.printStackTrace();
System.exit(1);
}
if (name == null) {
fatal("Specified jar file does not contain a 'Main-Class'"
+ " manifest attribute");
}
// Get arguments for the application
String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
// Invoke application's main class
try {
cl.invokeClass(name, newArgs);
} catch (ClassNotFoundException e) {
fatal("Class not found: " + name);
} catch (NoSuchMethodException e) {
fatal("Class does not define a 'main' method: " + name);
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
System.exit(1);
}
}
private static void fatal(String s) {
System.err.println(s);
System.exit(1);
}
private static void usage() {
fatal("Usage: java JarRunner url [args..]");
}
}
/**
* A class loader for loading jar files, both local and remote.
*/
class JarClassLoader extends URLClassLoader {
private URL url;
/**
* Creates a new JarClassLoader for the specified url.
*
* @param url
* the url of the jar file
*/
public JarClassLoader(URL url) {
super(new URL[] { url });
this.url = url;
}
/**
* Returns the name of the jar file main class, or null if no "Main-Class"
* manifest attributes was defined.
*/
public String getMainClassName() throws IOException {
URL u = new URL("jar", "", url + "!/");
JarURLConnection uc = (JarURLConnection) u.openConnection();
Attributes attr = uc.getMainAttributes();
return attr != null ? attr.getValue(Attributes.Name.MAIN_CLASS) : null;
}
/**
* Invokes the application in this jar file given the name of the main class
* and an array of arguments. The class must define a static method "main"
* which takes an array of String arguemtns and is of return type "void".
*
* @param name
* the name of the main class
* @param args
* the arguments for the application
* @exception ClassNotFoundException
* if the specified class could not be found
* @exception NoSuchMethodException
* if the specified class does not contain a "main" method
* @exception InvocationTargetException
* if the application raised an exception
*/
public void invokeClass(String name, String[] args)
throws ClassNotFoundException, NoSuchMethodException,
InvocationTargetException {
Class c = loadClass(name);
Method m = c.getMethod("main", new Class[] { args.getClass() });
m.setAccessible(true);
int mods = m.getModifiers();
if (m.getReturnType() != void.class || !Modifier.isStatic(mods)
|| !Modifier.isPublic(mods)) {
throw new NoSuchMethodException("main");
}
try {
m.invoke(null, new Object[] { args });
} catch (IllegalAccessException e) {
// This should not happen, as we have disabled access checks
}
}
}
|