| /* ******************************************************************* |
| * Copyright (c) 2005 Contributors. |
| * All rights reserved. |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution and is available at |
| * http://eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Alexandre Vasseur initial implementation |
| * ******************************************************************/ |
| |
| package org.aspectj.weaver; |
| |
| import java.io.IOException; |
| |
| import org.aspectj.weaver.patterns.TypePattern; |
| |
| /** |
| * Type munger for annotation style ITD declare parents. with an interface AND an implementation. Given the aspect that has a field |
| * public static Interface fieldI = ... // impl. we will weave in the Interface' methods and delegate to the aspect public static |
| * field fieldI |
| * |
| * Note: this munger DOES NOT handles the interface addition to the target classes - a regular Parent kinded munger must be added in |
| * coordination. |
| */ |
| public class MethodDelegateTypeMunger extends ResolvedTypeMunger { |
| |
| private final UnresolvedType aspect; |
| |
| private UnresolvedType fieldType; |
| |
| /** |
| * The mixin implementation (which should have a no-argument constructor) |
| */ |
| private final String implClassName; |
| |
| /** |
| * Type pattern this munger applies to |
| */ |
| private final TypePattern typePattern; |
| |
| /** |
| * When created to represent a mixed in method for @DeclareMixin, these hold the signature of the factory method |
| */ |
| private String factoryMethodName; |
| private String factoryMethodSignature; |
| |
| private int bitflags; |
| private static final int REPLACING_EXISTING_METHOD = 0x001; |
| |
| /** |
| * Construct a new type munger for @AspectJ ITD |
| * |
| * @param signature |
| * @param aspect |
| * @param implClassName |
| * @param typePattern |
| */ |
| public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern) { |
| super(MethodDelegate2, signature); |
| this.aspect = aspect; |
| this.typePattern = typePattern; |
| this.implClassName = implClassName; |
| factoryMethodName = ""; |
| factoryMethodSignature = ""; |
| } |
| |
| public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern, |
| String factoryMethodName, String factoryMethodSignature) { |
| super(MethodDelegate2, signature); |
| this.aspect = aspect; |
| this.typePattern = typePattern; |
| this.implClassName = implClassName; |
| this.factoryMethodName = factoryMethodName; |
| this.factoryMethodSignature = factoryMethodSignature; |
| } |
| |
| public boolean equals(Object other) { |
| if (!(other instanceof MethodDelegateTypeMunger)) { |
| return false; |
| } |
| MethodDelegateTypeMunger o = (MethodDelegateTypeMunger) other; |
| return ((o.aspect == null) ? (aspect == null) : aspect.equals(o.aspect)) |
| && ((o.typePattern == null) ? (typePattern == null) : typePattern.equals(o.typePattern)) |
| && ((o.implClassName == null) ? (implClassName == null) : implClassName.equals(o.implClassName)) |
| && ((o.fieldType == null ? (fieldType == null) : fieldType.equals(o.fieldType))) |
| && ((o.factoryMethodName == null) ? (factoryMethodName == null) : factoryMethodName.equals(o.factoryMethodName)) |
| && ((o.factoryMethodSignature == null) ? (factoryMethodSignature == null) : factoryMethodSignature |
| .equals(o.factoryMethodSignature)) && o.bitflags == bitflags; |
| } |
| |
| private volatile int hashCode = 0; |
| |
| public int hashCode() { |
| if (hashCode == 0) { |
| int result = 17; |
| result = 37 * result + ((aspect == null) ? 0 : aspect.hashCode()); |
| result = 37 * result + ((typePattern == null) ? 0 : typePattern.hashCode()); |
| result = 37 * result + ((implClassName == null) ? 0 : implClassName.hashCode()); |
| result = 37 * result + ((fieldType == null) ? 0 : fieldType.hashCode()); |
| result = 37 * result + ((factoryMethodName == null) ? 0 : factoryMethodName.hashCode()); |
| result = 37 * result + ((factoryMethodSignature == null) ? 0 : factoryMethodSignature.hashCode()); |
| result = 37 * result + bitflags; |
| hashCode = result; |
| } |
| return hashCode; |
| } |
| |
| public ResolvedMember getDelegate(ResolvedType targetType) { |
| return AjcMemberMaker.itdAtDeclareParentsField(targetType, fieldType, aspect); |
| } |
| |
| public ResolvedMember getDelegateFactoryMethod(World w) { |
| ResolvedType aspectType = w.resolve(aspect); |
| ResolvedMember[] methods = aspectType.getDeclaredMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| ResolvedMember rm = methods[i]; |
| if (rm.getName().equals(factoryMethodName) && rm.getSignature().equals(factoryMethodSignature)) { |
| return rm; |
| } |
| } |
| return null; |
| } |
| |
| public String getImplClassName() { |
| return implClassName; |
| } |
| |
| public void write(CompressingDataOutputStream s) throws IOException { |
| kind.write(s); |
| signature.write(s); |
| aspect.write(s); |
| s.writeUTF(implClassName); |
| typePattern.write(s); |
| fieldType.write(s); |
| s.writeUTF(factoryMethodName); |
| s.writeUTF(factoryMethodSignature); |
| s.writeInt(bitflags); |
| } |
| |
| public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context, boolean isEnhanced) |
| throws IOException { |
| ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); |
| UnresolvedType aspect = UnresolvedType.read(s); |
| String implClassName = s.readUTF(); |
| TypePattern tp = TypePattern.read(s, context); |
| MethodDelegateTypeMunger typeMunger = new MethodDelegateTypeMunger(signature, aspect, implClassName, tp); |
| UnresolvedType fieldType = null; |
| if (isEnhanced) { |
| fieldType = UnresolvedType.read(s); |
| } else { |
| // a guess... that will work in a lot of cases |
| fieldType = signature.getDeclaringType(); |
| } |
| typeMunger.setFieldType(fieldType); |
| if (isEnhanced) { |
| typeMunger.factoryMethodName = s.readUTF(); |
| typeMunger.factoryMethodSignature = s.readUTF(); |
| typeMunger.bitflags = s.readInt(); |
| } |
| return typeMunger; |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Needed for reweavable |
| * |
| * @return true |
| */ |
| public boolean changesPublicSignature() { |
| return true; |
| } |
| |
| public static class FieldHostTypeMunger extends ResolvedTypeMunger { |
| |
| private final 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 boolean equals(Object other) { |
| if (!(other instanceof FieldHostTypeMunger)) { |
| return false; |
| } |
| FieldHostTypeMunger o = (FieldHostTypeMunger) other; |
| return ((o.aspect == null) ? (aspect == null) : aspect.equals(o.aspect)) |
| && ((o.typePattern == null) ? (typePattern == null) : typePattern.equals(o.typePattern)); |
| } |
| |
| public int hashCode() { |
| int result = 17; |
| result = 37 * result + ((aspect == null) ? 0 : aspect.hashCode()); |
| result = 37 * result + ((typePattern == null) ? 0 : typePattern.hashCode()); |
| return result; |
| } |
| |
| public void write(CompressingDataOutputStream 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; |
| } |
| |
| public boolean existsToSupportShadowMunging() { |
| return true; |
| } |
| } |
| |
| public void setFieldType(UnresolvedType fieldType) { |
| this.fieldType = fieldType; |
| } |
| |
| public boolean specifiesDelegateFactoryMethod() { |
| return factoryMethodName != null && factoryMethodName.length() != 0; |
| } |
| |
| public String getFactoryMethodName() { |
| return factoryMethodName; |
| } |
| |
| public String getFactoryMethodSignature() { |
| return factoryMethodSignature; |
| } |
| |
| public UnresolvedType getAspect() { |
| return aspect; |
| } |
| |
| public boolean existsToSupportShadowMunging() { |
| return true; |
| } |
| |
| public void tagAsReplacingExistingMethod() { |
| bitflags |= REPLACING_EXISTING_METHOD; |
| } |
| |
| public boolean isReplacingExistingMethod() { |
| return (bitflags & REPLACING_EXISTING_METHOD) != 0; |
| } |
| } |