コード例 #1
0
 static Method findSingleMethod(Method[] methods, String name) {
   Method found = null;
   for (int i = 0, N = methods.length; i != N; ++i) {
     Method method = methods[i];
     if ((method != null) && name.equals(method.getName())) {
       if (found != null) {
         throw Context.reportRuntimeError2(
             "msg.no.overload", name, method.getDeclaringClass().getName());
       }
       found = method;
     }
   }
   return found;
 }
コード例 #2
0
  /**
   * Create a JavaScript function object from a Java method.
   *
   * <p>The <code>member</code> argument must be either a java.lang.reflect.Method
   * or a java.lang.reflect.Constructor and must match one of two forms.<p>
   *
   * The first form is a member with zero or more parameters
   * of the following types: Object, String, boolean, Scriptable,
   * int, or double. The Long type is not supported
   * because the double representation of a long (which is the
   * EMCA-mandated storage type for Numbers) may lose precision.
   * If the member is a Method, the return value must be void or one
   * of the types allowed for parameters.<p>
   *
   * The runtime will perform appropriate conversions based
   * upon the type of the parameter. A parameter type of
   * Object specifies that no conversions are to be done. A parameter
   * of type String will use Context.toString to convert arguments.
   * Similarly, parameters of type double, boolean, and Scriptable
   * will cause Context.toNumber, Context.toBoolean, and
   * Context.toObject, respectively, to be called.<p>
   *
   * If the method is not static, the Java 'this' value will
   * correspond to the JavaScript 'this' value. Any attempt
   * to call the function with a 'this' value that is not
   * of the right Java type will result in an error.<p>
   *
   * The second form is the variable arguments (or "varargs")
   * form. If the FunctionObject will be used as a constructor,
   * the member must have the following parameters
   * <pre>
   *      (Context cx, Object[] args, Function ctorObj,
   *       boolean inNewExpr)</pre>
   * and if it is a Method, be static and return an Object result.<p>
   *
   * Otherwise, if the FunctionObject will <i>not</i> be used to define a
   * constructor, the member must be a static Method with parameters
   *      (Context cx, Scriptable thisObj, Object[] args,
   *       Function funObj) </pre>
   * <pre>
   * and an Object result.<p>
   *
   * When the function varargs form is called as part of a function call,
   * the <code>args</code> parameter contains the
   * arguments, with <code>thisObj</code>
   * set to the JavaScript 'this' value. <code>funObj</code>
   * is the function object for the invoked function.<p>
   *
   * When the constructor varargs form is called or invoked while evaluating
   * a <code>new</code> expression, <code>args</code> contains the
   * arguments, <code>ctorObj</code> refers to this FunctionObject, and
   * <code>inNewExpr</code> is true if and only if  a <code>new</code>
   * expression caused the call. This supports defining a function that
   * has different behavior when called as a constructor than when
   * invoked as a normal function call. (For example, the Boolean
   * constructor, when called as a function,
   * will convert to boolean rather than creating a new object.)<p>
   *
   * @param name the name of the function
   * @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor
   *                            that defines the object
   * @param scope enclosing scope of function
   * @see gov.nbcs.rp.common.js.javascript.Scriptable
   */
  public FunctionObject(String name, Member methodOrConstructor, Scriptable scope) {
    if (methodOrConstructor instanceof Constructor) {
      member = new MemberBox((Constructor) methodOrConstructor);
      isStatic = true; // well, doesn't take a 'this'
    } else {
      member = new MemberBox((Method) methodOrConstructor);
      isStatic = member.isStatic();
    }
    String methodName = member.getName();
    this.functionName = name;
    Class[] types = member.argTypes;
    int arity = types.length;
    if ((arity == 4) && (types[1].isArray() || types[2].isArray())) {
      // Either variable args or an error.
      if (types[1].isArray()) {
        if (!isStatic
            || (types[0] != ScriptRuntime.ContextClass)
            || (types[1].getComponentType() != ScriptRuntime.ObjectClass)
            || (types[2] != ScriptRuntime.FunctionClass)
            || (types[3] != Boolean.TYPE)) {
          throw Context.reportRuntimeError1("msg.varargs.ctor", methodName);
        }
        parmsLength = VARARGS_CTOR;
      } else {
        if (!isStatic
            || (types[0] != ScriptRuntime.ContextClass)
            || (types[1] != ScriptRuntime.ScriptableClass)
            || (types[2].getComponentType() != ScriptRuntime.ObjectClass)
            || (types[3] != ScriptRuntime.FunctionClass)) {
          throw Context.reportRuntimeError1("msg.varargs.fun", methodName);
        }
        parmsLength = VARARGS_METHOD;
      }
    } else {
      parmsLength = arity;
      if (arity > 0) {
        typeTags = new byte[arity];
        for (int i = 0; i != arity; ++i) {
          int tag = getTypeTag(types[i]);
          if (tag == JAVA_UNSUPPORTED_TYPE) {
            throw Context.reportRuntimeError2("msg.bad.parms", types[i].getName(), methodName);
          }
          typeTags[i] = (byte) tag;
        }
      }
    }

    if (member.isMethod()) {
      Method method = member.method();
      Class returnType = method.getReturnType();
      if (returnType == Void.TYPE) {
        hasVoidReturn = true;
      } else {
        returnTypeTag = getTypeTag(returnType);
      }
    } else {
      Class ctorType = member.getDeclaringClass();
      if (!ScriptRuntime.ScriptableClass.isAssignableFrom(ctorType)) {
        throw Context.reportRuntimeError1("msg.bad.ctor.return", ctorType.getName());
      }
    }

    ScriptRuntime.setFunctionProtoAndParent(this, scope);
  }
