Exemplo n.º 1
0
 static String javaSignature(Class<?> type) {
   if (!type.isArray()) {
     return type.getName();
   } else {
     int arrayDimension = 0;
     do {
       ++arrayDimension;
       type = type.getComponentType();
     } while (type.isArray());
     String name = type.getName();
     String suffix = "[]";
     if (arrayDimension == 1) {
       return name.concat(suffix);
     } else {
       int length = name.length() + arrayDimension * suffix.length();
       StringBuffer sb = new StringBuffer(length);
       sb.append(name);
       while (arrayDimension != 0) {
         --arrayDimension;
         sb.append(suffix);
       }
       return sb.toString();
     }
   }
 }
Exemplo n.º 2
0
  public <T> Query addParameter(String name, Class<T> parameterClass, T value) {
    // TODO: must cover most of types: BigDecimal,Boolean,SmallInt,Double,Float,byte[]
    if (InputStream.class.isAssignableFrom(parameterClass))
      return addParameter(name, (InputStream) value);
    if (Integer.class == parameterClass) return addParameter(name, (Integer) value);
    if (Long.class == parameterClass) return addParameter(name, (Long) value);
    if (String.class == parameterClass) return addParameter(name, (String) value);
    if (Timestamp.class == parameterClass) return addParameter(name, (Timestamp) value);
    if (Time.class == parameterClass) return addParameter(name, (Time) value);

    if (parameterClass.isArray()
        // byte[] is used for blob already
        && byte[].class != parameterClass) {
      return addParameter(name, toObjectArray(value));
    }
    if (Collection.class.isAssignableFrom(parameterClass)) {
      return addParameter(name, (Collection) value);
    }

    final Object convertedValue = convertParameter(value);

    addParameterInternal(
        name,
        new ParameterSetter() {
          public void setParameter(int paramIdx, PreparedStatement statement) throws SQLException {
            getConnection()
                .getSql2o()
                .getQuirks()
                .setParameter(statement, paramIdx, convertedValue);
          }
        });

    return this;
  }
  /**
   * 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);
  }
Exemplo n.º 4
0
 /**
  * Gets the datatype of the object.
  *
  * @param obj the object
  * @return the type
  */
 public static String getDataType(Object obj) {
   if (obj == null) {
     return null;
   }
   if (obj instanceof String) {
     return "string"; //$NON-NLS-1$
   } else if (obj instanceof Collection) {
     return "collection"; //$NON-NLS-1$
   } else if (obj.getClass().isArray()) {
     // make sure ultimate component class is acceptable
     Class componentType = obj.getClass().getComponentType();
     while (componentType.isArray()) {
       componentType = componentType.getComponentType();
     }
     String type = componentType.getName();
     if (type.indexOf(".") == -1
         && "intdoubleboolean".indexOf(type) == -1) { // $NON-NLS-1$ //$NON-NLS-2$
       return null;
     }
     return "array"; //$NON-NLS-1$
   } else if (obj instanceof Double) {
     return "double"; //$NON-NLS-1$
   } else if (obj instanceof Integer) {
     return "int"; //$NON-NLS-1$
   } else {
     return "object"; //$NON-NLS-1$
   }
 }
Exemplo n.º 5
0
  /**
   * Examines a property's type to see which method should be used to parse the property's value.
   *
   * @param desc The description of the property
   * @param value The value of the XML attribute containing the prop value
   * @return The value stored in the element
   * @throws IOException If there is an error reading the document
   */
  public Object getObjectValue(PropertyDescriptor desc, String value) throws IOException {
    // Find out what kind of property it is
    Class type = desc.getPropertyType();

    // If it's an array, get the base type
    if (type.isArray()) {
      type = type.getComponentType();
    }

    // For native types, object wrappers for natives, and strings, use the
    // basic parse routine
    if (type.equals(Integer.TYPE)
        || type.equals(Long.TYPE)
        || type.equals(Short.TYPE)
        || type.equals(Byte.TYPE)
        || type.equals(Boolean.TYPE)
        || type.equals(Float.TYPE)
        || type.equals(Double.TYPE)
        || Integer.class.isAssignableFrom(type)
        || Long.class.isAssignableFrom(type)
        || Short.class.isAssignableFrom(type)
        || Byte.class.isAssignableFrom(type)
        || Boolean.class.isAssignableFrom(type)
        || Float.class.isAssignableFrom(type)
        || Double.class.isAssignableFrom(type)) {
      return parseBasicType(type, value);
    } else if (String.class.isAssignableFrom(type)) {
      return value;
    } else if (java.util.Date.class.isAssignableFrom(type)) {
      // If it's a date, use the date parser
      return parseDate(value, JOXDateHandler.determineDateFormat());
    } else {
      return null;
    }
  }
 private static int getJSTypeCode(Object value) {
   if (value == null) {
     return JSTYPE_NULL;
   } else if (value == Undefined.instance) {
     return JSTYPE_UNDEFINED;
   } else if (value instanceof String) {
     return JSTYPE_STRING;
   } else if (value instanceof Number) {
     return JSTYPE_NUMBER;
   } else if (value instanceof Boolean) {
     return JSTYPE_BOOLEAN;
   } else if (value instanceof Scriptable) {
     if (value instanceof NativeJavaClass) {
       return JSTYPE_JAVA_CLASS;
     } else if (value instanceof NativeJavaArray) {
       return JSTYPE_JAVA_ARRAY;
     } else if (value instanceof Wrapper) {
       return JSTYPE_JAVA_OBJECT;
     } else {
       return JSTYPE_OBJECT;
     }
   } else if (value instanceof Class) {
     return JSTYPE_JAVA_CLASS;
   } else {
     Class<?> valueClass = value.getClass();
     if (valueClass.isArray()) {
       return JSTYPE_JAVA_ARRAY;
     } else {
       return JSTYPE_JAVA_OBJECT;
     }
   }
 }
