1 33 34 35 package bsh; 36 37 import java.lang.reflect.Array ; 38 import java.lang.reflect.InvocationTargetException ; 39 40 43 class BSHAllocationExpression extends SimpleNode 44 { 45 BSHAllocationExpression(int id) { super(id); } 46 private static int innerClassCount = 0; 47 48 public Object eval( CallStack callstack, Interpreter interpreter) 49 throws EvalError 50 { 51 SimpleNode type = (SimpleNode)jjtGetChild(0); 53 54 SimpleNode args = (SimpleNode)jjtGetChild(1); 56 57 if ( type instanceof BSHAmbiguousName ) 58 { 59 BSHAmbiguousName name = (BSHAmbiguousName)type; 60 61 if (args instanceof BSHArguments) 62 return objectAllocation(name, (BSHArguments)args, 63 callstack, interpreter ); 64 else 65 return objectArrayAllocation(name, (BSHArrayDimensions)args, 66 callstack, interpreter ); 67 } 68 else 69 return primitiveArrayAllocation((BSHPrimitiveType)type, 70 (BSHArrayDimensions)args, callstack, interpreter ); 71 } 72 73 private Object objectAllocation( 74 BSHAmbiguousName nameNode, BSHArguments argumentsNode, 75 CallStack callstack, Interpreter interpreter 76 ) 77 throws EvalError 78 { 79 NameSpace namespace = callstack.top(); 80 81 Object [] args = argumentsNode.getArguments( callstack, interpreter ); 82 if ( args == null) 83 throw new EvalError( "Null args in new.", this, callstack ); 84 85 Object obj = nameNode.toObject( 87 callstack, interpreter, false ); 88 89 91 obj = nameNode.toObject( 92 callstack, interpreter, true ); 93 94 Class type = null; 95 if ( obj instanceof ClassIdentifier ) 96 type = ((ClassIdentifier)obj).getTargetClass(); 97 else 98 throw new EvalError( 99 "Unknown class: "+nameNode.text, this, callstack ); 100 101 boolean hasBody = jjtGetNumChildren() > 2; 103 104 if ( hasBody ) 105 { 106 BSHBlock body = (BSHBlock)jjtGetChild(2); 107 if ( type.isInterface() ) 108 return constructWithInterfaceBody( 109 type, args, body, callstack, interpreter ); 110 else 111 return constructWithClassBody( 112 type, args, body, callstack, interpreter ); 113 } else 114 return constructObject( type, args, callstack ); 115 } 116 117 private Object constructObject( 118 Class type, Object [] args, CallStack callstack ) 119 throws EvalError 120 { 121 Object obj; 122 try { 123 obj = Reflect.constructObject( type, args ); 124 } catch ( ReflectError e) { 125 throw new EvalError( 126 "Constructor error: " + e.getMessage(), this, callstack ); 127 } catch(InvocationTargetException e) { 128 Interpreter.debug("The constructor threw an exception:\n\t" + 130 e.getTargetException()); 131 throw new TargetError( 132 "Object constructor", e.getTargetException(), 133 this, callstack, true); 134 } 135 136 String className = type.getName(); 137 if ( className.indexOf("$") == -1 ) 139 return obj; 140 141 146 This ths = callstack.top().getThis( null ); 148 NameSpace instanceNameSpace = 149 Name.getClassNameSpace( ths.getNameSpace() ); 150 151 if ( instanceNameSpace != null 156 && className.startsWith( instanceNameSpace.getName() +"$") 157 ) 158 { 159 try { 160 ClassGenerator.getClassGenerator().setInstanceNameSpaceParent( 161 obj, className, instanceNameSpace ); 162 } catch ( UtilEvalError e ) { 163 throw e.toEvalError( this, callstack ); 164 } 165 } 166 167 return obj; 168 } 169 170 private Object constructWithClassBody( 171 Class type, Object [] args, BSHBlock block, 172 CallStack callstack, Interpreter interpreter ) 173 throws EvalError 174 { 175 String name = callstack.top().getName() + "$" + (++innerClassCount); 176 Modifiers modifiers = new Modifiers(); 177 modifiers.addModifier( Modifiers.CLASS, "public" ); 178 Class clas; 179 try { 180 clas = ClassGenerator.getClassGenerator() .generateClass( 181 name, modifiers, null, type, 182 block, false, callstack, interpreter ); 183 } catch ( UtilEvalError e ) { 184 throw e.toEvalError( this, callstack ); 185 } 186 try { 187 return Reflect.constructObject( clas, args ); 188 } catch ( Exception e ) { 189 if ( e instanceof InvocationTargetException ) 190 e = (Exception )((InvocationTargetException )e) 191 .getTargetException(); 192 throw new EvalError( 193 "Error constructing inner class instance: "+e, this, callstack 194 ); 195 } 196 } 197 198 private Object constructWithInterfaceBody( 199 Class type, Object [] args, BSHBlock body, 200 CallStack callstack, Interpreter interpreter ) 201 throws EvalError 202 { 203 NameSpace namespace = callstack.top(); 204 NameSpace local = new NameSpace(namespace, "AnonymousBlock"); 205 callstack.push(local); 206 body.eval( callstack, interpreter, true ); 207 callstack.pop(); 208 local.importStatic( type ); 211 try { 212 return local.getThis(interpreter).getInterface( type ); 213 } catch ( UtilEvalError e ) { 214 throw e.toEvalError( this, callstack ); 215 } 216 } 217 218 private Object objectArrayAllocation( 219 BSHAmbiguousName nameNode, BSHArrayDimensions dimensionsNode, 220 CallStack callstack, Interpreter interpreter 221 ) 222 throws EvalError 223 { 224 NameSpace namespace = callstack.top(); 225 Class type = nameNode.toClass( callstack, interpreter ); 226 if ( type == null ) 227 throw new EvalError( "Class " + nameNode.getName(namespace) 228 + " not found.", this, callstack ); 229 230 return arrayAllocation( dimensionsNode, type, callstack, interpreter ); 231 } 232 233 private Object primitiveArrayAllocation( 234 BSHPrimitiveType typeNode, BSHArrayDimensions dimensionsNode, 235 CallStack callstack, Interpreter interpreter 236 ) 237 throws EvalError 238 { 239 Class type = typeNode.getType(); 240 241 return arrayAllocation( dimensionsNode, type, callstack, interpreter ); 242 } 243 244 private Object arrayAllocation( 245 BSHArrayDimensions dimensionsNode, Class type, 246 CallStack callstack, Interpreter interpreter ) 247 throws EvalError 248 { 249 254 Object result = dimensionsNode.eval( type, callstack, interpreter ); 255 if ( result != Primitive.VOID ) 256 return result; 257 else 258 return arrayNewInstance( type, dimensionsNode, callstack ); 259 } 260 261 291 private Object arrayNewInstance( 292 Class type, BSHArrayDimensions dimensionsNode, CallStack callstack ) 293 throws EvalError 294 { 295 if ( dimensionsNode.numUndefinedDims > 0 ) 296 { 297 Object proto = Array.newInstance( 298 type, new int [dimensionsNode.numUndefinedDims] ); type = proto.getClass(); 300 } 301 302 try { 303 return Array.newInstance( 304 type, dimensionsNode.definedDimensions); 305 } catch( NegativeArraySizeException e1 ) { 306 throw new TargetError( e1, this, callstack ); 307 } catch( Exception e ) { 308 throw new EvalError("Can't construct primitive array: " + 309 e.getMessage(), this, callstack); 310 } 311 } 312 } 313 | Popular Tags |