]> source.dussan.org Git - aspectj.git/commitdiff
rearchitect @decp
authoravasseur <avasseur>
Mon, 19 Dec 2005 13:09:20 +0000 (13:09 +0000)
committeravasseur <avasseur>
Mon, 19 Dec 2005 13:09:20 +0000 (13:09 +0000)
aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareParents.java
tests/java5/ataspectj/ataspectj/DeclareParentsImplementsTest.java
tests/java5/ataspectj/ataspectj/DeclareParentsInterfaceTest.java
tests/ltw/aop-abstractaspect.xml
weaver/src/org/aspectj/weaver/AjcMemberMaker.java
weaver/src/org/aspectj/weaver/MethodDelegateTypeMunger.java
weaver/src/org/aspectj/weaver/NameMangler.java
weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java

index fe7267849153e1dd38209822ea64f5763b908d6d..b7c2452e29a09f0115ff34a1efcc360b79966d28 100644 (file)
@@ -27,7 +27,7 @@ public @interface DeclareParents {
      * The target types expression
      */
     String value();
-    
+
     /**
      * Optional class defining default implementation
      * of interface members (equivalent to defining
@@ -35,7 +35,7 @@ public @interface DeclareParents {
      * public methods of the interface).
      */
     Class defaultImpl() default DeclareParents.class;
-    
+
     // note - a default of "null" is not allowed,
     // hence the strange default given above.
 }