Exemplo n.º 7
0
 public static boolean typesMatch(Class<?>[] usedTypes, Class<?>[] expectedTypes) {
   // expectedTypes is empty
   if (ArrayUtil.isEmpty(expectedTypes)) return ArrayUtil.isEmpty(usedTypes);
   Class<?> lastExpectedType = ArrayUtil.lastElementOf(expectedTypes);
   if (lastExpectedType.isArray()) {
     // process varargs parameter
     if (usedTypes.length < expectedTypes.length - 1) return false; // fault
     if (usedTypes.length == expectedTypes.length - 1)
       return typesMatch(
           usedTypes, ArrayUtil.copyOfRange(expectedTypes, 0, usedTypes.length)); // empty varargs
     // check if all used types match the varargs type
     if (usedTypes.length >= expectedTypes.length) {
       Class<?> componentType = lastExpectedType.getComponentType();
       for (int i = expectedTypes.length - 1; i < usedTypes.length; i++) {
         Class<?> foundType = usedTypes[i];
         if (!typeMatches(foundType, componentType)) return false;
       }
       return true;
     }
   }
   if (usedTypes.length != expectedTypes.length) return false;
   if (expectedTypes.length == 0 && usedTypes.length == 0) return true;
   for (int i = 0; i < usedTypes.length; i++) {
     Class<?> expectedType = expectedTypes[i];
     Class<?> foundType = usedTypes[i];
     if (!typeMatches(foundType, expectedType)) return false;
   }
   return true;
 }
Exemplo n.º 8
0
 private static Object parseValue(String value, Prop p, Class type) {
   Object v = value;
   if (type.isArray()) {
     StringTokenizer st = new StringTokenizer(value, ",");
     Class ctype = type.getComponentType();
     v = Array.newInstance(ctype, st.countTokens());
     for (int i = 0; st.hasMoreTokens(); i++)
       Array.set(v, i, parseValue(st.nextToken(), p, ctype));
   } else if (type == boolean.class) {
     v = Boolean.valueOf(value);
   } else if (type == double.class) {
     v = Double.valueOf(value);
   } else if (type == int.class) {
     v = Integer.valueOf(value);
   } else if (p.field.isAnnotationPresent(TimeIntervalProp.class)) {
     if (value.endsWith("s")) {
       v = (long) (Double.parseDouble(value.substring(0, value.length() - 1)) * SEC);
     } else if (value.endsWith("m")) {
       v = (long) (Double.parseDouble(value.substring(0, value.length() - 1)) * MIN);
     } else {
       v = Long.valueOf(value);
     }
   }
   return v;
 }
 /**
  * Estimates a "shallow" memory usage of the given object. For arrays, this will be the memory
  * taken by array storage (no subreferences will be followed). For objects, this will be the
  * memory taken by the fields.
  *
  * <p>JVM object alignments are also applied.
  */
 public static long shallowSizeOf(Object obj) {
   if (obj == null) return 0;
   final Class<?> clz = obj.getClass();
   if (clz.isArray()) {
     return shallowSizeOfArray(obj);
   } else {
     return shallowSizeOfInstance(clz);
   }
 }
Exemplo n.º 10
0
 /**
  * Convert the type into a string. The string representation approximates the code that would be
  * used to define the type.
  *
  * @param type - the type.
  * @return a string representation of the type, similar to how it was declared.
  */
 public static String toString(Type type) {
   if (type instanceof ParameterizedType) return toString((ParameterizedType) type);
   if (type instanceof WildcardType) return toString((WildcardType) type);
   if (type instanceof GenericArrayType) return toString((GenericArrayType) type);
   if (type instanceof Class) {
     final Class theClass = (Class) type;
     return (theClass.isArray() ? theClass.getName() + "[]" : theClass.getName());
   }
   return type.toString();
 }
Exemplo n.º 11
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();
    }
  }
Exemplo n.º 12
0
 private void visitType(java.lang.reflect.Type type, StringBuilder builder) {
   if (type instanceof Class) {
     Class<?> cl = (Class<?>) type;
     if (cl.isPrimitive()) {
       builder.append(Type.getType(cl).getDescriptor());
     } else {
       if (cl.isArray()) {
         builder.append(cl.getName().replace('.', '/'));
       } else {
         builder.append('L');
         builder.append(cl.getName().replace('.', '/'));
         builder.append(';');
       }
     }
   } else if (type instanceof ParameterizedType) {
     ParameterizedType parameterizedType = (ParameterizedType) type;
     visitNested(parameterizedType.getRawType(), builder);
     builder.append('<');
     for (java.lang.reflect.Type param : parameterizedType.getActualTypeArguments()) {
       visitType(param, builder);
     }
     builder.append(">;");
   } else if (type instanceof WildcardType) {
     WildcardType wildcardType = (WildcardType) type;
     if (wildcardType.getUpperBounds().length == 1
         && wildcardType.getUpperBounds()[0].equals(Object.class)) {
       if (wildcardType.getLowerBounds().length == 0) {
         builder.append('*');
         return;
       }
     } else {
       for (java.lang.reflect.Type upperType : wildcardType.getUpperBounds()) {
         builder.append('+');
         visitType(upperType, builder);
       }
     }
     for (java.lang.reflect.Type lowerType : wildcardType.getLowerBounds()) {
       builder.append('-');
       visitType(lowerType, builder);
     }
   } else if (type instanceof TypeVariable) {
     TypeVariable<?> typeVar = (TypeVariable) type;
     builder.append('T');
     builder.append(typeVar.getName());
     builder.append(';');
   } else if (type instanceof GenericArrayType) {
     GenericArrayType arrayType = (GenericArrayType) type;
     builder.append('[');
     visitType(arrayType.getGenericComponentType(), builder);
   } else {
     throw new IllegalArgumentException(
         String.format("Cannot generate signature for %s.", type));
   }
 }
