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, that is, 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 <real.class.name> [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 <real.class.name> [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 }