/* *******************************************************************
 * Copyright (c) 2005 Contributors.
 * 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://eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *   Adrian Colyer			Initial implementation
 * ******************************************************************/
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;

Iterates over the signatures of a join point, calculating new signatures lazily to minimize processing and to avoid unneccessary "can't find type" errors. Iterator can be cached and reused by calling the "reset" method between iterations.
/** * Iterates over the signatures of a join point, calculating new signatures lazily to minimize processing and to avoid unneccessary * "can't find type" errors. Iterator can be cached and reused by calling the "reset" method between iterations. */
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"); }
Walk up the hierarchy creating one member for each type up to and including the first defining type.
/** * Walk up the hierarchy creating one member for each type up to and including the first defining type. */
private void addSignaturesUpToFirstDefiningMember() { ResolvedType originalDeclaringType = signaturesOfMember.getDeclaringType().resolve(world); ResolvedType superType = originalDeclaringType.getSuperclass(); if (superType != null && superType.equals(jlrProxy)) { // Proxy types are generated without any regard to generics (pr268419) and so the member walking // should also ignore them isProxy = true; } // is it the array constructor join point? 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; } // declaringType can be unresolved if we matched a synthetic member generated by Aj... // should be fixed elsewhere but add this resolve call on the end for now so that we can // focus on one problem at a time... firstDefiningType = firstDefiningMember.getDeclaringType().resolve(world); if (firstDefiningType != originalDeclaringType) { if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) { return; } } if (originalDeclaringType == firstDefiningType) { // a common case 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)); } } }
Build a list containing every type between subtype and supertype, inclusively.
/** * Build a list containing every type between subtype and supertype, inclusively. */
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 { // we haven't looked in this type yet visitedSuperTypes.add(superType); if (superType.isMissing()) { // issue a warning, stop looking for join point signatures in this line warnOnMissingType(superType); return findSignaturesFromSupertypes(); } ResolvedMemberImpl foundMember = (ResolvedMemberImpl) superType.lookupResolvedMember(firstDefiningMember, true, isProxy); if (foundMember != null && isVisibleTo(firstDefiningMember, foundMember)) { List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>(); // declaring type can be unresolved if the member can from an ITD... 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); // for next time we are reset if (additionalSignatures == Collections.EMPTY_LIST) { additionalSignatures = new ArrayList<JoinPointSignature>(); } additionalSignatures.add(member); // for this time } // if this was a parameterized type, look in the generic type that backs it too if (!isProxy && superType.isParameterizedType() && (foundMember.backingGenericMember != null)) { JoinPointSignature member = new JoinPointSignature(foundMember.backingGenericMember, foundMember.declaringType.resolve(world)); discoveredSignatures.add(member); // for next time we are reset if (additionalSignatures == Collections.EMPTY_LIST) { additionalSignatures = new ArrayList<JoinPointSignature>(); } additionalSignatures.add(member); // for this time } 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; }
Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if parent is private it is false.
Params:
  • childMember –
  • parentMember –
Returns:
/** * Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if * parent is private it is false. * * @param childMember * @param parentMember * @return */
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) { // which it should be... 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; } } }