View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.util;
20  
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Modifier;
23  
24  import org.apache.commons.lang3.StringUtils;
25  
26  /**
27   * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader to modify/generate classes as they're
28   * requested. You can take this as a template for your own applications.
29   * <p>
30   * Call this wrapper with:
31   * </p>
32   *
33   * <pre>
34   * java org.apache.bcel.util.JavaWrapper &lt;real.class.name&gt; [arguments]
35   * </pre>
36   * <p>
37   * To use your own class loader you can set the "bcel.classloader" system property.
38   * </p>
39   *
40   * <pre>
41   * java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader &lt;real.class.name&gt; [arguments]
42   * </pre>
43   *
44   * @see ClassLoader
45   */
46  public class JavaWrapper {
47  
48      private static java.lang.ClassLoader getClassLoader() {
49          final String s = System.getProperty("bcel.classloader");
50          if (StringUtils.isEmpty(s)) {
51              throw new IllegalStateException("The property 'bcel.classloader' must be defined");
52          }
53          try {
54              return (java.lang.ClassLoader) Class.forName(s).getConstructor().newInstance();
55          } catch (final Exception e) {
56              throw new IllegalStateException(e.toString(), e);
57          }
58      }
59  
60      /**
61       * Default main method used as wrapper, expects the fully qualified class name of the real class as the first argument.
62       */
63      public static void main(final String[] argv) throws Exception {
64          /*
65           * Expects class name as first argument, other arguments are by-passed.
66           */
67          if (argv.length == 0) {
68              System.out.println("Missing class name.");
69              return;
70          }
71          final String className = argv[0];
72          final String[] newArgv = new String[argv.length - 1];
73          System.arraycopy(argv, 1, newArgv, 0, newArgv.length);
74          new JavaWrapper().runMain(className, newArgv);
75      }
76  
77      private final java.lang.ClassLoader loader;
78  
79      public JavaWrapper() {
80          this(getClassLoader());
81      }
82  
83      public JavaWrapper(final java.lang.ClassLoader loader) {
84          this.loader = loader;
85      }
86  
87      /**
88       * Runs the main method of the given class with the arguments passed in argv
89       *
90       * @param className the fully qualified class name
91       * @param argv the arguments just as you would pass them directly
92       * @throws ClassNotFoundException if {@code className} can't be found.
93       */
94      public void runMain(final String className, final String[] argv) throws ClassNotFoundException {
95          final Class<?> cl = loader.loadClass(className);
96          Method method = null;
97          try {
98              method = cl.getMethod("main", argv.getClass());
99              /*
100              * Method main is sane ?
101              */
102             final int m = method.getModifiers();
103             final Class<?> r = method.getReturnType();
104             if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m) || r != Void.TYPE) {
105                 throw new NoSuchMethodException();
106             }
107         } catch (final NoSuchMethodException no) {
108             System.out.println("In class " + className + ": public static void main(String[] argv) is not defined");
109             return;
110         }
111         try {
112             method.invoke(null, (Object[]) argv);
113         } catch (final Exception ex) {
114             ex.printStackTrace();
115         }
116     }
117 }