package org.aspectj.weaver;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
public class JoinPointSignatureIterator implements Iterator<JoinPointSignature> {
ResolvedType firstDefiningType;
private Member signaturesOfMember;
private ResolvedMember firstDefiningMember;
private World world;
private List<JoinPointSignature> discoveredSignatures = new ArrayList<JoinPointSignature>();
private List<JoinPointSignature> additionalSignatures = Collections.emptyList();
private Iterator<JoinPointSignature> discoveredSignaturesIterator = null;
private Iterator<ResolvedType> superTypeIterator = null;
private boolean isProxy = false;
private Set<ResolvedType> visitedSuperTypes = new HashSet<ResolvedType>();
private List<SearchPair> yetToBeProcessedSuperMembers = null;
private boolean iteratingOverDiscoveredSignatures = true;
private boolean couldBeFurtherAsYetUndiscoveredSignatures = true;
private final static UnresolvedType jlrProxy = UnresolvedType.forSignature("Ljava/lang/reflect/Proxy;");
public JoinPointSignatureIterator(Member joinPointSignature, World world) {
this.signaturesOfMember = joinPointSignature;
this.world = world;
addSignaturesUpToFirstDefiningMember();
if (!shouldWalkUpHierarchy()) {
couldBeFurtherAsYetUndiscoveredSignatures = false;
}
}
public void reset() {
discoveredSignaturesIterator = discoveredSignatures.iterator();
additionalSignatures.clear();
iteratingOverDiscoveredSignatures = true;
}
public boolean hasNext() {
if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
return true;
} else if (couldBeFurtherAsYetUndiscoveredSignatures) {
if (additionalSignatures.size() > 0) {
return true;
} else {
return findSignaturesFromSupertypes();
}
} else {
return false;
}
}
public JoinPointSignature next() {
if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
return discoveredSignaturesIterator.next();
} else {
if (additionalSignatures.size() > 0) {
return additionalSignatures.remove(0);
}
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException("can't remove from JoinPointSignatureIterator");
}
private void addSignaturesUpToFirstDefiningMember() {
ResolvedType originalDeclaringType = signaturesOfMember.getDeclaringType().resolve(world);
ResolvedType superType = originalDeclaringType.getSuperclass();
if (superType != null && superType.equals(jlrProxy)) {
isProxy = true;
}
if (world.isJoinpointArrayConstructionEnabled() && originalDeclaringType.isArray()) {
Member m = signaturesOfMember;
ResolvedMember rm = new ResolvedMemberImpl(m.getKind(), m.getDeclaringType(), m.getModifiers(), m.getReturnType(), m
.getName(), m.getParameterTypes());
discoveredSignatures.add(new JoinPointSignature(rm, originalDeclaringType));
couldBeFurtherAsYetUndiscoveredSignatures = false;
return;
}
firstDefiningMember = (signaturesOfMember instanceof ResolvedMember ?
(ResolvedMember) signaturesOfMember: signaturesOfMember.resolve(world));
if (firstDefiningMember == null) {
couldBeFurtherAsYetUndiscoveredSignatures = false;
return;
}
firstDefiningType = firstDefiningMember.getDeclaringType().resolve(world);
if (firstDefiningType != originalDeclaringType) {
if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) {
return;
}
}
if (originalDeclaringType == firstDefiningType) {
discoveredSignatures.add(new JoinPointSignature(firstDefiningMember, originalDeclaringType));
} else {
List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
for (ResolvedType declaringType : declaringTypes) {
discoveredSignatures.add(new JoinPointSignature(firstDefiningMember, declaringType));
}
}
}
private void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List<ResolvedType> types) {
types.add(subType);
if (subType == superType) {
return;
} else {
for (Iterator<ResolvedType> iter = subType.getDirectSupertypes(); iter.hasNext();) {
ResolvedType parent = iter.next();
if (superType.isAssignableFrom(parent, true)) {
accumulateTypesInBetween(parent, superType, types);
}
}
}
}
private boolean shouldWalkUpHierarchy() {
if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) {
return false;
}
if (signaturesOfMember.getKind() == Member.FIELD) {
return false;
}
if (Modifier.isStatic(signaturesOfMember.getModifiers())) {
return false;
}
return true;
}
private boolean findSignaturesFromSupertypes() {
iteratingOverDiscoveredSignatures = false;
if (superTypeIterator == null) {
superTypeIterator = firstDefiningType.getDirectSupertypes();
}
if (superTypeIterator.hasNext()) {
ResolvedType superType = superTypeIterator.next();
if (isProxy && (superType.isGenericType() || superType.isParameterizedType())) {
superType = superType.getRawType();
}
if (visitedSuperTypes.contains(superType)) {
return findSignaturesFromSupertypes();
} else {
visitedSuperTypes.add(superType);
if (superType.isMissing()) {
warnOnMissingType(superType);
return findSignaturesFromSupertypes();
}
ResolvedMemberImpl foundMember = (ResolvedMemberImpl) superType.lookupResolvedMember(firstDefiningMember, true,
isProxy);
if (foundMember != null && isVisibleTo(firstDefiningMember, foundMember)) {
List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(world);
accumulateTypesInBetween(superType, resolvedDeclaringType, declaringTypes);
for (ResolvedType declaringType : declaringTypes) {
JoinPointSignature member = null;
if (isProxy) {
if (declaringType.isGenericType() || declaringType.isParameterizedType()) {
declaringType = declaringType.getRawType();
}
}
member = new JoinPointSignature(foundMember, declaringType);
discoveredSignatures.add(member);
if (additionalSignatures == Collections.EMPTY_LIST) {
additionalSignatures = new ArrayList<JoinPointSignature>();
}
additionalSignatures.add(member);
}
if (!isProxy && superType.isParameterizedType() && (foundMember.backingGenericMember != null)) {
JoinPointSignature member = new JoinPointSignature(foundMember.backingGenericMember,
foundMember.declaringType.resolve(world));
discoveredSignatures.add(member);
if (additionalSignatures == Collections.EMPTY_LIST) {
additionalSignatures = new ArrayList<JoinPointSignature>();
}
additionalSignatures.add(member);
}
if (yetToBeProcessedSuperMembers == null) {
yetToBeProcessedSuperMembers = new ArrayList<SearchPair>();
}
yetToBeProcessedSuperMembers.add(new SearchPair(foundMember, superType));
return true;
} else {
return findSignaturesFromSupertypes();
}
}
}
if (yetToBeProcessedSuperMembers != null && !yetToBeProcessedSuperMembers.isEmpty()) {
SearchPair nextUp = yetToBeProcessedSuperMembers.remove(0);
firstDefiningType = nextUp.type;
firstDefiningMember = nextUp.member;
superTypeIterator = null;
return findSignaturesFromSupertypes();
}
couldBeFurtherAsYetUndiscoveredSignatures = false;
return false;
}
private boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) {
return true;
}
if (Modifier.isPrivate(parentMember.getModifiers())) {
return false;
} else {
return true;
}
}
private void warnOnMissingType(ResolvedType missing) {
if (missing instanceof MissingResolvedTypeWithKnownSignature) {
MissingResolvedTypeWithKnownSignature mrt = (MissingResolvedTypeWithKnownSignature) missing;
mrt.raiseWarningOnJoinPointSignature(signaturesOfMember.toString());
}
}
private static class SearchPair {
public ResolvedMember member;
public ResolvedType type;
public SearchPair(ResolvedMember member, ResolvedType type) {
this.member = member;
this.type = type;
}
}
}