Exemplo n.º 13
0
 int[] arrayDimensions(Object a_object) {
   int count = 0;
   for (Class clazz = a_object.getClass(); clazz.isArray(); clazz = clazz.getComponentType()) {
     count++;
   }
   int dim[] = new int[count];
   for (int i = 0; i < count; i++) {
     dim[i] = Array.getLength(a_object);
     a_object = Array.get(a_object, 0);
   }
   return dim;
 }
Exemplo n.º 14
0
 static String jni_signature(Class c) {
   if (c == int.class) return "I";
   if (c == long.class) return "J";
   if (c == short.class) return "S";
   if (c == byte.class) return "B";
   if (c == boolean.class) return "Z";
   if (c == double.class) return "D";
   if (c == float.class) return "F";
   if (c == char.class) return "C";
   if (c == void.class) return "V";
   if (c.isArray()) return "[" + jni_signature(c.getComponentType());
   return "L" + name(c) + ";";
 }
Exemplo n.º 15
0
 /**
  * Check if the given element is an array.
  *
  * <p>Multidimensional arrays are not supported.
  *
  * <p>Non-empty 1-dimensional arrays of CompositeData and TabularData are not handled as arrays
  * but as tabular data.
  */
 public static boolean isSupportedArray(Object elem) {
   if (elem == null || !elem.getClass().isArray()) {
     return false;
   }
   Class<?> ct = elem.getClass().getComponentType();
   if (ct.isArray()) {
     return false;
   }
   if (Array.getLength(elem) > 0
       && (CompositeData.class.isAssignableFrom(ct) || TabularData.class.isAssignableFrom(ct))) {
     return false;
   }
   return true;
 }
Exemplo n.º 16
0
  public Document serialize(Object object, Document doc) {
    Class c = object.getClass();
    Integer id = getID(object);
    map.put(object, id);
    String mapSize = Integer.toString(map.size());

    // creating serialization objects
    Element objectElement = new Element("object");
    objectElement.setAttribute(new Attribute("class", c.getName()));
    objectElement.setAttribute(new Attribute("id", mapSize));
    doc.getRootElement().addContent(objectElement);

    if (!c.isArray()) // class is not an array
    {
      Field[] fields = c.getDeclaredFields();
      ArrayList<Element> fieldXML = serializeFields(fields, object, doc);
      for (int i = 0; i < fieldXML.size(); i++) {
        objectElement.addContent(fieldXML.get(i));
      }
    } else // class is an array
    {
      Object array = object;
      objectElement.setAttribute(new Attribute("length", Integer.toString(Array.getLength(array))));
      if (c.getComponentType().isPrimitive()) // class is array of primitives
      {
        for (int i = 0; i < Array.getLength(array); i++) {
          Element value = new Element("value");
          value.setText(Array.get(c, i).toString());
          objectElement.addContent(value);
        }
      } else // class is array of references
      {
        for (int j = 0; j < Array.getLength(array); j++) {
          Element ref = new Element("reference");
          id = getID(Array.get(c, j));
          if (id != -1) {
            ref.setText(Integer.toString(id));
          }
        }
        for (int k = 0; k < Array.getLength(array); k++) {
          serialize(Array.get(array, k), doc);
        }
      }
    }
    if (currentElement == 0) {
      referenceID = 0;
    }

    return doc;
  }
Exemplo n.º 17
0
  /**
   * Examines a property's type to see which method should be used to parse the property's value.
   *
   * @param desc The description of the property
   * @param element The XML element containing the property value
   * @return The value stored in the element
   * @throws IOException If there is an error reading the document
   */
  public Object getObjectValue(PropertyDescriptor desc, Element element) throws IOException {
    // Find out what kind of property it is
    Class type = desc.getPropertyType();

    // If it's an array, get the base type
    if (type.isArray()) {
      type = type.getComponentType();
    }

    // For native types, object wrappers for natives, and strings, use the
    // basic parse routine
    if (type.equals(Integer.TYPE)
        || type.equals(Long.TYPE)
        || type.equals(Short.TYPE)
        || type.equals(Byte.TYPE)
        || type.equals(Boolean.TYPE)
        || type.equals(Float.TYPE)
        || type.equals(Double.TYPE)
        || Integer.class.isAssignableFrom(type)
        || Long.class.isAssignableFrom(type)
        || Short.class.isAssignableFrom(type)
        || Byte.class.isAssignableFrom(type)
        || Boolean.class.isAssignableFrom(type)
        || Float.class.isAssignableFrom(type)
        || Double.class.isAssignableFrom(type)
        || String.class.isAssignableFrom(type)) {
      return readBasicType(type, element);
    } else if (java.util.Date.class.isAssignableFrom(type)) {
      // If it's a date, use the date parser
      return readDate(element);
    } else {
      try {
        // If it's an object, create a new instance of the object (it should
        // be a bean, or there will be trouble)
        Object newOb = type.newInstance();

        // Copy the XML element into the bean
        readObject(newOb, element);

        return newOb;
      } catch (InstantiationException exc) {
        throw new IOException(
            "Error creating object for " + desc.getName() + ": " + exc.toString());
      } catch (IllegalAccessException exc) {
        throw new IOException(
            "Error creating object for " + desc.getName() + ": " + exc.toString());
      }
    }
  }
Exemplo n.º 18
0
  private static Object createArgumentPlaceholder(Class<?> clazz, Integer placeholderId) {
    if (clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) || Character.class == clazz)
      return getPrimitivePlaceHolder(clazz, placeholderId);

    if (clazz == String.class) return String.valueOf(placeholderId);
    if (Date.class.isAssignableFrom(clazz)) return new Date(placeholderId);
    if (clazz.isArray()) return Array.newInstance(clazz.getComponentType(), 1);

    try {
      return createArgumentPlaceholderForUnknownClass(clazz, placeholderId);
    } catch (Exception e) {
      throw new ArgumentConversionException(
          "It is not possible to create a placeholder for class: " + clazz.getName(), e);
    }
  }
