/**
   * Create a default object of the given type. Prefers constructors with as few arguments as
   * possible. Creates an empty proxy for interfaces.
   *
   * @param type type to instantiate
   * @return default instance
   * @throws Exception if the default instance could not be created
   */
  private static Object instantiateType(Class<?> type) throws Exception {
    if (type.isPrimitive()) return Defaults.defaultValue(type);
    else if (type == Void.class) return null;
    else if (type.isArray()) return Array.newInstance(type, 0);
    else if (type.isInterface())
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          new Class[] {type},
          new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              return null;
            }
          });

    // Take a constructor with as few params as possible
    Constructor constructor = type.getDeclaredConstructors()[0];
    for (Constructor<?> c : type.getDeclaredConstructors()) {
      if (c.getParameterTypes().length < constructor.getParameterTypes().length) constructor = c;
    }

    Object[] params = new Object[constructor.getParameterTypes().length];
    for (int i = 0; i < constructor.getParameterTypes().length; i++) {
      params[i] = instantiateType(constructor.getParameterTypes()[i]);
    }
    return constructor.newInstance(params);
  }
Ejemplo n.º 2
0
  /**
   * Sets up the mocks defined in the given mock class.
   *
   * <p>If the type {@linkplain MockClass#realClass referred to} by the mock class is actually an
   * interface, then a {@linkplain #newEmptyProxy(ClassLoader, Class) new empty proxy} is created.
   *
   * @param mockClassOrInstance the mock class itself (given by its {@code Class} literal), or an
   *     instance of the mock class
   * @return the new proxy instance created for the mocked interface, or {@code null} otherwise
   * @throws IllegalArgumentException if a given mock class fails to specify the corresponding real
   *     class using the {@code @MockClass(realClass = ...)} annotation; or if a mock class defines
   *     a mock method for which no corresponding real method or constructor exists in the real
   *     class; or if the real method matching a mock method is {@code abstract}
   * @see #setUpMock(Class, Object)
   * @see #setUpMocks(Object...)
   * @see <a
   *     href="http://code.google.com/p/jmockit/source/browse/trunk/main/test/mockit/MockAnnotationsTest.java#696">
   *     Example</a>
   */
  public static <T> T setUpMock(Object mockClassOrInstance) {
    Class<?> mockClass;
    Object mock;

    if (mockClassOrInstance instanceof Class<?>) {
      mockClass = (Class<?>) mockClassOrInstance;
      mock = null;
    } else {
      mockClass = mockClassOrInstance.getClass();
      mock = mockClassOrInstance;
    }

    MockClassSetup setup = new MockClassSetup(mock, mockClass);
    Class<?> realClass = setup.getRealClass();
    T proxy = null;

    if (realClass.isInterface()) {
      //noinspection unchecked
      proxy = (T) newEmptyProxy(mockClass.getClassLoader(), realClass);
      setup.setRealClass(proxy.getClass());
    }

    setup.redefineMethods();

    return proxy;
  }
Ejemplo n.º 3
0
  @Nullable
  public InstanceFactory findInstanceFactory(@Nonnull Type mockedType) {
    InstanceFactory instanceFactory = mockedTypesAndInstances.get(mockedType);

    if (instanceFactory != null) {
      return instanceFactory;
    }

    Class<?> mockedClass = getClassType(mockedType);
    //noinspection ReuseOfLocalVariable
    instanceFactory = mockedTypesAndInstances.get(mockedClass);

    if (instanceFactory != null) {
      return instanceFactory;
    }

    boolean abstractType = mockedClass.isInterface() || isAbstract(mockedClass.getModifiers());

    for (Entry<Type, InstanceFactory> entry : mockedTypesAndInstances.entrySet()) {
      Type registeredMockedType = entry.getKey();
      Class<?> registeredMockedClass = getClassType(registeredMockedType);

      if (abstractType) {
        registeredMockedClass = getMockedClassOrInterfaceType(registeredMockedClass);
      }

      if (mockedClass.isAssignableFrom(registeredMockedClass)) {
        instanceFactory = entry.getValue();
        break;
      }
    }

    return instanceFactory;
  }
