Exemplo n.º 1
0
 /** @param elementType May be null if the type is unknown. */
 public void readField(
     Object object, String fieldName, String jsonName, Class elementType, JsonValue jsonMap) {
   Type type = ReflectionCache.getType(object.getClass());
   ObjectMap<String, FieldMetadata> fields = typeToFields.get(type);
   if (fields == null) fields = cacheFields(type);
   FieldMetadata metadata = fields.get(fieldName);
   if (metadata == null)
     throw new SerializationException(
         "Field not found: " + fieldName + " (" + type.getName() + ")");
   Field field = metadata.field;
   JsonValue jsonValue = jsonMap.get(jsonName);
   if (jsonValue == null) return;
   if (elementType == null) elementType = metadata.elementType;
   try {
     field.set(object, readValue(field.getType().getClassOfType(), elementType, jsonValue));
   } catch (IllegalAccessException ex) {
     throw new SerializationException(
         "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
   } catch (SerializationException ex) {
     ex.addTrace(field.getName() + " (" + type.getName() + ")");
     throw ex;
   } catch (RuntimeException runtimeEx) {
     SerializationException ex = new SerializationException(runtimeEx);
     ex.addTrace(field.getName() + " (" + type.getName() + ")");
     throw ex;
   }
 }
Exemplo n.º 2
0
  private ObjectMap<String, FieldMetadata> cacheFields(Type type) {
    ArrayList<Field> allFields = new ArrayList();
    Type nextClass = type;
    while (nextClass != null && nextClass.getClassOfType() != Object.class) {
      Collections.addAll(allFields, nextClass.getDeclaredFields());
      nextClass = nextClass.getSuperclass();
    }

    ObjectMap<String, FieldMetadata> nameToField = new ObjectMap();
    for (int i = 0, n = allFields.size(); i < n; i++) {
      Field field = allFields.get(i);

      if (field.isTransient()) continue;
      if (field.isStatic()) continue;
      if (field.isSynthetic()) continue;

      if (!field.isAccessible()) {
        try {
          field.setAccessible(true);
        } catch (AccessControlException ex) {
          continue;
        }
      }

      nameToField.put(field.getName(), new FieldMetadata(field));
    }
    typeToFields.put(type, nameToField);
    return nameToField;
  }
Exemplo n.º 3
0
 private Object newInstance(Type type) {
   try {
     return type.newInstance();
   } catch (Exception ex) {
     try {
       // Try a private constructor.
       Constructor constructor = type.getDeclaredConstructor();
       constructor.setAccessible(true);
       return constructor.newInstance();
     } catch (SecurityException ignored) {
     } catch (NoSuchMethodException ignored) {
       if (type.isArray())
         throw new SerializationException(
             "Encountered JSON object when expected array of type: " + type.getName(), ex);
       else if (type.isMemberClass() && !type.isStatic())
         throw new SerializationException(
             "Class cannot be created (non-static member class): " + type.getName(), ex);
       else
         throw new SerializationException(
             "Class cannot be created (missing no-arg constructor): " + type.getName(), ex);
     } catch (Exception privateConstructorException) {
       ex = privateConstructorException;
     }
     throw new SerializationException(
         "Error constructing instance of class: " + type.getName(), ex);
   }
 }
Exemplo n.º 4
0
 /**
  * s * @return an array containing all public methods of this class and its super classes. See
  * {@link Class#getMethods()}.
  */
 public Method[] getMethods() {
   if (allMethods == null) {
     ArrayList<Method> allMethodsList = new ArrayList<Method>();
     Type t = this;
     while (t != null) {
       for (Method m : t.methods) {
         if (m.isPublic()) allMethodsList.add(m);
       }
       t = t.getSuperclass();
     }
     allMethods = allMethodsList.toArray(new Method[allMethodsList.size()]);
   }
   return allMethods;
 }
Exemplo n.º 5
0
 /**
  * @return an array containing all the public fields of this class and its super classes. See
  *     {@link Class#getFields()}.
  */
 public Field[] getFields() {
   if (allFields == null) {
     ArrayList<Field> allFieldsList = new ArrayList<Field>();
     Type t = this;
     while (t != null) {
       for (Field f : t.fields) {
         if (f.isPublic) allFieldsList.add(f);
       }
       t = t.getSuperclass();
     }
     allFields = allFieldsList.toArray(new Field[allFieldsList.size()]);
   }
   return allFields;
 }
Exemplo n.º 6
0
 public void readFields(Object object, JsonValue jsonMap) {
   Type type = ReflectionCache.getType(object.getClass());
   ObjectMap<String, FieldMetadata> fields = typeToFields.get(type);
   if (fields == null) fields = cacheFields(type);
   for (JsonValue child = jsonMap.child(); child != null; child = child.next()) {
     FieldMetadata metadata = fields.get(child.name());
     if (metadata == null) {
       if (ignoreUnknownFields) {
         if (debug)
           System.out.println(
               "Ignoring unknown field: " + child.name() + " (" + type.getName() + ")");
         continue;
       } else
         throw new SerializationException(
             "Field not found: " + child.name() + " (" + type.getName() + ")");
     }
     Field field = metadata.field;
     // if (entry.value == null) continue; // I don't remember what this did. :(
     try {
       field.set(object, readValue(field.getType().getClassOfType(), metadata.elementType, child));
     } catch (IllegalAccessException ex) {
       throw new SerializationException(
           "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
     } catch (SerializationException ex) {
       ex.addTrace(field.getName() + " (" + type.getName() + ")");
       throw ex;
     } catch (RuntimeException runtimeEx) {
       SerializationException ex = new SerializationException(runtimeEx);
       ex.addTrace(field.getName() + " (" + type.getName() + ")");
       throw ex;
     }
   }
 }
Exemplo n.º 7
0
 /** @param elementType May be null if the type is unknown. */
 public void writeField(Object object, String fieldName, String jsonName, Class elementType) {
   Type type = ReflectionCache.getType(object.getClass());
   ObjectMap<String, FieldMetadata> fields = typeToFields.get(type);
   if (fields == null) fields = cacheFields(type);
   FieldMetadata metadata = fields.get(fieldName);
   if (metadata == null)
     throw new SerializationException(
         "Field not found: " + fieldName + " (" + type.getName() + ")");
   Field field = metadata.field;
   if (elementType == null) elementType = metadata.elementType;
   try {
     if (debug)
       System.out.println("Writing field: " + field.getName() + " (" + type.getName() + ")");
     writer.name(jsonName);
     writeValue(field.get(object), field.getType().getClassOfType(), elementType);
   } catch (IllegalAccessException ex) {
     throw new SerializationException(
         "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
   } catch (SerializationException ex) {
     ex.addTrace(field + " (" + type.getName() + ")");
     throw ex;
   } catch (Exception runtimeEx) {
     SerializationException ex = new SerializationException(runtimeEx);
     ex.addTrace(field + " (" + type.getName() + ")");
     throw ex;
   }
 }
Exemplo n.º 8
0
  private Object[] getDefaultValues(Type type) {
    if (!usePrototypes) return null;
    if (classToDefaultValues.containsKey(type)) return classToDefaultValues.get(type);
    Object object;
    try {
      object = newInstance(type);
    } catch (Exception ex) {
      classToDefaultValues.put(type, null);
      return null;
    }

    ObjectMap<String, FieldMetadata> fields = typeToFields.get(type);
    if (fields == null) fields = cacheFields(type);

    Object[] values = new Object[fields.size];
    classToDefaultValues.put(type, values);

    int i = 0;
    for (FieldMetadata metadata : fields.values()) {
      Field field = metadata.field;
      try {
        values[i++] = field.get(object);
      } catch (IllegalAccessException ex) {
        throw new SerializationException(
            "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
      } catch (SerializationException ex) {
        ex.addTrace(field + " (" + type.getName() + ")");
        throw ex;
      } catch (RuntimeException runtimeEx) {
        SerializationException ex = new SerializationException(runtimeEx);
        ex.addTrace(field + " (" + type.getName() + ")");
        throw ex;
      }
    }
    return values;
  }
Exemplo n.º 9
0
  public void writeFields(Object object) {
    Type type = ReflectionCache.getType(object.getClass());

    Object[] defaultValues = getDefaultValues(type);

    ObjectMap<String, FieldMetadata> fields = typeToFields.get(type);
    if (fields == null) fields = cacheFields(type);
    int i = 0;
    for (FieldMetadata metadata : new Values<FieldMetadata>(fields)) {
      Field field = metadata.field;
      try {
        Object value = field.get(object);

        if (defaultValues != null) {
          Object defaultValue = defaultValues[i++];
          if (value == null && defaultValue == null) continue;
          if (value != null && defaultValue != null && value.equals(defaultValue)) continue;
        }

        if (debug)
          System.out.println("Writing field: " + field.getName() + " (" + type.getName() + ")");
        writer.name(field.getName());
        writeValue(value, field.getType().getClassOfType(), metadata.elementType);
      } catch (IllegalAccessException ex) {
        throw new SerializationException(
            "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
      } catch (SerializationException ex) {
        ex.addTrace(field + " (" + type.getName() + ")");
        throw ex;
      } catch (Exception runtimeEx) {
        SerializationException ex = new SerializationException(runtimeEx);
        ex.addTrace(field + " (" + type.getName() + ")");
        throw ex;
      }
    }
  }
Exemplo n.º 10
0
 public String getTag(Type type) {
   String tag = classToTag.get(type);
   if (tag != null) return tag;
   return type.getName();
 }
Exemplo n.º 11
0
  /**
   * @param clazz May be null if the type is unknown.
   * @param elementType May be null if the type is unknown.
   * @return May be null.
   */
  public <T> T readValue(Class<T> clazz, Class elementType, JsonValue jsonData) {
    if (jsonData == null) return null;

    Type type = ReflectionCache.getType(clazz);
    if (jsonData.isObject()) {
      String className = typeName == null ? null : jsonData.getString(typeName, null);
      if (className != null) {
        jsonData.remove(typeName);
        try {
          type = ReflectionCache.forName(className);
        } catch (ClassNotFoundException ex) {
          type = tagToClass.get(className);
          if (type == null) throw new SerializationException(ex);
        }
      }

      Object object;
      if (type != null) {
        Serializer serializer = classToSerializer.get(type);
        if (serializer != null) return (T) serializer.read(this, jsonData, type.getClassOfType());

        object = newInstance(type);

        if (object instanceof Serializable) {
          ((Serializable) object).read(this, jsonData);
          return (T) object;
        }

        if (object instanceof HashMap) {
          HashMap result = (HashMap) object;
          for (JsonValue child = jsonData.child(); child != null; child = child.next())
            result.put(child.name(), readValue(elementType, null, child));
          return (T) result;
        }
      } else object = new OrderedMap();

      if (object instanceof ObjectMap) {
        ObjectMap result = (ObjectMap) object;
        for (JsonValue child = jsonData.child(); child != null; child = child.next())
          result.put(child.name(), readValue(elementType, null, child));
        return (T) result;
      }

      readFields(object, jsonData);
      return (T) object;
    }

    if (type != null) {
      Serializer serializer = classToSerializer.get(type);
      if (serializer != null) return (T) serializer.read(this, jsonData, type.getClassOfType());
    }

    if (jsonData.isArray()) {
      if (type == null || type.isAssignableFrom(ReflectionCache.getType(Array.class))) {
        Array newArray = new Array();
        for (JsonValue child = jsonData.child(); child != null; child = child.next())
          newArray.add(readValue(elementType, null, child));
        return (T) newArray;
      }
      if (type.isAssignableFrom(ReflectionCache.getType(ArrayList.class))) {
        ArrayList newArray = new ArrayList();
        for (JsonValue child = jsonData.child(); child != null; child = child.next())
          newArray.add(readValue(elementType, null, child));
        return (T) newArray;
      }
      if (type.isArray()) {
        Class componentType = type.getComponentType();
        if (elementType == null) elementType = componentType;
        Object newArray = ReflectionCache.newArray(componentType, jsonData.size());
        Type arrayType = ReflectionCache.getType(newArray.getClass());
        int i = 0;
        for (JsonValue child = jsonData.child(); child != null; child = child.next())
          arrayType.setArrayElement(newArray, i++, readValue(elementType, null, child));
        return (T) newArray;
      }
      throw new SerializationException(
          "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")");
    }

    Class t = type == null ? null : type.getClassOfType();
    if (jsonData.isNumber()) {
      try {
        if (type == null || t == float.class || t == Float.class)
          return (T) (Float) jsonData.asFloat();
        if (t == int.class || t == Integer.class) return (T) (Integer) jsonData.asInt();
        if (t == long.class || t == Long.class) return (T) (Long) jsonData.asLong();
        if (t == double.class || t == Double.class) return (T) (Double) (double) jsonData.asFloat();
        if (t == String.class) return (T) Float.toString(jsonData.asFloat());
        if (t == short.class || t == Short.class) return (T) (Short) (short) jsonData.asInt();
        if (t == byte.class || t == Byte.class) return (T) (Byte) (byte) jsonData.asInt();
      } catch (NumberFormatException ignored) {
      }
      jsonData = new JsonValue(jsonData.asString());
    }

    if (jsonData.isBoolean()) {
      try {
        if (type == null || t == boolean.class || t == Boolean.class)
          return (T) (Boolean) jsonData.asBoolean();
      } catch (NumberFormatException ignored) {
      }
      jsonData = new JsonValue(jsonData.asString());
    }

    if (jsonData.isString()) {
      String string = jsonData.asString();
      if (type == null || t == String.class) return (T) string;
      try {
        if (t == int.class || t == Integer.class) return (T) Integer.valueOf(string);
        if (t == float.class || t == Float.class) return (T) Float.valueOf(string);
        if (t == long.class || t == Long.class) return (T) Long.valueOf(string);
        if (t == double.class || t == Double.class) return (T) Double.valueOf(string);
        if (t == short.class || t == Short.class) return (T) Short.valueOf(string);
        if (t == byte.class || t == Byte.class) return (T) Byte.valueOf(string);
      } catch (NumberFormatException ignored) {
      }
      if (t == boolean.class || t == Boolean.class) return (T) Boolean.valueOf(string);
      if (t == char.class || t == Character.class) return (T) (Character) string.charAt(0);
      if (type.isEnum()) {
        Object[] constants = type.getEnumConstants();
        for (int i = 0, n = constants.length; i < n; i++)
          if (string.equals(constants[i].toString())) return (T) constants[i];
      }
      if (t == CharSequence.class) return (T) string;
      throw new SerializationException(
          "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")");
    }

    return null;
  }
Exemplo n.º 12
0
  /**
   * @param value May be null.
   * @param knownClass May be null if the type is unknown.
   * @param elementType May be null if the type is unknown.
   */
  public void writeValue(Object value, Class knownClass, Class elementType) {
    try {
      if (value == null) {
        writer.value(null);
        return;
      }

      Type knownType = ReflectionCache.getType(knownClass);
      Type actualType = ReflectionCache.getType(value.getClass());

      if (actualType.isPrimitive()
          || actualType.getClassOfType() == String.class
          || actualType.getClassOfType() == Integer.class
          || actualType.getClassOfType() == Boolean.class
          || actualType.getClassOfType() == Float.class
          || actualType.getClassOfType() == Long.class
          || actualType.getClassOfType() == Double.class
          || actualType.getClassOfType() == Short.class
          || actualType.getClassOfType() == Byte.class
          || actualType.getClassOfType() == Character.class) {
        writer.value(value);
        return;
      }

      if (value instanceof Serializable) {
        writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
        ((Serializable) value).write(this);
        writeObjectEnd();
        return;
      }

      Serializer serializer = classToSerializer.get(actualType);
      if (serializer != null) {
        serializer.write(this, value, knownType.getClassOfType());
        return;
      }

      if (value instanceof Array) {
        if (knownType != null && actualType != knownType)
          throw new SerializationException(
              "Serialization of an Array other than the known type is not supported.\n"
                  + "Known type: "
                  + knownType
                  + "\nActual type: "
                  + actualType);
        writeArrayStart();
        Array array = (Array) value;
        for (int i = 0, n = array.size; i < n; i++) writeValue(array.get(i), elementType, null);
        writeArrayEnd();
        return;
      }

      if (value instanceof Collection) {
        if (knownType != null && actualType != knownType)
          throw new SerializationException(
              "Serialization of a Collection other than the known type is not supported.\n"
                  + "Known type: "
                  + knownType
                  + "\nActual type: "
                  + actualType);
        writeArrayStart();
        for (Object item : (Collection) value) writeValue(item, elementType, null);
        writeArrayEnd();
        return;
      }

      if (actualType.isArray()) {
        if (elementType == null) elementType = actualType.getComponentType();
        int length = actualType.getArrayLength(value);
        writeArrayStart();
        for (int i = 0; i < length; i++)
          writeValue(actualType.getArrayElement(value, i), elementType, null);
        writeArrayEnd();
        return;
      }

      if (value instanceof OrderedMap) {
        if (knownType == null) knownType = ReflectionCache.getType(OrderedMap.class);
        writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
        OrderedMap map = (OrderedMap) value;
        for (Object key : map.orderedKeys()) {
          writer.name(convertToString(key));
          writeValue(map.get(key), elementType, null);
        }
        writeObjectEnd();
        return;
      }

      if (value instanceof ArrayMap) {
        if (knownType == null) knownType = ReflectionCache.getType(ArrayMap.class);
        writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
        ArrayMap map = (ArrayMap) value;
        for (int i = 0, n = map.size; i < n; i++) {
          writer.name(convertToString(map.keys[i]));
          writeValue(map.values[i], elementType, null);
        }
        writeObjectEnd();
        return;
      }

      if (value instanceof ObjectMap) {
        if (knownType == null) knownType = ReflectionCache.getType(OrderedMap.class);
        writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
        for (Entry entry : ((ObjectMap<?, ?>) value).entries()) {
          writer.name(convertToString(entry.key));
          writeValue(entry.value, elementType, null);
        }
        writeObjectEnd();
        return;
      }

      if (value instanceof Map) {
        if (knownType == null) knownType = ReflectionCache.getType(HashMap.class);
        writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
        for (Map.Entry entry : ((Map<?, ?>) value).entrySet()) {
          writer.name(convertToString(entry.getKey()));
          writeValue(entry.getValue(), elementType, null);
        }
        writeObjectEnd();
        return;
      }

      if (actualType.isEnum()) {
        writer.value(value);
        return;
      }

      writeObjectStart(actualType.getClassOfType(), knownType.getClassOfType());
      writeFields(value);
      writeObjectEnd();
    } catch (IOException ex) {
      throw new SerializationException(ex);
    }
  }