com.hazelcast.org.codehaus.commons.compiler.IClassBodyEvaluator Maven / Gradle / Ivy
/*
* Janino - An embedded Java[TM] compiler
*
* Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.hazelcast.org.codehaus.commons.compiler;
import java.io.IOException;
import java.io.Reader;
import com.hazelcast.org.codehaus.commons.compiler.lang.ClassLoaders;
import com.hazelcast.org.codehaus.commons.nullanalysis.Nullable;
/**
* Parses a class body and returns it as a {@link Class} object ready for use with
* java.lang.reflect.
*
* Example:
*
*
* import java.util.*;
*
* static private int a = 1;
* private int b = 2;
*
* public void func(int c, int d) {
* return func2(c, d);
* }
*
* private static void func2(int e, int f) {
* return e * f;
* }
*
*
* To set up an {@link IClassBodyEvaluator} object, proceed as follows:
*
*
* - Create an {@link IClassBodyEvaluator}-implementing class.
* - Configure the {@link IClassBodyEvaluator} by calling any of the following methods:
*
* - {@link #setDefaultImports(String[])}
* - {@link #setClassName(String)}
* - {@link #setExtendedClass(Class)}
* - {@link #setImplementedInterfaces(Class[])}
* - {@link #setParentClassLoader(ClassLoader)}
*
* -
* Call any of the {@link ICookable#cook(String, java.io.Reader)} methods to scan, parse, compile and load the
* class body into the JVM.
*
*
*
* To compile a class body and immediately instantiate an object, the {@link #createInstance(Reader)} methods can be
* used.
*
*
* The generated class may optionally extend/implement a given type; the returned instance can safely be type-cast
* to that {@code baseType}.
*
*
* Example:
*
*
* public interface Foo {
* int bar(int a, int b);
* }
* ...
* {@link IClassBodyEvaluator} cbe = {@link CompilerFactoryFactory}.{@link
* CompilerFactoryFactory#getDefaultCompilerFactory() getDefaultCompilerFactory}(). {@link
* ICompilerFactory#newClassBodyEvaluator() newClassBodyEvaluator}();
* Foo f = (Foo) ClassBodyEvaluator.createFastClassBodyEvaluator(
* new Scanner(null, new StringReader("public int bar(int a, int b) { return a + b; }")),
* Foo.class, // Base type to extend/implement
* (ClassLoader) null // Use current thread's context class loader
* );
* System.out.println("1 + 2 = " + f.bar(1, 2));
*
*/
public
interface IClassBodyEvaluator extends ICookable {
/**
* Default name for the generated class.
*/
String DEFAULT_CLASS_NAME = "SC";
/**
* The "parent class loader" is used to load referenced classes. Useful values are:
*
* {@code System.getSystemClassLoader()}
* The running JVM's class path
*
* {@code Thread.currentThread().getContextClassLoader()} or {@code null}
* The class loader effective for the invoking thread
*
* {@link ClassLoaders#BOOTCLASSPATH_CLASS_LOADER}
* The running JVM's boot class path
*
*
* The parent class loader defaults to the current thread's context class loader.
*
*/
void setParentClassLoader(@Nullable ClassLoader parentClassLoader);
/**
* Determines what kind of debugging information is included in the generates classes. The default is typically
* "{@code -g:none}".
*/
void setDebuggingInformation(boolean debugSource, boolean debugLines, boolean debugVars);
/**
* By default, {@link CompileException}s are thrown on compile errors, but an application my install its own
* {@link ErrorHandler}.
*
* Be aware that a single problem during compilation often causes a bunch of compile errors, so a good {@link
* ErrorHandler} counts errors and throws a {@link CompileException} when a limit is reached.
*
*
* If the given {@link ErrorHandler} throws {@link CompileException}s, then the compilation is terminated and
* the exception is propagated.
*
*
* If the given {@link ErrorHandler} does not throw {@link CompileException}s, then the compiler may or may not
* continue compilation, but must eventually throw a {@link CompileException}.
*
*
* In other words: The {@link ErrorHandler} may throw a {@link CompileException} or not, but the compiler must
* definitely throw a {@link CompileException} if one or more compile errors have occurred.
*
*
* @param compileErrorHandler {@code null} to restore the default behavior (throwing a {@link CompileException}
*/
void setCompileErrorHandler(@Nullable ErrorHandler compileErrorHandler);
/**
* By default, warnings are discarded, but an application my install a custom {@link WarningHandler}.
*
* @param warningHandler {@code null} to indicate that no warnings be issued
*/
void setWarningHandler(@Nullable WarningHandler warningHandler);
/**
* "Default imports" add to the system import "java.lang", i.e. the evaluator may refer to classes imported by
* default imports without having to explicitly declare IMPORT statements.
*
* Notice that JDK 5 "static imports" are also supported, as shown here:
*
*
* sc.setDefaultImports(
* "java.util.Map", // Single type import
* "java.io.*", // Type-import-on-demand
* "static java.util.Collections.EMPTY_MAP", // Single static import
* "static java.util.Collections.*", // Static-import-on-demand
* );
*/
void setDefaultImports(String... defaultImports);
/**
* @return The default imports that were previously configured with {@link #setDefaultImports(String...)}
*/
String[] getDefaultImports();
/**
* Sets the name of the generated class. Defaults to {@link #DEFAULT_CLASS_NAME}. In most cases, there is no need
* to set this name, because the generated class is loaded into its own {@link java.lang.ClassLoader} where its
* name cannot collide with classes generated by other evaluators.
*
* One reason to use this function is to have a class name in a non-default package, which can be relevant when
* types and members with DEFAULT accessibility are accessed.
*
*/
void setClassName(String className);
/**
* Sets a particular superclass that the generated class will extend. If extendedClass is {@code
* null}, the generated class will extend {@link Object}.
*
* The usual reason to set a base class for an evaluator is that the generated class can directly access the
* superclass's (non-private) members.
*
*/
void setExtendedClass(@Nullable Class> extendedClass);
/**
* @deprecated Use {@link #setExtendedClass(Class)} instead
*/
@Deprecated void
setExtendedType(@Nullable Class> extendedClass);
/**
* Sets a particular set of interfaces that the generated class will implement.
*/
void setImplementedInterfaces(Class>[] implementedInterfaces);
/**
* @deprecated Use {@link #setImplementedInterfaces(Class[])} instead
*/
@Deprecated void
setImplementedTypes(Class>[] implementedInterfaces);
/**
* @return The generated {@link Class}
* @throws IllegalStateException This {@link IClassBodyEvaluator} is not yet cooked
*/
Class> getClazz();
/**
* Scans, parses and compiles a class body from the tokens delivered by the the given {@link Reader}, then creates
* and returns an instance of that class.
*
* @param reader Source of class body tokens
* @return An object that extends the {@code extendedType} and implements the given
* {@code implementedTypes}
*/
Object createInstance(Reader reader) throws CompileException, IOException;
}