Ejemplo n.º 4
0
  public static void validatePassivating(Class<?> cl, Bean<?> bean, String typeName) {
    Class<?> beanClass = bean.getBeanClass();

    if (!Serializable.class.isAssignableFrom(beanClass) && false) {
      ConfigException exn =
          new ConfigException(
              L.l(
                  "{0}: {1} is an invalid {2} because it is not serializable.",
                  cl.getName(), bean, typeName));

      throw exn;
      // InjectManager.create().addDefinitionError(exn);
    }

    for (InjectionPoint ip : bean.getInjectionPoints()) {
      if (ip.isTransient() || ip.isDelegate()) continue;

      Class<?> type = getRawClass(ip.getType());

      if (type.isInterface()) continue;

      if (!Serializable.class.isAssignableFrom(type)) {
        ConfigException exn =
            new ConfigException(
                L.l(
                    "{0}: {1} is an invalid {4} because its injection point '{2}' of type {3} is not serializable.",
                    cl.getName(), bean, ip.getMember().getName(), ip.getType(), typeName));

        throw exn;
      }
    }
  }
Ejemplo n.º 5
0
  public SAMSignature(Class<SAM> samType, Class<?>[] genericTypes) {
    this.samType = samType;
    if (!samType.isInterface()) {
      throw new LambdaException("SAM class [%s] is required to be an interface", samType.getName());
    }

    buildGenericTypeVariables(genericTypes);
    findSamMethod();
    BuildSignature();
  }
