() {
public Class onClass(Class c,Void _) {
return c;
}
public Class onParameterizdType(ParameterizedType p,Void _) {
// TODO: why getRawType returns Type? not Class?
return visit(p.getRawType(),null);
}
public Class onGenericArray(GenericArrayType g,Void _) {
return Array.newInstance(
visit(g.getGenericComponentType(),null),
0 ).getClass();
}
public Class onVariable(TypeVariable v,Void _) {
return visit(v.getBounds()[0],null);
}
public Class onWildcard(WildcardType w,Void _) {
return visit(w.getUpperBounds()[0],null);
}
};
/**
* Returns the {@link Class} representation of the given type.
*
* This corresponds to the notion of the erasure in JSR-14.
*
*
* It made me realize how difficult it is to define the common navigation
* layer for two different underlying reflection library. The other way
* is to throw away the entire parameterization and go to the wrapper approach.
*/
public static Class erasure(Type t) {
return eraser.visit(t,null);
}
/**
* Returns the {@link Type} object that represents {@code clazz<T1,T2,T3>}.
*/
public static ParameterizedType createParameterizedType( Class rawType, Type... arguments ) {
return new ParameterizedTypeImpl(rawType,arguments,null);
}
/**
* Checks if the type is an array type.
*/
public static boolean isArray(Type t) {
if (t instanceof Class) {
Class c = (Class) t;
return c.isArray();
}
if(t instanceof GenericArrayType)
return true;
return false;
}
/**
* Checks if the type is an array type but not byte[].
*/
public static boolean isArrayButNotByteArray(Type t) {
if (t instanceof Class) {
Class c = (Class) t;
return c.isArray() && c!=byte[].class;
}
if(t instanceof GenericArrayType) {
t = ((GenericArrayType)t).getGenericComponentType();
return t!=Byte.TYPE;
}
return false;
}
/**
* Gets the component type of the array.
*
* @param t
* must be an array.
*/
public static Type getComponentType(Type t) {
if (t instanceof Class) {
Class c = (Class) t;
return c.getComponentType();
}
if(t instanceof GenericArrayType)
return ((GenericArrayType)t).getGenericComponentType();
throw new IllegalArgumentException();
}
/**
* Gets the i-th type argument from a parameterized type.
*
*
* Unlike {@link #getTypeArgument(Type, int, Type)}, this method
* throws {@link IllegalArgumentException} if the given type is
* not parameterized.
*/
public static Type getTypeArgument(Type type, int i) {
Type r = getTypeArgument(type, i, null);
if(r==null)
throw new IllegalArgumentException();
return r;
}
/**
* Gets the i-th type argument from a parameterized type.
*
*
* For example, {@code getTypeArgument([Map],0)=Integer}
* If the given type is not a parameterized type, returns the specified
* default value.
*
*
* This is convenient for handling raw types and parameterized types uniformly.
*
* @throws IndexOutOfBoundsException
* If i is out of range.
*/
public static Type getTypeArgument(Type type, int i, Type defaultValue) {
if (type instanceof ParameterizedType) {
ParameterizedType p = (ParameterizedType) type;
return fix(p.getActualTypeArguments()[i]);
} else
return defaultValue;
}
/**
* Checks if the given type is a primitive type.
*/
public static boolean isPrimitive(Type type) {
if (type instanceof Class) {
Class c = (Class) type;
return c.isPrimitive();
}
return false;
}
public static boolean isOverriding(Method method, Class base) {
// this isn't actually correct,
// as the JLS considers
// class Derived extends Base {
// Integer getX() { ... }
// }
// class Base {
// T getX() { ... }
// }
// to be overrided. Handling this correctly needs a careful implementation
String name = method.getName();
Class[] params = method.getParameterTypes();
while(base!=null) {
try {
if(base.getDeclaredMethod(name,params)!=null)
return true;
} catch (NoSuchMethodException e) {
// recursively go into the base class
}
base = base.getSuperclass();
}
return false;
}
/**
* JDK 5.0 has a bug of createing {@link GenericArrayType} where it shouldn't.
* fix that manually to work around the problem.
*
* See bug 6202725.
*/
private static Type fix(Type t) {
if(!(t instanceof GenericArrayType))
return t;
GenericArrayType gat = (GenericArrayType) t;
if(gat.getGenericComponentType() instanceof Class) {
Class c = (Class) gat.getGenericComponentType();
return Array.newInstance(c,0).getClass();
}
return t;
}
}
tiger-types-1.4/src/main/java/org/jvnet/tiger_types/Lister.java 0000644 0001750 0001750 00000014074 11455654743 025344 0 ustar jamespage jamespage /*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.tiger_types;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.EnumSet;
/**
* Abstracts away the process of creating a collection (array, {@link List}, etc)
* of items.
*
* @author Kohsuke Kawaguchi
*/
public abstract class Lister {
/**
* Type of the individual item
*/
public final Class itemType;
public final Type itemGenericType;
protected final Collection r;
protected Lister(Class itemType, Type itemGenericType) {
this(itemType,itemGenericType,new ArrayList());
}
protected Lister(Class itemType, Type itemGenericType, Collection r) {
this.itemType = itemType;
this.itemGenericType = itemGenericType;
this.r = r;
}
public void add(Object o) {
r.add(o);
}
public abstract T toCollection();
/**
* Creates a {@link Lister} instance that produces the given type.
*/
public static Lister create(Type t) {
return create(Types.erasure(t),t);
}
/**
* Creates a {@link Lister} instance that produces the given type.
*
* @param c
* The erasure version of 't'. This is taken
* as a parameter as a performance optimizaiton.
*
* @return
* null if the given type doesn't look like a collection.
* @throws IllegalArgumentException
* if the given type does look like a collection yet this implementation
* is not capable of how to handle it.
*/
public static Lister create(Class c, Type t) {
if(c.isArray()) {
// array
Class> ct = c.getComponentType();
return new Lister(ct,ct) {
public Object toCollection() {
return r.toArray((Object[])Array.newInstance(itemType,r.size()));
}
};
}
if(Collection.class.isAssignableFrom(c)) {
final Type col = Types.getBaseClass(t, Collection.class);
final Type itemType;
if (col instanceof ParameterizedType)
itemType = Types.getTypeArgument(col, 0);
else
itemType = Object.class;
Collection items=null;
try {
items = (Collection)c.newInstance();
} catch (InstantiationException e) {
// this is not instanciable. Try known instanciable versions.
for (Class ct : CONCRETE_TYPES) {
if(c.isAssignableFrom(ct)) {
try {
items = (Collection)ct.newInstance();
break;
} catch (InstantiationException x) {
throw toError(x);
} catch (IllegalAccessException x) {
throw toError(x);
}
}
}
// EnumSet
if(items==null && c==EnumSet.class) {
items = EnumSet.noneOf(Types.erasure(itemType).asSubclass(Enum.class));
}
if(items==null)
throw new IllegalArgumentException("Don't know how to instanciate "+c);
} catch (IllegalAccessException e) {
throw toError(e);
}
return new Lister(Types.erasure(itemType),itemType,items) {
public Object toCollection() {
return r;
}
};
}
return null;
}
private static IllegalAccessError toError(IllegalAccessException e) {
IllegalAccessError x = new IllegalAccessError();
x.initCause(e);
return x;
}
private static InstantiationError toError(InstantiationException e) {
InstantiationError x = new InstantiationError();
x.initCause(e);
return x;
}
private static final Class[] CONCRETE_TYPES = new Class[] {
ArrayList.class,
HashSet.class
};
}
tiger-types-1.4/src/main/java/org/jvnet/tiger_types/GenericArrayTypeImpl.java 0000644 0001750 0001750 00000006703 11455654743 030141 0 ustar jamespage jamespage /*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.tiger_types;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
/**
* Implementation of GenericArrayType interface for core reflection.
*/
final class GenericArrayTypeImpl implements GenericArrayType {
private Type genericComponentType;
GenericArrayTypeImpl(Type ct) {
assert ct!=null;
genericComponentType = ct;
}
/**
* Returns a Type object representing the component type
* of this array.
*
* @return a Type object representing the component type
* of this array
* @since 1.5
*/
public Type getGenericComponentType() {
return genericComponentType; // return cached component type
}
public String toString() {
Type componentType = getGenericComponentType();
StringBuilder sb = new StringBuilder();
if (componentType instanceof Class)
sb.append(((Class) componentType).getName());
else
sb.append(componentType.toString());
sb.append("[]");
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (o instanceof GenericArrayType) {
GenericArrayType that = (GenericArrayType) o;
Type thatComponentType = that.getGenericComponentType();
return genericComponentType.equals(thatComponentType);
} else
return false;
}
@Override
public int hashCode() {
return genericComponentType.hashCode();
}
}
tiger-types-1.4/src/main/java/org/jvnet/tiger_types/ParameterizedTypeImpl.java 0000644 0001750 0001750 00000015663 11455654743 030367 0 ustar jamespage jamespage /*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.tiger_types;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.util.Arrays;
/**
* {@link ParameterizedType} implementation.
*/
final class ParameterizedTypeImpl implements ParameterizedType {
private Type[] actualTypeArguments;
private Class> rawType;
private Type ownerType;
ParameterizedTypeImpl(Class> rawType,
Type[] actualTypeArguments,
Type ownerType) {
this.actualTypeArguments = actualTypeArguments;
this.rawType = rawType;
if (ownerType != null) {
this.ownerType = ownerType;
} else {
this.ownerType = rawType.getDeclaringClass();
}
validateConstructorArguments();
}
private void validateConstructorArguments() {
TypeVariable/*>*/[] formals = rawType.getTypeParameters();
// check correct arity of actual type args
if (formals.length != actualTypeArguments.length) {
throw new MalformedParameterizedTypeException();
}
for (int i = 0; i < actualTypeArguments.length; i++) {
// check actuals against formals' bounds
}
}
public Type[] getActualTypeArguments() {
return actualTypeArguments.clone();
}
public Class> getRawType() {
return rawType;
}
public Type getOwnerType() {
return ownerType;
}
/*
* From the JavaDoc for java.lang.reflect.ParameterizedType
* "Instances of classes that implement this interface must
* implement an equals() method that equates any two instances
* that share the same generic type declaration and have equal
* type parameters."
*/
@Override
public boolean equals(Object o) {
if (o instanceof ParameterizedType) {
// Check that information is equivalent
ParameterizedType that = (ParameterizedType) o;
if (this == that)
return true;
Type thatOwner = that.getOwnerType();
Type thatRawType = that.getRawType();
if (false) { // Debugging
boolean ownerEquality = (ownerType == null ?
thatOwner == null :
ownerType.equals(thatOwner));
boolean rawEquality = (rawType == null ?
thatRawType == null :
rawType.equals(thatRawType));
boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
for (Type t : actualTypeArguments) {
System.out.printf("\t\t%s%s%n", t, t.getClass());
}
System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
ownerEquality, rawEquality, typeArgEquality);
return ownerEquality && rawEquality && typeArgEquality;
}
return
(ownerType == null ?
thatOwner == null :
ownerType.equals(thatOwner)) &&
(rawType == null ?
thatRawType == null :
rawType.equals(thatRawType)) &&
Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
} else
return false;
}
@Override
public int hashCode() {
return Arrays.hashCode(actualTypeArguments) ^
(ownerType == null ? 0 : ownerType.hashCode()) ^
(rawType == null ? 0 : rawType.hashCode());
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (ownerType != null) {
if (ownerType instanceof Class)
sb.append(((Class) ownerType).getName());
else
sb.append(ownerType.toString());
sb.append(".");
if (ownerType instanceof ParameterizedTypeImpl) {
// Find simple name of nested type by removing the
// shared prefix with owner.
sb.append(rawType.getName().replace(((ParameterizedTypeImpl) ownerType).rawType.getName() + "$",
""));
} else
sb.append(rawType.getName());
} else
sb.append(rawType.getName());
if (actualTypeArguments != null &&
actualTypeArguments.length > 0) {
sb.append("<");
boolean first = true;
for (Type t : actualTypeArguments) {
if (!first)
sb.append(", ");
if (t instanceof Class)
sb.append(((Class) t).getName());
else
sb.append(t.toString());
first = false;
}
sb.append(">");
}
return sb.toString();
}
}