예제 #1
0
    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;
  }