From: jhugunin Date: Fri, 8 Aug 2003 00:26:22 +0000 (+0000) Subject: fix for Bugzilla Bug 41175 X-Git-Tag: V1_1_1~124 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=efc1cc47398443b33fe90da11c4cf1d14dc9c108;p=aspectj.git fix for Bugzilla Bug 41175 binary aspect-declared methods conflict, lost their exception clauses larger fix to address more issues with aspect-declared methods in bytecode form also addressed declared exception issue more generally this fix should be more stable than a smaller hack that just fixed this specific bug report would have been. added a few tests to match increased scope. --- diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java index 9ddf959d8..a1c8c8e02 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java @@ -212,8 +212,8 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration { ResolvedMember signature = new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers, - ResolvedTypeX.VOID, "", bindingAsMember.getParameterTypes()); - signature.setCheckedExceptions(world.fromEclipse(binding.thrownExceptions)); + ResolvedTypeX.VOID, "", bindingAsMember.getParameterTypes(), + world.fromEclipse(binding.thrownExceptions)); ResolvedMember syntheticInterMember = AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java index 662a5bc3f..2039fd54c 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java @@ -86,8 +86,8 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { binding = classScope.referenceContext.binding.resolveTypesFor(binding); ResolvedMember sig = new ResolvedMember(Member.METHOD, EclipseFactory.fromBinding(onTypeBinding), declaredModifiers, EclipseFactory.fromBinding(binding.returnType), new String(declaredSelector), - EclipseFactory.fromBindings(binding.parameters)); - sig.setCheckedExceptions(world.fromEclipse(binding.thrownExceptions)); + EclipseFactory.fromBindings(binding.parameters), + world.fromEclipse(binding.thrownExceptions)); NewMethodTypeMunger myMunger = new NewMethodTypeMunger(sig, null); setMunger(myMunger); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index 868499adc..daacbc4e5 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -43,6 +43,7 @@ public class AjLookupEnvironment extends LookupEnvironment { // private boolean builtInterTypesAndPerClauses = false; private List pendingTypesToWeave = new ArrayList(); + private Map dangerousInterfaces = new HashMap(); public AjLookupEnvironment( ITypeRequestor typeRequestor, @@ -151,16 +152,49 @@ public class AjLookupEnvironment extends LookupEnvironment { } } - - private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, Collection typeMungers, Collection declareParents, boolean skipInners) { -// if (new String(sourceType.sourceName()).equals("Target")) { -// Thread.currentThread().dumpStack(); -// } -// -// System.out.println("weaving types: " + new String(sourceType.sourceName())); -// System.out.println(" mungers: " + typeMungers); ResolvedTypeX onType = factory.fromEclipse(sourceType); + WeaverStateInfo info = onType.getWeaverState(); + + if (info != null && !info.isOldStyle()) { + Collection mungers = + onType.getWeaverState().getTypeMungers(onType); + + //System.out.println("mungers: " + mungers); + for (Iterator i = mungers.iterator(); i.hasNext(); ) { + ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); + EclipseTypeMunger munger = factory.makeEclipseTypeMunger(m); + if (munger.munge(sourceType)) { + if (onType.isInterface() && + munger.getMunger().needsAccessToTopmostImplementor()) + { + if (!onType.getWorld().getCrosscuttingMembersSet().containsAspect(munger.getAspectType())) { + dangerousInterfaces.put(onType, + "implementors of " + onType + " must be woven by " + + munger.getAspectType()); + } + } + } + + } + + return; + } + + //System.out.println("dangerousInterfaces: " + dangerousInterfaces); + + for (Iterator i = dangerousInterfaces.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + ResolvedTypeX interfaceType = (ResolvedTypeX)entry.getKey(); + if (onType.isTopmostImplementor(interfaceType)) { + factory.showMessage(IMessage.ERROR, + onType + ": " + entry.getValue(), + onType.getSourceLocation(), null); + } + } + + boolean needOldStyleWarning = (info != null && info.isOldStyle()); + onType.clearInterTypeMungers(); for (Iterator i = declareParents.iterator(); i.hasNext();) { @@ -170,6 +204,12 @@ public class AjLookupEnvironment extends LookupEnvironment { for (Iterator i = typeMungers.iterator(); i.hasNext();) { EclipseTypeMunger munger = (EclipseTypeMunger) i.next(); if (munger.matches(onType)) { + if (needOldStyleWarning) { + factory.showMessage(IMessage.WARNING, + "The class for " + onType + " should be recompiled with ajc-1.1.1 for best results", + onType.getSourceLocation(), null); + needOldStyleWarning = false; + } onType.addInterTypeMunger(munger); } } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java index 76de36409..e9f9f0402 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java @@ -192,8 +192,8 @@ public class EclipseFactory { binding.modifiers, fromBinding(binding.returnType), new String(binding.selector), - fromBindings(binding.parameters)); - ret.setCheckedExceptions(fromBindings(binding.thrownExceptions)); + fromBindings(binding.parameters), + fromBindings(binding.thrownExceptions)); return ret; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java index e965ea031..60f317f1f 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java @@ -66,8 +66,8 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName { return declaration instanceof AspectDeclaration; } - public boolean isWovenBy(ResolvedTypeX aspectType) { - return false; + public WeaverStateInfo getWeaverState() { + return null; } public ResolvedTypeX getSuperclass() { diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java index c98a12a11..0382c9a1f 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java @@ -101,7 +101,7 @@ public class BinaryFormsTestCase extends CommandTestCase { args.add("testdata/src1/binary/client/Client1.java"); - CommandTestCase.runCompiler(args, new int[] {9, 11, 15, 17}); + CommandTestCase.runCompiler(args, new int[] {15, 17, 22}); args = new ArrayList(); args.add("-classpath"); diff --git a/tests/ajcTests.xml b/tests/ajcTests.xml index 2ae8559ae..1a73d9990 100644 --- a/tests/ajcTests.xml +++ b/tests/ajcTests.xml @@ -6549,6 +6549,7 @@ + @@ -6629,4 +6630,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ajcTestsFailing.xml b/tests/ajcTestsFailing.xml index 8b5d79788..5439341a1 100644 --- a/tests/ajcTestsFailing.xml +++ b/tests/ajcTestsFailing.xml @@ -12,36 +12,6 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/bugs/DeclaredExceptions.java b/tests/bugs/DeclaredExceptions.java new file mode 100644 index 000000000..9baec0c15 --- /dev/null +++ b/tests/bugs/DeclaredExceptions.java @@ -0,0 +1,28 @@ +import java.lang.reflect.Method; +import java.io.*; +import org.aspectj.testing.Tester; + +public class DeclaredExceptions { + public static void main(String[] args) throws Exception { + Class c = C.class; + Method m = c.getDeclaredMethod("m", new Class[0]); + Tester.checkEqual(m.getExceptionTypes().length, 1); + Tester.checkEqual(m.getExceptionTypes()[0], IOException.class); + + c = I.class; + m = c.getDeclaredMethod("m", new Class[0]); + Tester.checkEqual(m.getExceptionTypes().length, 1); + Tester.checkEqual(m.getExceptionTypes()[0], IOException.class); + } +} + +interface I {} + +class C {} + +aspect A { + public void C.m() throws IOException { + } + + public void I.m() throws IOException { } +} \ No newline at end of file diff --git a/tests/bugs/interfaceLibrary/lib.jar b/tests/bugs/interfaceLibrary/lib.jar index 496514a29..57acb6aad 100644 Binary files a/tests/bugs/interfaceLibrary/lib.jar and b/tests/bugs/interfaceLibrary/lib.jar differ diff --git a/tests/bugs/interfaceLibrary/libClass.jar b/tests/bugs/interfaceLibrary/libClass.jar index 720435d62..ee68ce1c0 100644 Binary files a/tests/bugs/interfaceLibrary/libClass.jar and b/tests/bugs/interfaceLibrary/libClass.jar differ diff --git a/tests/new/interfaceLibrary/aspectOnly.jar b/tests/new/interfaceLibrary/aspectOnly.jar index 4aaffb645..eb6505b8c 100644 Binary files a/tests/new/interfaceLibrary/aspectOnly.jar and b/tests/new/interfaceLibrary/aspectOnly.jar differ diff --git a/tests/new/interfaceLibrary/aspectedInterfaceOnly.jar b/tests/new/interfaceLibrary/aspectedInterfaceOnly.jar index 9cb969b9d..1b8393320 100644 Binary files a/tests/new/interfaceLibrary/aspectedInterfaceOnly.jar and b/tests/new/interfaceLibrary/aspectedInterfaceOnly.jar differ diff --git a/tests/new/interfaceLibrary/aspectedInterfaceOnlyBinary.jar b/tests/new/interfaceLibrary/aspectedInterfaceOnlyBinary.jar index 9cb969b9d..fe334d076 100644 Binary files a/tests/new/interfaceLibrary/aspectedInterfaceOnlyBinary.jar and b/tests/new/interfaceLibrary/aspectedInterfaceOnlyBinary.jar differ diff --git a/tests/new/interfaceLibrary/interfaceOnly.jar b/tests/new/interfaceLibrary/interfaceOnly.jar index ede6fc868..15c0fa559 100644 Binary files a/tests/new/interfaceLibrary/interfaceOnly.jar and b/tests/new/interfaceLibrary/interfaceOnly.jar differ diff --git a/weaver/src/org/aspectj/weaver/AjAttribute.java b/weaver/src/org/aspectj/weaver/AjAttribute.java index f981d21b2..217f04280 100644 --- a/weaver/src/org/aspectj/weaver/AjAttribute.java +++ b/weaver/src/org/aspectj/weaver/AjAttribute.java @@ -88,7 +88,7 @@ public abstract class AjAttribute { if (name.equals(Aspect.AttributeName)) { return new Aspect(PerClause.readPerClause(s, context)); } else if (name.equals(WeaverState.AttributeName)) { - return new WeaverState(WeaverStateKind.read(s)); + return new WeaverState(WeaverStateInfo.read(s, context)); } else if (name.equals(AdviceAttribute.AttributeName)) { return AdviceAttribute.read(s, context); } else if (name.equals(PointcutDeclarationAttribute.AttributeName)) { @@ -162,15 +162,15 @@ public abstract class AjAttribute { public String getNameString() { return AttributeName; } - private WeaverStateKind kind; - public WeaverState(WeaverStateKind kind) { + private WeaverStateInfo kind; + public WeaverState(WeaverStateInfo kind) { this.kind = kind; } public void write(DataOutputStream s) throws IOException { kind.write(s); } - public WeaverStateKind reify() { + public WeaverStateInfo reify() { return kind; } } diff --git a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java index ae29a0d4c..308b020b9 100644 --- a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java @@ -232,8 +232,8 @@ public class AjcMemberMaker { Modifier.PUBLIC, method.getReturnType(), NameMangler.superDispatchMethod(baseType, method.getName()), - method.getParameterTypes()); - //XXX needs thrown exceptions to be correct + method.getParameterTypes(), + method.getExceptions()); } public static ResolvedMember inlineAccessMethodForMethod(TypeX aspectType, ResolvedMember method) { @@ -249,8 +249,7 @@ public class AjcMemberMaker { NameMangler.inlineAccessMethodForMethod(method.getName(), method.getDeclaringType(), aspectType), - paramTypes); - //XXX needs thrown exceptions to be correct + paramTypes, method.getExceptions()); } public static ResolvedMember inlineAccessMethodForFieldGet(TypeX aspectType, Member field) { @@ -382,7 +381,8 @@ public class AjcMemberMaker { Modifier.PUBLIC, ResolvedTypeX.VOID, "", - constructor.getParameterTypes()); + constructor.getParameterTypes(), + constructor.getExceptions()); //System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers)); if (Modifier.isPublic(constructor.getModifiers())) return ret; @@ -429,7 +429,8 @@ public class AjcMemberMaker { return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC, field.getReturnType(), NameMangler.interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()), - field.isStatic() ? TypeX.NONE : new TypeX[] {field.getDeclaringType()} + field.isStatic() ? TypeX.NONE : new TypeX[] {field.getDeclaringType()}, + TypeX.NONE ); } @@ -451,7 +452,7 @@ public class AjcMemberMaker { makePublicNonFinal(field.getModifiers()), field.getReturnType(), NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), field.getName()), - TypeX.NONE + TypeX.NONE, TypeX.NONE ); } @@ -464,7 +465,7 @@ public class AjcMemberMaker { return new ResolvedMember(Member.FIELD, onClass, makePublicNonFinal(field.getModifiers()), field.getReturnType(), NameMangler.interFieldInterfaceField(aspectType, field.getDeclaringType(), field.getName()), - TypeX.NONE + TypeX.NONE, TypeX.NONE ); } @@ -478,7 +479,7 @@ public class AjcMemberMaker { return new ResolvedMember(Member.METHOD, onType, modifiers, ResolvedTypeX.VOID, NameMangler.interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()), - new TypeX[] {field.getReturnType()} + new TypeX[] {field.getReturnType()}, TypeX.NONE ); } @@ -492,7 +493,7 @@ public class AjcMemberMaker { return new ResolvedMember(Member.METHOD, onType, modifiers, field.getReturnType(), NameMangler.interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()), - TypeX.NONE + TypeX.NONE, TypeX.NONE ); } @@ -514,7 +515,7 @@ public class AjcMemberMaker { modifiers, meth.getReturnType(), NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), - meth.getParameterTypes()); + meth.getParameterTypes(), meth.getExceptions()); } /** @@ -530,7 +531,7 @@ public class AjcMemberMaker { return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC, meth.getReturnType(), NameMangler.interMethodDispatcher(aspectType, meth.getDeclaringType(), meth.getName()), - paramTypes); + paramTypes, meth.getExceptions()); } /** @@ -552,7 +553,7 @@ public class AjcMemberMaker { return new ResolvedMember(Member.METHOD, aspectType, modifiers, meth.getReturnType(), NameMangler.interMethodBody(aspectType, meth.getDeclaringType(), meth.getName()), - paramTypes); + paramTypes, meth.getExceptions()); } @@ -568,7 +569,7 @@ public class AjcMemberMaker { ret.getModifiers(), ret.getReturnType(), ret.getName(), - freshParams); + freshParams, ret.getExceptions()); } public static ResolvedMember toObjectConversionMethod(TypeX fromType) { @@ -580,7 +581,7 @@ public class AjcMemberMaker { PUBLIC_STATIC, TypeX.OBJECT, name, - new TypeX[] { fromType }); + new TypeX[] { fromType }, TypeX.NONE); } else { return null; } diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java index 5b2e84131..ec81a0cf2 100644 --- a/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java +++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java @@ -66,6 +66,10 @@ public class CrosscuttingMembersSet { return isAspect; } + public boolean containsAspect(TypeX aspectType) { + return members.containsKey(aspectType); + } + //XXX only for testing public void addFixedCrosscuttingMembers(ResolvedTypeX aspectType) { members.put(aspectType, aspectType.crosscuttingMembers); diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java index 60164e167..d1a4e9633 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMember.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java @@ -34,7 +34,19 @@ public class ResolvedMember extends Member implements IHasPosition { protected int start, end; protected ISourceContext sourceContext = null; - // ---- + //XXX deprecate this in favor of the constructor below + public ResolvedMember( + Kind kind, + TypeX declaringType, + int modifiers, + TypeX returnType, + String name, + TypeX[] parameterTypes) + { + super(kind, declaringType, modifiers, returnType, name, parameterTypes); + } + + public ResolvedMember( Kind kind, @@ -42,9 +54,11 @@ public class ResolvedMember extends Member implements IHasPosition { int modifiers, TypeX returnType, String name, - TypeX[] parameterTypes) + TypeX[] parameterTypes, + TypeX[] checkedExceptions) { super(kind, declaringType, modifiers, returnType, name, parameterTypes); + this.checkedExceptions = checkedExceptions; } public ResolvedMember( diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java index 086ade7b2..a732cf82c 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -54,7 +54,7 @@ public abstract class ResolvedTypeMunger { //System.err.println("matching: " + this + " to " + matchType + " onType = " + onType); if (matchType.equals(onType)) { if (!onType.isExposedToWeaver()) { - if (!onType.isWovenBy(aspectType)) { + if (onType.getWeaverState() != null) { if (matchType.getWorld().getLint().typeNotExposedToWeaver.isEnabled()) { matchType.getWorld().getLint().typeNotExposedToWeaver.signal( matchType.getName(), signature.getSourceLocation()); @@ -183,4 +183,18 @@ public abstract class ResolvedTypeMunger { return null; } + public boolean changesPublicSignature() { + return kind == Field || kind == Method || kind == Constructor; + } + + public boolean needsAccessToTopmostImplementor() { + if (kind == Field) { + return true; + } else if (kind == Method) { + return !signature.isAbstract(); + } else { + return false; + } + } + } diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java index a9b6fa654..1861254a5 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java @@ -575,8 +575,8 @@ public abstract class ResolvedTypeX extends TypeX { return delegate.isExposedToWeaver(); //??? where does this belong } - public boolean isWovenBy(ResolvedTypeX aspectType) { - return delegate.isWovenBy(aspectType); + public WeaverStateInfo getWeaverState() { + return delegate.getWeaverState(); } public ResolvedMember[] getDeclaredFields() { @@ -684,7 +684,7 @@ public abstract class ResolvedTypeX extends TypeX { // public abstract ISourceLocation getSourceLocation(); - public abstract boolean isWovenBy(ResolvedTypeX aspectType); + public abstract WeaverStateInfo getWeaverState(); // public ISourceContext getSourceContext() { // return sourceContext; @@ -1270,8 +1270,7 @@ public abstract class ResolvedTypeX extends TypeX { public ISourceLocation getSourceLocation() { return null; } public boolean isExposedToWeaver() { return false; } - public boolean isWovenBy(ResolvedTypeX aspectType) { - return false; + public WeaverStateInfo getWeaverState() { + return null; } - } diff --git a/weaver/src/org/aspectj/weaver/WeaverStateInfo.java b/weaver/src/org/aspectj/weaver/WeaverStateInfo.java new file mode 100644 index 000000000..20b5347c1 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/WeaverStateInfo.java @@ -0,0 +1,121 @@ +/* ******************************************************************* + * 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 + * ******************************************************************/ + + +package org.aspectj.weaver; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.bridge.IMessage; +import org.aspectj.util.TypeSafeEnum; +import org.aspectj.weaver.bcel.BcelTypeMunger; + +public class WeaverStateInfo { + private List/*Entry*/ typeMungers; + private boolean oldStyle; + + public WeaverStateInfo() { + this(new ArrayList(), false); + } + + private WeaverStateInfo(List typeMungers, boolean oldStyle) { + this.typeMungers = typeMungers; + this.oldStyle = oldStyle; + } + + private static final int UNTOUCHED=0, WOVEN=2, EXTENDED=3; + + public static final WeaverStateInfo read(DataInputStream s, ISourceContext context) throws IOException { + byte b = s.readByte(); + + switch(b) { + case UNTOUCHED: + throw new RuntimeException("unexpected UNWOVEN"); + case WOVEN: + return new WeaverStateInfo(Collections.EMPTY_LIST, true); + case EXTENDED: + int n = s.readShort(); + List l = new ArrayList(); + for (int i=0; i < n; i++) { + TypeX aspectType = TypeX.read(s); + ResolvedTypeMunger typeMunger = + ResolvedTypeMunger.read(s, context); + l.add(new Entry(aspectType, typeMunger)); + } + return new WeaverStateInfo(l, false); + } + throw new RuntimeException("bad WeaverState.Kind: " + b); + } + + private static class Entry { + public TypeX aspectType; + public ResolvedTypeMunger typeMunger; + public Entry(TypeX aspectType, ResolvedTypeMunger typeMunger) { + this.aspectType = aspectType; + this.typeMunger = typeMunger; + } + + public String toString() { + return "<" + aspectType + ", " + typeMunger + ">"; + } + } + + public void write(DataOutputStream s) throws IOException { + if (oldStyle) throw new RuntimeException("shouldn't be writing this"); + + s.writeByte(EXTENDED); + int n = typeMungers.size(); + s.writeShort(n); + for (int i=0; i < n; i++) { + Entry e = (Entry)typeMungers.get(i); + e.aspectType.write(s); + e.typeMunger.write(s); + } + } + + public void addConcreteMunger(ConcreteTypeMunger munger) { + typeMungers.add(new Entry(munger.getAspectType(), munger.getMunger())); + } + + public String toString() { + return "WeaverStateInfo(" + typeMungers + ", " + oldStyle + ")"; + } + + + public List getTypeMungers(ResolvedTypeX onType) { + World world = onType.getWorld(); + List ret = new ArrayList(); + for (Iterator i = typeMungers.iterator(); i.hasNext();) { + Entry entry = (Entry) i.next(); + ResolvedTypeX aspectType = world.resolve(entry.aspectType, true); + if (aspectType == ResolvedTypeX.MISSING) { + world.showMessage(IMessage.ERROR, "aspect " + entry.aspectType + + " is needed when using type " + onType, + onType.getSourceLocation(), null); + continue; + } + + ret.add(new BcelTypeMunger(entry.typeMunger, aspectType)); + } + return ret; + } + + public boolean isOldStyle() { + return oldStyle; + } +} diff --git a/weaver/src/org/aspectj/weaver/WeaverStateKind.java b/weaver/src/org/aspectj/weaver/WeaverStateKind.java deleted file mode 100644 index 1960c8d12..000000000 --- a/weaver/src/org/aspectj/weaver/WeaverStateKind.java +++ /dev/null @@ -1,48 +0,0 @@ -/* ******************************************************************* - * 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 - * ******************************************************************/ - - -package org.aspectj.weaver; - -import java.io.DataInputStream; -import java.io.IOException; - -import org.aspectj.util.TypeSafeEnum; - -public class WeaverStateKind extends TypeSafeEnum { - private WeaverStateKind(String name, int key) { - super(name, key); - } - - public static final WeaverStateKind read(DataInputStream s) throws IOException { - byte b = s.readByte(); - switch(b) { - case 0: return Untouched; - case 2: return Woven; - } - throw new RuntimeException("bad WeaverState.Kind: " + b); - } - - - public static final WeaverStateKind Untouched = new WeaverStateKind("Untouched", 0); - public static final WeaverStateKind Woven = new WeaverStateKind("Woven", 2); - - - public byte[] getBytes() { - return new byte[] { getKey(), }; - } - - public boolean isWoven() { - return this == Woven; - } - -} diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index ebfb68170..792201dd0 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -374,5 +374,4 @@ public abstract class World { return ret; } - } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java index 8666df8f5..88b1e9b7c 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java @@ -107,8 +107,7 @@ public class BcelAdvice extends Advice { if (concreteAspect.getWorld().isXnoInline()) return false; //System.err.println("isWoven? " + ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState()); - return BcelWorld.getBcelObjectType(concreteAspect).getLazyClassGen().getWeaverState() - == WeaverStateKind.Woven; + return BcelWorld.getBcelObjectType(concreteAspect).getLazyClassGen().isWoven(); } public void implementOn(Shadow s) { diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index 5595b45db..866502e99 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -61,7 +61,7 @@ import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ShadowMunger; -import org.aspectj.weaver.WeaverStateKind; +import org.aspectj.weaver.WeaverStateInfo; class BcelClassWeaver implements IClassWeaver { @@ -75,7 +75,7 @@ class BcelClassWeaver implements IClassWeaver { List typeMungers) { boolean b = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers).weave(); - //System.err.println(clazz.getClassName() + ", " + clazz.getWeaverState()); + //System.out.println(clazz.getClassName() + ", " + clazz.getType().getWeaverState()); //clazz.print(); return b; } @@ -241,7 +241,7 @@ class BcelClassWeaver implements IClassWeaver { // ---- public boolean weave() { - if (clazz.getWeaverState().isWoven()) { + if (clazz.isWoven()) { world.showMessage(IMessage.ERROR, "class \'" + clazz.getType().getName() + "\' is already woven", ty.getSourceLocation(), null); @@ -309,7 +309,7 @@ class BcelClassWeaver implements IClassWeaver { // finally, if we changed, we add in the introduced methods. if (isChanged) { - clazz.setWeaverState(WeaverStateKind.Woven); + clazz.getOrCreateWeaverStateInfo(); weaveInAddedMethods(); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java index 864f127d6..81d8f1b8c 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java @@ -32,7 +32,7 @@ import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedPointcutDefinition; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; -import org.aspectj.weaver.WeaverStateKind; +import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; import org.aspectj.weaver.patterns.PerClause; @@ -51,7 +51,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { // strangely non-lazy private ResolvedPointcutDefinition[] pointcuts = null; private PerClause perClause = null; - private WeaverStateKind weaverState = null; + private WeaverStateInfo weaverState = null; private List typeMungers = Collections.EMPTY_LIST; private List declares = Collections.EMPTY_LIST; private ResolvedMember[] privilegedAccess = null; @@ -212,18 +212,11 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { unpackAspectAttributes(); } - //XXX we've lost information so that we don't know who wove into this - // class, only that someone did. For better error messages we should - // probably expand the information in weaverState - public boolean isWovenBy(ResolvedTypeX aspectType) { - return weaverState == WeaverStateKind.Woven; - } - - public WeaverStateKind getWeaverState() { + public WeaverStateInfo getWeaverState() { return weaverState; } - public void setWeaverState(WeaverStateKind weaverState) { + void setWeaverState(WeaverStateInfo weaverState) { this.weaverState = weaverState; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index d75d94efe..5b9de1855 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -36,6 +36,7 @@ import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedTypeMunger; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.patterns.Pointcut; @@ -51,21 +52,31 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } public boolean munge(BcelClassWeaver weaver) { + boolean changed = false; + if (munger.getKind() == ResolvedTypeMunger.Field) { - return mungeNewField(weaver, (NewFieldTypeMunger)munger); + changed = mungeNewField(weaver, (NewFieldTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.Method) { - return mungeNewMethod(weaver, (NewMethodTypeMunger)munger); + changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) { - return mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); + changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) { - return mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger); + changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.Constructor) { - return mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger); + changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.Parent) { - return mungeNewParent(weaver, (NewParentTypeMunger)munger); + changed = mungeNewParent(weaver, (NewParentTypeMunger)munger); } else { throw new RuntimeException("unimplemented"); } + + if (changed && munger.changesPublicSignature()) { + WeaverStateInfo info = + weaver.getLazyClassGen().getOrCreateWeaverStateInfo(); + info.addConcreteMunger(this); + } + + return changed; } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java index a5b5c06fb..0c30e8411 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -49,7 +50,7 @@ import org.aspectj.weaver.BCException; import org.aspectj.weaver.Member; import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.TypeX; -import org.aspectj.weaver.WeaverStateKind; +import org.aspectj.weaver.WeaverStateInfo; public final class LazyClassGen { @@ -152,8 +153,13 @@ public final class LazyClassGen { } private void writeBack() { - addAjcInitializers(); + if (myType != null && myType.getWeaverState() != null) { + myGen.addAttribute(BcelAttributes.bcelAttribute( + new AjAttribute.WeaverState(myType.getWeaverState()), + getConstantPoolGen())); + } + addAjcInitializers(); int len = methodGens.size(); myGen.setMethods(new Method[0]); @@ -305,29 +311,17 @@ public final class LazyClassGen { return myGen.getClassName(); } - public WeaverStateKind getWeaverState() { - WeaverStateKind kind = myType.getWeaverState(); - if (kind == null) return WeaverStateKind.Untouched; - return kind; + public boolean isWoven() { + return myType.getWeaverState() != null; } - - public void setWeaverState(WeaverStateKind s) { - Attribute[] attributes = myGen.getAttributes(); - if (attributes != null) { - for (int i = attributes.length - 1; i >=0; i--) { - Attribute a = attributes[i]; - if (a instanceof Unknown) { - Unknown u = (Unknown) a; - if (u.getName().equals(AjAttribute.WeaverState.AttributeName)) { - myGen.removeAttribute(u); - } - } - } - } - myGen.addAttribute(BcelAttributes.bcelAttribute( - new AjAttribute.WeaverState(s), - getConstantPoolGen())); - myType.setWeaverState(s); + + public WeaverStateInfo getOrCreateWeaverStateInfo() { + WeaverStateInfo ret = myType.getWeaverState(); + if (ret != null) return ret; + + ret = new WeaverStateInfo(); + myType.setWeaverState(ret); + return ret; } public InstructionFactory getFactory() { @@ -531,4 +525,5 @@ public final class LazyClassGen { public void forcePublic() { myGen.setAccessFlags(Utility.makePublic(myGen.getAccessFlags())); } + }