package bluej.utility;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import bluej.debugger.gentype.ConstructorReflective;
import bluej.debugger.gentype.FieldReflective;
import bluej.debugger.gentype.GenTypeClass;
import bluej.debugger.gentype.GenTypeDeclTpar;
import bluej.debugger.gentype.JavaPrimitiveType;
import bluej.debugger.gentype.JavaType;
import bluej.debugger.gentype.MethodReflective;
import bluej.debugger.gentype.Reflective;
| A reflective for GenTypeClass which uses the standard java reflection API.
|
| @author Davin McCall
|
public class JavaReflective
extends Reflective{
private Class<?> c;
@Override
public int hashCode()
{
return c.hashCode();
}
@Override
public boolean equals(Object other)
{
if (other instanceof JavaReflective) {
JavaReflective jrOther = (JavaReflective) other;
return jrOther.c == c;
}
return false;
}
public JavaReflective(Class<?> c)
{
if (c == null)
throw new NullPointerException();
this.c = c;
}
@Override
public String getName()
{
return c.getName();
}
@Override
public String getSimpleName()
{
if (c.isArray()) {
return c.getComponentType().getName().replace('$', '.') + "[]";
}
else {
return c.getName().replace('$', '.');
}
}
@Override
public boolean isInterface()
{
return c.isInterface();
}
@Override
public boolean isStatic()
{
return Modifier.isStatic(c.getModifiers());
}
@Override
public boolean isPublic()
{
return Modifier.isPublic(c.getModifiers());
}
@Override
public boolean isFinal()
{
return Modifier.isFinal(c.getModifiers());
}
@Override
public List getTypeParams()
{
return JavaUtils.getJavaUtils().getTypeParams(c);
}
@Override
public Reflective getArrayOf()
{
String rname;
if (c.isArray())
rname = "[" + c.getName();
else{ rname = "[L" + c.getName() + ";";
}
try {
ClassLoader cloader = c.getClassLoader();
Class<?> arrClass = Class.forName(rname, false, cloader);
return new JavaReflective(arrClass);
}
catch (ClassNotFoundException cnfe) {
}
return null;
}
@Override
public Reflective getRelativeClass(String name)
{
try {
ClassLoader cloader = c.getClassLoader();
if (cloader == null)
cloader = ClassLoader.getSystemClassLoader();
Class<?> cr = cloader.loadClass(name);
return new JavaReflective(cr);
}
catch (ClassNotFoundException cnfe) {
return null;
}
catch (LinkageError le) {
return null;
}
}
@Override
public List getSuperTypesR()
{
List<Reflective> l = new ArrayList<Reflective>();
if (c.isArray()) {
Class<?> ct = c.getComponentType();
JavaReflective ctR = new JavaReflective(ct);
List<Reflective> componentSuperTypes = ctR.getSuperTypesR();
Iterator<Reflective> i = componentSuperTypes.iterator();
while (i.hasNext()){
JavaReflective componentSuperType = (JavaReflective) i.next();
l.add(componentSuperType.getArrayOf());
}
}
Class<?> superclass = c.getSuperclass();
if ( superclass != null )
l.add(new JavaReflective(superclass));
Class<?> [] interfaces = c.getInterfaces();
for ( int i = 0; i < interfaces.length; i++ ) {
l.add(new JavaReflective(interfaces[i]));
}
if (superclass == null && interfaces.length == 0 && c.isInterface())
l.add(new JavaReflective(Object.class));
return l;
}
@Override
public List getSuperTypes()
{
List<GenTypeClass> l = new ArrayList<GenTypeClass>();
if (c.isArray()) {
Class<?> ct = c.getComponentType();
JavaReflective ctR = new JavaReflective(ct);
List<GenTypeClass> componentSuperTypes = ctR.getSuperTypes();
Iterator<GenTypeClass> i = componentSuperTypes.iterator();
while (i.hasNext()){
GenTypeClass componentSuperType = i.next();
l.add(componentSuperType.getArray());
}
}
GenTypeClass superclass = null;
try {
superclass = JavaUtils.getJavaUtils().getSuperclass(c);
if ( superclass != null ) {
l.add(superclass);
}
}
catch (ClassNotFoundException cnfe) {
}
GenTypeClass[] interfaces;
try {
interfaces = JavaUtils.getJavaUtils().getInterfaces(c);
for ( int i = 0; i < interfaces.length; i++ ) {
l.add(interfaces[i]);
}
}
catch (ClassNotFoundException cnfe) {
interfaces = new GenTypeClass[0];
}
if (superclass == null && interfaces.length == 0 && c.isInterface()) {
l.add(new GenTypeClass(new JavaReflective(Object.class)));
}
return l;
}
| Get the underlying class (as a java.lang.Class object) that this
| reflective represents.
|
public Class> getUnderlyingClass()
{
return c;
}
@Override
public boolean isAssignableFrom(Reflective r)
{
if (r instanceof JavaReflective) {
return c.isAssignableFrom(((JavaReflective)r).getUnderlyingClass());
}
else {
return false;
}
}
@Override
public Map getDeclaredFields()
{
try {
Field [] fields = c.getDeclaredFields();
Map<String,FieldReflective> rmap = new HashMap<String,FieldReflective>();
for (int i = 0; i < fields.length; i++) {
try {
JavaType fieldType = JavaUtils.getJavaUtils().getFieldType(fields[i]);
FieldReflective fref = new FieldReflective(fields[i].getName(), fieldType,
fields[i].getModifiers(), this);
rmap.put(fields[i].getName(), fref);
}
catch (ClassNotFoundException cnfe) {
}
}
if (c.isArray()) {
rmap.put("length", new FieldReflective("length", JavaPrimitiveType.getInt(),
Modifier.PUBLIC | Modifier.FINAL, this));
}
return rmap;
}
catch (LinkageError le) {
return Collections.emptyMap();
}
}
@Override
public Map> getDeclaredMethods()
{
try {
Method [] methods = c.getDeclaredMethods();
Map<String,Set<MethodReflective>> rmap = new HashMap<String,Set<MethodReflective>>();
for (Method method : methods) {
if (method.isSynthetic()) {
continue;
}
JavaType rtype;
try {
rtype = JavaUtils.getJavaUtils().getReturnType(method);
}
catch (ClassNotFoundException cnfe) {
rtype = JavaUtils.getJavaUtils().getRawReturnType(method);
}
List<GenTypeDeclTpar> tpars = JavaUtils.getJavaUtils().getTypeParams(method);
Map<String,GenTypeDeclTpar> tparMap = new HashMap<String,GenTypeDeclTpar>();
storeTparMappings(tpars, tparMap);
if (! Modifier.isStatic(method.getModifiers())) {
getTparMapping(method.getDeclaringClass(), tparMap);
}
try {
JavaType [] paramTypes = JavaUtils.getJavaUtils().getParamGenTypes(method, false);
List<JavaType> paramTypesList = new ArrayList<JavaType>(paramTypes.length);
for (JavaType paramType : paramTypes) {
paramTypesList.add(paramType.mapTparsToTypes(tparMap).getUpperBound());
}
rtype = rtype.mapTparsToTypes(tparMap).getUpperBound();
String name = method.getName();
MethodReflective mr = new MethodReflective(name, rtype, tpars, paramTypesList,
this,
JavaUtils.getJavaUtils().isVarArgs(method),
method.getModifiers());
Set<MethodReflective> rset = rmap.get(method.getName());
if (rset == null) {
rset = new HashSet<MethodReflective>();
rmap.put(method.getName(), rset);
}
rset.add(mr);
}
catch (ClassNotFoundException cnfe) {
continue;
}
}
if (c.isArray()) {
rmap.put("clone", Collections.singleton(new MethodReflective("clone",
new GenTypeClass(new JavaReflective(Object.class)),
new ArrayList<GenTypeDeclTpar>(), new ArrayList<JavaType>(), this, false,
Modifier.PUBLIC)));
}
return rmap;
}
catch (LinkageError le) {
return Collections.emptyMap();
}
}
@Override
public List getDeclaredConstructors()
{
List<ConstructorReflective> r = new ArrayList<>();
try {
for (Constructor<?> con : c.getDeclaredConstructors())
{
List<GenTypeDeclTpar> tpars = JavaUtils.getJavaUtils().getTypeParams(con);
Map<String, GenTypeDeclTpar> tparMap = new HashMap<String, GenTypeDeclTpar>();
storeTparMappings(tpars, tparMap);
try
{
JavaType [] paramTypes = JavaUtils.getJavaUtils().getParamGenTypes(con);
List<JavaType> paramTypesList = new ArrayList<JavaType>(paramTypes.length);
for (JavaType paramType : paramTypes)
{
paramTypesList.add(paramType.mapTparsToTypes(tparMap).getUpperBound());
}
r.add(new ConstructorReflective(tpars, paramTypesList, this,
JavaUtils.getJavaUtils().isVarArgs(con), con.getModifiers()));
}
catch (ClassNotFoundException exc)
{
}
}
}
catch (LinkageError | SecurityException exc) {
}
return r;
}
| Store, into the specified map, a mapping from the enclosing method/class/constructor
| type parameter names to the corresponding type parameters. Existing entries in the
| map are not overwritten.
|
| @param c The type, whose enclosing entities type parameters are required
| @param tparMap The map, into which the mappings from name to type parameter are to be stored
|
private void getTparMapping(Class<?> c, Map<String,GenTypeDeclTpar> tparMap)
{
JavaUtils ju = JavaUtils.getJavaUtils();
List<GenTypeDeclTpar> tpars = ju.getTypeParams(c);
storeTparMappings(tpars, tparMap);
Method m = c.getEnclosingMethod();
Constructor<?> cc = c.getEnclosingConstructor();
c = c.getEnclosingClass();
while (c != null){
if (m != null) {
tpars = ju.getTypeParams(m);
storeTparMappings(tpars, tparMap);
if (! Modifier.isStatic(m.getModifiers())) {
c = m.getDeclaringClass();
}
m = null;
}
else if (cc != null) {
tpars = ju.getTypeParams(cc);
storeTparMappings(tpars, tparMap);
c = cc.getDeclaringClass();
cc = null;
}
if (c != null) {
tpars = ju.getTypeParams(c);
storeTparMappings(tpars, tparMap);
c = c.getEnclosingClass();
if (c != null) {
m = c.getEnclosingMethod();
cc = c.getEnclosingConstructor();
}
}
}
}
| Store a set of mappings from type parameter names to the type parameter (GenTypeDeclTpar).
| Existing mappings are not overwritten.
|
| @param tpars The set of type parameters to create mappings for
| @param map The map of name to type parameter
|
private void storeTparMappings(List<GenTypeDeclTpar> tpars, Map<String, ? super GenTypeDeclTpar> map)
{
for (GenTypeDeclTpar tpar : tpars) {
if (! map.containsKey(tpar.getTparName())) {
map.put(tpar.getTparName(), tpar);
}
}
}
@Override
public Reflective getOuterClass()
{
Class<?> declaring = c.getDeclaringClass();
if (declaring != null) {
return new JavaReflective(declaring);
}
return null;
}
@Override
public Reflective getInnerClass(String name)
{
try {
Class<?> [] declared = c.getDeclaredClasses();
for (Class<?> inner : declared) {
String innerName = inner.getName();
int lastDollar = innerName.lastIndexOf('$');
if (lastDollar != -1) {
String baseName = innerName.substring(lastDollar + 1);
if (baseName.equals(name)) {
return new JavaReflective(inner);
}
}
}
}
catch (LinkageError le) {
}
return null;
}
@Override
public String getModuleName()
{
return c.getModule() != null ? c.getModule().getName() : null;
}
}
top,
use,
map,
class JavaReflective
. hashCode
. equals
. JavaReflective
. getName
. getSimpleName
. isInterface
. isStatic
. isPublic
. isFinal
. getTypeParams
. getArrayOf
. getRelativeClass
. getSuperTypesR
. getSuperTypes
. getUnderlyingClass
. isAssignableFrom
. getDeclaredFields
. getDeclaredMethods
. getDeclaredConstructors
. getTparMapping
. storeTparMappings
. getOuterClass
. getInnerClass
. getModuleName
644 neLoCode
+ 13 LoComm