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. 027 * <p> 028 * Call this wrapper with: 029 * </p> 030 * <pre>java org.apache.bcel.util.JavaWrapper <real.class.name> [arguments]</pre> 031 * <p> 032 * To use your own class loader you can set the "bcel.classloader" system property. 033 * </p> 034 * <pre>java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments]</pre> 035 * 036 * @see ClassLoader 037 */ 038public class JavaWrapper { 039 040 private final java.lang.ClassLoader loader; 041 042 043 private static java.lang.ClassLoader getClassLoader() { 044 final String s = System.getProperty("bcel.classloader"); 045 if ((s == null) || "".equals(s)) { 046 throw new IllegalArgumentException("The property 'bcel.classloader' must be defined"); 047 } 048 try { 049 return (java.lang.ClassLoader) Class.forName(s).newInstance(); 050 } catch (final Exception e) { 051 throw new RuntimeException(e.toString(), e); 052 } 053 } 054 055 056 public JavaWrapper(final java.lang.ClassLoader loader) { 057 this.loader = loader; 058 } 059 060 061 public JavaWrapper() { 062 this(getClassLoader()); 063 } 064 065 066 /** Runs the main method of the given class with the arguments passed in argv 067 * 068 * @param class_name the fully qualified class name 069 * @param argv the arguments just as you would pass them directly 070 */ 071 public void runMain( final String class_name, final String[] argv ) throws ClassNotFoundException { 072 final Class<?> cl = loader.loadClass(class_name); 073 Method method = null; 074 try { 075 method = cl.getMethod("main", new Class[] { 076 argv.getClass() 077 }); 078 /* Method main is sane ? 079 */ 080 final int m = method.getModifiers(); 081 final Class<?> r = method.getReturnType(); 082 if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m) 083 || (r != Void.TYPE)) { 084 throw new NoSuchMethodException(); 085 } 086 } catch (final NoSuchMethodException no) { 087 System.out.println("In class " + class_name 088 + ": public static void main(String[] argv) is not defined"); 089 return; 090 } 091 try { 092 method.invoke(null, new Object[] { 093 argv 094 }); 095 } catch (final Exception ex) { 096 ex.printStackTrace(); 097 } 098 } 099 100 101 /** Default main method used as wrapper, expects the fully qualified class name 102 * of the real class as the first argument. 103 */ 104 public static void main( final String[] argv ) throws Exception { 105 /* Expects class name as first argument, other arguments are by-passed. 106 */ 107 if (argv.length == 0) { 108 System.out.println("Missing class name."); 109 return; 110 } 111 final String class_name = argv[0]; 112 final String[] new_argv = new String[argv.length - 1]; 113 System.arraycopy(argv, 1, new_argv, 0, new_argv.length); 114 final JavaWrapper wrapper = new JavaWrapper(); 115 wrapper.runMain(class_name, new_argv); 116 } 117}