Ejemplo n.º 6
0
  public static void premain(String args, Instrumentation inst) throws Exception {
    try {
      String[] agentArgs;
      if (args == null) agentArgs = new String[] {""};
      else agentArgs = args.split(",");
      if (!agentArgs[0].equals("instrumenting")) jarFileName = agentArgs[0];
      BaseClassTransformer rct = null;
      rct = new BaseClassTransformer();
      if (agentArgs[0].equals("instrumenting")) {
        initVMClasses = new HashSet<String>();
        for (Class<?> c : inst.getAllLoadedClasses()) {
          ((Set<String>) initVMClasses).add(c.getName());
        }
      }
      if (!agentArgs[0].equals("instrumenting")) {

        inst.addTransformer(rct);
        Tracer.setLocals(new CounterThreadLocal());
        Tracer.overrideAll(true);
        for (Class<?> c : inst.getAllLoadedClasses()) {
          try {
            if (c.isInterface()) continue;
            if (c.isArray()) continue;
            byte[] bytes = rct.getBytes(c.getName());
            if (bytes == null) {
              continue;
            }
            inst.redefineClasses(new ClassDefinition[] {new ClassDefinition(c, bytes)});
          } catch (Throwable e) {
            synchronized (System.err) {
              System.err.println("" + c + " failed...");
              e.printStackTrace();
            }
          }
        }
        Runtime.getRuntime()
            .addShutdownHook(
                new Thread() {
                  public void run() {
                    Tracer.mark();
                    try {
                      PrintStream ps = new PrintStream("bailout.txt");
                      ps.println("Bailouts: " + Tracer.getBailoutCount());
                      ps.close();
                    } catch (Exception e) {
                    }
                    Tracer.unmark();
                  }
                });
        if ("true".equals(System.getProperty("bci.observerOn"))) Tracer.overrideAll(false);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
Ejemplo 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;
  }
Ejemplo n.º 8
0
 private T newContextObject() {
   try {
     if (type.isInterface()) {
       return (T) Classes.newDynamicProxy(type);
     } else {
       return (T) type.newInstance();
     }
   } catch (Exception anExc) {
     throw new XmlReadingException(anExc);
   }
 }
Ejemplo n.º 9
0
 public <T> T getInterface(Object thiz, Class<T> iface) throws ScriptException {
   if (iface == null || !iface.isInterface()) {
     throw new IllegalArgumentException("interface Class expected");
   }
   AccessControlContext accCtxt = AccessController.getContext();
   return iface.cast(
       Proxy.newProxyInstance(
           iface.getClassLoader(),
           new Class[] {iface},
           new InterfaceImplementorInvocationHandler(thiz, accCtxt)));
 }
Ejemplo n.º 10
0
 public static PropertyDescriptor[] getPropertyDescriptors(Class<?> objectClass) {
   // If the class is an interface, use custom method to get all prop descriptors in the
   // inheritance hierarchy.
   // PropertyUtils.getPropertyDescriptors() does not work correctly for interface inheritance. It
   // finds props in the
   // actual interface ok, but does not find props in the inheritance hierarchy.
   if (objectClass.isInterface()) {
     return getInterfacePropertyDescriptors(objectClass);
   } else {
     return BeanUtils.getPropertyDescriptors(objectClass);
   }
 }
Ejemplo n.º 11
0
  TestedField(
      @Nonnull InjectionState injectionState, @Nonnull Field field, @Nonnull Tested metadata) {
    this.injectionState = injectionState;
    testedField = field;
    this.metadata = metadata;
    fullInjection = metadata.fullyInitialized() ? new FullInjection(injectionState) : null;

    Class<?> fieldType = field.getType();

    if (fieldType.isInterface()) {
      testedObjectCreation = null;
    } else {
      testedObjectCreation = new TestedObjectCreation(injectionState, fullInjection, field);
      injectionState.lifecycleMethods.findLifecycleMethods(fieldType);
    }
  }
Ejemplo n.º 12
0
 private static void checkTypeAndAnnotations(Binder binder, Class<?> type) {
   if (!type.isInterface()) {
     binder.addError("Type %s must be an interface", type);
   }
   if (!Finders.class.isAssignableFrom(type)) {
     binder.addError("Type %s must be annotated with %s", type, Finders.class);
   }
   for (Method method : type.getMethods()) {
     if (!method.isAnnotationPresent(Finder.class)) {
       binder.addError("Method %s must be annotated with %s", method, Finder.class);
     }
     if (method.getReturnType() != Iterator.class) {
       binder.addError("Method %s must return an %s", method, Iterator.class);
     } else if (!resultType(method).isInterface()) {
       binder.addError("%s must be an interface on method %s", resultType(method), method);
     }
   }
 }
Ejemplo n.º 13
0
  static Object js_createAdpter(Context cx, Scriptable scope, Object[] args) {
    int N = args.length;
    if (N == 0) {
      throw ScriptRuntime.typeError0("msg.adapter.zero.args");
    }

    Class superClass = null;
    Class[] intfs = new Class[N - 1];
    int interfaceCount = 0;
    for (int i = 0; i != N - 1; ++i) {
      Object arg = args[i];
      if (!(arg instanceof NativeJavaClass)) {
        throw ScriptRuntime.typeError2(
            "msg.not.java.class.arg", String.valueOf(i), ScriptRuntime.toString(arg));
      }
      Class c = ((NativeJavaClass) arg).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);
    Scriptable obj = ScriptRuntime.toObject(cx, scope, args[N - 1]);

    Class adapterClass = getAdapterClass(scope, superClass, interfaces, obj);

    Class[] ctorParms = {ScriptRuntime.ContextFactoryClass, ScriptRuntime.ScriptableClass};
    Object[] ctorArgs = {cx.getFactory(), obj};
    try {
      Object adapter = adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
      return getAdapterSelf(adapterClass, adapter);
    } catch (Exception ex) {
      throw Context.throwAsScriptRuntimeEx(ex);
    }
  }
Ejemplo n.º 14
0
  /**
   * Return true if the type is not abstract and not an interface, and has a constructor annotated
   * with {@link Inject} or its only constructor is the default constructor.
   *
   * @param type A class type
   * @return True if the class type is instantiable
   */
  public static boolean isInstantiable(Class<?> type) {
    if (!Modifier.isAbstract(type.getModifiers()) && !type.isInterface()) {
      // first check for a constructor annotated with @Inject,
      //  - this doesn't care how many we'll let the injector complain
      //    if there are more than one
      for (Constructor<?> c : type.getDeclaredConstructors()) {
        if (c.getAnnotation(Inject.class) != null) {
          return true;
        }
      }

      // check if we only have the public default constructor
      if (type.getConstructors().length == 1
          && type.getConstructors()[0].getParameterTypes().length == 0) {
        return true;
      }
    }

    // no constructor available
    return false;
  }
Ejemplo n.º 15
0
  /**
   * Return the type distance between the child and parent types. The child type must be a subtype
   * of the parent. The type distance between a class and itself is 0; the distance from a class to
   * one of its immediate supertypes (superclass or a directly implemented interface) is 1; deeper
   * distances are computed recursively.
   *
   * @param child The child type
   * @param parent The parent type
   * @return The type distance
   * @throws IllegalArgumentException if {@code child} is not a subtype of {@code parent}.
   */
  public static int getTypeDistance(@Nonnull Class<?> child, @Nonnull Class<?> parent) {
    Preconditions.notNull("child class", child);
    Preconditions.notNull("parent class", parent);

    if (child.equals(parent)) {
      // fast-path same-class tests
      return 0;
    } else if (!parent.isAssignableFrom(child)) {
      // if child does not extend from the parent, return -1
      throw new IllegalArgumentException("child not a subclass of parent");
    } else if (!parent.isInterface()) {
      // if the parent is not an interface, we only need to follower superclasses
      int distance = 0;
      Class<?> cur = child;
      while (!cur.equals(parent)) {
        distance++;
        cur = cur.getSuperclass();
      }
      return distance;
    } else {
      // worst case, recursively compute the type
      // recursion is safe, as types aren't too deep except in crazy-land
      int minDepth = Integer.MAX_VALUE;
      Class<?> sup = child.getSuperclass();
      if (sup != null && parent.isAssignableFrom(sup)) {
        minDepth = getTypeDistance(sup, parent);
      }
      for (Class<?> iface : child.getInterfaces()) {
        if (parent.isAssignableFrom(iface)) {
          int d = getTypeDistance(iface, parent);
          if (d < minDepth) {
            minDepth = d;
          }
        }
      }
      // minDepth now holds the depth of the superclass with shallowest depth
      return minDepth + 1;
    }
  }
Ejemplo n.º 16
0
  // Other notes to implementors:
  // <p>
  // No stable mapping is promised between the single-method interface and
  // the implementation class C.  Over time, several implementation
  // classes might be used for the same type.
  // <p>
  // If the implementation is able
  // to prove that a wrapper of the required type
  // has already been created for a given
  // method handle, or for another method handle with the
  // same behavior, the implementation may return that wrapper in place of
  // a new wrapper.
  // <p>
  // This method is designed to apply to common use cases
  // where a single method handle must interoperate with
  // an interface that implements a function-like
  // API.  Additional variations, such as single-abstract-method classes with
  // private constructors, or interfaces with multiple but related
  // entry points, must be covered by hand-written or automatically
  // generated adapter classes.
  //
  public static <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
    if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
      throw new IllegalArgumentException("not a public interface: " + intfc.getName());
    final Method[] methods = getSingleNameMethods(intfc);
    if (methods == null)
      throw new IllegalArgumentException("not a single-method interface: " + intfc.getName());
    final MethodHandle[] vaTargets = new MethodHandle[methods.length];
    for (int i = 0; i < methods.length; i++) {
      Method sm = methods[i];
      MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
      MethodHandle checkTarget = target.asType(smMT); // make throw WMT
      checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
      vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
    }
    return intfc.cast(
        Proxy.newProxyInstance(
            intfc.getClassLoader(),
            new Class[] {intfc, WrapperInstance.class},
            new InvocationHandler() {
              private Object getArg(String name) {
                if ((Object) name == "getWrapperInstanceTarget") return target;
                if ((Object) name == "getWrapperInstanceType") return intfc;
                throw new AssertionError();
              }

              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                for (int i = 0; i < methods.length; i++) {
                  if (method.equals(methods[i])) return vaTargets[i].invokeExact(args);
                }
                if (method.getDeclaringClass() == WrapperInstance.class)
                  return getArg(method.getName());
                if (isObjectMethod(method)) return callObjectMethod(this, method, args);
                throw new InternalError("bad proxy method: " + method);
              }
            }));
  }
 private boolean isInterface() {
   return declaringClass.isInterface();
 }
