public Object invokeImpl(Object proxy, Method method, Object[] args) throws EvalError { String methodName = method.getName(); CallStack callstack = new CallStack(namespace); /* If equals() is not explicitly defined we must override the default implemented by the This object protocol for scripted object. To support XThis equals() must test for equality with the generated proxy object, not the scripted bsh This object; otherwise callers from outside in Java will not see a the proxy object as equal to itself. */ BshMethod equalsMethod = null; try { equalsMethod = namespace.getMethod("equals", new Class[] {Object.class}); } catch (UtilEvalError e) { /*leave null*/ } if (methodName.equals("equals") && equalsMethod == null) { Object obj = args[0]; return new Boolean(proxy == obj); } /* If toString() is not explicitly defined override the default to show the proxy interfaces. */ BshMethod toStringMethod = null; try { toStringMethod = namespace.getMethod("toString", new Class[] {}); } catch (UtilEvalError e) { /*leave null*/ } if (methodName.equals("toString") && toStringMethod == null) { Class[] ints = proxy.getClass().getInterfaces(); // XThis.this refers to the enclosing class instance StringBuilder sb = new StringBuilder(XThis.this.toString() + "\nimplements:"); for (int i = 0; i < ints.length; i++) sb.append(" " + ints[i].getName() + ((ints.length > 1) ? "," : "")); return sb.toString(); } Class[] paramTypes = method.getParameterTypes(); return Primitive.unwrap(invokeMethod(methodName, Primitive.wrap(args, paramTypes))); }
/** * Construct the array from the initializer syntax. * * @param baseType the base class type of the array (no dimensionality) * @param dimensions the top number of dimensions of the array e.g. 2 for a String [][]; */ public Object eval(Class baseType, int dimensions, CallStack callstack, Interpreter interpreter) throws EvalError { int numInitializers = jjtGetNumChildren(); // allocate the array to store the initializers int[] dima = new int[dimensions]; // description of the array // The other dimensions default to zero and are assigned when // the values are set. dima[0] = numInitializers; Object initializers = Array.newInstance(baseType, dima); // Evaluate the initializers for (int i = 0; i < numInitializers; i++) { SimpleNode node = (SimpleNode) jjtGetChild(i); Object currentInitializer; if (node instanceof BSHArrayInitializer) { if (dimensions < 2) throw new EvalError("Invalid Location for Intializer, position: " + i, this, callstack); currentInitializer = ((BSHArrayInitializer) node).eval(baseType, dimensions - 1, callstack, interpreter); } else currentInitializer = node.eval(callstack, interpreter); if (currentInitializer == Primitive.VOID) throw new EvalError("Void in array initializer, position" + i, this, callstack); // Determine if any conversion is necessary on the initializers. // // Quick test to see if conversions apply: // If the dimensionality of the array is 1 then the elements of // the initializer can be primitives or boxable types. If it is // greater then the values must be array (object) types and there // are currently no conversions that we do on those. // If we have conversions on those in the future then we need to // get the real base type here instead of the dimensionless one. Object value = currentInitializer; if (dimensions == 1) { // We do a bsh cast here. strictJava should be able to affect // the cast there when we tighten control try { value = Types.castObject(currentInitializer, baseType, Types.CAST); } catch (UtilEvalError e) { throw e.toEvalError("Error in array initializer", this, callstack); } // unwrap any primitive, map voids to null, etc. value = Primitive.unwrap(value); } // store the value in the array try { Array.set(initializers, i, value); } catch (IllegalArgumentException e) { Interpreter.debug("illegal arg" + e); throwTypeError(baseType, currentInitializer, i, callstack); } catch (ArrayStoreException e) { // I think this can happen Interpreter.debug("arraystore" + e); throwTypeError(baseType, currentInitializer, i, callstack); } } return initializers; }