Logo Search packages:      
Sourcecode: aspectj version File versions  Download package

JoinPointSignatureIterator.java

/* *******************************************************************
 * 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.
 */
00027 public class JoinPointSignatureIterator implements Iterator {

      private Member signaturesOfMember;
      private ResolvedMember firstDefiningMember;
      ResolvedType firstDefiningType;
      private World world;
      private List /* JoinPointSignature */discoveredSignatures = new ArrayList();
      private List additionalSignatures = Collections.EMPTY_LIST;
      private Iterator discoveredSignaturesIterator = null;
      private Iterator superTypeIterator = null;
      private boolean isProxy = false;
      private Set visitedSuperTypes = new HashSet();
      private List /* SearchPair */yetToBeProcessedSuperMembers = null;// new ArrayList();

      private boolean iteratingOverDiscoveredSignatures = true;
      private boolean couldBeFurtherAsYetUndiscoveredSignatures = true;
      private final static UnresolvedType jlrProxy = UnresolvedType.forSignature("Ljava/lang/reflect/Proxy;");

      /**
       * 
       */
      public JoinPointSignatureIterator(Member joinPointSignature, World inAWorld) {
            this.signaturesOfMember = joinPointSignature;
            this.world = inAWorld;
            addSignaturesUpToFirstDefiningMember();
            if (!shouldWalkUpHierarchy())
                  couldBeFurtherAsYetUndiscoveredSignatures = false;
      }

      public void reset() {
            discoveredSignaturesIterator = discoveredSignatures.iterator();
            additionalSignatures.clear();
            iteratingOverDiscoveredSignatures = true;
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.util.Iterator#hasNext()
       */
      public boolean hasNext() {
            if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
                  return true;
            } else if (couldBeFurtherAsYetUndiscoveredSignatures) {
                  if (additionalSignatures.size() > 0)
                        return true;
                  else
                        return findSignaturesFromSupertypes();
            } else {
                  return false;
            }
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.util.Iterator#next()
       */
      public Object next() {
            if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
                  return discoveredSignaturesIterator.next();
            } else {
                  if (additionalSignatures.size() > 0) {
                        return additionalSignatures.remove(0);
                  }
            }
            throw new NoSuchElementException();
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.util.Iterator#remove()
       */
      public void remove() {
            throw new UnsupportedOperationException("can't remove from JoinPointSignatureIterator");
      }

      private void addSignaturesUpToFirstDefiningMember() {
            // Walk up hierarchy creating one member for each type up to and including the
            // first defining type
            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;
            }

            if (world.isJoinpointArrayConstructionEnabled() && originalDeclaringType.isArray()) { // Aha, this must be the array
                  // constructor call join point - a
                  // 'special'...
                  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.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;
                  }
            }

            List declaringTypes = new ArrayList();
            accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
            for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
                  ResolvedType declaringType = (ResolvedType) iter.next();
                  ResolvedMember member = ((ResolvedMemberImpl) firstDefiningMember).withSubstituteDeclaringType(declaringType);
                  discoveredSignatures.add(member);
            }
      }

      /**
       * Build a list containing every type between subtype and supertype, inclusively.
       */
00156       private void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) {
            types.add(subType);
            if (subType == superType) {
                  return;
            } else {
                  for (Iterator iter = subType.getDirectSupertypes(); iter.hasNext();) {
                        ResolvedType parent = (ResolvedType) 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 (signaturesOfMember.isStatic())
                  return false;
            return true;
      }

      private boolean findSignaturesFromSupertypes() {
            iteratingOverDiscoveredSignatures = false;
            if (superTypeIterator == null) {
                  superTypeIterator = firstDefiningType.getDirectSupertypes();
            }
            if (superTypeIterator.hasNext()) {
                  ResolvedType superType = (ResolvedType) superTypeIterator.next();
                  if (isProxy && (superType.isGenericType() || superType.isParameterizedType())) {
                        superType = (ResolvedType) 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 declaringTypes = new ArrayList();
                              // declaring type can be unresolved if the member can from an ITD...
                              ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(world);
                              accumulateTypesInBetween(superType, resolvedDeclaringType, declaringTypes);
                              for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
                                    ResolvedType declaringType = (ResolvedType) iter.next();
                                    ResolvedMember member = null;
                                    if (isProxy) {
                                          if (declaringType.isGenericType() || declaringType.isParameterizedType()) {
                                                declaringType = (ResolvedType) declaringType.getRawType();
                                          }
                                          member = foundMember.withSubstituteDeclaringType(declaringType);
                                    } else {
                                          member = foundMember.withSubstituteDeclaringType(declaringType);
                                    }
                                    discoveredSignatures.add(member); // for next time we are reset
                                    if (additionalSignatures == Collections.EMPTY_LIST)
                                          additionalSignatures = new ArrayList();
                                    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)) {
                                    ResolvedMember 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();
                                    additionalSignatures.add(member); // for this time
                              }
                              if (yetToBeProcessedSuperMembers == null) {
                                    yetToBeProcessedSuperMembers = new ArrayList();
                              }
                              yetToBeProcessedSuperMembers.add(new SearchPair(foundMember, superType));
                              return true;
                        } else {
                              return findSignaturesFromSupertypes();
                        }
                  }
            }
            if (yetToBeProcessedSuperMembers != null && !yetToBeProcessedSuperMembers.isEmpty()) {
                  SearchPair nextUp = (SearchPair) 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.
       * 
       * @param childMember
       * @param parentMember
       * @return
       */
00261       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;
            }
      }

}

Generated by  Doxygen 1.6.0   Back to index