001 package net.sourceforge.retroweaver;
002
003 import java.io.File;
004 import java.io.IOException;
005 import java.lang.reflect.InvocationTargetException;
006 import java.lang.reflect.Method;
007 import java.lang.reflect.Modifier;
008 import java.net.JarURLConnection;
009 import java.net.URL;
010 import java.util.jar.Attributes;
011
012 public class WeaveRunner {
013
014 private final RetroWeaverClassLoader classLoader;
015
016 public WeaveRunner(String classPath) {
017 // use the current JVM version as the target
018 String version = System.getProperty("java.version");
019 int target;
020 switch (version.charAt(2)) {
021 case '2':
022 target = Weaver.VERSION_1_2;
023 break;
024 case '3':
025 target = Weaver.VERSION_1_3;
026 break;
027 case '4':
028 target = Weaver.VERSION_1_4;
029 break;
030 case '5':
031 target = Weaver.VERSION_1_5;
032 break;
033 default:
034 throw new RetroWeaverException("Unsupported JVM version: " + version);
035 }
036 final RetroWeaver retroWeaver = new RetroWeaver(target);
037 retroWeaver.setLazy(true);
038
039 classLoader = new RetroWeaverClassLoader();
040 classLoader.setClassPath(classPath);
041 classLoader.setWeaver(retroWeaver);
042 }
043
044 public void run(String className, String[] args)
045 throws ClassNotFoundException, NoSuchMethodException {
046 Class clazz = classLoader.loadClass(className);
047
048 Method m = clazz.getMethod("main", new Class[] { args.getClass() });
049 m.setAccessible(true);
050 int mods = m.getModifiers();
051 if (m.getReturnType() != void.class || !Modifier.isStatic(mods)
052 || !Modifier.isPublic(mods)) {
053 throw new NoSuchMethodException("main");
054 }
055 try {
056 m.invoke(null, new Object[] { args });
057 } catch (IllegalAccessException e) {
058 } catch (InvocationTargetException ite) {
059 throw new RetroWeaverException(ite);
060 }
061 }
062
063 public void executeJar(String jarFileName, String[] args)
064 throws ClassNotFoundException, NoSuchMethodException {
065 // add jar to class path
066 classLoader.addJarClassPathElement(jarFileName);
067
068 // get class name from MANIFEST
069 String className = null;
070 try {
071 URL u = new URL("jar:file:" + jarFileName + "!/");
072 JarURLConnection uc = (JarURLConnection) u.openConnection();
073 Attributes attr = uc.getMainAttributes();
074
075 if (attr != null) {
076 className = attr.getValue(Attributes.Name.MAIN_CLASS);
077 }
078 } catch (IOException ioe) {
079 }
080
081 if (className == null) {
082 System.err.println("No " + Attributes.Name.MAIN_CLASS + " specified in jar file " + jarFileName); // NOPMD by xlv
083 } else {
084 run(className, args);
085 }
086 }
087
088 public static void main(String[] args) throws ClassNotFoundException,
089 NoSuchMethodException {
090 String classPath = null;
091 String mainClass = null;
092 String jarFileName = null;
093
094 int argIndex = 0;
095 while (argIndex < args.length) {
096 String command = args[argIndex++];
097
098 if (command.equals("-cp") || command.equals("-classpath")) {
099 classPath = args[argIndex++];
100 } else if (command.equals("-jar")) {
101 jarFileName = args[argIndex++];
102 break;
103 } else {
104 mainClass = command;
105 break;
106 }
107 }
108 if (jarFileName == null) {
109 String errorMsg = null;
110
111 if (classPath == null) {
112 errorMsg = "Missing class path";
113 }
114 if (mainClass == null) {
115 errorMsg = "Missing main class or jar option";
116 }
117
118 if (errorMsg != null) {
119 System.out.println(errorMsg); // NOPMD by xlv
120 System.out.println(); // NOPMD by xlv
121 usage();
122 return;
123 }
124 }
125
126 String[] realArgs = new String[args.length - argIndex];
127 System.arraycopy(args, argIndex, realArgs, 0, args.length - argIndex);
128
129 WeaveRunner runner = new WeaveRunner(classPath);
130
131 if (jarFileName != null) {
132 runner.executeJar(jarFileName, realArgs);
133 } else {
134 runner.run(mainClass, realArgs);
135 }
136 }
137
138 private static final String nl = System.getProperty("line.separator");
139
140 private static void usage() {
141 String msg = "Usage: WeaveRunner [-options] class [args...]"
142 + nl
143 + "\t\t(to execute a class)"
144 + nl
145 + "\tor WeaveRunner [-options] -jar jarfile [args...]"
146 + nl
147 + "\t\t(to execute a jar file)"
148 + nl
149 + nl
150 + "where options include:"
151 + nl
152 + "\t-cp <class search path of directories and zip/jar files>"
153 + nl
154 + "\t-classpath <class search path of directories and zip/jar files>"
155 + nl + "\t\tA " + File.pathSeparatorChar
156 + " separated list of directories, JAR archives," + nl
157 + "\t\tand ZIP archives to search for class files." + nl;
158 System.out.println(msg); // NOPMD by xlv
159 }
160
161 }