Ejemplo n.º 18
0
  public Type navigateParameterized(String name, Type[] params) throws OclTypeException {
    Type ret = Basic.navigateAnyParameterized(name, params);
    if (ret != null) return ret;

    Method foundmethod = null;

    // this is very similar to tudresden.ocl.lib.OclAnyImpl.findMethod
    // if you find a bug here, its probably there as well.

    // suprisingly one has not to go after interfaces since methods
    // inherited from interfaces are automatically included into the
    // implementing class. This does not happen for methods inherited
    // from the superclass, so we have to ascend to all superclasses.

    // unfortunately the above is only true for classes, getSuperclass invoked
    // on an interface returns null, regardless of the interfaces extended by the
    // interface. Therefore, we need to check out getInterfaces() if iclass is
    // an interface
    HashSet hsVisited = new HashSet();
    LinkedList llToVisit = new LinkedList();
    if (c.isInterface()) {
      // as we're dealing with actual instances, it can be assumed that Object is
      // a superclass
      llToVisit.add(java.lang.Object.class);
    }

    classloop:
    for (Class iclass = c; iclass != null; ) // iclass=iclass.getSuperclass())
    {
      Method[] methods = iclass.getDeclaredMethods();
      methodloop:
      for (int i = 0; i < methods.length; i++) {
        if (!name.equals(methods[i].getName())) continue methodloop;
        Class[] methodparams = methods[i].getParameterTypes();
        if (params.length != methodparams.length) continue methodloop;

        System.err.print("Checking method " + name + " (");
        for (int j = 0; j < methodparams.length; j++) {
          if (j != 0) {
            System.err.print(", ");
          }

          System.err.print(methodparams[j]);
        }
        System.err.println(")");

        for (int j = 0; j < params.length; j++)
          if (!params[j].conformsTo(getTypeForClass(methodparams[j]))) {
            System.err.println("No conformance for paramter # " + j);
            continue methodloop;
          }
        if (foundmethod == null) foundmethod = methods[i];
        else throw new OclTypeException("ambigious method " + name + " of " + c + ") queried.");
        break classloop;
      }

      // determine classes to be visited
      if (iclass.isInterface()) {
        Class[] ca = iclass.getInterfaces();
        for (int i = 0; i < ca.length; i++) {
          if (!hsVisited.contains(ca[i])) {
            llToVisit.add(ca[i]);
          }
        }
      } else {
        if (!hsVisited.contains(iclass.getSuperclass())) {
          llToVisit.add(iclass.getSuperclass());
        }
      }

      // mark current class visited
      hsVisited.add(iclass);

      // go to next class
      if (!llToVisit.isEmpty()) {
        iclass = (Class) llToVisit.remove(0);
      } else {
        iclass = null;
      }
    }

    if (foundmethod == null) {
      StringBuffer sb = new StringBuffer();
      sb.append(c.toString() + " has no method " + name + " with parameters (");
      for (int i = 0; i < params.length; i++) {
        if (i != 0) sb.append(", ");
        sb.append(params[i] + "/" + params[i]);
      }
      sb.append(")");
      throw new OclTypeException(sb.toString());
    }

    return getTypeForClass(foundmethod.getReturnType());
  }
