refactoring of ShrikeMethod code to allow reuse
tentative beginnings of refactoring to separate Java-specifics: so far IClass.getModifiers() and IMethod.getDeclaredExceptions() are declared to throw UnsupportedOperationException git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3200 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
9ac4057c84
commit
2649737e84
|
@ -0,0 +1,542 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyWarning;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.collections.BimodalMap;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.SmallMap;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.Warnings;
|
||||
|
||||
public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
||||
|
||||
protected BytecodeClass(T loader, IClassHierarchy cha) {
|
||||
this.loader = loader;
|
||||
this.cha = cha;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Atom which holds the name of the super class. We cache this for efficiency reasons.
|
||||
*/
|
||||
protected ImmutableByteArray superName;
|
||||
|
||||
/**
|
||||
* The names of interfaces for this class. We cache this for efficiency reasons.
|
||||
*/
|
||||
protected ImmutableByteArray[] interfaceNames;
|
||||
|
||||
|
||||
/**
|
||||
* The object that loaded this class.
|
||||
*/
|
||||
protected final T loader;
|
||||
|
||||
/**
|
||||
* Governing class hierarchy for this class
|
||||
*/
|
||||
protected final IClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod
|
||||
*
|
||||
* TODO: get rid of this for classes (though keep it for interfaces) instead ... use a VMT.
|
||||
*/
|
||||
protected Map<Selector, IMethod> methodMap;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod used to cache method lookups from superclasses
|
||||
*/
|
||||
protected Map<Selector, IMethod> inheritCache;
|
||||
|
||||
/**
|
||||
* Canonical type representation
|
||||
*/
|
||||
protected TypeReference typeReference;
|
||||
|
||||
/**
|
||||
* superclass
|
||||
*/
|
||||
protected IClass superClass;
|
||||
|
||||
/**
|
||||
* Compute the superclass lazily.
|
||||
*/
|
||||
protected boolean superclassComputed = false;
|
||||
|
||||
/**
|
||||
* The IClasses that represent all interfaces this class implements (if it's a class) or extends (it it's an interface)
|
||||
*/
|
||||
protected Collection<IClass> allInterfaces = null;
|
||||
|
||||
/**
|
||||
* The instance fields declared in this class.
|
||||
*/
|
||||
protected IField[] instanceFields;
|
||||
|
||||
/**
|
||||
* The static fields declared in this class.
|
||||
*/
|
||||
protected IField[] staticFields;
|
||||
|
||||
/**
|
||||
* hash code; cached here for efficiency
|
||||
*/
|
||||
protected int hashCode;
|
||||
|
||||
private final HashMap<Atom, IField> fieldMap = HashMapFactory.make(5);
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A warning for when we get a class not found exception
|
||||
*/
|
||||
private static class ClassNotFoundWarning extends Warning {
|
||||
|
||||
final ImmutableByteArray className;
|
||||
|
||||
ClassNotFoundWarning(ImmutableByteArray className) {
|
||||
super(Warning.SEVERE);
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + className;
|
||||
}
|
||||
|
||||
public static ClassNotFoundWarning create(ImmutableByteArray className) {
|
||||
return new ClassNotFoundWarning(className);
|
||||
}
|
||||
}
|
||||
|
||||
public IClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
protected abstract IMethod[] computeDeclaredMethods() throws InvalidClassFileException;
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getReference()
|
||||
*/
|
||||
public TypeReference getReference() {
|
||||
return typeReference;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getSourceFileName()
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
return loader.getSourceFileName(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isArrayClass()
|
||||
*/
|
||||
public boolean isArrayClass() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public IClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getName()
|
||||
*/
|
||||
public TypeName getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isReferenceType()
|
||||
*/
|
||||
public boolean isReferenceType() {
|
||||
return getReference().isReferenceType();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getField(com.ibm.wala.util.Atom)
|
||||
*/
|
||||
public IField getField(Atom name) {
|
||||
if (fieldMap.containsKey(name)) {
|
||||
return fieldMap.get(name);
|
||||
} else {
|
||||
IField f = findDeclaredField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
} else if (superClass != null) {
|
||||
f = superClass.getField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// try superinterfaces
|
||||
try {
|
||||
for (IClass i : getAllImplementedInterfaces()) {
|
||||
f = i.getField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void computeSuperclass() {
|
||||
superclassComputed = true;
|
||||
|
||||
if (superName == null) {
|
||||
if (!getReference().equals(loader.getLanguage().getRootType())) {
|
||||
superClass = loader.lookupClass(loader.getLanguage().getRootType().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
superClass = loader.lookupClass(TypeName.findOrCreate(superName));
|
||||
}
|
||||
|
||||
public IClass getSuperclass() throws ClassHierarchyException {
|
||||
if (!superclassComputed) {
|
||||
computeSuperclass();
|
||||
}
|
||||
if (superClass == null && !getReference().equals(TypeReference.JavaLangObject)) {
|
||||
throw new ClassHierarchyException("No superclass found for " + this);
|
||||
}
|
||||
return superClass;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllFields()
|
||||
*/
|
||||
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>();
|
||||
result.addAll(getAllInstanceFields());
|
||||
result.addAll(getAllStaticFields());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllImplementedInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException {
|
||||
if (allInterfaces != null) {
|
||||
return allInterfaces;
|
||||
} else {
|
||||
Collection<IClass> C = computeAllInterfacesAsCollection();
|
||||
allInterfaces = Collections.unmodifiableCollection(C);
|
||||
return allInterfaces;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(instanceFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(staticFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDirectInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
return array2IClassSet(interfaceNames);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllInstanceFields()
|
||||
*/
|
||||
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredInstanceFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredInstanceFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllStaticFields()
|
||||
*/
|
||||
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredStaticFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredStaticFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||
*/
|
||||
public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
|
||||
Collection<IMethod> result = new LinkedList<IMethod>();
|
||||
Iterator<IMethod> declaredMethods = getDeclaredMethods().iterator();
|
||||
while (declaredMethods.hasNext()) {
|
||||
result.add(declaredMethods.next());
|
||||
}
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
|
||||
while (superDeclaredMethods.hasNext()) {
|
||||
result.add(superDeclaredMethods.next());
|
||||
}
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
||||
*/
|
||||
public Collection<IMethod> getDeclaredMethods() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableCollection(methodMap.values());
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector)
|
||||
*/
|
||||
public IMethod getMethod(Selector selector) {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e1) {
|
||||
e1.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// my methods + cached parent stuff
|
||||
IMethod result = methodMap.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (inheritCache != null) {
|
||||
result = inheritCache.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// check parent, caching if found
|
||||
try {
|
||||
if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) {
|
||||
IClass superclass = getSuperclass();
|
||||
if (superclass != null) {
|
||||
IMethod inherit = superclass.getMethod(selector);
|
||||
if (inherit != null) {
|
||||
if (inheritCache == null) {
|
||||
inheritCache = new BimodalMap<Selector, IMethod>(5);
|
||||
}
|
||||
inheritCache.put(selector, inherit);
|
||||
return inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
// didn't find it yet. special logic for interfaces
|
||||
try {
|
||||
if (isInterface() || isAbstract()) {
|
||||
final Iterator<IClass> it = getAllImplementedInterfaces().iterator();
|
||||
// try each superinterface
|
||||
while (it.hasNext()) {
|
||||
IClass k = it.next();
|
||||
result = k.getMethod(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE("Bad method lookup in " + this);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected void populateFieldArrayFromList(List<FieldImpl> L, IField[] A) {
|
||||
Iterator<FieldImpl> it = L.iterator();
|
||||
for (int i = 0; i < A.length; i++) {
|
||||
A[i] = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection of IClasses, representing the interfaces this class implements.
|
||||
*/
|
||||
protected Collection<IClass> computeAllInterfacesAsCollection() throws ClassHierarchyException {
|
||||
Collection<IClass> c = getDirectInterfaces();
|
||||
Set<IClass> result = HashSetFactory.make();
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
if (klass.isInterface()) {
|
||||
result.add(klass);
|
||||
} else {
|
||||
Warnings.add(ClassHierarchyWarning.create("expected an interface " + klass));
|
||||
}
|
||||
}
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
BytecodeClass I = (BytecodeClass) it.next();
|
||||
if (I.isInterface()) {
|
||||
result.addAll(I.computeAllInterfacesAsCollection());
|
||||
} else {
|
||||
Warnings.add(ClassHierarchyWarning.create("expected an interface " + I));
|
||||
}
|
||||
}
|
||||
|
||||
// now add any interfaces from the super class
|
||||
IClass sup = null;
|
||||
try {
|
||||
sup = getSuperclass();
|
||||
} catch (ClassHierarchyException e1) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
if (sup != null) {
|
||||
result.addAll(sup.getAllImplementedInterfaces());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method array2Set.
|
||||
*
|
||||
* @param interfaces a set of class names
|
||||
* @return Set of all IClasses that can be loaded corresponding to the class names in the interfaces array; raise warnings if
|
||||
* classes can not be loaded
|
||||
*/
|
||||
private Collection<IClass> array2IClassSet(ImmutableByteArray[] interfaces) {
|
||||
ArrayList<IClass> result = new ArrayList<IClass>(interfaces.length);
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
ImmutableByteArray name = interfaces[i];
|
||||
IClass klass = null;
|
||||
klass = loader.lookupClass(TypeName.findOrCreate(name));
|
||||
if (klass == null) {
|
||||
Warnings.add(ClassNotFoundWarning.create(name));
|
||||
} else {
|
||||
result.add(klass);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected IField findDeclaredField(Atom name) {
|
||||
for (int i = 0; i < instanceFields.length; i++) {
|
||||
if (instanceFields[i].getName() == name) {
|
||||
return instanceFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < staticFields.length; i++) {
|
||||
if (staticFields[i].getName() == name) {
|
||||
return staticFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void addFieldToList(List<FieldImpl> L, Atom name, ImmutableByteArray fieldType, int accessFlags,
|
||||
Collection<Annotation> annotations) {
|
||||
TypeName T = null;
|
||||
if (fieldType.get(fieldType.length() - 1) == ';') {
|
||||
T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1);
|
||||
} else {
|
||||
T = TypeName.findOrCreate(fieldType);
|
||||
}
|
||||
TypeReference type = TypeReference.findOrCreate(getClassLoader().getReference(), T);
|
||||
FieldReference fr = FieldReference.findOrCreate(getReference(), name, type);
|
||||
FieldImpl f = new FieldImpl(this, fr, accessFlags, annotations);
|
||||
L.add(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* set up the methodMap mapping
|
||||
*/
|
||||
protected void computeMethodMap() throws InvalidClassFileException {
|
||||
|
||||
if (methodMap == null) {
|
||||
IMethod[] methods = computeDeclaredMethods();
|
||||
if (methods.length > 5) {
|
||||
methodMap = HashMapFactory.make(methods.length);
|
||||
} else {
|
||||
methodMap = new SmallMap<Selector, IMethod>();
|
||||
}
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
IMethod m = methods[i];
|
||||
methodMap.put(m.getReference().getSelector(), m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -60,7 +60,7 @@ public interface IClass extends IClassHierarchyDweller {
|
|||
* @return the integer that encodes the class's modifiers,
|
||||
* as defined by the JVM specification
|
||||
*/
|
||||
int getModifiers();
|
||||
int getModifiers() throws UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* @return the superclass, or null if java.lang.Object
|
||||
|
|
|
@ -134,7 +134,7 @@ public interface IMethod extends IMember, ContextItem {
|
|||
* @return an array of the exception types declared by the throws clause for this method, or null if there are none
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
TypeReference[] getDeclaredExceptions() throws InvalidClassFileException;
|
||||
TypeReference[] getDeclaredExceptions() throws InvalidClassFileException, UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* @return the source line number corresponding to a particular bytecode index, or -1 if the information is not
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
public abstract class JVMClass<T extends IClassLoader> extends BytecodeClass<T> {
|
||||
|
||||
protected JVMClass(T loader, IClassHierarchy cha) {
|
||||
super(loader, cha);
|
||||
}
|
||||
|
||||
/**
|
||||
* JVM-level modifiers; cached here for efficiency
|
||||
*/
|
||||
protected int modifiers;
|
||||
|
||||
public int getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
boolean result = ((modifiers & Constants.ACC_PUBLIC) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
boolean result = ((modifiers & Constants.ACC_INTERFACE) != 0);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
boolean result = ((modifiers & Constants.ACC_ABSTRACT) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassInitializer()
|
||||
*/
|
||||
public IMethod getClassInitializer() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return methodMap.get(MethodReference.clinitSelector);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -11,18 +11,11 @@
|
|||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyWarning;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||
|
@ -33,29 +26,21 @@ import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader;
|
|||
import com.ibm.wala.shrikeCT.SignatureReader;
|
||||
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
|
||||
import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader.UnimplementedException;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.types.generics.ClassSignature;
|
||||
import com.ibm.wala.util.collections.BimodalMap;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.SmallMap;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.shrike.ShrikeClassReaderHandle;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.Warnings;
|
||||
|
||||
/**
|
||||
* A class read from Shrike
|
||||
*/
|
||||
public final class ShrikeClass implements IClass {
|
||||
public final class ShrikeClass extends JVMClass<IClassLoader> {
|
||||
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
|
@ -63,89 +48,16 @@ public final class ShrikeClass implements IClass {
|
|||
* The Shrike object that knows how to read the class file
|
||||
*/
|
||||
private final ShrikeClassReaderHandle reader;
|
||||
|
||||
/**
|
||||
* The object that loaded this class.
|
||||
*/
|
||||
private final IClassLoader loader;
|
||||
|
||||
/**
|
||||
* Governing class hierarchy for this class
|
||||
*/
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod
|
||||
*
|
||||
* TODO: get rid of this for classes (though keep it for interfaces) instead ... use a VMT.
|
||||
*/
|
||||
private Map<Selector, IMethod> methodMap;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod used to cache method lookups from superclasses
|
||||
*/
|
||||
private Map<Selector, IMethod> inheritCache;
|
||||
|
||||
/**
|
||||
* Canonical type representation
|
||||
*/
|
||||
private TypeReference typeReference;
|
||||
|
||||
/**
|
||||
* superclass
|
||||
*/
|
||||
private IClass superClass;
|
||||
|
||||
/**
|
||||
* Compute the superclass lazily.
|
||||
*/
|
||||
private boolean superclassComputed = false;
|
||||
|
||||
/**
|
||||
* An Atom which holds the name of the super class. We cache this for efficiency reasons.
|
||||
*/
|
||||
private ImmutableByteArray superName;
|
||||
|
||||
/**
|
||||
* The names of interfaces for this class. We cache this for efficiency reasons.
|
||||
*/
|
||||
private ImmutableByteArray[] interfaceNames;
|
||||
|
||||
/**
|
||||
* The IClasses that represent all interfaces this class implements (if it's a class) or extends (it it's an interface)
|
||||
*/
|
||||
private Collection<IClass> allInterfaces = null;
|
||||
|
||||
/**
|
||||
* The instance fields declared in this class.
|
||||
*/
|
||||
private IField[] instanceFields;
|
||||
|
||||
/**
|
||||
* The static fields declared in this class.
|
||||
*/
|
||||
private IField[] staticFields;
|
||||
|
||||
/**
|
||||
* JVM-level modifiers; cached here for efficiency
|
||||
*/
|
||||
private int modifiers;
|
||||
|
||||
/**
|
||||
* hash code; cached here for efficiency
|
||||
*/
|
||||
private final int hashCode;
|
||||
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if reader is null
|
||||
*/
|
||||
public ShrikeClass(ShrikeClassReaderHandle reader, IClassLoader loader, IClassHierarchy cha) throws InvalidClassFileException {
|
||||
super(loader, cha);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("reader is null");
|
||||
}
|
||||
this.reader = reader;
|
||||
this.loader = loader;
|
||||
this.cha = cha;
|
||||
computeTypeReference();
|
||||
this.hashCode = 2161 * getReference().hashCode();
|
||||
// as long as the reader is around, pull more data out
|
||||
|
@ -197,45 +109,6 @@ public final class ShrikeClass implements IClass {
|
|||
}
|
||||
}
|
||||
|
||||
private void populateFieldArrayFromList(List<FieldImpl> L, IField[] A) {
|
||||
Iterator<FieldImpl> it = L.iterator();
|
||||
for (int i = 0; i < A.length; i++) {
|
||||
A[i] = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
private void addFieldToList(List<FieldImpl> L, Atom name, ImmutableByteArray fieldType, int accessFlags,
|
||||
Collection<Annotation> annotations) {
|
||||
TypeName T = null;
|
||||
if (fieldType.get(fieldType.length() - 1) == ';') {
|
||||
T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1);
|
||||
} else {
|
||||
T = TypeName.findOrCreate(fieldType);
|
||||
}
|
||||
TypeReference type = TypeReference.findOrCreate(getClassLoader().getReference(), T);
|
||||
FieldReference fr = FieldReference.findOrCreate(getReference(), name, type);
|
||||
FieldImpl f = new FieldImpl(this, fr, accessFlags, annotations);
|
||||
L.add(f);
|
||||
}
|
||||
|
||||
public IClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
boolean result = ((modifiers & Constants.ACC_INTERFACE) != 0);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
boolean result = ((modifiers & Constants.ACC_ABSTRACT) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
|
@ -243,11 +116,7 @@ public final class ShrikeClass implements IClass {
|
|||
modifiers = reader.get().getAccessFlags();
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is not yet ready to actually load the superclass.
|
||||
* Instead, we pull out the name of the superclass and cache it here, to avoid hitting the reader later.
|
||||
*/
|
||||
|
@ -262,36 +131,6 @@ public final class ShrikeClass implements IClass {
|
|||
}
|
||||
}
|
||||
|
||||
private void computeSuperclass() {
|
||||
superclassComputed = true;
|
||||
|
||||
if (superName == null) {
|
||||
if (!getReference().equals(TypeReference.JavaLangObject)) {
|
||||
superClass = loader.lookupClass(TypeReference.JavaLangObject.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
superClass = loader.lookupClass(TypeName.findOrCreate(superName));
|
||||
if (DEBUG) {
|
||||
Trace.println("got superclass " + superClass + " for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
public IClass getSuperclass() throws ClassHierarchyException {
|
||||
if (!superclassComputed) {
|
||||
computeSuperclass();
|
||||
}
|
||||
if (superClass == null && !getReference().equals(TypeReference.JavaLangObject)) {
|
||||
try {
|
||||
throw new ClassHierarchyException("No superclass " + reader.get().getSuperName() + " found for " + this);
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return superClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is not yet ready to actually load the interfaces.
|
||||
* Instead, we pull out the name of the interfaces and cache it here, to avoid hitting the reader later.
|
||||
|
@ -308,125 +147,13 @@ public final class ShrikeClass implements IClass {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection of IClasses, representing the interfaces this class implements.
|
||||
*/
|
||||
private Collection<IClass> computeAllInterfacesAsCollection() throws ClassHierarchyException {
|
||||
Collection<IClass> c = getDirectInterfaces();
|
||||
Set<IClass> result = HashSetFactory.make();
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
if (klass.isInterface()) {
|
||||
result.add(klass);
|
||||
} else {
|
||||
Warnings.add(ClassHierarchyWarning.create("expected an interface " + klass));
|
||||
}
|
||||
}
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
IClass I = it.next();
|
||||
if (I.isInterface()) {
|
||||
if (I instanceof ShrikeClass) {
|
||||
ShrikeClass sc = (ShrikeClass) I;
|
||||
result.addAll(sc.computeAllInterfacesAsCollection());
|
||||
} else {
|
||||
Warnings.add(ClassHierarchyWarning.create("cannot handle superinterface that is not a ShrikeClass"));
|
||||
}
|
||||
} else {
|
||||
Warnings.add(ClassHierarchyWarning.create("expected an interface " + I));
|
||||
}
|
||||
}
|
||||
|
||||
// now add any interfaces from the super class
|
||||
IClass sup = null;
|
||||
try {
|
||||
sup = getSuperclass();
|
||||
} catch (ClassHierarchyException e1) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
if (sup != null) {
|
||||
result.addAll(sup.getAllImplementedInterfaces());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDirectInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
return array2IClassSet(interfaceNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method array2Set.
|
||||
*
|
||||
* @param interfaces a set of class names
|
||||
* @return Set of all IClasses that can be loaded corresponding to the class names in the interfaces array; raise warnings if
|
||||
* classes can not be loaded
|
||||
*/
|
||||
private Collection<IClass> array2IClassSet(ImmutableByteArray[] interfaces) {
|
||||
ArrayList<IClass> result = new ArrayList<IClass>(interfaces.length);
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
ImmutableByteArray name = interfaces[i];
|
||||
IClass klass = null;
|
||||
klass = loader.lookupClass(TypeName.findOrCreate(name));
|
||||
if (klass == null) {
|
||||
Warnings.add(ClassNotFoundWarning.create(name));
|
||||
} else {
|
||||
result.add(klass);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A warning for when we get a class not found exception
|
||||
*/
|
||||
private static class ClassNotFoundWarning extends Warning {
|
||||
|
||||
final ImmutableByteArray className;
|
||||
|
||||
ClassNotFoundWarning(ImmutableByteArray className) {
|
||||
super(Warning.SEVERE);
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + className;
|
||||
}
|
||||
|
||||
public static ClassNotFoundWarning create(ImmutableByteArray className) {
|
||||
return new ClassNotFoundWarning(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set up the methodMap mapping
|
||||
*/
|
||||
private void computeMethodMap() throws InvalidClassFileException {
|
||||
|
||||
if (methodMap == null) {
|
||||
ShrikeCTMethod[] methods = computeDeclaredMethods();
|
||||
if (methods.length > 5) {
|
||||
methodMap = HashMapFactory.make(methods.length);
|
||||
} else {
|
||||
methodMap = new SmallMap<Selector, IMethod>();
|
||||
}
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
ShrikeCTMethod m = methods[i];
|
||||
methodMap.put(m.getReference().getSelector(), m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the declared methods array
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
private ShrikeCTMethod[] computeDeclaredMethods() throws InvalidClassFileException {
|
||||
@Override
|
||||
protected ShrikeCTMethod[] computeDeclaredMethods() throws InvalidClassFileException {
|
||||
int methodCount = reader.get().getMethodCount();
|
||||
ShrikeCTMethod[] result = new ShrikeCTMethod[methodCount];
|
||||
for (int i = 0; i < methodCount; i++) {
|
||||
|
@ -439,128 +166,7 @@ public final class ShrikeClass implements IClass {
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector)
|
||||
*/
|
||||
public IMethod getMethod(Selector selector) {
|
||||
if (DEBUG) {
|
||||
Trace.println("getMethod " + selector + " in " + this);
|
||||
}
|
||||
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e1) {
|
||||
e1.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// my methods + cached parent stuff
|
||||
IMethod result = methodMap.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (inheritCache != null) {
|
||||
result = inheritCache.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// check parent, caching if found
|
||||
try {
|
||||
if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) {
|
||||
IClass superclass = getSuperclass();
|
||||
if (superclass != null) {
|
||||
IMethod inherit = superclass.getMethod(selector);
|
||||
if (inherit != null) {
|
||||
if (inheritCache == null) {
|
||||
inheritCache = new BimodalMap<Selector, IMethod>(5);
|
||||
}
|
||||
inheritCache.put(selector, inherit);
|
||||
return inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
// didn't find it yet. special logic for interfaces
|
||||
try {
|
||||
if (isInterface() || isAbstract()) {
|
||||
final Iterator<IClass> it = getAllImplementedInterfaces().iterator();
|
||||
// try each superinterface
|
||||
while (it.hasNext()) {
|
||||
IClass k = it.next();
|
||||
result = k.getMethod(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE("Bad method lookup in " + this);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
private final HashMap<Atom, IField> fieldMap = HashMapFactory.make(5);
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getField(com.ibm.wala.util.Atom)
|
||||
*/
|
||||
public IField getField(Atom name) {
|
||||
if (fieldMap.containsKey(name)) {
|
||||
return fieldMap.get(name);
|
||||
} else {
|
||||
IField f = findDeclaredField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
} else if (superClass != null) {
|
||||
f = superClass.getField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// try superinterfaces
|
||||
try {
|
||||
for (IClass i : getAllImplementedInterfaces()) {
|
||||
f = i.getField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IField findDeclaredField(Atom name) {
|
||||
for (int i = 0; i < instanceFields.length; i++) {
|
||||
if (instanceFields[i].getName() == name) {
|
||||
return instanceFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < staticFields.length; i++) {
|
||||
if (staticFields[i].getName() == name) {
|
||||
return staticFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* initialize the TypeReference field for this instance
|
||||
*
|
||||
|
@ -573,38 +179,7 @@ public final class ShrikeClass implements IClass {
|
|||
typeReference = TypeReference.findOrCreate(getClassLoader().getReference(), TypeName.findOrCreate(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getReference()
|
||||
*/
|
||||
public TypeReference getReference() {
|
||||
return typeReference;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getSourceFileName()
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
return loader.getSourceFileName(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllImplementedInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException {
|
||||
if (allInterfaces != null) {
|
||||
return allInterfaces;
|
||||
} else {
|
||||
Collection<IClass> C = computeAllInterfacesAsCollection();
|
||||
allInterfaces = Collections.unmodifiableCollection(C);
|
||||
return allInterfaces;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
|
@ -619,11 +194,6 @@ public final class ShrikeClass implements IClass {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public ClassReader getReader() {
|
||||
try {
|
||||
return reader.get();
|
||||
|
@ -633,76 +203,7 @@ public final class ShrikeClass implements IClass {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassInitializer()
|
||||
*/
|
||||
public IMethod getClassInitializer() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return methodMap.get(MethodReference.clinitSelector);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
||||
*/
|
||||
public Collection<IMethod> getDeclaredMethods() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableCollection(methodMap.values());
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isArrayClass()
|
||||
*/
|
||||
public boolean isArrayClass() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public IClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(instanceFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(staticFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getName()
|
||||
*/
|
||||
public TypeName getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#isReferenceType()
|
||||
*/
|
||||
public boolean isReferenceType() {
|
||||
return getReference().isReferenceType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear all optional cached data associated with this class
|
||||
*/
|
||||
|
@ -724,68 +225,7 @@ public final class ShrikeClass implements IClass {
|
|||
reader.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllInstanceFields()
|
||||
*/
|
||||
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredInstanceFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredInstanceFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllStaticFields()
|
||||
*/
|
||||
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredStaticFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredStaticFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||
*/
|
||||
public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
|
||||
Collection<IMethod> result = new LinkedList<IMethod>();
|
||||
Iterator<IMethod> declaredMethods = getDeclaredMethods().iterator();
|
||||
while (declaredMethods.hasNext()) {
|
||||
result.add(declaredMethods.next());
|
||||
}
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
|
||||
while (superDeclaredMethods.hasNext()) {
|
||||
result.add(superDeclaredMethods.next());
|
||||
}
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllFields()
|
||||
*/
|
||||
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>();
|
||||
result.addAll(getAllInstanceFields());
|
||||
result.addAll(getAllStaticFields());
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
boolean result = ((modifiers & Constants.ACC_PUBLIC) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<Annotation> getRuntimeInvisibleAnnotations() throws InvalidClassFileException, UnimplementedException {
|
||||
public Collection<Annotation> getRuntimeInvisibleAnnotations() throws InvalidClassFileException, UnimplementedException {
|
||||
RuntimeInvisibleAnnotationsReader r = getRuntimeInvisibleAnnotationsReader();
|
||||
if (r != null) {
|
||||
int[] offsets = r.getAnnotationOffsets();
|
||||
|
|
Loading…
Reference in New Issue