Esempio n. 1
0
  private Object getExplicitFunction(
      Scriptable scope, String name, Object javaObject, boolean isStatic) {
    Map<String, Object> ht = isStatic ? staticMembers : members;
    Object member = null;
    MemberBox methodOrCtor = findExplicitFunction(name, isStatic);

    if (methodOrCtor != null) {
      Scriptable prototype = ScriptableObject.getFunctionPrototype(scope);

      if (methodOrCtor.isCtor()) {
        NativeJavaConstructor fun = new NativeJavaConstructor(methodOrCtor);
        fun.setPrototype(prototype);
        member = fun;
        ht.put(name, fun);
      } else {
        String trueName = methodOrCtor.getName();
        member = ht.get(trueName);

        if (member instanceof NativeJavaMethod && ((NativeJavaMethod) member).methods.length > 1) {
          NativeJavaMethod fun = new NativeJavaMethod(methodOrCtor, name);
          fun.setPrototype(prototype);
          ht.put(name, fun);
          member = fun;
        }
      }
    }

    return member;
  }
Esempio n. 2
0
  void put(Scriptable scope, String name, Object javaObject, Object value, boolean isStatic) {
    Map<String, Object> ht = isStatic ? staticMembers : members;
    Object member = ht.get(name);
    if (!isStatic && member == null) {
      // Try to get static member from instance (LC3)
      member = staticMembers.get(name);
    }
    if (member == null) throw reportMemberNotFound(name);
    if (member instanceof FieldAndMethods) {
      FieldAndMethods fam = (FieldAndMethods) ht.get(name);
      member = fam.field;
    }

    // Is this a bean property "set"?
    if (member instanceof BeanProperty) {
      BeanProperty bp = (BeanProperty) member;
      if (bp.setter == null) {
        throw reportMemberNotFound(name);
      }
      // If there's only one setter or if the value is null, use the
      // main setter. Otherwise, let the NativeJavaMethod decide which
      // setter to use:
      if (bp.setters == null || value == null) {
        Class<?> setType = bp.setter.argTypes[0];
        Object[] args = {Context.jsToJava(value, setType)};
        try {
          bp.setter.invoke(javaObject, args);
        } catch (Exception ex) {
          throw Context.throwAsScriptRuntimeEx(ex);
        }
      } else {
        Object[] args = {value};
        bp.setters.call(
            Context.getContext(), ScriptableObject.getTopLevelScope(scope), scope, args);
      }
    } else {
      if (!(member instanceof Field)) {
        String str = (member == null) ? "msg.java.internal.private" : "msg.java.method.assign";
        throw Context.reportRuntimeError1(str, name);
      }
      Field field = (Field) member;
      Object javaValue = Context.jsToJava(value, field.getType());
      try {
        field.set(javaObject, javaValue);
      } catch (IllegalAccessException accessEx) {
        if ((field.getModifiers() & Modifier.FINAL) != 0) {
          // treat Java final the same as JavaScript [[READONLY]]
          return;
        }
        throw Context.throwAsScriptRuntimeEx(accessEx);
      } catch (IllegalArgumentException argEx) {
        throw Context.reportRuntimeError3(
            "msg.java.internal.field.type",
            value.getClass().getName(),
            field,
            javaObject.getClass().getName());
      }
    }
  }
Esempio n. 3
0
 private static ObjToIntMap getObjectFunctionNames(Scriptable obj) {
   Object[] ids = ScriptableObject.getPropertyIds(obj);
   ObjToIntMap map = new ObjToIntMap(ids.length);
   for (int i = 0; i != ids.length; ++i) {
     if (!(ids[i] instanceof String)) continue;
     String id = (String) ids[i];
     Object value = ScriptableObject.getProperty(obj, id);
     if (value instanceof Function) {
       Function f = (Function) value;
       int length = ScriptRuntime.toInt32(ScriptableObject.getProperty(f, "length"));
       if (length < 0) {
         length = 0;
       }
       map.put(id, length);
     }
   }
   return map;
 }
Esempio n. 4
0
  public LazilyLoadedCtor(
      ScriptableObject scope, String propertyName, String className, boolean sealed) {

    this.scope = scope;
    this.propertyName = propertyName;
    this.className = className;
    this.sealed = sealed;
    this.state = STATE_BEFORE_INIT;

    scope.addLazilyInitializedValue(propertyName, 0, this, ScriptableObject.DONTENUM);
  }
Esempio n. 5
0
  public static Function getFunction(Scriptable obj, String functionName) {
    Object x = ScriptableObject.getProperty(obj, functionName);
    if (x == Scriptable.NOT_FOUND) {
      // This method used to swallow the exception from calling
      // an undefined method. People have come to depend on this
      // somewhat dubious behavior. It allows people to avoid
      // implementing listener methods that they don't care about,
      // for instance.
      return null;
    }
    if (!(x instanceof Function)) throw ScriptRuntime.notFunctionError(x, functionName);

    return (Function) x;
  }
