1 package bsh; 2 3 import java.io.*; 4 import java.util.*; 5 import java.lang.reflect.InvocationTargetException ; 6 import java.lang.reflect.Method ; 7 8 12 public class ClassGeneratorImpl extends ClassGenerator 13 { 14 public Class generateClass( 15 String name, Modifiers modifiers, 16 Class [] interfaces, Class superClass, BSHBlock block, 17 boolean isInterface, CallStack callstack, Interpreter interpreter 18 ) 19 throws EvalError 20 { 21 return generateClassImpl( name, modifiers, interfaces, superClass, 23 block, isInterface, callstack, interpreter ); 24 } 25 26 public Object invokeSuperclassMethod( 27 BshClassManager bcm, Object instance, String methodName, Object [] args 28 ) 29 throws UtilEvalError, ReflectError, InvocationTargetException  30 { 31 return invokeSuperclassMethodImpl( bcm, instance, methodName, args ); 33 } 34 35 40 public void setInstanceNameSpaceParent( 42 Object instance, String className, NameSpace parent ) 43 { 44 This ithis = 45 ClassGeneratorUtil.getClassInstanceThis( instance, className ); 46 ithis.getNameSpace().setParent( parent ); 47 } 48 49 53 public static Class generateClassImpl( 54 String name, Modifiers modifiers, 55 Class [] interfaces, Class superClass, BSHBlock block, 56 boolean isInterface, CallStack callstack, Interpreter interpreter 57 ) 58 throws EvalError 59 { 60 try { 63 Capabilities.setAccessibility( true ); 64 } catch ( Capabilities.Unavailable e ) 65 { 66 throw new EvalError( 67 "Defining classes currently requires reflective Accessibility.", 68 block, callstack ); 69 } 70 71 NameSpace enclosingNameSpace = callstack.top(); 72 String packageName = enclosingNameSpace.getPackage(); 73 String className = enclosingNameSpace.isClass ? 74 ( enclosingNameSpace.getName()+"$"+name ) : name; 75 String fqClassName = 76 packageName == null ? className : packageName + "." + className; 77 78 BshClassManager bcm = interpreter.getClassManager(); 79 bcm.definingClass( fqClassName ); 81 82 NameSpace classStaticNameSpace = 84 new NameSpace( enclosingNameSpace, className); 85 classStaticNameSpace.isClass = true; 86 87 callstack.push( classStaticNameSpace ); 88 89 block.evalBlock( 92 callstack, interpreter, true, 93 ClassNodeFilter.CLASSCLASSES ); 94 95 Variable [] variables = 97 getDeclaredVariables( block, callstack, interpreter, packageName ); 98 DelayedEvalBshMethod [] methods = 99 getDeclaredMethods( block, callstack, interpreter, packageName ); 100 101 ClassGeneratorUtil classGenerator = new ClassGeneratorUtil( 102 modifiers, className, packageName, superClass, interfaces, 103 variables, methods, classStaticNameSpace, isInterface ); 104 byte [] code = classGenerator.generateClass(); 105 106 String dir = System.getProperty("debugClasses"); 108 if ( dir != null ) 109 try { 110 FileOutputStream out= 111 new FileOutputStream( dir+"/"+className+".class" ); 112 out.write(code); 113 out.close(); 114 } catch ( IOException e ) { } 115 116 Class genClass = bcm.defineClass( fqClassName, code ); 118 119 enclosingNameSpace.importClass( fqClassName.replace('$','.') ); 121 122 try { 123 classStaticNameSpace.setLocalVariable( 124 ClassGeneratorUtil.BSHINIT, block, false ); 125 } catch ( UtilEvalError e ) { 126 throw new InterpreterError("unable to init static: "+e ); 127 } 128 129 classStaticNameSpace.setClassStatic( genClass ); 132 133 block.evalBlock( 135 callstack, interpreter, true, 136 ClassNodeFilter.CLASSSTATIC ); 137 138 callstack.pop(); 139 140 if ( !genClass.isInterface() ) 141 { 142 String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC+className; 144 try { 145 LHS lhs = Reflect.getLHSStaticField( genClass, bshStaticFieldName ); 146 lhs.assign( 147 classStaticNameSpace.getThis( interpreter ), false ); 148 } catch ( Exception e ) { 149 throw new InterpreterError("Error in class gen setup: "+e ); 150 } 151 } 152 153 bcm.doneDefiningClass( fqClassName ); 154 return genClass; 155 } 156 157 static Variable [] getDeclaredVariables( 158 BSHBlock body, CallStack callstack, Interpreter interpreter, 159 String defaultPackage 160 ) 161 { 162 List vars = new ArrayList(); 163 for( int child=0; child<body.jjtGetNumChildren(); child++ ) 164 { 165 SimpleNode node = (SimpleNode)body.jjtGetChild(child); 166 if ( node instanceof BSHTypedVariableDeclaration ) 167 { 168 BSHTypedVariableDeclaration tvd = 169 (BSHTypedVariableDeclaration)node; 170 Modifiers modifiers = tvd.modifiers; 171 172 String type = tvd.getTypeDescriptor( 173 callstack, interpreter, defaultPackage ); 174 175 BSHVariableDeclarator [] vardec = tvd.getDeclarators(); 176 for( int i = 0; i< vardec.length; i++) 177 { 178 String name = vardec[i].name; 179 try { 180 Variable var = new Variable( 181 name, type, null, modifiers ); 182 vars.add( var ); 183 } catch ( UtilEvalError e ) { 184 } 186 } 187 } 188 } 189 190 return (Variable [])vars.toArray( new Variable[0] ); 191 } 192 193 static DelayedEvalBshMethod [] getDeclaredMethods( 194 BSHBlock body, CallStack callstack, Interpreter interpreter, 195 String defaultPackage 196 ) 197 throws EvalError 198 { 199 List methods = new ArrayList(); 200 for( int child=0; child<body.jjtGetNumChildren(); child++ ) 201 { 202 SimpleNode node = (SimpleNode)body.jjtGetChild(child); 203 if ( node instanceof BSHMethodDeclaration ) 204 { 205 BSHMethodDeclaration md = (BSHMethodDeclaration)node; 206 md.insureNodesParsed(); 207 Modifiers modifiers = md.modifiers; 208 String name = md.name; 209 String returnType = md.getReturnTypeDescriptor( 210 callstack, interpreter, defaultPackage ); 211 BSHReturnType returnTypeNode = md.getReturnTypeNode(); 212 BSHFormalParameters paramTypesNode = md.paramsNode; 213 String [] paramTypes = paramTypesNode.getTypeDescriptors( 214 callstack, interpreter, defaultPackage ); 215 216 DelayedEvalBshMethod bm = new DelayedEvalBshMethod( 217 name, 218 returnType, returnTypeNode, 219 md.paramsNode.getParamNames(), 220 paramTypes, paramTypesNode, 221 md.blockNode, null, 222 modifiers, callstack, interpreter 223 ); 224 225 methods.add( bm ); 226 } 227 } 228 229 return (DelayedEvalBshMethod [])methods.toArray( 230 new DelayedEvalBshMethod[0] ); 231 } 232 233 238 static class ClassNodeFilter implements BSHBlock.NodeFilter 239 { 240 public static final int STATIC=0, INSTANCE=1, CLASSES=2; 241 242 public static ClassNodeFilter CLASSSTATIC = 243 new ClassNodeFilter( STATIC ); 244 public static ClassNodeFilter CLASSINSTANCE = 245 new ClassNodeFilter( INSTANCE ); 246 public static ClassNodeFilter CLASSCLASSES = 247 new ClassNodeFilter( CLASSES ); 248 249 int context; 250 251 private ClassNodeFilter( int context ) { this.context = context; } 252 253 public boolean isVisible( SimpleNode node ) 254 { 255 if ( context == CLASSES ) 256 return node instanceof BSHClassDeclaration; 257 258 if ( node instanceof BSHClassDeclaration ) 260 return false; 261 262 if ( context == STATIC ) 263 return isStatic( node ); 264 265 if ( context == INSTANCE ) 266 return !isStatic( node ); 267 268 return true; 270 } 271 272 boolean isStatic( SimpleNode node ) 273 { 274 if ( node instanceof BSHTypedVariableDeclaration ) 275 return ((BSHTypedVariableDeclaration)node).modifiers != null 276 && ((BSHTypedVariableDeclaration)node).modifiers 277 .hasModifier("static"); 278 279 if ( node instanceof BSHMethodDeclaration ) 280 return ((BSHMethodDeclaration)node).modifiers != null 281 && ((BSHMethodDeclaration)node).modifiers 282 .hasModifier("static"); 283 284 if ( node instanceof BSHBlock) 286 return false; 287 288 return false; 289 } 290 } 291 292 public static Object invokeSuperclassMethodImpl( 293 BshClassManager bcm, Object instance, String methodName, Object [] args 294 ) 295 throws UtilEvalError, ReflectError, InvocationTargetException  296 { 297 String superName = ClassGeneratorUtil.BSHSUPER+methodName; 298 299 Class clas = instance.getClass(); 301 Method superMethod = Reflect.resolveJavaMethod( 302 bcm, clas, superName, Types.getTypes(args), false ); 303 if ( superMethod != null ) 304 return Reflect.invokeMethod( 305 superMethod, instance, args ); 306 307 Class superClass = clas.getSuperclass(); 310 superMethod = Reflect.resolveExpectedJavaMethod( 311 bcm, superClass, instance, methodName, args, 312 false ); 313 return Reflect.invokeMethod( superMethod, instance, args ); 314 } 315 316 } 317 | Popular Tags |