Ejemplo n.º 19
0
 /**
  * Return true if the type is not abstract and not an interface. This will return true essentially
  * when the class "should" have a default constructor or a constructor annotated with {@link
  * Inject @Inject} to be used properly.
  *
  * <p>As another special rule, if the input type is {@link Void}, false is returned because for
  * most intents and purposes, it is not instantiable.
  *
  * @param type The type to test
  * @return True if it should be instantiable
  */
 public static boolean shouldBeInstantiable(Class<?> type) {
   return !Modifier.isAbstract(type.getModifiers())
       && !type.isInterface()
       && !Void.class.equals(type);
 }
Ejemplo n.º 20
0
 private void writeCollection(
     final OutputStream outputStream,
     final Type collectionType,
     final Collection<?> collection,
     final QName outerTagName) {
   final Class<?> rawType;
   if (collectionType instanceof ParameterizedType) {
     final ParameterizedType returnType = (ParameterizedType) collectionType;
     rawType = (Class<?>) returnType.getRawType();
   } else if (collectionType instanceof Class<?>) {
     rawType = (Class<?>) collectionType;
   } else if (collectionType instanceof WildcardType) {
     final Type[] UpperBounds = ((WildcardType) collectionType).getUpperBounds();
     if (UpperBounds.length > 0) {
       rawType = (Class<?>) UpperBounds[0];
     } else {
       rawType = Object.class;
     }
   } else if (collectionType instanceof TypeVariable) {
     final Type[] UpperBounds = ((TypeVariable<?>) collectionType).getBounds();
     if (UpperBounds.length > 0) {
       rawType = (Class<?>) UpperBounds[0];
     } else {
       rawType = Object.class;
     }
   } else {
     throw new IllegalArgumentException("Unsupported type variable");
   }
   Class<?> elementType;
   if (Collection.class.isAssignableFrom(rawType)) {
     final Type[] paramTypes = Types.getTypeParametersFor(Collection.class, collectionType);
     elementType = Types.toRawType(paramTypes[0]);
     if (elementType.isInterface()) {
       // interfaces not supported by jaxb
       elementType = Types.commonAncestor(collection);
     }
   } else {
     elementType = Types.commonAncestor(collection);
   }
   try {
     // As long as JAXB is an option, we have to know that this is a StAXWriter as JAXB needs to
     // write to that.
     try (XmlWriter xmlWriter = XmlStreaming.newWriter(outputStream, "UTF-8")) {
       Marshaller marshaller = null;
       XmlWriterUtil.smartStartTag(xmlWriter, outerTagName);
       for (Object item : collection) {
         if (item != null) {
           if (item instanceof XmlSerializable) {
             ((XmlSerializable) item).serialize(xmlWriter);
           } else if (item instanceof Node) {
             XmlWriterUtil.serialize(xmlWriter, (Node) item);
           } else {
             if (marshaller == null) {
               JAXBContext jaxbcontext = null;
               if (elementType == null) {
                 jaxbcontext = newJAXBContext(JAXBCollectionWrapper.class);
               } else {
                 jaxbcontext = newJAXBContext(JAXBCollectionWrapper.class, elementType);
               }
               marshaller = jaxbcontext.createMarshaller();
             }
             marshaller.marshal(item, (XMLStreamWriter) getDelegateMethod().invoke(xmlWriter));
           }
         }
       }
       XmlWriterUtil.endTag(xmlWriter, outerTagName);
     }
   } catch (Throwable e) {
     throw new MessagingException(e);
   }
 }
 @Override
 public boolean isInterface() {
   return clazz.isInterface();
 }
  /**
   * Derive a ranking based on how "natural" the conversion is. The special value CONVERSION_NONE
   * means no conversion is possible, and CONVERSION_NONTRIVIAL signals that more type conformance
   * testing is required. Based on <a
   * href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">"preferred method
   * conversions" from Live Connect 3</a>
   */
  static int getConversionWeight(Object fromObj, Class<?> to) {
    int fromCode = getJSTypeCode(fromObj);

    switch (fromCode) {
      case JSTYPE_UNDEFINED:
        if (to == ScriptRuntime.StringClass || to == ScriptRuntime.ObjectClass) {
          return 1;
        }
        break;

      case JSTYPE_NULL:
        if (!to.isPrimitive()) {
          return 1;
        }
        break;

      case JSTYPE_BOOLEAN:
        // "boolean" is #1
        if (to == Boolean.TYPE) {
          return 1;
        } else if (to == ScriptRuntime.BooleanClass) {
          return 2;
        } else if (to == ScriptRuntime.ObjectClass) {
          return 3;
        } else if (to == ScriptRuntime.StringClass) {
          return 4;
        }
        break;

      case JSTYPE_NUMBER:
        if (to.isPrimitive()) {
          if (to == Double.TYPE) {
            return 1;
          } else if (to != Boolean.TYPE) {
            return 1 + getSizeRank(to);
          }
        } else {
          if (to == ScriptRuntime.StringClass) {
            // native numbers are #1-8
            return 9;
          } else if (to == ScriptRuntime.ObjectClass) {
            return 10;
          } else if (ScriptRuntime.NumberClass.isAssignableFrom(to)) {
            // "double" is #1
            return 2;
          }
        }
        break;

      case JSTYPE_STRING:
        if (to == ScriptRuntime.StringClass) {
          return 1;
        } else if (to.isInstance(fromObj)) {
          return 2;
        } else if (to.isPrimitive()) {
          if (to == Character.TYPE) {
            return 3;
          } else if (to != Boolean.TYPE) {
            return 4;
          }
        }
        break;

      case JSTYPE_JAVA_CLASS:
        if (to == ScriptRuntime.ClassClass) {
          return 1;
        } else if (to == ScriptRuntime.ObjectClass) {
          return 3;
        } else if (to == ScriptRuntime.StringClass) {
          return 4;
        }
        break;

      case JSTYPE_JAVA_OBJECT:
      case JSTYPE_JAVA_ARRAY:
        Object javaObj = fromObj;
        if (javaObj instanceof Wrapper) {
          javaObj = ((Wrapper) javaObj).unwrap();
        }
        if (to.isInstance(javaObj)) {
          return CONVERSION_NONTRIVIAL;
        }
        if (to == ScriptRuntime.StringClass) {
          return 2;
        } else if (to.isPrimitive() && to != Boolean.TYPE) {
          return (fromCode == JSTYPE_JAVA_ARRAY) ? CONVERSION_NONE : 2 + getSizeRank(to);
        }
        break;

      case JSTYPE_OBJECT:
        // Other objects takes #1-#3 spots
        if (to == fromObj.getClass()) {
          // No conversion required
          return 1;
        }
        if (to.isArray()) {
          if (fromObj instanceof NativeArray) {
            // This is a native array conversion to a java array
            // Array conversions are all equal, and preferable to object
            // and string conversion, per LC3.
            return 1;
          }
        } else if (to == ScriptRuntime.ObjectClass) {
          return 2;
        } else if (to == ScriptRuntime.StringClass) {
          return 3;
        } else if (to == ScriptRuntime.DateClass) {
          if (fromObj instanceof NativeDate) {
            // This is a native date to java date conversion
            return 1;
          }
        } else if (to.isInterface()) {
          if (fromObj instanceof Function) {
            // See comments in coerceType
            if (to.getMethods().length == 1) {
              return 1;
            }
          }
          return 11;
        } else if (to.isPrimitive() && to != Boolean.TYPE) {
          return 3 + getSizeRank(to);
        }
        break;
    }

    return CONVERSION_NONE;
  }
