Package org.aspectj.weaver.bcel

Source Code of org.aspectj.weaver.bcel.BcelTypeMunger

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* Contributors:
*     PARC     initial implementation
*     Alexandre Vasseur    @AspectJ ITDs
* ******************************************************************/


package org.aspectj.weaver.bcel;

import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.generic.BranchInstruction;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.FieldGen;
import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.bridge.WeaveMessage;
import org.aspectj.bridge.context.CompilationAndWeavingContext;
import org.aspectj.bridge.context.ContextToken;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.AnnotationOnTypeMunger;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.AsmRelationshipProvider;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MethodDelegateTypeMunger;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewConstructorTypeMunger;
import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.NewParentTypeMunger;
import org.aspectj.weaver.PerObjectInterfaceTypeMunger;
import org.aspectj.weaver.PrivilegedAccessMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.TypeVariableReference;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.Pointcut;

//XXX addLazyMethodGen is probably bad everywhere
public class BcelTypeMunger extends ConcreteTypeMunger {

  public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
    super(munger, aspectType);
  }

  public String toString() {
    return "(BcelTypeMunger " + getMunger() + ")";
  }

  public boolean munge(BcelClassWeaver weaver) {
    ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MUNGING_WITH, this);
    boolean changed = false;
    boolean worthReporting = true;
   
    if (munger.getKind() == ResolvedTypeMunger.Field) {
      changed = mungeNewField(weaver, (NewFieldTypeMunger)munger);
    } else if (munger.getKind() == ResolvedTypeMunger.Method) {
      changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
        } else if (munger.getKind() == ResolvedTypeMunger.MethodDelegate) {
            changed = mungeMethodDelegate(weaver, (MethodDelegateTypeMunger)munger);
        } else if (munger.getKind() == ResolvedTypeMunger.FieldHost) {
            changed = mungeFieldHost(weaver, (MethodDelegateTypeMunger.FieldHostTypeMunger)munger);
    } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
      changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
      worthReporting = false;
    } else if (munger.getKind() == ResolvedTypeMunger.PerTypeWithinInterface) {
      // PTWIMPL Transform the target type (add the aspect instance field)
      changed = mungePerTypeWithinTransformer(weaver);
      worthReporting = false;
    } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
      changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
      worthReporting = false;
    } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
      changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
    } else if (munger.getKind() == ResolvedTypeMunger.Parent) {
      changed = mungeNewParent(weaver, (NewParentTypeMunger)munger);
    } else if (munger.getKind() == ResolvedTypeMunger.AnnotationOnType) {
      changed = mungeNewAnnotationOnType(weaver,(AnnotationOnTypeMunger)munger);
      worthReporting=false;
        } else {
      throw new RuntimeException("unimplemented");
    }
   
    if (changed && munger.changesPublicSignature()) {
      WeaverStateInfo info =
        weaver.getLazyClassGen().getOrCreateWeaverStateInfo(BcelClassWeaver.getReweavableMode());
      info.addConcreteMunger(this);
    }

    if (changed && worthReporting) {
      if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
          AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
      } else {
          AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType())
      }
    }
   
    // TAG: WeavingMessage
    if (changed && worthReporting  && munger!=null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
      String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName();
      if (tName.indexOf("no debug info available")!=-1) tName = "no debug info available";
      else tName = getShortname(weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getPath());
      String fName = getShortname(getAspectType().getSourceLocation().getSourceFile().getPath());
          if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
            // This message could come out of AjLookupEnvironment.addParent if doing parents
            // munging at compile time only...
            NewParentTypeMunger parentTM = (NewParentTypeMunger)munger;
            if (parentTM.getNewParent().isInterface()) {
          weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
          new String[]{weaver.getLazyClassGen().getType().getName(),
          tName,parentTM.getNewParent().getName(),fName},
          weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
            } else {
                    weaver.getWorld().getMessageHandler().handleMessage(
                    WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,
                        new String[]{weaver.getLazyClassGen().getType().getName(),
                            tName,parentTM.getNewParent().getName(),fName
                                }));
//                  TAG: WeavingMessage    DECLARE PARENTS: EXTENDS
//                  reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
                   
            }
            } else if (munger.getKind().equals(ResolvedTypeMunger.FieldHost)) {
                ;//hidden
            } else {
            ResolvedMember declaredSig = munger.getDeclaredSignature();
            if (declaredSig==null) declaredSig= munger.getSignature();
            weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD,
            new String[]{weaver.getLazyClassGen().getType().getName(),
                       tName,munger.getKind().toString().toLowerCase(),
                       getAspectType().getName(),
                   fName+":'"+declaredSig+"'"},
               weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
         
    }
   
    CompilationAndWeavingContext.leavingPhase(tok);
    return changed;
  }

  private String getShortname(String path)  {
    int takefrom = path.lastIndexOf('/');
    if (takefrom == -1) {
      takefrom = path.lastIndexOf('\\');
    }
    return path.substring(takefrom+1);
  }
 
  private boolean mungeNewAnnotationOnType(BcelClassWeaver weaver,AnnotationOnTypeMunger munger) {
    // FIXME asc this has already been done up front, need to do it here too?
    weaver.getLazyClassGen().addAnnotation(munger.getNewAnnotation().getBcelAnnotation());
    return true;
  }

  /**
     * For a long time, AspectJ did not allow binary weaving of declare parents.  This restriction is now lifted
     * but could do with more testing!
   */
  private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger munger) {
    LazyClassGen  newParentTarget = weaver.getLazyClassGen();
    ResolvedType newParent       = munger.getNewParent();
       
        boolean cont = true; // Set to false when we error, so we don't actually *do* the munge          
        cont = enforceDecpRule1_abstractMethodsImplemented(weaver, munger.getSourceLocation(),newParentTarget, newParent);
        cont = enforceDecpRule2_cantExtendFinalClass(weaver,munger.getSourceLocation(),newParentTarget,newParent) && cont;
               
        List methods = newParent.getMethodsWithoutIterator(false,true);
        for (Iterator iter = methods.iterator(); iter.hasNext();) {
      ResolvedMember    superMethod = (ResolvedMember) iter.next();
          if (!superMethod.getName().equals("<init>")) {
        LazyMethodGen   subMethod = findMatchingMethod(newParentTarget, superMethod);
            if (subMethod!=null && !subMethod.isBridgeMethod()) { // FIXME asc is this safe for all bridge methods?
              cont = enforceDecpRule3_visibilityChanges(weaver, newParent, superMethod, subMethod) && cont;
              cont = enforceDecpRule4_compatibleReturnTypes(weaver, superMethod, subMethod)        && cont;
              cont = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver,munger.getSourceLocation(),superMethod,subMethod) && cont;
            }               
          }
        }
        if (!cont) return false; // A rule was violated and an error message already reported
            
        if (newParent.isClass()) { // Changing the supertype
             if (!attemptToModifySuperCalls(weaver,newParentTarget,newParent)) return false;
             newParentTarget.setSuperClass(newParent);
    } else { // Adding a new interface
      newParentTarget.addInterface(newParent,getSourceLocation());
    }
    return true;
  }


    /**
     * Rule 1: For the declare parents to be allowed, the target type must override and implement
     *         inherited abstract methods (if the type is not declared abstract)
     */
    private boolean enforceDecpRule1_abstractMethodsImplemented(BcelClassWeaver weaver, ISourceLocation mungerLoc,LazyClassGen newParentTarget, ResolvedType newParent) {
        boolean ruleCheckingSucceeded = true;
        if (!(newParentTarget.isAbstract() || newParentTarget.isInterface())) { // Ignore abstract classes or interfaces
            List methods = newParent.getMethodsWithoutIterator(false,true);
            for (Iterator i = methods.iterator(); i.hasNext();) {
                ResolvedMember o = (ResolvedMember)i.next();
                if (o.isAbstract() && !o.getName().startsWith("ajc$interField")) { // Ignore abstract methods of ajc$interField prefixed methods
                    ResolvedMember discoveredImpl = null;
                    List newParentTargetMethods = newParentTarget.getType().getMethodsWithoutIterator(false,true);
                    for (Iterator ii = newParentTargetMethods.iterator(); ii.hasNext() && discoveredImpl==null;) {
                        ResolvedMember gen2 = (ResolvedMember) ii.next();
                        if (gen2.getName().equals(o.getName()) &&
                            gen2.getParameterSignature().equals(o.getParameterSignature()) && !gen2.isAbstract()) {
                            discoveredImpl = gen2; // Found a valid implementation !
                        }
                    }    
                    if (discoveredImpl == null) {
                        // didnt find a valid implementation, lets check the ITDs on this type to see if they satisfy it
                        boolean satisfiedByITD = false;
                        for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext(); ) {
                            ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
                            if (m.getMunger().getKind() == ResolvedTypeMunger.Method) {
                                ResolvedMember sig = m.getSignature();
                                if (!Modifier.isAbstract(sig.getModifiers())) {
                                 
                                  // If the ITD shares a type variable with some target type, we need to tailor it for that
                                  // type
                                  if (m.isTargetTypeParameterized()) {
                                      ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
                                    m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
                                      sig = m.getSignature(); // possible sig change when type parameters filled in
                                  }
                                    if (ResolvedType
                                        .matches(
                                            AjcMemberMaker.interMethod(
                                                sig,m.getAspectType(),sig.getDeclaringType().resolve(weaver.getWorld()).isInterface()),o)) {
                                        satisfiedByITD = true;
                                    }
                                }
                            } else if (m.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) {
                                satisfiedByITD = true;//AV - that should be enough, no need to check more
                            }
                        }
                        if (!satisfiedByITD) {
                          error(weaver,
                                "The type " + newParentTarget.getName() + " must implement the inherited abstract method "+o.getDeclaringType()+"."+o.getName()+o.getParameterSignature(),
                                newParentTarget.getType().getSourceLocation(),new ISourceLocation[]{o.getSourceLocation(),mungerLoc});
                          ruleCheckingSucceeded=false;
                        }
                    }
                }
            }
        }
        return ruleCheckingSucceeded;
    }
   
    /**
     * Rule 2. Can't extend final types
     */
  private boolean enforceDecpRule2_cantExtendFinalClass(BcelClassWeaver weaver, ISourceLocation mungerLoc,
            LazyClassGen newParentTarget, ResolvedType newParent) {
        if (newParent.isFinal()) {
            error(weaver,"Cannot make type "+newParentTarget.getName()+" extend final class "+newParent.getName(),
                  newParentTarget.getType().getSourceLocation(),
                  new ISourceLocation[]{mungerLoc});
            return false;
        }
    return true;
  }


  /**
     * Rule 3. Can't narrow visibility of methods when overriding
   */
  private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, ResolvedMember superMethod, LazyMethodGen subMethod) {
        boolean cont = true;
      if (superMethod.isPublic()) {
        if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) {
          weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
                superMethod.getSourceLocation()));
          cont=false;
        }
      } else if (superMethod.isProtected()) {
        if (subMethod.isDefault() || subMethod.isPrivate()) {
          weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
                superMethod.getSourceLocation()));
          cont=false;
        }
      } else if (superMethod.isDefault()) {
        if (subMethod.isPrivate()) {
          weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
                superMethod.getSourceLocation()));
          cont=false;
        }
      }
    return cont;
  }
   
    /**
     * Rule 4. Can't have incompatible return types
     */
    private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod, LazyMethodGen subMethod) {
        boolean cont = true;
        String superReturnTypeSig = superMethod.getReturnType().getSignature();
          String subReturnTypeSig   = subMethod.getReturnType().getSignature();
          if (!superReturnTypeSig.equals(subReturnTypeSig)) {
            // Allow for covariance - wish I could test this (need Java5...)
            ResolvedType subType   = weaver.getWorld().resolve(subMethod.getReturnType());
            ResolvedType superType = weaver.getWorld().resolve(superMethod.getReturnType());
            if (!superType.isAssignableFrom(subType)) {
                ISourceLocation sloc = subMethod.getSourceLocation();
                weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                        "The return type is incompatible with "+superMethod.getDeclaringType()+"."+superMethod.getName()+superMethod.getParameterSignature(),
                        subMethod.getSourceLocation()));
                 cont=false;
            }
          }
        return cont;
    }
   
    /**
     * Rule5. Method overrides can't change the staticality (word?) - you can't override and make an instance
     *        method static or override and make a static method an instance method.
     */
    private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver,ISourceLocation mungerLoc,ResolvedMember superMethod, LazyMethodGen subMethod ) {
      if (superMethod.isStatic() && !subMethod.isStatic()) {
        error(weaver,"This instance method "+subMethod.getName()+subMethod.getParameterSignature()+
                     " cannot override the static method from "+superMethod.getDeclaringType().getName(),
              subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
        return false;
      } else if (!superMethod.isStatic() && subMethod.isStatic()) {
        error(weaver,"The static method "+subMethod.getName()+subMethod.getParameterSignature()+
                     " cannot hide the instance method from "+superMethod.getDeclaringType().getName(),
                subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
        return false;
      }
      return true;
    }

    public void error(BcelClassWeaver weaver,String text,ISourceLocation primaryLoc,ISourceLocation[] extraLocs) {
        IMessage msg = new Message(text, primaryLoc, true, extraLocs);
        weaver.getWorld().getMessageHandler().handleMessage(msg);
    }
  

  private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, ResolvedMember m) {
        LazyMethodGen found = null;
    // Search the type for methods overriding super methods (methods that come from the new parent)
    // Don't use the return value in the comparison as overriding doesnt
    for (Iterator i = newParentTarget.getMethodGens().iterator(); i.hasNext() && found==null;) {
        LazyMethodGen gen = (LazyMethodGen) i.next();
        if (gen.getName().equals(m.getName()) &&
            gen.getParameterSignature().equals(m.getParameterSignature())) {
            found = gen;
        }
    }       
    return found;
  }

    /**
     * The main part of implementing declare parents extends.  Modify super ctor calls to target the new type.
     */
  public boolean attemptToModifySuperCalls(BcelClassWeaver weaver,LazyClassGen newParentTarget, ResolvedType newParent) {
        String currentParent = newParentTarget.getSuperClassname();
        if (newParent.getGenericType()!=null) newParent = newParent.getGenericType(); // target new super calls at the generic type if its raw or parameterized
        List mgs = newParentTarget.getMethodGens();
       
        // Look for ctors to modify
        for (Iterator iter = mgs.iterator(); iter.hasNext();) {
          LazyMethodGen aMethod = (LazyMethodGen) iter.next();    
       
          if (aMethod.getName().equals("<init>")) {
            InstructionList insList = aMethod.getBody();
            InstructionHandle handle = insList.getStart();
            while (handle!= null) {
              if (handle.getInstruction() instanceof INVOKESPECIAL) {
                ConstantPoolGen cpg = newParentTarget.getConstantPoolGen();
                INVOKESPECIAL invokeSpecial = (INVOKESPECIAL)handle.getInstruction();
                if (invokeSpecial.getClassName(cpg).equals(currentParent) && invokeSpecial.getMethodName(cpg).equals("<init>")) {
                  // System.err.println("Transforming super call '<init>"+sp.getSignature(cpg)+"'");
                    
                  // 1. Check there is a ctor in the new parent with the same signature
                  ResolvedMember newCtor = getConstructorWithSignature(newParent,invokeSpecial.getSignature(cpg));
                       
                  if (newCtor == null) {
                               
                                // 2. Check ITDCs to see if the necessary ctor is provided that way
                                boolean satisfiedByITDC = false;
                                for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext() && !satisfiedByITDC; ) {
                                    ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
                                    if (m.getMunger() instanceof NewConstructorTypeMunger) {
                                        if (m.getSignature().getSignature().equals(invokeSpecial.getSignature(cpg))) {
                                            satisfiedByITDC = true;
                                        }
                                    }
                                }
                               
                                if (!satisfiedByITDC) {
                      String csig = createReadableCtorSig(newParent, cpg, invokeSpecial);
                      weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                        "Unable to modify hierarchy for "+newParentTarget.getClassName()+" - the constructor "+
                    csig+" is missing",this.getSourceLocation()));
                      return false;
                                }
                  }
                    
                  int idx = cpg.addMethodref(newParent.getName(), invokeSpecial.getMethodName(cpg), invokeSpecial.getSignature(cpg));
                  invokeSpecial.setIndex(idx);
                }
              }
              handle = handle.getNext();  
            }
          }
        }
        return true;
    }


  /**
     * Creates a nice signature for the ctor, something like "(int,Integer,String)"
   */
  private String createReadableCtorSig(ResolvedType newParent, ConstantPoolGen cpg, INVOKESPECIAL invokeSpecial) {
        StringBuffer sb = new StringBuffer();
    Type[] ctorArgs = invokeSpecial.getArgumentTypes(cpg);
      sb.append(newParent.getClassName());
      sb.append("(");
      for (int i = 0; i < ctorArgs.length; i++) {
      String argtype = ctorArgs[i].toString();
      if (argtype.lastIndexOf(".")!=-1)
        sb.append(argtype.substring(argtype.lastIndexOf(".")+1));
      else
        sb.append(argtype);
      if (i+1<ctorArgs.length) sb.append(",");
      }
      sb.append(")");
          return sb.toString();
  }

  private ResolvedMember getConstructorWithSignature(ResolvedType tx,String signature) {
        ResolvedMember[] mems = tx.getDeclaredJavaMethods();
        for (int i = 0; i < mems.length; i++) {
          ResolvedMember rm = mems[i];
          if (rm.getName().equals("<init>")) {
            if (rm.getSignature().equals(signature)) return rm;
          }
        }
        return null;
    }
   
   
  private boolean mungePrivilegedAccess(
    BcelClassWeaver weaver,
    PrivilegedAccessMunger munger)
  {
    LazyClassGen gen = weaver.getLazyClassGen();
    ResolvedMember member = munger.getMember();
   
    ResolvedType onType = weaver.getWorld().resolve(member.getDeclaringType(),munger.getSourceLocation());
    if (onType.isRawType()) onType = onType.getGenericType();

    //System.out.println("munging: " + gen + " with " + member);
    if (onType.equals(gen.getType())) {
      if (member.getKind() == Member.FIELD) {
        //System.out.println("matched: " + gen);
        addFieldGetter(gen, member,
          AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
        addFieldSetter(gen, member,
          AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
        return true;
      } else if (member.getKind() == Member.METHOD) {
        addMethodDispatch(gen, member,
          AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
        return true;
      } else if (member.getKind() == Member.CONSTRUCTOR) {
        for (Iterator i = gen.getMethodGens().iterator(); i.hasNext(); ) {
          LazyMethodGen m = (LazyMethodGen)i.next();
          if (m.getMemberView() != null
            && m.getMemberView().getKind() == Member.CONSTRUCTOR) {
            // m.getMemberView().equals(member)) {
            m.forcePublic();
            //return true;
          }
        }
        return true;
        //throw new BCException("no match for " + member + " in " + gen);
      } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
        gen.forcePublic();
        return true;
      } else {
        throw new RuntimeException("unimplemented");
      }
    }
    return false;
  }

  private void addFieldGetter(
    LazyClassGen gen,
    ResolvedMember field,
    ResolvedMember accessMethod)
  {
    LazyMethodGen mg = makeMethodGen(gen, accessMethod);
    InstructionList il = new InstructionList();
    InstructionFactory fact = gen.getFactory();
    if (field.isStatic()) {
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        field.getName(),
        BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
    } else {
      il.append(InstructionConstants.ALOAD_0);
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        field.getName(),
        BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
    }
    il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(field.getType())));
    mg.getBody().insert(il);
       
    gen.addMethodGen(mg,getSignature().getSourceLocation());
  }
 
  private void addFieldSetter(
    LazyClassGen gen,
    ResolvedMember field,
    ResolvedMember accessMethod)
  {
    LazyMethodGen mg = makeMethodGen(gen, accessMethod);
    InstructionList il = new InstructionList();
    InstructionFactory fact = gen.getFactory();
    Type fieldType = BcelWorld.makeBcelType(field.getType());
   
    if (field.isStatic()) {
      il.append(InstructionFactory.createLoad(fieldType, 0));
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        field.getName(),
        fieldType, Constants.PUTSTATIC));
    } else {
      il.append(InstructionConstants.ALOAD_0);
      il.append(InstructionFactory.createLoad(fieldType, 1));
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        field.getName(),
        fieldType, Constants.PUTFIELD));
    }
    il.append(InstructionFactory.createReturn(Type.VOID));
    mg.getBody().insert(il);
       
    gen.addMethodGen(mg,getSignature().getSourceLocation());
  }
 
  private void addMethodDispatch(
    LazyClassGen gen,
    ResolvedMember method,
    ResolvedMember accessMethod)
  {
    LazyMethodGen mg = makeMethodGen(gen, accessMethod);
    InstructionList il = new InstructionList();
    InstructionFactory fact = gen.getFactory();
    //Type fieldType = BcelWorld.makeBcelType(field.getType());
    Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
   
    int pos = 0;
 
    if (!method.isStatic()) {
      il.append(InstructionConstants.ALOAD_0);
      pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      il.append(InstructionFactory.createLoad(paramType, pos));
      pos+=paramType.getSize();
    }
    il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
        method));
    il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(method.getReturnType())));

    mg.getBody().insert(il);
       
    gen.addMethodGen(mg);
  }
 
 
  protected LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
    LazyMethodGen ret = new LazyMethodGen(
      member.getModifiers(),
      BcelWorld.makeBcelType(member.getReturnType()),
      member.getName(),
      BcelWorld.makeBcelTypes(member.getParameterTypes()),
      UnresolvedType.getNames(member.getExceptions()),
      gen);
       
        // 43972 : Static crosscutting makes interfaces unusable for javac
        // ret.makeSynthetic();   
    return ret;
  }


  protected FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
    return new FieldGen(
      member.getModifiers(),
      BcelWorld.makeBcelType(member.getReturnType()),
      member.getName(),
      gen.getConstantPoolGen());
  }


 

  private boolean mungePerObjectInterface(
    BcelClassWeaver weaver,
    PerObjectInterfaceTypeMunger munger)
  {
    //System.err.println("Munging perobject ["+munger+"] onto "+weaver.getLazyClassGen().getClassName());
    LazyClassGen gen = weaver.getLazyClassGen();
   
    if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
      FieldGen fg = makeFieldGen(gen,
        AjcMemberMaker.perObjectField(gen.getType(), aspectType));

        gen.addField(fg.getField(),getSourceLocation());
       
       
        Type fieldType = BcelWorld.makeBcelType(aspectType);
      LazyMethodGen mg = new LazyMethodGen(
        Modifier.PUBLIC,
        fieldType,
          NameMangler.perObjectInterfaceGet(aspectType),
        new Type[0], new String[0],
        gen);
      InstructionList il = new InstructionList();
      InstructionFactory fact = gen.getFactory();
      il.append(InstructionConstants.ALOAD_0);
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        fg.getName(),
        fieldType, Constants.GETFIELD));
      il.append(InstructionFactory.createReturn(fieldType));
      mg.getBody().insert(il);
       
      gen.addMethodGen(mg);
     
      LazyMethodGen mg1 = new LazyMethodGen(
        Modifier.PUBLIC,
        Type.VOID,
        NameMangler.perObjectInterfaceSet(aspectType),
       
        new Type[]{fieldType,}, new String[0],
        gen);
      InstructionList il1 = new InstructionList();
      il1.append(InstructionConstants.ALOAD_0);
      il1.append(InstructionFactory.createLoad(fieldType, 1));
      il1.append(fact.createFieldAccess(
        gen.getClassName(),
        fg.getName(),
        fieldType, Constants.PUTFIELD));
      il1.append(InstructionFactory.createReturn(Type.VOID));
      mg1.getBody().insert(il1);
       
      gen.addMethodGen(mg1);
     
      gen.addInterface(munger.getInterfaceType(),getSourceLocation());

      return true;
    } else {
      return false;
    }
  }
 
  // PTWIMPL Add field to hold aspect instance and an accessor
  private boolean mungePerTypeWithinTransformer(BcelClassWeaver weaver) {
    LazyClassGen gen = weaver.getLazyClassGen();
     
    // if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
     
      // Add (to the target type) the field that will hold the aspect instance
      // e.g ajc$com_blah_SecurityAspect$ptwAspectInstance
      FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perTypeWithinField(gen.getType(), aspectType));
        gen.addField(fg.getField(),getSourceLocation());
         
        // Add an accessor for this new field, the ajc$<aspectname>$localAspectOf() method
        // e.g. "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()"
        Type fieldType = BcelWorld.makeBcelType(aspectType);
      LazyMethodGen mg = new LazyMethodGen(
          Modifier.PUBLIC | Modifier.STATIC,fieldType,
            NameMangler.perTypeWithinLocalAspectOf(aspectType),
          new Type[0], new String[0],gen);
      InstructionList il = new InstructionList();
      //PTWIMPL ?? Should check if it is null and throw NoAspectBoundException
      InstructionFactory fact = gen.getFactory();
      il.append(fact.createFieldAccess(
        gen.getClassName(),
        fg.getName(),
        fieldType, Constants.GETSTATIC));
      il.append(InstructionFactory.createReturn(fieldType));
      mg.getBody().insert(il);   
      gen.addMethodGen(mg);
      return true;