index 8b701a28e8d5b62f60cd4a2a10b16deab0389b5a..b4cc9ed4e4783ee9d03d4d4ec452fd7c1e0ed79b 100644 (file)
@@ -50,10 +50,11 @@ public class DeclareParentsImplementsTest extends TestCase {
     @Aspect
     static class TestAspect {
 
-        @DeclareParents("ataspectj.DeclareParentsImplementsTest.Target")
-        public static Introduced i = new Implementation();//see here control of instantiation
+        @DeclareParents(value="ataspectj.DeclareParentsImplementsTest.Target",
+                        defaultImpl=Implementation.class)
+        public static Introduced i;
         // will lead to: class Target implements Introduced {
-        //    void intro(args) { TestAspect.i.intro(args); }
+        //    void intro(args) { delegate to some hidden field, lazy initialized here for now }
         // }
 
         @Before("execution(* ataspectj.DeclareParentsImplementsTest.Introduced.intro())")
index ffac0e4a26d24654ccec0530b1e6594af041b626..2823251e564f9922bc9f733c4213a33b48e90584 100644 (file)
@@ -15,6 +15,7 @@ import junit.framework.TestCase;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.DeclareImplements;
+import org.aspectj.lang.annotation.DeclareParents;
 
 import java.util.Arrays;
 
@@ -34,7 +35,7 @@ public class DeclareParentsInterfaceTest extends TestCase {
     @Aspect
     static class TestAspect {
 
-        @DeclareImplements("ataspectj.DeclareParentsInterfaceTest.Target")
+        @DeclareParents("ataspectj.DeclareParentsInterfaceTest.Target")
         Marker introduce;
 
         @Before("execution(* ataspectj.DeclareParentsInterfaceTest.Marker+.target())")
index 7f82c94eea4cf66c3bc2f95b2ea733e7638875be..00d541d5b87335efb60e15f3eb9c69ef65037e94 100644 (file)
@@ -5,4 +5,4 @@
     
     <weaver options="-showWeaveInfo"/>
 </aspectj>
-       
+
index 978f80ffd7e94ea906283333caca111c183d2857..a0add374c1fc55e41054bd7f51cbed8587ba8ef9 100644 (file)
@@ -499,8 +499,18 @@ public class AjcMemberMaker {
                        NameMangler.postIntroducedConstructor(aspectType, targetType),
                        UnresolvedType.insert(targetType, paramTypes));
        }
-       
-       public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) {
+
+    public static ResolvedMember itdAtDeclareParentsField(ResolvedType targetType, UnresolvedType itdType, UnresolvedType aspectType) {
+        return new ResolvedMemberImpl(
+                Member.FIELD,
+                targetType,
+                Modifier.PRIVATE,
+                itdType,
+                NameMangler.itdAtDeclareParentsField(aspectType, itdType),
+                null);
+    }
+
+    public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) {
 //             
 //             ResolvedType targetType,
 //             UnresolvedType[] argTypes,
index e7bc20d3b7e85b63972e9786f9d70b0acebbb5b1..fbfccd6062b8fa02c5c68d104ba1b14354353e5e 100644 (file)
@@ -28,10 +28,12 @@ import org.aspectj.weaver.patterns.TypePattern;
  */
 public class MethodDelegateTypeMunger extends ResolvedTypeMunger {
 
+    private final UnresolvedType aspect;
+
     /**
-     * The field in the aspect that hosts the mixin instance
+     * The mixin impl (no arg ctor)
      */
-    private final ResolvedMember aspectFieldDelegate;
+    private final String implClassName;
 
     /**
      * Type pattern this munger applies to
@@ -43,52 +45,42 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger {
      *
      * @param signature
      * @param aspect
-     * @param fieldName
+     * @param implClassName
      * @param typePattern
      */
-    public MethodDelegateTypeMunger(ResolvedMember signature, ResolvedType aspect, String fieldName, TypePattern typePattern) {
+    public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern) {
         super(MethodDelegate, signature);
+        this.aspect = aspect;
         this.typePattern = typePattern;
-
-        ResolvedMember[] fields = aspect.getDeclaredFields();//note: will unpack attributes
-        ResolvedMember field = null;
-        for (int i = 0; i < fields.length; i++) {
-            if (fieldName.equals(fields[i].getName())) {
-                field = fields[i];
-                break;
-            }
-        }
-        if (field == null) {           
-            throw new RuntimeException("Should not happen: aspect field not found for @DeclareParents delegate");
-        } else {
-            aspectFieldDelegate = field;
-        }
+        this.implClassName = implClassName;
     }
 
-    private MethodDelegateTypeMunger(ResolvedMember signature, ResolvedMember fieldDelegate, TypePattern typePattern) {
-        super(MethodDelegate, signature);
-        this.aspectFieldDelegate = fieldDelegate;
-        this.typePattern = typePattern;
+    public ResolvedMember getDelegate(ResolvedType targetType) {
+        return AjcMemberMaker.itdAtDeclareParentsField(
+                targetType,
+                signature.getDeclaringType(),
+                aspect
+        );
     }
 
-    public ResolvedMember getDelegate() {
-        return aspectFieldDelegate;
+    public String getImplClassName() {
+        return implClassName;
     }
 
     public void write(DataOutputStream s) throws IOException {
         kind.write(s);
         signature.write(s);
-        aspectFieldDelegate.write(s);
+        aspect.write(s);
+        s.writeUTF(implClassName);
         typePattern.write(s);
     }
 
-
-
     public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException {
         ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context);
-        ResolvedMemberImpl field = ResolvedMemberImpl.readResolvedMember(s, context);
+        UnresolvedType aspect = UnresolvedType.read(s);
+        String implClassName = s.readUTF();
         TypePattern tp = TypePattern.read(s, context);
-        return new MethodDelegateTypeMunger(signature, field, tp);
+        return new MethodDelegateTypeMunger(signature, aspect, implClassName, tp);
     }
 
     /**
@@ -115,4 +107,62 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger {
     public boolean changesPublicSignature() {
         return true;
     }
+
+    public static class FieldHostTypeMunger extends ResolvedTypeMunger {
+
+        private UnresolvedType aspect;
+
+        /**
+         * Type pattern this munger applies to
+         */
+        private final TypePattern typePattern;
+
+        /**
+         * Construct a new type munger for @AspectJ ITD
+         *
+         * @param field
+         * @param aspect
+         * @param typePattern
+         */
+        public FieldHostTypeMunger(ResolvedMember field, UnresolvedType aspect, TypePattern typePattern) {
+            super(FieldHost, field);
+            this.aspect = aspect;
+            this.typePattern = typePattern;
+        }
+
+        public void write(DataOutputStream s) throws IOException {
+            kind.write(s);
+            signature.write(s);
+            aspect.write(s);
+            typePattern.write(s);
+        }
+
+        public static ResolvedTypeMunger readFieldHost(VersionedDataInputStream s, ISourceContext context) throws IOException {
+            ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context);
+            UnresolvedType aspect = UnresolvedType.read(s);
+            TypePattern tp = TypePattern.read(s, context);
+            return new FieldHostTypeMunger(signature, aspect, tp);
+        }
+
+        /**
+         * Match based on given type pattern, only classes can be matched
+         *
+         * @param matchType
+         * @param aspectType
+         * @return true if match
+         */
+        public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+            // match only on class
+            if (matchType.isEnum() || matchType.isInterface() || matchType.isAnnotation()) {
+                return false;
+            }
+
+            return typePattern.matchesStatically(matchType);
+        }
+
+        public boolean changesPublicSignature() {
+            return false;
+        }
+
+    }
 }
index 17a29a52810203aaf979d9be183427ca61b002f3..4dfd751b9577f40bf5c4ead1364aa25972f88ea9 100644 (file)
@@ -64,16 +64,17 @@ public class NameMangler {
        
        // PTWIMPL method names that must include aspect type
        public static String perTypeWithinFieldForTarget(UnresolvedType aspectType) {
-               String s = makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance");
-               return s;
+               return makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance");
        }
-       
-       public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) {
+
+    public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) {
                return makeName(aspectType.getNameAsIdentifier(), "localAspectOf");
        }
        
-       
-       
+    public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) {
+        return makeName(aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier());
+    }
+
        public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) {
                return makeName("privMethod", aspectType.getNameAsIdentifier(),
                                        objectType.getNameAsIdentifier(), name);
index 0e95d39c54b5f8d61d7300aecb9605179502dca4..5891b9bc84fed3ffc71acadc8707d1c7c7c8b905 100644 (file)
@@ -135,6 +135,8 @@ public abstract class ResolvedTypeMunger {
                        return NewConstructorTypeMunger.readConstructor(s, context);
         } else if (kind == MethodDelegate) {
             return MethodDelegateTypeMunger.readMethod(s, context);
+        } else if (kind == FieldHost) {
+            return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context);
         } else {
                        throw new RuntimeException("unimplemented");
                }
