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    }