/** * ClassTypeSignature base * * @param clazz * @param builder */ private static String classTypeBase(String className) { return 'L' + encodeClassName(className); }
@SuppressWarnings("unchecked") private static <T> Class<T> getBound(Type[] bounds) { if (bounds.length == 0) { return (Class<T>) Object.class; } else { return getTypeParamBoundRawType(bounds[0]); } }
/** * JavaTypeSignature * * @param type * @param builder */ private static void javaType(Type type, StringBuilder builder) { if (type instanceof Class) { nonGenericType((Class<?>) type, builder); } else if (type instanceof ParameterizedType) { parameterizedType((ParameterizedType) type, builder); } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; builder.append('['); javaType(genericArrayType.getGenericComponentType(), builder); } else if (type instanceof WildcardType) { wildcardType((WildcardType) type, builder); } else if (type instanceof TypeVariable) { typeVariable((TypeVariable<?>) type, builder); } else { throw new IllegalArgumentException("Signature encoding error - unsupported type: " + type); } }
private static void parameterizedType(ParameterizedType parameterizedType, StringBuilder builder) { Type rawType = parameterizedType.getRawType(); if (rawType instanceof Class) { builder.append(classTypeBase(((Class<?>) rawType).getName())); } else { throw new IllegalStateException(String.format("Signature encoding error - unsupported raw type: %s of parameterized type: %s", parameterizedType, rawType)); } builder.append(TYPE_PARAM_DEL_START); for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { javaType(actualTypeArgument, builder); } builder.append(TYPE_PARAM_DEL_END); builder.append(SEMICOLON); }
/** * TypeParameter * * @param typeVariable * @param builder */ private static void typeParameter(TypeVariable<?> typeVariable, StringBuilder builder) { builder.append(typeVariable.getName()); Type[] bounds = typeVariable.getBounds(); if (bounds.length > 0) { for (int i = 0; i < bounds.length; i++) { // If the first bound is an interface, add additional colon to comply with the spec (ClassBound is not optional) if (i == 0 && getTypeParamBoundRawType(bounds[i]).isInterface()) { builder.append(COLON); } builder.append(COLON); javaType(bounds[i], builder); } } else { // If no upper bound is declared, the upper bound is java.lang.Object builder.append(COLON); javaType(Object.class, builder); } }
/** * BaseType, ClassTypeSignature or ArrayTypeSignature * * @param clazz */ private static void nonGenericType(Class<?> clazz, StringBuilder builder) { if (void.class.equals(clazz)) { builder.append(VOID_CLASS_DESCRIPTOR); } else if (byte.class.equals(clazz)) { builder.append(BYTE_CLASS_DESCRIPTOR); } else if (char.class.equals(clazz)) { builder.append(CHAR_CLASS_DESCRIPTOR); } else if (double.class.equals(clazz)) { builder.append(DOUBLE_CLASS_DESCRIPTOR); } else if (float.class.equals(clazz)) { builder.append(FLOAT_CLASS_DESCRIPTOR); } else if (int.class.equals(clazz)) { builder.append(INT_CLASS_DESCRIPTOR); } else if (long.class.equals(clazz)) { builder.append(LONG_CLASS_DESCRIPTOR); } else if (short.class.equals(clazz)) { builder.append(SHORT_CLASS_DESCRIPTOR); } else if (boolean.class.equals(clazz)) { builder.append(BOOLEAN_CLASS_DESCRIPTOR); } else if (clazz.isArray()) { builder.append(encodeClassName(clazz.getName())); } else { builder.append(classTypeBase(clazz.getName()) + SEMICOLON); } }
builder.append(TYPE_PARAM_DEL_START); for (TypeVariable<?> typeParam : typeParams) { typeParameter(typeParam, builder); if (params.length > 0) { for (Type paramType : params) { javaType(paramType, builder); javaType(method.getGenericReturnType(), builder); javaType(exceptionType, builder);
@SuppressWarnings("unchecked") private static <T> Class<T> getTypeParamBoundRawType(Type type) { if (type instanceof Class<?>) { return (Class<T>) type; } if (type instanceof ParameterizedType) { if (((ParameterizedType) type).getRawType() instanceof Class<?>) { return (Class<T>) ((ParameterizedType) type).getRawType(); } } if (type instanceof TypeVariable<?>) { TypeVariable<?> variable = (TypeVariable<?>) type; Type[] bounds = variable.getBounds(); return getBound(bounds); } throw new IllegalStateException("Signature encoding error - unexpected type parameter bound type: " + type); }
/** * Note that Java language does not support more than one upper/lower bound. * * @param wildcard * @param builder */ private static void wildcardType(WildcardType wildcard, StringBuilder builder) { if (wildcard.getLowerBounds().length > 0) { for (Type lowerBound : wildcard.getLowerBounds()) { builder.append(WILDCARD_LOWER_BOUND); javaType(lowerBound, builder); } } else { if (wildcard.getUpperBounds().length == 0 || (wildcard.getUpperBounds().length == 1 && Object.class.equals(wildcard.getUpperBounds()[0]))) { // If no upper bound is explicitly declared, the upper bound is java.lang.Object // It's not clear whether an empty array may be returned builder.append(WILDCARD_NO_BOUND); } else { for (Type upperBound : wildcard.getUpperBounds()) { builder.append(WILDCARD_UPPER_BOUND); javaType(upperBound, builder); } } } }
private static void parameterizedType(ParameterizedType parameterizedType, StringBuilder builder) { Type rawType = parameterizedType.getRawType(); if (rawType instanceof Class) { builder.append(classTypeBase(((Class<?>) rawType).getName())); } else { throw new IllegalStateException(String.format("Signature encoding error - unsupported raw type: %s of parameterized type: %s", parameterizedType, rawType)); } builder.append(TYPE_PARAM_DEL_START); for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { javaType(actualTypeArgument, builder); } builder.append(TYPE_PARAM_DEL_END); builder.append(SEMICOLON); }
/** * TypeParameter * * @param typeVariable * @param builder */ private static void typeParameter(TypeVariable<?> typeVariable, StringBuilder builder) { builder.append(typeVariable.getName()); Type[] bounds = typeVariable.getBounds(); if (bounds.length > 0) { for (int i = 0; i < bounds.length; i++) { // If the first bound is an interface, add additional colon to comply with the spec (ClassBound is not optional) if (i == 0 && getTypeParamBoundRawType(bounds[i]).isInterface()) { builder.append(COLON); } builder.append(COLON); javaType(bounds[i], builder); } } else { // If no upper bound is declared, the upper bound is java.lang.Object builder.append(COLON); javaType(Object.class, builder); } }
/** * BaseType, ClassTypeSignature or ArrayTypeSignature * * @param clazz */ private static void nonGenericType(Class<?> clazz, StringBuilder builder) { if (void.class.equals(clazz)) { builder.append(VOID_CLASS_DESCRIPTOR); } else if (byte.class.equals(clazz)) { builder.append(BYTE_CLASS_DESCRIPTOR); } else if (char.class.equals(clazz)) { builder.append(CHAR_CLASS_DESCRIPTOR); } else if (double.class.equals(clazz)) { builder.append(DOUBLE_CLASS_DESCRIPTOR); } else if (float.class.equals(clazz)) { builder.append(FLOAT_CLASS_DESCRIPTOR); } else if (int.class.equals(clazz)) { builder.append(INT_CLASS_DESCRIPTOR); } else if (long.class.equals(clazz)) { builder.append(LONG_CLASS_DESCRIPTOR); } else if (short.class.equals(clazz)) { builder.append(SHORT_CLASS_DESCRIPTOR); } else if (boolean.class.equals(clazz)) { builder.append(BOOLEAN_CLASS_DESCRIPTOR); } else if (clazz.isArray()) { builder.append(encodeClassName(clazz.getName())); } else { builder.append(classTypeBase(clazz.getName()) + SEMICOLON); } }
builder.append(TYPE_PARAM_DEL_START); for (TypeVariable<?> typeParam : typeParams) { typeParameter(typeParam, builder); if (params.length > 0) { for (Type paramType : params) { javaType(paramType, builder); javaType(method.getGenericReturnType(), builder); javaType(exceptionType, builder);
@SuppressWarnings("unchecked") private static <T> Class<T> getTypeParamBoundRawType(Type type) { if (type instanceof Class<?>) { return (Class<T>) type; } if (type instanceof ParameterizedType) { if (((ParameterizedType) type).getRawType() instanceof Class<?>) { return (Class<T>) ((ParameterizedType) type).getRawType(); } } if (type instanceof TypeVariable<?>) { TypeVariable<?> variable = (TypeVariable<?>) type; Type[] bounds = variable.getBounds(); return getBound(bounds); } throw new IllegalStateException("Signature encoding error - unexpected type parameter bound type: " + type); }
/** * Note that Java language does not support more than one upper/lower bound. * * @param wildcard * @param builder */ private static void wildcardType(WildcardType wildcard, StringBuilder builder) { if (wildcard.getLowerBounds().length > 0) { for (Type lowerBound : wildcard.getLowerBounds()) { builder.append(WILDCARD_LOWER_BOUND); javaType(lowerBound, builder); } } else { if (wildcard.getUpperBounds().length == 0 || (wildcard.getUpperBounds().length == 1 && Object.class.equals(wildcard.getUpperBounds()[0]))) { // If no upper bound is explicitly declared, the upper bound is java.lang.Object // It's not clear whether an empty array may be returned builder.append(WILDCARD_NO_BOUND); } else { for (Type upperBound : wildcard.getUpperBounds()) { builder.append(WILDCARD_UPPER_BOUND); javaType(upperBound, builder); } } } }
/** * JavaTypeSignature * * @param type * @param builder */ private static void javaType(Type type, StringBuilder builder) { if (type instanceof Class) { nonGenericType((Class<?>) type, builder); } else if (type instanceof ParameterizedType) { parameterizedType((ParameterizedType) type, builder); } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; builder.append('['); javaType(genericArrayType.getGenericComponentType(), builder); } else if (type instanceof WildcardType) { wildcardType((WildcardType) type, builder); } else if (type instanceof TypeVariable) { typeVariable((TypeVariable<?>) type, builder); } else { throw new IllegalArgumentException("Signature encoding error - unsupported type: " + type); } }
private static void parameterizedType(ParameterizedType parameterizedType, StringBuilder builder) { Type rawType = parameterizedType.getRawType(); if (rawType instanceof Class) { builder.append(classTypeBase(((Class<?>) rawType).getName())); } else { throw new IllegalStateException(String.format("Signature encoding error - unsupported raw type: %s of parameterized type: %s", parameterizedType, rawType)); } builder.append(TYPE_PARAM_DEL_START); for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { javaType(actualTypeArgument, builder); } builder.append(TYPE_PARAM_DEL_END); builder.append(SEMICOLON); }
/** * TypeParameter * * @param typeVariable * @param builder */ private static void typeParameter(TypeVariable<?> typeVariable, StringBuilder builder) { builder.append(typeVariable.getName()); Type[] bounds = typeVariable.getBounds(); if (bounds.length > 0) { for (int i = 0; i < bounds.length; i++) { // If the first bound is an interface, add additional colon to comply with the spec (ClassBound is not optional) if (i == 0 && getTypeParamBoundRawType(bounds[i]).isInterface()) { builder.append(COLON); } builder.append(COLON); javaType(bounds[i], builder); } } else { // If no upper bound is declared, the upper bound is java.lang.Object builder.append(COLON); javaType(Object.class, builder); } }
/** * BaseType, ClassTypeSignature or ArrayTypeSignature * * @param clazz */ private static void nonGenericType(Class<?> clazz, StringBuilder builder) { if (void.class.equals(clazz)) { builder.append(VOID_CLASS_DESCRIPTOR); } else if (byte.class.equals(clazz)) { builder.append(BYTE_CLASS_DESCRIPTOR); } else if (char.class.equals(clazz)) { builder.append(CHAR_CLASS_DESCRIPTOR); } else if (double.class.equals(clazz)) { builder.append(DOUBLE_CLASS_DESCRIPTOR); } else if (float.class.equals(clazz)) { builder.append(FLOAT_CLASS_DESCRIPTOR); } else if (int.class.equals(clazz)) { builder.append(INT_CLASS_DESCRIPTOR); } else if (long.class.equals(clazz)) { builder.append(LONG_CLASS_DESCRIPTOR); } else if (short.class.equals(clazz)) { builder.append(SHORT_CLASS_DESCRIPTOR); } else if (boolean.class.equals(clazz)) { builder.append(BOOLEAN_CLASS_DESCRIPTOR); } else if (clazz.isArray()) { builder.append(encodeClassName(clazz.getName())); } else { builder.append(classTypeBase(clazz.getName()) + SEMICOLON); } }
builder.append(TYPE_PARAM_DEL_START); for (TypeVariable<?> typeParam : typeParams) { typeParameter(typeParam, builder); if (params.length > 0) { for (Type paramType : params) { javaType(paramType, builder); javaType(method.getGenericReturnType(), builder); javaType(exceptionType, builder);