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 }