Exemplo n.º 19
0
 private static void vis(String name, Class type, Object value, String indent) throws Exception {
   if (value == null) { // nothing interesting to say
     prt(indent + name + ": null");
   } else if (type.isPrimitive()) { // primitive
     if (type == Boolean.TYPE) prt(indent + name + ": " + ((Boolean) value).booleanValue());
     else if (type == Character.TYPE) prt(indent + name + ": " + ((Character) value).charValue());
     else if (type == Byte.TYPE) prt(indent + name + ": " + ((Byte) value).byteValue());
     else if (type == Short.TYPE) prt(indent + name + ": " + ((Short) value).shortValue());
     else if (type == Integer.TYPE) prt(indent + name + ": " + ((Integer) value).intValue());
     else if (type == Long.TYPE) prt(indent + name + ": " + ((Long) value).longValue());
     else if (type == Float.TYPE) prt(indent + name + ": " + ((Float) value).floatValue());
     else if (type == Double.TYPE) prt(indent + name + ": " + ((Double) value).doubleValue());
     else throw new IllegalArgumentException(); // NotReached
   } else if (type.isArray()) { // array
     Class componentType = type.getComponentType();
     prt(indent + name + ": " + componentType.getName() + "[]");
     for (int i = 0, n = Array.getLength(value); i < n; ++i)
       vis("" + i, componentType, Array.get(value, i), indent + "   ");
   } else if (type.getName()
       .equals("java.lang.String")) { // treat frequently used type as special case
     prt(indent + name + ": \"" + (String) value + "\"");
   } else { // class (or interface)
     Field[] fields =
         type
             .getFields(); // !!note: Sun's jvm only returns *public* fields, jx returns *all*
                           // fields
     if (fields.length == 0) { // no fields
       // prt(indent + name + ": declared as " + type.getName() + " actually is " + (value == null
       // ? "null" : value.getClass().getName()) + " self-described as \"" + value + "\"");
       prt(
           indent
               + name
               + ": declared as "
               + type.getName()
               + " actually is "
               + (value == null ? "null" : value.getClass().getName()));
     } else { // use fields to describe object
       prt(indent + name + ": " + type.getName());
       for (int i = 0, n = fields.length; i < n; ++i) {
         Field f = fields[i];
         if (Modifier.isStatic(f.getModifiers()))
           vis(f.getName(), f.getType(), f.get(value), indent + "   static ");
         else vis(f.getName(), f.getType(), f.get(value), indent + "   ");
       }
     }
   }
 }
 private void putInstance(
     Class<?> parameterType, Object actualArguments, Object otherArguments, int index) {
   Object actualArgument, otherArgument;
   if (parameterType == boolean.class) {
     actualArgument = DEFAULT_BOOLEAN;
     otherArgument = OTHER_BOOLEAN;
   } else if (parameterType == byte.class) {
     actualArgument = DEFAULT_BYTE;
     otherArgument = OTHER_BYTE;
   } else if (parameterType == char.class) {
     actualArgument = DEFAULT_CHAR;
     otherArgument = OTHER_CHAR;
   } else if (parameterType == short.class) {
     actualArgument = DEFAULT_SHORT;
     otherArgument = OTHER_SHORT;
   } else if (parameterType == int.class) {
     actualArgument = DEFAULT_INT;
     otherArgument = OTHER_INT;
   } else if (parameterType == long.class) {
     actualArgument = DEFAULT_LONG;
     otherArgument = OTHER_LONG;
   } else if (parameterType == float.class) {
     actualArgument = DEFAULT_FLOAT;
     otherArgument = OTHER_FLOAT;
   } else if (parameterType == double.class) {
     actualArgument = DEFAULT_DOUBLE;
     otherArgument = OTHER_DOUBLE;
   } else if (parameterType.isEnum()) {
     Object[] enumConstants = parameterType.getEnumConstants();
     if (enumConstants.length == 1) {
       throw new IllegalArgumentException("Enum with only one constant: " + parameterType);
     }
     actualArgument = enumConstants[0];
     otherArgument = enumConstants[1];
   } else if (parameterType.isArray()) {
     actualArgument = Array.newInstance(parameterType.getComponentType(), 1);
     otherArgument = Array.newInstance(parameterType.getComponentType(), 1);
     putInstance(parameterType.getComponentType(), actualArgument, otherArgument, 0);
   } else {
     actualArgument = creator.replace(parameterType, generator, false);
     refinement.apply(actualArgument);
     otherArgument = creator.replace(parameterType, generator, true);
     refinement.apply(otherArgument);
   }
   Array.set(actualArguments, index, actualArgument);
   Array.set(otherArguments, index, otherArgument);
 }
Exemplo n.º 21
0
  /**
   * @return Null if class might be a bean; type String (that identifies why it's not a bean) if not
   */
  public static String canBeABeanType(Class<?> type) {
    // First: language constructs that ain't beans:
    if (type.isAnnotation()) {
      return "annotation";
    }
    if (type.isArray()) {
      return "array";
    }
    if (type.isEnum()) {
      return "enum";
    }
    if (type.isPrimitive()) {
      return "primitive";
    }

    // Anything else? Seems valid, then
    return null;
  }
  /**
   * Returns the shallow instance size in bytes an instance of the given class would occupy. This
   * works with all conventional classes and primitive types, but not with arrays (the size then
   * depends on the number of elements and varies from object to object).
   *
   * @see #shallowSizeOf(Object)
   * @throws IllegalArgumentException if {@code clazz} is an array class.
   */
  public static long shallowSizeOfInstance(Class<?> clazz) {
    if (clazz.isArray())
      throw new IllegalArgumentException("This method does not work with array classes.");
    if (clazz.isPrimitive()) return primitiveSizes.get(clazz);

    long size = NUM_BYTES_OBJECT_HEADER;

    // Walk type hierarchy
    for (; clazz != null; clazz = clazz.getSuperclass()) {
      final Field[] fields = clazz.getDeclaredFields();
      for (Field f : fields) {
        if (!Modifier.isStatic(f.getModifiers())) {
          size = adjustForField(size, f);
        }
      }
    }
    return alignObjectSize(size);
  }
