001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.util; 020 021import java.lang.reflect.Method; 022import java.lang.reflect.Modifier; 023 024import org.apache.commons.lang3.StringUtils; 025 026/** 027 * Java interpreter replacement, that is, wrapper that uses its own ClassLoader to modify/generate classes as they're 028 * requested. You can take this as a template for your own applications. 029 * <p> 030 * Call this wrapper with: 031 * </p> 032 * 033 * <pre> 034 * java org.apache.bcel.util.JavaWrapper <real.class.name> [arguments] 035 * </pre> 036 * <p> 037 * To use your own class loader you can set the "bcel.classloader" system property. 038 * </p> 039 * 040 * <pre> 041 * java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments] 042 * </pre> 043 * 044 * @see ClassLoader 045 */ 046public class JavaWrapper { 047 048 private static java.lang.ClassLoader getClassLoader() { 049 final String s = System.getProperty("bcel.classloader"); 050 if (StringUtils.isEmpty(s)) { 051 throw new IllegalStateException("The property 'bcel.classloader' must be defined"); 052 } 053 try { 054 return (java.lang.ClassLoader) Class.forName(s).getConstructor().newInstance(); 055 } catch (final Exception e) { 056 throw new IllegalStateException(e.toString(), e); 057 } 058 } 059 060 /** 061 * Default main method used as wrapper, expects the fully qualified class name of the real class as the first argument. 062 * 063 * @param argv command line arguments where first argument is the class name. 064 * @throws Exception Thrown if an error occurs during execution. 065 */ 066 public static void main(final String[] argv) throws Exception { 067 /* 068 * Expects class name as first argument, other arguments are by-passed. 069 */ 070 if (argv.length == 0) { 071 System.out.println("Missing class name."); 072 return; 073 } 074 final String className = argv[0]; 075 final String[] newArgv = new String[argv.length - 1]; 076 System.arraycopy(argv, 1, newArgv, 0, newArgv.length); 077 new JavaWrapper().runMain(className, newArgv); 078 } 079 080 private final java.lang.ClassLoader loader; 081 082 /** 083 * Constructs a JavaWrapper with the default class loader. 084 */ 085 public JavaWrapper() { 086 this(getClassLoader()); 087 } 088 089 /** 090 * Constructs a JavaWrapper with the specified class loader. 091 * 092 * @param loader The class loader to use. 093 */ 094 public JavaWrapper(final java.lang.ClassLoader loader) { 095 this.loader = loader; 096 } 097 098 /** 099 * Runs the main method of the given class with the arguments passed in argv 100 * 101 * @param className The fully qualified class name. 102 * @param argv The arguments just as you would pass them directly. 103 * @throws ClassNotFoundException Thrown if {@code className} can't be found. 104 */ 105 public void runMain(final String className, final String[] argv) throws ClassNotFoundException { 106 final Class<?> cl = loader.loadClass(className); 107 Method method = null; 108 try { 109 method = cl.getMethod("main", argv.getClass()); 110 /* 111 * Method main is sane ? 112 */ 113 final int m = method.getModifiers(); 114 final Class<?> r = method.getReturnType(); 115 if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m) || r != Void.TYPE) { 116 throw new NoSuchMethodException(); 117 } 118 } catch (final NoSuchMethodException no) { 119 System.out.println("In class " + className + ": public static void main(String[] argv) is not defined"); 120 return; 121 } 122 try { 123 method.invoke(null, (Object[]) argv); 124 } catch (final Exception ex) { 125 ex.printStackTrace(); 126 } 127 } 128}