|
What this is
Other links
The source code
package bsh;
import java.io.*;
import java.util.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
@author Pat Niemeyer (pat@pat.net)
*/
public class ClassGeneratorImpl extends ClassGenerator
{
public Class generateClass(
String name, Modifiers modifiers,
Class [] interfaces, Class superClass, BSHBlock block,
boolean isInterface, CallStack callstack, Interpreter interpreter
)
throws EvalError
{
// Delegate to the static method
return generateClassImpl( name, modifiers, interfaces, superClass,
block, isInterface, callstack, interpreter );
}
public Object invokeSuperclassMethod(
BshClassManager bcm, Object instance, String methodName, Object [] args
)
throws UtilEvalError, ReflectError, InvocationTargetException
{
// Delegate to the static method
return invokeSuperclassMethodImpl( bcm, instance, methodName, args );
}
/**
Change the parent of the class instance namespace.
This is currently used for inner class support.
Note: This method will likely be removed in the future.
*/
// This could be static
public void setInstanceNameSpaceParent(
Object instance, String className, NameSpace parent )
{
This ithis =
ClassGeneratorUtil.getClassInstanceThis( instance, className );
ithis.getNameSpace().setParent( parent );
}
/**
Parse the BSHBlock for for the class definition and generate the class
using ClassGenerator.
*/
public static Class generateClassImpl(
String name, Modifiers modifiers,
Class [] interfaces, Class superClass, BSHBlock block,
boolean isInterface, CallStack callstack, Interpreter interpreter
)
throws EvalError
{
// Scripting classes currently requires accessibility
// This can be eliminated with a bit more work.
Capabilities.setAccessibility( true );
if ( !Capabilities.haveAccessibility() )
throw new InterpreterError(
"Defining classes currently requires reflect Accessibility.");
NameSpace enclosingNameSpace = callstack.top();
String packageName = enclosingNameSpace.getPackage();
String className = enclosingNameSpace.isClass ?
( enclosingNameSpace.getName()+"$"+name ) : name;
String fqClassName =
packageName == null ? className : packageName + "." + className;
BshClassManager bcm = interpreter.getClassManager();
// Race condition here...
bcm.definingClass( fqClassName );
// Create the class static namespace
NameSpace classStaticNameSpace =
new NameSpace( enclosingNameSpace, className);
classStaticNameSpace.isClass = true;
callstack.push( classStaticNameSpace );
// Evaluate any inner class class definitions in the block
// effectively recursively call this method for contained classes first
block.evalBlock(
callstack, interpreter, true/*override*/,
ClassNodeFilter.CLASSCLASSES );
// Generate the type for our class
Variable [] variables =
getDeclaredVariables( block, callstack, interpreter, packageName );
DelayedEvalBshMethod [] methods =
getDeclaredMethods( block, callstack, interpreter, packageName );
ClassGeneratorUtil classGenerator = new ClassGeneratorUtil(
modifiers, className, packageName, superClass, interfaces,
variables, methods, classStaticNameSpace, isInterface );
byte [] code = classGenerator.generateClass();
// if debug, write out the class file to debugClasses directory
String dir = System.getProperty("debugClasses");
if ( dir != null )
try {
FileOutputStream out=
new FileOutputStream( dir+"/"+className+".class" );
out.write(code);
out.close();
} catch ( IOException e ) { }
// Define the new class in the classloader
Class genClass = bcm.defineClass( fqClassName, code );
//bcm.doneDefiningClass( fqClassName );
// import the unq name into parent
enclosingNameSpace.importClass( fqClassName.replace('$','.') );
// Also cache the class so that no import resolution must occur
// this avoids having to load our enclosing class which isn't
// finished being generated yet... oy.
// caching is not correct and doesn't seem to help...
// enclosingNameSpace.cacheClass( name, genClass );
// Also cache it in the static namespace...
//classStaticNameSpace.cacheClass( name, genClass );
//classStaticNameSpace.importClass( fqClassName.replace('$','.') );
try {
classStaticNameSpace.setLocalVariable(
ClassGeneratorUtil.BSHINIT, block, false/*strictJava*/ );
} catch ( UtilEvalError e ) {
throw new InterpreterError("unable to init static: "+e );
}
// Give the static space its class static import
// important to do this after all classes are defined
classStaticNameSpace.setClassStatic( genClass );
// evaluate the static portion of the block in the static space
block.evalBlock(
callstack, interpreter, true/*override*/,
ClassNodeFilter.CLASSSTATIC );
callstack.pop();
if ( !genClass.isInterface() )
{
// Set the static bsh This callback
String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC+className;
try {
LHS lhs = Reflect.getLHSStaticField( genClass, bshStaticFieldName );
lhs.assign(
classStaticNameSpace.getThis( interpreter ), false/*strict*/ );
} catch ( Exception e ) {
throw new InterpreterError("Error in class gen setup: "+e );
}
}
bcm.doneDefiningClass( fqClassName );
return genClass;
}
static Variable [] getDeclaredVariables(
BSHBlock body, CallStack callstack, Interpreter interpreter,
String defaultPackage
)
throws EvalError
{
List vars = new ArrayList();
for( int child=0; child |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.