Exemplo n.º 23
0
  public static Class<?> getActualType(Type genericType, final int pos) {

    if (genericType == null) return null;
    if (!ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
      if (genericType instanceof TypeVariable)
        genericType = getType(((TypeVariable<?>) genericType).getBounds(), pos);
      else if (genericType instanceof WildcardType) {
        final WildcardType wildcardType = (WildcardType) genericType;
        Type[] bounds = wildcardType.getLowerBounds();
        if (bounds.length == 0) bounds = wildcardType.getUpperBounds();
        genericType = getType(bounds, pos);
      }

      final Class<?> cls = (Class<?>) genericType;
      return cls.isArray() ? cls.getComponentType() : cls;
    }
    final ParameterizedType paramType = (ParameterizedType) genericType;
    final Type t = getType(paramType.getActualTypeArguments(), pos);
    return t instanceof Class ? (Class<?>) t : getActualType(t, pos);
  }
Exemplo n.º 24
0
 private static StringBuilder appendTypeString(StringBuilder sb, Class<?> type) {
   while (type.isArray()) {
     sb.append('[');
     type = type.getComponentType();
   }
   if (type.isPrimitive()) {
     char typeLetter;
     if (type == Boolean.TYPE) {
       typeLetter = 'Z';
     } else if (type == Long.TYPE) {
       typeLetter = 'J';
     } else {
       String typeName = type.getName();
       typeLetter = Character.toUpperCase(typeName.charAt(0));
     }
     sb.append(typeLetter);
   } else {
     sb.append('L');
     sb.append(type.getName().replace('.', '/'));
     sb.append(';');
   }
   return sb;
 }
  /*
   * Non-recursive version of object descend. This consumes more memory than recursive in-depth
   * traversal but prevents stack overflows on long chains of objects
   * or complex graphs (a max. recursion depth on my machine was ~5000 objects linked in a chain
   * so not too much).
   */
  private static long measureObjectSize(Object root) {
    // Objects seen so far.
    final IdentityHashSet<Object> seen = new IdentityHashSet<Object>();
    // Class cache with reference Field and precalculated shallow size.
    final IdentityHashMap<Class<?>, ClassCache> classCache =
        new IdentityHashMap<Class<?>, ClassCache>();
    // Stack of objects pending traversal. Recursion caused stack overflows.
    final ArrayList<Object> stack = new ArrayList<Object>();
    stack.add(root);

    long totalSize = 0;
    while (!stack.isEmpty()) {
      final Object ob = stack.remove(stack.size() - 1);

      if (ob == null || seen.contains(ob)) {
        continue;
      }
      seen.add(ob);

      final Class<?> obClazz = ob.getClass();
      if (obClazz.isArray()) {
        /*
         * Consider an array, possibly of primitive types. Push any of its references to
         * the processing stack and accumulate this array's shallow size.
         */
        long size = NUM_BYTES_ARRAY_HEADER;
        final int len = Array.getLength(ob);
        if (len > 0) {
          Class<?> componentClazz = obClazz.getComponentType();
          if (componentClazz.isPrimitive()) {
            size += (long) len * primitiveSizes.get(componentClazz);
          } else {
            size += (long) NUM_BYTES_OBJECT_REF * len;

            // Push refs for traversal later.
            for (int i = len; --i >= 0; ) {
              final Object o = Array.get(ob, i);
              if (o != null && !seen.contains(o)) {
                stack.add(o);
              }
            }
          }
        }
        totalSize += alignObjectSize(size);
      } else {
        /*
         * Consider an object. Push any references it has to the processing stack
         * and accumulate this object's shallow size.
         */
        try {
          ClassCache cachedInfo = classCache.get(obClazz);
          if (cachedInfo == null) {
            classCache.put(obClazz, cachedInfo = createCacheEntry(obClazz));
          }

          for (Field f : cachedInfo.referenceFields) {
            // Fast path to eliminate redundancies.
            final Object o = f.get(ob);
            if (o != null && !seen.contains(o)) {
              stack.add(o);
            }
          }

          totalSize += cachedInfo.alignedShallowInstanceSize;
        } catch (IllegalAccessException e) {
          // this should never happen as we enabled setAccessible().
          throw new RuntimeException("Reflective field access failed?", e);
        }
      }
    }

    // Help the GC (?).
    seen.clear();
    stack.clear();
    classCache.clear();

    return totalSize;
  }
Exemplo n.º 26
0
  public static DeepHierarchyElement[] getDeepFieldHierarchy(
      Class<?> parentClass, String field, HintContainer deepIndexHintContainer) {
    if (!MappingUtils.isDeepMapping(field)) {
      MappingUtils.throwMappingException("Field does not contain deep field delimitor");
    }

    StringTokenizer toks = new StringTokenizer(field, DozerConstants.DEEP_FIELD_DELIMITER);
    Class<?> latestClass = parentClass;
    DeepHierarchyElement[] hierarchy = new DeepHierarchyElement[toks.countTokens()];
    int index = 0;
    int hintIndex = 0;
    while (toks.hasMoreTokens()) {
      String aFieldName = toks.nextToken();
      String theFieldName = aFieldName;
      int collectionIndex = -1;

      if (aFieldName.contains("[")) {
        theFieldName = aFieldName.substring(0, aFieldName.indexOf("["));
        collectionIndex =
            Integer.parseInt(
                aFieldName.substring(aFieldName.indexOf("[") + 1, aFieldName.indexOf("]")));
      }

      PropertyDescriptor propDescriptor =
          findPropertyDescriptor(latestClass, theFieldName, deepIndexHintContainer);
      DeepHierarchyElement r = new DeepHierarchyElement(propDescriptor, collectionIndex);

      if (propDescriptor == null) {
        MappingUtils.throwMappingException(
            "Exception occurred determining deep field hierarchy for Class --> "
                + parentClass.getName()
                + ", Field --> "
                + field
                + ".  Unable to determine property descriptor for Class --> "
                + latestClass.getName()
                + ", Field Name: "
                + aFieldName);
      }

      latestClass = propDescriptor.getPropertyType();
      if (toks.hasMoreTokens()) {
        if (latestClass.isArray()) {
          latestClass = latestClass.getComponentType();
        } else if (Collection.class.isAssignableFrom(latestClass)) {
          Class<?> genericType = determineGenericsType(propDescriptor);

          if (genericType == null && deepIndexHintContainer == null) {
            MappingUtils.throwMappingException(
                "Hint(s) or Generics not specified.  Hint(s) or Generics must be specified for deep mapping with indexed field(s). Exception occurred determining deep field hierarchy for Class --> "
                    + parentClass.getName()
                    + ", Field --> "
                    + field
                    + ".  Unable to determine property descriptor for Class --> "
                    + latestClass.getName()
                    + ", Field Name: "
                    + aFieldName);
          }
          if (genericType != null) {
            latestClass = genericType;
          } else {
            latestClass = deepIndexHintContainer.getHint(hintIndex);
            hintIndex += 1;
          }
        }
      }
      hierarchy[index++] = r;
    }

    return hierarchy;
  }
