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 */ 017package org.apache.bcel.util; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021 022import org.apache.commons.lang3.StringUtils; 023 024/** 025 * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader to modify/generate classes as they're 026 * requested. You can take this as a template for your own applications. 027 * <p> 028 * Call this wrapper with: 029 * </p> 030 * 031 * <pre> 032 * java org.apache.bcel.util.JavaWrapper <real.class.name> [arguments] 033 * </pre> 034 * <p> 035 * To use your own class loader you can set the "bcel.classloader" system property. 036 * </p> 037 * 038 * <pre> 039 * java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments] 040 * </pre> 041 * 042 * @see ClassLoader 043 */ 044public class JavaWrapper { 045 046 private static java.lang.ClassLoader getClassLoader() { 047 final String s = System.getProperty("bcel.classloader"); 048 if (StringUtils.isEmpty(s)) { 049 throw new IllegalStateException("The property 'bcel.classloader' must be defined"); 050 } 051 try { 052 return (java.lang.ClassLoader) Class.forName(s).getConstructor().newInstance(); 053 } catch (final Exception e) { 054 throw new IllegalStateException(e.toString(), e); 055 } 056 } 057 058 /** 059 * Default main method used as wrapper, expects the fully qualified class name of the real class as the first argument. 060 */ 061 public static void main(final String[] argv) throws Exception { 062 /* 063 * Expects class name as first argument, other arguments are by-passed. 064 */ 065 if (argv.length == 0) { 066 System.out.println("Missing class name."); 067 return; 068 } 069 final String className = argv[0]; 070 final String[] newArgv = new String[argv.length - 1]; 071 System.arraycopy(argv, 1, newArgv, 0, newArgv.length); 072 new JavaWrapper().runMain(className, newArgv); 073 } 074 075 private final java.lang.ClassLoader loader; 076 077 public JavaWrapper() { 078 this(getClassLoader()); 079 } 080 081 public JavaWrapper(final java.lang.ClassLoader loader) { 082 this.loader = loader; 083 } 084 085 /** 086 * Runs the main method of the given class with the arguments passed in argv 087 * 088 * @param className the fully qualified class name 089 * @param argv the arguments just as you would pass them directly 090 * @throws ClassNotFoundException if {@code className} can't be found. 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}