001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License. 
016 *
017 */
018package org.apache.bcel.util;
019
020import java.lang.reflect.Method;
021import java.lang.reflect.Modifier;
022
023/**
024 * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader
025 * to modify/generate classes as they're requested. You can take this as a template
026 * for your own applications.<br>
027 * Call this wrapper with
028 * <pre>java org.apache.bcel.util.JavaWrapper &lt;real.class.name&gt; [arguments]</pre>
029 * <p>
030 * To use your own class loader you can set the "bcel.classloader" system property
031 * which defaults to "org.apache.bcel.util.ClassLoader", e.g., with
032 * <pre>java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader &lt;real.class.name&gt; [arguments]</pre>
033 * </p>
034 *
035 * @version $Id: JavaWrapper.html 898356 2014-02-18 05:44:40Z ggregory $
036 * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
037 * @see ClassLoader
038 */
039public class JavaWrapper {
040
041    private java.lang.ClassLoader loader;
042
043
044    private static java.lang.ClassLoader getClassLoader() {
045        String s = System.getProperty("bcel.classloader");
046        if ((s == null) || "".equals(s)) {
047            s = "org.apache.bcel.util.ClassLoader";
048        }
049        try {
050            return (java.lang.ClassLoader) Class.forName(s).newInstance();
051        } catch (Exception e) {
052            throw new RuntimeException(e.toString(), e);
053        }
054    }
055
056
057    public JavaWrapper(java.lang.ClassLoader loader) {
058        this.loader = loader;
059    }
060
061
062    public JavaWrapper() {
063        this(getClassLoader());
064    }
065
066
067    /** Runs the main method of the given class with the arguments passed in argv
068     *
069     * @param class_name the fully qualified class name
070     * @param argv the arguments just as you would pass them directly
071     */
072    public void runMain( String class_name, String[] argv ) throws ClassNotFoundException {
073        Class<?> cl = loader.loadClass(class_name);
074        Method method = null;
075        try {
076            method = cl.getMethod("main", new Class[] {
077                argv.getClass()
078            });
079            /* Method main is sane ?
080             */
081            int m = method.getModifiers();
082            Class<?> r = method.getReturnType();
083            if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m)
084                    || (r != Void.TYPE)) {
085                throw new NoSuchMethodException();
086            }
087        } catch (NoSuchMethodException no) {
088            System.out.println("In class " + class_name
089                    + ": public static void main(String[] argv) is not defined");
090            return;
091        }
092        try {
093            method.invoke(null, new Object[] {
094                argv
095            });
096        } catch (Exception ex) {
097            ex.printStackTrace();
098        }
099    }
100
101
102    /** Default main method used as wrapper, expects the fully qualified class name
103     * of the real class as the first argument.
104     */
105    public static void main( String[] argv ) throws Exception {
106        /* Expects class name as first argument, other arguments are by-passed.
107         */
108        if (argv.length == 0) {
109            System.out.println("Missing class name.");
110            return;
111        }
112        String class_name = argv[0];
113        String[] new_argv = new String[argv.length - 1];
114        System.arraycopy(argv, 1, new_argv, 0, new_argv.length);
115        JavaWrapper wrapper = new JavaWrapper();
116        wrapper.runMain(class_name, new_argv);
117    }
118}