Esempio n. 6
0
 private Object buildValue() {
   Class cl = Kit.classOrNull(className);
   if (cl != null) {
     try {
       Object value = ScriptableObject.buildClassCtor(scope, cl, sealed, false);
       if (value == null) {
         // cl has own static initializer which is expected
         // to set the property on its own.
         value = scope.get(propertyName, scope);
         if (value != Scriptable.NOT_FOUND) return value;
       }
     } catch (InvocationTargetException ex) {
       Throwable target = ex.getTargetException();
       if (target instanceof RuntimeException) {
         throw (RuntimeException) target;
       }
     } catch (RhinoException ex) {
     } catch (InstantiationException ex) {
     } catch (IllegalAccessException ex) {
     } catch (SecurityException ex) {
     }
   }
   return Scriptable.NOT_FOUND;
 }
Esempio n. 7
0
  static JavaMembers lookupClass(
      Scriptable scope, Class<?> dynamicType, Class<?> staticType, boolean includeProtected) {
    JavaMembers members;
    scope = ScriptableObject.getTopLevelScope(scope);
    ClassCache cache = ClassCache.get(scope);
    Map<Class<?>, JavaMembers> ct = cache.getClassCacheMap();

    Class<?> cl = dynamicType;
    for (; ; ) {
      members = ct.get(cl);
      if (members != null) {
        return members;
      }
      try {
        members = new JavaMembers(scope, cl, includeProtected);
        break;
      } catch (SecurityException e) {
        // Reflection may fail for objects that are in a restricted
        // access package (e.g. sun.*).  If we get a security
        // exception, try again with the static type if it is interface.
        // Otherwise, try superclass
        if (staticType != null && staticType.isInterface()) {
          cl = staticType;
          staticType = null; // try staticType only once
        } else {
          Class<?> parent = cl.getSuperclass();
          if (parent == null) {
            if (cl.isInterface()) {
              // last resort after failed staticType interface
              parent = ScriptRuntime.ObjectClass;
            } else {
              throw e;
            }
          }
          cl = parent;
        }
      }
    }

    if (cache.isCachingEnabled()) ct.put(cl, members);
    return members;
  }
Esempio n. 8
0
 Object get(Scriptable scope, String name, Object javaObject, boolean isStatic) {
   Map<String, Object> ht = isStatic ? staticMembers : members;
   Object member = ht.get(name);
   if (!isStatic && member == null) {
     // Try to get static member from instance (LC3)
     member = staticMembers.get(name);
   }
   if (member == null) {
     member =
         this.getExplicitFunction(
             scope, name,
             javaObject, isStatic);
     if (member == null) return Scriptable.NOT_FOUND;
   }
   if (member instanceof Scriptable) {
     return member;
   }
   Context cx = Context.getContext();
   Object rval;
   Class<?> type;
   try {
     if (member instanceof BeanProperty) {
       BeanProperty bp = (BeanProperty) member;
       if (bp.getter == null) return Scriptable.NOT_FOUND;
       rval = bp.getter.invoke(javaObject, Context.emptyArgs);
       type = bp.getter.method().getReturnType();
     } else {
       Field field = (Field) member;
       rval = field.get(isStatic ? null : javaObject);
       type = field.getType();
     }
   } catch (Exception ex) {
     throw Context.throwAsScriptRuntimeEx(ex);
   }
   // Need to wrap the object before we return it.
   scope = ScriptableObject.getTopLevelScope(scope);
   return cx.getWrapFactory().wrap(cx, scope, rval, type);
 }
Esempio n. 9
0
 FieldAndMethods(Scriptable scope, MemberBox[] methods, Field field) {
   super(methods);
   this.field = field;
   setParentScope(scope);
   setPrototype(ScriptableObject.getFunctionPrototype(scope));
 }
Esempio n. 10
0
 public static Scriptable createAdapterWrapper(Scriptable obj, Object adapter) {
   Scriptable scope = ScriptableObject.getTopLevelScope(obj);
   NativeJavaObject res = new NativeJavaObject(scope, adapter, null, true);
   res.setPrototype(obj);
   return res;
 }