//    } else {
//      return false;
//    }
  }

  // ??? Why do we have this method? I thought by now we would know if it matched or not
  private boolean couldMatch(
    BcelObjectType bcelObjectType,
    Pointcut pointcut) {
    return !bcelObjectType.isInterface();
  }
 
  private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
    World w = weaver.getWorld();
    // Resolving it will sort out the tvars
    ResolvedMember unMangledInterMethod = munger.getSignature().resolve(w);
    // do matching on the unMangled one, but actually add them to the mangled method
    ResolvedMember interMethodBody = munger.getDeclaredInterMethodBody(aspectType,w);
    ResolvedMember interMethodDispatcher = munger.getDeclaredInterMethodDispatcher(aspectType,w);
    ResolvedMember memberHoldingAnyAnnotations = interMethodDispatcher;
    ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation());
    LazyClassGen gen = weaver.getLazyClassGen();
    boolean mungingInterface = gen.isInterface();
   
    if (onType.isRawType()) onType = onType.getGenericType();

    boolean onInterface = onType.isInterface();
   
   
    // Simple checks, can't ITD on annotations or enums
    if (onType.isAnnotation()) {
      signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
      return false;   
    }
   
    if (onType.isEnum()) {
      signalError(WeaverMessages.ITDM_ON_ENUM_NOT_ALLOWED,weaver,onType);
      return false;
    }
   
    if (onInterface && gen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(),true) != null) {
        // this is ok, we could be providing the default implementation of a method
        // that the target has already declared
        return false;
    }
   
    // If we are processing the intended ITD target type (might be an interface)
    if (onType.equals(gen.getType())) {
      ResolvedMember mangledInterMethod =
          AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface);
           
     
      LazyMethodGen newMethod = makeMethodGen(gen, mangledInterMethod);
      if (mungingInterface) {
        // we want the modifiers of the ITD to be used for all *implementors* of the
        // interface, but the method itself we add to the interface must be public abstract
        newMethod.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
      }
     
      // pr98901
        // For copying the annotations across, we have to discover the real member in the aspect
        // which is holding them.
      if (weaver.getWorld().isInJava5Mode()){
        AnnotationX annotationsOnRealMember[] = null;
        ResolvedType toLookOn = aspectType;
        if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
        ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,memberHoldingAnyAnnotations,false);
        if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
            memberHoldingAnyAnnotations+"' on aspect "+aspectType);
        annotationsOnRealMember = realMember.getAnnotations();
       
        if (annotationsOnRealMember!=null) {
          for (int i = 0; i < annotationsOnRealMember.length; i++) {
            AnnotationX annotationX = annotationsOnRealMember[i];
            Annotation a = annotationX.getBcelAnnotation();
            AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
            newMethod.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
          }
        }
        // the below loop fixes the very special (and very stupid)
        // case where an aspect declares an annotation
        // on an ITD it declared on itself.
        List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
        for (Iterator i = allDecams.iterator(); i.hasNext();){
          DeclareAnnotation decaMC = (DeclareAnnotation) i.next()
          if (decaMC.matches(unMangledInterMethod,weaver.getWorld())
              && newMethod.getEnclosingClass().getType() == aspectType) {
            newMethod.addAnnotation(decaMC.getAnnotationX());
          }
        }
      }

      // If it doesn't target an interface and there is a body (i.e. it isnt abstract)
      if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) {
        InstructionList body = newMethod.getBody();
        InstructionFactory fact = gen.getFactory();
        int pos = 0;
 
        if (!unMangledInterMethod.isStatic()) {
          body.append(InstructionFactory.createThis());
          pos++;
        }
        Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
        for (int i = 0, len = paramTypes.length; i < len; i++) {
          Type paramType = paramTypes[i];
          body.append(InstructionFactory.createLoad(paramType, pos));
          pos+=paramType.getSize();
        }
        body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
        body.append(
          InstructionFactory.createReturn(
            BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));
       
        if (weaver.getWorld().isInJava5Mode()) { // Don't need bridge methods if not in 1.5 mode.
          createAnyBridgeMethodsForCovariance(weaver, munger, unMangledInterMethod, onType, gen, paramTypes);
        }
       
      } else {
        //??? this is okay
        //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
      }
     

      // XXX make sure to check that we set exceptions properly on this guy.
      weaver.addLazyMethodGen(newMethod);
      weaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(),getSignature().getSourceLocation());
     
      addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
     
        return true;
       
    } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {
     
      // This means the 'gen' should be the top most implementor
      // - if it is *not* then something went wrong after we worked
      // out that it was the top most implementor (see pr49657)
        if (!gen.getType().isTopmostImplementor(onType)) {
          ResolvedType rtx = gen.getType().getTopmostImplementor(onType);
          if (!rtx.isExposedToWeaver()) {
            ISourceLocation sLoc = munger.getSourceLocation();
              weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
                  WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR,rtx,getAspectType().getName()),
              (sLoc==null?getAspectType().getSourceLocation():sLoc)));
          } else {
            // XXX what does this state mean?
            // We have incorrectly identified what is the top most implementor and its not because
            // a type wasn't exposed to the weaver
          }
        return false;
        } else {
   
        ResolvedMember mangledInterMethod =
          AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);
   
        LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod);
        if (mungingInterface) {
        // we want the modifiers of the ITD to be used for all *implementors* of the
        // interface, but the method itself we add to the interface must be public abstract
        mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
        }
           
        Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
        Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());
     
        InstructionList body = mg.getBody();
        InstructionFactory fact = gen.getFactory();
        int pos = 0;

        if (!mangledInterMethod.isStatic()) {
        body.append(InstructionFactory.createThis());
        pos++;
        }
        for (int i = 0, len = paramTypes.length; i < len; i++) {
        Type paramType = paramTypes[i];
        body.append(InstructionFactory.createLoad(paramType, pos));
        pos+=paramType.getSize();
        }
      
        body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
        Type t= BcelWorld.makeBcelType(interMethodBody.getReturnType());
        if (!t.equals(returnType)) {
          body.append(fact.createCast(t,returnType));
        }
        body.append(InstructionFactory.createReturn(returnType));
        mg.definingType = onType;
     
        weaver.addOrReplaceLazyMethodGen(mg);
     
        addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());

        // Work out if we need a bridge method for the new method added to the topmostimplementor.
        if (munger.getDeclaredSignature()!=null) { // Check if the munger being processed is a parameterized form of some original munger.
        boolean needsbridging = false;
          ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
        if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
        UnresolvedType[] originalParams = toBridgeTo.getParameterTypes();
        UnresolvedType[] newParams = munger.getSignature().getParameterTypes();
        for (int ii = 0;ii<originalParams.length;ii++) {
          if (!originalParams[ii].getErasureSignature().equals(newParams[ii].getErasureSignature())) needsbridging=true;
        }
        if (toBridgeTo!=null && needsbridging) {
          ResolvedMember bridgerMethod = AjcMemberMaker.bridgerToInterMethod(unMangledInterMethod,gen.getType());
          ResolvedMember bridgingSetter = AjcMemberMaker.interMethod(toBridgeTo, aspectType, false);
         
          // FIXME asc ----------------8<---------------- extract method
          LazyMethodGen bridgeMethod = makeMethodGen(gen,bridgingSetter)
          paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
          Type[] bridgingToParms = BcelWorld.makeBcelTypes(unMangledInterMethod.getParameterTypes());
          returnType   = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
          body = bridgeMethod.getBody();
          fact = gen.getFactory();
          pos = 0;

            if (!bridgingSetter.isStatic()) {
            body.append(InstructionFactory.createThis());
            pos++;
            }
            for (int i = 0, len = paramTypes.length; i < len; i++) {
             Type paramType = paramTypes[i];
            body.append(InstructionFactory.createLoad(paramType, pos));
            if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(unMangledInterMethod.getParameterTypes()[i].getErasureSignature()) ) {
//            System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
            body.append(fact.createCast(paramType,bridgingToParms[i]));
            }
            pos+=paramType.getSize();
            }
        
            body.append(Utility.createInvoke(fact, weaver.getWorld(), bridgerMethod));
            body.append(InstructionFactory.createReturn(returnType));
            gen.addMethodGen(bridgeMethod);
//              mg.definingType = onType;
            // FIXME asc (see above) ---------------------8<--------------- extract method
        }
       
        }       
       
       
        return true;
        }
    } else {
      return false;
    }
  }
 
  /**
   * Create any bridge method required because of covariant returns being used.  This method is used in the case
   * where an ITD is applied to some type and it may be in an override relationship with a method from the supertype - but
   * due to covariance there is a mismatch in return values.
   * Example of when required:
     Super defines:   Object m(String s)
       Sub defines:   String m(String s)
       then we need a bridge method in Sub called 'Object m(String s)' that forwards to 'String m(String s)'
   */
  private void createAnyBridgeMethodsForCovariance(BcelClassWeaver weaver, NewMethodTypeMunger munger, ResolvedMember unMangledInterMethod, ResolvedType onType, LazyClassGen gen, Type[] paramTypes) {
    // PERFORMANCE BOTTLENECK? Might need investigating, method analysis between types in a hierarchy just seems expensive...
    // COVARIANCE BRIDGING
    // Algorithm:  Step1. Check in this type - has someone already created the bridge method?
    //             Step2. Look above us - do we 'override' a method and yet differ in return type (i.e. covariance)
    //             Step3. Create a forwarding bridge method
    ResolvedType superclass = onType.getSuperclass();
    boolean quitRightNow = false;
   
    String localMethodName    = unMangledInterMethod.getName();
    String localParameterSig  = unMangledInterMethod.getParameterSignature();
    String localReturnTypeESig = unMangledInterMethod.getReturnType().getErasureSignature();

    // Step1
    boolean alreadyDone = false; // Compiler might have done it
    ResolvedMember[] localMethods = onType.getDeclaredMethods();
    for (int i = 0; i < localMethods.length; i++) {
      ResolvedMember member = localMethods[i];
      if (member.getName().equals(localMethodName)) {
        // Check the params
        if (member.getParameterSignature().equals(localParameterSig)) alreadyDone = true;
      }
    }
   
    // Step2
    if (!alreadyDone) {
      // Use the iterator form of 'getMethods()' so we do as little work as necessary
      for (Iterator iter = onType.getSuperclass().getMethods();iter.hasNext() && !quitRightNow;) {
        ResolvedMember aMethod = (ResolvedMember) iter.next();
        if (aMethod.getName().equals(localMethodName) && aMethod.getParameterSignature().equals(localParameterSig)) {
          // check the return types, if they are different we need a bridging method.
          if (!aMethod.getReturnType().getErasureSignature().equals(localReturnTypeESig) && !Modifier.isPrivate(aMethod.getModifiers())) {
            // Step3
            createBridgeMethod(weaver.getWorld(), munger, unMangledInterMethod, gen, paramTypes, aMethod);
            quitRightNow = true;
          }
        }
      }
    }
  }

  /**
   * Create a bridge method for a particular munger. 
   * @param world
   * @param munger
   * @param unMangledInterMethod the method to bridge 'to' that we have already created in the 'subtype'
   * @param clazz the class in which to put the bridge method
   * @param paramTypes Parameter types for the bridge method, passed in as an optimization since the caller is likely to have already created them.
   * @param theBridgeMethod
   */
  private void createBridgeMethod(BcelWorld world, NewMethodTypeMunger munger,
      ResolvedMember unMangledInterMethod, LazyClassGen clazz, Type[] paramTypes, ResolvedMember theBridgeMethod) {
    InstructionList body;
    InstructionFactory fact;
    int pos = 0;
   
    LazyMethodGen bridgeMethod = makeMethodGen(clazz,theBridgeMethod); // The bridge method in this type will have the same signature as the one in the supertype
    bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040 /*BRIDGE    = 0x00000040*/ );
    UnresolvedType[] newParams = munger.getSignature().getParameterTypes();
    Type returnType   = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
    body = bridgeMethod.getBody();
    fact = clazz.getFactory();

    if (!unMangledInterMethod.isStatic()) {
       body.append(InstructionFactory.createThis());
       pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
//          if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(unMangledInterMethod.getParameterTypes()[i].getErasureSignature())) {
//            System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
//            body.append(fact.createCast(paramType,bridgingToParms[i]));
//          }
      pos+=paramType.getSize();
    }

    body.append(Utility.createInvoke(fact, world,unMangledInterMethod));
    body.append(InstructionFactory.createReturn(returnType));
    clazz.addMethodGen(bridgeMethod);
  }
 
    private boolean mungeMethodDelegate(BcelClassWeaver weaver, MethodDelegateTypeMunger munger) {
        ResolvedMember introduced = munger.getSignature();

        LazyClassGen gen = weaver.getLazyClassGen();

        ResolvedType fromType = weaver.getWorld().resolve(introduced.getDeclaringType(),munger.getSourceLocation());
        if (fromType.isRawType()) fromType = fromType.getGenericType();

        if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
            // don't signal error as it could be a consequence of a wild type pattern
            return false;
        }

        boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
        if (shouldApply) {
            LazyMethodGen mg = new LazyMethodGen(
                    introduced.getModifiers() - Modifier.ABSTRACT,
                    BcelWorld.makeBcelType(introduced.getReturnType()),
                    introduced.getName(),
                    BcelWorld.makeBcelTypes(introduced.getParameterTypes()),
                    BcelWorld.makeBcelTypesAsClassNames(introduced.getExceptions()),
                    gen
            );

            //annotation copy from annotation on ITD interface
            if (weaver.getWorld().isInJava5Mode()){
                AnnotationX annotationsOnRealMember[] = null;
                ResolvedType toLookOn = weaver.getWorld().lookupOrCreateName(introduced.getDeclaringType());
                if (fromType.isRawType()) toLookOn = fromType.getGenericType();
                // lookup the method
                ResolvedMember[] ms = toLookOn.getDeclaredJavaMethods();
                for (int i = 0; i < ms.length; i++) {
                    ResolvedMember m = ms[i];
                    if (introduced.getName().equals(m.getName()) && introduced.getSignature().equals(m.getSignature())) {
                        annotationsOnRealMember = m.getAnnotations();
                    }
                }
                if (annotationsOnRealMember!=null) {
                    for (int i = 0; i < annotationsOnRealMember.length; i++) {
                        AnnotationX annotationX = annotationsOnRealMember[i];
                        Annotation a = annotationX.getBcelAnnotation();
                        AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
                        mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
                    }
                }
            }

            InstructionList body = new InstructionList();
            InstructionFactory fact = gen.getFactory();

            // getfield
            body.append(InstructionConstants.ALOAD_0);
            body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
            BranchInstruction ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
            body.append(ifNonNull);
            InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);
            body.append(fact.createNew(munger.getImplClassName()));
            body.append(InstructionConstants.DUP);
            body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
            body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
            ifNonNull.setTarget(ifNonNullElse);
            body.append(InstructionConstants.ALOAD_0);
            body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));

            //args
            int pos = 0;
        if (!introduced.isStatic()) { // skip 'this' (?? can this really happen)
          //body.append(InstructionFactory.createThis());
          pos++;
        }
            Type[] paramTypes = BcelWorld.makeBcelTypes(introduced.getParameterTypes());
            for (int i = 0, len = paramTypes.length; i < len; i++) {
                Type paramType = paramTypes[i];
                body.append(InstructionFactory.createLoad(paramType, pos));
                pos+=paramType.getSize();
            }
            body.append(Utility.createInvoke(fact, Constants.INVOKEINTERFACE, introduced));
            body.append(
                InstructionFactory.createReturn(
                    BcelWorld.makeBcelType(introduced.getReturnType())
                )
            );

            mg.getBody().append(body);
            // XXX make sure to check that we set exceptions properly on this guy.
            weaver.addLazyMethodGen(mg);
            weaver.getLazyClassGen().warnOnAddedMethod(mg.getMethod(),getSignature().getSourceLocation());
            return true;
        }
        return false;
    }

    private boolean mungeFieldHost(BcelClassWeaver weaver, MethodDelegateTypeMunger.FieldHostTypeMunger munger) {
        LazyClassGen gen = weaver.getLazyClassGen();
        if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
            // don't signal error as it could be a consequence of a wild type pattern
            return false;
        }
        boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
        ResolvedMember host = AjcMemberMaker.itdAtDeclareParentsField(
                weaver.getLazyClassGen().getType(),
                munger.getSignature().getType(),
                aspectType);
        weaver.getLazyClassGen().addField(makeFieldGen(
                weaver.getLazyClassGen(),
                host).getField(), null);
        return true;
    }


    private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) {
    World world = aspectType.getWorld();
    boolean debug = false;
    if (debug) {
      System.err.println("Searching for a member on type: "+aspectType);
      System.err.println("Member we are looking for: "+lookingFor);
    }

    ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods();
    UnresolvedType [] lookingForParams = lookingFor.getParameterTypes();
   
    ResolvedMember realMember = null;
    for (int i = 0; realMember==null && i < aspectMethods.length; i++) {
      ResolvedMember member = aspectMethods[i];
      if (member.getName().equals(lookingFor.getName())){
        UnresolvedType [] memberParams = member.getGenericParameterTypes();
        if (memberParams.length == lookingForParams.length){
          if (debug) System.err.println("Reviewing potential candidates: "+member);
          boolean matchOK = true;
          // If not related to a ctor ITD then the name is enough to confirm we have the
          // right one.  If it is ctor related we need to check the params all match, although
          // only the erasure.
          if (isCtorRelated) {
            for (int j = 0; j < memberParams.length && matchOK; j++){
            ResolvedType pMember = memberParams[j].resolve(world);
            ResolvedType pLookingFor = lookingForParams[j].resolve(world);
           
            if (pMember.isTypeVariableReference())
              pMember = ((TypeVariableReference)pMember).getTypeVariable().getFirstBound().resolve(world);
            if (pMember.isParameterizedType() || pMember.isGenericType())
              pMember = pMember.getRawType().resolve(aspectType.getWorld());
           
            if (pLookingFor.isTypeVariableReference())
              pLookingFor = ((TypeVariableReference)pLookingFor).getTypeVariable().getFirstBound().resolve(world);
            if (pLookingFor.isParameterizedType() || pLookingFor.isGenericType())
              pLookingFor = pLookingFor.getRawType().resolve(world);
           
            if (debug) System.err.println("Comparing parameter "+j+"   member="+pMember+"   lookingFor="+pLookingFor);
            if (!pMember.equals(pLookingFor)){
              matchOK=false;
            }
            }
          }
          if (matchOK) realMember = member;
        }
      }
    }
    if (debug && realMember==null) System.err.println("Didn't find a match");
    return realMember;
  }

  private void addNeededSuperCallMethods(
    BcelClassWeaver weaver,
    ResolvedType onType,
    Set neededSuperCalls)
  {
    LazyClassGen gen = weaver.getLazyClassGen();
   
    for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext();) {
      ResolvedMember superMethod = (ResolvedMember) iter.next();
      if (weaver.addDispatchTarget(superMethod)) {
        //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
        boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
        String dispatchName;
        if (isSuper)
          dispatchName =
            NameMangler.superDispatchMethod(onType, superMethod.getName());
        else
          dispatchName =
            NameMangler.protectedDispatchMethod(
              onType,
              superMethod.getName());
        LazyMethodGen dispatcher =
          makeDispatcher(
            gen,
            dispatchName,
            superMethod,
            weaver.getWorld(),
            isSuper);

        weaver.addLazyMethodGen(dispatcher);
      }
    }
  }

  private void signalError(String msgid,BcelClassWeaver weaver,UnresolvedType onType) {
    IMessage msg = MessageUtil.error(
        WeaverMessages.format(msgid,onType.getName()),getSourceLocation());
    weaver.getWorld().getMessageHandler().handleMessage(msg);
  }

  private boolean mungeNewConstructor(
    BcelClassWeaver weaver,
    NewConstructorTypeMunger newConstructorTypeMunger)
  {
   
    final LazyClassGen currentClass = weaver.getLazyClassGen();
    final InstructionFactory fact = currentClass.getFactory();

    ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
    ResolvedType   onType = newConstructorMember.getDeclaringType().resolve(weaver.getWorld());
    if (onType.isRawType()) onType = onType.getGenericType();
   
    if (onType.isAnnotation()) {
      signalError(WeaverMessages.ITDC_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
      return false;
    }
   
    if (onType.isEnum()) {
      signalError(WeaverMessages.ITDC_ON_ENUM_NOT_ALLOWED,weaver,onType);
      return false;
    }
   
    if (! onType.equals(currentClass.getType())) return false;

    ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
    //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
    LazyMethodGen mg =
      makeMethodGen(currentClass, newConstructorMember);
    mg.setEffectiveSignature(newConstructorTypeMunger.getSignature(),Shadow.ConstructorExecution,true);
   
//     pr98901
      // For copying the annotations across, we have to discover the real member in the aspect
      // which is holding them.
    if (weaver.getWorld().isInJava5Mode()){
     
      ResolvedMember interMethodDispatcher =AjcMemberMaker.postIntroducedConstructor(aspectType,onType,newConstructorTypeMunger.getSignature().getParameterTypes());
      AnnotationX annotationsOnRealMember[] = null;
      ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher,true);
      if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
          interMethodDispatcher+"' on aspect "+aspectType);
      annotationsOnRealMember = realMember.getAnnotations();
      if (annotationsOnRealMember!=null) {
        for (int i = 0; i < annotationsOnRealMember.length; i++) {
          AnnotationX annotationX = annotationsOnRealMember[i];
          Annotation a = annotationX.getBcelAnnotation();
          AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
          mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
        }
      }
      // the below loop fixes the very special (and very stupid)
      // case where an aspect declares an annotation
      // on an ITD it declared on itself.
      List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
      for (Iterator i = allDecams.iterator(); i.hasNext();){
        DeclareAnnotation decaMC = (DeclareAnnotation) i.next()
        if (decaMC.matches(explicitConstructor,weaver.getWorld())
            && mg.getEnclosingClass().getType() == aspectType) {
          mg.addAnnotation(decaMC.getAnnotationX());
        }
      }
    }
   
    currentClass.addMethodGen(mg);
    //weaver.addLazyMethodGen(freshConstructor);
   
    InstructionList body = mg.getBody();
   
    // add to body:  push arts for call to pre, from actual args starting at 1 (skipping this), going to
    //               declared argcount + 1
    UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
    Type[] paramTypes = mg.getArgumentTypes();
    int frameIndex = 1;
    for (int i = 0, len = declaredParams.length; i < len; i++) {
      body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex));
      frameIndex += paramTypes[i].getSize();
    }
    // do call to pre
    Member preMethod =
      AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
    body.append(Utility.createInvoke(fact, null, preMethod));
   
    // create a local, and store return pre stuff into it.
    int arraySlot = mg.allocateLocal(1);
    body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot));
   
    // put this on the stack
    body.append(InstructionConstants.ALOAD_0);
   
    // unpack pre args onto stack
    UnresolvedType[] superParamTypes = explicitConstructor.getParameterTypes();
   
    for (int i = 0, len = superParamTypes.length; i < len; i++) {
      body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
      body.append(Utility.createConstant(fact, i));
      body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
      body.append(
        Utility.createConversion(
          fact,
          Type.OBJECT,
          BcelWorld.makeBcelType(superParamTypes[i])));
    }

    // call super/this
   
    body.append(Utility.createInvoke(fact, null, explicitConstructor));
   
    // put this back on the stack

    body.append(InstructionConstants.ALOAD_0);
   
    // unpack params onto stack
    Member postMethod =
      AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
    UnresolvedType[] postParamTypes = postMethod.getParameterTypes();
   
    for (int i = 1, len = postParamTypes.length; i < len; i++) {
      body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
      body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
      body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
      body.append(
        Utility.createConversion(
          fact,
          Type.OBJECT,
          BcelWorld.makeBcelType(postParamTypes[i])));
    }   
   
    // call post
    body.append(Utility.createInvoke(fact, null, postMethod));
   
    // don't forget to return!!
    body.append(InstructionConstants.RETURN);
   
    return true;   
  }


  private static LazyMethodGen makeDispatcher(
    LazyClassGen onGen,
    String dispatchName,
    ResolvedMember superMethod,
    BcelWorld world,
    boolean isSuper)
  {
    Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
    Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
       
    int modifiers = Modifier.PUBLIC;
    if (onGen.isInterface()) modifiers |= Modifier.ABSTRACT;
       
    LazyMethodGen mg =
        new LazyMethodGen(
          modifiers,
          returnType,
          dispatchName,
          paramTypes,
          UnresolvedType.getNames(superMethod.getExceptions()),
          onGen);
    InstructionList body = mg.getBody();
   
    if (onGen.isInterface()) return mg;
   
    // assert (!superMethod.isStatic())
    InstructionFactory fact = onGen.getFactory();
    int pos = 0;
   
    body.append(InstructionFactory.createThis());
    pos++;
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      pos+=paramType.getSize();
    }
    if (isSuper) {
      body.append(Utility.createSuperInvoke(fact, world, superMethod));
    } else {
      body.append(Utility.createInvoke(fact, world, superMethod));
    }
    body.append(InstructionFactory.createReturn(returnType));

    return mg;
 
 
  private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
    /*ResolvedMember initMethod = */munger.getInitMethod(aspectType);
    LazyClassGen gen = weaver.getLazyClassGen();
    ResolvedMember field = munger.getSignature();
   
    ResolvedType onType = weaver.getWorld().resolve(field.getDeclaringType(),munger.getSourceLocation());
    if (onType.isRawType()) onType = onType.getGenericType();

    boolean onInterface = onType.isInterface();
   
    if (onType.isAnnotation()) {
      signalError(WeaverMessages.ITDF_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
      return false;
    }
   
    if (onType.isEnum()) {
      signalError(WeaverMessages.ITDF_ON_ENUM_NOT_ALLOWED,weaver,onType);
      return false;
    }
   
    ResolvedMember interMethodBody = munger.getInitMethod(aspectType);
   
    AnnotationX annotationsOnRealMember[] = null;
    // pr98901
      // For copying the annotations across, we have to discover the real member in the aspect
      // which is holding them.
    if (weaver.getWorld().isInJava5Mode()){
        // the below line just gets the method with the same name in aspectType.getDeclaredMethods();
        ResolvedType toLookOn = aspectType;
        if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
        ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,interMethodBody,false);
        if (realMember==null) throw new BCException("Couldn't find ITD init member '"+
            interMethodBody+"' on aspect "+aspectType);
        annotationsOnRealMember = realMember.getAnnotations();
    }
   
    if (onType.equals(gen.getType())) {
      if (onInterface) {
        ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType);
        LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
        gen.addMethodGen(mg);
       
        LazyMethodGen mg1 = makeMethodGen(gen,
          AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
        gen.addMethodGen(mg1);
      } else {
        weaver.addInitializer(this);
        FieldGen fg = makeFieldGen(gen,
          AjcMemberMaker.interFieldClassField(field, aspectType));
       
        if (annotationsOnRealMember!=null) {
          for (int i = 0; i < annotationsOnRealMember.length; i++) {
            AnnotationX annotationX = annotationsOnRealMember[i];
            Annotation a = annotationX.getBcelAnnotation();
            AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true)
            fg.addAnnotation(ag);
          }
        }
       
        gen.addField(fg.getField(),getSourceLocation());
         
      }
        return true;
    } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
      // wew know that we can't be static since we don't allow statics on interfaces
      if (field.isStatic()) throw new RuntimeException("unimplemented");
      weaver.addInitializer(this);
      //System.err.println("impl body on " + gen.getType() + " for " + munger);
     
     
      Type fieldType =   BcelWorld.makeBcelType(field.getType());
       
      FieldGen fg = makeFieldGen(gen,AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
         
        if (annotationsOnRealMember!=null) {
          for (int i = 0; i < annotationsOnRealMember.length; i++) {
            AnnotationX annotationX = annotationsOnRealMember[i];
            Annotation a = annotationX.getBcelAnnotation();
            AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true)
            fg.addAnnotation(ag);
          }
        }
       
          gen.addField(fg.getField(),getSourceLocation());
        //this uses a shadow munger to add init method to constructors
        //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
       
        ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType()/*onType*/, aspectType);
      LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
      InstructionList il = new InstructionList();
      InstructionFactory fact = gen.getFactory();
      if (field.isStatic()) {
        il.append(fact.createFieldAccess(
          gen.getClassName(),
          fg.getName(),
          fieldType, Constants.GETSTATIC));
      } else {
        il.append(InstructionConstants.ALOAD_0);
        il.append(fact.createFieldAccess(
          gen.getClassName(),
          fg.getName(),
          fieldType, Constants.GETFIELD));
      }
      il.append(InstructionFactory.createReturn(fieldType));
      mg.getBody().insert(il);
       
      gen.addMethodGen(mg);
           
      // Check if we need bridge methods for the field getter and setter
      if (munger.getDeclaredSignature()!=null) { // is this munger a parameterized form of some original munger?
        ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
        boolean needsbridging = false;
        if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
        if (toBridgeTo!=null && needsbridging) {
          ResolvedMember bridgingGetter = AjcMemberMaker.interFieldInterfaceGetter(toBridgeTo, gen.getType(), aspectType);         
          createBridgeMethodForITDF(weaver,gen,itdfieldGetter,bridgingGetter);
        }
      }   
     
      ResolvedMember itdfieldSetter = AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType);
      LazyMethodGen mg1 = makeMethodGen(gen, itdfieldSetter);
      InstructionList il1 = new InstructionList();
      if (field.isStatic()) {
        il1.append(InstructionFactory.createLoad(fieldType, 0));
        il1.append(fact.createFieldAccess(
          gen.getClassName(),
          fg.getName(),
          fieldType, Constants.PUTSTATIC));
      } else {
        il1.append(InstructionConstants.ALOAD_0);
        il1.append(InstructionFactory.createLoad(fieldType, 1));
        il1.append(fact.createFieldAccess(
          gen.getClassName(),
          fg.getName(),
          fieldType, Constants.PUTFIELD));
      }
      il1.append(InstructionFactory.createReturn(Type.VOID));
      mg1.getBody().insert(il1);
       
      gen.addMethodGen(mg1);
     
      if (munger.getDeclaredSignature()!=null) {
        ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
        boolean needsbridging = false;
        if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
        if (toBridgeTo!=null && needsbridging) {
        ResolvedMember bridgingSetter = AjcMemberMaker.interFieldInterfaceSetter(toBridgeTo, gen.getType(), aspectType);
        createBridgeMethodForITDF(weaver, gen, itdfieldSetter, bridgingSetter);
        }
        }
     
        return true;
    } else {
      return false;
    }
  }

  // FIXME asc combine with other createBridge.. method in this class, avoid the duplication...
  private void createBridgeMethodForITDF(BcelClassWeaver weaver, LazyClassGen gen, ResolvedMember itdfieldSetter, ResolvedMember bridgingSetter) {
    InstructionFactory fact;
    LazyMethodGen bridgeMethod = makeMethodGen(gen,bridgingSetter)
    Type[] paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
      Type[] bridgingToParms = BcelWorld.makeBcelTypes(itdfieldSetter.getParameterTypes());
      Type returnType   = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
      InstructionList body = bridgeMethod.getBody();
      fact = gen.getFactory();
      int pos = 0;

      if (!bridgingSetter.isStatic()) {
      body.append(InstructionFactory.createThis());
      pos++;
      }
      for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(itdfieldSetter.getParameterTypes()[i].getErasureSignature()) ) {
        // une cast est required
        System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
        body.append(fact.createCast(paramType,bridgingToParms[i]));
      }
      pos+=paramType.getSize();
      }
    
      body.append(Utility.createInvoke(fact, weaver.getWorld(), itdfieldSetter));
      body.append(InstructionFactory.createReturn(returnType));
      gen.addMethodGen(bridgeMethod);
  }
 
  public ConcreteTypeMunger parameterizedFor(ResolvedType target) {
    return new BcelTypeMunger(munger.parameterizedFor(target),aspectType);
  }
 
  /**
   * Returns a list of type variable aliases used in this munger.  For example, if the
   * ITD is 'int I<A,B>.m(List<A> las,List<B> lbs) {}' then this returns a list containing
   * the strings "A" and "B".
   */
  public List /*String*/ getTypeVariableAliases() {
    return munger.getTypeVariableAliases();
  }
}
   
TOP

Related Classes of org.aspectj.weaver.bcel.BcelTypeMunger

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.