@@ -237,12 +239,14 @@ public abstract class ResolvedTypeMunger {
                    case 2: return Method;
                    case 5: return Constructor;
                 case 9: return MethodDelegate;
+                case 10: return FieldHost;
             }
                throw new BCException("bad kind: " + key);
            }
 
         public String toString() {
             // we want MethodDelegate to appear as Method in WeaveInfo messages
+            //TODO we may want something for fieldhost ?
             if (MethodDelegate.getName().equals(getName())) {
                 return Method.toString();
             } else {
@@ -267,6 +271,7 @@ public abstract class ResolvedTypeMunger {
        public static final Kind AnnotationOnType = new Kind("AnnotationOnType",8); // not serialized
 
     public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);// serialized, @AJ ITDs
+    public static final Kind FieldHost = new Kind("FieldHost", 10);// serialized, @AJ ITDs
 
     public static final String SUPER_DISPATCH_NAME = "superDispatch";
 
index e07f44c422c29ade0afd2954fb5a5fb644472ab1..9297f1d16819632965f4f062d9df89806c73cbe5 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.lang.reflect.Modifier;
 
 import org.aspectj.apache.bcel.Constants;
 import org.aspectj.apache.bcel.classfile.Attribute;
@@ -31,6 +32,7 @@ import org.aspectj.apache.bcel.classfile.annotation.Annotation;
 import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
+import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
 import org.aspectj.apache.bcel.generic.Type;
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.IMessageHandler;
@@ -50,6 +52,9 @@ import org.aspectj.weaver.ResolvedPointcutDefinition;
 import org.aspectj.weaver.ResolvedType;
 import org.aspectj.weaver.UnresolvedType;
 import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.NewFieldTypeMunger;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.Member;
 import org.aspectj.weaver.patterns.AndPointcut;
 import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
 import org.aspectj.weaver.patterns.DeclareParents;
@@ -317,7 +322,6 @@ public class AtAjAttributes {
                 if (acceptAttribute(fattribute)) {
                     RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute;
                     if (handleDeclareErrorOrWarningAnnotation(frvs, fstruct)
-                            || handleDeclareImplementsAnnotation(frvs, fstruct)
                             || handleDeclareParentsAnnotation(frvs, fstruct)) {
                         // semantic check - must be in an @Aspect [remove if previous block bypassed in advance]
                         if (!type.isAnnotationStyleAspect()) {
@@ -338,7 +342,7 @@ public class AtAjAttributes {
             }
             struct.ajAttributes.addAll(fstruct.ajAttributes);
         }
-        
+
         return struct.ajAttributes;
     }
 
@@ -463,8 +467,8 @@ public class AtAjAttributes {
         // Note: field annotation are for ITD and DEOW - processed at class level directly
         return Collections.EMPTY_LIST;
     }
-    
-    
+
+
     /**
      * Read @Aspect
      *
@@ -518,12 +522,12 @@ public class AtAjAttributes {
                             struct.context,
                             bindings
                         );
-                
+
 //                // we can't resolve here since the perclause typically refers to pointcuts
 //                // defined in the aspect that we haven't told the BcelObjectType about yet.
-//                
+//
 //                perClause.resolve(binding);
-                
+
                 // so we prepare to do it later...
                 aspectAttribute.setResolutionScope(binding);
                 return true;
@@ -607,47 +611,47 @@ public class AtAjAttributes {
         return false;
     }
 
-    /**
-     * Read @DeclareImplements
-     *
-     * @param runtimeAnnotations
-     * @param struct
-     * @return true if found
-     */
-    private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) {
-        Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
-        if (deci != null) {
-            ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE);
-            String deciPattern = deciPatternNVP.getValue().stringifyValue();
-            if (deciPattern != null) {
-                TypePattern typePattern = parseTypePattern(deciPattern, struct);
-                ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld());
-                if (fieldType.isPrimitiveType()) {
-                    return false;
-                } else if (fieldType.isInterface()) {
-                    TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false);
-                    parent.resolve(struct.enclosingType.getWorld());
-                    List parents = new ArrayList(1);
-                    parents.add(parent);
-                    //TODO kick ISourceLocation sl = struct.bField.getSourceLocation();    ??
-                    struct.ajAttributes.add(
-                            new AjAttribute.DeclareAttribute(
-                                    new DeclareParents(
-                                        typePattern,
-                                        parents,
-                                        false
-                                    )
-                            )
-                    );
-                    return true;
-                } else {
-                    reportError("@DeclareImplements: can only be used on field whose type is an interface", struct);
-                    return false;
-                }
-            }
-        }
-        return false;
-    }
+//    /**
+//     * Read @DeclareImplements
+//     *
+//     * @param runtimeAnnotations
+//     * @param struct
+//     * @return true if found
+//     */
+//    private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) {
+//        Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
+//        if (deci != null) {
+//            ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE);
+//            String deciPattern = deciPatternNVP.getValue().stringifyValue();
+//            if (deciPattern != null) {
+//                TypePattern typePattern = parseTypePattern(deciPattern, struct);
+//                ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld());
+//                if (fieldType.isPrimitiveType()) {
+//                    return false;
+//                } else if (fieldType.isInterface()) {
+//                    TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false);
+//                    parent.resolve(struct.enclosingType.getWorld());
+//                    List parents = new ArrayList(1);
+//                    parents.add(parent);
+//                    //TODO kick ISourceLocation sl = struct.bField.getSourceLocation();    ??
+//                    struct.ajAttributes.add(
+//                            new AjAttribute.DeclareAttribute(
+//                                    new DeclareParents(
+//                                        typePattern,
+//                                        parents,
+//                                        false
+//                                    )
+//                            )
+//                    );
+//                    return true;
+//                } else {
+//                    reportError("@DeclareImplements: can only be used on field whose type is an interface", struct);
+//                    return false;
+//                }
+//            }
+//        }
+//        return false;
+//    }
 
     /**
      * Read @DeclareParents
@@ -664,9 +668,7 @@ public class AtAjAttributes {
             if (decpPattern != null) {
                 TypePattern typePattern = parseTypePattern(decpPattern, struct);
                 ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld());
-                if (fieldType.isPrimitiveType()) {
-                    return false;
-                } else if (fieldType.isInterface() && (struct.field.isPublic() && struct.field.isStatic())) {
+                if (fieldType.isInterface()) {
                     TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false);
                     parent.resolve(struct.enclosingType.getWorld());
                     //TODO kick ISourceLocation sl = struct.bField.getSourceLocation();    ??
@@ -681,25 +683,66 @@ public class AtAjAttributes {
                                     )
                             )
                     );
+
+
+                    // do we have a defaultImpl=xxx.class (ie implementation)
+                    String defaultImplClassName = null;
+                    ElementNameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl");
+                    if (defaultImplNVP != null) {
+                        ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue();
+                        defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName();
+                        if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) {
+                            defaultImplClassName = null;
+                        }
+                        //TODO check public no arg ctor
+                    }
+
                     // then iterate on field interface hierarchy (not object)
-                    for (Iterator it = fieldType.getMethods(); it.hasNext();) {
-                        ResolvedMember method = (ResolvedMember)it.next();
+                    boolean hasAtLeastOneMethod = false;
+                    ResolvedMember[] methods = (ResolvedMember[])fieldType.getMethodsWithoutIterator(true, false).toArray(new ResolvedMember[0]);
+                    for (int i = 0; i < methods.length; i++) {
+                        ResolvedMember method = (ResolvedMember)methods[i];
                         if (method.isAbstract()) {
+                            if (defaultImplClassName == null) {
+                                // non marker interface with no default impl provided
+                                reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided", struct);
+                                return false;
+                            }
+                            hasAtLeastOneMethod = true;
+                            
                             struct.ajAttributes.add(
                                     new AjAttribute.TypeMunger(
                                             new MethodDelegateTypeMunger(
                                                 method,
                                                 struct.enclosingType,
-                                                struct.field.getName(),
+                                                defaultImplClassName,
                                                 typePattern
                                             )
                                     )
                             );
                         }
                     }
+                    // successfull so far, we thus need a bcel type munger to have
+                    // a field hosting the mixin in the target type
+                    if (hasAtLeastOneMethod) {
+                        struct.ajAttributes.add(
+                                new AjAttribute.TypeMunger(
+                                        new MethodDelegateTypeMunger.FieldHostTypeMunger(
+                                                AjcMemberMaker.itdAtDeclareParentsField(
+                                                        null,//prototyped
+                                                        fieldType,
+                                                        struct.enclosingType
+                                                ),
+                                                struct.enclosingType,
+                                                typePattern
+                                        )
+                                )
+                        );
+                    }
+
                     return true;
                 } else {
-                    reportError("@DeclareParents: can only be used on a public static field whose type is an interface", struct);
+                    reportError("@DeclareParents: can only be used on a field whose type is an interface", struct);
                     return false;
                 }
             }
index 9bbd0d49e07d5fad5f811a054b28b1da17d41d1d..46332675a547aca1c58fe84b14875414eb57a613 100644 (file)
@@ -29,6 +29,7 @@ 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.BranchInstruction;
 import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.ISourceLocation;
@@ -63,7 +64,7 @@ import org.aspectj.weaver.WeaverStateInfo;
 import org.aspectj.weaver.World;
 import org.aspectj.weaver.patterns.DeclareAnnotation;
 import org.aspectj.weaver.patterns.Pointcut;
-
+import org.aspectj.lang.Signature;
 
 //XXX addLazyMethodGen is probably bad everywhere
 public class BcelTypeMunger extends ConcreteTypeMunger {
@@ -87,6 +88,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        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;
@@ -147,7 +150,9 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
 //                  reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
                     
                        }
-               } else {
+            } 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,
@@ -1103,11 +1108,23 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
             InstructionList body = new InstructionList();
             InstructionFactory fact = gen.getFactory();
 
-            // getstatic field from aspect
-            body.append(Utility.createGet(fact, munger.getDelegate()));
-
+            // 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'
+               if (!introduced.isStatic()) { // skip 'this' (?? can this really happen)
                  //body.append(InstructionFactory.createThis());
                  pos++;
                }
@@ -1133,7 +1150,25 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
         return false;
     }
 
-       private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) {
+    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) {