Exemplo n.º 27
0
  void doTest(String name) throws Exception {
    Method m = tests.get(name);
    Method m_check = tests.get(name + "_check");
    Class[] paramTypes = m.getParameterTypes();
    Object[] params = new Object[paramTypes.length];
    Class retType = m.getReturnType();
    boolean isIntArray =
        (retType.isPrimitive() && !retType.equals(Void.TYPE))
            || (retType.equals(Void.TYPE) && paramTypes[0].getComponentType().isPrimitive())
            || (retType.isArray() && retType.getComponentType().isPrimitive());

    Args args = m.getAnnotation(Args.class);

    Object src = null;
    switch (args.src()) {
      case SMALL:
        {
          if (isIntArray) {
            src = small_int_src;
          } else {
            src = small_a_src;
          }
          break;
        }
      case LARGE:
        {
          if (isIntArray) {
            src = large_int_src;
          } else {
            src = large_a_src;
          }
          break;
        }
      case ZERO:
        {
          if (isIntArray) {
            src = zero_int_src;
          } else {
            src = zero_a_src;
          }
          break;
        }
    }

    for (int i = 0; i < 20000; i++) {
      boolean failure = false;

      int p = 0;

      if (params.length > 0) {
        if (isIntArray) {
          params[0] = ((int[]) src).clone();
        } else {
          params[0] = ((A[]) src).clone();
        }
        p++;
      }

      if (params.length > 1) {
        switch (args.dst()) {
          case NEW:
            {
              if (isIntArray) {
                params[1] = new int[((int[]) params[0]).length];
              } else {
                params[1] = new A[((A[]) params[0]).length];
              }
              p++;
              break;
            }
          case SRC:
            {
              params[1] = params[0];
              p++;
              break;
            }
          case NONE:
            break;
        }
      }

      for (int j = 0; j < args.extra_args().length; j++) {
        params[p + j] = args.extra_args()[j];
      }

      Object res = m.invoke(null, params);

      if (retType.isPrimitive() && !retType.equals(Void.TYPE)) {
        int s = (int) res;
        int sum = 0;
        int[] int_res = (int[]) src;
        for (int j = 0; j < int_res.length; j++) {
          sum += int_res[j];
        }
        failure = (s != sum);
        if (failure) {
          System.out.println("Test " + name + " failed: result = " + s + " != " + sum);
        }
      } else {
        Object dest = null;
        if (!retType.equals(Void.TYPE)) {
          dest = res;
        } else {
          dest = params[1];
        }

        if (m_check != null) {
          failure = (boolean) m_check.invoke(null, new Object[] {src, dest});
        } else {
          if (isIntArray) {
            int[] int_res = (int[]) src;
            int[] int_dest = (int[]) dest;
            for (int j = 0; j < int_res.length; j++) {
              if (int_res[j] != int_dest[j]) {
                System.out.println(
                    "Test "
                        + name
                        + " failed for "
                        + j
                        + " src["
                        + j
                        + "]="
                        + int_res[j]
                        + ", dest["
                        + j
                        + "]="
                        + int_dest[j]);
                failure = true;
              }
            }
          } else {
            Object[] object_res = (Object[]) src;
            Object[] object_dest = (Object[]) dest;
            for (int j = 0; j < object_res.length; j++) {
              if (object_res[j] != object_dest[j]) {
                System.out.println(
                    "Test "
                        + name
                        + " failed for "
                        + j
                        + " src["
                        + j
                        + "]="
                        + object_res[j]
                        + ", dest["
                        + j
                        + "]="
                        + object_dest[j]);
                failure = true;
              }
            }
          }
        }
      }

      if (failure) {
        success = false;
        break;
      }
    }
  }