コード例 #3
0
ファイル: JavaAdapter.java プロジェクト: sq001/aurora-project
  static Object js_createAdapter(Context cx, Scriptable scope, Object[] args) {
    int N = args.length;
    if (N == 0) {
      throw ScriptRuntime.typeError0("msg.adapter.zero.args");
    }

    // Expected arguments:
    // Any number of NativeJavaClass objects representing the super-class
    // and/or interfaces to implement, followed by one NativeObject providing
    // the implementation, followed by any number of arguments to pass on
    // to the (super-class) constructor.

    int classCount;
    for (classCount = 0; classCount < N - 1; classCount++) {
      Object arg = args[classCount];
      // We explicitly test for NativeObject here since checking for
      // instanceof ScriptableObject or !(instanceof NativeJavaClass)
      // would fail for a Java class that isn't found in the class path
      // as NativeJavaPackage extends ScriptableObject.
      if (arg instanceof NativeObject) {
        break;
      }
      if (!(arg instanceof NativeJavaClass)) {
        throw ScriptRuntime.typeError2(
            "msg.not.java.class.arg", String.valueOf(classCount), ScriptRuntime.toString(arg));
      }
    }
    Class<?> superClass = null;
    Class<?>[] intfs = new Class[classCount];
    int interfaceCount = 0;
    for (int i = 0; i < classCount; ++i) {
      Class<?> c = ((NativeJavaClass) args[i]).getClassObject();
      if (!c.isInterface()) {
        if (superClass != null) {
          throw ScriptRuntime.typeError2("msg.only.one.super", superClass.getName(), c.getName());
        }
        superClass = c;
      } else {
        intfs[interfaceCount++] = c;
      }
    }

    if (superClass == null) {
      superClass = ScriptRuntime.ObjectClass;
    }

    Class<?>[] interfaces = new Class[interfaceCount];
    System.arraycopy(intfs, 0, interfaces, 0, interfaceCount);
    // next argument is implementation, must be scriptable
    Scriptable obj = ScriptableObject.ensureScriptable(args[classCount]);

    Class<?> adapterClass = getAdapterClass(scope, superClass, interfaces, obj);
    Object adapter;

    int argsCount = N - classCount - 1;
    try {
      if (argsCount > 0) {
        // Arguments contain parameters for super-class constructor.
        // We use the generic Java method lookup logic to find and
        // invoke the right constructor.
        Object[] ctorArgs = new Object[argsCount + 2];
        ctorArgs[0] = obj;
        ctorArgs[1] = cx.getFactory();
        System.arraycopy(args, classCount + 1, ctorArgs, 2, argsCount);
        // TODO: cache class wrapper?
        NativeJavaClass classWrapper = new NativeJavaClass(scope, adapterClass, true);
        NativeJavaMethod ctors = classWrapper.members.ctors;
        int index = ctors.findCachedFunction(cx, ctorArgs);
        if (index < 0) {
          String sig = NativeJavaMethod.scriptSignature(args);
          throw Context.reportRuntimeError2("msg.no.java.ctor", adapterClass.getName(), sig);
        }

        // Found the constructor, so try invoking it.
        adapter = NativeJavaClass.constructInternal(ctorArgs, ctors.methods[index]);
      } else {
        Class<?>[] ctorParms = {ScriptRuntime.ScriptableClass, ScriptRuntime.ContextFactoryClass};
        Object[] ctorArgs = {obj, cx.getFactory()};
        adapter = adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
      }

      Object self = getAdapterSelf(adapterClass, adapter);
      // Return unwrapped JavaAdapter if it implements Scriptable
      if (self instanceof Wrapper) {
        Object unwrapped = ((Wrapper) self).unwrap();
        if (unwrapped instanceof Scriptable) {
          if (unwrapped instanceof ScriptableObject) {
            ScriptRuntime.setObjectProtoAndParent((ScriptableObject) unwrapped, scope);
          }
          return unwrapped;
        }
      }
      return self;
    } catch (Exception ex) {
      throw Context.throwAsScriptRuntimeEx(ex);
    }
  }
コード例 #4
0
ファイル: JavaMembers.java プロジェクト: jenkinsci/core-js
 RuntimeException reportMemberNotFound(String memberName) {
   return Context.reportRuntimeError2("msg.java.member.not.found", cl.getName(), memberName);
 }
コード例 #5
0
 static void reportConversionError(Object value, Class<?> type) {
   // It uses String.valueOf(value), not value.toString() since
   // value can be null, bug 282447.
   throw Context.reportRuntimeError2(
       "msg.conversion.not.allowed", String.valueOf(value), JavaMembers.javaSignature(type));
 }