Ejemplo n.º 23
0
  /**
   * Gets the actual type arguments that are used in a given implementation of a given generic base
   * class or interface. (Based on code copyright 2007 by Ian Robertson).
   *
   * @param base the generic base class or interface
   * @param implementation the type (potentially) implementing the given base class or interface
   * @return a list of the raw classes for the actual type arguments.
   */
  @NotNull
  public static List<Class<?>> getTypeArguments(
      @NotNull Class<?> base, @NotNull Class<?> implementation) {
    Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();

    // first we need to resolve all supertypes up to the required base class or interface
    // and find the right Type for it
    Type type;

    Queue<Type> toCheck = new LinkedList<Type>();
    toCheck.add(implementation);
    while (true) {
      // if we have checked everything and not found the base class we return an empty list
      if (toCheck.isEmpty()) return ImmutableList.of();

      type = toCheck.remove();
      Class<?> clazz;

      if (type instanceof Class) {
        // there is no useful information for us in raw types, so just keep going up the inheritance
        // chain
        clazz = (Class) type;
        if (base.isInterface()) {
          // if we are actually looking for the type parameters to an interface we also need to
          // look at all the ones implemented by the given current one
          toCheck.addAll(Arrays.asList(clazz.getGenericInterfaces()));
        }
      } else if (type instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) type;
        clazz = (Class) parameterizedType.getRawType();

        // for instances of ParameterizedType we extract and remember all type arguments
        TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        for (int i = 0; i < actualTypeArguments.length; i++) {
          resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
        }
      } else {
        return ImmutableList.of();
      }

      // we can stop if we have reached the sought for base type
      if (base.equals(getClass(type))) break;

      toCheck.add(clazz.getGenericSuperclass());
    }

    // finally, for each actual type argument provided to baseClass,
    // determine (if possible) the raw class for that type argument.
    Type[] actualTypeArguments;
    if (type instanceof Class) {
      actualTypeArguments = ((Class) type).getTypeParameters();
    } else {
      actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
    }
    List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
    // resolve types by chasing down type variables.
    for (Type baseType : actualTypeArguments) {
      while (resolvedTypes.containsKey(baseType)) {
        baseType = resolvedTypes.get(baseType);
      }
      typeArgumentsAsClasses.add(getClass(baseType));
    }
    return typeArgumentsAsClasses;
  }
  /** 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;
  }
Ejemplo n.º 25
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);
    }
  }