Exemplo n.º 28
0
  public ValueType getValueType(
      int iParam,
      int nParams,
      Class<?> c,
      Type t,
      AnnotatedElement element,
      Annotation... directAnnotations) {
    boolean isPtr = isAnnotationPresent(Ptr.class, element, directAnnotations);
    boolean isCLong = isAnnotationPresent(org.bridj.ann.CLong.class, element, directAnnotations);
    Constructor cons = getAnnotation(Constructor.class, element, directAnnotations);

    if (isPtr || cons != null || isCLong) {
      if (!(c == Long.class || c == Long.TYPE))
        throw new RuntimeException(
            "Annotation should only be used on a long parameter, not on a " + c.getName());

      if (isPtr) {
        if (!Platform.is64Bits()) direct = false;
      } else if (isCLong) {
        if (Platform.CLONG_SIZE != 8) direct = false;
      } else if (cons != null) {
        isCPlusPlus = true;
        startsWithThis = true;
        if (iParam != 0)
          throw new RuntimeException(
              "Annotation "
                  + Constructor.class.getName()
                  + " cannot have more than one (long) argument");
      }
      return ValueType.eSizeTValue;
    }
    if (c == null || c.equals(Void.TYPE)) return ValueType.eVoidValue;
    if (c == Integer.class || c == Integer.TYPE) return ValueType.eIntValue;
    if (c == Long.class || c == Long.TYPE) {
      return !isPtr || Platform.is64Bits() ? ValueType.eLongValue : ValueType.eIntValue;
    }
    if (c == Short.class || c == Short.TYPE) return ValueType.eShortValue;
    if (c == Byte.class || c == Byte.TYPE) return ValueType.eByteValue;
    if (c == Boolean.class || c == Boolean.TYPE) return ValueType.eBooleanValue;
    if (c == Float.class || c == Float.TYPE) {
      usesFloats();
      return ValueType.eFloatValue;
    }
    if (c == char.class || c == Character.TYPE) {
      if (Platform.WCHAR_T_SIZE != 2) direct = false;
      return ValueType.eWCharValue;
    }
    if (c == Double.class || c == Double.TYPE) {
      usesFloats();
      return ValueType.eDoubleValue;
    }
    if (c == CLong.class) {
      direct = false;
      return ValueType.eCLongObjectValue;
    }
    if (c == SizeT.class) {
      direct = false;
      return ValueType.eSizeTObjectValue;
    }
    if (c == TimeT.class) {
      direct = false;
      return ValueType.eTimeTObjectValue;
    }
    if (Pointer.class.isAssignableFrom(c)) {
      direct = false;
      CallIO cio = CallIO.Utils.createPointerCallIO(c, t);
      if (BridJ.veryVerbose) BridJ.info("CallIO : " + cio);
      addCallIO(cio);
      return ValueType.ePointerValue;
    }
    if (c.isArray() && iParam == nParams - 1) {
      direct = false;
      return ValueType.eEllipsis;
    }
    if (ValuedEnum.class.isAssignableFrom(c)) {
      direct = false;
      CallIO cio =
          CallIO.Utils.createValuedEnumCallIO(
              (Class) Utils.getClass(Utils.getUniqueParameterizedTypeParameter(t)));
      if (BridJ.veryVerbose) BridJ.info("CallIO : " + cio);
      addCallIO(cio);

      return ValueType.eIntFlagSet;
    }
    if (NativeObject.class.isAssignableFrom(c)) {
      Pointer<DCstruct> pStruct = null;
      if (StructObject.class.isAssignableFrom(c)) {
        StructIO io = StructIO.getInstance(c, t);
        try {
          pStruct = DyncallStructs.buildDCstruct(io.desc);
        } catch (Throwable th) {
          BridJ.error(
              "Unable to create low-level struct metadata for "
                  + Utils.toString(t)
                  + " : won't be able to use it as a by-value function argument.",
              th);
        }
      }
      addCallIO(new CallIO.NativeObjectHandler((Class<? extends NativeObject>) c, t, pStruct));
      direct = false;
      return ValueType.eNativeObjectValue;
    }

    throw new NoSuchElementException(
        "No " + ValueType.class.getSimpleName() + " for class " + c.getName());
  }