Esempio n. 11
0
  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);
    }
  }
  /** Type-munging for field setting and method invocation. Conforms to LC3 specification */
  static Object coerceTypeImpl(Class<?> type, Object value) {
    if (value != null && value.getClass() == type) {
      return value;
    }

    switch (getJSTypeCode(value)) {
      case JSTYPE_NULL:
        // raise error if type.isPrimitive()
        if (type.isPrimitive()) {
          reportConversionError(value, type);
        }
        return null;

      case JSTYPE_UNDEFINED:
        if (type == ScriptRuntime.StringClass || type == ScriptRuntime.ObjectClass) {
          return "undefined";
        } else {
          reportConversionError("undefined", type);
        }
        break;

      case JSTYPE_BOOLEAN:
        // Under LC3, only JS Booleans can be coerced into a Boolean value
        if (type == Boolean.TYPE
            || type == ScriptRuntime.BooleanClass
            || type == ScriptRuntime.ObjectClass) {
          return value;
        } else if (type == ScriptRuntime.StringClass) {
          return value.toString();
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_NUMBER:
        if (type == ScriptRuntime.StringClass) {
          return ScriptRuntime.toString(value);
        } else if (type == ScriptRuntime.ObjectClass) {
          return coerceToNumber(Double.TYPE, value);
        } else if ((type.isPrimitive() && type != Boolean.TYPE)
            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
          return coerceToNumber(type, value);
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_STRING:
        if (type == ScriptRuntime.StringClass || type.isInstance(value)) {
          return value;
        } else if (type == Character.TYPE || type == ScriptRuntime.CharacterClass) {
          // Special case for converting a single char string to a
          // character
          // Placed here because it applies *only* to JS strings,
          // not other JS objects converted to strings
          if (((String) value).length() == 1) {
            return new Character(((String) value).charAt(0));
          } else {
            return coerceToNumber(type, value);
          }
        } else if ((type.isPrimitive() && type != Boolean.TYPE)
            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
          return coerceToNumber(type, value);
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_JAVA_CLASS:
        if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
        }

        if (type == ScriptRuntime.ClassClass || type == ScriptRuntime.ObjectClass) {
          return value;
        } else if (type == ScriptRuntime.StringClass) {
          return value.toString();
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_JAVA_OBJECT:
      case JSTYPE_JAVA_ARRAY:
        if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
        }
        if (type.isPrimitive()) {
          if (type == Boolean.TYPE) {
            reportConversionError(value, type);
          }
          return coerceToNumber(type, value);
        } else {
          if (type == ScriptRuntime.StringClass) {
            return value.toString();
          } else {
            if (type.isInstance(value)) {
              return value;
            } else {
              reportConversionError(value, type);
            }
          }
        }
        break;

      case JSTYPE_OBJECT:
        if (type == ScriptRuntime.StringClass) {
          return ScriptRuntime.toString(value);
        } else if (type.isPrimitive()) {
          if (type == Boolean.TYPE) {
            reportConversionError(value, type);
          }
          return coerceToNumber(type, value);
        } else if (type.isInstance(value)) {
          return value;
        } else if (type == ScriptRuntime.DateClass && value instanceof NativeDate) {
          double time = ((NativeDate) value).getJSTimeValue();
          // XXX: This will replace NaN by 0
          return new Date((long) time);
        } else if (type.isArray() && value instanceof NativeArray) {
          // Make a new java array, and coerce the JS array components
          // to the target (component) type.
          NativeArray array = (NativeArray) value;
          long length = array.getLength();
          Class<?> arrayType = type.getComponentType();
          Object Result = Array.newInstance(arrayType, (int) length);
          for (int i = 0; i < length; ++i) {
            try {
              Array.set(Result, i, coerceType(arrayType, array.get(i, array)));
            } catch (EvaluatorException ee) {
              reportConversionError(value, type);
            }
          }

          return Result;
        } else if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
          if (type.isInstance(value)) return value;
          reportConversionError(value, type);
        } else if (type.isInterface() && value instanceof Callable) {
          // Try to use function as implementation of Java interface.
          //
          // XXX: Currently only instances of ScriptableObject are
          // supported since the resulting interface proxies should
          // be reused next time conversion is made and generic
          // Callable has no storage for it. Weak references can
          // address it but for now use this restriction.
          if (value instanceof ScriptableObject) {
            ScriptableObject so = (ScriptableObject) value;
            Object key = Kit.makeHashKeyFromPair(COERCED_INTERFACE_KEY, type);
            Object old = so.getAssociatedValue(key);
            if (old != null) {
              // Function was already wrapped
              return old;
            }
            Context cx = Context.getContext();
            Object glue = InterfaceAdapter.create(cx, type, (Callable) value);
            // Store for later retrival
            glue = so.associateValue(key, glue);
            return glue;
          }
          reportConversionError(value, type);
        } else {
          reportConversionError(value, type);
        }
        break;
    }

    return value;
  }
 public Scriptable getPrototype() {
   if (prototype == null && javaObject instanceof String) {
     return ScriptableObject.getClassPrototype(parent, "String");
   }
   return prototype;
 }