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