1 33 34 35 package bsh; 36 37 import java.util.Hashtable ; 38 import java.lang.reflect.Array ; 39 import java.lang.reflect.InvocationTargetException ; 40 41 class BSHPrimarySuffix extends SimpleNode 42 { 43 public static final int 44 CLASS = 0, 45 INDEX = 1, 46 NAME = 2, 47 PROPERTY = 3; 48 49 public int operation; 50 Object index; 51 public String field; 52 53 BSHPrimarySuffix(int id) { super(id); } 54 55 68 public Object doSuffix( 69 Object obj, boolean toLHS, 70 CallStack callstack, Interpreter interpreter) 71 throws EvalError 72 { 73 if ( operation == CLASS ) 76 if ( obj instanceof BSHType ) { 77 if ( toLHS ) 78 throw new EvalError("Can't assign .class", 79 this, callstack ); 80 NameSpace namespace = callstack.top(); 81 return ((BSHType)obj).getType( callstack, interpreter ); 82 } else 83 throw new EvalError( 84 "Attempt to use .class suffix on non class.", 85 this, callstack ); 86 87 99 if ( obj instanceof SimpleNode ) 100 if ( obj instanceof BSHAmbiguousName ) 101 obj = ((BSHAmbiguousName)obj).toObject(callstack, interpreter); 102 else 103 obj = ((SimpleNode)obj).eval(callstack, interpreter); 104 else 105 if ( obj instanceof LHS ) 106 try { 107 obj = ((LHS)obj).getValue(); 108 } catch ( UtilEvalError e ) { 109 throw e.toEvalError( this, callstack ); 110 } 111 112 try 113 { 114 switch(operation) 115 { 116 case INDEX: 117 return doIndex( obj, toLHS, callstack, interpreter ); 118 119 case NAME: 120 return doName( obj, toLHS, callstack, interpreter ); 121 122 case PROPERTY: 123 return doProperty( toLHS, obj, callstack, interpreter ); 124 125 default: 126 throw new InterpreterError( "Unknown suffix type" ); 127 } 128 } 129 catch(ReflectError e) 130 { 131 throw new EvalError("reflection error: " + e, this, callstack ); 132 } 133 catch(InvocationTargetException e) 134 { 135 throw new TargetError( "target exception", e.getTargetException(), 136 this, callstack, true); 137 } 138 } 139 140 144 private Object doName( 145 Object obj, boolean toLHS, 146 CallStack callstack, Interpreter interpreter) 147 throws EvalError, ReflectError, InvocationTargetException 148 { 149 try { 150 if ( field.equals("length") && obj.getClass().isArray() ) 152 if ( toLHS ) 153 throw new EvalError( 154 "Can't assign array length", this, callstack ); 155 else 156 return new Primitive(Array.getLength(obj)); 157 158 if ( jjtGetNumChildren() == 0 ) 160 if ( toLHS ) 161 return Reflect.getLHSObjectField(obj, field); 162 else 163 return Reflect.getObjectFieldValue( obj, field ); 164 165 Object [] oa = ((BSHArguments)jjtGetChild(0)).getArguments( 168 callstack, interpreter); 169 170 try { 176 return Reflect.invokeObjectMethod( 177 obj, field, oa, interpreter, callstack, this ); 178 } catch ( ReflectError e ) { 179 throw new EvalError( 180 "Error in method invocation: " + e.getMessage(), 181 this, callstack ); 182 } catch ( InvocationTargetException e ) 183 { 184 String msg = "Method Invocation "+field; 185 Throwable te = e.getTargetException(); 186 187 192 boolean isNative = true; 193 if ( te instanceof EvalError ) 194 if ( te instanceof TargetError ) 195 isNative = ((TargetError)te).inNativeCode(); 196 else 197 isNative = false; 198 199 throw new TargetError( msg, te, this, callstack, isNative ); 200 } 201 202 } catch ( UtilEvalError e ) { 203 throw e.toEvalError( this, callstack ); 204 } 205 } 206 207 209 static int getIndexAux( 210 Object obj, CallStack callstack, Interpreter interpreter, 211 SimpleNode callerInfo ) 212 throws EvalError 213 { 214 if ( !obj.getClass().isArray() ) 215 throw new EvalError("Not an array", callerInfo, callstack ); 216 217 int index; 218 try { 219 Object indexVal = 220 ((SimpleNode)callerInfo.jjtGetChild(0)).eval( 221 callstack, interpreter ); 222 if ( !(indexVal instanceof Primitive) ) 223 indexVal = Types.castObject( 224 indexVal, Integer.TYPE, Types.ASSIGNMENT ); 225 index = ((Primitive)indexVal).intValue(); 226 } catch( UtilEvalError e ) { 227 Interpreter.debug("doIndex: "+e); 228 throw e.toEvalError( 229 "Arrays may only be indexed by integer types.", 230 callerInfo, callstack ); 231 } 232 233 return index; 234 } 235 236 240 private Object doIndex( 241 Object obj, boolean toLHS, 242 CallStack callstack, Interpreter interpreter ) 243 throws EvalError, ReflectError 244 { 245 int index = getIndexAux( obj, callstack, interpreter, this ); 246 if ( toLHS ) 247 return new LHS(obj, index); 248 else 249 try { 250 return Reflect.getIndex(obj, index); 251 } catch ( UtilEvalError e ) { 252 throw e.toEvalError( this, callstack ); 253 } 254 } 255 256 260 private Object doProperty( boolean toLHS, 261 Object obj, CallStack callstack, Interpreter interpreter ) 262 throws EvalError 263 { 264 if(obj == Primitive.VOID) 265 throw new EvalError( 266 "Attempt to access property on undefined variable or class name", 267 this, callstack ); 268 269 if ( obj instanceof Primitive ) 270 throw new EvalError("Attempt to access property on a primitive", 271 this, callstack ); 272 273 Object value = ((SimpleNode)jjtGetChild(0)).eval( 274 callstack, interpreter); 275 276 if ( !( value instanceof String ) ) 277 throw new EvalError( 278 "Property expression must be a String or identifier.", 279 this, callstack ); 280 281 if ( toLHS ) 282 return new LHS(obj, (String )value); 283 284 CollectionManager cm = CollectionManager.getCollectionManager(); 286 if ( cm.isMap( obj ) ) 287 { 288 Object val = cm.getFromMap( obj, value ); 289 return ( val == null ? val = Primitive.NULL : val ); 290 } 291 292 try { 293 return Reflect.getObjectProperty( obj, (String )value ); 294 } 295 catch ( UtilEvalError e) 296 { 297 throw e.toEvalError( "Property: "+value, this, callstack ); 298 } 299 catch (ReflectError e) 300 { 301 throw new EvalError("No such property: " + value, this, callstack ); 302 } 303 } 304 } 305 306 | Popular Tags |