Exemplo n.º 29
0
  /* PROTECTED METHODS */
  protected void getBeanElements(
      Element parentElement, String objectName, String objectType, Object bean)
      throws IntrospectionException, IllegalAccessException {
    if (objectName == null) {
      // Get just the class name by lopping off the package name
      StringBuffer sb = new StringBuffer(bean.getClass().getName());
      sb.delete(0, sb.lastIndexOf(".") + 1);
      objectName = sb.toString();
    }

    // Check if the bean is a standard Java object type or a byte[] (encoded as a base 64 array)
    Element element = getStandardObjectElement(document, bean, objectName);
    // If the body element object is null then the bean is not a standard Java object type
    if (element != null) {
      if (includeNullValues
          || !element
              .getAttribute(
                  NamespaceConstants.NSPREFIX_SCHEMA_XSI
                      + ":"
                      + org.apache.axis.Constants.ATTR_TYPE)
              .equals("anyType")) {
        if (!includeTypeInfo) {
          element.removeAttribute(
              NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":" + org.apache.axis.Constants.ATTR_TYPE);
          element.removeAttribute(NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":null");
        }
        parentElement.appendChild(element);
      }
    } else {
      // Analyze the bean
      Class classOfBean = null;
      if (bean != null) classOfBean = bean.getClass();
      // If the object is an array, then serialize each of the beans in the array.
      if ((classOfBean != null) && (classOfBean.isArray())) {
        String[] arrayInfo = getXsdSoapArrayInfo(classOfBean.getCanonicalName(), nsPrefix);
        int arrayLen = Array.getLength(bean);
        StringBuffer arrayType = new StringBuffer(arrayInfo[1]);
        arrayType.insert(arrayType.indexOf("[]") + 1, arrayLen);
        if (objectName.charAt(objectName.length() - 1) == ';')
          objectName =
              new StringBuffer(objectName).deleteCharAt(objectName.length() - 1).toString();
        element = document.createElement(objectName);
        parentElement.appendChild(element);
        // Get the bean objects from the array and serialize each
        for (int i = 0; i < arrayLen; i++) {
          Object b = Array.get(bean, i);
          if (b != null) {
            String name = null;
            if (objectName.charAt(objectName.length() - 1) == 's') {
              name = formatName(objectName.substring(0, objectName.length() - 1));
            }
            getBeanElements(element, name, b.getClass().getName(), b);
          } else {
            // Array element is null, so don't include it and decrement the # elements in the array
            int index = arrayType.indexOf("[");
            arrayType.replace(index + 1, index + 2, String.valueOf(--arrayLen));
          }
          if (includeTypeInfo) {
            element.setAttributeNS(
                NamespaceConstants.NSURI_SCHEMA_XSI,
                NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":" + Constants.ATTR_TYPE,
                NamespaceConstants.NSPREFIX_SOAP_ENCODING + ":Array");
            element.setAttributeNS(
                NamespaceConstants.NSURI_SOAP_ENCODING,
                NamespaceConstants.NSPREFIX_SOAP_ENCODING + ":" + Constants.ATTR_ARRAY_TYPE,
                arrayInfo[0] + ":" + arrayType.toString());
          }
        }
      } else {
        int beanType = 0;
        String beanName = null;
        if (classOfBean != null) {
          if (classOfBean == Vector.class) {
            beanType = 1;
            beanName = "Vector";
          } else if (classOfBean == ArrayList.class) {
            beanType = 2;
            beanName = "ArrayList";
          } else if (classOfBean == LinkedList.class) {
            beanType = 3;
            beanName = "LinkedList";
          } else if (classOfBean == Hashtable.class) {
            beanType = 4;
            beanName = "Hashtable";
          } else if (classOfBean == Properties.class) {
            beanType = 5;
            beanName = "Properties";
          } else if ((classOfBean == HashMap.class) || (classOfBean == SortedMap.class)) {
            beanType = 6;
            beanName = "Map";
          }
        }
        if (beanType > 0) {
          String prefix = null;
          if ((beanType == 1) || (beanType == 5))
            prefix = NamespaceConstants.NSPREFIX_SOAP_ENCODING;
          if (beanType == 6) prefix = Constants.NS_PREFIX_XMLSOAP;
          else prefix = DEFAULT_NS_PREFIX;
          element = document.createElement(objectName);
          if (includeTypeInfo) {
            element.setAttributeNS(
                NamespaceConstants.NSURI_SCHEMA_XSI,
                NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":" + Constants.ATTR_TYPE,
                prefix + ":" + beanName);
            if (bean == null)
              element.setAttributeNS(
                  NamespaceConstants.NSURI_SCHEMA_XSI,
                  NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":null",
                  "true");
          }
          parentElement.appendChild(element);
          if ((beanType >= 1) && (beanType <= 3)) {
            AbstractCollection collection = (AbstractCollection) bean;
            // Get the bean objects from the vector and serialize each
            Iterator it = collection.iterator();
            while (it.hasNext()) {
              Object b = it.next();
              String name = null;
              if (b != null) {
                if (objectName.charAt(objectName.length() - 1) == 's') {
                  name = formatName(objectName.substring(0, objectName.length() - 1));
                } else name = "item";
              }
              getBeanElements(element, name, b.getClass().getName(), b);
            }
          } else if ((beanType == 4) || (beanType == 5)) {
            Hashtable hashtable = (Hashtable) bean;
            // Get the bean objects from the hashtable or properties and serialize each
            Enumeration en = hashtable.keys();
            while (en.hasMoreElements()) {
              Object key = en.nextElement();
              String keyClassName = key.getClass().getName();
              Object value = hashtable.get(key);
              String beanClassName = null;
              if (value != null) beanClassName = value.getClass().getName();
              Element itemElement = document.createElement("item");
              element.appendChild(itemElement);
              getBeanElements(itemElement, "key", keyClassName, key);
              getBeanElements(itemElement, "value", beanClassName, value);
            }
          } else if (beanType == 6) {
            Map map = null;
            if (classOfBean == HashMap.class) map = (HashMap) bean;
            else if (classOfBean == SortedMap.class) map = (SortedMap) bean;
            // Get the bean objects from the hashmap and serialize each
            Set set = map.keySet();
            Iterator it = set.iterator();
            while (it.hasNext()) {
              Object key = it.next();
              String keyClassName = key.getClass().getName();
              Object value = map.get(key);
              String beanClassName = null;
              if (value != null) beanClassName = value.getClass().getName();
              Element itemElement = document.createElement("item");
              element.appendChild(itemElement);
              getBeanElements(itemElement, "key", keyClassName, key);
              getBeanElements(itemElement, "value", beanClassName, value);
            }
          }
        } else {
          // Create a parent element for this bean's properties
          if (objectName.charAt(objectName.length() - 1) == ';')
            objectName =
                new StringBuffer(objectName).deleteCharAt(objectName.length() - 1).toString();
          objectName = formatName(objectName);
          element = document.createElement(objectName);
          parentElement.appendChild(element);
          if (includeTypeInfo) {
            StringBuffer className = new StringBuffer(objectType);
            element.setAttributeNS(
                NamespaceConstants.NSURI_SCHEMA_XSI,
                NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":" + Constants.ATTR_TYPE,
                nsPrefix + ":" + className.delete(0, className.lastIndexOf(".") + 1).toString());
          }
          if (classOfBean != null) {
            // Get an array of property descriptors
            BeanInfo bi = Introspector.getBeanInfo(classOfBean);
            PropertyDescriptor[] pds = bi.getPropertyDescriptors();
            // For each property of the bean, get a SOAPBodyElement that
            // represents the individual property. Append that SOAPBodyElement
            // to the class name element of the SOAP body.
            for (int i = 0; i < pds.length; i++) {
              PropertyDescriptor pd = pds[i];
              getBeanElementProperties(element, bean, pd);
            }
          } else {
            if (includeTypeInfo)
              element.setAttributeNS(
                  NamespaceConstants.NSURI_SCHEMA_XSI,
                  NamespaceConstants.NSPREFIX_SCHEMA_XSI + ":null",
                  "true");
          }
        }
      }
    }
  }
Exemplo n.º 30
-21
  /**
   * Returns all the classes related to <code>type</code> by a {@link Connection}
   *
   * @param type The given {@link Model} interface.
   * @return A list that contains all the models in a relationship with <code>type</code> interface.
   */
  protected List<Class> getAllReleatedClasses(Class type) {

    if (relatedClasses.containsKey(type)) return relatedClasses.get(type);

    List<Class> related = new ArrayList<Class>();
    Method[] getters = CommonStatic.getDeclaredGetters(type);

    for (Method g : getters)
      if (g.isAnnotationPresent(Connection.class)) {

        Class t = g.getReturnType();
        t = t.isArray() ? t.getComponentType() : t;

        if (!related.contains(t)) related.add(t);
      }

    relatedClasses.put(type, related);

    return related;
  }