blob: 20959ad0d7eceeb227178a6f1227d5dc36a6c873 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jexl2;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* Helper class to test GC / reference interactions.
* Dynamically creates a class by compiling generated source Java code and
* load it through a dedicated class loader.
*/
public class ClassCreator {
private final JexlEngine jexl;
private final File base;
private File packageDir = null;
private int seed = 0;
private String className = null;
private String sourceName = null;
private ClassLoader loader = null;
public static final boolean canRun = comSunToolsJavacMain();
/**
* Check if we can invoke Sun's java compiler.
* @return true if it is possible, false otherwise
*/
private static boolean comSunToolsJavacMain() {
try {
Class<?> javac = ClassCreatorTest.class.getClassLoader().loadClass("com.sun.tools.javac.Main");
return javac != null;
} catch (Exception xany) {
return false;
}
}
public ClassCreator(JexlEngine theJexl, File theBase) throws Exception {
jexl = theJexl;
base = theBase;
}
public void clear() {
seed = 0;
packageDir = null;
className = null;
sourceName = null;
packageDir = null;
loader = null;
}
public void setSeed(int s) {
seed = s;
className = "foo" + s;
sourceName = className + ".java";
packageDir = new File(base, seed + "/org/apache/commons/jexl2/generated");
packageDir.mkdirs();
loader = null;
}
public String getClassName() {
return "org.apache.commons.jexl2.generated." + className;
}
public Class<?> getClassInstance() throws Exception {
return getClassLoader().loadClass("org.apache.commons.jexl2.generated." + className);
}
public ClassLoader getClassLoader() throws Exception {
if (loader == null) {
URL classpath = (new File(base, Integer.toString(seed))).toURI().toURL();
loader = new URLClassLoader(new URL[]{classpath}, null);
}
return loader;
}
public Class<?> createClass() throws Exception {
// generate, compile & validate
generate();
Class<?> clazz = compile();
if (clazz == null) {
throw new Exception("failed to compile foo" + seed);
}
Object v = validate(clazz);
if (v instanceof Integer && ((Integer) v).intValue() == seed) {
return clazz;
}
throw new Exception("failed to validate foo" + seed);
}
void generate() throws Exception {
FileWriter aWriter = new FileWriter(new File(packageDir, sourceName), false);
aWriter.write("package org.apache.commons.jexl2.generated;");
aWriter.write("public class " + className + "{\n");
aWriter.write("private int value =");
aWriter.write(Integer.toString(seed));
aWriter.write(";\n");
aWriter.write(" public void setValue(int v) {");
aWriter.write(" value = v;");
aWriter.write(" }\n");
aWriter.write(" public int getValue() {");
aWriter.write(" return value;");
aWriter.write(" }\n");
aWriter.write(" }\n");
aWriter.flush();
aWriter.close();
}
Class<?> compile() throws Exception {
String source = packageDir.getPath() + "/" + sourceName;
Class<?> javac = getClassLoader().loadClass("com.sun.tools.javac.Main");
if (javac == null) {
return null;
}
Integer r = (Integer) jexl.invokeMethod(javac, "compile", source);
if (r.intValue() >= 0) {
return getClassLoader().loadClass("org.apache.commons.jexl2.generated." + className);
}
return null;
}
Object validate(Class<?> clazz) throws Exception {
Class<?> params[] = {};
Object paramsObj[] = {};
Object iClass = clazz.newInstance();
Method thisMethod = clazz.getDeclaredMethod("getValue", params);
return thisMethod.invoke(iClass, paramsObj);
}
}