|
What this is
Other links
The source codepackage 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.