@@ -0,0 +1,158 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.Set; | |||
public abstract class AbstractAnnotationAJ implements AnnotationAJ { | |||
protected final ResolvedType type; | |||
private Set supportedTargets = null; // @target meta annotation | |||
public AbstractAnnotationAJ(ResolvedType type) { | |||
this.type = type; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final ResolvedType getType() { | |||
return type; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getTypeSignature() { | |||
return type.getSignature(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getTypeName() { | |||
return type.getName(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnAnnotationType() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("ANNOTATION_TYPE"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnField() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("FIELD"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnRegularType() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("TYPE"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final void ensureAtTargetInitialized() { | |||
if (supportedTargets == null) { | |||
AnnotationAJ atTargetAnnotation = retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET); | |||
if (atTargetAnnotation == null) { | |||
supportedTargets = Collections.EMPTY_SET; | |||
} else { | |||
supportedTargets = atTargetAnnotation.getTargets(); | |||
} | |||
} | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getValidTargets() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("{"); | |||
for (Iterator iter = supportedTargets.iterator(); iter.hasNext();) { | |||
String evalue = (String) iter.next(); | |||
sb.append(evalue); | |||
if (iter.hasNext()) { | |||
sb.append(","); | |||
} | |||
} | |||
sb.append("}"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean specifiesTarget() { | |||
ensureAtTargetInitialized(); | |||
return !supportedTargets.isEmpty(); | |||
} | |||
/** | |||
* Helper method to retrieve an annotation on an annotation e.g. retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET) | |||
*/ | |||
private final AnnotationAJ retrieveAnnotationOnAnnotation(UnresolvedType requiredAnnotationSignature) { | |||
AnnotationAJ[] annos = type.getAnnotations(); | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationAJ a = annos[i]; | |||
if (a.getTypeSignature().equals(requiredAnnotationSignature.getSignature())) { | |||
return annos[i]; | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean isRuntimeVisible(); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract Set getTargets(); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean hasNameValuePair(String name, String value); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean hasNamedValue(String name); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract String stringify(); | |||
} |
@@ -0,0 +1,128 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Andy Clement - June 2005 - separated out from ResolvedType | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.util.GenericSignature; | |||
import org.aspectj.util.GenericSignatureParser; | |||
import org.aspectj.util.GenericSignature.ClassSignature; | |||
public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDelegate { | |||
private String sourcefilename = UNKNOWN_SOURCE_FILE; | |||
private ISourceContext sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; | |||
protected boolean exposedToWeaver; | |||
protected ReferenceType resolvedTypeX; | |||
protected ClassSignature cachedGenericClassTypeSignature; | |||
// Happens to match Bcel javaClass default of '<Unknown>' | |||
public final static String UNKNOWN_SOURCE_FILE = "<Unknown>"; | |||
public AbstractReferenceTypeDelegate(ReferenceType resolvedTypeX, boolean exposedToWeaver) { | |||
this.resolvedTypeX = resolvedTypeX; | |||
this.exposedToWeaver = exposedToWeaver; | |||
} | |||
public final boolean isClass() { | |||
return !isAspect() && !isInterface(); | |||
} | |||
/** | |||
* Designed to be overriden by EclipseType to disable collection of shadow mungers during pre-weave compilation phase | |||
*/ | |||
public boolean doesNotExposeShadowMungers() { | |||
return false; | |||
} | |||
public boolean isExposedToWeaver() { | |||
return exposedToWeaver; | |||
} | |||
public ReferenceType getResolvedTypeX() { | |||
return resolvedTypeX; | |||
} | |||
public final String getSourcefilename() { | |||
return sourcefilename; | |||
} | |||
public final void setSourcefilename(String sourceFileName) { | |||
sourcefilename = sourceFileName; | |||
if (sourceFileName != null && sourceFileName.equals(AbstractReferenceTypeDelegate.UNKNOWN_SOURCE_FILE)) { | |||
sourcefilename = "Type '" + getResolvedTypeX().getName() + "' (no debug info available)"; | |||
} else { | |||
String pname = getResolvedTypeX().getPackageName(); | |||
if (pname != null) { | |||
sourcefilename = pname.replace('.', '/') + '/' + sourceFileName; | |||
} | |||
} | |||
if (sourcefilename != null && sourceContext instanceof SourceContextImpl) { | |||
((SourceContextImpl) sourceContext).setSourceFileName(sourcefilename); | |||
} | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return getSourceContext().makeSourceLocation(0, 0); | |||
} | |||
public ISourceContext getSourceContext() { | |||
return sourceContext; | |||
} | |||
public void setSourceContext(ISourceContext isc) { | |||
sourceContext = isc; | |||
} | |||
public GenericSignature.ClassSignature getGenericClassTypeSignature() { | |||
if (cachedGenericClassTypeSignature == null) { | |||
String sig = getDeclaredGenericSignature(); | |||
if (sig != null) { | |||
GenericSignatureParser parser = new GenericSignatureParser(); | |||
cachedGenericClassTypeSignature = parser.parseAsClassSignature(sig); | |||
} | |||
} | |||
return cachedGenericClassTypeSignature; | |||
} | |||
protected GenericSignature.FormalTypeParameter[] getFormalTypeParametersFromOuterClass() { | |||
List typeParameters = new ArrayList(); | |||
ReferenceType outer = (ReferenceType) getOuterClass(); | |||
ReferenceTypeDelegate outerDelegate = outer.getDelegate(); | |||
AbstractReferenceTypeDelegate outerObjectType = (AbstractReferenceTypeDelegate) outerDelegate; | |||
if (outerObjectType.isNested()) { | |||
GenericSignature.FormalTypeParameter[] parentParams = outerObjectType.getFormalTypeParametersFromOuterClass(); | |||
for (int i = 0; i < parentParams.length; i++) { | |||
typeParameters.add(parentParams[i]); | |||
} | |||
} | |||
GenericSignature.ClassSignature outerSig = outerObjectType.getGenericClassTypeSignature(); | |||
if (outerSig != null) { | |||
for (int i = 0; i < outerSig.formalTypeParameters.length; i++) { | |||
typeParameters.add(outerSig.formalTypeParameters[i]); | |||
} | |||
} | |||
GenericSignature.FormalTypeParameter[] ret = new GenericSignature.FormalTypeParameter[typeParameters.size()]; | |||
typeParameters.toArray(ret); | |||
return ret; | |||
} | |||
public boolean copySourceContext() { | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,444 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.patterns.AndPointcut; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.TypePattern; | |||
public abstract class Advice extends ShadowMunger { | |||
protected AjAttribute.AdviceAttribute attribute; // the pointcut field is | |||
// ignored | |||
protected AdviceKind kind; // alias of attribute.getKind() | |||
protected Member signature; | |||
protected boolean hasMatchedAtLeastOnce = false; | |||
// not necessarily declaring aspect, this is a semantics change from 1.0 | |||
protected ResolvedType concreteAspect; // null until after concretize | |||
protected List innerCflowEntries = Collections.EMPTY_LIST; // just for | |||
// cflow*Entry | |||
// kinds | |||
protected int nFreeVars; // just for cflow*Entry kinds | |||
protected TypePattern exceptionType; // just for Softener kind | |||
// if we are parameterized, these type may be different to the advice | |||
// signature types | |||
protected UnresolvedType[] bindingParameterTypes; | |||
protected List/* Lint.Kind */suppressedLintKinds = null; // based on | |||
// annotations on | |||
// this advice | |||
public ISourceLocation lastReportedMonitorExitJoinpointLocation = null; | |||
public static Advice makeCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, int nFreeVars, | |||
List innerCflowEntries, ResolvedType inAspect) { | |||
Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry, entry, stackField, 0, | |||
entry); | |||
// 0); | |||
ret.innerCflowEntries = innerCflowEntries; | |||
ret.nFreeVars = nFreeVars; | |||
ret.concreteAspect = inAspect; | |||
return ret; | |||
} | |||
public static Advice makePerCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, ResolvedType inAspect, | |||
List innerCflowEntries) { | |||
Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.PerCflowBelowEntry : AdviceKind.PerCflowEntry, entry, | |||
stackField, 0, entry); | |||
ret.innerCflowEntries = innerCflowEntries; | |||
ret.concreteAspect = inAspect; | |||
return ret; | |||
} | |||
public static Advice makePerObjectEntry(World world, Pointcut entry, boolean isThis, ResolvedType inAspect) { | |||
Advice ret = world.createAdviceMunger(isThis ? AdviceKind.PerThisEntry : AdviceKind.PerTargetEntry, entry, null, 0, entry); | |||
ret.concreteAspect = inAspect; | |||
return ret; | |||
} | |||
// PTWIMPL per type within entry advice is what initializes the aspect | |||
// instance in the matched type | |||
public static Advice makePerTypeWithinEntry(World world, Pointcut p, ResolvedType inAspect) { | |||
Advice ret = world.createAdviceMunger(AdviceKind.PerTypeWithinEntry, p, null, 0, p); | |||
ret.concreteAspect = inAspect; | |||
return ret; | |||
} | |||
public static Advice makeSoftener(World world, Pointcut entry, TypePattern exceptionType, ResolvedType inAspect, | |||
IHasSourceLocation loc) { | |||
Advice ret = world.createAdviceMunger(AdviceKind.Softener, entry, null, 0, loc); | |||
ret.exceptionType = exceptionType; | |||
ret.concreteAspect = inAspect; | |||
// System.out.println("made ret: " + ret + " with " + exceptionType); | |||
return ret; | |||
} | |||
public Advice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) { | |||
super(pointcut, attribute.getStart(), attribute.getEnd(), attribute.getSourceContext()); | |||
this.attribute = attribute; | |||
kind = attribute.getKind(); // alias | |||
this.signature = signature; | |||
if (signature != null) { | |||
bindingParameterTypes = signature.getParameterTypes(); | |||
} else { | |||
bindingParameterTypes = new UnresolvedType[0]; | |||
} | |||
} | |||
public boolean match(Shadow shadow, World world) { | |||
if (super.match(shadow, world)) { | |||
if (shadow.getKind() == Shadow.ExceptionHandler) { | |||
if (kind.isAfter() || kind == AdviceKind.Around) { | |||
world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.ONLY_BEFORE_ON_HANDLER), | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} | |||
} | |||
if (shadow.getKind() == Shadow.SynchronizationLock || shadow.getKind() == Shadow.SynchronizationUnlock) { | |||
if (kind == AdviceKind.Around | |||
// Don't work, see comments in SynchronizationTests | |||
// && attribute.getProceedCallSignatures()!=null | |||
// && attribute.getProceedCallSignatures().length!=0 | |||
) { | |||
world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.NO_AROUND_ON_SYNCHRONIZATION), | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} | |||
} | |||
if (hasExtraParameter() && kind == AdviceKind.AfterReturning) { | |||
ResolvedType resolvedExtraParameterType = getExtraParameterType().resolve(world); | |||
ResolvedType shadowReturnType = shadow.getReturnType().resolve(world); | |||
boolean matches = (resolvedExtraParameterType.isConvertableFrom(shadowReturnType) && shadow.getKind() | |||
.hasReturnValue()); | |||
if (matches && resolvedExtraParameterType.isParameterizedType()) { | |||
maybeIssueUncheckedMatchWarning(resolvedExtraParameterType, shadowReturnType, shadow, world); | |||
} | |||
return matches; | |||
} else if (hasExtraParameter() && kind == AdviceKind.AfterThrowing) { // pr119749 | |||
ResolvedType exceptionType = getExtraParameterType().resolve(world); | |||
if (!exceptionType.isCheckedException()) | |||
return true; | |||
UnresolvedType[] shadowThrows = shadow.getSignature().getExceptions(world); | |||
boolean matches = false; | |||
for (int i = 0; i < shadowThrows.length && !matches; i++) { | |||
ResolvedType type = shadowThrows[i].resolve(world); | |||
if (exceptionType.isAssignableFrom(type)) | |||
matches = true; | |||
} | |||
return matches; | |||
} else if (kind == AdviceKind.PerTargetEntry) { | |||
return shadow.hasTarget(); | |||
} else if (kind == AdviceKind.PerThisEntry) { | |||
return shadow.hasThis(); | |||
} else if (kind == AdviceKind.Around) { | |||
if (shadow.getKind() == Shadow.PreInitialization) { | |||
world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.AROUND_ON_PREINIT), | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} else if (shadow.getKind() == Shadow.Initialization) { | |||
world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.AROUND_ON_INIT), getSourceLocation(), | |||
shadow.getSourceLocation()); | |||
return false; | |||
} else if (shadow.getKind() == Shadow.StaticInitialization | |||
&& shadow.getEnclosingType().resolve(world).isInterface()) { | |||
world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AROUND_ON_INTERFACE_STATICINIT, shadow | |||
.getEnclosingType().getName()), getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} else { | |||
// System.err.println(getSignature().getReturnType() + | |||
// " from " + shadow.getReturnType()); | |||
if (getSignature().getReturnType() == ResolvedType.VOID) { | |||
if (shadow.getReturnType() != ResolvedType.VOID) { | |||
world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.NON_VOID_RETURN, shadow), | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} | |||
} else if (getSignature().getReturnType().equals(UnresolvedType.OBJECT)) { | |||
return true; | |||
} else { | |||
ResolvedType shadowReturnType = shadow.getReturnType().resolve(world); | |||
ResolvedType adviceReturnType = getSignature().getGenericReturnType().resolve(world); | |||
if (shadowReturnType.isParameterizedType() && adviceReturnType.isRawType()) { // Set | |||
// < | |||
// Integer | |||
// > | |||
// and | |||
// Set | |||
ResolvedType shadowReturnGenericType = shadowReturnType.getGenericType(); // Set | |||
ResolvedType adviceReturnGenericType = adviceReturnType.getGenericType(); // Set | |||
if (shadowReturnGenericType.isAssignableFrom(adviceReturnGenericType) | |||
&& world.getLint().uncheckedAdviceConversion.isEnabled()) { | |||
world.getLint().uncheckedAdviceConversion.signal(new String[] { shadow.toString(), | |||
shadowReturnType.getName(), adviceReturnType.getName() }, shadow.getSourceLocation(), | |||
new ISourceLocation[] { getSourceLocation() }); | |||
} | |||
} else if (!shadowReturnType.isAssignableFrom(adviceReturnType)) { | |||
// System.err.println(this + ", " + sourceContext + | |||
// ", " + start); | |||
world.showMessage(IMessage.ERROR, WeaverMessages | |||
.format(WeaverMessages.INCOMPATIBLE_RETURN_TYPE, shadow), getSourceLocation(), shadow | |||
.getSourceLocation()); | |||
return false; | |||
} | |||
} | |||
} | |||
} | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} | |||
/** | |||
* In after returning advice if we are binding the extra parameter to a parameterized type we may not be able to do a type-safe | |||
* conversion. | |||
* | |||
* @param resolvedExtraParameterType the type in the after returning declaration | |||
* @param shadowReturnType the type at the shadow | |||
* @param world | |||
*/ | |||
private void maybeIssueUncheckedMatchWarning(ResolvedType afterReturningType, ResolvedType shadowReturnType, Shadow shadow, | |||
World world) { | |||
boolean inDoubt = !afterReturningType.isAssignableFrom(shadowReturnType); | |||
if (inDoubt && world.getLint().uncheckedArgument.isEnabled()) { | |||
String uncheckedMatchWith = afterReturningType.getSimpleBaseName(); | |||
if (shadowReturnType.isParameterizedType() && (shadowReturnType.getRawType() == afterReturningType.getRawType())) { | |||
uncheckedMatchWith = shadowReturnType.getSimpleName(); | |||
} | |||
if (!Utils.isSuppressing(getSignature().getAnnotations(), "uncheckedArgument")) { | |||
world.getLint().uncheckedArgument.signal(new String[] { afterReturningType.getSimpleName(), uncheckedMatchWith, | |||
afterReturningType.getSimpleBaseName(), shadow.toResolvedString(world) }, getSourceLocation(), | |||
new ISourceLocation[] { shadow.getSourceLocation() }); | |||
} | |||
} | |||
} | |||
// ---- | |||
public AdviceKind getKind() { | |||
return kind; | |||
} | |||
public Member getSignature() { | |||
return signature; | |||
} | |||
public boolean hasExtraParameter() { | |||
return (getExtraParameterFlags() & ExtraArgument) != 0; | |||
} | |||
protected int getExtraParameterFlags() { | |||
return attribute.getExtraParameterFlags(); | |||
} | |||
protected int getExtraParameterCount() { | |||
return countOnes(getExtraParameterFlags() & ParameterMask); | |||
} | |||
public UnresolvedType[] getBindingParameterTypes() { | |||
return bindingParameterTypes; | |||
} | |||
public void setBindingParameterTypes(UnresolvedType[] types) { | |||
bindingParameterTypes = types; | |||
} | |||
public static int countOnes(int bits) { | |||
int ret = 0; | |||
while (bits != 0) { | |||
if ((bits & 1) != 0) | |||
ret += 1; | |||
bits = bits >> 1; | |||
} | |||
return ret; | |||
} | |||
public int getBaseParameterCount() { | |||
return getSignature().getParameterTypes().length - getExtraParameterCount(); | |||
} | |||
public String[] getBaseParameterNames(World world) { | |||
String[] allNames = getSignature().getParameterNames(world); | |||
int extras = getExtraParameterCount(); | |||
if (extras == 0) | |||
return allNames; | |||
String[] result = new String[getBaseParameterCount()]; | |||
for (int i = 0; i < result.length; i++) { | |||
result[i] = allNames[i]; | |||
} | |||
return result; | |||
} | |||
public UnresolvedType getExtraParameterType() { | |||
if (!hasExtraParameter()) | |||
return ResolvedType.MISSING; | |||
if (signature instanceof ResolvedMember) { | |||
if (getConcreteAspect().isAnnotationStyleAspect()) { | |||
// bug 122742 - if we're an annotation style aspect then one | |||
// of the extra parameters could be JoinPoint which we want | |||
// to ignore | |||
int baseParmCnt = getBaseParameterCount(); | |||
UnresolvedType[] genericParameterTypes = ((ResolvedMember) signature).getGenericParameterTypes(); | |||
while ((baseParmCnt + 1 < genericParameterTypes.length) | |||
&& (genericParameterTypes[baseParmCnt].equals(AjcMemberMaker.TYPEX_JOINPOINT) | |||
|| genericParameterTypes[baseParmCnt].equals(AjcMemberMaker.TYPEX_STATICJOINPOINT) || genericParameterTypes[baseParmCnt] | |||
.equals(AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT))) { | |||
baseParmCnt++; | |||
} | |||
return ((ResolvedMember) signature).getGenericParameterTypes()[baseParmCnt]; | |||
} | |||
return ((ResolvedMember) signature).getGenericParameterTypes()[getBaseParameterCount()]; | |||
} else { | |||
return signature.getParameterTypes()[getBaseParameterCount()]; | |||
} | |||
} | |||
public UnresolvedType getDeclaringAspect() { | |||
return getOriginalSignature().getDeclaringType(); | |||
} | |||
protected Member getOriginalSignature() { | |||
return signature; | |||
} | |||
protected String extraParametersToString() { | |||
if (getExtraParameterFlags() == 0) { | |||
return ""; | |||
} else { | |||
return "(extraFlags: " + getExtraParameterFlags() + ")"; | |||
} | |||
} | |||
public Pointcut getPointcut() { | |||
return pointcut; | |||
} | |||
// ---- | |||
/** | |||
* @param fromType is guaranteed to be a non-abstract aspect | |||
* @param clause has been concretized at a higher level | |||
*/ | |||
public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) { | |||
// assert !fromType.isAbstract(); | |||
Pointcut p = pointcut.concretize(fromType, getDeclaringType(), signature.getArity(), this); | |||
if (clause != null) { | |||
Pointcut oldP = p; | |||
p = new AndPointcut(clause, p); | |||
p.copyLocationFrom(oldP); | |||
p.state = Pointcut.CONCRETE; | |||
// FIXME ? ATAJ copy unbound bindings to ignore | |||
p.m_ignoreUnboundBindingForNames = oldP.m_ignoreUnboundBindingForNames; | |||
} | |||
Advice munger = world.getWeavingSupport().createAdviceMunger(attribute, p, signature); | |||
munger.concreteAspect = fromType; | |||
munger.bindingParameterTypes = bindingParameterTypes; | |||
munger.setDeclaringType(getDeclaringType()); | |||
// System.err.println("concretizing here " + p + " with clause " + | |||
// clause); | |||
return munger; | |||
} | |||
// ---- from object | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("(").append(getKind()).append(extraParametersToString()); | |||
sb.append(": ").append(pointcut).append("->").append(signature).append(")"); | |||
return sb.toString(); | |||
// return "(" | |||
// + getKind() | |||
// + extraParametersToString() | |||
// + ": " | |||
// + pointcut | |||
// + "->" | |||
// + signature | |||
// + ")"; | |||
} | |||
// XXX this perhaps ought to take account of the other fields in advice ... | |||
public boolean equals(Object other) { | |||
if (!(other instanceof Advice)) | |||
return false; | |||
Advice o = (Advice) other; | |||
return o.kind.equals(kind) && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)) | |||
&& ((o.signature == null) ? (signature == null) : o.signature.equals(signature)); | |||
// && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? | |||
// (getSourceLocation() == null) | |||
// : o.getSourceLocation().equals(getSourceLocation())) | |||
// : true) // pr134471 - remove when handles are improved | |||
// // to be independent of location | |||
// ; | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37 * result + kind.hashCode(); | |||
result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode()); | |||
result = 37 * result + ((signature == null) ? 0 : signature.hashCode()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
// ---- fields | |||
public static final int ExtraArgument = 1; | |||
public static final int ThisJoinPoint = 2; | |||
public static final int ThisJoinPointStaticPart = 4; | |||
public static final int ThisEnclosingJoinPointStaticPart = 8; | |||
public static final int ParameterMask = 0xf; | |||
public static final int CanInline = 0x40; | |||
// for testing only | |||
public void setLexicalPosition(int lexicalPosition) { | |||
start = lexicalPosition; | |||
} | |||
public ResolvedType getConcreteAspect() { | |||
return concreteAspect; | |||
} | |||
public boolean hasMatchedSomething() { | |||
return hasMatchedAtLeastOnce; | |||
} | |||
public void setHasMatchedSomething(boolean hasMatchedSomething) { | |||
hasMatchedAtLeastOnce = hasMatchedSomething; | |||
} | |||
public abstract boolean hasDynamicTests(); | |||
} |
@@ -0,0 +1,117 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.IOException; | |||
import org.aspectj.util.TypeSafeEnum; | |||
/** | |||
* The five kinds of advice in AspectJ. | |||
* | |||
* @author Erik Hilsdale | |||
* @author Jim Hugunin | |||
*/ | |||
public class AdviceKind extends TypeSafeEnum { | |||
private int precedence; | |||
private boolean isAfter; | |||
private boolean isCflow; | |||
public AdviceKind(String name, int key, int precedence, boolean isAfter, boolean isCflow) { | |||
super(name, key); | |||
this.precedence = precedence; | |||
this.isAfter = isAfter; | |||
this.isCflow = isCflow; | |||
} | |||
public static AdviceKind read(VersionedDataInputStream s) throws IOException { | |||
int key = s.readByte(); | |||
switch(key) { | |||
case 1: return Before; | |||
case 2: return After; | |||
case 3: return AfterThrowing; | |||
case 4: return AfterReturning; | |||
case 5: return Around; | |||
case 6: return CflowEntry; | |||
case 7: return CflowBelowEntry; | |||
case 8: return InterInitializer; | |||
case 9: return PerCflowEntry; | |||
case 10: return PerCflowBelowEntry; | |||
case 11: return PerThisEntry; | |||
case 12: return PerTargetEntry; | |||
case 13: return Softener; | |||
case 14: return PerTypeWithinEntry; | |||
} | |||
throw new RuntimeException("unimplemented kind: " + key); | |||
} | |||
public static final AdviceKind Before = new AdviceKind("before", 1, 0, false, false); | |||
public static final AdviceKind After = new AdviceKind("after", 2, 0, true, false); | |||
public static final AdviceKind AfterThrowing = new AdviceKind("afterThrowing", 3, 0, true, false); | |||
public static final AdviceKind AfterReturning = new AdviceKind("afterReturning", 4, 0, true, false); | |||
public static final AdviceKind Around = new AdviceKind("around", 5, 0, false, false); | |||
// these kinds can't be declared, but are used by the weaver | |||
public static final AdviceKind CflowEntry = new AdviceKind("cflowEntry", 6, 1, false, true); | |||
public static final AdviceKind CflowBelowEntry = new AdviceKind("cflowBelowEntry", 7, -1, false, true); //XXX resolve precednece with the below | |||
public static final AdviceKind InterInitializer = new AdviceKind("interInitializer", 8, -2, false, false); | |||
public static final AdviceKind PerCflowEntry = new AdviceKind("perCflowEntry", 9, 1, false, true); | |||
public static final AdviceKind PerCflowBelowEntry = new AdviceKind("perCflowBelowEntry", 10, -1, false, true); | |||
public static final AdviceKind PerThisEntry = new AdviceKind("perThisEntry", 11, 1, false, false); | |||
public static final AdviceKind PerTargetEntry = new AdviceKind("perTargetEntry", 12, 1, false, false); | |||
public static final AdviceKind Softener = new AdviceKind("softener", 13, 1, false, false); | |||
// PTWIMPL Advice representing when aspect should be initialized | |||
public static final AdviceKind PerTypeWithinEntry = new AdviceKind("perTypeWithinEntry",14,1,false,false); | |||
public static AdviceKind stringToKind(String s) { | |||
if (s.equals(Before.getName())) return Before; | |||
if (s.equals(After.getName())) return After; | |||
if (s.equals(AfterThrowing.getName())) return AfterThrowing; | |||
if (s.equals(AfterReturning.getName())) return AfterReturning; | |||
if (s.equals(Around.getName())) return Around; | |||
throw new IllegalArgumentException("unknown kind: " + "\"" + s + "\""); | |||
} | |||
public boolean isAfter() { | |||
return this.isAfter; | |||
} | |||
public boolean isCflow() { | |||
return this.isCflow; | |||
} | |||
public int getPrecedence() { | |||
return precedence; | |||
} | |||
public boolean isPerEntry() { | |||
return | |||
this == PerCflowEntry || this == PerCflowBelowEntry || | |||
this == PerThisEntry || this == PerTargetEntry || | |||
this == PerTypeWithinEntry; // PTWIMPL Allow for PTW case | |||
} | |||
public boolean isPerObjectEntry() { | |||
return this == PerThisEntry || this == PerTargetEntry; | |||
} | |||
} |
@@ -0,0 +1,699 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.EOFException; | |||
import java.io.IOException; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.bridge.Version; | |||
import org.aspectj.util.FileUtil; | |||
import org.aspectj.weaver.patterns.Declare; | |||
import org.aspectj.weaver.patterns.IScope; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* These attributes are written to and read from .class files (see the JVM | |||
* spec). | |||
* | |||
* <p> | |||
* Each member or type can have a number of AjAttributes. Each such attribute is | |||
* in 1-1 correspondence with an Unknown bcel attribute. Creating one of these | |||
* does NOTHING to the underlying thing, so if you really want to add an | |||
* attribute to a particular thing, well, you'd better actually do that. | |||
* | |||
* @author Erik Hilsdale | |||
* @author Jim Hugunin | |||
*/ | |||
public abstract class AjAttribute { | |||
public static final String AttributePrefix = "org.aspectj.weaver"; | |||
protected abstract void write(DataOutputStream s) throws IOException; | |||
public abstract String getNameString(); | |||
public char[] getNameChars() { | |||
return getNameString().toCharArray(); | |||
} | |||
/** | |||
* Just writes the contents | |||
*/ | |||
public byte[] getBytes() { | |||
try { | |||
ByteArrayOutputStream b0 = new ByteArrayOutputStream(); | |||
DataOutputStream s0 = new DataOutputStream(b0); | |||
write(s0); | |||
return b0.toByteArray(); | |||
} catch (IOException e) { | |||
// shouldn't happen with ByteArrayOutputStreams | |||
throw new RuntimeException("sanity check"); | |||
} | |||
} | |||
/** | |||
* Writes the full attribute, i.e. name_index, length, and contents | |||
*/ | |||
public byte[] getAllBytes(short nameIndex) { | |||
try { | |||
byte[] bytes = getBytes(); | |||
ByteArrayOutputStream b0 = new ByteArrayOutputStream(); | |||
DataOutputStream s0 = new DataOutputStream(b0); | |||
s0.writeShort(nameIndex); | |||
s0.writeInt(bytes.length); | |||
s0.write(bytes); | |||
return b0.toByteArray(); | |||
} catch (IOException e) { | |||
// shouldn't happen with ByteArrayOutputStreams | |||
throw new RuntimeException("sanity check"); | |||
} | |||
} | |||
public static AjAttribute read(AjAttribute.WeaverVersionInfo v, String name, byte[] bytes, ISourceContext context, World w) { | |||
try { | |||
if (bytes == null) | |||
bytes = new byte[0]; | |||
VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(bytes)); | |||
s.setVersion(v); | |||
if (name.equals(Aspect.AttributeName)) { | |||
return new Aspect(PerClause.readPerClause(s, context)); | |||
} else if (name.equals(MethodDeclarationLineNumberAttribute.AttributeName)) { | |||
return MethodDeclarationLineNumberAttribute.read(s); | |||
} else if (name.equals(WeaverState.AttributeName)) { | |||
return new WeaverState(WeaverStateInfo.read(s, context)); | |||
} else if (name.equals(WeaverVersionInfo.AttributeName)) { | |||
return WeaverVersionInfo.read(s); | |||
} else if (name.equals(AdviceAttribute.AttributeName)) { | |||
AdviceAttribute aa = AdviceAttribute.read(s, context); | |||
aa.getPointcut().check(context, w); | |||
return aa; | |||
} else if (name.equals(PointcutDeclarationAttribute.AttributeName)) { | |||
PointcutDeclarationAttribute pda = new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context)); | |||
pda.pointcutDef.getPointcut().check(context, w); | |||
return pda; | |||
} else if (name.equals(TypeMunger.AttributeName)) { | |||
return new TypeMunger(ResolvedTypeMunger.read(s, context)); | |||
} else if (name.equals(AjSynthetic.AttributeName)) { | |||
return new AjSynthetic(); | |||
} else if (name.equals(DeclareAttribute.AttributeName)) { | |||
return new DeclareAttribute(Declare.read(s, context)); | |||
} else if (name.equals(PrivilegedAttribute.AttributeName)) { | |||
return PrivilegedAttribute.read(s, context); | |||
} else if (name.equals(SourceContextAttribute.AttributeName)) { | |||
return SourceContextAttribute.read(s); | |||
} else if (name.equals(EffectiveSignatureAttribute.AttributeName)) { | |||
return EffectiveSignatureAttribute.read(s, context); | |||
} else { | |||
// We have to tell the user about this... | |||
if (w == null || w.getMessageHandler() == null) | |||
throw new BCException("unknown attribute" + name); | |||
w.getMessageHandler().handleMessage(MessageUtil.warn("unknown attribute encountered " + name)); | |||
return null; | |||
} | |||
} catch (BCException e) { | |||
throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e); | |||
} catch (IOException e) { | |||
throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e); | |||
} | |||
} | |||
// ---- | |||
/** | |||
* Synthetic members should have NO advice put on them or on their contents. | |||
* This attribute is currently unused as we consider all members starting | |||
* with NameMangler.PREFIX to automatically be synthetic. As we use this we | |||
* might find that we want multiple kinds of synthetic. In particular, if we | |||
* want to treat the call to a synthetic getter (say, of an introduced | |||
* field) as a field reference itself, then a method might want a particular | |||
* kind of AjSynthetic attribute that also includes a signature of what it | |||
* stands for. | |||
*/ | |||
public static class AjSynthetic extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.AjSynthetic"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
// private ResolvedTypeMunger munger; | |||
public AjSynthetic() { | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
} | |||
} | |||
public static class TypeMunger extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.TypeMunger"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final ResolvedTypeMunger munger; | |||
public TypeMunger(ResolvedTypeMunger munger) { | |||
this.munger = munger; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
munger.write(s); | |||
} | |||
public ConcreteTypeMunger reify(World world, ResolvedType aspectType) { | |||
return world.getWeavingSupport().concreteTypeMunger(munger, aspectType); | |||
} | |||
} | |||
public static class WeaverState extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.WeaverState"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final WeaverStateInfo kind; | |||
public WeaverState(WeaverStateInfo kind) { | |||
this.kind = kind; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
} | |||
public WeaverStateInfo reify() { | |||
return kind; | |||
} | |||
} | |||
public static class WeaverVersionInfo extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.WeaverVersion"; | |||
// If you change the format of an AspectJ class file, you have two | |||
// options: | |||
// - changing the minor version means you have not added anything that | |||
// prevents | |||
// previous versions of the weaver from operating (e.g. | |||
// MethodDeclarationLineNumber attribute) | |||
// - changing the major version means you have added something that | |||
// prevents previous | |||
// versions of the weaver from operating correctly. | |||
// | |||
// The user will get a warning for any org.aspectj.weaver attributes the | |||
// weaver does | |||
// not recognize. | |||
// When we don't know ... (i.e. pre 1.2.1) | |||
public final static short WEAVER_VERSION_MAJOR_UNKNOWN = 0; | |||
public final static short WEAVER_VERSION_MINOR_UNKNOWN = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.2.1 | |||
public final static short WEAVER_VERSION_MAJOR_AJ121 = 1; | |||
public final static short WEAVER_VERSION_MINOR_AJ121 = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.5.0 | |||
public final static short WEAVER_VERSION_MAJOR_AJ150M4 = 3; | |||
public final static short WEAVER_VERSION_MAJOR_AJ150 = 2; | |||
public final static short WEAVER_VERSION_MINOR_AJ150 = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.6.0 | |||
public final static short WEAVER_VERSION_MAJOR_AJ160M2 = 5; | |||
public final static short WEAVER_VERSION_MAJOR_AJ160 = 4; | |||
public final static short WEAVER_VERSION_MINOR_AJ160 = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.6.1 | |||
public final static short WEAVER_VERSION_MAJOR_AJ161 = 6; // annotation | |||
// value | |||
// binding | |||
public final static short WEAVER_VERSION_MINOR_AJ161 = 0; | |||
// These are the weaver major/minor versions for *this* weaver | |||
private final static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ161; | |||
private final static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ161; | |||
public final static WeaverVersionInfo UNKNOWN = new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN, | |||
WEAVER_VERSION_MINOR_UNKNOWN); | |||
public final static WeaverVersionInfo CURRENT = new WeaverVersionInfo(CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR); | |||
// These are the versions read in from a particular class file. | |||
private final short major_version; | |||
private final short minor_version; | |||
private long buildstamp = Version.NOTIME; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
// Default ctor uses the current version numbers | |||
public WeaverVersionInfo() { | |||
major_version = CURRENT_VERSION_MAJOR; | |||
minor_version = CURRENT_VERSION_MINOR; | |||
} | |||
public WeaverVersionInfo(short major, short minor) { | |||
major_version = major; | |||
minor_version = minor; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeShort(CURRENT_VERSION_MAJOR); | |||
s.writeShort(CURRENT_VERSION_MINOR); | |||
s.writeLong(Version.getTime()); // build used to construct the | |||
// class... | |||
} | |||
public static WeaverVersionInfo read(VersionedDataInputStream s) throws IOException { | |||
short major = s.readShort(); | |||
short minor = s.readShort(); | |||
WeaverVersionInfo wvi = new WeaverVersionInfo(major, minor); | |||
if (s.getMajorVersion() >= WEAVER_VERSION_MAJOR_AJ150M4) { | |||
long stamp = 0; | |||
try { | |||
stamp = s.readLong(); | |||
wvi.setBuildstamp(stamp); | |||
} catch (EOFException eof) { | |||
// didnt find that build stamp - its not the end of the | |||
// world | |||
} | |||
} | |||
return wvi; | |||
} | |||
public short getMajorVersion() { | |||
return major_version; | |||
} | |||
public short getMinorVersion() { | |||
return minor_version; | |||
} | |||
public static short getCurrentWeaverMajorVersion() { | |||
return CURRENT_VERSION_MAJOR; | |||
} | |||
public static short getCurrentWeaverMinorVersion() { | |||
return CURRENT_VERSION_MINOR; | |||
} | |||
public void setBuildstamp(long stamp) { | |||
buildstamp = stamp; | |||
} | |||
public long getBuildstamp() { | |||
return buildstamp; | |||
} | |||
public String toString() { | |||
return major_version + "." + minor_version; | |||
} | |||
public static String toCurrentVersionString() { | |||
return CURRENT_VERSION_MAJOR + "." + CURRENT_VERSION_MINOR; | |||
} | |||
} | |||
public static class SourceContextAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.SourceContext"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final String sourceFileName; | |||
private final int[] lineBreaks; | |||
public SourceContextAttribute(String sourceFileName, int[] lineBreaks) { | |||
this.sourceFileName = sourceFileName; | |||
this.lineBreaks = lineBreaks; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeUTF(sourceFileName); | |||
FileUtil.writeIntArray(lineBreaks, s); | |||
} | |||
public static SourceContextAttribute read(VersionedDataInputStream s) throws IOException { | |||
return new SourceContextAttribute(s.readUTF(), FileUtil.readIntArray(s)); | |||
} | |||
public int[] getLineBreaks() { | |||
return lineBreaks; | |||
} | |||
public String getSourceFileName() { | |||
return sourceFileName; | |||
} | |||
} | |||
public static class MethodDeclarationLineNumberAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.MethodDeclarationLineNumber"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final int lineNumber; | |||
// AV: added in 1.5 M3 thus handling cases where we don't have that | |||
// information | |||
private final int offset; | |||
public MethodDeclarationLineNumberAttribute(int line, int offset) { | |||
lineNumber = line; | |||
this.offset = offset; | |||
} | |||
public int getLineNumber() { | |||
return lineNumber; | |||
} | |||
public int getOffset() { | |||
return offset; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeInt(lineNumber); | |||
s.writeInt(offset); | |||
} | |||
public static MethodDeclarationLineNumberAttribute read(VersionedDataInputStream s) throws IOException { | |||
int line = s.readInt(); | |||
int offset = 0; | |||
if (s.available() > 0) { | |||
offset = s.readInt(); | |||
} | |||
return new MethodDeclarationLineNumberAttribute(line, offset); | |||
} | |||
public String toString() { | |||
return AttributeName + ": " + lineNumber + ":" + offset; | |||
} | |||
} | |||
public static class PointcutDeclarationAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.PointcutDeclaration"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final ResolvedPointcutDefinition pointcutDef; | |||
public PointcutDeclarationAttribute(ResolvedPointcutDefinition pointcutDef) { | |||
this.pointcutDef = pointcutDef; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
pointcutDef.write(s); | |||
} | |||
public ResolvedPointcutDefinition reify() { | |||
return pointcutDef; | |||
} | |||
} | |||
public static class DeclareAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Declare"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final Declare declare; | |||
public DeclareAttribute(Declare declare) { | |||
this.declare = declare; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
declare.write(s); | |||
} | |||
public Declare getDeclare() { | |||
return declare; | |||
} | |||
} | |||
public static class AdviceAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Advice"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final AdviceKind kind; | |||
private final Pointcut pointcut; | |||
private final int extraParameterFlags; | |||
private final int start; | |||
private final int end; | |||
private final ISourceContext sourceContext; | |||
// these are only used by around advice | |||
private boolean proceedInInners; | |||
private ResolvedMember[] proceedCallSignatures; // size == # of proceed | |||
// calls in body | |||
private boolean[] formalsUnchangedToProceed; // size == formals.size | |||
private UnresolvedType[] declaredExceptions; | |||
/** | |||
* @param lexicalPosition must be greater than the lexicalPosition of | |||
* any advice declared before this one in an aspect, | |||
* otherwise, it can be any value. | |||
*/ | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end, | |||
ISourceContext sourceContext) { | |||
this.kind = kind; | |||
this.pointcut = pointcut; | |||
extraParameterFlags = extraArgumentFlags; | |||
this.start = start; | |||
this.end = end; | |||
this.sourceContext = sourceContext; | |||
// XXX put this back when testing works better (or fails better) | |||
// if (kind == AdviceKind.Around) throw new | |||
// IllegalArgumentException("not for around"); | |||
} | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end, | |||
ISourceContext sourceContext, boolean proceedInInners, ResolvedMember[] proceedCallSignatures, | |||
boolean[] formalsUnchangedToProceed, UnresolvedType[] declaredExceptions) { | |||
this.kind = kind; | |||
this.pointcut = pointcut; | |||
extraParameterFlags = extraArgumentFlags; | |||
this.start = start; | |||
this.end = end; | |||
this.sourceContext = sourceContext; | |||
if (kind != AdviceKind.Around) | |||
throw new IllegalArgumentException("only for around"); | |||
this.proceedInInners = proceedInInners; | |||
this.proceedCallSignatures = proceedCallSignatures; | |||
this.formalsUnchangedToProceed = formalsUnchangedToProceed; | |||
this.declaredExceptions = declaredExceptions; | |||
} | |||
public static AdviceAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
AdviceKind kind = AdviceKind.read(s); | |||
if (kind == AdviceKind.Around) { | |||
return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context, s | |||
.readBoolean(), ResolvedMemberImpl.readResolvedMemberArray(s, context), FileUtil.readBooleanArray(s), | |||
UnresolvedType.readArray(s)); | |||
} else { | |||
return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context); | |||
} | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
pointcut.write(s); | |||
s.writeByte(extraParameterFlags); | |||
s.writeInt(start); | |||
s.writeInt(end); | |||
if (kind == AdviceKind.Around) { | |||
s.writeBoolean(proceedInInners); | |||
ResolvedMemberImpl.writeArray(proceedCallSignatures, s); | |||
FileUtil.writeBooleanArray(formalsUnchangedToProceed, s); | |||
UnresolvedType.writeArray(declaredExceptions, s); | |||
} | |||
} | |||
public Advice reify(Member signature, World world) { | |||
return world.getWeavingSupport().createAdviceMunger(this, pointcut, signature); | |||
} | |||
public String toString() { | |||
return "AdviceAttribute(" + kind + ", " + pointcut + ", " + extraParameterFlags + ", " + start + ")"; | |||
} | |||
public int getExtraParameterFlags() { | |||
return extraParameterFlags; | |||
} | |||
public AdviceKind getKind() { | |||
return kind; | |||
} | |||
public Pointcut getPointcut() { | |||
return pointcut; | |||
} | |||
public UnresolvedType[] getDeclaredExceptions() { | |||
return declaredExceptions; | |||
} | |||
public boolean[] getFormalsUnchangedToProceed() { | |||
return formalsUnchangedToProceed; | |||
} | |||
public ResolvedMember[] getProceedCallSignatures() { | |||
return proceedCallSignatures; | |||
} | |||
public boolean isProceedInInners() { | |||
return proceedInInners; | |||
} | |||
public int getEnd() { | |||
return end; | |||
} | |||
public ISourceContext getSourceContext() { | |||
return sourceContext; | |||
} | |||
public int getStart() { | |||
return start; | |||
} | |||
} | |||
public static class Aspect extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Aspect"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final PerClause perClause; | |||
private IScope resolutionScope; | |||
public Aspect(PerClause perClause) { | |||
this.perClause = perClause; | |||
} | |||
public PerClause reify(ResolvedType inAspect) { | |||
// XXXperClause.concretize(inAspect); | |||
return perClause; | |||
} | |||
public PerClause reifyFromAtAspectJ(ResolvedType inAspect) { | |||
perClause.resolve(resolutionScope); | |||
return perClause; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
perClause.write(s); | |||
} | |||
public void setResolutionScope(IScope binding) { | |||
resolutionScope = binding; | |||
} | |||
} | |||
public static class PrivilegedAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Privileged"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final ResolvedMember[] accessedMembers; | |||
public PrivilegedAttribute(ResolvedMember[] accessedMembers) { | |||
this.accessedMembers = accessedMembers; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
ResolvedMemberImpl.writeArray(accessedMembers, s); | |||
} | |||
public ResolvedMember[] getAccessedMembers() { | |||
return accessedMembers; | |||
} | |||
public static PrivilegedAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
return new PrivilegedAttribute(ResolvedMemberImpl.readResolvedMemberArray(s, context)); | |||
} | |||
} | |||
public static class EffectiveSignatureAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.EffectiveSignature"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private final ResolvedMember effectiveSignature; | |||
private final Shadow.Kind shadowKind; | |||
private final boolean weaveBody; | |||
public EffectiveSignatureAttribute(ResolvedMember effectiveSignature, Shadow.Kind shadowKind, boolean weaveBody) { | |||
this.effectiveSignature = effectiveSignature; | |||
this.shadowKind = shadowKind; | |||
this.weaveBody = weaveBody; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
effectiveSignature.write(s); | |||
shadowKind.write(s); | |||
s.writeBoolean(weaveBody); | |||
} | |||
public static EffectiveSignatureAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
return new EffectiveSignatureAttribute(ResolvedMemberImpl.readResolvedMember(s, context), Shadow.Kind.read(s), s | |||
.readBoolean()); | |||
} | |||
public ResolvedMember getEffectiveSignature() { | |||
return effectiveSignature; | |||
} | |||
public String toString() { | |||
return "EffectiveSignatureAttribute(" + effectiveSignature + ", " + shadowKind + ")"; | |||
} | |||
public Shadow.Kind getShadowKind() { | |||
return shadowKind; | |||
} | |||
public boolean isWeaveBody() { | |||
return weaveBody; | |||
} | |||
} | |||
} |
@@ -0,0 +1,621 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
//import org.aspectj.weaver.ResolvedType.Name; | |||
public class AjcMemberMaker { | |||
private static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; | |||
private static final int PRIVATE_STATIC = Modifier.PRIVATE | Modifier.STATIC; | |||
private static final int PUBLIC_STATIC = Modifier.PUBLIC | Modifier.STATIC; | |||
private static final int BRIDGE = 0x0040; | |||
private static final int VISIBILITY = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; | |||
public static final UnresolvedType CFLOW_STACK_TYPE = UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE); | |||
public static final UnresolvedType AROUND_CLOSURE_TYPE = UnresolvedType | |||
.forSignature("Lorg/aspectj/runtime/internal/AroundClosure;"); | |||
public static final UnresolvedType CONVERSIONS_TYPE = UnresolvedType.forSignature("Lorg/aspectj/runtime/internal/Conversions;"); | |||
public static final UnresolvedType NO_ASPECT_BOUND_EXCEPTION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/NoAspectBoundException;"); | |||
public static ResolvedMember ajcPreClinitMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, NameMangler.AJC_PRE_CLINIT_NAME, "()V"); | |||
} | |||
public static ResolvedMember ajcPostClinitMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, NameMangler.AJC_POST_CLINIT_NAME, "()V"); | |||
} | |||
public static Member noAspectBoundExceptionInit() { | |||
return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>", "()V"); | |||
} | |||
public static Member noAspectBoundExceptionInit2() { | |||
return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>", | |||
"(Ljava/lang/String;Ljava/lang/Throwable;)V"); | |||
} | |||
public static Member noAspectBoundExceptionInitWithCause() { | |||
return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>", | |||
"(Ljava/lang/String;Ljava/lang/Throwable;)V"); | |||
} | |||
public static ResolvedMember perCflowPush(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, NameMangler.PERCFLOW_PUSH_METHOD, "()V"); | |||
} | |||
public static ResolvedMember perCflowField(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, PUBLIC_STATIC_FINAL, NameMangler.PERCFLOW_FIELD_NAME, | |||
CFLOW_STACK_TYPE.getSignature()); | |||
} | |||
public static ResolvedMember perSingletonField(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, PUBLIC_STATIC_FINAL, NameMangler.PERSINGLETON_FIELD_NAME, | |||
declaringType.getSignature()); | |||
} | |||
public static ResolvedMember initFailureCauseField(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, PRIVATE_STATIC, NameMangler.INITFAILURECAUSE_FIELD_NAME, | |||
UnresolvedType.THROWABLE.getSignature()); | |||
} | |||
public static ResolvedMember perObjectField(UnresolvedType declaringType, ResolvedType aspectType) { | |||
int modifiers = Modifier.PRIVATE; | |||
if (!UnresolvedType.SERIALIZABLE.resolve(aspectType.getWorld()).isAssignableFrom(aspectType)) { | |||
modifiers |= Modifier.TRANSIENT; | |||
} | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, aspectType, NameMangler | |||
.perObjectInterfaceField(aspectType), UnresolvedType.NONE); | |||
} | |||
// PTWIMPL ResolvedMember for aspect instance field, declared in matched type | |||
public static ResolvedMember perTypeWithinField(UnresolvedType declaringType, ResolvedType aspectType) { | |||
int modifiers = Modifier.PRIVATE | Modifier.STATIC; | |||
if (!isSerializableAspect(aspectType)) { | |||
modifiers |= Modifier.TRANSIENT; | |||
} | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, aspectType, NameMangler | |||
.perTypeWithinFieldForTarget(aspectType), UnresolvedType.NONE); | |||
} | |||
// PTWIMPL ResolvedMember for type instance field, declared in aspect | |||
// (holds typename for which aspect instance exists) | |||
public static ResolvedMember perTypeWithinWithinTypeField(UnresolvedType declaringType, ResolvedType aspectType) { | |||
int modifiers = Modifier.PRIVATE; | |||
if (!isSerializableAspect(aspectType)) { | |||
modifiers |= Modifier.TRANSIENT; | |||
} | |||
return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, UnresolvedType.JAVA_LANG_STRING, | |||
NameMangler.PERTYPEWITHIN_WITHINTYPEFIELD, UnresolvedType.NONE); | |||
} | |||
private static boolean isSerializableAspect(ResolvedType aspectType) { | |||
return UnresolvedType.SERIALIZABLE.resolve(aspectType.getWorld()).isAssignableFrom(aspectType); | |||
} | |||
public static ResolvedMember perObjectBind(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, NameMangler.PEROBJECT_BIND_METHOD, | |||
"(Ljava/lang/Object;)V"); | |||
} | |||
// PTWIMPL ResolvedMember for getInstance() method, declared in aspect | |||
public static ResolvedMember perTypeWithinGetInstance(UnresolvedType declaringType) { | |||
// private static a.X ajc$getInstance(java.lang.Class) | |||
ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, declaringType, // return value | |||
NameMangler.PERTYPEWITHIN_GETINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType.JAVA_LANG_CLASS }); | |||
return rm; | |||
} | |||
// PTWIMPL ResolvedMember for getWithinTypeName() method | |||
public static ResolvedMember perTypeWithinGetWithinTypeNameMethod(UnresolvedType declaringType, boolean inJava5Mode) { | |||
// public String getWithinTypeName() | |||
ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, Modifier.PUBLIC, | |||
UnresolvedType.JAVA_LANG_STRING, // return value | |||
NameMangler.PERTYPEWITHIN_GETWITHINTYPENAME_METHOD, UnresolvedType.NONE); | |||
return rm; | |||
} | |||
public static ResolvedMember perTypeWithinCreateAspectInstance(UnresolvedType declaringType) { | |||
// public static a.X ajc$createAspectInstance(java.lang.String) | |||
ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, declaringType, // return value | |||
NameMangler.PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType | |||
.forSignature("Ljava/lang/String;") }, new UnresolvedType[] {}); | |||
return rm; | |||
} | |||
public static UnresolvedType perObjectInterfaceType(UnresolvedType aspectType) { | |||
return UnresolvedType.forName(aspectType.getName() + "$ajcMightHaveAspect"); | |||
} | |||
public static ResolvedMember perObjectInterfaceGet(UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.METHOD, perObjectInterfaceType(aspectType), Modifier.PUBLIC | Modifier.ABSTRACT, | |||
NameMangler.perObjectInterfaceGet(aspectType), "()" + aspectType.getSignature()); | |||
} | |||
public static ResolvedMember perObjectInterfaceSet(UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.METHOD, perObjectInterfaceType(aspectType), Modifier.PUBLIC | Modifier.ABSTRACT, | |||
NameMangler.perObjectInterfaceSet(aspectType), "(" + aspectType.getSignature() + ")V"); | |||
} | |||
// PTWIMPL ResolvedMember for localAspectOf() method, declared in matched type | |||
public static ResolvedMember perTypeWithinLocalAspectOf(UnresolvedType shadowType, UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.METHOD, shadowType,// perTypeWithinInterfaceType(aspectType), | |||
Modifier.PUBLIC | Modifier.STATIC, NameMangler.perTypeWithinLocalAspectOf(aspectType), "()" | |||
+ aspectType.getSignature()); | |||
} | |||
public static ResolvedMember perSingletonAspectOfMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "aspectOf", "()" + declaringType.getSignature()); | |||
} | |||
public static ResolvedMember perSingletonHasAspectMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "hasAspect", "()Z"); | |||
} | |||
public static ResolvedMember perCflowAspectOfMethod(UnresolvedType declaringType) { | |||
return perSingletonAspectOfMethod(declaringType); | |||
} | |||
public static ResolvedMember perCflowHasAspectMethod(UnresolvedType declaringType) { | |||
return perSingletonHasAspectMethod(declaringType); | |||
} | |||
public static ResolvedMember perObjectAspectOfMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "aspectOf", "(Ljava/lang/Object;)" | |||
+ declaringType.getSignature()); | |||
} | |||
public static ResolvedMember perObjectHasAspectMethod(UnresolvedType declaringType) { | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "hasAspect", "(Ljava/lang/Object;)Z"); | |||
} | |||
// PTWIMPL ResolvedMember for aspectOf(), declared in aspect | |||
public static ResolvedMember perTypeWithinAspectOfMethod(UnresolvedType declaringType, boolean inJava5Mode) { | |||
UnresolvedType parameterType = null; | |||
if (inJava5Mode) { | |||
parameterType = UnresolvedType.forRawTypeName("java.lang.Class"); | |||
} else { | |||
parameterType = UnresolvedType.forSignature("Ljava/lang/Class;"); | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, declaringType, "aspectOf", | |||
new UnresolvedType[] { parameterType }); | |||
// return new ResolvedMemberImpl(Member.METHOD, | |||
// declaringType, PUBLIC_STATIC, "aspectOf", | |||
// "(Ljava/lang/Class;)" + declaringType.getSignature()); | |||
} | |||
/* | |||
* public static ResolvedMember perTypeWithinGetWithinTypeMethod(UnresolvedType declaringType, boolean inJava5Mode) { | |||
* UnresolvedType returnType = null; if (inJava5Mode) { returnType = UnresolvedType.forRawTypeName("java.lang.Class"); } else { | |||
* returnType = UnresolvedType.forSignature("Ljava/lang/Class;"); } return new | |||
* ResolvedMemberImpl(Member.METHOD,declaringType,Modifier.PUBLIC,ResolvedType.JAVA_LANG_STRING,"getWithinType",new | |||
* UnresolvedType[]{}); } | |||
*/ | |||
// PTWIMPL ResolvedMember for hasAspect(), declared in aspect | |||
public static ResolvedMember perTypeWithinHasAspectMethod(UnresolvedType declaringType, boolean inJava5Mode) { | |||
UnresolvedType parameterType = null; | |||
if (inJava5Mode) { | |||
parameterType = UnresolvedType.forRawTypeName("java.lang.Class"); | |||
} else { | |||
parameterType = UnresolvedType.forSignature("Ljava/lang/Class;"); | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, ResolvedType.BOOLEAN, "hasAspect", | |||
new UnresolvedType[] { parameterType }); | |||
// return new ResolvedMemberImpl(Member.METHOD, | |||
// declaringType, PUBLIC_STATIC, "hasAspect", | |||
// "(Ljava/lang/Class;)Z"); | |||
} | |||
// -- privileged accessors | |||
public static ResolvedMember privilegedAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) { | |||
return new ResolvedMemberImpl(Member.METHOD, method.getDeclaringType(), Modifier.PUBLIC | |||
| (method.isStatic() ? Modifier.STATIC : 0), method.getReturnType(), NameMangler.privilegedAccessMethodForMethod( | |||
method.getName(), method.getDeclaringType(), aspectType), method.getParameterTypes(), method.getExceptions()); | |||
} | |||
public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field) { | |||
String sig; | |||
if (field.isStatic()) { | |||
sig = "()" + field.getReturnType().getSignature(); | |||
} else { | |||
sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature(); | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() | |||
// ? Modifier.STATIC : 0), | |||
NameMangler.privilegedAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig); | |||
} | |||
public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field) { | |||
String sig; | |||
if (field.isStatic()) { | |||
sig = "(" + field.getReturnType().getSignature() + ")V"; | |||
} else { | |||
sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V"; | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() | |||
// ? Modifier.STATIC : 0), | |||
NameMangler.privilegedAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig); | |||
} | |||
// --- inline accessors | |||
// ??? can eclipse handle a transform this weird without putting synthetics into the mix | |||
public static ResolvedMember superAccessMethod(UnresolvedType baseType, ResolvedMember method) { | |||
return new ResolvedMemberImpl(Member.METHOD, baseType, Modifier.PUBLIC, method.getReturnType(), NameMangler | |||
.superDispatchMethod(baseType, method.getName()), method.getParameterTypes(), method.getExceptions()); | |||
} | |||
public static ResolvedMember inlineAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) { | |||
UnresolvedType[] paramTypes = method.getParameterTypes(); | |||
if (!method.isStatic()) { | |||
paramTypes = UnresolvedType.insert(method.getDeclaringType(), paramTypes); | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, | |||
PUBLIC_STATIC, // ??? what about privileged and super access | |||
// ???Modifier.PUBLIC | (method.isStatic() ? Modifier.STATIC : 0), | |||
method.getReturnType(), | |||
NameMangler.inlineAccessMethodForMethod(method.getName(), method.getDeclaringType(), aspectType), paramTypes, | |||
method.getExceptions()); | |||
} | |||
public static ResolvedMember inlineAccessMethodForFieldGet(UnresolvedType aspectType, Member field) { | |||
String sig; | |||
if (field.isStatic()) { | |||
sig = "()" + field.getReturnType().getSignature(); | |||
} else { | |||
sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature(); | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() ? | |||
// Modifier.STATIC : 0), | |||
NameMangler.inlineAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig); | |||
} | |||
public static ResolvedMember inlineAccessMethodForFieldSet(UnresolvedType aspectType, Member field) { | |||
String sig; | |||
if (field.isStatic()) { | |||
sig = "(" + field.getReturnType().getSignature() + ")V"; | |||
} else { | |||
sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V"; | |||
} | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() ? | |||
// Modifier.STATIC : 0), | |||
NameMangler.inlineAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig); | |||
} | |||
// --- runtimeLibrary api stuff | |||
public static Member cflowStackPeekInstance() { | |||
return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "peekInstance", "()Ljava/lang/Object;"); | |||
} | |||
public static Member cflowStackPushInstance() { | |||
return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "pushInstance", "(Ljava/lang/Object;)V"); | |||
} | |||
public static Member cflowStackIsValid() { | |||
return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "isValid", "()Z"); | |||
} | |||
public static Member cflowStackInit() { | |||
return new MemberImpl(Member.CONSTRUCTOR, CFLOW_STACK_TYPE, 0, "<init>", "()V"); | |||
} | |||
public static Member aroundClosurePreInitializationField() { | |||
return new MemberImpl(Member.FIELD, AROUND_CLOSURE_TYPE, 0, "preInitializationState", "[Ljava/lang/Object;"); | |||
} | |||
public static Member aroundClosurePreInitializationGetter() { | |||
return new MemberImpl(Member.METHOD, AROUND_CLOSURE_TYPE, 0, "getPreInitializationState", "()[Ljava/lang/Object;"); | |||
} | |||
public static ResolvedMember preIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType, | |||
UnresolvedType[] paramTypes) { | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC_FINAL, UnresolvedType.OBJECTARRAY, NameMangler | |||
.preIntroducedConstructor(aspectType, targetType), paramTypes); | |||
} | |||
public static ResolvedMember postIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType, | |||
UnresolvedType[] paramTypes) { | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC_FINAL, ResolvedType.VOID, NameMangler | |||
.postIntroducedConstructor(aspectType, targetType), UnresolvedType.insert(targetType, paramTypes)); | |||
} | |||
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, | |||
// int modifiers) | |||
// { | |||
ResolvedMember ret = new ResolvedMemberImpl(Member.CONSTRUCTOR, targetType, Modifier.PUBLIC, ResolvedType.VOID, "<init>", | |||
constructor.getParameterTypes(), constructor.getExceptions()); | |||
// System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers)); | |||
if (Modifier.isPublic(constructor.getModifiers())) | |||
return ret; | |||
while (true) { | |||
ret = addCookieTo(ret, aspectType); | |||
if (targetType.lookupMemberNoSupers(ret) == null) | |||
return ret; | |||
} | |||
} | |||
public static ResolvedMember interFieldInitializer(ResolvedMember field, UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, NameMangler.interFieldInitializer(aspectType, field | |||
.getDeclaringType(), field.getName()), field.isStatic() ? "()V" : "(" + field.getDeclaringType().getSignature() | |||
+ ")V"); | |||
} | |||
/** | |||
* Makes public and non-final | |||
*/ | |||
private static int makePublicNonFinal(int modifiers) { | |||
return (modifiers & ~VISIBILITY & ~Modifier.FINAL) | Modifier.PUBLIC; | |||
} | |||
/** | |||
* This static method goes on the aspect that declares the inter-type field | |||
*/ | |||
public static ResolvedMember interFieldSetDispatcher(ResolvedMember field, UnresolvedType aspectType) { | |||
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, ResolvedType.VOID, NameMangler | |||
.interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()), | |||
field.isStatic() ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] { | |||
field.getDeclaringType(), field.getReturnType() }); | |||
rm.setTypeVariables(field.getTypeVariables()); | |||
return rm; | |||
} | |||
/** | |||
* This static method goes on the aspect that declares the inter-type field | |||
*/ | |||
public static ResolvedMember interFieldGetDispatcher(ResolvedMember field, UnresolvedType aspectType) { | |||
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, field.getReturnType(), NameMangler | |||
.interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()), | |||
field.isStatic() ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE); | |||
rm.setTypeVariables(field.getTypeVariables()); | |||
return rm; | |||
} | |||
// private static int makeFieldModifiers(int declaredModifiers) { | |||
// int ret = Modifier.PUBLIC; | |||
// if (Modifier.isTransient(declaredModifiers)) ret |= Modifier.TRANSIENT; | |||
// if (Modifier.isVolatile(declaredModifiers)) ret |= Modifier.VOLATILE; | |||
// return ret; | |||
// } | |||
/** | |||
* This field goes on the class the field is declared onto | |||
*/ | |||
public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), makePublicNonFinal(field.getModifiers()), field | |||
.getReturnType(), NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), | |||
field.getName()), UnresolvedType.NONE, UnresolvedType.NONE); | |||
} | |||
/** | |||
* This field goes on top-most implementers of the interface the field is declared onto | |||
*/ | |||
public static ResolvedMember interFieldInterfaceField(ResolvedMember field, UnresolvedType onClass, UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl(Member.FIELD, onClass, makePublicNonFinal(field.getModifiers()), field.getReturnType(), | |||
NameMangler.interFieldInterfaceField(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE, | |||
UnresolvedType.NONE); | |||
} | |||
/** | |||
* This instance method goes on the interface the field is declared onto as well as its top-most implementors | |||
*/ | |||
public static ResolvedMember interFieldInterfaceSetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) { | |||
int modifiers = Modifier.PUBLIC; | |||
if (onType.isInterface()) | |||
modifiers |= Modifier.ABSTRACT; | |||
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, ResolvedType.VOID, NameMangler | |||
.interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()), new UnresolvedType[] { field | |||
.getReturnType() }, UnresolvedType.NONE); | |||
rm.setTypeVariables(field.getTypeVariables()); | |||
return rm; | |||
} | |||
/** | |||
* This instance method goes on the interface the field is declared onto as well as its top-most implementors | |||
*/ | |||
public static ResolvedMember interFieldInterfaceGetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) { | |||
int modifiers = Modifier.PUBLIC; | |||
if (onType.isInterface()) | |||
modifiers |= Modifier.ABSTRACT; | |||
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, field.getReturnType(), NameMangler | |||
.interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE, | |||
UnresolvedType.NONE); | |||
rm.setTypeVariables(field.getTypeVariables()); | |||
return rm; | |||
} | |||
/** | |||
* This method goes on the target type of the inter-type method. (and possibly the topmost-implementors, if the target type is | |||
* an interface). The implementation will call the interMethodDispatch method on the aspect. | |||
*/ | |||
public static ResolvedMember interMethod(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) { | |||
if (Modifier.isPublic(meth.getModifiers()) && !onInterface) | |||
return meth; | |||
int modifiers = makePublicNonFinal(meth.getModifiers()); | |||
if (onInterface) | |||
modifiers |= Modifier.ABSTRACT; | |||
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(), | |||
NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth | |||
.getParameterTypes(), meth.getExceptions()); | |||
rmi.setTypeVariables(meth.getTypeVariables()); | |||
return rmi; | |||
} | |||
/** | |||
* This method goes on the target type of the inter-type method. (and possibly the topmost-implementors, if the target type is | |||
* an interface). The implementation will call the interMethodDispatch method on the aspect. | |||
*/ | |||
public static ResolvedMember interMethodBridger(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) { | |||
// if (Modifier.isPublic(meth.getModifiers()) && !onInterface) | |||
// return meth; | |||
int modifiers = makePublicNonFinal(meth.getModifiers()) | BRIDGE; | |||
if (onInterface) | |||
modifiers |= Modifier.ABSTRACT; | |||
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(), | |||
NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth | |||
.getParameterTypes(), meth.getExceptions()); | |||
rmi.setTypeVariables(meth.getTypeVariables()); | |||
return rmi; | |||
} | |||
/** | |||
* Sometimes the intertyped method requires a bridge method alongside it. For example if the method 'N SomeI<N>.m()' is put onto | |||
* an interface 'interface I<N extends Number>' and then a concrete implementation is 'class C implements I<Float>' then the ITD | |||
* on the interface will be 'Number m()', whereas the ITD on the 'topmostimplementor' will be 'Float m()'. A bridge method needs | |||
* to be created in the topmostimplementor 'Number m()' that delegates to 'Float m()' | |||
*/ | |||
public static ResolvedMember bridgerToInterMethod(ResolvedMember meth, UnresolvedType aspectType) { | |||
int modifiers = makePublicNonFinal(meth.getModifiers()); | |||
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, modifiers, meth.getReturnType(), NameMangler | |||
.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth.getParameterTypes(), | |||
meth.getExceptions()); | |||
rmi.setTypeVariables(meth.getTypeVariables()); | |||
return rmi; | |||
} | |||
/** | |||
* This static method goes on the declaring aspect of the inter-type method. The implementation calls the interMethodBody() | |||
* method on the aspect. | |||
*/ | |||
public static ResolvedMember interMethodDispatcher(ResolvedMember meth, UnresolvedType aspectType) { | |||
UnresolvedType[] paramTypes = meth.getParameterTypes(); | |||
if (!meth.isStatic()) { | |||
paramTypes = UnresolvedType.insert(meth.getDeclaringType(), paramTypes); | |||
} | |||
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, meth.getReturnType(), NameMangler | |||
.interMethodDispatcher(aspectType, meth.getDeclaringType(), meth.getName()), paramTypes, meth.getExceptions()); | |||
rmi.setTypeVariables(meth.getTypeVariables()); | |||
return rmi; | |||
} | |||
/** | |||
* This method goes on the declaring aspect of the inter-type method. It contains the real body of the ITD method. | |||
*/ | |||
public static ResolvedMember interMethodBody(ResolvedMember meth, UnresolvedType aspectType) { | |||
UnresolvedType[] paramTypes = meth.getParameterTypes(); | |||
if (!meth.isStatic()) { | |||
paramTypes = UnresolvedType.insert(meth.getDeclaringType(), paramTypes); | |||
} | |||
int modifiers = PUBLIC_STATIC; | |||
if (Modifier.isStrict(meth.getModifiers())) { | |||
modifiers |= Modifier.STRICT; | |||
} | |||
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, modifiers, meth.getReturnType(), NameMangler | |||
.interMethodBody(aspectType, meth.getDeclaringType(), meth.getName()), paramTypes, meth.getExceptions()); | |||
rmi.setTypeVariables(meth.getTypeVariables()); | |||
return rmi; | |||
} | |||
private static ResolvedMember addCookieTo(ResolvedMember ret, UnresolvedType aspectType) { | |||
UnresolvedType[] params = ret.getParameterTypes(); | |||
UnresolvedType[] freshParams = UnresolvedType.add(params, aspectType); | |||
return new ResolvedMemberImpl(ret.getKind(), ret.getDeclaringType(), ret.getModifiers(), ret.getReturnType(), | |||
ret.getName(), freshParams, ret.getExceptions()); | |||
} | |||
public static ResolvedMember toObjectConversionMethod(UnresolvedType fromType) { | |||
if (fromType.isPrimitiveType()) { | |||
String name = fromType.toString() + "Object"; | |||
return new ResolvedMemberImpl(Member.METHOD, CONVERSIONS_TYPE, PUBLIC_STATIC, UnresolvedType.OBJECT, name, | |||
new UnresolvedType[] { fromType }, UnresolvedType.NONE); | |||
} else { | |||
return null; | |||
} | |||
} | |||
public static Member interfaceConstructor(ResolvedType resolvedTypeX) { | |||
// AMC next two lines should not be needed when sig for generic type is changed | |||
ResolvedType declaringType = resolvedTypeX; | |||
if (declaringType.isRawType()) | |||
declaringType = declaringType.getGenericType(); | |||
return new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringType, Modifier.PUBLIC, "<init>", "()V"); | |||
} | |||
// -- common types we use. Note: Java 5 dependand types are refered to as String | |||
public final static UnresolvedType ASPECT_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Aspect;"); | |||
public final static UnresolvedType BEFORE_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Before;"); | |||
public final static UnresolvedType AROUND_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Around;"); | |||
public final static UnresolvedType AFTERRETURNING_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/AfterReturning;"); | |||
public final static UnresolvedType AFTERTHROWING_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/AfterThrowing;"); | |||
public final static UnresolvedType AFTER_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/After;"); | |||
public final static UnresolvedType POINTCUT_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Pointcut;"); | |||
public final static UnresolvedType DECLAREERROR_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/DeclareError;"); | |||
public final static UnresolvedType DECLAREWARNING_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/DeclareWarning;"); | |||
public final static UnresolvedType DECLAREPRECEDENCE_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/DeclarePrecedence;"); | |||
// public final static UnresolvedType DECLAREIMPLEMENTS_ANNOTATION = | |||
// UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/DeclareImplements;"); | |||
public final static UnresolvedType DECLAREPARENTS_ANNOTATION = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/annotation/DeclareParents;"); | |||
public final static UnresolvedType TYPEX_JOINPOINT = UnresolvedType.forSignature("Lorg/aspectj/lang/JoinPoint;"); | |||
public final static UnresolvedType TYPEX_PROCEEDINGJOINPOINT = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/ProceedingJoinPoint;"); | |||
public final static UnresolvedType TYPEX_STATICJOINPOINT = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;"); | |||
public final static UnresolvedType TYPEX_ENCLOSINGSTATICJOINPOINT = UnresolvedType | |||
.forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;"); | |||
} |
@@ -0,0 +1,21 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2004 IBM Corporation. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Represents any element that may have annotations | |||
*/ | |||
public interface AnnotatedElement { | |||
boolean hasAnnotation(UnresolvedType ofType); | |||
ResolvedType[] getAnnotationTypes(); | |||
AnnotationAJ getAnnotationOfType(UnresolvedType ofType); | |||
} |
@@ -0,0 +1,102 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006-2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Set; | |||
/** | |||
* Simple representation of an annotation that the weaver can work with. | |||
* | |||
* @author AndyClement | |||
*/ | |||
public interface AnnotationAJ { | |||
public static final AnnotationAJ[] EMPTY_ARRAY = new AnnotationAJ[0]; | |||
/** | |||
* @return the signature for the annotation type, eg. Lcom/foo/MyAnno; | |||
*/ | |||
public String getTypeSignature(); | |||
/** | |||
* @return the type name for the annotation, eg. com.foo.MyAnno | |||
*/ | |||
public String getTypeName(); | |||
/** | |||
* @return the type of the annotation | |||
*/ | |||
public ResolvedType getType(); | |||
/** | |||
* return true if this annotation can target an annotation type | |||
*/ | |||
public boolean allowedOnAnnotationType(); | |||
/** | |||
* @return true if this annotation can be put on a field | |||
*/ | |||
public boolean allowedOnField(); | |||
/** | |||
* @return true if this annotation can target a 'regular' type. A 'regular' type is enum/class/interface - it is *not* | |||
* annotation. | |||
*/ | |||
public boolean allowedOnRegularType(); | |||
/** | |||
* @return for the @target annotation, this will return a set of the element-types it can be applied to. For other annotations , | |||
* it returns the empty set. | |||
*/ | |||
public Set getTargets(); | |||
/** | |||
* @param name the name of the value | |||
* @return true if there is a value with that name | |||
*/ | |||
public boolean hasNamedValue(String name); | |||
/** | |||
* @param name the name of the annotation field | |||
* @param value the value of the annotation field | |||
* @return true if there is a value with the specified name and value | |||
*/ | |||
public boolean hasNameValuePair(String name, String value); | |||
/** | |||
* @return String representation of the valid targets for this annotation, eg. "{TYPE,FIELD}" | |||
*/ | |||
public String getValidTargets(); | |||
/** | |||
* @return String form of the annotation and any values, eg. @Foo(a=b,c=d) | |||
*/ | |||
public String stringify(); | |||
/** | |||
* @return true if this annotation is marked with @target | |||
*/ | |||
public boolean specifiesTarget(); | |||
/** | |||
* @return true if the annotation is marked for runtime visibility | |||
*/ | |||
public boolean isRuntimeVisible(); | |||
/** | |||
* Determine the string representation of the value of a field. For example in @SuppressAjWarnings({"adviceDidNotMatch"}) | |||
* the return value for getStringFormOfValue("value") would be "[adviceDidNotMatch]". | |||
* | |||
* @param name the name of the annotation field being looked up | |||
* @return string representation of the value of that field, may be null if no such field set | |||
*/ | |||
public String getStringFormOfValue(String name); | |||
} |
@@ -0,0 +1,35 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class AnnotationAnnotationValue extends AnnotationValue { | |||
private AnnotationAJ value; | |||
public AnnotationAnnotationValue(AnnotationAJ value) { | |||
super(AnnotationValue.ANNOTATION); | |||
this.value = value; | |||
} | |||
public AnnotationAJ getAnnotation() { | |||
return value; | |||
} | |||
public String stringify() { | |||
return value.stringify(); | |||
} | |||
public String toString() { | |||
return value.toString(); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class AnnotationNameValuePair { | |||
private String name; | |||
private AnnotationValue val; | |||
public AnnotationNameValuePair(String name,AnnotationValue val) { | |||
this.name = name; | |||
this.val = val; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public AnnotationValue getValue() { | |||
return val; | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(name+"="+val.toString()); | |||
return sb.toString(); | |||
} | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
if (!name.equals("value")) { | |||
sb.append(name+"="); | |||
} | |||
sb.append(val.stringify()); | |||
return sb.toString(); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 IBM | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
/** | |||
* Represents adding an annotation to a type | |||
*/ | |||
public class AnnotationOnTypeMunger extends ResolvedTypeMunger { | |||
AnnotationAJ newAnnotation; | |||
public AnnotationOnTypeMunger(AnnotationAJ anno) { | |||
super(AnnotationOnType, null); | |||
newAnnotation = anno; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public AnnotationAJ getNewAnnotation() { | |||
return newAnnotation; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof AnnotationOnTypeMunger)) | |||
return false; | |||
AnnotationOnTypeMunger o = (AnnotationOnTypeMunger) other; | |||
// TODO does not check equality of annotation values | |||
return newAnnotation.getTypeSignature().equals( | |||
o.newAnnotation.getTypeSignature()); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37 * result + newAnnotation.getTypeSignature().hashCode(); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/******************************************************************** | |||
* 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: | |||
* Helen Hawkins - Initial implementation | |||
*******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataInputStream; | |||
import java.io.IOException; | |||
import org.aspectj.util.TypeSafeEnum; | |||
/** | |||
* A TypeSafeEnum similar to the Java5 ElementType Enum | |||
*/ | |||
public class AnnotationTargetKind extends TypeSafeEnum { | |||
public AnnotationTargetKind(String name, int key) { | |||
super(name, key); | |||
} | |||
public static AnnotationTargetKind read(DataInputStream s) throws IOException { | |||
int key = s.readByte(); | |||
switch(key) { | |||
case 1: return ANNOTATION_TYPE; | |||
case 2: return CONSTRUCTOR; | |||
case 3: return FIELD; | |||
case 4: return LOCAL_VARIABLE; | |||
case 5: return METHOD; | |||
case 6: return PACKAGE; | |||
case 7: return PARAMETER; | |||
case 8: return TYPE; | |||
} | |||
throw new BCException("weird annotation target kind " + key); | |||
} | |||
public static final AnnotationTargetKind ANNOTATION_TYPE = new AnnotationTargetKind("ANNOTATION_TYPE", 1); | |||
public static final AnnotationTargetKind CONSTRUCTOR = new AnnotationTargetKind("CONSTRUCTOR", 2); | |||
public static final AnnotationTargetKind FIELD = new AnnotationTargetKind("FIELD", 3); | |||
public static final AnnotationTargetKind LOCAL_VARIABLE = new AnnotationTargetKind("LOCAL_VARIABLE", 4); | |||
public static final AnnotationTargetKind METHOD = new AnnotationTargetKind("METHOD", 5); | |||
public static final AnnotationTargetKind PACKAGE = new AnnotationTargetKind("PACKAGE", 6); | |||
public static final AnnotationTargetKind PARAMETER = new AnnotationTargetKind("PARAMETER", 7); | |||
public static final AnnotationTargetKind TYPE = new AnnotationTargetKind("TYPE", 8); | |||
} |
@@ -0,0 +1,72 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public abstract class AnnotationValue { | |||
protected int valueKind; | |||
public static final int STRING = 's'; | |||
public static final int ENUM_CONSTANT = 'e'; | |||
public static final int CLASS = 'c'; | |||
public static final int ANNOTATION = '@'; | |||
public static final int ARRAY = '['; | |||
public static final int PRIMITIVE_INT = 'I'; | |||
public static final int PRIMITIVE_BYTE = 'B'; | |||
public static final int PRIMITIVE_CHAR = 'C'; | |||
public static final int PRIMITIVE_DOUBLE = 'D'; | |||
public static final int PRIMITIVE_FLOAT = 'F'; | |||
public static final int PRIMITIVE_LONG = 'J'; | |||
public static final int PRIMITIVE_SHORT = 'S'; | |||
public static final int PRIMITIVE_BOOLEAN= 'Z'; | |||
public abstract String stringify(); | |||
public AnnotationValue(int kind) { | |||
valueKind = kind; | |||
} | |||
public static String whatKindIsThis(int kind) { | |||
switch (kind) { | |||
case PRIMITIVE_BYTE: // byte | |||
return "byte"; | |||
case PRIMITIVE_CHAR: // char | |||
return "char"; | |||
case PRIMITIVE_DOUBLE: // double | |||
return "double"; | |||
case PRIMITIVE_FLOAT: // float | |||
return "float"; | |||
case PRIMITIVE_INT: // int | |||
return "int"; | |||
case PRIMITIVE_LONG: // long | |||
return "long"; | |||
case PRIMITIVE_SHORT: // short | |||
return "short"; | |||
case PRIMITIVE_BOOLEAN: // boolean | |||
return "boolean"; | |||
case 's': // String | |||
return "string"; | |||
case 'e': // Enum constant | |||
return "enum"; | |||
case 'c': // Class | |||
return "class"; | |||
case '@': // Annotation | |||
return "annotation"; | |||
case '[': // Array | |||
return "array"; | |||
default: | |||
throw new RuntimeException("Dont know what this is : "+kind); | |||
} | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class ArrayAnnotationValue extends AnnotationValue { | |||
private AnnotationValue[] values; | |||
public ArrayAnnotationValue() { | |||
super(AnnotationValue.ARRAY); | |||
} | |||
public void setValues(AnnotationValue[] values) { | |||
this.values = values; | |||
} | |||
public ArrayAnnotationValue(AnnotationValue[] values) { | |||
super(AnnotationValue.ARRAY); | |||
this.values = values; | |||
} | |||
public AnnotationValue[] getValues() { | |||
return values; | |||
} | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("["); | |||
for (int i = 0; i < values.length; i++) { | |||
sb.append(values[i].stringify()); | |||
if (i+1<values.length) sb.append(","); | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("{"); | |||
for (int i = 0; i < values.length; i++) { | |||
sb.append(values[i].toString()); | |||
if ((i+1)<values.length) sb.append(","); | |||
} | |||
sb.append("}"); | |||
return sb.toString(); | |||
} | |||
} |
@@ -0,0 +1,196 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
/** | |||
* Represents a resolved array type | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class ArrayReferenceType extends ReferenceType { | |||
private final ResolvedType componentType; | |||
public ArrayReferenceType(String sig, String erasureSig, World world, ResolvedType componentType) { | |||
super(sig, erasureSig, world); | |||
this.componentType = componentType; | |||
} | |||
// These methods are from the original implementation when Array was a ResolvedType and not a ReferenceType | |||
public final ResolvedMember[] getDeclaredFields() { | |||
return ResolvedMember.NONE; | |||
} | |||
public final ResolvedMember[] getDeclaredMethods() { | |||
// ??? should this return clone? Probably not... | |||
// If it ever does, here is the code: | |||
// ResolvedMember cloneMethod = | |||
// new ResolvedMember(Member.METHOD,this,Modifier.PUBLIC,UnresolvedType.OBJECT,"clone",new UnresolvedType[]{}); | |||
// return new ResolvedMember[]{cloneMethod}; | |||
return ResolvedMember.NONE; | |||
} | |||
public final ResolvedType[] getDeclaredInterfaces() { | |||
return new ResolvedType[] { world.getCoreType(CLONEABLE), world.getCoreType(SERIALIZABLE) }; | |||
} | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
return null; | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
return AnnotationAJ.EMPTY_ARRAY; | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
return ResolvedType.NONE; | |||
} | |||
public final ResolvedMember[] getDeclaredPointcuts() { | |||
return ResolvedMember.NONE; | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
return false; | |||
} | |||
public final ResolvedType getSuperclass() { | |||
return world.getCoreType(OBJECT); | |||
} | |||
public final boolean isAssignableFrom(ResolvedType o) { | |||
if (!o.isArray()) | |||
return false; | |||
if (o.getComponentType().isPrimitiveType()) { | |||
return o.equals(this); | |||
} else { | |||
return getComponentType().resolve(world).isAssignableFrom(o.getComponentType().resolve(world)); | |||
} | |||
} | |||
public boolean isAssignableFrom(ResolvedType o, boolean allowMissing) { | |||
return isAssignableFrom(o); | |||
} | |||
public final boolean isCoerceableFrom(ResolvedType o) { | |||
if (o.equals(UnresolvedType.OBJECT) || o.equals(UnresolvedType.SERIALIZABLE) || o.equals(UnresolvedType.CLONEABLE)) { | |||
return true; | |||
} | |||
if (!o.isArray()) | |||
return false; | |||
if (o.getComponentType().isPrimitiveType()) { | |||
return o.equals(this); | |||
} else { | |||
return getComponentType().resolve(world).isCoerceableFrom(o.getComponentType().resolve(world)); | |||
} | |||
} | |||
public final int getModifiers() { | |||
int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; | |||
return (componentType.getModifiers() & mask) | Modifier.FINAL; | |||
} | |||
public UnresolvedType getComponentType() { | |||
return componentType; | |||
} | |||
public ResolvedType getResolvedComponentType() { | |||
return componentType; | |||
} | |||
public ISourceContext getSourceContext() { | |||
return getResolvedComponentType().getSourceContext(); | |||
} | |||
// Methods overridden from ReferenceType follow | |||
public TypeVariable[] getTypeVariables() { | |||
if (this.typeVariables == null && componentType.getTypeVariables() != null) { | |||
this.typeVariables = componentType.getTypeVariables(); | |||
for (int i = 0; i < this.typeVariables.length; i++) { | |||
this.typeVariables[i].resolve(world); | |||
} | |||
} | |||
return this.typeVariables; | |||
} | |||
public boolean isAnnotation() { | |||
return false; | |||
} | |||
public boolean isAnonymous() { | |||
return false; | |||
} | |||
public boolean isAnnotationStyleAspect() { | |||
return false; | |||
} | |||
public boolean isAspect() { | |||
return false; | |||
} | |||
public boolean isPrimitiveType() { | |||
return typeKind == TypeKind.PRIMITIVE; | |||
} | |||
public boolean isSimpleType() { | |||
return typeKind == TypeKind.SIMPLE; | |||
} | |||
public boolean isRawType() { | |||
return typeKind == TypeKind.RAW; | |||
} | |||
public boolean isGenericType() { | |||
return typeKind == TypeKind.GENERIC; | |||
} | |||
public boolean isParameterizedType() { | |||
return typeKind == TypeKind.PARAMETERIZED; | |||
} | |||
public boolean isTypeVariableReference() { | |||
return typeKind == TypeKind.TYPE_VARIABLE; | |||
} | |||
public boolean isGenericWildcard() { | |||
return typeKind == TypeKind.WILDCARD; | |||
} | |||
public boolean isEnum() { | |||
return false; | |||
} | |||
public boolean isNested() { | |||
return false; | |||
} | |||
public boolean isClass() { | |||
return false; | |||
} | |||
public boolean canAnnotationTargetType() { | |||
return false; | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return null; | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.PrintStream; | |||
import java.io.PrintWriter; | |||
import org.aspectj.bridge.context.CompilationAndWeavingContext; | |||
/** | |||
* Exception to use inside the bcweaver. | |||
*/ | |||
public class BCException extends RuntimeException { | |||
Throwable thrown; | |||
public BCException() { | |||
super(); | |||
} | |||
public BCException(String s) { | |||
super(s + "\n" + CompilationAndWeavingContext.getCurrentContext()); | |||
} | |||
public BCException(String s, Throwable thrown) { | |||
this(s); | |||
this.thrown = thrown; | |||
} | |||
public void printStackTrace() { | |||
printStackTrace(System.err); | |||
} | |||
public void printStackTrace(PrintStream s) { | |||
printStackTrace(new PrintWriter(s)); | |||
} | |||
public void printStackTrace(PrintWriter s) { | |||
super.printStackTrace(s); | |||
if (null != thrown) { | |||
s.print("Caused by: "); | |||
s.print(thrown.getClass().getName()); | |||
String message = thrown.getMessage(); | |||
if (null != message) { | |||
s.print(": "); | |||
s.print(message); | |||
} | |||
s.println(); | |||
thrown.printStackTrace(s); | |||
} | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006-2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.patterns.FormalBinding; | |||
import org.aspectj.weaver.patterns.SimpleScope; | |||
/** | |||
* BindingScope that knows the enclosingType, which is needed for pointcut reference resolution | |||
* | |||
* @author Alexandre Vasseur | |||
*/ | |||
public class BindingScope extends SimpleScope { | |||
private final ResolvedType m_enclosingType; | |||
private final ISourceContext m_sourceContext; | |||
public BindingScope(ResolvedType type, ISourceContext sourceContext, FormalBinding[] bindings) { | |||
super(type.getWorld(), bindings); | |||
m_enclosingType = type; | |||
m_sourceContext = sourceContext; | |||
} | |||
public ResolvedType getEnclosingType() { | |||
return m_enclosingType; | |||
} | |||
public ISourceLocation makeSourceLocation(IHasPosition location) { | |||
return m_sourceContext.makeSourceLocation(location); | |||
} | |||
public UnresolvedType lookupType(String name, IHasPosition location) { | |||
// bug 126560 | |||
if (m_enclosingType != null) { | |||
// add the package we're in to the list of imported | |||
// prefixes so that we can find types in the same package | |||
String pkgName = m_enclosingType.getPackageName(); | |||
if (pkgName != null && !pkgName.equals("")) { | |||
String[] currentImports = getImportedPrefixes(); | |||
String[] newImports = new String[currentImports.length + 1]; | |||
for (int i = 0; i < currentImports.length; i++) { | |||
newImports[i] = currentImports[i]; | |||
} | |||
newImports[currentImports.length] = pkgName.concat("."); | |||
setImportedPrefixes(newImports); | |||
} | |||
} | |||
return super.lookupType(name, location); | |||
} | |||
} |
@@ -0,0 +1,334 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Map; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* A BoundedReferenceType is the result of a generics wildcard expression ? | |||
* extends String, ? super Foo etc.. | |||
* | |||
* The "signature" for a bounded reference type follows the generic signature | |||
* specification in section 4.4 of JVM spec: *,+,- plus signature strings. | |||
* | |||
* The bound may be a type variable (e.g. ? super T) | |||
*/ | |||
public class BoundedReferenceType extends ReferenceType { | |||
private ResolvedType lowerBound; | |||
private ResolvedType upperBound; | |||
protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0]; | |||
protected boolean isExtends = true; | |||
protected boolean isSuper = false; | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, | |||
World world) { | |||
super((isExtends ? "+" : "-") + aBound.signature, | |||
aBound.signatureErasure, world); | |||
this.isExtends = isExtends; | |||
this.isSuper = !isExtends; | |||
if (isExtends) { | |||
upperBound = aBound; | |||
} else { | |||
lowerBound = aBound; | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
} | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate( | |||
(ReferenceType) getUpperBound())); | |||
} | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, | |||
World world, ReferenceType[] additionalInterfaces) { | |||
this(aBound, isExtends, world); | |||
this.additionalInterfaceBounds = additionalInterfaces; | |||
} | |||
public ReferenceType[] getAdditionalBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds == null ? 0 | |||
: additionalInterfaceBounds.length]; | |||
for (int i = 0; i < parameterizedAdditionalInterfaces.length; i++) { | |||
parameterizedAdditionalInterfaces[i] = (ReferenceType) additionalInterfaceBounds[i] | |||
.parameterize(typeBindings); | |||
} | |||
if (isExtends) { | |||
return new BoundedReferenceType((ReferenceType) getUpperBound() | |||
.parameterize(typeBindings), isExtends, world, | |||
parameterizedAdditionalInterfaces); | |||
} else { | |||
return new BoundedReferenceType((ReferenceType) getLowerBound() | |||
.parameterize(typeBindings), isExtends, world, | |||
parameterizedAdditionalInterfaces); | |||
} | |||
} | |||
/** | |||
* only for use when resolving GenericsWildcardTypeX or a | |||
* TypeVariableReferenceType | |||
*/ | |||
protected BoundedReferenceType(String sig, String sigErasure, World world) { | |||
super(sig, sigErasure, world); | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate( | |||
(ReferenceType) getUpperBound())); | |||
} | |||
public ReferenceType[] getInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public boolean hasLowerBound() { | |||
return getLowerBound() != null; | |||
} | |||
public boolean isExtends() { | |||
return (isExtends && !getUpperBound().getSignature().equals( | |||
"Ljava/lang/Object;")); | |||
} | |||
public boolean isSuper() { | |||
return isSuper; | |||
} | |||
public boolean alwaysMatches(ResolvedType aCandidateType) { | |||
if (isExtends()) { | |||
// aCandidateType must be a subtype of upperBound | |||
return ((ReferenceType) getUpperBound()) | |||
.isAssignableFrom(aCandidateType); | |||
} else if (isSuper()) { | |||
// aCandidateType must be a supertype of lowerBound | |||
return aCandidateType | |||
.isAssignableFrom((ReferenceType) getLowerBound()); | |||
} else { | |||
return true; // straight '?' | |||
} | |||
} | |||
// this "maybe matches" that | |||
public boolean canBeCoercedTo(ResolvedType aCandidateType) { | |||
if (alwaysMatches(aCandidateType)) | |||
return true; | |||
if (aCandidateType.isGenericWildcard()) { | |||
BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType; | |||
ResolvedType myUpperBound = (ResolvedType) getUpperBound(); | |||
ResolvedType myLowerBound = (ResolvedType) getLowerBound(); | |||
if (isExtends()) { | |||
if (boundedRT.isExtends()) { | |||
return myUpperBound | |||
.isAssignableFrom((ResolvedType) boundedRT | |||
.getUpperBound()); | |||
} else if (boundedRT.isSuper()) { | |||
return myUpperBound == boundedRT.getLowerBound(); | |||
} else { | |||
return true; // it's '?' | |||
} | |||
} else if (isSuper()) { | |||
if (boundedRT.isSuper()) { | |||
return ((ResolvedType) boundedRT.getLowerBound()) | |||
.isAssignableFrom(myLowerBound); | |||
} else if (boundedRT.isExtends()) { | |||
return myLowerBound == boundedRT.getUpperBound(); | |||
} else { | |||
return true; | |||
} | |||
} else { | |||
return true; | |||
} | |||
} else { | |||
return false; | |||
} | |||
} | |||
public String getSimpleName() { | |||
if (!isExtends() && !isSuper()) | |||
return "?"; | |||
if (isExtends()) { | |||
return ("? extends " + getUpperBound().getSimpleName()); | |||
} else { | |||
return ("? super " + getLowerBound().getSimpleName()); | |||
} | |||
} | |||
// override to include additional interface bounds... | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
ResolvedType[] interfaces = super.getDeclaredInterfaces(); | |||
if (additionalInterfaceBounds.length > 0) { | |||
ResolvedType[] allInterfaces = new ResolvedType[interfaces.length | |||
+ additionalInterfaceBounds.length]; | |||
System | |||
.arraycopy(interfaces, 0, allInterfaces, 0, | |||
interfaces.length); | |||
System.arraycopy(additionalInterfaceBounds, 0, allInterfaces, | |||
interfaces.length, additionalInterfaceBounds.length); | |||
return allInterfaces; | |||
} else { | |||
return interfaces; | |||
} | |||
} | |||
public boolean isGenericWildcard() { | |||
return true; | |||
} | |||
protected static class ReferenceTypeReferenceTypeDelegate extends | |||
AbstractReferenceTypeDelegate { | |||
public ReferenceTypeReferenceTypeDelegate(ReferenceType backing) { | |||
super(backing, false); | |||
} | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
throw new UnsupportedOperationException( | |||
"What on earth do you think you are doing???"); | |||
} | |||
public boolean isAspect() { | |||
return resolvedTypeX.isAspect(); | |||
} | |||
public boolean isAnnotationStyleAspect() { | |||
return resolvedTypeX.isAnnotationStyleAspect(); | |||
} | |||
public boolean isInterface() { | |||
return resolvedTypeX.isInterface(); | |||
} | |||
public boolean isEnum() { | |||
return resolvedTypeX.isEnum(); | |||
} | |||
public boolean isAnnotation() { | |||
return resolvedTypeX.isAnnotation(); | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return resolvedTypeX.isAnnotationWithRuntimeRetention(); | |||
} | |||
public boolean isAnonymous() { | |||
return resolvedTypeX.isAnonymous(); | |||
} | |||
public boolean isNested() { | |||
return resolvedTypeX.isNested(); | |||
} | |||
public ResolvedType getOuterClass() { | |||
return resolvedTypeX.getOuterClass(); | |||
} | |||
public String getRetentionPolicy() { | |||
return resolvedTypeX.getRetentionPolicy(); | |||
} | |||
public boolean canAnnotationTargetType() { | |||
return resolvedTypeX.canAnnotationTargetType(); | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return resolvedTypeX.getAnnotationTargetKinds(); | |||
} | |||
public boolean isGeneric() { | |||
return resolvedTypeX.isGenericType(); | |||
} | |||
public String getDeclaredGenericSignature() { | |||
return resolvedTypeX.getDeclaredGenericSignature(); | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
return resolvedTypeX.hasAnnotation(ofType); | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
return resolvedTypeX.getAnnotations(); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
return resolvedTypeX.getAnnotationTypes(); | |||
} | |||
public ResolvedMember[] getDeclaredFields() { | |||
return resolvedTypeX.getDeclaredFields(); | |||
} | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
return resolvedTypeX.getDeclaredInterfaces(); | |||
} | |||
public ResolvedMember[] getDeclaredMethods() { | |||
return resolvedTypeX.getDeclaredMethods(); | |||
} | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
return resolvedTypeX.getDeclaredPointcuts(); | |||
} | |||
public PerClause getPerClause() { | |||
return resolvedTypeX.getPerClause(); | |||
} | |||
public Collection getDeclares() { | |||
return resolvedTypeX.getDeclares(); | |||
} | |||
public Collection getTypeMungers() { | |||
return resolvedTypeX.getTypeMungers(); | |||
} | |||
public Collection getPrivilegedAccesses() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
public int getModifiers() { | |||
return resolvedTypeX.getModifiers(); | |||
} | |||
public ResolvedType getSuperclass() { | |||
return resolvedTypeX.getSuperclass(); | |||
} | |||
public WeaverStateInfo getWeaverState() { | |||
return null; | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
return resolvedTypeX.getTypeVariables(); | |||
} | |||
public void ensureDelegateConsistent() { | |||
resolvedTypeX.getDelegate().ensureDelegateConsistent(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,151 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Map; | |||
import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* Representation of a shadow munger for a declare error or warning declaration. | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class Checker extends ShadowMunger { | |||
private final String message; | |||
private final boolean isError; // if not error then it is a warning | |||
private volatile int hashCode = -1; | |||
/** | |||
* Create a Checker for a deow. | |||
* | |||
* @param deow the declare error or warning for which to create the checker munger | |||
*/ | |||
public Checker(DeclareErrorOrWarning deow) { | |||
super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext()); | |||
this.message = deow.getMessage(); | |||
this.isError = deow.isError(); | |||
} | |||
/** | |||
* Only used when filling in a parameterized Checker. | |||
* | |||
* @param pc the pointcut | |||
* @param start the start | |||
* @param end the end | |||
* @param context the source context | |||
* @param message the message string | |||
* @param isError whether it is an error or just a warning | |||
*/ | |||
private Checker(Pointcut pc, int start, int end, ISourceContext context, String message, boolean isError) { | |||
super(pc, start, end, context); | |||
this.message = message; | |||
this.isError = isError; | |||
} | |||
public boolean isError() { | |||
return isError; | |||
} | |||
/** | |||
* Not supported for a Checker | |||
*/ | |||
public void specializeOn(Shadow shadow) { | |||
throw new RuntimeException("illegal state"); | |||
} | |||
/** | |||
* Not supported for a Checker | |||
*/ | |||
public void implementOn(Shadow shadow) { | |||
throw new RuntimeException("illegal state"); | |||
} | |||
/** | |||
* Determine if the Checker matches at a shadow. If it does then we can immediately report the message. There (currently) can | |||
* never be a non-statically determinable match. | |||
* | |||
* @param shadow the shadow which to match against | |||
* @param world the world through which to access message handlers | |||
*/ | |||
public boolean match(Shadow shadow, World world) { | |||
if (super.match(shadow, world)) { | |||
world.reportCheckerMatch(this, shadow); | |||
} | |||
return false; | |||
} | |||
// FIXME what the hell? | |||
public int compareTo(Object other) { | |||
return 0; | |||
} | |||
// FIXME Alex: ATAJ is that ok in all cases ? | |||
/** | |||
* Default to true | |||
* | |||
* @return | |||
*/ | |||
public boolean mustCheckExceptions() { | |||
return true; | |||
} | |||
public Collection getThrownExceptions() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
// FIXME this perhaps ought to take account of the other fields in advice ... | |||
public boolean equals(Object other) { | |||
if (!(other instanceof Checker)) { | |||
return false; | |||
} | |||
Checker o = (Checker) other; | |||
return o.isError == isError && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)); | |||
} | |||
public int hashCode() { | |||
if (hashCode == -1) { | |||
int result = 17; | |||
result = 37 * result + (isError ? 1 : 0); | |||
result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
public ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap) { | |||
Checker ret = new Checker(this.pointcut.parameterizeWith(typeVariableMap, declaringType.getWorld()), this.start, this.end, | |||
this.sourceContext, this.message, this.isError); | |||
return ret; | |||
} | |||
/** | |||
* Concretize this Checker by concretizing the pointcut. | |||
* | |||
*/ | |||
public ShadowMunger concretize(ResolvedType theAspect, World world, PerClause clause) { | |||
this.pointcut = this.pointcut.concretize(theAspect, getDeclaringType(), 0, this); | |||
this.hashCode = -1; | |||
return this; | |||
} | |||
public String getMessage() { | |||
return this.message; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class ClassAnnotationValue extends AnnotationValue { | |||
private String signature; | |||
public ClassAnnotationValue(String sig) { | |||
super(AnnotationValue.CLASS); | |||
this.signature = sig; | |||
} | |||
public String stringify() { | |||
return signature; | |||
} | |||
public String toString() { | |||
return signature; | |||
} | |||
} |
@@ -0,0 +1,144 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.util.PartialOrder; | |||
public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparable { | |||
protected ResolvedTypeMunger munger; | |||
protected ResolvedType aspectType; | |||
public ConcreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) { | |||
this.munger = munger; | |||
this.aspectType = aspectType; | |||
} | |||
// An EclipseTypeMunger and a BcelTypeMunger may say TRUE for equivalentTo()... | |||
// public boolean equivalentTo(Object other) { | |||
// if (! (other instanceof ConcreteTypeMunger)) return false; | |||
// ConcreteTypeMunger o = (ConcreteTypeMunger) other; | |||
// return ((o.getMunger() == null) ? (getMunger() == null) : o.getMunger().equals(getMunger())) | |||
// && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType())); | |||
// } | |||
// public abstract boolean munge(LazyClassGen gen); | |||
/** | |||
* returns null for mungers that are used internally, but were not part of a declared thing in source code. | |||
*/ | |||
public ResolvedTypeMunger getMunger() { | |||
return munger; | |||
} | |||
public ResolvedType getAspectType() { | |||
return aspectType; | |||
} | |||
public ResolvedMember getSignature() { | |||
return munger.getSignature(); | |||
} | |||
public World getWorld() { | |||
return aspectType.getWorld(); | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
if (munger == null) | |||
return null; | |||
return munger.getSourceLocation(); // XXX | |||
} | |||
public boolean matches(ResolvedType onType) { | |||
if (munger == null) | |||
throw new RuntimeException("huh: " + this); | |||
return munger.matches(onType, aspectType); | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member) { | |||
return munger.getMatchingSyntheticMember(member, aspectType); | |||
} | |||
public int compareTo(Object other) { | |||
ConcreteTypeMunger o = (ConcreteTypeMunger) other; | |||
ResolvedType otherAspect = o.aspectType; | |||
if (aspectType.equals(otherAspect)) { | |||
return getSignature().getStart() < o.getSignature().getStart() ? -1 : +1; | |||
} else if (aspectType.isAssignableFrom(o.aspectType)) { | |||
return +1; | |||
} else if (o.aspectType.isAssignableFrom(aspectType)) { | |||
return -1; | |||
} else { | |||
return 0; | |||
} | |||
} | |||
public int fallbackCompareTo(Object other) { | |||
// ConcreteTypeMunger o = (ConcreteTypeMunger) other; | |||
return 0; | |||
} | |||
/** | |||
* returns true if the ITD target type used type variables, for example I<T>. When they are specified like this, the ITDs | |||
* 'share' type variables with the generic type. Usually this method is called because we need to know whether to tailor the | |||
* munger for addition to a particular type. For example: <code> | |||
* interface I<T> {} | |||
* | |||
* aspect X implements I<String> { | |||
* List<T> I<T>.foo { return null; } | |||
* } | |||
* </code> In this case the munger matches X but it matches with the form <code> | |||
* List<String> foo() { return null; } | |||
* </code> | |||
*/ | |||
public boolean isTargetTypeParameterized() { | |||
if (munger == null) | |||
return false; | |||
return munger.sharesTypeVariablesWithGenericType(); | |||
} | |||
/** | |||
* For an ITD made on a generic type that shares type variables with that target type, this method will tailor the ITD for a | |||
* particular usage of the generic type - either in its raw or parameterized form. | |||
*/ | |||
public abstract ConcreteTypeMunger parameterizedFor(ResolvedType targetType); | |||
public boolean isLateMunger() { | |||
if (munger == null) | |||
return false; | |||
return munger.isLateMunger(); | |||
} | |||
public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world); | |||
/** | |||
* Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow() | |||
* pointcut we create a new cflow field in the aspect, and that is added via a BcelCflowCounterFieldAdder. | |||
* | |||
* During compilation we need to compare sets of type mungers, and if some only come into existence after the 'shadowy' type | |||
* things have been processed, we need to ignore them during the comparison. | |||
* | |||
* Returning true from this method indicates the type munger exists to support 'shadowy' stuff - and so can be ignored in some | |||
* comparison. | |||
*/ | |||
public boolean existsToSupportShadowMunging() { | |||
if (munger != null) { | |||
return munger.existsToSupportShadowMunging(); | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Some useful weaver constants. | |||
* | |||
* Current uses: | |||
* 1. Holds values that are necessary for working with 1.5 code but | |||
* which don't exist in a 1.4 world. | |||
*/ | |||
public interface Constants { | |||
public final static int ACC_BRIDGE = 0x0040; | |||
public final static int ACC_VARARGS = 0x0080; | |||
public final static String RUNTIME_LEVEL_12 = "1.2"; | |||
public final static String RUNTIME_LEVEL_15 = "1.5"; | |||
// Default for 1.5.0 | |||
public final static String RUNTIME_LEVEL_DEFAULT = RUNTIME_LEVEL_15; | |||
} |
@@ -0,0 +1,533 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.aspectj.weaver.patterns.Declare; | |||
import org.aspectj.weaver.patterns.DeclareAnnotation; | |||
import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | |||
import org.aspectj.weaver.patterns.DeclareParents; | |||
import org.aspectj.weaver.patterns.DeclarePrecedence; | |||
import org.aspectj.weaver.patterns.DeclareSoft; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.PointcutRewriter; | |||
/** | |||
* This holds on to all members that have an invasive effect outside of there | |||
* own compilation unit. These members need to be all gathered up and in a world | |||
* before any weaving can take place. | |||
* | |||
* They are also important in the compilation process and need to be gathered up | |||
* before the inter-type declaration weaving stage (unsurprisingly). | |||
* | |||
* All members are concrete. | |||
* | |||
* @author Jim Hugunin | |||
*/ | |||
public class CrosscuttingMembers { | |||
private final ResolvedType inAspect; | |||
private final World world; | |||
private PerClause perClause; | |||
private List shadowMungers = new ArrayList(4); | |||
private List typeMungers = new ArrayList(4); | |||
private List lateTypeMungers = new ArrayList(0); | |||
private List declareParents = new ArrayList(4); | |||
private List declareSofts = new ArrayList(0); | |||
private List declareDominates = new ArrayList(4); | |||
// These are like declare parents type mungers | |||
private List declareAnnotationsOnType = new ArrayList(); | |||
private List declareAnnotationsOnField = new ArrayList(); | |||
private List declareAnnotationsOnMethods = new ArrayList(); // includes | |||
// ctors | |||
private boolean shouldConcretizeIfNeeded = true; | |||
public CrosscuttingMembers(ResolvedType inAspect, boolean shouldConcretizeIfNeeded) { | |||
this.inAspect = inAspect; | |||
world = inAspect.getWorld(); | |||
this.shouldConcretizeIfNeeded = shouldConcretizeIfNeeded; | |||
} | |||
private final Hashtable cflowFields = new Hashtable(); | |||
private final Hashtable cflowBelowFields = new Hashtable(); | |||
// public void addConcreteShadowMungers(Collection c) { | |||
// shadowMungers.addAll(c); | |||
// } | |||
public void addConcreteShadowMunger(ShadowMunger m) { | |||
// assert m is concrete | |||
shadowMungers.add(m); | |||
} | |||
public void addShadowMungers(Collection c) { | |||
for (Iterator i = c.iterator(); i.hasNext();) { | |||
addShadowMunger((ShadowMunger) i.next()); | |||
} | |||
} | |||
private void addShadowMunger(ShadowMunger m) { | |||
if (inAspect.isAbstract()) | |||
return; // we don't do mungers for abstract aspects | |||
addConcreteShadowMunger(m.concretize(inAspect, world, perClause)); | |||
} | |||
public void addTypeMungers(Collection c) { | |||
typeMungers.addAll(c); | |||
} | |||
public void addTypeMunger(ConcreteTypeMunger m) { | |||
if (m == null) | |||
throw new Error("FIXME AV - should not happen or what ?");// return; | |||
// //??? | |||
typeMungers.add(m); | |||
} | |||
public void addLateTypeMungers(Collection c) { | |||
lateTypeMungers.addAll(c); | |||
} | |||
public void addLateTypeMunger(ConcreteTypeMunger m) { | |||
lateTypeMungers.add(m); | |||
} | |||
public void addDeclares(Collection c) { | |||
for (Iterator i = c.iterator(); i.hasNext();) { | |||
addDeclare((Declare) i.next()); | |||
} | |||
} | |||
public void addDeclare(Declare declare) { | |||
// this is not extensible, oh well | |||
if (declare instanceof DeclareErrorOrWarning) { | |||
ShadowMunger m = new Checker((DeclareErrorOrWarning) declare); | |||
m.setDeclaringType(declare.getDeclaringType()); | |||
addShadowMunger(m); | |||
} else if (declare instanceof DeclarePrecedence) { | |||
declareDominates.add(declare); | |||
} else if (declare instanceof DeclareParents) { | |||
DeclareParents dp = (DeclareParents) declare; | |||
exposeTypes(dp.getParents().getExactTypes()); | |||
declareParents.add(dp); | |||
} else if (declare instanceof DeclareSoft) { | |||
DeclareSoft d = (DeclareSoft) declare; | |||
// Ordered so that during concretization we can check the related | |||
// munger | |||
ShadowMunger m = Advice.makeSoftener(world, d.getPointcut(), d.getException(), inAspect, d); | |||
m.setDeclaringType(d.getDeclaringType()); | |||
Pointcut concretePointcut = d.getPointcut().concretize(inAspect, d.getDeclaringType(), 0, m); | |||
m.pointcut = concretePointcut; | |||
declareSofts.add(new DeclareSoft(d.getException(), concretePointcut)); | |||
addConcreteShadowMunger(m); | |||
} else if (declare instanceof DeclareAnnotation) { | |||
// FIXME asc perf Possible Improvement. Investigate why this is | |||
// called twice in a weave ? | |||
DeclareAnnotation da = (DeclareAnnotation) declare; | |||
if (da.getAspect() == null) | |||
da.setAspect(inAspect); | |||
if (da.isDeclareAtType()) { | |||
declareAnnotationsOnType.add(da); | |||
} else if (da.isDeclareAtField()) { | |||
declareAnnotationsOnField.add(da); | |||
} else if (da.isDeclareAtMethod() || da.isDeclareAtConstuctor()) { | |||
declareAnnotationsOnMethods.add(da); | |||
} | |||
} else { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
} | |||
public void exposeTypes(Collection typesToExpose) { | |||
for (Iterator i = typesToExpose.iterator(); i.hasNext();) { | |||
exposeType((UnresolvedType) i.next()); | |||
} | |||
} | |||
public void exposeType(UnresolvedType typeToExpose) { | |||
if (ResolvedType.isMissing(typeToExpose)) | |||
return; | |||
if (typeToExpose.isParameterizedType() || typeToExpose.isRawType()) { | |||
if (typeToExpose instanceof ResolvedType) { | |||
typeToExpose = ((ResolvedType) typeToExpose).getGenericType(); | |||
} else { | |||
typeToExpose = UnresolvedType.forSignature(typeToExpose.getErasureSignature()); | |||
} | |||
} | |||
// Check we haven't already got a munger for this: | |||
String signatureToLookFor = typeToExpose.getSignature(); | |||
for (Iterator iterator = typeMungers.iterator(); iterator.hasNext();) { | |||
ConcreteTypeMunger cTM = (ConcreteTypeMunger) iterator.next(); | |||
ResolvedTypeMunger rTM = cTM.getMunger(); | |||
if (rTM != null && rTM instanceof ExposeTypeMunger) { | |||
String exposedType = ((ExposeTypeMunger) rTM).getExposedTypeSignature(); | |||
if (exposedType.equals(signatureToLookFor)) | |||
return; // dont need to bother | |||
} | |||
} | |||
addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new ExposeTypeMunger(typeToExpose), inAspect)); | |||
// ResolvedMember member = new ResolvedMemberImpl( | |||
// Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, | |||
// "<clinit>", UnresolvedType.NONE); | |||
// addTypeMunger(world.concreteTypeMunger( | |||
// new PrivilegedAccessMunger(member), inAspect)); | |||
} | |||
public void addPrivilegedAccesses(Collection accessedMembers) { | |||
for (Iterator i = accessedMembers.iterator(); i.hasNext();) { | |||
addPrivilegedAccess((ResolvedMember) i.next()); | |||
} | |||
} | |||
private void addPrivilegedAccess(ResolvedMember member) { | |||
// System.err.println("add priv access: " + member); | |||
addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new PrivilegedAccessMunger(member), inAspect)); | |||
} | |||
public Collection getCflowEntries() { | |||
ArrayList ret = new ArrayList(); | |||
for (Iterator i = shadowMungers.iterator(); i.hasNext();) { | |||
ShadowMunger m = (ShadowMunger) i.next(); | |||
if (m instanceof Advice) { | |||
Advice a = (Advice) m; | |||
if (a.getKind().isCflow()) { | |||
ret.add(a); | |||
} | |||
} | |||
} | |||
return ret; | |||
} | |||
/** | |||
* Updates the records if something has changed. This is called at most | |||
* twice, firstly whilst collecting ITDs and declares. At this point the | |||
* CrosscuttingMembers we're comparing ourselves with doesn't know about | |||
* shadowmungers. Therefore a straight comparison with the existing list of | |||
* shadowmungers would return that something has changed even though it | |||
* might not have, so in this first round we ignore the shadowMungers. The | |||
* second time this is called is whilst we're preparing to weave. At this | |||
* point we know everything in the system and so we're able to compare the | |||
* shadowMunger list. (see bug 129163) | |||
* | |||
* @param other | |||
* @param careAboutShadowMungers | |||
* @return true if something has changed since the last time this method was | |||
* called, false otherwise | |||
*/ | |||
public boolean replaceWith(CrosscuttingMembers other, boolean careAboutShadowMungers) { | |||
boolean changed = false; | |||
if (careAboutShadowMungers) { | |||
if (perClause == null || !perClause.equals(other.perClause)) { | |||
changed = true; | |||
perClause = other.perClause; | |||
} | |||
} | |||
// XXX all of the below should be set equality rather than list equality | |||
// System.err.println("old: " + shadowMungers + " new: " + | |||
// other.shadowMungers); | |||
if (careAboutShadowMungers) { | |||
// bug 129163: use set equality rather than list equality | |||
Set theseShadowMungers = new HashSet(); | |||
Set theseInlinedAroundMungers = new HashSet(); | |||
for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) { | |||
ShadowMunger munger = (ShadowMunger) iter.next(); | |||
if (munger instanceof Advice) { | |||
Advice adviceMunger = (Advice) munger; | |||
// bug 154054: if we're around advice that has been inlined | |||
// then we need to do more checking than existing equals | |||
// methods allow | |||
if (!world.isXnoInline() && adviceMunger.getKind().equals(AdviceKind.Around)) { | |||
theseInlinedAroundMungers.add(adviceMunger); | |||
} else { | |||
theseShadowMungers.add(adviceMunger); | |||
} | |||
} else { | |||
theseShadowMungers.add(munger); | |||
} | |||
} | |||
Set tempSet = new HashSet(); | |||
tempSet.addAll(other.shadowMungers); | |||
Set otherShadowMungers = new HashSet(); | |||
Set otherInlinedAroundMungers = new HashSet(); | |||
for (Iterator iter = tempSet.iterator(); iter.hasNext();) { | |||
ShadowMunger munger = (ShadowMunger) iter.next(); | |||
if (munger instanceof Advice) { | |||
Advice adviceMunger = (Advice) munger; | |||
// bug 154054: if we're around advice that has been inlined | |||
// then we need to do more checking than existing equals | |||
// methods allow | |||
if (!world.isXnoInline() && adviceMunger.getKind().equals(AdviceKind.Around)) { | |||
otherInlinedAroundMungers.add(rewritePointcutInMunger(adviceMunger)); | |||
} else { | |||
otherShadowMungers.add(rewritePointcutInMunger(adviceMunger)); | |||
} | |||
} else { | |||
otherShadowMungers.add(rewritePointcutInMunger(munger)); | |||
} | |||
} | |||
if (!theseShadowMungers.equals(otherShadowMungers)) { | |||
changed = true; | |||
} | |||
if (!equivalent(theseInlinedAroundMungers, otherInlinedAroundMungers)) { | |||
changed = true; | |||
} | |||
// bug 158573 - if there are no changes then preserve whether | |||
// or not a particular shadowMunger has matched something. | |||
if (!changed) { | |||
for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) { | |||
ShadowMunger munger = (ShadowMunger) iter.next(); | |||
int i = other.shadowMungers.indexOf(munger); | |||
ShadowMunger otherMunger = (ShadowMunger) other.shadowMungers.get(i); | |||
if (munger instanceof Advice) { | |||
((Advice) otherMunger).setHasMatchedSomething(((Advice) munger).hasMatchedSomething()); | |||
} | |||
} | |||
} | |||
// replace the existing list of shadowmungers with the | |||
// new ones in case anything like the sourcelocation has | |||
// changed, however, don't want this flagged as a change | |||
// which will force a full build - bug 134541 | |||
shadowMungers = other.shadowMungers; | |||
} | |||
// bug 129163: use set equality rather than list equality and | |||
// if we dont care about shadow mungers then ignore those | |||
// typeMungers which are created to help with the implementation | |||
// of shadowMungers | |||
Set theseTypeMungers = new HashSet(); | |||
Set otherTypeMungers = new HashSet(); | |||
if (!careAboutShadowMungers) { | |||
for (Iterator iter = typeMungers.iterator(); iter.hasNext();) { | |||
Object o = iter.next(); | |||
if (o instanceof ConcreteTypeMunger) { | |||
ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) o; | |||
if (!typeMunger.existsToSupportShadowMunging()) { | |||
theseTypeMungers.add(typeMunger); | |||
} | |||
} else { | |||
theseTypeMungers.add(o); | |||
} | |||
} | |||
for (Iterator iter = other.typeMungers.iterator(); iter.hasNext();) { | |||
Object o = iter.next(); | |||
if (o instanceof ConcreteTypeMunger) { | |||
ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) o; | |||
if (!typeMunger.existsToSupportShadowMunging()) { | |||
otherTypeMungers.add(typeMunger); | |||
} | |||
} else { | |||
otherTypeMungers.add(o); | |||
} | |||
} | |||
} else { | |||
theseTypeMungers.addAll(typeMungers); | |||
otherTypeMungers.addAll(other.typeMungers); | |||
} | |||
// initial go at equivalence logic rather than set compare (see | |||
// pr133532) | |||
// if (theseTypeMungers.size()!=otherTypeMungers.size()) { | |||
// changed = true; | |||
// typeMungers = other.typeMungers; | |||
// } else { | |||
// boolean foundInequality=false; | |||
// for (Iterator iter = theseTypeMungers.iterator(); iter.hasNext() && | |||
// !foundInequality;) { | |||
// Object thisOne = (Object) iter.next(); | |||
// boolean foundInOtherSet = false; | |||
// for (Iterator iterator = otherTypeMungers.iterator(); | |||
// iterator.hasNext();) { | |||
// Object otherOne = (Object) iterator.next(); | |||
// if (thisOne instanceof ConcreteTypeMunger && otherOne instanceof | |||
// ConcreteTypeMunger) { | |||
// if (((ConcreteTypeMunger)thisOne).equivalentTo(otherOne)) { | |||
// foundInOtherSet=true; | |||
// } else if (thisOne.equals(otherOne)) { | |||
// foundInOtherSet=true; | |||
// } | |||
// } else { | |||
// if (thisOne.equals(otherOne)) { | |||
// foundInOtherSet=true; | |||
// } | |||
// } | |||
// } | |||
// if (!foundInOtherSet) foundInequality=true; | |||
// } | |||
// if (foundInequality) { | |||
// changed = true; | |||
// typeMungers = other.typeMungers; | |||
// // } else { | |||
// // typeMungers = other.typeMungers; | |||
// } | |||
// } | |||
if (!theseTypeMungers.equals(otherTypeMungers)) { | |||
changed = true; | |||
typeMungers = other.typeMungers; | |||
} | |||
if (!lateTypeMungers.equals(other.lateTypeMungers)) { | |||
changed = true; | |||
lateTypeMungers = other.lateTypeMungers; | |||
} | |||
if (!declareDominates.equals(other.declareDominates)) { | |||
changed = true; | |||
declareDominates = other.declareDominates; | |||
} | |||
if (!declareParents.equals(other.declareParents)) { | |||
changed = true; | |||
declareParents = other.declareParents; | |||
} | |||
if (!declareSofts.equals(other.declareSofts)) { | |||
changed = true; | |||
declareSofts = other.declareSofts; | |||
} | |||
// DECAT for when attempting to replace an aspect | |||
if (!declareAnnotationsOnType.equals(other.declareAnnotationsOnType)) { | |||
changed = true; | |||
declareAnnotationsOnType = other.declareAnnotationsOnType; | |||
} | |||
if (!declareAnnotationsOnField.equals(other.declareAnnotationsOnField)) { | |||
changed = true; | |||
declareAnnotationsOnField = other.declareAnnotationsOnField; | |||
} | |||
if (!declareAnnotationsOnMethods.equals(other.declareAnnotationsOnMethods)) { | |||
changed = true; | |||
declareAnnotationsOnMethods = other.declareAnnotationsOnMethods; | |||
} | |||
return changed; | |||
} | |||
private boolean equivalent(Set theseInlinedAroundMungers, Set otherInlinedAroundMungers) { | |||
if (theseInlinedAroundMungers.size() != otherInlinedAroundMungers.size()) { | |||
return false; | |||
} | |||
for (Iterator iter = theseInlinedAroundMungers.iterator(); iter.hasNext();) { | |||
Advice thisAdvice = (Advice) iter.next(); | |||
boolean foundIt = false; | |||
for (Iterator iterator = otherInlinedAroundMungers.iterator(); iterator.hasNext();) { | |||
Advice otherAdvice = (Advice) iterator.next(); | |||
if (thisAdvice.equals(otherAdvice)) { | |||
if (thisAdvice.getSignature() instanceof ResolvedMemberImpl) { | |||
if (((ResolvedMemberImpl) thisAdvice.getSignature()).isEquivalentTo(otherAdvice.getSignature())) { | |||
foundIt = true; | |||
continue; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
if (!foundIt) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
private ShadowMunger rewritePointcutInMunger(ShadowMunger munger) { | |||
PointcutRewriter pr = new PointcutRewriter(); | |||
Pointcut p = munger.getPointcut(); | |||
Pointcut newP = pr.rewrite(p); | |||
if (p.m_ignoreUnboundBindingForNames.length != 0) {// *sigh* dirty fix | |||
// for dirty hacky | |||
// implementation | |||
// pr149305 | |||
newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames; | |||
} | |||
munger.setPointcut(newP); | |||
return munger; | |||
} | |||
public void setPerClause(PerClause perClause) { | |||
if (shouldConcretizeIfNeeded) { | |||
this.perClause = perClause.concretize(inAspect); | |||
} else { | |||
this.perClause = perClause; | |||
} | |||
} | |||
public List getDeclareDominates() { | |||
return declareDominates; | |||
} | |||
public List getDeclareParents() { | |||
return declareParents; | |||
} | |||
public List getDeclareSofts() { | |||
return declareSofts; | |||
} | |||
public List getShadowMungers() { | |||
return shadowMungers; | |||
} | |||
public List getTypeMungers() { | |||
return typeMungers; | |||
} | |||
public List getLateTypeMungers() { | |||
return lateTypeMungers; | |||
} | |||
public List getDeclareAnnotationOnTypes() { | |||
return declareAnnotationsOnType; | |||
} | |||
public List getDeclareAnnotationOnFields() { | |||
return declareAnnotationsOnField; | |||
} | |||
/** | |||
* includes declare @method and @constructor | |||
*/ | |||
public List getDeclareAnnotationOnMethods() { | |||
return declareAnnotationsOnMethods; | |||
} | |||
public Map getCflowBelowFields() { | |||
return cflowBelowFields; | |||
} | |||
public Map getCflowFields() { | |||
return cflowFields; | |||
} | |||
public void clearCaches() { | |||
cflowFields.clear(); | |||
cflowBelowFields.clear(); | |||
} | |||
} |
@@ -0,0 +1,305 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.aspectj.weaver.patterns.DeclareParents; | |||
import org.aspectj.weaver.patterns.IVerificationRequired; | |||
import org.aspectj.weaver.tools.Trace; | |||
import org.aspectj.weaver.tools.TraceFactory; | |||
/** | |||
* This holds on to all CrosscuttingMembers for a world. It handles management of change. | |||
* | |||
* @author Jim Hugunin | |||
*/ | |||
public class CrosscuttingMembersSet { | |||
// FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice | |||
private final Map /* ResolvedType (the aspect) > CrosscuttingMembers */members = new HashMap(); | |||
private List shadowMungers = null; | |||
private List typeMungers = null; | |||
private List lateTypeMungers = null; | |||
private List declareSofts = null; | |||
private List declareParents = null; | |||
private List declareAnnotationOnTypes = null; | |||
private List declareAnnotationOnFields = null; | |||
private List declareAnnotationOnMethods = null; // includes ctors | |||
private List declareDominates = null; | |||
private boolean changedSinceLastReset = false; | |||
private List /* IVerificationRequired */verificationList = null; // List of things to be verified once the type system is | |||
// 'complete' | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(CrosscuttingMembersSet.class); | |||
public CrosscuttingMembersSet(World world) { | |||
trace.enter("<init>", this, world); | |||
trace.exit("<init>"); | |||
} | |||
public boolean addOrReplaceAspect(ResolvedType aspectType) { | |||
return addOrReplaceAspect(aspectType, true); | |||
} | |||
/** | |||
* @return whether or not that was a change to the global signature XXX for efficiency we will need a richer representation than | |||
* this | |||
*/ | |||
public boolean addOrReplaceAspect(ResolvedType aspectType, boolean inWeavingPhase) { | |||
trace.enter("addOrReplaceAspect", this, new Object[] { aspectType, new Boolean(inWeavingPhase) }); | |||
boolean change = false; | |||
CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType); | |||
if (xcut == null) { | |||
members.put(aspectType, aspectType.collectCrosscuttingMembers(inWeavingPhase)); | |||
clearCaches(); | |||
change = true; | |||
} else { | |||
if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase), inWeavingPhase)) { | |||
clearCaches(); | |||
change = true; | |||
} else { | |||
if (inWeavingPhase) { | |||
// bug 134541 - even though we haven't changed we may have updated the | |||
// sourcelocation for the shadowMunger which we need to pick up | |||
shadowMungers = null; | |||
} | |||
change = false; | |||
} | |||
} | |||
if (aspectType.isAbstract()) { | |||
// we might have sub-aspects that need to re-collect their crosscutting members from us | |||
boolean ancestorChange = addOrReplaceDescendantsOf(aspectType, inWeavingPhase); | |||
change = change || ancestorChange; | |||
} | |||
changedSinceLastReset = changedSinceLastReset || change; | |||
trace.exit("addOrReplaceAspect", change); | |||
return change; | |||
} | |||
private boolean addOrReplaceDescendantsOf(ResolvedType aspectType, boolean inWeavePhase) { | |||
// System.err.println("Looking at descendants of "+aspectType.getName()); | |||
Set knownAspects = members.keySet(); | |||
Set toBeReplaced = new HashSet(); | |||
for (Iterator it = knownAspects.iterator(); it.hasNext();) { | |||
ResolvedType candidateDescendant = (ResolvedType) it.next(); | |||
if ((candidateDescendant != aspectType) && (aspectType.isAssignableFrom(candidateDescendant))) { | |||
toBeReplaced.add(candidateDescendant); | |||
} | |||
} | |||
boolean change = false; | |||
for (Iterator it = toBeReplaced.iterator(); it.hasNext();) { | |||
ResolvedType next = (ResolvedType) it.next(); | |||
boolean thisChange = addOrReplaceAspect(next, inWeavePhase); | |||
change = change || thisChange; | |||
} | |||
return change; | |||
} | |||
public void addAdviceLikeDeclares(ResolvedType aspectType) { | |||
CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType); | |||
xcut.addDeclares(aspectType.collectDeclares(true)); | |||
} | |||
public boolean deleteAspect(UnresolvedType aspectType) { | |||
boolean isAspect = members.remove(aspectType) != null; | |||
clearCaches(); | |||
return isAspect; | |||
} | |||
public boolean containsAspect(UnresolvedType aspectType) { | |||
return members.containsKey(aspectType); | |||
} | |||
// XXX only for testing | |||
public void addFixedCrosscuttingMembers(ResolvedType aspectType) { | |||
members.put(aspectType, aspectType.crosscuttingMembers); | |||
clearCaches(); | |||
} | |||
private void clearCaches() { | |||
shadowMungers = null; | |||
typeMungers = null; | |||
lateTypeMungers = null; | |||
declareSofts = null; | |||
declareParents = null; | |||
declareAnnotationOnFields = null; | |||
declareAnnotationOnMethods = null; | |||
declareAnnotationOnTypes = null; | |||
declareDominates = null; | |||
} | |||
public List getShadowMungers() { | |||
if (shadowMungers == null) { | |||
ArrayList ret = new ArrayList(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getShadowMungers()); | |||
} | |||
shadowMungers = ret; | |||
} | |||
return shadowMungers; | |||
} | |||
public List getTypeMungers() { | |||
if (typeMungers == null) { | |||
ArrayList ret = new ArrayList(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getTypeMungers()); | |||
} | |||
typeMungers = ret; | |||
} | |||
return typeMungers; | |||
} | |||
public List getLateTypeMungers() { | |||
if (lateTypeMungers == null) { | |||
ArrayList ret = new ArrayList(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getLateTypeMungers()); | |||
} | |||
lateTypeMungers = ret; | |||
} | |||
return lateTypeMungers; | |||
} | |||
public List getDeclareSofts() { | |||
if (declareSofts == null) { | |||
Set ret = new HashSet(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareSofts()); | |||
} | |||
declareSofts = new ArrayList(); | |||
declareSofts.addAll(ret); | |||
} | |||
return declareSofts; | |||
} | |||
public List getDeclareParents() { | |||
if (declareParents == null) { | |||
Set ret = new HashSet(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareParents()); | |||
} | |||
declareParents = new ArrayList(); | |||
declareParents.addAll(ret); | |||
} | |||
return declareParents; | |||
} | |||
// DECAT Merge multiple together | |||
public List getDeclareAnnotationOnTypes() { | |||
if (declareAnnotationOnTypes == null) { | |||
Set ret = new HashSet(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnTypes()); | |||
} | |||
declareAnnotationOnTypes = new ArrayList(); | |||
declareAnnotationOnTypes.addAll(ret); | |||
} | |||
return declareAnnotationOnTypes; | |||
} | |||
public List getDeclareAnnotationOnFields() { | |||
if (declareAnnotationOnFields == null) { | |||
Set ret = new HashSet(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnFields()); | |||
} | |||
declareAnnotationOnFields = new ArrayList(); | |||
declareAnnotationOnFields.addAll(ret); | |||
} | |||
return declareAnnotationOnFields; | |||
} | |||
/** | |||
* Return an amalgamation of the declare @method/@constructor statements. | |||
*/ | |||
public List getDeclareAnnotationOnMethods() { | |||
if (declareAnnotationOnMethods == null) { | |||
Set ret = new HashSet(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnMethods()); | |||
} | |||
declareAnnotationOnMethods = new ArrayList(); | |||
declareAnnotationOnMethods.addAll(ret); | |||
} | |||
return declareAnnotationOnMethods; | |||
} | |||
public List getDeclareDominates() { | |||
if (declareDominates == null) { | |||
ArrayList ret = new ArrayList(); | |||
for (Iterator i = members.values().iterator(); i.hasNext();) { | |||
ret.addAll(((CrosscuttingMembers) i.next()).getDeclareDominates()); | |||
} | |||
declareDominates = ret; | |||
} | |||
return declareDominates; | |||
} | |||
public ResolvedType findAspectDeclaringParents(DeclareParents p) { | |||
Set keys = this.members.keySet(); | |||
for (Iterator iter = keys.iterator(); iter.hasNext();) { | |||
ResolvedType element = (ResolvedType) iter.next(); | |||
for (Iterator i = ((CrosscuttingMembers) members.get(element)).getDeclareParents().iterator(); i.hasNext();) { | |||
DeclareParents dp = (DeclareParents) i.next(); | |||
if (dp.equals(p)) | |||
return element; | |||
} | |||
} | |||
return null; | |||
} | |||
public void reset() { | |||
verificationList = null; | |||
changedSinceLastReset = false; | |||
} | |||
public boolean hasChangedSinceLastReset() { | |||
return changedSinceLastReset; | |||
} | |||
/** | |||
* Record something that needs verifying when we believe the type system is complete. Used for things that can't be verified as | |||
* we go along - for example some recursive type variable references (pr133307) | |||
*/ | |||
public void recordNecessaryCheck(IVerificationRequired verification) { | |||
if (verificationList == null) | |||
verificationList = new ArrayList(); | |||
verificationList.add(verification); | |||
} | |||
/** | |||
* Called when type bindings are complete - calls all registered verification objects in turn. | |||
*/ | |||
public void verify() { | |||
if (verificationList == null) | |||
return; | |||
for (Iterator iter = verificationList.iterator(); iter.hasNext();) { | |||
IVerificationRequired element = (IVerificationRequired) iter.next(); | |||
element.verify(); | |||
} | |||
verificationList = null; | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2007 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Linton Ye https://bugs.eclipse.org/bugs/show_bug.cgi?id=193065 | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
/** | |||
* <p> | |||
* This interface is introduced to support tools like PointcutDoctor. | |||
* </p> | |||
* <p> | |||
* A CustomMungerFactory is used to create ShadowMungers and/or | |||
* ConcreteTypeMungers so that an extender can extract extra information during | |||
* the weaving process. | |||
* </p> | |||
* <p> | |||
* A CustomMungerFactory is assigned to a weaver through its AjCompiler in | |||
* extenders' code, and gets invoked by the weaver right before the weaving | |||
* starts. The custom shadow/type mungers being created will be added into the | |||
* shadow/type munger list in the weaver and participate the weaving process. | |||
* For example, the match method of each custom shadow munger will be called | |||
* against each shadow. | |||
* </p> | |||
* @author lintonye | |||
* | |||
*/ | |||
public interface CustomMungerFactory { | |||
/** | |||
* @param aspectType | |||
* @return a Collection<ShadowMunger> of custom shadow mungers for the | |||
* given aspect | |||
*/ | |||
public Collection/* ShadowMunger */createCustomShadowMungers( | |||
ResolvedType aspectType); | |||
/** | |||
* @param aspectType | |||
* @return a Collection<ConcreteTypeMunger> of custom type mungers for the | |||
* given aspect | |||
*/ | |||
public Collection/* ConcreteTypeMunger */createCustomTypeMungers( | |||
ResolvedType aspectType); | |||
public Collection/* ShadowMunger */getAllCreatedCustomShadowMungers(); | |||
public Collection/* ConcreteTypeMunger */getAllCreatedCustomTypeMungers(); | |||
} |
@@ -0,0 +1,506 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2004 IBM Corporation | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Matthew Webster | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.PrintStream; | |||
import java.lang.ref.WeakReference; | |||
import java.net.URL; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Properties; | |||
import java.util.Set; | |||
import java.util.WeakHashMap; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.IMessageHolder; | |||
import org.aspectj.bridge.Version; | |||
import org.aspectj.weaver.tools.Trace; | |||
import org.aspectj.weaver.tools.TraceFactory; | |||
import org.aspectj.weaver.tools.Traceable; | |||
/** | |||
* @author websterm | |||
* | |||
* To change the template for this generated type comment go to | |||
* Window>Preferences>Java>Code Generation>Code and Comments | |||
*/ | |||
public class Dump { | |||
public final static String DUMP_CONDITION_PROPERTY = "org.aspectj.weaver.Dump.condition"; | |||
public final static String DUMP_DIRECTORY_PROPERTY = "org.aspectj.dump.directory"; | |||
/* Format for unique filename based on date & time */ | |||
private static final String FILENAME_PREFIX = "ajcore"; | |||
// private static final DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); | |||
// private static final DateFormat timeFormat = new SimpleDateFormat("HHmmss.SSS"); | |||
private static final String FILENAME_SUFFIX = "txt"; | |||
public static final String UNKNOWN_FILENAME = "Unknown"; | |||
public static final String DUMP_EXCLUDED = "Excluded"; | |||
public static final String NULL_OR_EMPTY = "Empty"; | |||
private static Class exceptionClass; | |||
private static IMessage.Kind conditionKind = IMessage.ABORT; | |||
private static File directory = new File("."); | |||
private String reason; | |||
private String fileName; | |||
private PrintStream print; | |||
private static String[] savedCommandLine; | |||
private static List savedFullClasspath; | |||
private static IMessageHolder savedMessageHolder; | |||
private static Map nodes = new WeakHashMap(); | |||
private static String lastDumpFileName = UNKNOWN_FILENAME; | |||
private static boolean preserveOnNextReset = false; | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(Dump.class); | |||
/** | |||
* for testing only, so that we can verify dump contents | |||
* after compilation has completely finished | |||
*/ | |||
public static void preserveOnNextReset() { | |||
preserveOnNextReset = true; | |||
} | |||
public static void reset() { | |||
if (preserveOnNextReset) { | |||
preserveOnNextReset = false; | |||
return; | |||
} | |||
else { | |||
nodes.clear(); | |||
savedMessageHolder = null; | |||
} | |||
} | |||
/* | |||
* Dump methods | |||
*/ | |||
public static String dump (String reason) { | |||
String fileName = UNKNOWN_FILENAME; | |||
Dump dump = null; | |||
try { | |||
dump = new Dump(reason); | |||
fileName = dump.getFileName(); | |||
dump.dumpDefault(); | |||
} | |||
finally { | |||
if (dump != null) dump.close(); | |||
} | |||
return fileName; | |||
} | |||
public static String dumpWithException (Throwable th) { | |||
return dumpWithException(savedMessageHolder,th); | |||
} | |||
public static String dumpWithException (IMessageHolder messageHolder, Throwable th) { | |||
if (trace.isTraceEnabled()) trace.enter("dumpWithException",null,new Object[] {messageHolder, th}); | |||
String fileName = UNKNOWN_FILENAME; | |||
Dump dump = null; | |||
try { | |||
dump = new Dump(th.getClass().getName()); | |||
fileName = dump.getFileName(); | |||
dump.dumpException(messageHolder,th); | |||
} | |||
finally { | |||
if (dump != null) dump.close(); | |||
} | |||
if (trace.isTraceEnabled()) trace.exit("dumpWithException",fileName); | |||
return fileName; | |||
} | |||
public static String dumpOnExit () { | |||
return dumpOnExit(savedMessageHolder, false); | |||
} | |||
public static String dumpOnExit (IMessageHolder messageHolder, boolean reset) { | |||
if (trace.isTraceEnabled()) trace.enter("dumpOnExit",null,messageHolder); | |||
String fileName = UNKNOWN_FILENAME; | |||
if (!shouldDumpOnExit(messageHolder)) { | |||
fileName = DUMP_EXCLUDED; | |||
} | |||
else { | |||
Dump dump = null; | |||
try { | |||
dump = new Dump(conditionKind.toString()); | |||
fileName = dump.getFileName(); | |||
dump.dumpDefault(messageHolder); | |||
} | |||
finally { | |||
if (dump != null) dump.close(); | |||
} | |||
} | |||
if (reset) messageHolder.clearMessages(); | |||
if (trace.isTraceEnabled()) trace.exit("dumpOnExit",fileName); | |||
return fileName; | |||
} | |||
private static boolean shouldDumpOnExit (IMessageHolder messageHolder) { | |||
if (trace.isTraceEnabled()) trace.enter("shouldDumpOnExit",null,messageHolder); | |||
if (trace.isTraceEnabled()) trace.event("shouldDumpOnExit",null,conditionKind); | |||
boolean result = (messageHolder == null) || messageHolder.hasAnyMessage(conditionKind,true); | |||
if (trace.isTraceEnabled()) trace.exit("shouldDumpOnExit",result); | |||
return result; | |||
} | |||
/* | |||
* Dump configuration | |||
*/ | |||
public static void setDumpOnException (boolean b) { | |||
if (b) { | |||
exceptionClass = java.lang.Throwable.class; | |||
} | |||
else { | |||
exceptionClass = null; | |||
} | |||
} | |||
public static boolean setDumpDirectory (String directoryName) { | |||
if (trace.isTraceEnabled()) trace.enter("setDumpDirectory",null,directoryName); | |||
boolean success = false; | |||
File newDirectory = new File(directoryName); | |||
if (newDirectory.exists()) { | |||
directory = newDirectory; | |||
success = true; | |||
} | |||
if (trace.isTraceEnabled()) trace.exit("setDumpDirectory",success); | |||
return success; | |||
} | |||
public static boolean getDumpOnException () { | |||
return (exceptionClass != null); | |||
} | |||
public static boolean setDumpOnExit (IMessage.Kind condition) { | |||
if (trace.isTraceEnabled()) trace.event("setDumpOnExit",null,condition); | |||
conditionKind = condition; | |||
return true; | |||
} | |||
public static boolean setDumpOnExit (String condition) { | |||
for (Iterator i = IMessage.KINDS.iterator(); i.hasNext();) { | |||
IMessage.Kind kind = (IMessage.Kind)i.next(); | |||
if (kind.toString().equals(condition)) { | |||
return setDumpOnExit(kind); | |||
} | |||
} | |||
return false; | |||
} | |||
public static IMessage.Kind getDumpOnExit () { | |||
return conditionKind; | |||
} | |||
public static String getLastDumpFileName () { | |||
return lastDumpFileName; | |||
} | |||
/* | |||
* Dump registration | |||
*/ | |||
public static void saveCommandLine (String[] args) { | |||
savedCommandLine = new String[args.length]; | |||
System.arraycopy(args,0,savedCommandLine,0,args.length); | |||
} | |||
public static void saveFullClasspath (List list) { | |||
savedFullClasspath = list; | |||
} | |||
public static void saveMessageHolder (IMessageHolder holder) { | |||
savedMessageHolder = holder; | |||
} | |||
public static void registerNode (Class module, INode newNode) { | |||
if (trace.isTraceEnabled()) trace.enter("registerNode",null,new Object[] { module, newNode} ); | |||
nodes.put(newNode,new WeakReference(newNode)); | |||
if (trace.isTraceEnabled()) trace.exit("registerNode",nodes.size()); | |||
} | |||
/* | |||
* Dump methods | |||
*/ | |||
private Dump (String reason) { | |||
if (trace.isTraceEnabled()) trace.enter("<init>",this,reason); | |||
this.reason = reason; | |||
openDump(); | |||
dumpAspectJProperties(); | |||
dumpDumpConfiguration(); | |||
if (trace.isTraceEnabled()) trace.exit("<init>",this); | |||
} | |||
public String getFileName() { | |||
return fileName; | |||
} | |||
private void dumpDefault () { | |||
dumpDefault(savedMessageHolder); | |||
} | |||
private void dumpDefault (IMessageHolder holder) { | |||
dumpSytemProperties(); | |||
dumpCommandLine(); | |||
dumpFullClasspath(); | |||
dumpCompilerMessages(holder); | |||
dumpNodes(); | |||
} | |||
private void dumpNodes() { | |||
/* | |||
* Dump registered nodes | |||
*/ | |||
IVisitor dumpVisitor = new IVisitor() { | |||
public void visitObject (Object obj) { | |||
println(formatObj(obj)); | |||
} | |||
public void visitList (List list) { | |||
println(list); | |||
} | |||
}; | |||
Set keys = nodes.keySet(); | |||
for (Iterator i = keys.iterator(); i.hasNext();) { | |||
Object module = i.next(); | |||
// INode dumpNode = (INode)nodes.get(module); | |||
INode dumpNode = (INode)module; | |||
println("---- " + formatObj(dumpNode) + " ----"); | |||
try { | |||
dumpNode.accept(dumpVisitor); | |||
} | |||
catch (Exception ex) { | |||
trace.error(formatObj(dumpNode).toString(),ex); | |||
} | |||
} | |||
} | |||
private void dumpException (IMessageHolder messageHolder, Throwable th) { | |||
println("---- Exception Information ---"); | |||
println(th); | |||
dumpDefault(messageHolder); | |||
} | |||
private void dumpAspectJProperties () { | |||
println("---- AspectJ Properties ---"); | |||
println("AspectJ Compiler " + Version.text + " built on " + Version.time_text); | |||
} | |||
private void dumpDumpConfiguration () { | |||
println("---- Dump Properties ---"); | |||
println("Dump file: " + fileName); | |||
println("Dump reason: " + reason); | |||
println("Dump on exception: " + (exceptionClass != null)); | |||
println("Dump at exit condition: " + conditionKind); | |||
} | |||
private void dumpFullClasspath () { | |||
println("---- Full Classpath ---"); | |||
if (savedFullClasspath != null && savedFullClasspath.size() > 0) { | |||
for (Iterator iter = savedFullClasspath.iterator(); iter.hasNext(); ) { | |||
String fileName = (String)iter.next(); | |||
File file = new File(fileName); | |||
println(file); | |||
} | |||
} | |||
else { | |||
println(NULL_OR_EMPTY); | |||
} | |||
} | |||
private void dumpSytemProperties () { | |||
println("---- System Properties ---"); | |||
Properties props = System.getProperties(); | |||
println(props); | |||
} | |||
private void dumpCommandLine () { | |||
println("---- Command Line ---"); | |||
println(savedCommandLine); | |||
} | |||
private void dumpCompilerMessages (IMessageHolder messageHolder) { | |||
println("---- Compiler Messages ---"); | |||
if (messageHolder != null) for (Iterator i = messageHolder.getUnmodifiableListView().iterator(); i.hasNext(); ) { | |||
IMessage message = (IMessage)i.next(); | |||
println(message.toString()); | |||
} | |||
else { | |||
println(NULL_OR_EMPTY); | |||
} | |||
} | |||
/* | |||
* Dump output | |||
*/ | |||
private void openDump () { | |||
if (print != null) return; | |||
Date now = new Date(); | |||
fileName = FILENAME_PREFIX + "." | |||
+ new SimpleDateFormat("yyyyMMdd").format(now) + "." | |||
+ new SimpleDateFormat("HHmmss.SSS").format(now) + "." | |||
+ FILENAME_SUFFIX; | |||
try { | |||
File file = new File(directory,fileName); | |||
print = new PrintStream(new FileOutputStream(file),true); | |||
trace.info("Dumping to " + file.getAbsolutePath()); | |||
} | |||
catch (Exception ex) { | |||
print = System.err; | |||
trace.info("Dumping to stderr"); | |||
fileName = UNKNOWN_FILENAME; | |||
} | |||
lastDumpFileName = fileName; | |||
} | |||
public void close () { | |||
print.close(); | |||
} | |||
private void println (Object obj) { | |||
print.println(obj); | |||
} | |||
private void println (Object[] array) { | |||
if (array == null) { | |||
println(NULL_OR_EMPTY); | |||
return; | |||
} | |||
for (int i = 0; i < array.length; i++) { | |||
print.println(array[i]); | |||
} | |||
} | |||
private void println (Properties props) { | |||
Iterator iter = props.keySet().iterator(); | |||
while (iter.hasNext()) { | |||
String key = (String)iter.next(); | |||
String value = props.getProperty(key); | |||
print.println(key + "=" + value); | |||
} | |||
} | |||
private void println (Throwable th) { | |||
th.printStackTrace(print); | |||
} | |||
private void println (File file) { | |||
print.print(file.getAbsolutePath()); | |||
if (!file.exists()) { | |||
println("(missing)"); | |||
} | |||
else if (file.isDirectory()) { | |||
int count = file.listFiles().length; | |||
println("(" + count + " entries)"); | |||
} | |||
else { | |||
println("(" + file.length() + " bytes)"); | |||
} | |||
} | |||
private void println (List list) { | |||
if (list == null || list.isEmpty()) println(NULL_OR_EMPTY); | |||
else for (Iterator i = list.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof Exception) { | |||
println((Exception)o); | |||
} else { | |||
println(o.toString()); | |||
} | |||
} | |||
} | |||
private static Object formatObj(Object obj) { | |||
/* These classes have a safe implementation of toString() */ | |||
if (obj == null | |||
|| obj instanceof String | |||
|| obj instanceof Number | |||
|| obj instanceof Boolean | |||
|| obj instanceof Exception | |||
|| obj instanceof Character | |||
|| obj instanceof Class | |||
|| obj instanceof File | |||
|| obj instanceof StringBuffer | |||
|| obj instanceof URL | |||
) return obj; | |||
else try { | |||
/* Classes can provide an alternative implementation of toString() */ | |||
if (obj instanceof Traceable) { | |||
Traceable t = (Traceable)obj; | |||
return t.toTraceString(); | |||
} | |||
/* Use classname@hashcode */ | |||
else return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); | |||
/* Object.hashCode() can be override and may thow an exception */ | |||
} catch (Exception ex) { | |||
return obj.getClass().getName() + "@FFFFFFFF"; | |||
} | |||
} | |||
static { | |||
String exceptionName = System.getProperty("org.aspectj.weaver.Dump.exception","true"); | |||
if (!exceptionName.equals("false")) setDumpOnException(true); | |||
String conditionName = System.getProperty(DUMP_CONDITION_PROPERTY); | |||
if (conditionName != null) setDumpOnExit(conditionName); | |||
String directoryName = System.getProperty(DUMP_DIRECTORY_PROPERTY); | |||
if (directoryName != null) setDumpDirectory(directoryName); | |||
} | |||
public interface INode { | |||
public void accept (IVisitor visior); | |||
} | |||
public interface IVisitor { | |||
public void visitObject (Object s); | |||
public void visitList (List list); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class EnumAnnotationValue extends AnnotationValue { | |||
private String type; | |||
private String value; | |||
public EnumAnnotationValue(String type,String value) { | |||
super(AnnotationValue.ENUM_CONSTANT); | |||
this.type = type; | |||
this.value = value; | |||
} | |||
public String getType() { | |||
return type; | |||
} | |||
public String stringify() { | |||
return value; | |||
} | |||
public String toString() { | |||
return value; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2007 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement, IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Special kind of privileged access munger which exposes a type to be public. | |||
*/ | |||
public class ExposeTypeMunger extends PrivilegedAccessMunger { | |||
public ExposeTypeMunger(UnresolvedType typeToExpose) { | |||
super(new ResolvedMemberImpl(Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "<clinit>", UnresolvedType.NONE)); | |||
} | |||
public String toString() { | |||
return "ExposeTypeMunger("+getSignature().getDeclaringType().getName()+")"; | |||
} | |||
public String getExposedTypeSignature() { | |||
return getSignature().getDeclaringType().getSignature(); | |||
} | |||
} |
@@ -0,0 +1,158 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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 | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* A delegate that can sit in the ReferenceType instance created for an aspect generated from aop.xml. Only answers the minimal set | |||
* of information required as the type is processed. | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class GeneratedReferenceTypeDelegate extends AbstractReferenceTypeDelegate { | |||
private ResolvedType superclass; | |||
public GeneratedReferenceTypeDelegate(ReferenceType backing) { | |||
super(backing, false); | |||
} | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isAspect() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isAnnotationStyleAspect() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isInterface() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isEnum() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isAnnotation() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isAnonymous() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isNested() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public ResolvedType getOuterClass() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public String getRetentionPolicy() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean canAnnotationTargetType() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean isGeneric() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public String getDeclaredGenericSignature() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public ResolvedMember[] getDeclaredFields() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
return ResolvedType.NONE; | |||
} | |||
public ResolvedMember[] getDeclaredMethods() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public PerClause getPerClause() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public Collection getDeclares() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public Collection getTypeMungers() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public Collection getPrivilegedAccesses() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public int getModifiers() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public void setSuperclass(ResolvedType superclass) { | |||
this.superclass = superclass; | |||
} | |||
public ResolvedType getSuperclass() { | |||
return this.superclass; | |||
} | |||
public WeaverStateInfo getWeaverState() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
public void ensureDelegateConsistent() { | |||
throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM Corporation and others. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* IBM Corporation - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Iterator; | |||
/** | |||
* @author colyer | |||
* | |||
* Clients implementing the IClassFileProvider can have a set of class files under | |||
* their control woven by a weaver, by calling the weave(IClassFileProvider source) method. | |||
* The contract is that a call to getRequestor().acceptResult() is providing a result for | |||
* the class file most recently returned from the getClassFileIterator(). | |||
*/ | |||
public interface IClassFileProvider { | |||
/** | |||
* Answer an iterator that can be used to iterate over a set of UnwovenClassFiles to | |||
* be woven. During a weave, this method may be called multiple times. | |||
* @return iterator over UnwovenClassFiles. | |||
*/ | |||
Iterator getClassFileIterator(); | |||
/** | |||
* The client to which the woven results should be returned. | |||
*/ | |||
IWeaveRequestor getRequestor(); | |||
/** | |||
* @return true if weaver should only do some internal munging as the one needed | |||
* for @AspectJ aspectOf methods creation | |||
*/ | |||
boolean isApplyAtAspectJMungersOnly(); | |||
} |
@@ -0,0 +1,29 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* An IClassWeaver is initialized with a class (a type, really, but let's ignore that for now) | |||
* and a world, and has one method that actually weaves the contents of the world into the class | |||
* implementation. | |||
*/ | |||
public interface IClassWeaver { | |||
/** perform the weaving. | |||
* | |||
* @return <code>true</code> if the class is changed by the weaving, <code>false</code> otherwise. | |||
*/ | |||
boolean weave(); | |||
} |
@@ -0,0 +1,23 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2000, 2003 IBM Corporation and others. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* IBM Corporation - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.ISourceLocation; | |||
/** | |||
* Clients can pass a single cross-reference handler to the weaver on construction of a BcelWorld. Any cross-references detected | |||
* during munging will be notified to the handler. | |||
*/ | |||
public interface ICrossReferenceHandler { | |||
void addCrossReference(ISourceLocation from, ISourceLocation to, String kind, boolean runtimeTest); | |||
} |
@@ -0,0 +1,16 @@ | |||
/******************************************************************** | |||
* Copyright (c) 2006 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: IBM Corporation - initial API and implementation | |||
* Helen Hawkins - iniital version | |||
*******************************************************************/ | |||
package org.aspectj.weaver; | |||
public interface IEclipseSourceContext extends ISourceContext { | |||
public void removeUnnecessaryProblems(Member method, int problemLineNumber); | |||
} |
@@ -0,0 +1,33 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public interface IHasPosition { | |||
/** | |||
* The starting index of this location in the character stream. | |||
*/ | |||
int getStart(); | |||
/** | |||
* The ending index of this location in the character stream | |||
* | |||
* This points to the last character in this token. | |||
* | |||
* If a location truly had no contents, then start == end + 1. We don't recommend this. | |||
*/ | |||
int getEnd(); | |||
// | |||
// String getFileName(); | |||
} |
@@ -0,0 +1,21 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public interface IHasSourceLocation extends IHasPosition { | |||
ISourceContext getSourceContext(); | |||
ISourceLocation getSourceLocation(); | |||
} |
@@ -0,0 +1,23 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public interface ISourceContext { | |||
public ISourceLocation makeSourceLocation(IHasPosition position); | |||
public ISourceLocation makeSourceLocation(int line, int offset); | |||
public int getOffset(); | |||
public void tidy(); | |||
} |
@@ -0,0 +1,26 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* History: 246125 | |||
* @author Andy Clement | |||
*/ | |||
public interface IUnwovenClassFile { | |||
String getFilename(); | |||
String getClassName(); | |||
byte[] getBytes(); | |||
char[] getClassNameAsChars(); | |||
} |
@@ -0,0 +1,38 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM Corporation and others. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* IBM Corporation - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* @author colyer | |||
* | |||
* This interface is implemented by clients driving weaving through the IClassFileProvider interface. It is used by the | |||
* weaver to return woven class file results back to the client. The client can correlate weave results with inputs since it | |||
* knows the last UnwovenClassFile returned by its iterator. | |||
*/ | |||
public interface IWeaveRequestor { | |||
/* | |||
* A class file resulting from a weave (yes, even though the type name says "unwoven"...). | |||
*/ | |||
void acceptResult(IUnwovenClassFile result); | |||
// various notifications to the requestor about our progress... | |||
void processingReweavableState(); | |||
void addingTypeMungers(); | |||
void weavingAspects(); | |||
void weavingClasses(); | |||
void weaveCompleted(); | |||
} |
@@ -0,0 +1,44 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.weaver.ast.Var; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* Encapsulates operations that a world will need to support if it is actually going to modify bytecode rather than just match | |||
* against it. {@see BcelWeavingSupport} | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public interface IWeavingSupport { | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature); | |||
public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField); | |||
public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField); | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed | |||
* | |||
* @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind) | |||
*/ | |||
public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind); | |||
public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType); | |||
public ConcreteTypeMunger createAccessForInlineMunger(ResolvedType inAspect); | |||
public Var makeCflowAccessVar(ResolvedType formalType, Member cflowField, int arrayIndex); | |||
} |
@@ -0,0 +1,147 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class IntMap { | |||
// public static final IntMap EMPTY = new IntMap(0) { | |||
// public boolean directlyInAdvice() { return true; } | |||
// public ShadowMunger getEnclosingAdvice() { return null; } //XXX possible | |||
// }; | |||
// XXX begin hack to avoid a signature refactoring in Pointcut | |||
private ResolvedType concreteAspect; | |||
private ShadowMunger enclosingAdvice; | |||
private List/* ResolvedPointcutDefinition */enclosingDefinition = new ArrayList(); | |||
public void pushEnclosingDefinition(ResolvedPointcutDefinition def) { | |||
enclosingDefinition.add(def); | |||
} | |||
public void popEnclosingDefinitition() { | |||
enclosingDefinition.remove(enclosingDefinition.size() - 1); | |||
} | |||
public ResolvedPointcutDefinition peekEnclosingDefinition() { | |||
if (enclosingDefinition.size() == 0) | |||
return null; | |||
return (ResolvedPointcutDefinition) enclosingDefinition.get(enclosingDefinition.size() - 1); | |||
} | |||
public boolean directlyInAdvice() { | |||
return enclosingDefinition.isEmpty(); | |||
} | |||
public ShadowMunger getEnclosingAdvice() { | |||
return enclosingAdvice; | |||
} | |||
public void setEnclosingAdvice(ShadowMunger advice) { | |||
this.enclosingAdvice = advice; | |||
} | |||
public Member getAdviceSignature() { | |||
if (enclosingAdvice instanceof Advice) | |||
return ((Advice) enclosingAdvice).getSignature(); | |||
else | |||
return null; | |||
} | |||
public ResolvedType getConcreteAspect() { | |||
return concreteAspect; | |||
} | |||
public void setConcreteAspect(ResolvedType concreteAspect) { | |||
this.concreteAspect = concreteAspect; | |||
} | |||
public void copyContext(IntMap bindings) { | |||
this.enclosingAdvice = bindings.enclosingAdvice; | |||
this.enclosingDefinition = bindings.enclosingDefinition; | |||
this.concreteAspect = bindings.concreteAspect; | |||
} | |||
// XXX end hack to avoid a signature refactoring in Pointcut | |||
private static final int MISSING = -1; | |||
private int[] map; | |||
private IntMap(int[] map) { | |||
this.map = map; | |||
} | |||
public IntMap() { | |||
map = new int[0]; | |||
} | |||
public IntMap(int initialCapacity) { | |||
map = new int[initialCapacity]; | |||
for (int i = 0; i < initialCapacity; i++) { | |||
map[i] = MISSING; | |||
} | |||
} | |||
public void put(int key, int val) { | |||
/* assert (val >= 0 && key >= 0) */ | |||
if (key >= map.length) { | |||
int[] tmp = new int[key * 2 + 1]; // ??? better expansion function | |||
System.arraycopy(map, 0, tmp, 0, map.length); | |||
for (int i = map.length, len = tmp.length; i < len; i++) | |||
tmp[i] = MISSING; | |||
map = tmp; | |||
} | |||
map[key] = val; | |||
} | |||
public int get(int key) { | |||
return map[key]; | |||
} | |||
public boolean hasKey(int key) { | |||
return (key < map.length && map[key] != MISSING); | |||
} | |||
// ---- factory methods | |||
public static IntMap idMap(int size) { | |||
int[] map = new int[size]; | |||
for (int i = 0; i < size; i++) { | |||
map[i] = i; | |||
} | |||
return new IntMap(map); | |||
} | |||
// ---- from object | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer("["); | |||
boolean seenFirst = false; | |||
for (int i = 0, len = map.length; i < len; i++) { | |||
if (map[i] != MISSING) { | |||
if (seenFirst) { | |||
buf.append(", "); | |||
} | |||
seenFirst = true; | |||
buf.append(i); | |||
buf.append(" -> "); | |||
buf.append(map[i]); | |||
} | |||
} | |||
buf.append("]"); | |||
return buf.toString(); | |||
} | |||
} |
@@ -0,0 +1,264 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.NoSuchElementException; | |||
import java.util.Set; | |||
public final class Iterators { | |||
/** | |||
* Private constructor, nobody should ever make one of these | |||
*/ | |||
private Iterators() { | |||
} | |||
/** | |||
* A getter represents a mapping function from Object to Iterator | |||
*/ | |||
public interface Getter { | |||
Iterator get(Object target); | |||
} | |||
/** | |||
* A filter represents a mapping function from Iterator to Iterator | |||
*/ | |||
public interface Filter { | |||
Iterator filter(Iterator in); | |||
} | |||
/** | |||
* Create a new filter F that, when wrapped around another iterator I, creates a new iterator I' that will return only those | |||
* values of I that have not yet been returned by I', discarding duplicates. | |||
*/ | |||
public static Filter dupFilter() { | |||
return new Filter() { | |||
final Set seen = new HashSet(); // should have weak ptrs? | |||
public Iterator filter(final Iterator in) { | |||
return new Iterator() { | |||
boolean fresh = false; | |||
Object peek; | |||
public boolean hasNext() { | |||
if (fresh) | |||
return true; | |||
while (true) { | |||
if (!in.hasNext()) | |||
return false; | |||
peek = in.next(); | |||
if (!seen.contains(peek)) { | |||
return fresh = true; | |||
} else { | |||
peek = null; // garbage collection | |||
} | |||
} | |||
} | |||
public Object next() { | |||
if (!hasNext()) | |||
throw new NoSuchElementException(); | |||
Object ret = peek; | |||
peek = null; | |||
fresh = false; | |||
return ret; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
}; | |||
} | |||
/** | |||
* Creates an iterator that will return the elements of a specified array, in order. Like Arrays.asList(o).iterator(), without | |||
* all that pesky safety. | |||
*/ | |||
public static Iterator array(final Object[] o) { | |||
return new Iterator() { | |||
int i = 0; | |||
int len = (o == null) ? 0 : o.length; | |||
public boolean hasNext() { | |||
return i < len; | |||
} | |||
public Object next() { | |||
if (i < len) { | |||
return o[i++]; | |||
} else { | |||
throw new NoSuchElementException(); | |||
} | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in I), G(i). | |||
*/ | |||
public static Iterator mapOver(final Iterator a, final Getter g) { | |||
return new Iterator() { | |||
Iterator delegate = new Iterator() { | |||
public boolean hasNext() { | |||
if (!a.hasNext()) | |||
return false; | |||
Object o = a.next(); | |||
delegate = append1(g.get(o), this); | |||
return delegate.hasNext(); | |||
} | |||
public Object next() { | |||
if (!hasNext()) | |||
throw new UnsupportedOperationException(); | |||
return delegate.next(); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
public boolean hasNext() { | |||
return delegate.hasNext(); | |||
} | |||
public Object next() { | |||
return delegate.next(); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in I) i :: forall (i' in | |||
* g(i)) recur(i', g) | |||
*/ | |||
public static Iterator recur(final Object a, final Getter g) { | |||
return new Iterator() { | |||
Iterator delegate = one(a); | |||
public boolean hasNext() { | |||
return delegate.hasNext(); | |||
} | |||
public Object next() { | |||
Object next = delegate.next(); | |||
delegate = append(g.get(next), delegate); | |||
return next; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If | |||
* B is empty, simply returns A, and if A is empty, simply returns B. Do NOT USE if b.hasNext() is not idempotent. | |||
*/ | |||
public static Iterator append(final Iterator a, final Iterator b) { | |||
if (!b.hasNext()) | |||
return a; | |||
return append1(a, b); | |||
} | |||
/** | |||
* creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If | |||
* A is empty, simply returns B. Guaranteed not to call B.hasNext() until A is empty. | |||
*/ | |||
public static Iterator append1(final Iterator a, final Iterator b) { | |||
if (!a.hasNext()) | |||
return b; | |||
return new Iterator() { | |||
public boolean hasNext() { | |||
return a.hasNext() || b.hasNext(); | |||
} | |||
public Object next() { | |||
if (a.hasNext()) | |||
return a.next(); | |||
if (b.hasNext()) | |||
return b.next(); | |||
throw new NoSuchElementException(); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* creates an iterator I based on a base iterator A and an object O. Returns the elements returned by A, followed by O. | |||
*/ | |||
public static Iterator snoc(final Iterator first, final Object last) { | |||
return new Iterator() { | |||
Object last1 = last; | |||
public boolean hasNext() { | |||
return first.hasNext() || last1 != null; | |||
} | |||
public Object next() { | |||
if (first.hasNext()) | |||
return first.next(); | |||
else if (last1 == null) | |||
throw new NoSuchElementException(); | |||
Object ret = last1; | |||
last1 = null; | |||
return ret; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* creates an iterator I based on an object O. Returns O, once. | |||
*/ | |||
public static Iterator one(final Object it) { | |||
return new Iterator() { | |||
boolean avail = true; | |||
public boolean hasNext() { | |||
return avail; | |||
} | |||
public Object next() { | |||
if (!avail) | |||
throw new NoSuchElementException(); | |||
avail = false; | |||
return it; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
} |
@@ -0,0 +1,409 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; | |||
/** | |||
* @author colyer Instances of this class are created by | |||
* ResolvedMember.getSignatures() when collating all of the signatures | |||
* for a member. We need to create entries in the set for the "gaps" in | |||
* the hierarchy. For example: | |||
* | |||
* class A { void foo(); } | |||
* | |||
* class B extends A {} | |||
* | |||
* Join Point : call(* B.foo()) | |||
* | |||
* has signatures: | |||
* | |||
* B.foo() AND A.foo() B.foo() will be created as a | |||
* ResolvedMemberWithSubstituteDeclaringType | |||
* | |||
* Oh for a JDK 1.4 dynamic proxy.... we have to run on 1.3 :( | |||
*/ | |||
public class JoinPointSignature implements ResolvedMember { | |||
private ResolvedMember realMember; | |||
private ResolvedType substituteDeclaringType; | |||
public JoinPointSignature(ResolvedMember backing, ResolvedType aType) { | |||
this.realMember = backing; | |||
this.substituteDeclaringType = aType; | |||
} | |||
public UnresolvedType getDeclaringType() { | |||
return substituteDeclaringType; | |||
} | |||
public int getModifiers(World world) { | |||
return realMember.getModifiers(world); | |||
} | |||
public int getModifiers() { | |||
return realMember.getModifiers(); | |||
} | |||
public UnresolvedType[] getExceptions(World world) { | |||
return realMember.getExceptions(world); | |||
} | |||
public UnresolvedType[] getExceptions() { | |||
return realMember.getExceptions(); | |||
} | |||
public ShadowMunger getAssociatedShadowMunger() { | |||
return realMember.getAssociatedShadowMunger(); | |||
} | |||
public boolean isAjSynthetic() { | |||
return realMember.isAjSynthetic(); | |||
} | |||
public boolean hasAnnotations() { | |||
return realMember.hasAnnotations(); | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
return realMember.hasAnnotation(ofType); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
return realMember.getAnnotationTypes(); | |||
} | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
return realMember.getAnnotationOfType(ofType); | |||
} | |||
public void setAnnotationTypes(UnresolvedType[] annotationtypes) { | |||
realMember.setAnnotationTypes(annotationtypes); | |||
} | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
realMember.addAnnotation(annotation); | |||
} | |||
public boolean isBridgeMethod() { | |||
return realMember.isBridgeMethod(); | |||
} | |||
public boolean isVarargsMethod() { | |||
return realMember.isVarargsMethod(); | |||
} | |||
public boolean isSynthetic() { | |||
return realMember.isSynthetic(); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
realMember.write(s); | |||
} | |||
public ISourceContext getSourceContext(World world) { | |||
return realMember.getSourceContext(world); | |||
} | |||
public String[] getParameterNames() { | |||
return realMember.getParameterNames(); | |||
} | |||
public void setParameterNames(String[] names) { | |||
realMember.setParameterNames(names); | |||
} | |||
public String[] getParameterNames(World world) { | |||
return realMember.getParameterNames(world); | |||
} | |||
public EffectiveSignatureAttribute getEffectiveSignature() { | |||
return realMember.getEffectiveSignature(); | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return realMember.getSourceLocation(); | |||
} | |||
public int getEnd() { | |||
return realMember.getEnd(); | |||
} | |||
public ISourceContext getSourceContext() { | |||
return realMember.getSourceContext(); | |||
} | |||
public int getStart() { | |||
return realMember.getStart(); | |||
} | |||
public void setPosition(int sourceStart, int sourceEnd) { | |||
realMember.setPosition(sourceStart, sourceEnd); | |||
} | |||
public void setSourceContext(ISourceContext sourceContext) { | |||
realMember.setSourceContext(sourceContext); | |||
} | |||
public boolean isAbstract() { | |||
return realMember.isAbstract(); | |||
} | |||
public boolean isPublic() { | |||
return realMember.isPublic(); | |||
} | |||
public boolean isProtected() { | |||
return realMember.isProtected(); | |||
} | |||
public boolean isNative() { | |||
return realMember.isNative(); | |||
} | |||
public boolean isDefault() { | |||
return realMember.isDefault(); | |||
} | |||
public boolean isVisible(ResolvedType fromType) { | |||
return realMember.isVisible(fromType); | |||
} | |||
public void setCheckedExceptions(UnresolvedType[] checkedExceptions) { | |||
realMember.setCheckedExceptions(checkedExceptions); | |||
} | |||
public void setAnnotatedElsewhere(boolean b) { | |||
realMember.setAnnotatedElsewhere(b); | |||
} | |||
public boolean isAnnotatedElsewhere() { | |||
return realMember.isAnnotatedElsewhere(); | |||
} | |||
public UnresolvedType getGenericReturnType() { | |||
return realMember.getGenericReturnType(); | |||
} | |||
public UnresolvedType[] getGenericParameterTypes() { | |||
return realMember.getGenericParameterTypes(); | |||
} | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized) { | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, | |||
isParameterized); | |||
} | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized, List aliases) { | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, | |||
isParameterized, aliases); | |||
} | |||
public void setTypeVariables(TypeVariable[] types) { | |||
realMember.setTypeVariables(types); | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
return realMember.getTypeVariables(); | |||
} | |||
public TypeVariable getTypeVariableNamed(String name) { | |||
return realMember.getTypeVariableNamed(name); | |||
} | |||
public boolean matches(ResolvedMember aCandidateMatch) { | |||
return realMember.matches(aCandidateMatch); | |||
} | |||
public ResolvedMember resolve(World world) { | |||
return realMember.resolve(world); | |||
} | |||
public int compareTo(Object other) { | |||
return realMember.compareTo(other); | |||
} | |||
public MemberKind getKind() { | |||
return realMember.getKind(); | |||
} | |||
public UnresolvedType getReturnType() { | |||
return realMember.getReturnType(); | |||
} | |||
public UnresolvedType getType() { | |||
return realMember.getType(); | |||
} | |||
public String getName() { | |||
return realMember.getName(); | |||
} | |||
public UnresolvedType[] getParameterTypes() { | |||
return realMember.getParameterTypes(); | |||
} | |||
public AnnotationAJ[][] getParameterAnnotations() { | |||
return realMember.getParameterAnnotations(); | |||
} | |||
public ResolvedType[][] getParameterAnnotationTypes() { | |||
return realMember.getParameterAnnotationTypes(); | |||
} | |||
public String getSignature() { | |||
return realMember.getSignature(); | |||
} | |||
public int getArity() { | |||
return realMember.getArity(); | |||
} | |||
public String getParameterSignature() { | |||
return realMember.getParameterSignature(); | |||
} | |||
public boolean isCompatibleWith(Member am) { | |||
return realMember.isCompatibleWith(am); | |||
} | |||
public boolean isStatic() { | |||
return realMember.isStatic(); | |||
} | |||
public boolean isInterface() { | |||
return realMember.isInterface(); | |||
} | |||
public boolean isPrivate() { | |||
return realMember.isPrivate(); | |||
} | |||
public boolean canBeParameterized() { | |||
return realMember.canBeParameterized(); | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
return realMember.getAnnotations(); | |||
} | |||
public Collection getDeclaringTypes(World world) { | |||
throw new UnsupportedOperationException( | |||
"Adrian doesn't think you should be calling this..."); | |||
} | |||
public Iterator getJoinPointSignatures(World world) { | |||
return realMember.getJoinPointSignatures(world); | |||
} | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(getReturnType().getName()); | |||
buf.append(' '); | |||
buf.append(getDeclaringType().getName()); | |||
buf.append('.'); | |||
buf.append(getName()); | |||
if (getKind() != FIELD) { | |||
buf.append("("); | |||
UnresolvedType[] parameterTypes = getParameterTypes(); | |||
if (parameterTypes.length != 0) { | |||
buf.append(parameterTypes[0]); | |||
for (int i = 1, len = parameterTypes.length; i < len; i++) { | |||
buf.append(", "); | |||
buf.append(parameterTypes[i].getName()); | |||
} | |||
} | |||
buf.append(")"); | |||
} | |||
return buf.toString(); | |||
} | |||
public String toGenericString() { | |||
return realMember.toGenericString(); | |||
} | |||
public String toDebugString() { | |||
return realMember.toDebugString(); | |||
} | |||
public void resetName(String newName) { | |||
realMember.resetName(newName); | |||
} | |||
public void resetKind(MemberKind newKind) { | |||
realMember.resetKind(newKind); | |||
} | |||
public void resetModifiers(int newModifiers) { | |||
realMember.resetModifiers(newModifiers); | |||
} | |||
public void resetReturnTypeToObjectArray() { | |||
realMember.resetReturnTypeToObjectArray(); | |||
} | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof JoinPointSignature)) | |||
return false; | |||
JoinPointSignature other = (JoinPointSignature) obj; | |||
if (!realMember.equals(other.realMember)) | |||
return false; | |||
if (!substituteDeclaringType.equals(other.substituteDeclaringType)) | |||
return false; | |||
return true; | |||
} | |||
public int hashCode() { | |||
return 17 + (37 * realMember.hashCode()) | |||
+ (37 * substituteDeclaringType.hashCode()); | |||
} | |||
public boolean hasBackingGenericMember() { | |||
return realMember.hasBackingGenericMember(); | |||
} | |||
public ResolvedMember getBackingGenericMember() { | |||
return realMember.getBackingGenericMember(); | |||
} | |||
public void evictWeavingState() { | |||
realMember.evictWeavingState(); | |||
} | |||
public ResolvedMember parameterizedWith(Map m, World w) { | |||
return realMember.parameterizedWith(m, w); | |||
} | |||
public String getAnnotationDefaultValue() { | |||
return realMember.getAnnotationDefaultValue(); | |||
} | |||
public String getParameterSignatureErased() { | |||
return realMember.getParameterSignatureErased(); | |||
} | |||
public String getSignatureErased() { | |||
return realMember.getSignatureErased(); | |||
} | |||
} |
@@ -0,0 +1,251 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.NoSuchElementException; | |||
import java.util.Set; | |||
/** | |||
* Iterates over the signatures of a join point, calculating new signatures | |||
* lazily to minimize processing and to avoid unneccessary "can't find type" | |||
* errors. Iterator can be cached and reused by calling the "reset" method | |||
* between iterations. | |||
*/ | |||
public class JoinPointSignatureIterator implements Iterator { | |||
private Member signaturesOfMember; | |||
private ResolvedMember firstDefiningMember; | |||
ResolvedType firstDefiningType; | |||
private World world; | |||
private List /*JoinPointSignature*/ discoveredSignatures = new ArrayList(); | |||
private List additionalSignatures = Collections.EMPTY_LIST; | |||
private Iterator discoveredSignaturesIterator = null; | |||
private Iterator superTypeIterator = null; | |||
private Set visitedSuperTypes = new HashSet(); | |||
private List /*SearchPair*/ yetToBeProcessedSuperMembers = null;//new ArrayList(); | |||
private boolean iteratingOverDiscoveredSignatures = true; | |||
private boolean couldBeFurtherAsYetUndiscoveredSignatures = true; | |||
/** | |||
* | |||
*/ | |||
public JoinPointSignatureIterator(Member joinPointSignature, World inAWorld) { | |||
this.signaturesOfMember = joinPointSignature; | |||
this.world = inAWorld; | |||
addSignaturesUpToFirstDefiningMember(); | |||
if (!shouldWalkUpHierarchy()) couldBeFurtherAsYetUndiscoveredSignatures = false; | |||
} | |||
public void reset() { | |||
discoveredSignaturesIterator = discoveredSignatures.iterator(); | |||
additionalSignatures.clear(); | |||
iteratingOverDiscoveredSignatures = true; | |||
} | |||
/* (non-Javadoc) | |||
* @see java.util.Iterator#hasNext() | |||
*/ | |||
public boolean hasNext() { | |||
if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) { | |||
return true; | |||
} else if (couldBeFurtherAsYetUndiscoveredSignatures) { | |||
if (additionalSignatures.size() > 0) return true; | |||
else return findSignaturesFromSupertypes(); | |||
} else { | |||
return false; | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see java.util.Iterator#next() | |||
*/ | |||
public Object next() { | |||
if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) { | |||
return discoveredSignaturesIterator.next(); | |||
} else { | |||
if (additionalSignatures.size() > 0) { | |||
return additionalSignatures.remove(0); | |||
} | |||
} | |||
throw new NoSuchElementException(); | |||
} | |||
/* (non-Javadoc) | |||
* @see java.util.Iterator#remove() | |||
*/ | |||
public void remove() { | |||
throw new UnsupportedOperationException("can't remove from JoinPointSignatureIterator"); | |||
} | |||
private void addSignaturesUpToFirstDefiningMember() { | |||
// Walk up hierarchy creating one member for each type up to and including the | |||
// first defining type | |||
ResolvedType originalDeclaringType = signaturesOfMember.getDeclaringType().resolve(world); | |||
if (world.isJoinpointArrayConstructionEnabled() && originalDeclaringType.isArray()) { // Aha, this must be the array constructor call join point - a 'special'... | |||
Member m = signaturesOfMember; | |||
ResolvedMember rm = new ResolvedMemberImpl(m.getKind(),m.getDeclaringType(),m.getModifiers(),m.getReturnType(),m.getName(),m.getParameterTypes()); | |||
discoveredSignatures.add(new JoinPointSignature(rm,originalDeclaringType)); | |||
couldBeFurtherAsYetUndiscoveredSignatures = false; | |||
return; | |||
} | |||
firstDefiningMember = signaturesOfMember.resolve(world); | |||
if (firstDefiningMember == null) { | |||
couldBeFurtherAsYetUndiscoveredSignatures = false; | |||
return; | |||
} | |||
// declaringType can be unresolved if we matched a synthetic member generated by Aj... | |||
// should be fixed elsewhere but add this resolve call on the end for now so that we can | |||
// focus on one problem at a time... | |||
firstDefiningType = firstDefiningMember.getDeclaringType().resolve(world); | |||
if (firstDefiningType != originalDeclaringType) { | |||
if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) { | |||
return; | |||
} | |||
} | |||
List declaringTypes = new ArrayList(); | |||
accumulateTypesInBetween(originalDeclaringType, | |||
firstDefiningType, | |||
declaringTypes); | |||
for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) { | |||
ResolvedType declaringType = (ResolvedType) iter.next(); | |||
ResolvedMember member = ((ResolvedMemberImpl)firstDefiningMember).withSubstituteDeclaringType(declaringType); | |||
discoveredSignatures.add(member); | |||
} | |||
} | |||
/** | |||
* Build a list containing every type between subtype and supertype, inclusively. | |||
*/ | |||
private void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) { | |||
types.add(subType); | |||
if (subType == superType) { | |||
return; | |||
} else { | |||
for (Iterator iter = subType.getDirectSupertypes(); iter.hasNext();) { | |||
ResolvedType parent = (ResolvedType) iter.next(); | |||
if (superType.isAssignableFrom(parent,true)) { | |||
accumulateTypesInBetween(parent, superType,types); | |||
} | |||
} | |||
} | |||
} | |||
private boolean shouldWalkUpHierarchy() { | |||
if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) return false; | |||
if (signaturesOfMember.getKind() == Member.FIELD) return false; | |||
if (signaturesOfMember.isStatic()) return false; | |||
return true; | |||
} | |||
private boolean findSignaturesFromSupertypes() { | |||
iteratingOverDiscoveredSignatures = false; | |||
if (superTypeIterator == null) { | |||
superTypeIterator = firstDefiningType.getDirectSupertypes(); | |||
} | |||
if (superTypeIterator.hasNext()) { | |||
ResolvedType superType = (ResolvedType) superTypeIterator.next(); | |||
if (visitedSuperTypes.contains(superType)) { | |||
return findSignaturesFromSupertypes(); | |||
} else { | |||
// we haven't looked in this type yet | |||
visitedSuperTypes.add(superType); | |||
if (superType.isMissing()) { | |||
// issue a warning, stop looking for join point signatures in this line | |||
warnOnMissingType(superType); | |||
return findSignaturesFromSupertypes(); | |||
} | |||
ResolvedMemberImpl foundMember = (ResolvedMemberImpl) superType.lookupResolvedMember(firstDefiningMember,true); | |||
if (foundMember != null && isVisibleTo(firstDefiningMember,foundMember)) { | |||
List declaringTypes = new ArrayList(); | |||
// declaring type can be unresolved if the member can from an ITD... | |||
ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(world); | |||
accumulateTypesInBetween(superType, resolvedDeclaringType, declaringTypes); | |||
for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) { | |||
ResolvedType declaringType = (ResolvedType) iter.next(); | |||
ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType); | |||
discoveredSignatures.add(member); // for next time we are reset | |||
if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList(); | |||
additionalSignatures.add(member); // for this time | |||
} | |||
// if this was a parameterized type, look in the generic type that backs it too | |||
if (superType.isParameterizedType() && (foundMember.backingGenericMember != null)) { | |||
ResolvedMember member =new JoinPointSignature(foundMember.backingGenericMember,foundMember.declaringType.resolve(world)); | |||
discoveredSignatures.add(member); // for next time we are reset | |||
if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList(); | |||
additionalSignatures.add(member); // for this time | |||
} | |||
if (yetToBeProcessedSuperMembers==null) yetToBeProcessedSuperMembers=new ArrayList(); | |||
yetToBeProcessedSuperMembers.add(new SearchPair(foundMember,superType)); | |||
return true; | |||
} else { | |||
return findSignaturesFromSupertypes(); | |||
} | |||
} | |||
} | |||
if (yetToBeProcessedSuperMembers!=null && !yetToBeProcessedSuperMembers.isEmpty()) { | |||
SearchPair nextUp = (SearchPair) yetToBeProcessedSuperMembers.remove(0); | |||
firstDefiningType = nextUp.type; | |||
firstDefiningMember = nextUp.member; | |||
superTypeIterator = null; | |||
return findSignaturesFromSupertypes(); | |||
} | |||
couldBeFurtherAsYetUndiscoveredSignatures = false; | |||
return false; | |||
} | |||
/** | |||
* Returns true if the parent member is visible to the child member | |||
* In the same declaring type this is always true, otherwise if parent is private | |||
* it is false. | |||
* @param childMember | |||
* @param parentMember | |||
* @return | |||
*/ | |||
private boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) { | |||
if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) return true; | |||
if (Modifier.isPrivate(parentMember.getModifiers())) { | |||
return false; | |||
} else { | |||
return true; | |||
} | |||
} | |||
private void warnOnMissingType(ResolvedType missing) { | |||
if (missing instanceof MissingResolvedTypeWithKnownSignature) { | |||
// which it should be... | |||
MissingResolvedTypeWithKnownSignature mrt = (MissingResolvedTypeWithKnownSignature) missing; | |||
mrt.raiseWarningOnJoinPointSignature(signaturesOfMember.toString()); | |||
} | |||
} | |||
private static class SearchPair { | |||
public ResolvedMember member; | |||
public ResolvedType type; | |||
public SearchPair(ResolvedMember member, ResolvedType type) { | |||
this.member = member; | |||
this.type = type; | |||
} | |||
} | |||
} |
@@ -0,0 +1,315 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.text.MessageFormat; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import java.util.Properties; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.weaver.tools.Trace; | |||
import org.aspectj.weaver.tools.TraceFactory; | |||
public class Lint { | |||
/* private */Map kinds = new HashMap(); | |||
/* private */World world; | |||
public final Kind invalidAbsoluteTypeName = new Kind("invalidAbsoluteTypeName", "no match for this type name: {0}"); | |||
public final Kind invalidWildcardTypeName = new Kind("invalidWildcardTypeName", "no match for this type pattern: {0}"); | |||
public final Kind unresolvableMember = new Kind("unresolvableMember", "can not resolve this member: {0}"); | |||
public final Kind typeNotExposedToWeaver = new Kind("typeNotExposedToWeaver", | |||
"this affected type is not exposed to the weaver: {0}"); | |||
public final Kind shadowNotInStructure = new Kind("shadowNotInStructure", | |||
"the shadow for this join point is not exposed in the structure model: {0}"); | |||
public final Kind unmatchedSuperTypeInCall = new Kind("unmatchedSuperTypeInCall", | |||
"does not match because declaring type is {0}, if match desired use target({1})"); | |||
public final Kind unmatchedTargetKind = new Kind("unmatchedTargetKind", "does not match because annotation {0} has @Target{1}"); | |||
public final Kind canNotImplementLazyTjp = new Kind("canNotImplementLazyTjp", | |||
"can not implement lazyTjp on this joinpoint {0} because around advice is used"); | |||
public final Kind multipleAdviceStoppingLazyTjp = new Kind("multipleAdviceStoppingLazyTjp", | |||
"can not implement lazyTjp at joinpoint {0} because of advice conflicts, see secondary locations to find conflicting advice"); | |||
public final Kind needsSerialVersionUIDField = new Kind("needsSerialVersionUIDField", | |||
"serialVersionUID of type {0} needs to be set because of {1}"); | |||
public final Kind serialVersionUIDBroken = new Kind("brokeSerialVersionCompatibility", | |||
"serialVersionUID of type {0} is broken because of added field {1}"); | |||
public final Kind noInterfaceCtorJoinpoint = new Kind("noInterfaceCtorJoinpoint", | |||
"no interface constructor-execution join point - use {0}+ for implementing classes"); | |||
public final Kind noJoinpointsForBridgeMethods = new Kind( | |||
"noJoinpointsForBridgeMethods", | |||
"pointcut did not match on the method call to a bridge method. Bridge methods are generated by the compiler and have no join points"); | |||
public final Kind enumAsTargetForDecpIgnored = new Kind("enumAsTargetForDecpIgnored", | |||
"enum type {0} matches a declare parents type pattern but is being ignored"); | |||
public final Kind annotationAsTargetForDecpIgnored = new Kind("annotationAsTargetForDecpIgnored", | |||
"annotation type {0} matches a declare parents type pattern but is being ignored"); | |||
public final Kind cantMatchArrayTypeOnVarargs = new Kind("cantMatchArrayTypeOnVarargs", | |||
"an array type as the last parameter in a signature does not match on the varargs declared method: {0}"); | |||
public final Kind adviceDidNotMatch = new Kind("adviceDidNotMatch", "advice defined in {0} has not been applied"); | |||
public final Kind invalidTargetForAnnotation = new Kind("invalidTargetForAnnotation", | |||
"{0} is not a valid target for annotation {1}, this annotation can only be applied to {2}"); | |||
public final Kind elementAlreadyAnnotated = new Kind("elementAlreadyAnnotated", | |||
"{0} - already has an annotation of type {1}, cannot add a second instance"); | |||
public final Kind runtimeExceptionNotSoftened = new Kind("runtimeExceptionNotSoftened", | |||
"{0} will not be softened as it is already a RuntimeException"); | |||
public final Kind uncheckedArgument = new Kind("uncheckedArgument", | |||
"unchecked match of {0} with {1} when argument is an instance of {2} at join point {3}"); | |||
public final Kind uncheckedAdviceConversion = new Kind("uncheckedAdviceConversion", | |||
"unchecked conversion when advice applied at shadow {0}, expected {1} but advice uses {2}"); | |||
public final Kind noGuardForLazyTjp = new Kind("noGuardForLazyTjp", | |||
"can not build thisJoinPoint lazily for this advice since it has no suitable guard"); | |||
public final Kind noExplicitConstructorCall = new Kind("noExplicitConstructorCall", | |||
"inter-type constructor does not contain explicit constructor call: field initializers in the target type will not be executed"); | |||
public final Kind aspectExcludedByConfiguration = new Kind("aspectExcludedByConfiguration", | |||
"aspect {0} exluded for class loader {1}"); | |||
public final Kind unorderedAdviceAtShadow = new Kind("unorderedAdviceAtShadow", | |||
"at this shadow {0} no precedence is specified between advice applying from aspect {1} and aspect {2}"); | |||
public final Kind swallowedExceptionInCatchBlock = new Kind("swallowedExceptionInCatchBlock", | |||
"exception swallowed in catch block"); | |||
public final Kind calculatingSerialVersionUID = new Kind("calculatingSerialVersionUID", | |||
"calculated SerialVersionUID for type {0} to be {1}"); | |||
// there are a lot of messages in the cant find type family - I'm defining an umbrella lint warning that | |||
// allows a user to control their severity (for e.g. ltw or binary weaving) | |||
public final Kind cantFindType = new Kind("cantFindType", "{0}"); | |||
public final Kind cantFindTypeAffectingJoinPointMatch = new Kind("cantFindTypeAffectingJPMatch", "{0}"); | |||
public final Kind advisingSynchronizedMethods = new Kind("advisingSynchronizedMethods", | |||
"advice matching the synchronized method shadow ''{0}'' will be executed outside the lock rather than inside (compiler limitation)"); | |||
public final Kind mustWeaveXmlDefinedAspects = new Kind( | |||
"mustWeaveXmlDefinedAspects", | |||
"XML Defined aspects must be woven in cases where cflow pointcuts are involved. Currently the include/exclude patterns exclude ''{0}''"); | |||
/** | |||
* Indicates an aspect could not be found when attempting reweaving. | |||
*/ | |||
public final Kind missingAspectForReweaving = new Kind("missingAspectForReweaving", | |||
"aspect {0} cannot be found when reweaving {1}"); | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class); | |||
public Lint(World world) { | |||
if (trace.isTraceEnabled()) | |||
trace.enter("<init>", this, world); | |||
this.world = world; | |||
if (trace.isTraceEnabled()) | |||
trace.exit("<init>"); | |||
} | |||
public void setAll(String messageKind) { | |||
if (trace.isTraceEnabled()) | |||
trace.enter("setAll", this, messageKind); | |||
setAll(getMessageKind(messageKind)); | |||
if (trace.isTraceEnabled()) | |||
trace.exit("setAll"); | |||
} | |||
private void setAll(IMessage.Kind messageKind) { | |||
for (Iterator i = kinds.values().iterator(); i.hasNext();) { | |||
Kind kind = (Kind) i.next(); | |||
kind.setKind(messageKind); | |||
} | |||
} | |||
public void setFromProperties(File file) { | |||
if (trace.isTraceEnabled()) | |||
trace.enter("setFromProperties", this, file); | |||
try { | |||
InputStream s = new FileInputStream(file); | |||
setFromProperties(s); | |||
} catch (IOException ioe) { | |||
MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_LOAD_ERROR, file.getPath(), ioe | |||
.getMessage())); | |||
} | |||
if (trace.isTraceEnabled()) | |||
trace.exit("setFromProperties"); | |||
} | |||
public void loadDefaultProperties() { | |||
InputStream s = getClass().getResourceAsStream("XlintDefault.properties"); | |||
if (s == null) { | |||
MessageUtil.warn(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_ERROR)); | |||
return; | |||
} | |||
try { | |||
setFromProperties(s); | |||
} catch (IOException ioe) { | |||
MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_PROBLEM, ioe | |||
.getMessage())); | |||
} | |||
} | |||
private void setFromProperties(InputStream s) throws IOException { | |||
Properties p = new Properties(); | |||
p.load(s); | |||
setFromProperties(p); | |||
} | |||
public void setFromProperties(Properties properties) { | |||
for (Iterator i = properties.entrySet().iterator(); i.hasNext();) { | |||
Map.Entry entry = (Map.Entry) i.next(); | |||
Kind kind = (Kind) kinds.get(entry.getKey()); | |||
if (kind == null) { | |||
MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR, entry.getKey())); | |||
} else { | |||
kind.setKind(getMessageKind((String) entry.getValue())); | |||
} | |||
} | |||
} | |||
public Collection allKinds() { | |||
return kinds.values(); | |||
} | |||
public Kind getLintKind(String name) { | |||
return (Kind) kinds.get(name); | |||
} | |||
// temporarily suppress the given lint messages | |||
public void suppressKinds(Collection lintKind) { | |||
if (lintKind.isEmpty()) | |||
return; | |||
for (Iterator iter = lintKind.iterator(); iter.hasNext();) { | |||
Kind k = (Kind) iter.next(); | |||
k.setSuppressed(true); | |||
} | |||
} | |||
// remove any suppression of lint warnings in place | |||
public void clearAllSuppressions() { | |||
for (Iterator iter = kinds.values().iterator(); iter.hasNext();) { | |||
Kind k = (Kind) iter.next(); | |||
k.setSuppressed(false); | |||
} | |||
} | |||
public void clearSuppressions(Collection lintKind) { | |||
if (lintKind.isEmpty()) | |||
return; | |||
for (Iterator iter = lintKind.iterator(); iter.hasNext();) { | |||
Kind k = (Kind) iter.next(); | |||
k.setSuppressed(false); | |||
} | |||
} | |||
private IMessage.Kind getMessageKind(String v) { | |||
if (v.equals("ignore")) | |||
return null; | |||
else if (v.equals("warning")) | |||
return IMessage.WARNING; | |||
else if (v.equals("error")) | |||
return IMessage.ERROR; | |||
MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_VALUE_ERROR, v)); | |||
return null; | |||
} | |||
public Kind fromKey(String lintkey) { | |||
return (Lint.Kind) kinds.get(lintkey); | |||
} | |||
public class Kind { | |||
private final String name; | |||
private final String message; | |||
private IMessage.Kind kind = IMessage.WARNING; | |||
private boolean isSupressed = false; // by SuppressAjWarnings | |||
public Kind(String name, String message) { | |||
this.name = name; | |||
this.message = message; | |||
kinds.put(this.name, this); | |||
} | |||
public void setSuppressed(boolean shouldBeSuppressed) { | |||
this.isSupressed = shouldBeSuppressed; | |||
} | |||
public boolean isEnabled() { | |||
return (kind != null) && !isSupressed(); | |||
} | |||
private boolean isSupressed() { | |||
// can't suppress errors! | |||
return isSupressed && (kind != IMessage.ERROR); | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public IMessage.Kind getKind() { | |||
return kind; | |||
} | |||
public void setKind(IMessage.Kind kind) { | |||
this.kind = kind; | |||
} | |||
public void signal(String info, ISourceLocation location) { | |||
if (kind == null) | |||
return; | |||
String text = MessageFormat.format(message, new Object[] { info }); | |||
text += " [Xlint:" + name + "]"; | |||
world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, null, getLintKind(name))); | |||
} | |||
public void signal(String[] infos, ISourceLocation location, ISourceLocation[] extraLocations) { | |||
if (kind == null) | |||
return; | |||
String text = MessageFormat.format(message, (Object[]) infos); | |||
text += " [Xlint:" + name + "]"; | |||
world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, extraLocations, getLintKind(name))); | |||
} | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002-2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* AndyClement extracted as self contained type from Lint type (4-Aug-06) | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.Message; | |||
public class LintMessage extends Message { | |||
// private Lint.Kind lintKind; | |||
private String lintKind; | |||
public LintMessage( | |||
String message, | |||
IMessage.Kind messageKind, | |||
ISourceLocation location, | |||
ISourceLocation[] extraLocations, | |||
Lint.Kind lintKind) { | |||
super(message,"",messageKind,location,null,extraLocations); | |||
this.lintKind = lintKind.getName(); | |||
} | |||
public LintMessage(String message, String extraDetails, org.aspectj.weaver.Lint.Kind kind2, Kind kind, ISourceLocation sourceLocation, Throwable object, | |||
ISourceLocation[] seeAlsoLocations, boolean declared, int id, int sourceStart, int sourceEnd) { | |||
super(message,extraDetails,kind,sourceLocation,object,seeAlsoLocations,declared,id,sourceStart,sourceEnd); | |||
this.lintKind = kind2.getName(); | |||
} | |||
/** | |||
* @return Returns the Lint kind of this message | |||
*/ | |||
public String getLintKind() { | |||
return lintKind; | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* AMC extracted as interface | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
/** | |||
* Abstract representation of a member within a type. | |||
*/ | |||
public interface Member extends Comparable { | |||
public static final Member[] NONE = new Member[0]; | |||
public static final MemberKind METHOD = new MemberKind("METHOD", 1); | |||
public static final MemberKind FIELD = new MemberKind("FIELD", 2); | |||
public static final MemberKind CONSTRUCTOR = new MemberKind("CONSTRUCTOR", | |||
3); | |||
public static final MemberKind STATIC_INITIALIZATION = new MemberKind( | |||
"STATIC_INITIALIZATION", 4); | |||
public static final MemberKind POINTCUT = new MemberKind("POINTCUT", 5); | |||
public static final MemberKind ADVICE = new MemberKind("ADVICE", 6); | |||
public static final MemberKind HANDLER = new MemberKind("HANDLER", 7); | |||
public static final MemberKind MONITORENTER = new MemberKind( | |||
"MONITORENTER", 8); | |||
public static final MemberKind MONITOREXIT = new MemberKind("MONITOREXIT", | |||
9); | |||
public static final AnnotationAJ[][] NO_PARAMETER_ANNOTATIONXS = new AnnotationAJ[][] {}; | |||
public static final ResolvedType[][] NO_PARAMETER_ANNOTATION_TYPES = new ResolvedType[][] {}; | |||
public MemberKind getKind(); | |||
public ResolvedMember resolve(World world); | |||
public int compareTo(Object other); | |||
public UnresolvedType getDeclaringType(); | |||
public UnresolvedType getReturnType(); | |||
public UnresolvedType getGenericReturnType(); | |||
public UnresolvedType[] getGenericParameterTypes(); | |||
public UnresolvedType getType(); | |||
public String getName(); | |||
public UnresolvedType[] getParameterTypes(); | |||
/** | |||
* Return full signature, including return type, e.g. "()LFastCar;". For a | |||
* signature without the return type, use getParameterSignature() - it is | |||
* important to choose the right one in the face of covariance. | |||
*/ | |||
public String getSignature(); | |||
public Iterator getJoinPointSignatures(World world); | |||
public int getArity(); | |||
/** | |||
* Return signature without return type, e.g. "()" for a signature *with* | |||
* the return type, use getSignature() - it is important to choose the right | |||
* one in the face of covariance. | |||
*/ | |||
public String getParameterSignature(); | |||
public int getModifiers(World world); | |||
public int getModifiers(); | |||
public boolean isStatic(); | |||
public boolean isInterface(); | |||
public boolean isPrivate(); | |||
/** | |||
* Returns true iff the member is generic (NOT parameterized) | |||
*/ | |||
public boolean canBeParameterized(); | |||
public AnnotationAJ[] getAnnotations(); | |||
public Collection/* ResolvedType */getDeclaringTypes(World world); | |||
public String[] getParameterNames(World world); | |||
public UnresolvedType[] getExceptions(World world); | |||
} |
@@ -0,0 +1,565 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
public class MemberImpl implements Member { | |||
protected MemberKind kind; | |||
protected int modifiers; | |||
protected String name; | |||
protected UnresolvedType returnType; | |||
protected UnresolvedType declaringType; | |||
protected UnresolvedType[] parameterTypes; | |||
private final String signature; | |||
private String paramSignature; | |||
// OPTIMIZE move out of the member! | |||
private boolean reportedCantFindDeclaringType = false; | |||
private boolean reportedUnresolvableMember = false; | |||
/** | |||
* All the signatures that a join point with this member as its signature | |||
* has. | |||
*/ | |||
private JoinPointSignatureIterator joinPointSignatures = null; | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, String name, String signature) { | |||
this.kind = kind; | |||
this.declaringType = declaringType; | |||
this.modifiers = modifiers; | |||
this.name = name; | |||
this.signature = signature; | |||
if (kind == FIELD) { | |||
this.returnType = UnresolvedType.forSignature(signature); | |||
this.parameterTypes = UnresolvedType.NONE; | |||
} else { | |||
Object[] returnAndParams = signatureToTypes(signature, false); | |||
this.returnType = (UnresolvedType) returnAndParams[0]; | |||
this.parameterTypes = (UnresolvedType[]) returnAndParams[1]; | |||
// always safe not to do this ?!? | |||
// String oldsig=new String(signature); | |||
// signature = typesToSignature(returnType,parameterTypes,true); | |||
} | |||
} | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes) { | |||
this.kind = kind; | |||
this.declaringType = declaringType; | |||
this.modifiers = modifiers; | |||
this.returnType = returnType; | |||
this.name = name; | |||
this.parameterTypes = parameterTypes; | |||
if (kind == FIELD) { | |||
this.signature = returnType.getErasureSignature(); | |||
} else { | |||
this.signature = typesToSignature(returnType, parameterTypes, true); | |||
} | |||
} | |||
public ResolvedMember resolve(World world) { | |||
return world.resolve(this); | |||
} | |||
// ---- utility methods | |||
/** | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing | |||
* return type, argument types parsed from the JVM bytecode signature of a | |||
* method. Yes, this should actually return a nice statically-typed pair | |||
* object, but we don't have one of those. | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.signatureToTypes("()[Z")[0].equals(Type.forSignature("[Z")) | |||
* UnresolvedType.signatureToTypes("(JJ)I")[1] | |||
* .equals(UnresolvedType.forSignatures(new String[] {"J", "J"})) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* @param signature | |||
* the JVM bytecode method signature string we want to break | |||
* apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the | |||
* return types and parameter types. | |||
*/ | |||
// OPTIMIZE move static util methods out into a memberutils class | |||
public static String typesToSignature(UnresolvedType returnType, | |||
UnresolvedType[] paramTypes, boolean useRawTypes) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("("); | |||
for (int i = 0, len = paramTypes.length; i < len; i++) { | |||
if (paramTypes[i].isParameterizedType() && useRawTypes) | |||
buf.append(paramTypes[i].getErasureSignature()); | |||
else if (paramTypes[i].isTypeVariableReference() && useRawTypes) | |||
buf.append(paramTypes[i].getErasureSignature()); | |||
else | |||
buf.append(paramTypes[i].getSignature()); | |||
} | |||
buf.append(")"); | |||
if (returnType.isParameterizedType() && useRawTypes) | |||
buf.append(returnType.getErasureSignature()); | |||
else if (returnType.isTypeVariableReference() && useRawTypes) | |||
buf.append(returnType.getErasureSignature()); | |||
else | |||
buf.append(returnType.getSignature()); | |||
return buf.toString(); | |||
} | |||
/** | |||
* Returns "(<signaturesOfParamTypes>,...)" - unlike the other | |||
* typesToSignature that also includes the return type, this one just deals | |||
* with the parameter types. | |||
*/ | |||
public static String typesToSignature(UnresolvedType[] paramTypes) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("("); | |||
for (int i = 0; i < paramTypes.length; i++) { | |||
buf.append(paramTypes[i].getSignature()); | |||
} | |||
buf.append(")"); | |||
return buf.toString(); | |||
} | |||
/** | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing | |||
* return type, argument types parsed from the JVM bytecode signature of a | |||
* method. Yes, this should actually return a nice statically-typed pair | |||
* object, but we don't have one of those. | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.signatureToTypes("()[Z")[0].equals(Type.forSignature("[Z")) | |||
* UnresolvedType.signatureToTypes("(JJ)I")[1] | |||
* .equals(UnresolvedType.forSignatures(new String[] {"J", "J"})) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* @param signature | |||
* the JVM bytecode method signature string we want to break | |||
* apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the | |||
* return types and parameter types. | |||
*/ | |||
private static Object[] signatureToTypes(String sig, | |||
boolean keepParameterizationInfo) { | |||
boolean hasParameters = sig.charAt(1) != ')'; | |||
if (hasParameters) { | |||
List l = new ArrayList(); | |||
int i = 1; | |||
boolean hasAnyAnglies = sig.indexOf('<') != -1; | |||
while (true) { | |||
char c = sig.charAt(i); | |||
if (c == ')') | |||
break; // break out when the hit the ')' | |||
int start = i; | |||
while (c == '[') | |||
c = sig.charAt(++i); | |||
if (c == 'L' || c == 'P') { | |||
int nextSemicolon = sig.indexOf(';', start); | |||
int firstAngly = (hasAnyAnglies ? sig.indexOf('<', start) | |||
: -1); | |||
if (!hasAnyAnglies || firstAngly == -1 | |||
|| firstAngly > nextSemicolon) { | |||
i = nextSemicolon + 1; | |||
l.add(UnresolvedType.forSignature(sig.substring(start, | |||
i))); | |||
} else { | |||
// generics generics generics | |||
// Have to skip to the *correct* ';' | |||
boolean endOfSigReached = false; | |||
int posn = firstAngly; | |||
int genericDepth = 0; | |||
while (!endOfSigReached) { | |||
switch (sig.charAt(posn)) { | |||
case '<': | |||
genericDepth++; | |||
break; | |||
case '>': | |||
genericDepth--; | |||
break; | |||
case ';': | |||
if (genericDepth == 0) | |||
endOfSigReached = true; | |||
break; | |||
default: | |||
} | |||
posn++; | |||
} | |||
// posn now points to the correct nextSemicolon :) | |||
i = posn; | |||
l.add(UnresolvedType.forSignature(sig.substring(start, | |||
i))); | |||
} | |||
} else if (c == 'T') { // assumed 'reference' to a type | |||
// variable, so just "Tname;" | |||
int nextSemicolon = sig.indexOf(';', start); | |||
String nextbit = sig.substring(start, nextSemicolon); | |||
l.add(UnresolvedType.forSignature(nextbit)); | |||
i = nextSemicolon + 1; | |||
} else { | |||
i++; | |||
l.add(UnresolvedType.forSignature(sig.substring(start, i))); | |||
} | |||
} | |||
UnresolvedType[] paramTypes = (UnresolvedType[]) l | |||
.toArray(new UnresolvedType[l.size()]); | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig | |||
.substring(i + 1, sig.length())); | |||
return new Object[] { returnType, paramTypes }; | |||
} else { | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig | |||
.substring(2)); | |||
return new Object[] { returnType, UnresolvedType.NONE }; | |||
} | |||
} | |||
// ---- factory methods | |||
public static MemberImpl field(String declaring, int mods, String name, | |||
String signature) { | |||
return field(declaring, mods, UnresolvedType.forSignature(signature), | |||
name); | |||
} | |||
// public static Member field(UnresolvedType declaring, int mods, String | |||
// name, UnresolvedType type) { | |||
// return new MemberImpl(FIELD, declaring, mods, type, name, | |||
// UnresolvedType.NONE); | |||
// } | |||
// OPTIMIZE do we need to call this? unless necessary the signatureToTypes() | |||
// call smacks of laziness on the behalf of the caller | |||
// of this method | |||
public static MemberImpl method(UnresolvedType declaring, int mods, | |||
String name, String signature) { | |||
Object[] pair = signatureToTypes(signature, false); | |||
return method(declaring, mods, (UnresolvedType) pair[0], name, | |||
(UnresolvedType[]) pair[1]); | |||
} | |||
public static MemberImpl monitorEnter() { | |||
return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT, | |||
Modifier.STATIC, ResolvedType.VOID, "<lock>", | |||
UnresolvedType.ARRAY_WITH_JUST_OBJECT); | |||
} | |||
public static MemberImpl monitorExit() { | |||
return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT, | |||
Modifier.STATIC, ResolvedType.VOID, "<unlock>", | |||
UnresolvedType.ARRAY_WITH_JUST_OBJECT); | |||
} | |||
public static Member pointcut(UnresolvedType declaring, String name, | |||
String signature) { | |||
Object[] pair = signatureToTypes(signature, false); | |||
return pointcut(declaring, 0, (UnresolvedType) pair[0], name, | |||
(UnresolvedType[]) pair[1]); | |||
} | |||
private static MemberImpl field(String declaring, int mods, | |||
UnresolvedType ty, String name) { | |||
return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods, | |||
ty, name, UnresolvedType.NONE); | |||
} | |||
public static MemberImpl method(UnresolvedType declTy, int mods, | |||
UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
return new MemberImpl( | |||
// ??? this calls <clinit> a method | |||
name.equals("<init>") ? CONSTRUCTOR : METHOD, declTy, mods, | |||
rTy, name, paramTys); | |||
} | |||
private static Member pointcut(UnresolvedType declTy, int mods, | |||
UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
return new MemberImpl(POINTCUT, declTy, mods, rTy, name, paramTys); | |||
} | |||
public static ResolvedMemberImpl makeExceptionHandlerSignature( | |||
UnresolvedType inType, UnresolvedType catchType) { | |||
return new ResolvedMemberImpl(HANDLER, inType, Modifier.STATIC, | |||
"<catch>", "(" + catchType.getSignature() + ")V"); | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof Member)) | |||
return false; | |||
Member o = (Member) other; | |||
return (getKind() == o.getKind() && getName().equals(o.getName()) | |||
&& getSignature().equals(o.getSignature()) && getDeclaringType() | |||
.equals(o.getDeclaringType())); | |||
} | |||
/** | |||
* Equality is checked based on the underlying signature, so the hash code | |||
* of a member is based on its kind, name, signature, and declaring type. | |||
* The algorithm for this was taken from page 38 of effective java. | |||
*/ | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37 * result + getKind().hashCode(); | |||
result = 37 * result + getName().hashCode(); | |||
result = 37 * result + getSignature().hashCode(); | |||
result = 37 * result + getDeclaringType().hashCode(); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
public int compareTo(Object other) { | |||
Member o = (Member) other; | |||
int i = getName().compareTo(o.getName()); | |||
if (i != 0) | |||
return i; | |||
return getSignature().compareTo(o.getSignature()); | |||
} | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(returnType.getName()); | |||
buf.append(' '); | |||
buf.append(declaringType.getName()); | |||
buf.append('.'); | |||
buf.append(name); | |||
if (kind != FIELD) { | |||
buf.append("("); | |||
if (parameterTypes.length != 0) { | |||
buf.append(parameterTypes[0]); | |||
for (int i = 1, len = parameterTypes.length; i < len; i++) { | |||
buf.append(", "); | |||
buf.append(parameterTypes[i].getName()); | |||
} | |||
} | |||
buf.append(")"); | |||
} | |||
return buf.toString(); | |||
} | |||
public MemberKind getKind() { | |||
return kind; | |||
} | |||
public UnresolvedType getDeclaringType() { | |||
return declaringType; | |||
} | |||
public UnresolvedType getReturnType() { | |||
return returnType; | |||
} | |||
public UnresolvedType getGenericReturnType() { | |||
return getReturnType(); | |||
} | |||
public UnresolvedType[] getGenericParameterTypes() { | |||
return getParameterTypes(); | |||
} | |||
public final UnresolvedType getType() { | |||
return returnType; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public UnresolvedType[] getParameterTypes() { | |||
return parameterTypes; | |||
} | |||
public String getSignature() { | |||
return signature; | |||
} | |||
public int getArity() { | |||
return parameterTypes.length; | |||
} | |||
public String getParameterSignature() { | |||
if (paramSignature != null) | |||
return paramSignature; | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("("); | |||
for (int i = 0; i < parameterTypes.length; i++) { | |||
UnresolvedType tx = parameterTypes[i]; | |||
sb.append(tx.getSignature()); | |||
} | |||
sb.append(")"); | |||
paramSignature = sb.toString(); | |||
return paramSignature; | |||
} | |||
// OPTIMIZE see next line. Why the hell are they in here if we only know it | |||
// once resolution has occurred... | |||
// ---- things we know only with resolution | |||
public int getModifiers(World world) { | |||
ResolvedMember resolved = resolve(world); | |||
if (resolved == null) { | |||
reportDidntFindMember(world); | |||
return 0; | |||
} | |||
return resolved.getModifiers(); | |||
} | |||
public UnresolvedType[] getExceptions(World world) { | |||
ResolvedMember resolved = resolve(world); | |||
if (resolved == null) { | |||
reportDidntFindMember(world); | |||
return UnresolvedType.NONE; | |||
} | |||
return resolved.getExceptions(); | |||
} | |||
public final boolean isStatic() { | |||
return Modifier.isStatic(modifiers); | |||
} | |||
public final boolean isInterface() { | |||
return Modifier.isInterface(modifiers); | |||
} | |||
public final boolean isPrivate() { | |||
return Modifier.isPrivate(modifiers); | |||
} | |||
public boolean canBeParameterized() { | |||
return false; | |||
} | |||
public int getModifiers() { | |||
return modifiers; | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
throw new UnsupportedOperationException( | |||
"You should resolve this member '" + this | |||
+ "' and call getAnnotations() on the result..."); | |||
} | |||
// ---- fields 'n' stuff | |||
public Collection/* ResolvedType */getDeclaringTypes(World world) { | |||
ResolvedType myType = getDeclaringType().resolve(world); | |||
Collection ret = new HashSet(); | |||
if (kind == CONSTRUCTOR) { | |||
// this is wrong if the member doesn't exist, but that doesn't | |||
// matter | |||
ret.add(myType); | |||
} else if (isStatic() || kind == FIELD) { | |||
walkUpStatic(ret, myType); | |||
} else { | |||
walkUp(ret, myType); | |||
} | |||
return ret; | |||
} | |||
private boolean walkUp(Collection acc, ResolvedType curr) { | |||
if (acc.contains(curr)) | |||
return true; | |||
boolean b = false; | |||
for (Iterator i = curr.getDirectSupertypes(); i.hasNext();) { | |||
b |= walkUp(acc, (ResolvedType) i.next()); | |||
} | |||
if (!b && curr.isParameterizedType()) { | |||
b = walkUp(acc, curr.getGenericType()); | |||
} | |||
if (!b) { | |||
b = curr.lookupMemberNoSupers(this) != null; | |||
} | |||
if (b) | |||
acc.add(curr); | |||
return b; | |||
} | |||
private boolean walkUpStatic(Collection acc, ResolvedType curr) { | |||
if (curr.lookupMemberNoSupers(this) != null) { | |||
acc.add(curr); | |||
return true; | |||
} else { | |||
boolean b = false; | |||
for (Iterator i = curr.getDirectSupertypes(); i.hasNext();) { | |||
b |= walkUpStatic(acc, (ResolvedType) i.next()); | |||
} | |||
if (!b && curr.isParameterizedType()) { | |||
b = walkUpStatic(acc, curr.getGenericType()); | |||
} | |||
if (b) | |||
acc.add(curr); | |||
return b; | |||
} | |||
} | |||
public String[] getParameterNames(World world) { | |||
ResolvedMember resolved = resolve(world); | |||
if (resolved == null) { | |||
reportDidntFindMember(world); | |||
return null; | |||
} | |||
return resolved.getParameterNames(); | |||
} | |||
/** | |||
* All the signatures that a join point with this member as its signature | |||
* has. | |||
*/ | |||
public Iterator getJoinPointSignatures(World inAWorld) { | |||
if (joinPointSignatures == null) { | |||
joinPointSignatures = new JoinPointSignatureIterator(this, inAWorld); | |||
} | |||
joinPointSignatures.reset(); | |||
return joinPointSignatures; | |||
} | |||
/** | |||
* Raises an [Xlint:cantFindType] message if the declaring type cannot be | |||
* found or an [Xlint:unresolvableMember] message if the type can be found | |||
* (bug 149908) | |||
*/ | |||
private void reportDidntFindMember(World world) { | |||
if (reportedCantFindDeclaringType || reportedUnresolvableMember) | |||
return; | |||
ResolvedType rType = getDeclaringType().resolve(world); | |||
if (rType.isMissing()) { | |||
world.getLint().cantFindType.signal(WeaverMessages.format( | |||
WeaverMessages.CANT_FIND_TYPE, rType.getName()), null); | |||
reportedCantFindDeclaringType = true; | |||
} else { | |||
world.getLint().unresolvableMember.signal(getName(), null); | |||
reportedUnresolvableMember = true; | |||
} | |||
} | |||
public void wipeJoinpointSignatures() { | |||
joinPointSignatures = null; | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-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 MemberKind extends TypeSafeEnum { | |||
public MemberKind(String name, int key) { super(name, key); } | |||
public static MemberKind read(DataInputStream s) throws IOException { | |||
int key = s.readByte(); | |||
switch(key) { | |||
case 1: return Member.METHOD; | |||
case 2: return Member.FIELD; | |||
case 3: return Member.CONSTRUCTOR; | |||
case 4: return Member.STATIC_INITIALIZATION; | |||
case 5: return Member.POINTCUT; | |||
case 6: return Member.ADVICE; | |||
case 7: return Member.HANDLER; | |||
case 8: return Member.MONITORENTER; | |||
case 9: return Member.MONITOREXIT; | |||
} | |||
throw new BCException("Unexpected memberkind, should be (1-9) but was " + key); | |||
} | |||
} |
@@ -0,0 +1,202 @@ | |||
/* ******************************************************************* | |||
* 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.DataOutputStream; | |||
import java.io.IOException; | |||
import org.aspectj.weaver.patterns.TypePattern; | |||
/** | |||
* Type munger for @AspectJ ITD declare parents ie 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; | |||
/** | |||
* The mixin impl (no arg ctor) | |||
*/ | |||
private final String implClassName; | |||
/** | |||
* Type pattern this munger applies to | |||
*/ | |||
private final TypePattern typePattern; | |||
/** | |||
* 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(MethodDelegate, signature); | |||
this.aspect = aspect; | |||
this.typePattern = typePattern; | |||
this.implClassName = implClassName; | |||
} | |||
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)); | |||
} | |||
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()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
public ResolvedMember getDelegate(ResolvedType targetType) { | |||
return AjcMemberMaker.itdAtDeclareParentsField( | |||
targetType, | |||
signature.getDeclaringType(), | |||
aspect | |||
); | |||
} | |||
public String getImplClassName() { | |||
return implClassName; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.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); | |||
UnresolvedType aspect = UnresolvedType.read(s); | |||
String implClassName = s.readUTF(); | |||
TypePattern tp = TypePattern.read(s, context); | |||
return new MethodDelegateTypeMunger(signature, aspect, implClassName, 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); | |||
} | |||
/** | |||
* Needed for reweavable | |||
* | |||
* @return true | |||
*/ | |||
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 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(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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,212 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.context.CompilationAndWeavingContext; | |||
/** | |||
* When we try to resolve a type in the world that we require to be present, | |||
* and then fail to find it, we return an instance of this class. This class | |||
* defers the production of the "can't find type error" until the first time | |||
* that someone asks a question that can't be answered solely from the signature. | |||
* This enables the weaver to be more tolerant of missing types. | |||
* | |||
*/ | |||
public class MissingResolvedTypeWithKnownSignature extends ResolvedType { | |||
private static ResolvedMember[] NO_MEMBERS = new ResolvedMember[0]; | |||
private static ResolvedType[] NO_TYPES = new ResolvedType[0]; | |||
private boolean issuedCantFindTypeError = false; | |||
private boolean issuedJoinPointWarning = false; | |||
private boolean issuedMissingInterfaceWarning = false; | |||
/** | |||
* @param signature | |||
* @param world | |||
*/ | |||
public MissingResolvedTypeWithKnownSignature(String signature, World world) { | |||
super(signature, world); | |||
} | |||
public boolean isMissing() { return true; } | |||
/** | |||
* @param signature | |||
* @param signatureErasure | |||
* @param world | |||
*/ | |||
public MissingResolvedTypeWithKnownSignature(String signature, | |||
String signatureErasure, World world) { | |||
super(signature, signatureErasure, world); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getDeclaredFields() | |||
*/ | |||
public ResolvedMember[] getDeclaredFields() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_FIELDS); | |||
return NO_MEMBERS; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getDeclaredMethods() | |||
*/ | |||
public ResolvedMember[] getDeclaredMethods() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_METHODS); | |||
return NO_MEMBERS; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getDeclaredInterfaces() | |||
*/ | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_INTERFACES); | |||
return NO_TYPES; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getDeclaredPointcuts() | |||
*/ | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_POINTCUTS); | |||
return NO_MEMBERS; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getSuperclass() | |||
*/ | |||
public ResolvedType getSuperclass() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_SUPERCLASS); | |||
return ResolvedType.MISSING; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getModifiers() | |||
*/ | |||
public int getModifiers() { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_MODIFIERS); | |||
return 0; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#getSourceContext() | |||
*/ | |||
public ISourceContext getSourceContext() { | |||
return new ISourceContext() { | |||
public ISourceLocation makeSourceLocation(IHasPosition position) { | |||
return null; | |||
} | |||
public ISourceLocation makeSourceLocation(int line, int offset) { | |||
return null; | |||
} | |||
public int getOffset() { | |||
return 0; | |||
} | |||
public void tidy() {} | |||
}; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#isAssignableFrom(org.aspectj.weaver.ResolvedType) | |||
*/ | |||
public boolean isAssignableFrom(ResolvedType other) { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_ASSIGNABLE,other.getName()); | |||
return false; | |||
} | |||
public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) { | |||
if (allowMissing) return false; | |||
else return isAssignableFrom(other); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ResolvedType#isCoerceableFrom(org.aspectj.weaver.ResolvedType) | |||
*/ | |||
public boolean isCoerceableFrom(ResolvedType other) { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_COERCEABLE,other.getName()); | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.AnnotatedElement#hasAnnotation(org.aspectj.weaver.UnresolvedType) | |||
*/ | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_ANNOTATION); | |||
return false; | |||
} | |||
public List getInterTypeMungers() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
public List getInterTypeMungersIncludingSupers() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
public List getInterTypeParentMungers() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
public List getInterTypeParentMungersIncludingSupers() { | |||
return Collections.EMPTY_LIST; | |||
} | |||
protected void collectInterTypeMungers(List collector) { | |||
return; | |||
} | |||
public void raiseWarningOnJoinPointSignature(String signature) { | |||
if (issuedJoinPointWarning) return; | |||
String message = WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_JOINPOINT,getName(),signature); | |||
message += "\n" + CompilationAndWeavingContext.getCurrentContext(); | |||
world.getLint().cantFindTypeAffectingJoinPointMatch.signal(message,null); | |||
// MessageUtil.warn(world.getMessageHandler(),message); | |||
issuedJoinPointWarning = true; | |||
} | |||
public void raiseWarningOnMissingInterfaceWhilstFindingMethods() { | |||
if (issuedMissingInterfaceWarning) return; | |||
String message = WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_INTERFACE_METHODS,getName(),signature); | |||
message += "\n" + CompilationAndWeavingContext.getCurrentContext(); | |||
world.getLint().cantFindTypeAffectingJoinPointMatch.signal(message,null); | |||
//MessageUtil.warn(world.getMessageHandler(),message); | |||
issuedMissingInterfaceWarning = true; | |||
} | |||
private void raiseCantFindType(String key) { | |||
if (issuedCantFindTypeError) return; | |||
String message = WeaverMessages.format(key,getName()); | |||
message += "\n" + CompilationAndWeavingContext.getCurrentContext(); | |||
world.getLint().cantFindType.signal(message,null); | |||
// MessageUtil.error(world.getMessageHandler(),message); | |||
issuedCantFindTypeError = true; | |||
} | |||
private void raiseCantFindType(String key,String insert) { | |||
if (issuedCantFindTypeError) return; | |||
String message = WeaverMessages.format(key,getName(),insert); | |||
message += "\n" + CompilationAndWeavingContext.getCurrentContext(); | |||
world.getLint().cantFindType.signal(message,null); | |||
// MessageUtil.error(world.getMessageHandler(),message); | |||
issuedCantFindTypeError = true; | |||
} | |||
} |
@@ -0,0 +1,334 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
public class NameMangler { | |||
// public static final char[] AJC_DOLLAR_PREFIX = { 'a', 'j', 'c', '$' }; | |||
// public static final char[] CLINIT = { '<', 'c', 'l', 'i', 'n', 'i', 't', '>' }; | |||
public static final String PREFIX = "ajc$"; | |||
// public static final char[] INIT = { '<', 'i', 'n', 'i', 't', '>' }; | |||
public static final String ITD_PREFIX = PREFIX + "interType$"; | |||
// public static final char[] METHOD_ASPECTOF = {'a', 's', 'p','e','c','t','O','f'}; | |||
// public static final char[] METHOD_HASASPECT = { 'h', 'a', 's', 'A', 's', 'p', 'e', 'c', 't' }; | |||
// public static final char[] STATIC_INITIALIZER = { '<', 'c', 'l', 'i', 'n', 'i', 't', '>' }; | |||
public static final String CFLOW_STACK_TYPE = "org.aspectj.runtime.internal.CFlowStack"; | |||
public static final String CFLOW_COUNTER_TYPE = "org.aspectj.runtime.internal.CFlowCounter"; | |||
public static final UnresolvedType CFLOW_STACK_UNRESOLVEDTYPE = UnresolvedType | |||
.forSignature("Lorg/aspectj/runtime/internal/CFlowStack;"); | |||
public static final UnresolvedType CFLOW_COUNTER_UNRESOLVEDTYPE = UnresolvedType | |||
.forSignature("Lorg/aspectj/runtime/internal/CFlowCounter;"); | |||
public static final String SOFT_EXCEPTION_TYPE = "org.aspectj.lang.SoftException"; | |||
public static final String PERSINGLETON_FIELD_NAME = PREFIX + "perSingletonInstance"; | |||
public static final String PERCFLOW_FIELD_NAME = PREFIX + "perCflowStack"; | |||
// public static final String PERTHIS_FIELD_NAME = PREFIX + "perSingletonInstance"; | |||
// ----- | |||
public static final String PERCFLOW_PUSH_METHOD = PREFIX + "perCflowPush"; | |||
public static final String PEROBJECT_BIND_METHOD = PREFIX + "perObjectBind"; | |||
// PTWIMPL Method and field names | |||
public static final String PERTYPEWITHIN_GETINSTANCE_METHOD = PREFIX + "getInstance"; | |||
public static final String PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD = PREFIX + "createAspectInstance"; | |||
public static final String PERTYPEWITHIN_WITHINTYPEFIELD = PREFIX + "withinType"; | |||
public static final String PERTYPEWITHIN_GETWITHINTYPENAME_METHOD = "getWithinTypeName"; | |||
public static final String AJC_PRE_CLINIT_NAME = PREFIX + "preClinit"; | |||
public static final String AJC_POST_CLINIT_NAME = PREFIX + "postClinit"; | |||
public static final String INITFAILURECAUSE_FIELD_NAME = PREFIX + "initFailureCause"; | |||
public static boolean isSyntheticMethod(String methodName, boolean declaredInAspect) { | |||
if (methodName.startsWith(PREFIX)) { | |||
// it's synthetic unless it is an advice method | |||
if (methodName.startsWith("ajc$before") || methodName.startsWith("ajc$after")) { | |||
return false; | |||
} else if (methodName.startsWith("ajc$around")) { | |||
// around advice method is not synthetic, but generated proceed is... | |||
return (methodName.endsWith("proceed")); | |||
} else if (methodName.startsWith("ajc$interMethod$")) { | |||
return false; // body of an itd-m | |||
} | |||
return true; | |||
} else if (methodName.indexOf("_aroundBody") != -1) { | |||
return true; | |||
} | |||
// these aren't the droids you're looking for...move along...... pr148727 | |||
// else if (declaredInAspect) { | |||
// if (methodName.equals("aspectOf") || methodName.equals("hasAspect")) { | |||
// return true; | |||
// } | |||
// } | |||
return false; | |||
} | |||
public static String perObjectInterfaceGet(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "perObjectGet"); | |||
} | |||
public static String perObjectInterfaceSet(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "perObjectSet"); | |||
} | |||
public static String perObjectInterfaceField(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "perObjectField"); | |||
} | |||
// PTWIMPL method names that must include aspect type | |||
public static String perTypeWithinFieldForTarget(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); | |||
} | |||
public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "localAspectOf"); | |||
} | |||
public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) { | |||
return makeName("instance", aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier()); | |||
} | |||
public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("privMethod", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
public static String privilegedAccessMethodForFieldGet(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("privFieldGet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
public static String privilegedAccessMethodForFieldSet(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("privFieldSet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
public static String inlineAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("inlineAccessMethod", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
public static String inlineAccessMethodForFieldGet(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("inlineAccessFieldGet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
public static String inlineAccessMethodForFieldSet(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("inlineAccessFieldSet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* The name of methods corresponding to advice declarations Of the form: | |||
* "ajc$[AdviceKind]$[AspectName]$[NumberOfAdviceInAspect]$[PointcutHash]" | |||
*/ | |||
public static String adviceName(String nameAsIdentifier, AdviceKind kind, int adviceSeqNumber, int pcdHash) { | |||
String newname = makeName(kind.getName(), nameAsIdentifier, Integer.toString(adviceSeqNumber), Integer.toHexString(pcdHash)); | |||
return newname; | |||
} | |||
/** | |||
* This field goes on top-most implementers of the interface the field is declared onto | |||
*/ | |||
public static String interFieldInterfaceField(UnresolvedType aspectType, UnresolvedType interfaceType, String name) { | |||
return makeName("interField", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This instance method goes on the interface the field is declared onto as well as its top-most implementors | |||
*/ | |||
public static String interFieldInterfaceSetter(UnresolvedType aspectType, UnresolvedType interfaceType, String name) { | |||
return makeName("interFieldSet", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This instance method goes on the interface the field is declared onto as well as its top-most implementors | |||
*/ | |||
public static String interFieldInterfaceGetter(UnresolvedType aspectType, UnresolvedType interfaceType, String name) { | |||
return makeName("interFieldGet", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This static method goes on the aspect that declares the inter-type field | |||
*/ | |||
public static String interFieldSetDispatcher(UnresolvedType aspectType, UnresolvedType onType, String name) { | |||
return makeName("interFieldSetDispatch", aspectType.getNameAsIdentifier(), onType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This static method goes on the aspect that declares the inter-type field | |||
*/ | |||
public static String interFieldGetDispatcher(UnresolvedType aspectType, UnresolvedType onType, String name) { | |||
return makeName("interFieldGetDispatch", aspectType.getNameAsIdentifier(), onType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This field goes on the class the field is declared onto | |||
*/ | |||
public static String interFieldClassField(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
if (Modifier.isPublic(modifiers)) | |||
return name; | |||
// ??? might want to handle case where aspect and class are in same package similar to public | |||
return makeName("interField", makeVisibilityName(modifiers, aspectType), name); | |||
} | |||
// /** | |||
// * This static method goes on the aspect that declares the inter-type field | |||
// */ | |||
// public static String classFieldSetDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
// return makeName("interFieldSetDispatch", aspectType.getNameAsIdentifier(), | |||
// classType.getNameAsIdentifier(), name); | |||
// } | |||
// | |||
// /** | |||
// * This static method goes on the aspect that declares the inter-type field | |||
// */ | |||
// public static String classFieldGetDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name) | |||
// { | |||
// return makeName( | |||
// "interFieldGetDispatch", | |||
// aspectType.getNameAsIdentifier(), | |||
// classType.getNameAsIdentifier(), | |||
// name); | |||
// } | |||
/** | |||
* This static void method goes on the aspect that declares the inter-type field and is called from the appropriate place | |||
* (target's initializer, or clinit, or topmost implementer's inits), to initialize the field; | |||
*/ | |||
public static String interFieldInitializer(UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
return makeName("interFieldInit", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name); | |||
} | |||
// ---- | |||
/** | |||
* This method goes on the target type of the inter-type method. (and possibly the topmost-implemeters, if the target type is an | |||
* interface) | |||
*/ | |||
public static String interMethod(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
if (Modifier.isPublic(modifiers)) | |||
return name; | |||
// ??? might want to handle case where aspect and class are in same package similar to public | |||
return makeName("interMethodDispatch2", makeVisibilityName(modifiers, aspectType), name); | |||
} | |||
/** | |||
* This static method goes on the declaring aspect of the inter-type method. | |||
*/ | |||
public static String interMethodDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
return makeName("interMethodDispatch1", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This static method goes on the declaring aspect of the inter-type method. | |||
*/ | |||
public static String interMethodBody(UnresolvedType aspectType, UnresolvedType classType, String name) { | |||
return makeName("interMethod", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name); | |||
} | |||
// ---- | |||
/** | |||
* This static method goes on the declaring aspect of the inter-type constructor. | |||
*/ | |||
public static String preIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType) { | |||
return makeName("preInterConstructor", aspectType.getNameAsIdentifier(), targetType.getNameAsIdentifier()); | |||
} | |||
/** | |||
* This static method goes on the declaring aspect of the inter-type constructor. | |||
*/ | |||
public static String postIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType) { | |||
return makeName("postInterConstructor", aspectType.getNameAsIdentifier(), targetType.getNameAsIdentifier()); | |||
} | |||
// ---- | |||
/** | |||
* This static method goes on the target class of the inter-type method. | |||
*/ | |||
public static String superDispatchMethod(UnresolvedType classType, String name) { | |||
return makeName("superDispatch", classType.getNameAsIdentifier(), name); | |||
} | |||
/** | |||
* This static method goes on the target class of the inter-type method. | |||
*/ | |||
public static String protectedDispatchMethod(UnresolvedType classType, String name) { | |||
return makeName("protectedDispatch", classType.getNameAsIdentifier(), name); | |||
} | |||
// ---- | |||
private static String makeVisibilityName(int modifiers, UnresolvedType aspectType) { | |||
if (Modifier.isPrivate(modifiers)) { | |||
return aspectType.getOutermostType().getNameAsIdentifier(); | |||
} else if (Modifier.isProtected(modifiers)) { | |||
throw new RuntimeException("protected inter-types not allowed"); | |||
} else if (Modifier.isPublic(modifiers)) { | |||
return ""; | |||
} else { | |||
return aspectType.getPackageNameAsIdentifier(); | |||
} | |||
} | |||
private static String makeName(String s1, String s2) { | |||
return "ajc$" + s1 + "$" + s2; | |||
} | |||
public static String makeName(String s1, String s2, String s3) { | |||
return "ajc$" + s1 + "$" + s2 + "$" + s3; | |||
} | |||
public static String makeName(String s1, String s2, String s3, String s4) { | |||
return "ajc$" + s1 + "$" + s2 + "$" + s3 + "$" + s4; | |||
} | |||
public static String cflowStack(CrosscuttingMembers xcut) { | |||
return makeName("cflowStack", Integer.toHexString(xcut.getCflowEntries().size())); | |||
} | |||
public static String cflowCounter(CrosscuttingMembers xcut) { | |||
return makeName("cflowCounter", Integer.toHexString(xcut.getCflowEntries().size())); | |||
} | |||
public static String makeClosureClassName(UnresolvedType enclosingType, int index) { | |||
return enclosingType.getName() + "$AjcClosure" + index; | |||
} | |||
public static String aroundCallbackMethodName(Member shadowSig, String suffixTag) { | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append(getExtractableName(shadowSig)).append("_aroundBody").append(suffixTag); | |||
return ret.toString(); | |||
} | |||
public static String getExtractableName(Member shadowSignature) { | |||
String name = shadowSignature.getName(); | |||
MemberKind kind = shadowSignature.getKind(); | |||
if (kind == Member.CONSTRUCTOR) | |||
return "init$"; | |||
else if (kind == Member.STATIC_INITIALIZATION) | |||
return "clinit$"; | |||
else | |||
return name; | |||
} | |||
public static String proceedMethodName(String adviceMethodName) { | |||
return adviceMethodName + "proceed"; | |||
} | |||
} |
@@ -0,0 +1,144 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public class NewConstructorTypeMunger extends ResolvedTypeMunger { | |||
private ResolvedMember syntheticConstructor; | |||
private ResolvedMember explicitConstructor; | |||
public NewConstructorTypeMunger( | |||
ResolvedMember signature, | |||
ResolvedMember syntheticConstructor, | |||
ResolvedMember explicitConstructor, | |||
Set superMethodsCalled, | |||
List typeVariableAliases) { | |||
super(Constructor, signature); | |||
this.syntheticConstructor = syntheticConstructor; | |||
this.typeVariableAliases = typeVariableAliases; | |||
this.explicitConstructor = explicitConstructor; | |||
this.setSuperMethodsCalled(superMethodsCalled); | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof NewConstructorTypeMunger)) return false; | |||
NewConstructorTypeMunger o = (NewConstructorTypeMunger)other; | |||
return ((o.syntheticConstructor == null) ? (syntheticConstructor == null ) | |||
: syntheticConstructor.equals(o.syntheticConstructor)) | |||
& ((o.explicitConstructor == null) ? (explicitConstructor == null ) | |||
: explicitConstructor.equals(o.explicitConstructor)); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37*result + ((syntheticConstructor == null) ? 0 : syntheticConstructor.hashCode()); | |||
result = 37*result + ((explicitConstructor == null) ? 0 : explicitConstructor.hashCode()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
// doesnt seem required.... | |||
// public ResolvedMember getDispatchMethod(UnresolvedType aspectType) { | |||
// return AjcMemberMaker.interMethodBody(signature, aspectType); | |||
// } | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.write(s); | |||
syntheticConstructor.write(s); | |||
explicitConstructor.write(s); | |||
writeSuperMethodsCalled(s); | |||
writeSourceLocation(s); | |||
writeOutTypeAliases(s); | |||
} | |||
public static ResolvedTypeMunger readConstructor(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ISourceLocation sloc = null; | |||
ResolvedMember sig = ResolvedMemberImpl.readResolvedMember(s, context); | |||
ResolvedMember syntheticCtor = ResolvedMemberImpl.readResolvedMember(s, context); | |||
ResolvedMember explicitCtor = ResolvedMemberImpl.readResolvedMember(s, context); | |||
Set superMethodsCalled = readSuperMethodsCalled(s); | |||
sloc = readSourceLocation(s); | |||
List typeVarAliases = readInTypeAliases(s); | |||
ResolvedTypeMunger munger = new NewConstructorTypeMunger(sig,syntheticCtor,explicitCtor,superMethodsCalled,typeVarAliases); | |||
if (sloc!=null) munger.setSourceLocation(sloc); | |||
return munger; | |||
} | |||
public ResolvedMember getExplicitConstructor() { | |||
return explicitConstructor; | |||
} | |||
public ResolvedMember getSyntheticConstructor() { | |||
return syntheticConstructor; | |||
} | |||
public void setExplicitConstructor(ResolvedMember explicitConstructor) { | |||
this.explicitConstructor = explicitConstructor; | |||
// reset hashCode so that its recalculated with new value | |||
hashCode = 0; | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
ResolvedMember ret = getSyntheticConstructor(); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
return super.getMatchingSyntheticMember(member, aspectType); | |||
} | |||
public void check(World world) { | |||
if (getSignature().getDeclaringType().resolve(world).isAspect()) { | |||
world.showMessage(IMessage.ERROR, | |||
WeaverMessages.format(WeaverMessages.ITD_CONS_ON_ASPECT), | |||
getSignature().getSourceLocation(), null); | |||
} | |||
} | |||
/** | |||
* see ResolvedTypeMunger.parameterizedFor(ResolvedType) | |||
*/ | |||
public ResolvedTypeMunger parameterizedFor(ResolvedType target) { | |||
ResolvedType genericType = target; | |||
if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType(); | |||
ResolvedMember parameterizedSignature = null; | |||
// If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used | |||
// in the original ITD declaration to the ones used in the actual target type declaration. | |||
if (target.isGenericType()) { | |||
TypeVariable vars[] = target.getTypeVariables(); | |||
UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length]; | |||
for (int i = 0; i < vars.length; i++) { | |||
varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]); | |||
} | |||
parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases); | |||
} else { | |||
// For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>) | |||
parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases); | |||
} | |||
NewConstructorTypeMunger nctm = new NewConstructorTypeMunger(parameterizedSignature,syntheticConstructor,explicitConstructor,getSuperMethodsCalled(),typeVariableAliases); | |||
nctm.setSourceLocation(getSourceLocation()); | |||
return nctm; | |||
} | |||
} |
@@ -0,0 +1,124 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public class NewFieldTypeMunger extends ResolvedTypeMunger { | |||
public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled, List typeVariableAliases) { | |||
super(Field, signature); | |||
this.typeVariableAliases = typeVariableAliases; | |||
signature.setAnnotatedElsewhere(true); | |||
this.setSuperMethodsCalled(superMethodsCalled); | |||
} | |||
public ResolvedMember getInitMethod(UnresolvedType aspectType) { | |||
return AjcMemberMaker.interFieldInitializer(signature, aspectType); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.write(s); | |||
writeSuperMethodsCalled(s); | |||
writeSourceLocation(s); | |||
writeOutTypeAliases(s); | |||
} | |||
public static ResolvedTypeMunger readField(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ISourceLocation sloc = null; | |||
ResolvedMember fieldSignature = ResolvedMemberImpl.readResolvedMember(s, context); | |||
Set superMethodsCalled = readSuperMethodsCalled(s); | |||
sloc = readSourceLocation(s); | |||
List aliases = readInTypeAliases(s); | |||
ResolvedTypeMunger munger = new NewFieldTypeMunger(fieldSignature,superMethodsCalled,aliases); | |||
if (sloc!=null) munger.setSourceLocation(sloc); | |||
return munger; | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
//??? might give a field where a method is expected | |||
ResolvedType onType = aspectType.getWorld().resolve(getSignature().getDeclaringType()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
ResolvedMember ret = AjcMemberMaker.interFieldGetDispatcher(getSignature(), aspectType); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
ret = AjcMemberMaker.interFieldSetDispatcher(getSignature(), aspectType); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
ret = AjcMemberMaker.interFieldInterfaceGetter(getSignature(), onType, aspectType); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
ret = AjcMemberMaker.interFieldInterfaceSetter(getSignature(), onType, aspectType); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
return super.getMatchingSyntheticMember(member, aspectType); | |||
} | |||
/** | |||
* see ResolvedTypeMunger.parameterizedFor(ResolvedType) | |||
*/ | |||
public ResolvedTypeMunger parameterizedFor(ResolvedType target) { | |||
ResolvedType genericType = target; | |||
if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType(); | |||
ResolvedMember parameterizedSignature = null; | |||
// If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used | |||
// in the original ITD declaration to the ones used in the actual target type declaration. | |||
if (target.isGenericType()) { | |||
TypeVariable vars[] = target.getTypeVariables(); | |||
UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length]; | |||
for (int i = 0; i < vars.length; i++) { | |||
varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]); | |||
} | |||
parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases); | |||
} else { | |||
// For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>) | |||
parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases); | |||
} | |||
NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases); | |||
nftm.setDeclaredSignature(getSignature()); | |||
nftm.setSourceLocation(getSourceLocation()); | |||
return nftm; | |||
} | |||
public ResolvedTypeMunger parameterizeWith(Map m, World w) { | |||
ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m,w); | |||
NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases); | |||
nftm.setDeclaredSignature(getSignature()); | |||
nftm.setSourceLocation(getSourceLocation()); | |||
return nftm; | |||
} | |||
public boolean equals(Object other) { | |||
if (! (other instanceof NewFieldTypeMunger)) return false; | |||
NewFieldTypeMunger o = (NewFieldTypeMunger) other; | |||
return kind.equals(o.kind) | |||
&& ((o.signature == null) ? (signature == null ) : signature.equals(o.signature)) | |||
&& ((o.declaredSignature == null) ? (declaredSignature == null ) : declaredSignature.equals(o.declaredSignature)) | |||
&& ((o.typeVariableAliases == null) ? (typeVariableAliases == null ) : typeVariableAliases.equals(o.typeVariableAliases)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + kind.hashCode(); | |||
result = 37*result + ((signature == null) ? 0 : signature.hashCode()); | |||
result = 37*result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode()); | |||
result = 37*result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode()); | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,146 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public class NewMethodTypeMunger extends ResolvedTypeMunger { | |||
public NewMethodTypeMunger(ResolvedMember signature, Set superMethodsCalled, List typeVariableAliases) { | |||
super(Method, signature); | |||
this.typeVariableAliases = typeVariableAliases; | |||
this.setSuperMethodsCalled(superMethodsCalled); | |||
} | |||
public ResolvedMember getInterMethodBody(UnresolvedType aspectType) { | |||
return AjcMemberMaker.interMethodBody(signature, aspectType); | |||
} | |||
/** | |||
* If the munger has a declared signature | |||
*/ | |||
public ResolvedMember getDeclaredInterMethodBody(UnresolvedType aspectType, World w) { | |||
if (declaredSignature != null) { | |||
ResolvedMember rm = declaredSignature.parameterizedWith(null, signature.getDeclaringType().resolve(w), false, | |||
getTypeVariableAliases()); | |||
return AjcMemberMaker.interMethodBody(rm, aspectType); | |||
} else { | |||
return AjcMemberMaker.interMethodBody(signature, aspectType); | |||
} | |||
} | |||
// public ResolvedMember getInterMethodDispatcher(UnresolvedType aspectType) { | |||
// return AjcMemberMaker.interMethodDispatcher(signature, aspectType); | |||
// } | |||
public ResolvedMember getDeclaredInterMethodDispatcher(UnresolvedType aspectType, World w) { | |||
if (declaredSignature != null) { | |||
ResolvedMember rm = declaredSignature.parameterizedWith(null, signature.getDeclaringType().resolve(w), false, | |||
getTypeVariableAliases()); | |||
return AjcMemberMaker.interMethodDispatcher(rm, aspectType); | |||
} else { | |||
return AjcMemberMaker.interMethodDispatcher(signature, aspectType); | |||
} | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.write(s); | |||
writeSuperMethodsCalled(s); | |||
writeSourceLocation(s); | |||
writeOutTypeAliases(s); | |||
} | |||
public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ISourceLocation sloc = null; | |||
ResolvedMemberImpl rmImpl = ResolvedMemberImpl.readResolvedMember(s, context); | |||
Set superMethodsCalled = readSuperMethodsCalled(s); | |||
sloc = readSourceLocation(s); | |||
List typeVarAliases = readInTypeAliases(s); | |||
ResolvedTypeMunger munger = new NewMethodTypeMunger(rmImpl, superMethodsCalled, typeVarAliases); | |||
if (sloc != null) | |||
munger.setSourceLocation(sloc); | |||
return munger; | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
ResolvedMember ret = AjcMemberMaker.interMethodDispatcher(getSignature(), aspectType); | |||
if (ResolvedType.matches(ret, member)) | |||
return getSignature(); | |||
return super.getMatchingSyntheticMember(member, aspectType); | |||
} | |||
/** | |||
* see ResolvedTypeMunger.parameterizedFor(ResolvedType) | |||
*/ | |||
public ResolvedTypeMunger parameterizedFor(ResolvedType target) { | |||
ResolvedType genericType = target; | |||
if (target.isRawType() || target.isParameterizedType()) | |||
genericType = genericType.getGenericType(); | |||
ResolvedMember parameterizedSignature = null; | |||
// If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used | |||
// in the original ITD declaration to the ones used in the actual target type declaration. | |||
if (target.isGenericType()) { | |||
TypeVariable vars[] = target.getTypeVariables(); | |||
UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length]; | |||
for (int i = 0; i < vars.length; i++) { | |||
varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]); | |||
} | |||
parameterizedSignature = getSignature().parameterizedWith(varRefs, genericType, true, typeVariableAliases); | |||
} else { | |||
// For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>) | |||
parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(), genericType, | |||
target.isParameterizedType(), typeVariableAliases); | |||
} | |||
NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases); | |||
nmtm.setDeclaredSignature(getSignature()); | |||
nmtm.setSourceLocation(getSourceLocation()); | |||
return nmtm; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof NewMethodTypeMunger)) | |||
return false; | |||
NewMethodTypeMunger o = (NewMethodTypeMunger) other; | |||
return kind.equals(o.kind) | |||
&& ((o.signature == null) ? (signature == null) : signature.equals(o.signature)) | |||
&& ((o.declaredSignature == null) ? (declaredSignature == null) : declaredSignature.equals(o.declaredSignature)) | |||
&& ((o.typeVariableAliases == null) ? (typeVariableAliases == null) : typeVariableAliases | |||
.equals(o.typeVariableAliases)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + kind.hashCode(); | |||
result = 37 * result + ((signature == null) ? 0 : signature.hashCode()); | |||
result = 37 * result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode()); | |||
result = 37 * result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode()); | |||
return result; | |||
} | |||
public ResolvedTypeMunger parameterizeWith(Map m, World w) { | |||
ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m, w); | |||
NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases); | |||
nmtm.setDeclaredSignature(getSignature()); | |||
nmtm.setSourceLocation(getSourceLocation()); | |||
return nmtm; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
public class NewParentTypeMunger extends ResolvedTypeMunger { | |||
ResolvedType newParent; | |||
public NewParentTypeMunger(ResolvedType newParent) { | |||
super(Parent, null); | |||
this.newParent = newParent; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public ResolvedType getNewParent() { | |||
return newParent; | |||
} | |||
public boolean equals(Object other) { | |||
if (! (other instanceof NewParentTypeMunger)) return false; | |||
NewParentTypeMunger o = (NewParentTypeMunger) other; | |||
return newParent.equals(o.newParent); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37*result + newParent.hashCode(); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
} |
@@ -0,0 +1,91 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Alexandre Vasseur rearchitected for #75442 finer grained matching | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.weaver.patterns.PerFromSuper; | |||
import org.aspectj.weaver.patterns.PerObject; | |||
import org.aspectj.weaver.patterns.PerThisOrTargetPointcutVisitor; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.TypePattern; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
public class PerObjectInterfaceTypeMunger extends ResolvedTypeMunger { | |||
private final UnresolvedType interfaceType; | |||
private final Pointcut testPointcut; | |||
private TypePattern lazyTestTypePattern; | |||
public boolean equals(Object other) { | |||
if (other==null || !(other instanceof PerObjectInterfaceTypeMunger)) return false; | |||
PerObjectInterfaceTypeMunger o = (PerObjectInterfaceTypeMunger)other; | |||
return ((testPointcut == null) ? (o.testPointcut == null ) : testPointcut.equals(o.testPointcut)) | |||
&& ((lazyTestTypePattern == null) ? (o.lazyTestTypePattern == null ) : lazyTestTypePattern.equals(o.lazyTestTypePattern)); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37*result + ((testPointcut == null) ? 0 : testPointcut.hashCode()); | |||
result = 37*result + ((lazyTestTypePattern == null) ? 0 : lazyTestTypePattern.hashCode()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
public PerObjectInterfaceTypeMunger(UnresolvedType aspectType, Pointcut testPointcut) { | |||
super(PerObjectInterface, null); | |||
this.testPointcut = testPointcut; | |||
this.interfaceType = AjcMemberMaker.perObjectInterfaceType(aspectType); | |||
} | |||
private TypePattern getTestTypePattern(ResolvedType aspectType) { | |||
if (lazyTestTypePattern == null) { | |||
final boolean isPerThis; | |||
if (aspectType.getPerClause() instanceof PerFromSuper) { | |||
PerFromSuper ps = (PerFromSuper) aspectType.getPerClause(); | |||
isPerThis = ((PerObject) ps.lookupConcretePerClause(aspectType)).isThis(); | |||
} else { | |||
isPerThis = ((PerObject) aspectType.getPerClause()).isThis(); | |||
} | |||
PerThisOrTargetPointcutVisitor v = new PerThisOrTargetPointcutVisitor(!isPerThis, aspectType); | |||
lazyTestTypePattern = v.getPerTypePointcut(testPointcut); | |||
// reset hashCode so that its recalculated with the new lazyTestTypePattern | |||
hashCode = 0; | |||
} | |||
return lazyTestTypePattern; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
throw new RuntimeException("shouldn't be serialized"); | |||
} | |||
public UnresolvedType getInterfaceType() { | |||
return interfaceType; | |||
} | |||
public Pointcut getTestPointcut() { | |||
return testPointcut; | |||
} | |||
public boolean matches(ResolvedType matchType, ResolvedType aspectType) { | |||
if (matchType.isInterface()) return false; | |||
return getTestTypePattern(aspectType).matchesStatically(matchType); | |||
} | |||
public boolean isLateMunger() { | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 IBM, 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.weaver.patterns.PerTypeWithin; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
// PTWIMPL Target type munger adds the localAspectOf() method | |||
public class PerTypeWithinTargetTypeMunger extends ResolvedTypeMunger { | |||
private UnresolvedType aspectType; | |||
private PerTypeWithin testPointcut; | |||
public PerTypeWithinTargetTypeMunger(UnresolvedType aspectType, PerTypeWithin testPointcut) { | |||
super(PerTypeWithinInterface, null); | |||
this.aspectType = aspectType; | |||
this.testPointcut = testPointcut; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerTypeWithinTargetTypeMunger)) return false; | |||
PerTypeWithinTargetTypeMunger o = (PerTypeWithinTargetTypeMunger)other; | |||
return ((o.testPointcut == null) ? (testPointcut == null ) : testPointcut.equals(o.testPointcut)) | |||
&& ((o.aspectType == null) ? (aspectType == null ) : aspectType.equals(o.aspectType)); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37*result + ((testPointcut == null) ? 0 : testPointcut.hashCode()); | |||
result = 37*result + ((aspectType == null) ? 0 : aspectType.hashCode()); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
throw new RuntimeException("shouldn't be serialized"); | |||
} | |||
public UnresolvedType getAspectType() { | |||
return aspectType; | |||
} | |||
public Pointcut getTestPointcut() { | |||
return testPointcut; | |||
} | |||
// This is a lexical within() so if you say PerTypeWithin(Test) and matchType is an | |||
// inner type (e.g. Test$NestedType) then it should match successfully | |||
// Does not match if the target is an interface | |||
public boolean matches(ResolvedType matchType, ResolvedType aspectType) { | |||
return isWithinType(matchType).alwaysTrue() && | |||
!matchType.isInterface(); | |||
} | |||
private FuzzyBoolean isWithinType(ResolvedType type) { | |||
while (type != null) { | |||
if (testPointcut.getTypePattern().matchesStatically(type)) { | |||
return FuzzyBoolean.YES; | |||
} | |||
type = type.getDeclaringType(); | |||
} | |||
return FuzzyBoolean.NO; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2006 IBM | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor; | |||
import org.aspectj.weaver.patterns.AndPointcut; | |||
import org.aspectj.weaver.patterns.KindedPointcut; | |||
import org.aspectj.weaver.patterns.NotPointcut; | |||
import org.aspectj.weaver.patterns.OrPointcut; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* Walks a pointcut and determines if the synchronization related designators have been used: lock() or unlock() | |||
*/ | |||
public class PoliceExtensionUse extends AbstractPatternNodeVisitor { | |||
private boolean synchronizationDesignatorEncountered; | |||
private World world; | |||
private Pointcut p; | |||
public PoliceExtensionUse(World w, Pointcut p) { | |||
this.world = w; | |||
this.p = p; | |||
this.synchronizationDesignatorEncountered = false; | |||
} | |||
public boolean synchronizationDesignatorEncountered() { | |||
return synchronizationDesignatorEncountered; | |||
} | |||
public Object visit(KindedPointcut node, Object data) { | |||
if (world == null) | |||
return super.visit(node, data); // error scenario can sometimes lead to this LazyClassGen.toLongString() | |||
if (node.getKind() == Shadow.SynchronizationLock || node.getKind() == Shadow.SynchronizationUnlock) | |||
synchronizationDesignatorEncountered = true; | |||
// Check it! | |||
if (!world.isJoinpointSynchronizationEnabled()) { | |||
if (node.getKind() == Shadow.SynchronizationLock) { | |||
IMessage m = MessageUtil.warn( | |||
"lock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization", p | |||
.getSourceLocation()); | |||
world.getMessageHandler().handleMessage(m); | |||
} else if (node.getKind() == Shadow.SynchronizationUnlock) { | |||
IMessage m = MessageUtil.warn( | |||
"unlock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization", p | |||
.getSourceLocation()); | |||
world.getMessageHandler().handleMessage(m); | |||
} | |||
} | |||
return super.visit(node, data); | |||
} | |||
public Object visit(AndPointcut node, Object data) { | |||
node.getLeft().accept(this, data); | |||
node.getRight().accept(this, data); | |||
return node; | |||
} | |||
public Object visit(NotPointcut node, Object data) { | |||
node.getNegatedPointcut().accept(this, data); | |||
return node; | |||
} | |||
public Object visit(OrPointcut node, Object data) { | |||
node.getLeft().accept(this, data); | |||
node.getRight().accept(this, data); | |||
return node; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class Position implements IHasPosition { | |||
private int start, end; | |||
public Position(int start, int end) { | |||
this.start = start; | |||
this.end = end; | |||
} | |||
public int getEnd() { | |||
return end; | |||
} | |||
public int getStart() { | |||
return start; | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
public class PrivilegedAccessMunger extends ResolvedTypeMunger { | |||
public PrivilegedAccessMunger(ResolvedMember member) { | |||
super(PrivilegedAccess, member); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
throw new RuntimeException("shouldn't be serialized"); | |||
} | |||
public ResolvedMember getMember() { | |||
return getSignature(); | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
ResolvedMember ret; | |||
if (getSignature().getKind() == Member.FIELD) { | |||
ret = AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, getSignature()); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
ret = AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, getSignature()); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
} else { | |||
//System.err.println("sig: " + getSignature()); | |||
ret = AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, getSignature()); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); | |||
} | |||
return null; | |||
} | |||
public boolean equals(Object other) { | |||
if (! (other instanceof PrivilegedAccessMunger)) return false; | |||
PrivilegedAccessMunger o = (PrivilegedAccessMunger) other; | |||
return kind.equals(o.kind) | |||
&& ((o.signature == null) ? (signature == null ) : signature.equals(o.signature)) | |||
&& ((o.declaredSignature == null) ? (declaredSignature == null ) : declaredSignature.equals(o.declaredSignature)) | |||
&& ((o.typeVariableAliases == null) ? (typeVariableAliases == null ) : typeVariableAliases.equals(o.typeVariableAliases)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + kind.hashCode(); | |||
result = 37*result + ((signature == null) ? 0 : signature.hashCode()); | |||
result = 37*result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode()); | |||
result = 37*result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode()); | |||
return result; | |||
} | |||
public boolean existsToSupportShadowMunging() { | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,810 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Andy Clement - June 2005 - separated out from ResolvedType | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.patterns.Declare; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* A reference type represents some 'real' type, not a primitive, not an array - but a real type, for example java.util.List. Each | |||
* ReferenceType has a delegate that is the underlying artifact - either an eclipse artifact or a bcel artifact. If the type | |||
* represents a raw type (i.e. there is a generic form) then the genericType field is set to point to the generic type. If it is for | |||
* a parameterized type then the generic type is also set to point to the generic form. | |||
*/ | |||
public class ReferenceType extends ResolvedType { | |||
/** | |||
* For generic types, this list holds references to all the derived raw and parameterized versions. We need this so that if the | |||
* generic delegate is swapped during incremental compilation, the delegate of the derivatives is swapped also. | |||
*/ | |||
private final List/* ReferenceType */derivativeTypes = new ArrayList(); | |||
/** | |||
* For parameterized types (or the raw type) - this field points to the actual reference type from which they are derived. | |||
*/ | |||
ReferenceType genericType = null; | |||
ReferenceTypeDelegate delegate = null; | |||
int startPos = 0; | |||
int endPos = 0; | |||
// cached values for members | |||
ResolvedMember[] parameterizedMethods = null; | |||
ResolvedMember[] parameterizedFields = null; | |||
ResolvedMember[] parameterizedPointcuts = null; | |||
ResolvedType[] parameterizedInterfaces = null; | |||
Collection parameterizedDeclares = null; | |||
Collection parameterizedTypeMungers = null; | |||
// ??? should set delegate before any use | |||
public ReferenceType(String signature, World world) { | |||
super(signature, world); | |||
} | |||
public ReferenceType(String signature, String signatureErasure, World world) { | |||
super(signature, signatureErasure, world); | |||
} | |||
public static ReferenceType fromTypeX(UnresolvedType tx, World world) { | |||
ReferenceType rt = new ReferenceType(tx.getErasureSignature(), world); | |||
rt.typeKind = tx.typeKind; | |||
return rt; | |||
} | |||
/** | |||
* Constructor used when creating a parameterized type. | |||
*/ | |||
public ReferenceType(ResolvedType theGenericType, ResolvedType[] theParameters, World aWorld) { | |||
super(makeParameterizedSignature(theGenericType, theParameters), theGenericType.signatureErasure, aWorld); | |||
ReferenceType genericReferenceType = (ReferenceType) theGenericType; | |||
this.typeParameters = theParameters; | |||
this.genericType = genericReferenceType; | |||
this.typeKind = TypeKind.PARAMETERIZED; | |||
this.delegate = genericReferenceType.getDelegate(); | |||
genericReferenceType.addDependentType(this); | |||
} | |||
/** | |||
* Constructor used when creating a raw type. | |||
*/ | |||
// public ReferenceType( | |||
// ResolvedType theGenericType, | |||
// World aWorld) { | |||
// super(theGenericType.getErasureSignature(), | |||
// theGenericType.getErasureSignature(), | |||
// aWorld); | |||
// ReferenceType genericReferenceType = (ReferenceType) theGenericType; | |||
// this.typeParameters = null; | |||
// this.genericType = genericReferenceType; | |||
// this.typeKind = TypeKind.RAW; | |||
// this.delegate = genericReferenceType.getDelegate(); | |||
// genericReferenceType.addDependentType(this); | |||
// } | |||
private void addDependentType(ReferenceType dependent) { | |||
this.derivativeTypes.add(dependent); | |||
} | |||
public String getSignatureForAttribute() { | |||
if (genericType == null || typeParameters == null) | |||
return getSignature(); | |||
return makeDeclaredSignature(genericType, typeParameters); | |||
} | |||
/** | |||
* Create a reference type for a generic type | |||
*/ | |||
public ReferenceType(UnresolvedType genericType, World world) { | |||
super(genericType.getSignature(), world); | |||
typeKind = TypeKind.GENERIC; | |||
} | |||
public boolean isClass() { | |||
return delegate.isClass(); | |||
} | |||
public boolean isGenericType() { | |||
return !isParameterizedType() && !isRawType() && delegate.isGeneric(); | |||
} | |||
public String getGenericSignature() { | |||
String sig = delegate.getDeclaredGenericSignature(); | |||
return (sig == null) ? "" : sig; | |||
} | |||
public AnnotationAJ[] getAnnotations() { | |||
return delegate.getAnnotations(); | |||
} | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
delegate.addAnnotation(annotationX); | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
return delegate.hasAnnotation(ofType); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
if (delegate == null) { | |||
throw new BCException("Unexpected null delegate for type " + this.getName()); | |||
} | |||
return delegate.getAnnotationTypes(); | |||
} | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
AnnotationAJ[] axs = delegate.getAnnotations(); | |||
if (axs == null) { | |||
return null; | |||
} | |||
for (int i = 0; i < axs.length; i++) { | |||
if (axs[i].getTypeSignature().equals(ofType.getSignature())) { | |||
return axs[i]; | |||
} | |||
} | |||
return null; | |||
} | |||
public boolean isAspect() { | |||
return delegate.isAspect(); | |||
} | |||
public boolean isAnnotationStyleAspect() { | |||
return delegate.isAnnotationStyleAspect(); | |||
} | |||
public boolean isEnum() { | |||
return delegate.isEnum(); | |||
} | |||
public boolean isAnnotation() { | |||
return delegate.isAnnotation(); | |||
} | |||
public boolean isAnonymous() { | |||
return delegate.isAnonymous(); | |||
} | |||
public boolean isNested() { | |||
return delegate.isNested(); | |||
} | |||
public ResolvedType getOuterClass() { | |||
return delegate.getOuterClass(); | |||
} | |||
public String getRetentionPolicy() { | |||
return delegate.getRetentionPolicy(); | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return delegate.isAnnotationWithRuntimeRetention(); | |||
} | |||
public boolean canAnnotationTargetType() { | |||
return delegate.canAnnotationTargetType(); | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return delegate.getAnnotationTargetKinds(); | |||
} | |||
// true iff the statement "this = (ThisType) other" would compile | |||
public boolean isCoerceableFrom(ResolvedType o) { | |||
ResolvedType other = o.resolve(world); | |||
if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) { | |||
return true; | |||
} | |||
if (this.isParameterizedType() && other.isParameterizedType()) { | |||
return isCoerceableFromParameterizedType(other); | |||
} | |||
if (!this.isInterface() && !other.isInterface()) { | |||
return false; | |||
} | |||
if (this.isFinal() || other.isFinal()) { | |||
return false; | |||
} | |||
// ??? needs to be Methods, not just declared methods? JLS 5.5 unclear | |||
ResolvedMember[] a = getDeclaredMethods(); | |||
ResolvedMember[] b = other.getDeclaredMethods(); // ??? is this cast | |||
// always safe | |||
for (int ai = 0, alen = a.length; ai < alen; ai++) { | |||
for (int bi = 0, blen = b.length; bi < blen; bi++) { | |||
if (!b[bi].isCompatibleWith(a[ai])) | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
private final boolean isCoerceableFromParameterizedType(ResolvedType other) { | |||
if (!other.isParameterizedType()) | |||
return false; | |||
ResolvedType myRawType = (ResolvedType) getRawType(); | |||
ResolvedType theirRawType = (ResolvedType) other.getRawType(); | |||
if (myRawType == theirRawType) { | |||
if (getTypeParameters().length == other.getTypeParameters().length) { | |||
// there's a chance it can be done | |||
ResolvedType[] myTypeParameters = getResolvedTypeParameters(); | |||
ResolvedType[] theirTypeParameters = other.getResolvedTypeParameters(); | |||
for (int i = 0; i < myTypeParameters.length; i++) { | |||
if (myTypeParameters[i] != theirTypeParameters[i]) { | |||
// thin ice now... but List<String> may still be | |||
// coerceable from e.g. List<T> | |||
if (myTypeParameters[i].isGenericWildcard()) { | |||
BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i]; | |||
if (!wildcard.canBeCoercedTo(theirTypeParameters[i])) | |||
return false; | |||
} else if (myTypeParameters[i].isTypeVariableReference()) { | |||
TypeVariableReferenceType tvrt = (TypeVariableReferenceType) myTypeParameters[i]; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
tv.resolve(world); | |||
if (!tv.canBeBoundTo(theirTypeParameters[i])) | |||
return false; | |||
} else if (theirTypeParameters[i].isTypeVariableReference()) { | |||
TypeVariableReferenceType tvrt = (TypeVariableReferenceType) theirTypeParameters[i]; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
tv.resolve(world); | |||
if (!tv.canBeBoundTo(myTypeParameters[i])) | |||
return false; | |||
} else { | |||
return false; | |||
} | |||
} | |||
} | |||
return true; | |||
} | |||
} else { | |||
// we do this walk for situations like the following: | |||
// Base<T>, Sub<S,T> extends Base<S> | |||
// is Sub<Y,Z> coerceable from Base<X> ??? | |||
for (Iterator i = getDirectSupertypes(); i.hasNext();) { | |||
ReferenceType parent = (ReferenceType) i.next(); | |||
if (parent.isCoerceableFromParameterizedType(other)) | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
public boolean isAssignableFrom(ResolvedType other) { | |||
return isAssignableFrom(other, false); | |||
} | |||
// true iff the statement "this = other" would compile. | |||
public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) { | |||
if (other.isPrimitiveType()) { | |||
if (!world.isInJava5Mode()) | |||
return false; | |||
if (ResolvedType.validBoxing.contains(this.getSignature() + other.getSignature())) | |||
return true; | |||
} | |||
if (this == other) | |||
return true; | |||
if (this.getSignature().equals(ResolvedType.OBJECT.getSignature())) | |||
return true; | |||
if ((this.isRawType() || this.isGenericType()) && other.isParameterizedType()) { | |||
if (isAssignableFrom((ResolvedType) other.getRawType())) | |||
return true; | |||
} | |||
if (this.isRawType() && other.isGenericType()) { | |||
if (isAssignableFrom((ResolvedType) other.getRawType())) | |||
return true; | |||
} | |||
if (this.isGenericType() && other.isRawType()) { | |||
if (isAssignableFrom(other.getGenericType())) | |||
return true; | |||
} | |||
if (this.isParameterizedType()) { | |||
// look at wildcards... | |||
if (((ReferenceType) this.getRawType()).isAssignableFrom(other)) { | |||
boolean wildcardsAllTheWay = true; | |||
ResolvedType[] myParameters = this.getResolvedTypeParameters(); | |||
for (int i = 0; i < myParameters.length; i++) { | |||
if (!myParameters[i].isGenericWildcard()) { | |||
wildcardsAllTheWay = false; | |||
} else { | |||
BoundedReferenceType boundedRT = (BoundedReferenceType) myParameters[i]; | |||
if (boundedRT.isExtends() || boundedRT.isSuper()) { | |||
wildcardsAllTheWay = false; | |||
} | |||
} | |||
} | |||
if (wildcardsAllTheWay && !other.isParameterizedType()) | |||
return true; | |||
// we have to match by parameters one at a time | |||
ResolvedType[] theirParameters = other.getResolvedTypeParameters(); | |||
boolean parametersAssignable = true; | |||
if (myParameters.length == theirParameters.length) { | |||
for (int i = 0; i < myParameters.length; i++) { | |||
if (myParameters[i] == theirParameters[i]) | |||
continue; | |||
if (myParameters[i].isAssignableFrom(theirParameters[i], allowMissing)) { | |||
continue; | |||
} | |||
if (!myParameters[i].isGenericWildcard()) { | |||
parametersAssignable = false; | |||
break; | |||
} else { | |||
BoundedReferenceType wildcardType = (BoundedReferenceType) myParameters[i]; | |||
if (!wildcardType.alwaysMatches(theirParameters[i])) { | |||
parametersAssignable = false; | |||
break; | |||
} | |||
} | |||
} | |||
} else { | |||
parametersAssignable = false; | |||
} | |||
if (parametersAssignable) | |||
return true; | |||
} | |||
} | |||
if (isTypeVariableReference() && !other.isTypeVariableReference()) { // eg | |||
// . | |||
// this | |||
// = | |||
// T | |||
// other | |||
// = | |||
// Ljava | |||
// / | |||
// lang | |||
// / | |||
// Object | |||
// ; | |||
TypeVariable aVar = ((TypeVariableReference) this).getTypeVariable(); | |||
return aVar.resolve(world).canBeBoundTo(other); | |||
} | |||
if (other.isTypeVariableReference()) { | |||
TypeVariableReferenceType otherType = (TypeVariableReferenceType) other; | |||
if (this instanceof TypeVariableReference) { | |||
return ((TypeVariableReference) this).getTypeVariable().resolve(world).canBeBoundTo( | |||
otherType.getTypeVariable().getFirstBound().resolve(world));// pr171952 | |||
// return | |||
// ((TypeVariableReference)this).getTypeVariable()==otherType | |||
// .getTypeVariable(); | |||
} else { | |||
// FIXME asc should this say canBeBoundTo?? | |||
return this.isAssignableFrom(otherType.getTypeVariable().getFirstBound().resolve(world)); | |||
} | |||
} | |||
if (allowMissing && other.isMissing()) | |||
return false; | |||
for (Iterator i = other.getDirectSupertypes(); i.hasNext();) { | |||
if (this.isAssignableFrom((ResolvedType) i.next(), allowMissing)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
public ISourceContext getSourceContext() { | |||
return delegate.getSourceContext(); | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
ISourceContext isc = delegate.getSourceContext(); | |||
return isc.makeSourceLocation(new Position(startPos, endPos)); | |||
} | |||
public boolean isExposedToWeaver() { | |||
return (delegate == null) || delegate.isExposedToWeaver(); // ??? where | |||
// does this | |||
// belong | |||
} | |||
public WeaverStateInfo getWeaverState() { | |||
return delegate.getWeaverState(); | |||
} | |||
public ResolvedMember[] getDeclaredFields() { | |||
if (parameterizedFields != null) | |||
return parameterizedFields; | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateFields = delegate.getDeclaredFields(); | |||
parameterizedFields = new ResolvedMember[delegateFields.length]; | |||
for (int i = 0; i < delegateFields.length; i++) { | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
isParameterizedType()); | |||
} | |||
return parameterizedFields; | |||
} else { | |||
return delegate.getDeclaredFields(); | |||
} | |||
} | |||
/** | |||
* Find out from the generic signature the true signature of any interfaces I implement. If I am parameterized, these may then | |||
* need to be parameterized before returning. | |||
*/ | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
if (parameterizedInterfaces != null) | |||
return parameterizedInterfaces; | |||
if (isParameterizedType()) { | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
// UnresolvedType[] paramTypes = | |||
// getTypesForMemberParameterization(); | |||
parameterizedInterfaces = new ResolvedType[delegateInterfaces.length]; | |||
for (int i = 0; i < delegateInterfaces.length; i++) { | |||
// We may have to sub/super set the set of parametertypes if the | |||
// implemented interface | |||
// needs more or less than this type does. (pr124803/pr125080) | |||
if (delegateInterfaces[i].isParameterizedType()) { | |||
parameterizedInterfaces[i] = delegateInterfaces[i].parameterize(getMemberParameterizationMap()).resolve(world); | |||
} else { | |||
parameterizedInterfaces[i] = delegateInterfaces[i]; | |||
} | |||
} | |||
return parameterizedInterfaces; | |||
} else if (isRawType()) { | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
UnresolvedType[] paramTypes = getTypesForMemberParameterization(); | |||
parameterizedInterfaces = new ResolvedType[delegateInterfaces.length]; | |||
for (int i = 0; i < parameterizedInterfaces.length; i++) { | |||
parameterizedInterfaces[i] = delegateInterfaces[i]; | |||
if (parameterizedInterfaces[i].isGenericType()) { | |||
// a generic supertype of a raw type is replaced by its raw | |||
// equivalent | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i].getRawType().resolve(getWorld()); | |||
} else if (parameterizedInterfaces[i].isParameterizedType()) { | |||
// a parameterized supertype collapses any type vars to | |||
// their upper bounds | |||
UnresolvedType[] toUseForParameterization = determineThoseTypesToUse(parameterizedInterfaces[i], paramTypes); | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i].parameterizedWith(toUseForParameterization); | |||
} | |||
} | |||
return parameterizedInterfaces; | |||
} | |||
return delegate.getDeclaredInterfaces(); | |||
} | |||
/** | |||
* Locates the named type variable in the list of those on this generic type and returns the type parameter from the second list | |||
* supplied. Returns null if it can't be found | |||
*/ | |||
// private UnresolvedType findTypeParameterInList(String name, | |||
// TypeVariable[] tvarsOnThisGenericType, UnresolvedType[] | |||
// paramTypes) { | |||
// int position = -1; | |||
// for (int i = 0; i < tvarsOnThisGenericType.length; i++) { | |||
// TypeVariable tv = tvarsOnThisGenericType[i]; | |||
// if (tv.getName().equals(name)) position = i; | |||
// } | |||
// if (position == -1 ) return null; | |||
// return paramTypes[position]; | |||
// } | |||
/** | |||
* It is possible this type has multiple type variables but the interface we are about to parameterize only uses a subset - this | |||
* method determines the subset to use by looking at the type variable names used. For example: <code> | |||
* class Foo<T extends String,E extends Number> implements SuperInterface<T> {} | |||
* </code> where <code> | |||
* interface SuperInterface<Z> {} | |||
* </code> In that | |||
* example, a use of the 'Foo' raw type should know that it implements the SuperInterface<String>. | |||
*/ | |||
private UnresolvedType[] determineThoseTypesToUse(ResolvedType parameterizedInterface, UnresolvedType[] paramTypes) { | |||
// What are the type parameters for the supertype? | |||
UnresolvedType[] tParms = parameterizedInterface.getTypeParameters(); | |||
UnresolvedType[] retVal = new UnresolvedType[tParms.length]; | |||
// Go through the supertypes type parameters, if any of them is a type | |||
// variable, use the | |||
// real type variable on the declaring type. | |||
// it is possibly overkill to look up the type variable - ideally the | |||
// entry in the type parameter list for the | |||
// interface should be the a ref to the type variable in the current | |||
// type ... but I'm not 100% confident right now. | |||
for (int i = 0; i < tParms.length; i++) { | |||
UnresolvedType tParm = tParms[i]; | |||
if (tParm.isTypeVariableReference()) { | |||
TypeVariableReference tvrt = (TypeVariableReference) tParm; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
int rank = getRank(tv.getName()); | |||
// -1 probably means it is a reference to a type variable on the | |||
// outer generic type (see pr129566) | |||
if (rank != -1) { | |||
retVal[i] = paramTypes[rank]; | |||
} else { | |||
retVal[i] = tParms[i]; | |||
} | |||
} else { | |||
retVal[i] = tParms[i]; | |||
} | |||
} | |||
return retVal; | |||
} | |||
/** | |||
* Returns the position within the set of type variables for this type for the specified type variable name. Returns -1 if there | |||
* is no type variable with the specified name. | |||
*/ | |||
private int getRank(String tvname) { | |||
TypeVariable[] thisTypesTVars = getGenericType().getTypeVariables(); | |||
for (int i = 0; i < thisTypesTVars.length; i++) { | |||
TypeVariable tv = thisTypesTVars[i]; | |||
if (tv.getName().equals(tvname)) | |||
return i; | |||
} | |||
return -1; | |||
} | |||
public ResolvedMember[] getDeclaredMethods() { | |||
if (parameterizedMethods != null) | |||
return parameterizedMethods; | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateMethods = delegate.getDeclaredMethods(); | |||
UnresolvedType[] parameters = getTypesForMemberParameterization(); | |||
parameterizedMethods = new ResolvedMember[delegateMethods.length]; | |||
for (int i = 0; i < delegateMethods.length; i++) { | |||
parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters, this, isParameterizedType()); | |||
} | |||
return parameterizedMethods; | |||
} else { | |||
return delegate.getDeclaredMethods(); | |||
} | |||
} | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
if (parameterizedPointcuts != null) | |||
return parameterizedPointcuts; | |||
if (isParameterizedType()) { | |||
ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts(); | |||
parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; | |||
for (int i = 0; i < delegatePointcuts.length; i++) { | |||
parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
isParameterizedType()); | |||
} | |||
return parameterizedPointcuts; | |||
} else { | |||
return delegate.getDeclaredPointcuts(); | |||
} | |||
} | |||
private UnresolvedType[] getTypesForMemberParameterization() { | |||
UnresolvedType[] parameters = null; | |||
if (isParameterizedType()) { | |||
parameters = getTypeParameters(); | |||
} else if (isRawType()) { | |||
// raw type, use upper bounds of type variables on generic type | |||
TypeVariable[] tvs = getGenericType().getTypeVariables(); | |||
parameters = new UnresolvedType[tvs.length]; | |||
for (int i = 0; i < tvs.length; i++) { | |||
parameters[i] = tvs[i].getFirstBound(); | |||
} | |||
} | |||
return parameters; | |||
} | |||
public UnresolvedType getRawType() { | |||
return super.getRawType().resolve(getWorld()); | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
if (this.typeVariables == null) { | |||
this.typeVariables = delegate.getTypeVariables(); | |||
for (int i = 0; i < this.typeVariables.length; i++) { | |||
this.typeVariables[i].resolve(world); | |||
} | |||
} | |||
return this.typeVariables; | |||
} | |||
public PerClause getPerClause() { | |||
PerClause pclause = delegate.getPerClause(); | |||
if (isParameterizedType()) { // could cache the result here... | |||
Map parameterizationMap = getAjMemberParameterizationMap(); | |||
pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, world); | |||
} | |||
return pclause; | |||
} | |||
public Collection getDeclares() { | |||
if (parameterizedDeclares != null) | |||
return parameterizedDeclares; | |||
Collection declares = null; | |||
if (ajMembersNeedParameterization()) { | |||
Collection genericDeclares = delegate.getDeclares(); | |||
parameterizedDeclares = new ArrayList(); | |||
Map parameterizationMap = getAjMemberParameterizationMap(); | |||
for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) { | |||
Declare declareStatement = (Declare) iter.next(); | |||
parameterizedDeclares.add(declareStatement.parameterizeWith(parameterizationMap, world)); | |||
} | |||
declares = parameterizedDeclares; | |||
} else { | |||
declares = delegate.getDeclares(); | |||
} | |||
for (Iterator iter = declares.iterator(); iter.hasNext();) { | |||
Declare d = (Declare) iter.next(); | |||
d.setDeclaringType(this); | |||
} | |||
return declares; | |||
} | |||
protected Collection getTypeMungers() { | |||
return delegate.getTypeMungers(); | |||
} | |||
// GENERICITDFIX | |||
// // Map parameterizationMap = getAjMemberParameterizationMap(); | |||
// | |||
// // if (parameterizedTypeMungers != null) return parameterizedTypeMungers; | |||
// Collection ret = null; | |||
// if (ajMembersNeedParameterization()) { | |||
// Collection genericDeclares = delegate.getTypeMungers(); | |||
// parameterizedTypeMungers = new ArrayList(); | |||
// Map parameterizationMap = getAjMemberParameterizationMap(); | |||
// for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) { | |||
// ConcreteTypeMunger munger = (ConcreteTypeMunger)iter.next(); | |||
// parameterizedTypeMungers.add(munger.parameterizeWith(parameterizationMap, | |||
// world)); | |||
// } | |||
// ret = parameterizedTypeMungers; | |||
// } else { | |||
// ret = delegate.getTypeMungers(); | |||
// } | |||
// return ret; | |||
// } | |||
protected Collection getPrivilegedAccesses() { | |||
return delegate.getPrivilegedAccesses(); | |||
} | |||
public int getModifiers() { | |||
return delegate.getModifiers(); | |||
} | |||
public ResolvedType getSuperclass() { | |||
ResolvedType ret = null; | |||
try { | |||
world.setTypeVariableLookupScope(this); | |||
ret = delegate.getSuperclass(); | |||
} finally { | |||
world.setTypeVariableLookupScope(null); | |||
} | |||
if (this.isParameterizedType() && ret.isParameterizedType()) { | |||
ret = ret.parameterize(getMemberParameterizationMap()).resolve(getWorld()); | |||
} | |||
return ret; | |||
} | |||
public ReferenceTypeDelegate getDelegate() { | |||
return delegate; | |||
} | |||
public void setDelegate(ReferenceTypeDelegate delegate) { | |||
// Don't copy from BcelObjectType to EclipseSourceType - the context may | |||
// be tidied (result null'd) after previous weaving | |||
if (this.delegate != null && this.delegate.copySourceContext() | |||
&& this.delegate.getSourceContext() != SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) | |||
((AbstractReferenceTypeDelegate) delegate).setSourceContext(this.delegate.getSourceContext()); | |||
this.delegate = delegate; | |||
for (Iterator it = this.derivativeTypes.iterator(); it.hasNext();) { | |||
ReferenceType dependent = (ReferenceType) it.next(); | |||
dependent.setDelegate(delegate); | |||
} | |||
// If we are raw, we have a generic type - we should ensure it uses the | |||
// same delegate | |||
if (isRawType() && getGenericType() != null) { | |||
ReferenceType genType = (ReferenceType) getGenericType(); | |||
if (genType.getDelegate() != delegate) { // avoids circular updates | |||
genType.setDelegate(delegate); | |||
} | |||
} | |||
clearParameterizationCaches(); | |||
} | |||
private void clearParameterizationCaches() { | |||
parameterizedFields = null; | |||
parameterizedInterfaces = null; | |||
parameterizedMethods = null; | |||
parameterizedPointcuts = null; | |||
} | |||
public int getEndPos() { | |||
return endPos; | |||
} | |||
public int getStartPos() { | |||
return startPos; | |||
} | |||
public void setEndPos(int endPos) { | |||
this.endPos = endPos; | |||
} | |||
public void setStartPos(int startPos) { | |||
this.startPos = startPos; | |||
} | |||
public boolean doesNotExposeShadowMungers() { | |||
return delegate.doesNotExposeShadowMungers(); | |||
} | |||
public String getDeclaredGenericSignature() { | |||
return delegate.getDeclaredGenericSignature(); | |||
} | |||
public void setGenericType(ReferenceType rt) { | |||
genericType = rt; | |||
// Should we 'promote' this reference type from simple to raw? | |||
// makes sense if someone is specifying that it has a generic form | |||
if (typeKind == TypeKind.SIMPLE) { | |||
typeKind = TypeKind.RAW; | |||
signatureErasure = signature; | |||
} | |||
} | |||
public void demoteToSimpleType() { | |||
genericType = null; | |||
typeKind = TypeKind.SIMPLE; | |||
signatureErasure = null; | |||
} | |||
public ResolvedType getGenericType() { | |||
if (isGenericType()) | |||
return this; | |||
return genericType; | |||
} | |||
/** | |||
* a parameterized signature starts with a "P" in place of the "L", see the comment on signatures in UnresolvedType. | |||
* | |||
* @param aGenericType | |||
* @param someParameters | |||
* @return | |||
*/ | |||
private static String makeParameterizedSignature(ResolvedType aGenericType, ResolvedType[] someParameters) { | |||
String rawSignature = aGenericType.getErasureSignature(); | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append(PARAMETERIZED_TYPE_IDENTIFIER); | |||
ret.append(rawSignature.substring(1, rawSignature.length() - 1)); | |||
ret.append("<"); | |||
for (int i = 0; i < someParameters.length; i++) { | |||
ret.append(someParameters[i].getSignature()); | |||
} | |||
ret.append(">;"); | |||
return ret.toString(); | |||
} | |||
private static String makeDeclaredSignature(ResolvedType aGenericType, UnresolvedType[] someParameters) { | |||
StringBuffer ret = new StringBuffer(); | |||
String rawSig = aGenericType.getErasureSignature(); | |||
ret.append(rawSig.substring(0, rawSig.length() - 1)); | |||
ret.append("<"); | |||
for (int i = 0; i < someParameters.length; i++) { | |||
ret.append(((ReferenceType) someParameters[i]).getSignatureForAttribute()); | |||
} | |||
ret.append(">;"); | |||
return ret.toString(); | |||
} | |||
} |
@@ -0,0 +1,105 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Andy Clement - June 2005 - separated out from ResolvedType | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* Abstraction over a type - a reference type is Object and a descendant of Object, other types (int/etc) are considered primitive | |||
* types. Abstract implementation provided by AbstractReferenceTypeDelegate. | |||
*/ | |||
public interface ReferenceTypeDelegate { | |||
// TODO asc move to proxy | |||
public void addAnnotation(AnnotationAJ annotationX); | |||
public void ensureDelegateConsistent(); // Required evil because of mutator | |||
// methods in delegates :( (see | |||
// pr85132) | |||
public boolean isAspect(); | |||
public boolean isAnnotationStyleAspect(); | |||
public boolean isInterface(); | |||
public boolean isEnum(); | |||
public boolean isAnnotation(); | |||
public String getRetentionPolicy(); | |||
public boolean canAnnotationTargetType(); | |||
public AnnotationTargetKind[] getAnnotationTargetKinds(); | |||
public boolean isAnnotationWithRuntimeRetention(); | |||
public boolean isClass(); | |||
public boolean isGeneric(); | |||
public boolean isAnonymous(); | |||
public boolean isNested(); | |||
public boolean isExposedToWeaver(); | |||
public boolean hasAnnotation(UnresolvedType ofType); | |||
public AnnotationAJ[] getAnnotations(); | |||
public ResolvedType[] getAnnotationTypes(); | |||
public ResolvedMember[] getDeclaredFields(); | |||
public ResolvedType[] getDeclaredInterfaces(); | |||
public ResolvedMember[] getDeclaredMethods(); | |||
public ResolvedMember[] getDeclaredPointcuts(); | |||
public TypeVariable[] getTypeVariables(); | |||
public PerClause getPerClause(); | |||
public Collection getDeclares(); | |||
public Collection getTypeMungers(); | |||
public Collection getPrivilegedAccesses(); | |||
public int getModifiers(); | |||
public ResolvedType getSuperclass(); | |||
public WeaverStateInfo getWeaverState(); | |||
public ReferenceType getResolvedTypeX(); | |||
public boolean doesNotExposeShadowMungers(); | |||
public ISourceContext getSourceContext(); | |||
public String getSourcefilename(); | |||
public String getDeclaredGenericSignature(); | |||
public ResolvedType getOuterClass(); | |||
public boolean copySourceContext(); | |||
} |
@@ -0,0 +1,191 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* AMC extracted as interface | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public interface ResolvedMember extends Member, AnnotatedElement, | |||
TypeVariableDeclaringElement { | |||
public static final ResolvedMember[] NONE = new ResolvedMember[0]; | |||
public int getModifiers(World world); | |||
public int getModifiers(); | |||
public UnresolvedType[] getExceptions(World world); | |||
public UnresolvedType[] getExceptions(); | |||
public ShadowMunger getAssociatedShadowMunger(); | |||
public boolean isAjSynthetic(); | |||
public boolean isCompatibleWith(Member am); | |||
public boolean hasAnnotations(); | |||
public boolean hasAnnotation(UnresolvedType ofType); | |||
public AnnotationAJ[] getAnnotations(); | |||
public ResolvedType[] getAnnotationTypes(); | |||
public void setAnnotationTypes(UnresolvedType[] annotationtypes); | |||
public void addAnnotation(AnnotationAJ annotation); | |||
public boolean isBridgeMethod(); | |||
public boolean isVarargsMethod(); | |||
public boolean isSynthetic(); | |||
public void write(DataOutputStream s) throws IOException; | |||
public ISourceContext getSourceContext(World world); | |||
public String[] getParameterNames(); | |||
public void setParameterNames(String[] names); | |||
public AnnotationAJ[][] getParameterAnnotations(); | |||
public ResolvedType[][] getParameterAnnotationTypes(); | |||
public String getAnnotationDefaultValue(); | |||
public String getParameterSignatureErased(); | |||
public String getSignatureErased(); | |||
public String[] getParameterNames(World world); | |||
public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature(); | |||
public ISourceLocation getSourceLocation(); | |||
public int getEnd(); | |||
public ISourceContext getSourceContext(); | |||
public int getStart(); | |||
public void setPosition(int sourceStart, int sourceEnd); | |||
public void setSourceContext(ISourceContext sourceContext); | |||
public boolean isAbstract(); | |||
public boolean isPublic(); | |||
public boolean isProtected(); | |||
public boolean isNative(); | |||
public boolean isDefault(); | |||
public boolean isVisible(ResolvedType fromType); | |||
public void setCheckedExceptions(UnresolvedType[] checkedExceptions); | |||
public void setAnnotatedElsewhere(boolean b); | |||
public boolean isAnnotatedElsewhere(); | |||
// like toString but include generic signature info | |||
public String toGenericString(); | |||
public String toDebugString(); | |||
public boolean hasBackingGenericMember(); | |||
public ResolvedMember getBackingGenericMember(); | |||
/** | |||
* Get the UnresolvedType for the return type, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType getGenericReturnType(); | |||
/** | |||
* Get the TypeXs of the parameter types, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType[] getGenericParameterTypes(); | |||
// return a resolved member in which all type variables in the signature of | |||
// this | |||
// member have been replaced with the given bindings. | |||
// the isParameterized flag tells us whether we are creating a raw type | |||
// version or not | |||
// if isParameterized List<T> will turn into List<String> (for example), | |||
// but if !isParameterized List<T> will turn into List. | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized); | |||
// this variant allows for aliases for type variables (i.e. allowing them to | |||
// have another name) | |||
// this is used for processing ITDs that share type variables with their | |||
// target generic type | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized, List aliases); | |||
public void setTypeVariables(TypeVariable[] types); | |||
public TypeVariable[] getTypeVariables(); | |||
// /** | |||
// * If this member is defined by a parameterized super-type, return the | |||
// erasure | |||
// * of that member. | |||
// * For example: | |||
// * interface I<T> { T foo(T aTea); } | |||
// * class C implements I<String> { | |||
// * String foo(String aString) { return "something"; } | |||
// * } | |||
// * The resolved member for C.foo has signature String foo(String). The | |||
// * erasure of that member is Object foo(Object) -- use upper bound of type | |||
// * variable. | |||
// * A type is a supertype of itself. | |||
// */ | |||
// public ResolvedMember getErasure(); | |||
/** | |||
* Returns true if this member matches the other. The matching takes into | |||
* account name and parameter types only. When comparing parameter types, we | |||
* allow any type variable to match any other type variable regardless of | |||
* bounds. | |||
*/ | |||
public boolean matches(ResolvedMember aCandidateMatch); | |||
public void resetName(String newName); | |||
public void resetKind(MemberKind newKind); | |||
public void resetModifiers(int newModifiers); | |||
public void resetReturnTypeToObjectArray(); | |||
public void evictWeavingState(); | |||
public ResolvedMember parameterizedWith(Map m, World w); | |||
} |
@@ -0,0 +1,165 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
public class ResolvedPointcutDefinition extends ResolvedMemberImpl { | |||
private Pointcut pointcut; | |||
public ResolvedPointcutDefinition( | |||
UnresolvedType declaringType, | |||
int modifiers, | |||
String name, | |||
UnresolvedType[] parameterTypes, | |||
Pointcut pointcut) | |||
{ | |||
this(declaringType, modifiers, name, parameterTypes, ResolvedType.VOID, pointcut); | |||
} | |||
/** | |||
* An instance which can be given a specific returnType, used f.e. in if() pointcut for @AJ | |||
* | |||
* @param declaringType | |||
* @param modifiers | |||
* @param name | |||
* @param parameterTypes | |||
* @param returnType | |||
* @param pointcut | |||
*/ | |||
public ResolvedPointcutDefinition( | |||
UnresolvedType declaringType, | |||
int modifiers, | |||
String name, | |||
UnresolvedType[] parameterTypes, | |||
UnresolvedType returnType, | |||
Pointcut pointcut) | |||
{ | |||
super( | |||
POINTCUT, | |||
declaringType, | |||
modifiers, | |||
returnType, | |||
name, | |||
parameterTypes); | |||
this.pointcut = pointcut; | |||
//XXXpointcut.assertState(Pointcut.RESOLVED); | |||
checkedExceptions = UnresolvedType.NONE; | |||
} | |||
// ---- | |||
public void write(DataOutputStream s) throws IOException { | |||
getDeclaringType().write(s); | |||
s.writeInt(getModifiers()); | |||
s.writeUTF(getName()); | |||
UnresolvedType.writeArray(getParameterTypes(), s); | |||
pointcut.write(s); | |||
} | |||
public static ResolvedPointcutDefinition read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ResolvedPointcutDefinition rpd = | |||
new ResolvedPointcutDefinition( | |||
UnresolvedType.read(s), | |||
s.readInt(), | |||
s.readUTF(), | |||
UnresolvedType.readArray(s), | |||
Pointcut.read(s, context)); | |||
rpd.setSourceContext(context); // whilst we have a source context, let's remember it | |||
return rpd; | |||
} | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("pointcut "); | |||
buf.append((getDeclaringType()==null?"<nullDeclaringType>":getDeclaringType().getName())); | |||
buf.append("."); | |||
buf.append(getName()); | |||
buf.append("("); | |||
for (int i=0; i < getParameterTypes().length; i++) { | |||
if (i > 0) buf.append(", "); | |||
buf.append(getParameterTypes()[i].toString()); | |||
} | |||
buf.append(")"); | |||
//buf.append(pointcut); | |||
return buf.toString(); | |||
} | |||
public Pointcut getPointcut() { | |||
return pointcut; | |||
} | |||
public boolean isAjSynthetic() { | |||
return true; | |||
} | |||
/** | |||
* Called when asking a parameterized super-aspect for its pointcuts. | |||
*/ | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, boolean isParameterized) { | |||
TypeVariable[] typeVariables = getDeclaringType().resolve(newDeclaringType.getWorld()).getTypeVariables(); | |||
if (isParameterized && (typeVariables.length != typeParameters.length)) { | |||
throw new IllegalStateException("Wrong number of type parameters supplied"); | |||
} | |||
Map typeMap = new HashMap(); | |||
boolean typeParametersSupplied = typeParameters!=null && typeParameters.length>0; | |||
if (typeVariables!=null) { | |||
// If no 'replacements' were supplied in the typeParameters array then collapse | |||
// type variables to their first bound. | |||
for (int i = 0; i < typeVariables.length; i++) { | |||
UnresolvedType ut = (!typeParametersSupplied?typeVariables[i].getFirstBound():typeParameters[i]); | |||
typeMap.put(typeVariables[i].getName(),ut); | |||
} | |||
} | |||
UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(),typeMap,isParameterized); | |||
UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length]; | |||
for (int i = 0; i < parameterizedParameterTypes.length; i++) { | |||
parameterizedParameterTypes[i] = | |||
parameterize(getGenericParameterTypes()[i], typeMap,isParameterized); | |||
} | |||
ResolvedPointcutDefinition ret = new ResolvedPointcutDefinition( | |||
newDeclaringType, | |||
getModifiers(), | |||
getName(), | |||
parameterizedParameterTypes, | |||
parameterizedReturnType, | |||
pointcut.parameterizeWith(typeMap,newDeclaringType.getWorld()) | |||
); | |||
ret.setTypeVariables(getTypeVariables()); | |||
ret.setSourceContext(getSourceContext()); | |||
ret.setPosition(getStart(),getEnd()); | |||
ret.setParameterNames(getParameterNames()); | |||
return ret; | |||
//return this; | |||
} | |||
// for testing | |||
public static final ResolvedPointcutDefinition DUMMY = | |||
new ResolvedPointcutDefinition(UnresolvedType.OBJECT, 0, "missing", | |||
UnresolvedType.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED)); | |||
public static final ResolvedPointcutDefinition[] NO_POINTCUTS = new ResolvedPointcutDefinition[]{}; | |||
public void setPointcut(Pointcut pointcut) { | |||
this.pointcut = pointcut; | |||
} | |||
} |
@@ -0,0 +1,446 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Alexandre Vasseur @AspectJ ITDs | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.EOFException; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.ObjectInputStream; | |||
import java.io.ObjectOutputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.SourceLocation; | |||
import org.aspectj.util.TypeSafeEnum; | |||
/** | |||
* This is an abstraction over method/field introduction. It might not have the chops to handle other inter-type declarations. This | |||
* is the thing that is used on the eclipse side and serialized into a ConcreteTypeMunger. | |||
*/ | |||
public abstract class ResolvedTypeMunger { | |||
protected Kind kind; | |||
protected ResolvedMember signature; | |||
/** | |||
* The declared signature is filled in when a type munger is parameterized for application to a particular type. It represents | |||
* the signature originally declared in the source file. | |||
*/ | |||
protected ResolvedMember declaredSignature; | |||
// This list records the occurences (in order) of any names specified in the <> | |||
// for a target type for the ITD. So for example, for List<C,B,A> this list | |||
// will be C,B,A - the list is used later to map other occurrences of C,B,A | |||
// across the intertype declaration to the right type variables in the generic | |||
// type upon which the itd is being made. | |||
// might need serializing the class file for binary weaving. | |||
protected List /* String */typeVariableAliases; | |||
private Set /* resolvedMembers */superMethodsCalled = Collections.EMPTY_SET; | |||
private ISourceLocation location; // Lost during serialize/deserialize ! | |||
public ResolvedTypeMunger(Kind kind, ResolvedMember signature) { | |||
this.kind = kind; | |||
this.signature = signature; | |||
UnresolvedType declaringType = signature != null ? signature.getDeclaringType() : null; | |||
if (declaringType != null) { | |||
if (declaringType.isRawType()) | |||
throw new IllegalStateException("Use generic type, not raw type"); | |||
if (declaringType.isParameterizedType()) | |||
throw new IllegalStateException("Use generic type, not parameterized type"); | |||
} | |||
// boolean aChangeOccurred = false; | |||
// | |||
// UnresolvedType rt = signature.getReturnType(); | |||
// if (rt.isParameterizedType() || rt.isGenericType()) {rt = rt.getRawType();aChangeOccurred=true;} | |||
// UnresolvedType[] pt = signature.getParameterTypes(); | |||
// for (int i = 0; i < pt.length; i++) { | |||
// if (pt[i].isParameterizedType() || pt[i].isGenericType()) { pt[i] = pt[i].getRawType();aChangeOccurred=true;} | |||
// } | |||
// if (aChangeOccurred) { | |||
// this.signature = new | |||
// ResolvedMemberImpl(signature.getKind(),signature.getDeclaringType(),signature.getModifiers(),rt,signature | |||
// .getName(),pt,signature.getExceptions()); | |||
// } | |||
} | |||
public void setSourceLocation(ISourceLocation isl) { | |||
location = isl; | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return location; | |||
} | |||
// ---- | |||
// fromType is guaranteed to be a non-abstract aspect | |||
// public ConcreteTypeMunger concretize(World world, ResolvedType aspectType) { | |||
// | |||
// ConcreteTypeMunger munger = world.concreteTypeMunger(this, aspectType); | |||
// return munger; | |||
// } | |||
public boolean matches(ResolvedType matchType, ResolvedType aspectType) { | |||
ResolvedType onType = matchType.getWorld().resolve(signature.getDeclaringType()); | |||
if (onType.isRawType()) | |||
onType = onType.getGenericType(); | |||
// System.err.println("matching: " + this + " to " + matchType + " onType = " + onType); | |||
if (matchType.equals(onType)) { | |||
if (!onType.isExposedToWeaver()) { | |||
// if the onType is an interface, and it already has the member we are about | |||
// to munge, then this is ok... | |||
boolean ok = (onType.isInterface() && (onType.lookupMemberWithSupersAndITDs(getSignature()) != null)); | |||
if (!ok && onType.getWeaverState() == null) { | |||
if (matchType.getWorld().getLint().typeNotExposedToWeaver.isEnabled()) { | |||
matchType.getWorld().getLint().typeNotExposedToWeaver.signal(matchType.getName(), signature | |||
.getSourceLocation()); | |||
} | |||
} | |||
} | |||
return true; | |||
} | |||
// System.err.println("NO MATCH DIRECT"); | |||
if (onType.isInterface()) { | |||
return matchType.isTopmostImplementor(onType); | |||
} else { | |||
return false; | |||
} | |||
} | |||
// ---- | |||
public String toString() { | |||
return "ResolvedTypeMunger(" + getKind() + ", " + getSignature() + ")"; | |||
// .superMethodsCalled + ")"; | |||
} | |||
// ---- | |||
public static ResolvedTypeMunger read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
Kind kind = Kind.read(s); | |||
if (kind == Field) { | |||
return NewFieldTypeMunger.readField(s, context); | |||
} else if (kind == Method) { | |||
return NewMethodTypeMunger.readMethod(s, context); | |||
} else if (kind == Constructor) { | |||
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"); | |||
} | |||
} | |||
protected static Set readSuperMethodsCalled(VersionedDataInputStream s) throws IOException { | |||
Set ret = new HashSet(); | |||
int n = s.readInt(); | |||
if (n < 0) | |||
throw new BCException("Problem deserializing type munger"); | |||
for (int i = 0; i < n; i++) { | |||
ret.add(ResolvedMemberImpl.readResolvedMember(s, null)); | |||
} | |||
return ret; | |||
} | |||
protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException { | |||
if (superMethodsCalled == null || superMethodsCalled.size() == 0) { | |||
s.writeInt(0); | |||
return; | |||
} | |||
List ret = new ArrayList(superMethodsCalled); | |||
Collections.sort(ret); | |||
int n = ret.size(); | |||
s.writeInt(n); | |||
for (Iterator i = ret.iterator(); i.hasNext();) { | |||
ResolvedMember m = (ResolvedMember) i.next(); | |||
m.write(s); | |||
} | |||
} | |||
protected static ISourceLocation readSourceLocation(VersionedDataInputStream s) throws IOException { | |||
// Location persistence for type mungers was added after 1.2.1 was shipped... | |||
if (s.getMajorVersion() < AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) | |||
return null; | |||
SourceLocation ret = null; | |||
ObjectInputStream ois = null; | |||
try { | |||
// This logic copes with the location missing from the attribute - an EOFException will | |||
// occur on the next line and we ignore it. | |||
ois = new ObjectInputStream(s); | |||
Boolean validLocation = (Boolean) ois.readObject(); | |||
if (validLocation.booleanValue()) { | |||
File f = (File) ois.readObject(); | |||
Integer ii = (Integer) ois.readObject(); | |||
Integer offset = (Integer) ois.readObject(); | |||
ret = new SourceLocation(f, ii.intValue()); | |||
ret.setOffset(offset.intValue()); | |||
} | |||
} catch (EOFException eof) { | |||
return null; // This exception occurs if processing an 'old style' file where the | |||
// type munger attributes don't include the source location. | |||
} catch (IOException ioe) { | |||
// Something went wrong, maybe this is an 'old style' file that doesnt attach locations to mungers? | |||
// (but I thought that was just an EOFException?) | |||
ioe.printStackTrace(); | |||
return null; | |||
} catch (ClassNotFoundException e) { | |||
} finally { | |||
if (ois != null) | |||
ois.close(); | |||
} | |||
return ret; | |||
} | |||
protected void writeSourceLocation(DataOutputStream s) throws IOException { | |||
ObjectOutputStream oos = new ObjectOutputStream(s); | |||
// oos.writeObject(location); | |||
oos.writeObject(new Boolean(location != null)); | |||
if (location != null) { | |||
oos.writeObject(location.getSourceFile()); | |||
oos.writeObject(new Integer(location.getLine())); | |||
oos.writeObject(new Integer(location.getOffset())); | |||
} | |||
oos.flush(); | |||
oos.close(); | |||
} | |||
public abstract void write(DataOutputStream s) throws IOException; | |||
public Kind getKind() { | |||
return kind; | |||
} | |||
public static class Kind extends TypeSafeEnum { | |||
/* private */Kind(String name, int key) { | |||
super(name, key); | |||
} | |||
public static Kind read(DataInputStream s) throws IOException { | |||
int key = s.readByte(); | |||
switch (key) { | |||
case 1: | |||
return Field; | |||
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 { | |||
return super.toString(); | |||
} | |||
} | |||
} | |||
// ---- fields | |||
public static final Kind Field = new Kind("Field", 1); | |||
public static final Kind Method = new Kind("Method", 2); | |||
public static final Kind Constructor = new Kind("Constructor", 5); | |||
// not serialized, only created during concretization of aspects | |||
public static final Kind PerObjectInterface = new Kind("PerObjectInterface", 3); | |||
public static final Kind PrivilegedAccess = new Kind("PrivilegedAccess", 4); | |||
public static final Kind Parent = new Kind("Parent", 6); | |||
public static final Kind PerTypeWithinInterface = new Kind("PerTypeWithinInterface", 7); // PTWIMPL not serialized, used during | |||
// concretization of aspects | |||
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"; | |||
public void setSuperMethodsCalled(Set c) { | |||
this.superMethodsCalled = c; | |||
} | |||
public Set getSuperMethodsCalled() { | |||
return superMethodsCalled; | |||
} | |||
public ResolvedMember getSignature() { | |||
return signature; | |||
} | |||
// ---- | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
if ((getSignature() != null) && getSignature().isPublic() && member.equals(getSignature())) { | |||
return getSignature(); | |||
} | |||
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; | |||
} | |||
} | |||
protected static List readInTypeAliases(VersionedDataInputStream s) throws IOException { | |||
if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { | |||
int count = s.readInt(); | |||
if (count != 0) { | |||
List aliases = new ArrayList(); | |||
for (int i = 0; i < count; i++) { | |||
aliases.add(s.readUTF()); | |||
} | |||
return aliases; | |||
} | |||
} | |||
return null; | |||
} | |||
protected void writeOutTypeAliases(DataOutputStream s) throws IOException { | |||
// Write any type variable aliases | |||
if (typeVariableAliases == null || typeVariableAliases.size() == 0) { | |||
s.writeInt(0); | |||
} else { | |||
s.writeInt(typeVariableAliases.size()); | |||
for (Iterator iter = typeVariableAliases.iterator(); iter.hasNext();) { | |||
String element = (String) iter.next(); | |||
s.writeUTF(element); | |||
} | |||
} | |||
} | |||
public List getTypeVariableAliases() { | |||
return typeVariableAliases; | |||
} | |||
public boolean hasTypeVariableAliases() { | |||
return (typeVariableAliases != null && typeVariableAliases.size() > 0); | |||
} | |||
/** | |||
* return true if type variables are specified with the target type for this ITD. e.g. this would return true: | |||
* "int I<A,B>.m() { return 42; }" | |||
*/ | |||
public boolean sharesTypeVariablesWithGenericType() { | |||
return (typeVariableAliases != null && typeVariableAliases.size() > 0); | |||
} | |||
/** | |||
* Parameterizes a resolved type munger for a particular usage of its target type (this is used when the target type is generic | |||
* and the ITD shares type variables with the target) see ConcreteTypeMunger.parameterizedFor | |||
*/ | |||
public ResolvedTypeMunger parameterizedFor(ResolvedType target) { | |||
throw new BCException("Dont call parameterizedFor on a type munger of this kind: " + this.getClass()); | |||
} | |||
// ResolvedType genericType = target; | |||
// if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType(); | |||
// ResolvedMember parameterizedSignature = null; | |||
// // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used | |||
// // in the original ITD declaration to the ones used in the actual target type declaration. | |||
// if (target.isGenericType()) { | |||
// TypeVariable vars[] = target.getTypeVariables(); | |||
// UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length]; | |||
// for (int i = 0; i < vars.length; i++) { | |||
// varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]); | |||
// } | |||
// parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases); | |||
// } else { | |||
// // For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>) | |||
// parameterizedSignature = | |||
// getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases); | |||
// } | |||
// return new NewMethodTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases); | |||
// } | |||
// /** | |||
// * see ResolvedTypeMunger.parameterizedFor(ResolvedType) | |||
// */ | |||
// public ResolvedTypeMunger parameterizedFor(ResolvedType target) { | |||
// ResolvedType genericType = target; | |||
// if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType(); | |||
// ResolvedMember parameterizedSignature = | |||
// getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases); | |||
// return new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases); | |||
// } | |||
public void setDeclaredSignature(ResolvedMember rm) { | |||
declaredSignature = rm; | |||
} | |||
public ResolvedMember getDeclaredSignature() { | |||
return declaredSignature; | |||
} | |||
/** | |||
* A late munger has to be done after shadow munging since which shadows are matched can affect the operation of the late | |||
* munger. e.g. perobjectinterfacemunger | |||
*/ | |||
public boolean isLateMunger() { | |||
return false; | |||
} | |||
/** | |||
* Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow() | |||
* pointcut we create a new cflow field in the aspect, and that is added via a BcelCflowCounterFieldAdder. | |||
* | |||
* During compilation we need to compare sets of type mungers, and if some only come into existence after the 'shadowy' type | |||
* things have been processed, we need to ignore them during the comparison. | |||
* | |||
* Returning true from this method indicates the type munger exists to support 'shadowy' stuff - and so can be ignored in some | |||
* comparison. | |||
*/ | |||
public boolean existsToSupportShadowMunging() { | |||
return false; | |||
} | |||
public ResolvedTypeMunger parameterizeWith(Map m, World w) { | |||
throw new BCException("Dont call parameterizeWith() on a type munger of this kind: " + this.getClass()); | |||
} | |||
} |
@@ -0,0 +1,666 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataInputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.util.PartialOrder; | |||
import org.aspectj.util.TypeSafeEnum; | |||
import org.aspectj.weaver.ast.Var; | |||
/* | |||
* The superclass of anything representing a the shadow of a join point. A shadow represents | |||
* some bit of code, and encompasses both entry and exit from that code. All shadows have a kind | |||
* and a signature. | |||
*/ | |||
public abstract class Shadow { | |||
// every Shadow has a unique id, doesn't matter if it wraps... | |||
private static int nextShadowID = 100; // easier to spot than zero. // OPTIMIZE is this a bug? static? | |||
private final Kind kind; | |||
private final Member signature; | |||
private Member matchingSignature; | |||
private ResolvedMember resolvedSignature; | |||
protected final Shadow enclosingShadow; | |||
protected List mungers = Collections.EMPTY_LIST; | |||
public int shadowId = nextShadowID++; // every time we build a shadow, it gets a new id | |||
// ---- | |||
protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) { | |||
this.kind = kind; | |||
this.signature = signature; | |||
this.enclosingShadow = enclosingShadow; | |||
} | |||
// ---- | |||
public abstract World getIWorld(); | |||
public List /* ShadowMunger */getMungers() { | |||
return mungers; | |||
} | |||
/** | |||
* could this(*) pcd ever match | |||
*/ | |||
public final boolean hasThis() { | |||
if (getKind().neverHasThis()) { | |||
return false; | |||
} else if (getKind().isEnclosingKind()) { | |||
return !getSignature().isStatic(); | |||
} else if (enclosingShadow == null) { | |||
return false; | |||
} else { | |||
return enclosingShadow.hasThis(); | |||
} | |||
} | |||
/** | |||
* the type of the this object here | |||
* | |||
* @throws IllegalStateException if there is no this here | |||
*/ | |||
public final UnresolvedType getThisType() { | |||
if (!hasThis()) | |||
throw new IllegalStateException("no this"); | |||
if (getKind().isEnclosingKind()) { | |||
return getSignature().getDeclaringType(); | |||
} else { | |||
return enclosingShadow.getThisType(); | |||
} | |||
} | |||
/** | |||
* a var referencing this | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public abstract Var getThisVar(); | |||
/** | |||
* could target(*) pcd ever match | |||
*/ | |||
public final boolean hasTarget() { | |||
if (getKind().neverHasTarget()) { | |||
return false; | |||
} else if (getKind().isTargetSameAsThis()) { | |||
return hasThis(); | |||
} else { | |||
return !getSignature().isStatic(); | |||
} | |||
} | |||
/** | |||
* the type of the target object here | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public final UnresolvedType getTargetType() { | |||
if (!hasTarget()) | |||
throw new IllegalStateException("no target"); | |||
return getSignature().getDeclaringType(); | |||
} | |||
/** | |||
* a var referencing the target | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public abstract Var getTargetVar(); | |||
public UnresolvedType[] getArgTypes() { | |||
if (getKind() == FieldSet) | |||
return new UnresolvedType[] { getSignature().getReturnType() }; | |||
return getSignature().getParameterTypes(); | |||
} | |||
public boolean isShadowForArrayConstructionJoinpoint() { | |||
return (getKind() == ConstructorCall && signature.getDeclaringType().isArray()); | |||
} | |||
public boolean isShadowForMonitor() { | |||
return (getKind() == SynchronizationLock || getKind() == SynchronizationUnlock); | |||
} | |||
// will return the right length array of ints depending on how many dimensions the array has | |||
public ResolvedType[] getArgumentTypesForArrayConstructionShadow() { | |||
String s = signature.getDeclaringType().getSignature(); | |||
int pos = s.indexOf("["); | |||
int dims = 1; | |||
while (pos < s.length()) { | |||
pos++; | |||
if (pos < s.length()) | |||
dims += (s.charAt(pos) == '[' ? 1 : 0); | |||
} | |||
if (dims == 1) | |||
return new ResolvedType[] { ResolvedType.INT }; | |||
ResolvedType[] someInts = new ResolvedType[dims]; | |||
for (int i = 0; i < dims; i++) | |||
someInts[i] = ResolvedType.INT; | |||
return someInts; | |||
} | |||
public UnresolvedType[] getGenericArgTypes() { | |||
if (isShadowForArrayConstructionJoinpoint()) { | |||
return getArgumentTypesForArrayConstructionShadow(); | |||
} | |||
if (isShadowForMonitor()) { | |||
return UnresolvedType.ARRAY_WITH_JUST_OBJECT; | |||
} | |||
if (getKind() == FieldSet) | |||
return new UnresolvedType[] { getResolvedSignature().getGenericReturnType() }; | |||
return getResolvedSignature().getGenericParameterTypes(); | |||
} | |||
public UnresolvedType getArgType(int arg) { | |||
if (getKind() == FieldSet) | |||
return getSignature().getReturnType(); | |||
return getSignature().getParameterTypes()[arg]; | |||
} | |||
public int getArgCount() { | |||
if (getKind() == FieldSet) | |||
return 1; | |||
return getSignature().getParameterTypes().length; | |||
} | |||
// /** | |||
// * Return name of the argument at position 'i' at this shadow. This does not make sense for all shadows - but can be useful in | |||
// * the case of, for example, method-execution. | |||
// * | |||
// * @return null if it cannot be determined | |||
// */ | |||
// public String getArgName(int i, World w) { | |||
// String[] names = getSignature().getParameterNames(w); | |||
// if (names == null || i >= names.length) | |||
// return null; | |||
// return names[i]; | |||
// } | |||
public abstract UnresolvedType getEnclosingType(); | |||
public abstract Var getArgVar(int i); | |||
public abstract Var getThisJoinPointVar(); | |||
public abstract Var getThisJoinPointStaticPartVar(); | |||
public abstract Var getThisEnclosingJoinPointStaticPartVar(); | |||
// annotation variables | |||
public abstract Var getKindedAnnotationVar(UnresolvedType forAnnotationType); | |||
public abstract Var getWithinAnnotationVar(UnresolvedType forAnnotationType); | |||
public abstract Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType); | |||
public abstract Var getThisAnnotationVar(UnresolvedType forAnnotationType); | |||
public abstract Var getTargetAnnotationVar(UnresolvedType forAnnotationType); | |||
public abstract Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType); | |||
public abstract Member getEnclosingCodeSignature(); | |||
/** | |||
* returns the kind of shadow this is, representing what happens under this shadow | |||
*/ | |||
public Kind getKind() { | |||
return kind; | |||
} | |||
/** | |||
* returns the signature of the thing under this shadow | |||
*/ | |||
public Member getSignature() { | |||
return signature; | |||
} | |||
/** | |||
* returns the signature of the thing under this shadow, with any synthetic arguments removed | |||
*/ | |||
public Member getMatchingSignature() { | |||
return matchingSignature != null ? matchingSignature : signature; | |||
} | |||
public void setMatchingSignature(Member member) { | |||
this.matchingSignature = member; | |||
} | |||
/** | |||
* returns the resolved signature of the thing under this shadow | |||
* | |||
*/ | |||
public ResolvedMember getResolvedSignature() { | |||
if (resolvedSignature == null) { | |||
resolvedSignature = signature.resolve(getIWorld()); | |||
} | |||
return resolvedSignature; | |||
} | |||
public UnresolvedType getReturnType() { | |||
if (kind == ConstructorCall) | |||
return getSignature().getDeclaringType(); | |||
else if (kind == FieldSet) | |||
return ResolvedType.VOID; | |||
else if (kind == SynchronizationLock || kind == SynchronizationUnlock) | |||
return ResolvedType.VOID; | |||
return getResolvedSignature().getGenericReturnType(); | |||
} | |||
public static String METHOD_EXECUTION = "method-execution"; | |||
public static String METHOD_CALL = "method-call"; | |||
public static String CONSTRUCTOR_EXECUTION = "constructor-execution"; | |||
public static String CONSTRUCTOR_CALL = "constructor-call"; | |||
public static String FIELD_GET = "field-get"; | |||
public static String FIELD_SET = "field-set"; | |||
public static String STATICINITIALIZATION = "staticinitialization"; | |||
public static String PREINITIALIZATION = "preinitialization"; | |||
public static String INITIALIZATION = "initialization"; | |||
public static String EXCEPTION_HANDLER = "exception-handler"; | |||
public static String SYNCHRONIZATION_LOCK = "lock"; | |||
public static String SYNCHRONIZATION_UNLOCK = "unlock"; | |||
public static String ADVICE_EXECUTION = "adviceexecution"; | |||
/** | |||
* These names are the ones that will be returned by thisJoinPoint.getKind() Those need to be documented somewhere | |||
*/ | |||
public static final Kind MethodCall = new Kind(METHOD_CALL, 1, true); | |||
public static final Kind ConstructorCall = new Kind(CONSTRUCTOR_CALL, 2, true); | |||
public static final Kind MethodExecution = new Kind(METHOD_EXECUTION, 3, false); | |||
public static final Kind ConstructorExecution = new Kind(CONSTRUCTOR_EXECUTION, 4, false); | |||
public static final Kind FieldGet = new Kind(FIELD_GET, 5, true); | |||
public static final Kind FieldSet = new Kind(FIELD_SET, 6, true); | |||
public static final Kind StaticInitialization = new Kind(STATICINITIALIZATION, 7, false); | |||
public static final Kind PreInitialization = new Kind(PREINITIALIZATION, 8, false); | |||
public static final Kind AdviceExecution = new Kind(ADVICE_EXECUTION, 9, false); | |||
public static final Kind Initialization = new Kind(INITIALIZATION, 10, false); | |||
public static final Kind ExceptionHandler = new Kind(EXCEPTION_HANDLER, 11, true); | |||
public static final Kind SynchronizationLock = new Kind(SYNCHRONIZATION_LOCK, 12, true); | |||
public static final Kind SynchronizationUnlock = new Kind(SYNCHRONIZATION_UNLOCK, 13, true); | |||
// Bits here are 1<<(Kind.getKey()) - and unfortunately keys didn't start at zero so bits here start at 2 | |||
public static final int MethodCallBit = 0x002; | |||
public static final int ConstructorCallBit = 0x004; | |||
public static final int MethodExecutionBit = 0x008; | |||
public static final int ConstructorExecutionBit = 0x010; | |||
public static final int FieldGetBit = 0x020; | |||
public static final int FieldSetBit = 0x040; | |||
public static final int StaticInitializationBit = 0x080; | |||
public static final int PreInitializationBit = 0x100; | |||
public static final int AdviceExecutionBit = 0x200; | |||
public static final int InitializationBit = 0x400; | |||
public static final int ExceptionHandlerBit = 0x800; | |||
public static final int SynchronizationLockBit = 0x1000; | |||
public static final int SynchronizationUnlockBit = 0x2000; | |||
public static final int MAX_SHADOW_KIND = 13; | |||
public static final Kind[] SHADOW_KINDS = new Kind[] { MethodCall, ConstructorCall, MethodExecution, ConstructorExecution, | |||
FieldGet, FieldSet, StaticInitialization, PreInitialization, AdviceExecution, Initialization, ExceptionHandler, | |||
SynchronizationLock, SynchronizationUnlock }; | |||
public static final int ALL_SHADOW_KINDS_BITS; | |||
public static final int NO_SHADOW_KINDS_BITS; | |||
static { | |||
ALL_SHADOW_KINDS_BITS = 0x3ffe; | |||
NO_SHADOW_KINDS_BITS = 0x0000; | |||
} | |||
/** | |||
* Return count of how many bits set in the supplied parameter. | |||
*/ | |||
public static int howMany(int i) { | |||
int count = 0; | |||
for (int j = 0; j < SHADOW_KINDS.length; j++) { | |||
if ((i & SHADOW_KINDS[j].bit) != 0) | |||
count++; | |||
} | |||
return count; | |||
} | |||
/** | |||
* A type-safe enum representing the kind of shadows | |||
*/ | |||
public static final class Kind extends TypeSafeEnum { | |||
// private boolean argsOnStack; //XXX unused | |||
public int bit; | |||
public Kind(String name, int key, boolean argsOnStack) { | |||
super(name, key); | |||
bit = 1 << key; | |||
// this.argsOnStack = argsOnStack; | |||
} | |||
public String toLegalJavaIdentifier() { | |||
return getName().replace('-', '_'); | |||
} | |||
public boolean argsOnStack() { | |||
return !isTargetSameAsThis(); | |||
} | |||
// !!! this is false for handlers! | |||
public boolean allowsExtraction() { | |||
return true; | |||
} | |||
public boolean isSet(int i) { | |||
return (i & bit) != 0; | |||
} | |||
// XXX revisit along with removal of priorities | |||
public boolean hasHighPriorityExceptions() { | |||
return !isTargetSameAsThis(); | |||
} | |||
private final static int hasReturnValueFlag = MethodCallBit | ConstructorCallBit | MethodExecutionBit | FieldGetBit | |||
| AdviceExecutionBit; | |||
/** | |||
* These shadow kinds have return values that can be bound in after returning(Dooberry doo) advice. | |||
* | |||
* @return | |||
*/ | |||
public boolean hasReturnValue() { | |||
return (bit & hasReturnValueFlag) != 0; | |||
} | |||
private final static int isEnclosingKindFlag = MethodExecutionBit | ConstructorExecutionBit | AdviceExecutionBit | |||
| StaticInitializationBit | InitializationBit; | |||
/** | |||
* These are all the shadows that contains other shadows within them and are often directly associated with methods. | |||
*/ | |||
public boolean isEnclosingKind() { | |||
return (bit & isEnclosingKindFlag) != 0; | |||
} | |||
private final static int isTargetSameAsThisFlag = MethodExecutionBit | ConstructorExecutionBit | StaticInitializationBit | |||
| PreInitializationBit | AdviceExecutionBit | InitializationBit; | |||
public boolean isTargetSameAsThis() { | |||
return (bit & isTargetSameAsThisFlag) != 0; | |||
} | |||
private final static int neverHasTargetFlag = ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit | |||
| StaticInitializationBit | SynchronizationLockBit | SynchronizationUnlockBit; | |||
public boolean neverHasTarget() { | |||
return (bit & neverHasTargetFlag) != 0; | |||
} | |||
private final static int neverHasThisFlag = PreInitializationBit | StaticInitializationBit; | |||
public boolean neverHasThis() { | |||
return (bit & neverHasThisFlag) != 0; | |||
} | |||
public String getSimpleName() { | |||
int dash = getName().lastIndexOf('-'); | |||
if (dash == -1) | |||
return getName(); | |||
else | |||
return getName().substring(dash + 1); | |||
} | |||
public static Kind read(DataInputStream s) throws IOException { | |||
int key = s.readByte(); | |||
switch (key) { | |||
case 1: | |||
return MethodCall; | |||
case 2: | |||
return ConstructorCall; | |||
case 3: | |||
return MethodExecution; | |||
case 4: | |||
return ConstructorExecution; | |||
case 5: | |||
return FieldGet; | |||
case 6: | |||
return FieldSet; | |||
case 7: | |||
return StaticInitialization; | |||
case 8: | |||
return PreInitialization; | |||
case 9: | |||
return AdviceExecution; | |||
case 10: | |||
return Initialization; | |||
case 11: | |||
return ExceptionHandler; | |||
case 12: | |||
return SynchronizationLock; | |||
case 13: | |||
return SynchronizationUnlock; | |||
} | |||
throw new BCException("unknown kind: " + key); | |||
} | |||
} | |||
/** | |||
* Only does the check if the munger requires it (@AJ aspects don't) | |||
* | |||
* @param munger | |||
* @return | |||
*/ | |||
protected boolean checkMunger(ShadowMunger munger) { | |||
if (munger.mustCheckExceptions()) { | |||
for (Iterator i = munger.getThrownExceptions().iterator(); i.hasNext();) { | |||
if (!checkCanThrow(munger, (ResolvedType) i.next())) | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
protected boolean checkCanThrow(ShadowMunger munger, ResolvedType resolvedTypeX) { | |||
if (getKind() == ExceptionHandler) { | |||
// XXX much too lenient rules here, need to walk up exception handlers | |||
return true; | |||
} | |||
if (!isDeclaredException(resolvedTypeX, getSignature())) { | |||
getIWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_THROW_CHECKED, resolvedTypeX, this), // from | |||
// advice | |||
// in | |||
// \ | |||
// '" | |||
// + | |||
// munger | |||
// . | |||
// + | |||
// "\'" | |||
// , | |||
getSourceLocation(), munger.getSourceLocation()); | |||
} | |||
return true; | |||
} | |||
private boolean isDeclaredException(ResolvedType resolvedTypeX, Member member) { | |||
ResolvedType[] excs = getIWorld().resolve(member.getExceptions(getIWorld())); | |||
for (int i = 0, len = excs.length; i < len; i++) { | |||
if (excs[i].isAssignableFrom(resolvedTypeX)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
public void addMunger(ShadowMunger munger) { | |||
if (checkMunger(munger)) { | |||
if (mungers == Collections.EMPTY_LIST) | |||
mungers = new ArrayList(); | |||
this.mungers.add(munger); | |||
} | |||
} | |||
public final void implement() { | |||
sortMungers(); | |||
if (mungers == null) | |||
return; | |||
prepareForMungers(); | |||
implementMungers(); | |||
} | |||
private void sortMungers() { | |||
List sorted = PartialOrder.sort(mungers); | |||
// Bunch of code to work out whether to report xlints for advice that isn't ordered at this Joinpoint | |||
possiblyReportUnorderedAdvice(sorted); | |||
if (sorted == null) { | |||
// this means that we have circular dependencies | |||
for (Iterator i = mungers.iterator(); i.hasNext();) { | |||
ShadowMunger m = (ShadowMunger) i.next(); | |||
getIWorld().getMessageHandler().handleMessage( | |||
MessageUtil.error(WeaverMessages.format(WeaverMessages.CIRCULAR_DEPENDENCY, this), m.getSourceLocation())); | |||
} | |||
} | |||
mungers = sorted; | |||
} | |||
// not quite optimal... but the xlint is ignore by default | |||
private void possiblyReportUnorderedAdvice(List sorted) { | |||
if (sorted != null && getIWorld().getLint().unorderedAdviceAtShadow.isEnabled() && mungers.size() > 1) { | |||
// Stores a set of strings of the form 'aspect1:aspect2' which indicates there is no | |||
// precedence specified between the two aspects at this shadow. | |||
Set clashingAspects = new HashSet(); | |||
int max = mungers.size(); | |||
// Compare every pair of advice mungers | |||
for (int i = max - 1; i >= 0; i--) { | |||
for (int j = 0; j < i; j++) { | |||
Object a = mungers.get(i); | |||
Object b = mungers.get(j); | |||
// Make sure they are the right type | |||
if (a instanceof Advice && b instanceof Advice) { | |||
Advice adviceA = (Advice) a; | |||
Advice adviceB = (Advice) b; | |||
if (!adviceA.concreteAspect.equals(adviceB.concreteAspect)) { | |||
AdviceKind adviceKindA = adviceA.getKind(); | |||
AdviceKind adviceKindB = adviceB.getKind(); | |||
// make sure they are the nice ones (<6) and not any synthetic advice ones we | |||
// create to support other features of the language. | |||
if (adviceKindA.getKey() < (byte) 6 && adviceKindB.getKey() < (byte) 6 | |||
&& adviceKindA.getPrecedence() == adviceKindB.getPrecedence()) { | |||
// Ask the world if it knows about precedence between these | |||
Integer order = getIWorld().getPrecedenceIfAny(adviceA.concreteAspect, adviceB.concreteAspect); | |||
if (order != null && order.equals(new Integer(0))) { | |||
String key = adviceA.getDeclaringAspect() + ":" + adviceB.getDeclaringAspect(); | |||
String possibleExistingKey = adviceB.getDeclaringAspect() + ":" + adviceA.getDeclaringAspect(); | |||
if (!clashingAspects.contains(possibleExistingKey)) | |||
clashingAspects.add(key); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
for (Iterator iter = clashingAspects.iterator(); iter.hasNext();) { | |||
String element = (String) iter.next(); | |||
String aspect1 = element.substring(0, element.indexOf(":")); | |||
String aspect2 = element.substring(element.indexOf(":") + 1); | |||
getIWorld().getLint().unorderedAdviceAtShadow.signal(new String[] { this.toString(), aspect1, aspect2 }, this | |||
.getSourceLocation(), null); | |||
} | |||
} | |||
} | |||
/** | |||
* Prepare the shadow for implementation. After this is done, the shadow should be in such a position that each munger simply | |||
* needs to be implemented. | |||
*/ | |||
protected void prepareForMungers() { | |||
throw new RuntimeException("Generic shadows cannot be prepared"); | |||
} | |||
/** Actually implement the (non-empty) mungers associated with this shadow */ | |||
private void implementMungers() { | |||
World world = getIWorld(); | |||
for (Iterator iter = mungers.iterator(); iter.hasNext();) { | |||
ShadowMunger munger = (ShadowMunger) iter.next(); | |||
munger.implementOn(this); | |||
world.reportMatch(munger, this); | |||
} | |||
} | |||
public abstract ISourceLocation getSourceLocation(); | |||
// ---- utility | |||
public String toString() { | |||
return getKind() + "(" + getSignature() + ")"; // + getSourceLines(); | |||
} | |||
public String toResolvedString(World world) { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(getKind()); | |||
sb.append("("); | |||
Member m = getSignature(); | |||
if (m == null) { | |||
sb.append("<<missing signature>>"); | |||
} else { | |||
ResolvedMember rm = world.resolve(m); | |||
if (rm == null) { | |||
sb.append("<<unresolvableMember:").append(m).append(">>"); | |||
} else { | |||
String genString = rm.toGenericString(); | |||
if (genString == null) { | |||
sb.append("<<unableToGetGenericStringFor:").append(rm).append(">>"); | |||
} else { | |||
sb.append(genString); | |||
} | |||
} | |||
} | |||
sb.append(")"); | |||
return sb.toString(); | |||
// was: return getKind() + "(" + world.resolve(getSignature()).toGenericString() + ")"; | |||
} | |||
/** | |||
* Convert a bit array for the shadow kinds into a set of them... should only be used for testing - mainline code should do bit | |||
* manipulation! | |||
*/ | |||
public static Set toSet(int i) { | |||
Set results = new HashSet(); | |||
for (int j = 0; j < Shadow.SHADOW_KINDS.length; j++) { | |||
Kind k = Shadow.SHADOW_KINDS[j]; | |||
if (k.isSet(i)) | |||
results.add(k); | |||
} | |||
return results; | |||
} | |||
} |
@@ -0,0 +1,191 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.File; | |||
import java.util.Collection; | |||
import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.SourceLocation; | |||
import org.aspectj.util.PartialOrder; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* For every shadow munger, nothing can be done with it until it is concretized. Then... | |||
* | |||
* (Then we call fast match.) | |||
* | |||
* For every shadow munger, for every shadow, first match is called, then (if match returned true) the shadow munger is specialized | |||
* for the shadow, which may modify state. Then implement is called. | |||
*/ | |||
public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition { | |||
protected Pointcut pointcut; | |||
// these three fields hold the source location of this munger | |||
protected int start, end; | |||
protected ISourceContext sourceContext; | |||
private ISourceLocation sourceLocation; | |||
private ISourceLocation binarySourceLocation; | |||
private File binaryFile; | |||
public String handle = null; | |||
private ResolvedType declaringType; // the type that declared this munger. | |||
public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext) { | |||
this.pointcut = pointcut; | |||
this.start = start; | |||
this.end = end; | |||
this.sourceContext = sourceContext; | |||
} | |||
public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause); | |||
public abstract void specializeOn(Shadow shadow); | |||
public abstract void implementOn(Shadow shadow); | |||
/** | |||
* All overriding methods should call super | |||
*/ | |||
public boolean match(Shadow shadow, World world) { | |||
return pointcut.match(shadow).maybeTrue(); | |||
} | |||
public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap); | |||
public int fallbackCompareTo(Object other) { | |||
return toString().compareTo(toString()); | |||
} | |||
public int getEnd() { | |||
return end; | |||
} | |||
public int getStart() { | |||
return start; | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
if (sourceLocation == null) { | |||
if (sourceContext != null) { | |||
sourceLocation = sourceContext.makeSourceLocation(this); | |||
} | |||
} | |||
if (isBinary()) { | |||
if (binarySourceLocation == null) { | |||
binarySourceLocation = getBinarySourceLocation(sourceLocation); | |||
} | |||
return binarySourceLocation; | |||
} | |||
return sourceLocation; | |||
} | |||
// ---- fields | |||
public static final ShadowMunger[] NONE = new ShadowMunger[0]; | |||
public Pointcut getPointcut() { | |||
return pointcut; | |||
} | |||
// pointcut may be updated during rewriting... | |||
public void setPointcut(Pointcut pointcut) { | |||
this.pointcut = pointcut; | |||
} | |||
/** | |||
* Invoked when the shadow munger of a resolved type are processed. | |||
* | |||
* @param aType | |||
*/ | |||
public void setDeclaringType(ResolvedType aType) { | |||
declaringType = aType; | |||
} | |||
public ResolvedType getDeclaringType() { | |||
return declaringType; | |||
} | |||
/** | |||
* @return a Collection of ResolvedType for all checked exceptions that might be thrown by this munger | |||
*/ | |||
public abstract Collection getThrownExceptions(); | |||
/** | |||
* Does the munger has to check that its exception are accepted by the shadow ? ATAJ: It s not the case for @AJ around advice | |||
* f.e. that can throw Throwable, even if the advised method does not throw any exceptions. | |||
* | |||
* @return true if munger has to check that its exceptions can be throwned based on the shadow | |||
*/ | |||
public abstract boolean mustCheckExceptions(); | |||
/** | |||
* Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the | |||
* binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the | |||
* resolvedDeclaringAspect. | |||
*/ | |||
public ISourceLocation getBinarySourceLocation(ISourceLocation sl) { | |||
if (sl == null) | |||
return null; | |||
String sourceFileName = null; | |||
if (getDeclaringType() instanceof ReferenceType) { | |||
String s = ((ReferenceType) getDeclaringType()).getDelegate().getSourcefilename(); | |||
int i = s.lastIndexOf('/'); | |||
if (i != -1) { | |||
sourceFileName = s.substring(i + 1); | |||
} else { | |||
sourceFileName = s; | |||
} | |||
} | |||
ISourceLocation sLoc = new SourceLocation(getBinaryFile(), sl.getLine(), sl.getEndLine(), | |||
((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourceFileName); | |||
return sLoc; | |||
} | |||
/** | |||
* Returns the File with pathname to the class file, for example either C:\temp | |||
* \ajcSandbox\workspace\ajcTest16957.tmp\simple.jar!pkg\BinaryAspect.class if the class file is in a jar file, or | |||
* C:\temp\ajcSandbox\workspace\ajcTest16957.tmp!pkg\BinaryAspect.class if the class file is in a directory | |||
*/ | |||
private File getBinaryFile() { | |||
if (binaryFile == null) { | |||
String s = getDeclaringType().getBinaryPath(); | |||
File f = getDeclaringType().getSourceLocation().getSourceFile(); | |||
int i = f.getPath().lastIndexOf('.'); | |||
String path = f.getPath().substring(0, i) + ".class"; | |||
binaryFile = new File(s + "!" + path); | |||
} | |||
return binaryFile; | |||
} | |||
/** | |||
* Returns whether or not this shadow munger came from a binary aspect - keep a record of whether or not we've checked if we're | |||
* binary otherwise we keep caluclating the same thing many times | |||
*/ | |||
public boolean isBinary() { | |||
if (!checkedIsBinary) { | |||
ResolvedType rt = getDeclaringType(); | |||
if (rt != null) { | |||
isBinary = ((rt.getBinaryPath() == null) ? false : true); | |||
} | |||
checkedIsBinary = true; | |||
} | |||
return isBinary; | |||
} | |||
private boolean isBinary; | |||
private boolean checkedIsBinary; | |||
} |
@@ -0,0 +1,246 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - refactored out of MemberImpl | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.reflect.Modifier; | |||
public class SignatureUtils { | |||
public static String getSignatureString(Member m, World world) { | |||
MemberKind kind = m.getKind(); | |||
if (kind == Member.METHOD) { | |||
return getMethodSignatureString(m,world); | |||
} else if (kind == Member.CONSTRUCTOR) { | |||
return getConstructorSignatureString(m,world); | |||
} else if (kind == Member.FIELD) { | |||
return getFieldSignatureString(m,world); | |||
} else if (kind == Member.HANDLER) { | |||
return getHandlerSignatureString(m,world); | |||
} else if (kind == Member.STATIC_INITIALIZATION) { | |||
return getStaticInitializationSignatureString(m,world); | |||
} else if (kind == Member.ADVICE) { | |||
return getAdviceSignatureString(m,world); | |||
} else if (kind == Member.MONITORENTER || kind == Member.MONITOREXIT) { | |||
return getMonitorSignatureString(m,world); | |||
} else { | |||
throw new BCException("Do not know the signature string for MemberKind "+kind); | |||
} | |||
} | |||
public static String getSignatureMakerName(Member m) { | |||
MemberKind kind = m.getKind(); | |||
if (kind == Member.METHOD) { | |||
return "makeMethodSig"; | |||
} else if (kind == Member.CONSTRUCTOR) { | |||
return "makeConstructorSig"; | |||
} else if (kind == Member.FIELD) { | |||
return "makeFieldSig"; | |||
} else if (kind == Member.HANDLER) { | |||
return "makeCatchClauseSig"; | |||
} else if (kind == Member.STATIC_INITIALIZATION) { | |||
return "makeInitializerSig"; | |||
} else if (kind == Member.ADVICE) { | |||
return "makeAdviceSig"; | |||
} else if (kind == Member.MONITORENTER) { | |||
return "makeLockSig"; | |||
} else if (kind == Member.MONITOREXIT) { | |||
return "makeUnlockSig"; | |||
} else { | |||
throw new BCException("Do not know the signature maker name for MemberKind "+kind); | |||
} | |||
} | |||
public static String getSignatureType(Member m) { | |||
MemberKind kind = m.getKind(); | |||
if (m.getName().equals("<clinit>") && kind!=Member.STATIC_INITIALIZATION) throw new BCException(); | |||
// if (m.getName().equals("<clinit>")) return "org.aspectj.lang.reflect.InitializerSignature"; | |||
if (kind == Member.METHOD) { | |||
return "org.aspectj.lang.reflect.MethodSignature"; | |||
} else if (kind == Member.CONSTRUCTOR) { | |||
return "org.aspectj.lang.reflect.ConstructorSignature"; | |||
} else if (kind == Member.FIELD) { | |||
return "org.aspectj.lang.reflect.FieldSignature"; | |||
} else if (kind == Member.HANDLER) { | |||
return "org.aspectj.lang.reflect.CatchClauseSignature"; | |||
} else if (kind == Member.STATIC_INITIALIZATION) { | |||
return "org.aspectj.lang.reflect.InitializerSignature"; | |||
} else if (kind == Member.ADVICE) { | |||
return "org.aspectj.lang.reflect.AdviceSignature"; | |||
} else if (kind == Member.MONITORENTER) { | |||
return "org.aspectj.lang.reflect.LockSignature"; | |||
} else if (kind == Member.MONITOREXIT) { | |||
return "org.aspectj.lang.reflect.UnlockSignature"; | |||
} else { | |||
throw new BCException("Do not know the signature type for MemberKind "+kind); | |||
} | |||
} | |||
// --- | |||
private static String getHandlerSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(0)); | |||
buf.append('-'); | |||
//buf.append(getName()); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterTypes()[0])); | |||
buf.append('-'); | |||
String pName = "<missing>"; | |||
String[] names = m.getParameterNames(world); | |||
if (names != null) pName = names[0]; | |||
buf.append(pName); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
private static String getStaticInitializationSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(m.getModifiers(world))); | |||
buf.append('-'); | |||
//buf.append(getName()); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String getAdviceSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(m.getModifiers(world))); | |||
buf.append('-'); | |||
buf.append(m.getName()); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterTypes())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterNames(world))); | |||
buf.append('-'); | |||
buf.append(makeString(m.getExceptions(world))); | |||
buf.append('-'); | |||
buf.append(makeString(m.getReturnType())); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String getMethodSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(m.getModifiers(world))); | |||
buf.append('-'); | |||
buf.append(m.getName()); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterTypes())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterNames(world))); | |||
buf.append('-'); | |||
buf.append(makeString(m.getExceptions(world))); | |||
buf.append('-'); | |||
buf.append(makeString(m.getReturnType())); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String getMonitorSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(Modifier.STATIC)); // modifiers | |||
buf.append('-'); | |||
buf.append(m.getName()); // name | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); // Declaring Type | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterTypes()[0])); // Parameter Types | |||
buf.append('-'); | |||
buf.append(""); // Parameter names | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String getConstructorSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(m.getModifiers(world))); | |||
buf.append('-'); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterTypes())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getParameterNames(world))); | |||
buf.append('-'); | |||
buf.append(makeString(m.getExceptions(world))); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String getFieldSignatureString(Member m, World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(makeString(m.getModifiers(world))); | |||
buf.append('-'); | |||
buf.append(m.getName()); | |||
buf.append('-'); | |||
buf.append(makeString(m.getDeclaringType())); | |||
buf.append('-'); | |||
buf.append(makeString(m.getReturnType())); | |||
buf.append('-'); | |||
return buf.toString(); | |||
} | |||
protected static String makeString(int i) { | |||
return Integer.toString(i, 16); | |||
} | |||
protected static String makeString(UnresolvedType t) { | |||
// this is the inverse of the odd behavior for Class.forName w/ arrays | |||
if (t.isArray()) { | |||
// this behavior matches the string used by the eclipse compiler for Foo.class literals | |||
return t.getSignature().replace('/', '.'); | |||
} else { | |||
return t.getName(); | |||
} | |||
} | |||
protected static String makeString(UnresolvedType[] types) { | |||
if (types == null) return ""; | |||
StringBuffer buf = new StringBuffer(); | |||
for (int i = 0, len=types.length; i < len; i++) { | |||
buf.append(makeString(types[i])); | |||
buf.append(':'); | |||
} | |||
return buf.toString(); | |||
} | |||
protected static String makeString(String[] names) { | |||
if (names == null) return ""; | |||
StringBuffer buf = new StringBuffer(); | |||
for (int i = 0, len=names.length; i < len; i++) { | |||
buf.append(names[i]); | |||
buf.append(':'); | |||
} | |||
return buf.toString(); | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class SimpleAnnotationValue extends AnnotationValue { | |||
public SimpleAnnotationValue(int kind) { | |||
super(kind); | |||
} | |||
public SimpleAnnotationValue(int kind, Object value) { | |||
super(kind); | |||
switch (kind) { | |||
case AnnotationValue.PRIMITIVE_BYTE: theByte = ((Byte)value).byteValue(); break; | |||
case AnnotationValue.PRIMITIVE_CHAR: theChar = ((Character)value).charValue(); break; | |||
case AnnotationValue.PRIMITIVE_INT: theInt = ((Integer)value).intValue(); break; | |||
case AnnotationValue.STRING: theString = (String)value; break; | |||
case AnnotationValue.PRIMITIVE_DOUBLE: theDouble = ((Double)value).doubleValue(); break; | |||
case AnnotationValue.PRIMITIVE_FLOAT: theFloat = ((Float)value).floatValue(); break; | |||
case AnnotationValue.PRIMITIVE_LONG: theLong = ((Long)value).longValue(); break; | |||
case AnnotationValue.PRIMITIVE_SHORT: theShort = ((Short)value).shortValue(); break; | |||
case AnnotationValue.PRIMITIVE_BOOLEAN: theBoolean = ((Boolean)value).booleanValue(); break; | |||
default: | |||
throw new BCException("Not implemented for this kind: "+whatKindIsThis(kind)); | |||
} | |||
} | |||
private byte theByte; | |||
private char theChar; | |||
private int theInt; | |||
private String theString; | |||
private double theDouble; | |||
private float theFloat; | |||
private long theLong; | |||
private short theShort; | |||
private boolean theBoolean; | |||
public void setValueString(String s) { theString = s; } | |||
public void setValueByte(byte b) { theByte = b; } | |||
public void setValueChar(char c) { theChar = c; } | |||
public void setValueInt(int i) { theInt = i; } | |||
public String stringify() { | |||
switch (valueKind) { | |||
case 'B': // byte | |||
return Byte.toString(theByte); | |||
case 'C': // char | |||
return new Character(theChar).toString(); | |||
case 'D': // double | |||
return Double.toString(theDouble); | |||
case 'F': // float | |||
return Float.toString(theFloat); | |||
case 'I': // int | |||
return Integer.toString(theInt); | |||
case 'J': // long | |||
return Long.toString(theLong); | |||
case 'S': // short | |||
return Short.toString(theShort); | |||
case 'Z': // boolean | |||
return new Boolean(theBoolean).toString(); | |||
case 's': // String | |||
return theString; | |||
default: throw new BCException("Do not understand this kind: "+valueKind); | |||
} | |||
} | |||
public String toString() { | |||
return stringify(); | |||
} | |||
} |
@@ -0,0 +1,109 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.SourceLocation; | |||
public class SourceContextImpl implements ISourceContext { | |||
// private AbstractReferenceTypeDelegate delegate; | |||
private int[] lineBreaks; | |||
String sfname; | |||
public SourceContextImpl(AbstractReferenceTypeDelegate delegate) { | |||
// this.delegate = delegate; | |||
sfname = delegate.getSourcefilename(); | |||
} | |||
public void configureFromAttribute(String name,int []linebreaks) { | |||
// this.delegate.setSourcefilename(name); | |||
sfname = name; | |||
this.lineBreaks = linebreaks; | |||
} | |||
public void setSourceFileName(String name) { | |||
sfname = name; | |||
} | |||
private File getSourceFile() { | |||
return new File(sfname); | |||
// return new File(delegate.getSourcefilename()); | |||
} | |||
public void tidy() {} | |||
public int getOffset() { return 0; } | |||
/* | |||
// AMC - a temporary "fudge" to give as much information as possible about the identity of the | |||
// source file this source location points to. | |||
String internalClassName = getEnclosingClass().getInternalClassName(); | |||
String fileName = getEnclosingClass().getFileName(); | |||
String extension = fileName.substring( fileName.lastIndexOf("."), fileName.length()); | |||
String filePrefix = fileName.substring( 0, fileName.lastIndexOf(".")); | |||
// internal class name is e.g. figures/Point, we don't know whether the file was | |||
// .aj or .java so we put it together with the file extension of the enclosing class | |||
// BUT... sometimes internalClassName is a different class (an aspect), so we only use it if it | |||
// matches the file name. | |||
String mostAccurateFileNameGuess; | |||
if ( internalClassName.endsWith(filePrefix)) { | |||
mostAccurateFileNameGuess = internalClassName + extension; | |||
} else { | |||
mostAccurateFileNameGuess = fileName; | |||
} | |||
return new SourceLocation(new File(mostAccurateFileNameGuess), getSourceLine()); | |||
*/ | |||
public ISourceLocation makeSourceLocation(IHasPosition position) { | |||
if (lineBreaks != null) { | |||
int line = Arrays.binarySearch(lineBreaks, position.getStart()); | |||
if (line < 0) line = -line; | |||
return new SourceLocation(getSourceFile(), line); //??? have more info | |||
} else { | |||
return new SourceLocation(getSourceFile(), 0); | |||
} | |||
} | |||
public ISourceLocation makeSourceLocation(int line, int offset) { | |||
if (line < 0) line = 0; | |||
SourceLocation sl = new SourceLocation(getSourceFile(), line); | |||
if (offset > 0) { | |||
sl.setOffset(offset); | |||
} else { | |||
if (lineBreaks != null) { | |||
int likelyOffset = 0; | |||
if (line > 0 && line < lineBreaks.length) { | |||
//1st char of given line is next char after previous end of line | |||
likelyOffset = lineBreaks[line-1] + 1; | |||
} | |||
sl.setOffset(likelyOffset); | |||
} | |||
} | |||
return sl; | |||
} | |||
public final static ISourceContext UNKNOWN_SOURCE_CONTEXT = new ISourceContext() { | |||
public ISourceLocation makeSourceLocation(IHasPosition position) {return null;} | |||
public ISourceLocation makeSourceLocation(int line, int offset) {return null;} | |||
public int getOffset() {return 0;} | |||
public void tidy() {} | |||
}; | |||
} |
@@ -0,0 +1,153 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* This type represents the weavers abstraction of an annotation - it is not tied to any underlying BCI toolkit. The weaver actualy | |||
* handles these through AnnotationX wrapper objects - until we start transforming the BCEL annotations into this form (expensive) | |||
* or offer a clever visitor mechanism over the BCEL annotation stuff that builds these annotation types directly. | |||
* | |||
* @author AndyClement | |||
*/ | |||
public class StandardAnnotation extends AbstractAnnotationAJ { | |||
private final boolean isRuntimeVisible; | |||
private List /* of AnnotationNVPair */nvPairs = null; | |||
public StandardAnnotation(ResolvedType type, boolean isRuntimeVisible) { | |||
super(type); | |||
this.isRuntimeVisible = isRuntimeVisible; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean isRuntimeVisible() { | |||
return isRuntimeVisible; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("@").append(type.getClassName()); | |||
if (hasNameValuePairs()) { | |||
sb.append("("); | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.stringify()); | |||
} | |||
sb.append(")"); | |||
} | |||
return sb.toString(); | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("ANNOTATION [" + getTypeSignature() + "] [" + (isRuntimeVisible ? "runtimeVisible" : "runtimeInvisible") + "] ["); | |||
if (nvPairs != null) { | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.toString()); | |||
if (iter.hasNext()) | |||
sb.append(","); | |||
} | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNamedValue(String n) { | |||
if (nvPairs == null) | |||
return false; | |||
for (int i = 0; i < nvPairs.size(); i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i); | |||
if (pair.getName().equals(n)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNameValuePair(String n, String v) { | |||
if (nvPairs == null) | |||
return false; | |||
for (int i = 0; i < nvPairs.size(); i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i); | |||
if (pair.getName().equals(n)) { | |||
if (pair.getValue().stringify().equals(v)) | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public Set /* <String> */getTargets() { | |||
if (!type.equals(UnresolvedType.AT_TARGET)) { | |||
return Collections.EMPTY_SET; | |||
} | |||
AnnotationNameValuePair nvp = (AnnotationNameValuePair) nvPairs.get(0); | |||
ArrayAnnotationValue aav = (ArrayAnnotationValue) nvp.getValue(); | |||
AnnotationValue[] avs = aav.getValues(); | |||
Set targets = new HashSet(); | |||
for (int i = 0; i < avs.length; i++) { | |||
AnnotationValue value = avs[i]; | |||
targets.add(value.stringify()); | |||
} | |||
return targets; | |||
} | |||
public List getNameValuePairs() { | |||
return nvPairs; | |||
} | |||
public boolean hasNameValuePairs() { | |||
return nvPairs != null && nvPairs.size() != 0; | |||
} | |||
public void addNameValuePair(AnnotationNameValuePair pair) { | |||
if (nvPairs == null) { | |||
nvPairs = new ArrayList(); | |||
} | |||
nvPairs.add(pair); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public String getStringFormOfValue(String name) { | |||
if (hasNameValuePairs()) { | |||
for (Iterator iterator = nvPairs.iterator(); iterator.hasNext();) { | |||
AnnotationNameValuePair nvPair = (AnnotationNameValuePair) iterator.next(); | |||
if (nvPair.getName().equals(name)) { | |||
return nvPair.getValue().stringify(); | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
public class StaticJoinPointFactory { | |||
// int usedKeys; | |||
// | |||
// List/*String*/ strings = new ArrayList(); | |||
// Map/*String,Integer*/ keysForStrings = new HashMap(); | |||
// | |||
// public StaticJoinPointFactory() { | |||
// super(); | |||
// } | |||
// | |||
// static char[] encoding = new char[] { | |||
// '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',//10 | |||
// 'a', 'b', 'z', //36 | |||
// 'A', 'B', 'Z', //62 | |||
// '%', '$', //64 | |||
// }; | |||
// | |||
// static int TWO_WORDS = 64*64-1; | |||
// static int WORD_MASK = 63; | |||
// | |||
// public void write(String s, StringBuffer result) { | |||
// int i = getIndex(s); | |||
// encode(i, result); | |||
// } | |||
// | |||
// void encode(int i, StringBuffer result) { | |||
// if (i > TWO_WORDS) { | |||
// throw new RuntimeException("unimplemented"); | |||
// } else { | |||
// result.append( encoding[(i >> 6) & WORD_MASK] ); | |||
// result.append( encoding[i & WORD_MASK] ); | |||
// } | |||
// } | |||
// | |||
// public String read(StringReader reader) { | |||
// int i = reader.read(); | |||
// | |||
// } | |||
} |
@@ -0,0 +1,35 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.Map; | |||
/** | |||
* Some methods need a temporary type munger (because ConcreteTypeMunger is abstract - dont ask...). | |||
* | |||
* TODO ought to remove the need for this or at least sort out the two methods that are in it, they look wierd... | |||
* | |||
* @author AndyClement | |||
*/ | |||
public class TemporaryTypeMunger extends ConcreteTypeMunger { | |||
public TemporaryTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) { | |||
super(munger, aspectType); | |||
} | |||
public ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world) { | |||
throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger"); | |||
} | |||
public ConcreteTypeMunger parameterizedFor(ResolvedType targetType) { | |||
throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger"); | |||
} | |||
} |
@@ -0,0 +1,293 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @author colyer | |||
* | |||
*/ | |||
public class TypeFactory { | |||
/** | |||
* Create a parameterized version of a generic type. | |||
* | |||
* @param aGenericType | |||
* @param someTypeParameters note, in the case of an inner type of a parameterized type, this parameter may legitimately be null | |||
* @param inAWorld | |||
* @return | |||
*/ | |||
public static ReferenceType createParameterizedType(ResolvedType aBaseType, UnresolvedType[] someTypeParameters, World inAWorld) { | |||
ResolvedType baseType = aBaseType; | |||
if (!aBaseType.isGenericType()) { | |||
// try and find the generic type... | |||
if (someTypeParameters != null && someTypeParameters.length > 0) { | |||
if (!aBaseType.isRawType()) | |||
throw new IllegalStateException("Expecting raw type, not: " + aBaseType); | |||
baseType = baseType.getGenericType(); | |||
if (baseType == null) | |||
throw new IllegalStateException("Raw type does not have generic type set"); | |||
} // else if someTypeParameters is null, then the base type is allowed to be non-generic, it's an inner | |||
} | |||
ResolvedType[] resolvedParameters = inAWorld.resolve(someTypeParameters); | |||
ReferenceType pType = new ReferenceType(baseType, resolvedParameters, inAWorld); | |||
// pType.setSourceContext(aBaseType.getSourceContext()); | |||
return (ReferenceType) pType.resolve(inAWorld); | |||
} | |||
/** | |||
* Create an *unresolved* parameterized version of a generic type. | |||
*/ | |||
public static UnresolvedType createUnresolvedParameterizedType(String sig, String erasuresig, UnresolvedType[] arguments) { | |||
return new UnresolvedType(sig, erasuresig, arguments); | |||
} | |||
// public static ReferenceType createRawType( | |||
// ResolvedType aBaseType, | |||
// World inAWorld | |||
// ) { | |||
// if (aBaseType.isRawType()) return (ReferenceType) aBaseType; | |||
// if (!aBaseType.isGenericType()) { | |||
// if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting generic type"); | |||
// } | |||
// ReferenceType rType = new ReferenceType(aBaseType,inAWorld); | |||
// //rType.setSourceContext(aBaseType.getSourceContext()); | |||
// return (ReferenceType) rType.resolve(inAWorld); | |||
// } | |||
/** | |||
* Creates a sensible unresolvedtype from some signature, for example: signature = LIGuard<TT;>; bound = toString=IGuard<T> | |||
* sig=PIGuard<TT;>; sigErasure=LIGuard; kind=parameterized | |||
*/ | |||
private static UnresolvedType convertSigToType(String aSignature) { | |||
UnresolvedType bound = null; | |||
int startOfParams = aSignature.indexOf('<'); | |||
if (startOfParams == -1) { | |||
bound = UnresolvedType.forSignature(aSignature); | |||
} else { | |||
int endOfParams = aSignature.lastIndexOf('>'); | |||
String signatureErasure = "L" + aSignature.substring(1, startOfParams) + ";"; | |||
UnresolvedType[] typeParams = createTypeParams(aSignature.substring(startOfParams + 1, endOfParams)); | |||
bound = new UnresolvedType("P" + aSignature.substring(1), signatureErasure, typeParams); | |||
} | |||
return bound; | |||
} | |||
/** | |||
* Used by UnresolvedType.read, creates a type from a full signature. | |||
* | |||
* @param signature | |||
* @return | |||
*/ | |||
public static UnresolvedType createTypeFromSignature(String signature) { | |||
if (signature.equals(ResolvedType.MISSING_NAME)) | |||
return ResolvedType.MISSING; | |||
char firstChar = signature.charAt(0); | |||
if (firstChar == 'P') { | |||
// parameterized type, calculate signature erasure and type parameters | |||
// (see pr122458) It is possible for a parameterized type to have *no* type parameters visible in its signature. | |||
// This happens for an inner type of a parameterized type which simply inherits the type parameters | |||
// of its parent. In this case it is parameterized but theres no < in the signature. | |||
int startOfParams = signature.indexOf('<'); | |||
if (startOfParams == -1) { | |||
// Should be an inner type of a parameterized type - could assert there is a '$' in the signature.... | |||
String signatureErasure = "L" + signature.substring(1); | |||
UnresolvedType[] typeParams = new UnresolvedType[0]; | |||
return new UnresolvedType(signature, signatureErasure, typeParams); | |||
} else { | |||
int endOfParams = locateMatchingEndBracket(signature, startOfParams);// signature.lastIndexOf('>'); | |||
StringBuffer erasureSig = new StringBuffer(signature); | |||
while (startOfParams != -1) { | |||
erasureSig.delete(startOfParams, endOfParams + 1); | |||
startOfParams = locateFirstBracket(erasureSig); | |||
if (startOfParams != -1) | |||
endOfParams = locateMatchingEndBracket(erasureSig, startOfParams); | |||
} | |||
String signatureErasure = "L" + erasureSig.toString().substring(1); | |||
// the type parameters of interest are only those that apply to the 'last type' in the signature | |||
// if the signature is 'PMyInterface<String>$MyOtherType;' then there are none... | |||
String lastType = null; | |||
int nestedTypePosition = signature.indexOf("$", endOfParams); // don't look for $ INSIDE the parameters | |||
if (nestedTypePosition != -1) | |||
lastType = signature.substring(nestedTypePosition + 1); | |||
else | |||
lastType = new String(signature); | |||
startOfParams = lastType.indexOf("<"); | |||
endOfParams = locateMatchingEndBracket(lastType, startOfParams); | |||
UnresolvedType[] typeParams = UnresolvedType.NONE; | |||
if (startOfParams != -1) { | |||
typeParams = createTypeParams(lastType.substring(startOfParams + 1, endOfParams)); | |||
} | |||
return new UnresolvedType(signature, signatureErasure, typeParams); | |||
} | |||
// can't replace above with convertSigToType - leads to stackoverflow | |||
} else if (signature.equals("?") || signature.equals("*")) { | |||
return WildcardedUnresolvedType.QUESTIONMARK; | |||
} else if (firstChar == '+') { | |||
// ? extends ... | |||
UnresolvedType upperBound = convertSigToType(signature.substring(1)); | |||
WildcardedUnresolvedType wildcardedUT = new WildcardedUnresolvedType(signature, upperBound, null); | |||
return wildcardedUT; | |||
} else if (firstChar == '-') { | |||
// ? super ... | |||
UnresolvedType lowerBound = convertSigToType(signature.substring(1)); | |||
WildcardedUnresolvedType wildcardedUT = new WildcardedUnresolvedType(signature, null, lowerBound); | |||
return wildcardedUT; | |||
} else if (firstChar == 'T') { | |||
String typeVariableName = signature.substring(1); | |||
if (typeVariableName.endsWith(";")) { | |||
typeVariableName = typeVariableName.substring(0, typeVariableName.length() - 1); | |||
} | |||
return new UnresolvedTypeVariableReferenceType(new TypeVariable(typeVariableName)); | |||
} else if (firstChar == '[') { | |||
int dims = 0; | |||
while (signature.charAt(dims) == '[') | |||
dims++; | |||
UnresolvedType componentType = createTypeFromSignature(signature.substring(dims)); | |||
return new UnresolvedType(signature, signature.substring(0, dims) + componentType.getErasureSignature()); | |||
} else if (signature.length() == 1) { // could be a primitive | |||
switch (firstChar) { | |||
case 'V': | |||
return ResolvedType.VOID; | |||
case 'Z': | |||
return ResolvedType.BOOLEAN; | |||
case 'B': | |||
return ResolvedType.BYTE; | |||
case 'C': | |||
return ResolvedType.CHAR; | |||
case 'D': | |||
return ResolvedType.DOUBLE; | |||
case 'F': | |||
return ResolvedType.FLOAT; | |||
case 'I': | |||
return ResolvedType.INT; | |||
case 'J': | |||
return ResolvedType.LONG; | |||
case 'S': | |||
return ResolvedType.SHORT; | |||
} | |||
} | |||
return new UnresolvedType(signature); | |||
} | |||
private static int locateMatchingEndBracket(String signature, int startOfParams) { | |||
if (startOfParams == -1) | |||
return -1; | |||
int count = 1; | |||
int idx = startOfParams; | |||
while (count > 0 && idx < signature.length()) { | |||
idx++; | |||
if (signature.charAt(idx) == '<') | |||
count++; | |||
if (signature.charAt(idx) == '>') | |||
count--; | |||
} | |||
return idx; | |||
} | |||
private static int locateMatchingEndBracket(StringBuffer signature, int startOfParams) { | |||
if (startOfParams == -1) | |||
return -1; | |||
int count = 1; | |||
int idx = startOfParams; | |||
while (count > 0 && idx < signature.length()) { | |||
idx++; | |||
if (signature.charAt(idx) == '<') | |||
count++; | |||
if (signature.charAt(idx) == '>') | |||
count--; | |||
} | |||
return idx; | |||
} | |||
private static int locateFirstBracket(StringBuffer signature) { | |||
int idx = 0; | |||
while (idx < signature.length()) { | |||
if (signature.charAt(idx) == '<') | |||
return idx; | |||
idx++; | |||
} | |||
return -1; | |||
} | |||
private static UnresolvedType[] createTypeParams(String typeParameterSpecification) { | |||
String remainingToProcess = typeParameterSpecification; | |||
List types = new ArrayList(); | |||
while (!remainingToProcess.equals("")) { | |||
int endOfSig = 0; | |||
int anglies = 0; | |||
boolean sigFound = false; // OPTIMIZE can this be done better? | |||
for (endOfSig = 0; (endOfSig < remainingToProcess.length()) && !sigFound; endOfSig++) { | |||
char thisChar = remainingToProcess.charAt(endOfSig); | |||
switch (thisChar) { | |||
case '<': | |||
anglies++; | |||
break; | |||
case '>': | |||
anglies--; | |||
break; | |||
case '[': | |||
if (anglies == 0) { | |||
// the next char might be a [ or a primitive type ref (BCDFIJSZ) | |||
int nextChar = endOfSig + 1; | |||
while (remainingToProcess.charAt(nextChar) == '[') { | |||
nextChar++; | |||
} | |||
if ("BCDFIJSZ".indexOf(remainingToProcess.charAt(nextChar)) != -1) { | |||
// it is something like [I or [[S | |||
sigFound = true; | |||
endOfSig = nextChar; | |||
break; | |||
} | |||
} | |||
break; | |||
case ';': | |||
if (anglies == 0) { | |||
sigFound = true; | |||
break; | |||
} | |||
} | |||
} | |||
types.add(createTypeFromSignature(remainingToProcess.substring(0, endOfSig))); | |||
remainingToProcess = remainingToProcess.substring(endOfSig); | |||
} | |||
UnresolvedType[] typeParams = new UnresolvedType[types.size()]; | |||
types.toArray(typeParams); | |||
return typeParams; | |||
} | |||
// OPTIMIZE improve all this signature processing stuff, use char arrays, etc | |||
/** | |||
* Create a signature then delegate to the other factory method. Same input/output: baseTypeSignature="LSomeType;" arguments[0]= | |||
* something with sig "Pcom/Foo<Ljava/lang/String;>;" signature created = "PSomeType<Pcom/Foo<Ljava/lang/String;>;>;" | |||
*/ | |||
public static UnresolvedType createUnresolvedParameterizedType(String baseTypeSignature, UnresolvedType[] arguments) { | |||
StringBuffer parameterizedSig = new StringBuffer(); | |||
parameterizedSig.append(ResolvedType.PARAMETERIZED_TYPE_IDENTIFIER); | |||
parameterizedSig.append(baseTypeSignature.substring(1, baseTypeSignature.length() - 1)); | |||
if (arguments.length > 0) { | |||
parameterizedSig.append("<"); | |||
for (int i = 0; i < arguments.length; i++) { | |||
parameterizedSig.append(arguments[i].getSignature()); | |||
} | |||
parameterizedSig.append(">"); | |||
} | |||
parameterizedSig.append(";"); | |||
return createUnresolvedParameterizedType(parameterizedSig.toString(), baseTypeSignature, arguments); | |||
} | |||
} |
@@ -0,0 +1,372 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
/** | |||
* Represents a type variable with bounds | |||
*/ | |||
public class TypeVariable { | |||
public static final TypeVariable[] NONE = new TypeVariable[0]; | |||
/** | |||
* whether or not the bounds of this type variable have been | |||
* resolved | |||
*/ | |||
private boolean isResolved = false; | |||
private boolean beingResolved = false; | |||
/** | |||
* the name of the type variable as recorded in the generic signature | |||
*/ | |||
private String name; | |||
private int rank; | |||
// It would be nice to push this field onto the TypeVariableDeclaringElement | |||
// interface (a getKind()) but at the moment we don't always guarantee | |||
// to set the declaring element (eclipse seems to utilise the knowledge of | |||
// what declared the type variable, but we dont yet...) | |||
/** | |||
* What kind of element declared this type variable? | |||
*/ | |||
private int declaringElementKind = UNKNOWN; | |||
public static final int UNKNOWN = -1; | |||
public static final int METHOD = 1; | |||
public static final int TYPE = 2; | |||
private TypeVariableDeclaringElement declaringElement; | |||
/** | |||
* the upper bound of the type variable (default to Object). | |||
* From the extends clause, eg. T extends Number. | |||
*/ | |||
private UnresolvedType upperBound = UnresolvedType.OBJECT; | |||
/** | |||
* any additional upper (interface) bounds. | |||
* from the extends clause, e.g. T extends Number & Comparable | |||
*/ | |||
private UnresolvedType[] additionalInterfaceBounds = new UnresolvedType[0]; | |||
/** | |||
* any lower bound. | |||
* from the super clause, eg T super Foo | |||
*/ | |||
private UnresolvedType lowerBound = null; | |||
public TypeVariable(String aName) { | |||
this.name = aName; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound) { | |||
this(aName); | |||
this.upperBound = anUpperBound; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound, | |||
UnresolvedType[] someAdditionalInterfaceBounds) { | |||
this(aName,anUpperBound); | |||
this.additionalInterfaceBounds = someAdditionalInterfaceBounds; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound, | |||
UnresolvedType[] someAdditionalInterfaceBounds, UnresolvedType aLowerBound) { | |||
this(aName,anUpperBound,someAdditionalInterfaceBounds); | |||
this.lowerBound = aLowerBound; | |||
} | |||
// First bound is the first 'real' bound, this can be an interface if | |||
// no class bound was specified (it will default to object) | |||
public UnresolvedType getFirstBound() { | |||
if (upperBound.equals(UnresolvedType.OBJECT) && additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) { | |||
return additionalInterfaceBounds[0]; | |||
} | |||
return upperBound; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType[] getAdditionalInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
/** | |||
* resolve all the bounds of this type variable | |||
*/ | |||
public TypeVariable resolve(World inSomeWorld) { | |||
if (beingResolved) { return this; } // avoid spiral of death | |||
beingResolved = true; | |||
if (isResolved) return this; | |||
TypeVariable resolvedTVar = null; | |||
if (declaringElement != null) { | |||
// resolve by finding the real type var that we refer to... | |||
if (declaringElementKind == TYPE) { | |||
UnresolvedType declaring = (UnresolvedType) declaringElement; | |||
ReferenceType rd = (ReferenceType) declaring.resolve(inSomeWorld); | |||
TypeVariable[] tVars = rd.getTypeVariables(); | |||
for (int i = 0; i < tVars.length; i++) { | |||
if (tVars[i].getName().equals(getName())) { | |||
resolvedTVar = tVars[i]; | |||
break; | |||
} | |||
} | |||
} else { | |||
// look for type variable on method... | |||
ResolvedMember declaring = (ResolvedMember) declaringElement; | |||
TypeVariable[] tvrts = declaring.getTypeVariables(); | |||
for (int i = 0; i < tvrts.length; i++) { | |||
if (tvrts[i].getName().equals(getName())) resolvedTVar = tvrts[i]; | |||
// if (tvrts[i].isTypeVariableReference()) { | |||
// TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld); | |||
// TypeVariable tv = tvrt.getTypeVariable(); | |||
// if (tv.getName().equals(getName())) resolvedTVar = tv; | |||
// } | |||
} | |||
} | |||
if (resolvedTVar == null) { | |||
// well, this is bad... we didn't find the type variable on the member | |||
// could be a separate compilation issue... | |||
// should issue message, this is a workaround to get us going... | |||
resolvedTVar = this; | |||
} | |||
} else { | |||
resolvedTVar = this; | |||
} | |||
upperBound = resolvedTVar.upperBound; | |||
lowerBound = resolvedTVar.lowerBound; | |||
additionalInterfaceBounds = resolvedTVar.additionalInterfaceBounds; | |||
upperBound = upperBound.resolve(inSomeWorld); | |||
if (lowerBound != null) lowerBound = lowerBound.resolve(inSomeWorld); | |||
if (additionalInterfaceBounds!=null) { | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld); | |||
} | |||
} | |||
isResolved = true; | |||
beingResolved = false; | |||
return this; | |||
} | |||
/** | |||
* answer true if the given type satisfies all of the bound constraints of this | |||
* type variable. | |||
* If type variable has not been resolved then throws IllegalStateException | |||
*/ | |||
public boolean canBeBoundTo(ResolvedType aCandidateType) { | |||
if (!isResolved) throw new IllegalStateException("Can't answer binding questions prior to resolving"); | |||
// wildcard can accept any binding | |||
if (aCandidateType.isGenericWildcard()) { // AMC - need a more robust test! | |||
return true; | |||
} | |||
// otherwise can be bound iff... | |||
// aCandidateType is a subtype of upperBound | |||
if (!isASubtypeOf(upperBound,aCandidateType)) { | |||
return false; | |||
} | |||
// aCandidateType is a subtype of all additionalInterfaceBounds | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
if (!isASubtypeOf(additionalInterfaceBounds[i], aCandidateType)) { | |||
return false; | |||
} | |||
} | |||
// lowerBound is a subtype of aCandidateType | |||
if ((lowerBound != null) && (!isASubtypeOf(aCandidateType,lowerBound))) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
private boolean isASubtypeOf(UnresolvedType candidateSuperType, UnresolvedType candidateSubType) { | |||
ResolvedType superType = (ResolvedType) candidateSuperType; | |||
ResolvedType subType = (ResolvedType) candidateSubType; | |||
return superType.isAssignableFrom(subType); | |||
} | |||
// only used when resolving | |||
public void setUpperBound(UnresolvedType aTypeX) { | |||
this.upperBound = aTypeX; | |||
} | |||
// only used when resolving | |||
public void setLowerBound(UnresolvedType aTypeX) { | |||
this.lowerBound = aTypeX; | |||
} | |||
// only used when resolving | |||
public void setAdditionalInterfaceBounds(UnresolvedType[] someTypeXs) { | |||
this.additionalInterfaceBounds = someTypeXs; | |||
} | |||
public String toDebugString() { | |||
return getDisplayName(); | |||
} | |||
public String getDisplayName() { | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append(name); | |||
if (!getFirstBound().getName().equals("java.lang.Object")) { | |||
ret.append(" extends "); | |||
ret.append(getFirstBound().getName()); | |||
if (additionalInterfaceBounds != null) { | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
if (!getFirstBound().equals(additionalInterfaceBounds[i])) { | |||
ret.append(" & "); | |||
ret.append(additionalInterfaceBounds[i].getName()); | |||
} | |||
} | |||
} | |||
} | |||
if (lowerBound != null) { | |||
ret.append(" super "); | |||
ret.append(lowerBound.getName()); | |||
} | |||
return ret.toString(); | |||
} | |||
// good enough approximation | |||
public String toString() { | |||
return "TypeVar " + getDisplayName(); | |||
} | |||
/** | |||
* Return complete signature, e.g. "T extends Number" would return "T:Ljava/lang/Number;" | |||
* note: MAY INCLUDE P types if bounds are parameterized types | |||
*/ | |||
public String getSignature() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(name); | |||
sb.append(":"); | |||
sb.append(upperBound.getSignature()); | |||
if (additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) { | |||
sb.append(":"); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
UnresolvedType iBound = additionalInterfaceBounds[i]; | |||
sb.append(iBound.getSignature()); | |||
} | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* @return signature for inclusion in an attribute, there must be no 'P' in it signatures | |||
*/ | |||
public String getSignatureForAttribute() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(name); | |||
sb.append(":"); | |||
sb.append(((ResolvedType)upperBound).getSignatureForAttribute()); | |||
if (additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) { | |||
sb.append(":"); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
ResolvedType iBound = (ResolvedType)additionalInterfaceBounds[i]; | |||
sb.append(iBound.getSignatureForAttribute()); | |||
} | |||
} | |||
return sb.toString(); | |||
} | |||
public void setRank(int rank) { | |||
this.rank=rank; | |||
} | |||
public int getRank() { | |||
return rank; | |||
} | |||
public void setDeclaringElement(TypeVariableDeclaringElement element) { | |||
this.declaringElement = element; | |||
if (element instanceof UnresolvedType) { | |||
this.declaringElementKind = TYPE; | |||
} else { | |||
this.declaringElementKind = METHOD; | |||
} | |||
} | |||
public TypeVariableDeclaringElement getDeclaringElement() { | |||
return declaringElement; | |||
} | |||
public void setDeclaringElementKind(int kind) { | |||
this.declaringElementKind = kind; | |||
} | |||
public int getDeclaringElementKind() { | |||
// if (declaringElementKind==UNKNOWN) throw new RuntimeException("Dont know declarer of this tvar : "+this); | |||
return declaringElementKind; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
// name, upperbound, additionalInterfaceBounds, lowerbound | |||
s.writeUTF(name); | |||
upperBound.write(s); | |||
if (additionalInterfaceBounds==null || additionalInterfaceBounds.length==0) { | |||
s.writeInt(0); | |||
} else { | |||
s.writeInt(additionalInterfaceBounds.length); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
UnresolvedType ibound = additionalInterfaceBounds[i]; | |||
ibound.write(s); | |||
} | |||
} | |||
} | |||
public static TypeVariable read(VersionedDataInputStream s) throws IOException { | |||
//if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { | |||
String name = s.readUTF(); | |||
UnresolvedType ubound = UnresolvedType.read(s); | |||
int iboundcount = s.readInt(); | |||
UnresolvedType[] ibounds = UnresolvedType.NONE; | |||
if (iboundcount>0) { | |||
ibounds = new UnresolvedType[iboundcount]; | |||
for (int i=0; i<iboundcount; i++) { | |||
ibounds[i] = UnresolvedType.read(s); | |||
} | |||
} | |||
TypeVariable newVariable = new TypeVariable(name,ubound,ibounds); | |||
return newVariable; | |||
} | |||
public String getGenericSignature() { | |||
return "T"+name+";"; | |||
// return "T"+getSignature(); | |||
} | |||
public String getErasureSignature() { | |||
return getFirstBound().getErasureSignature(); | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
/* ******************************************************************* | |||
* 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: | |||
* Andy Clement Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Tag interface - methods and types can be declaring elements for | |||
* type variables. See the TypeVariable class which holds onto | |||
* the declaring element | |||
*/ | |||
public interface TypeVariableDeclaringElement { | |||
public TypeVariable getTypeVariableNamed(String name); | |||
} |
@@ -0,0 +1,22 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Implemented by Types that represent references to type variables | |||
* | |||
*/ | |||
public interface TypeVariableReference { | |||
TypeVariable getTypeVariable(); | |||
} |
@@ -0,0 +1,146 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
/** | |||
* Represents a type variable in a type or generic method declaration | |||
*/ | |||
public class TypeVariableReferenceType extends BoundedReferenceType implements TypeVariableReference { | |||
private TypeVariable typeVariable; | |||
private boolean resolvedIfBounds = false; | |||
// If 'fixedUp' then the type variable in here is a reference to the real one that may | |||
// exist either on a member or a type. Not fixedUp means that we unpacked a generic | |||
// signature and weren't able to fix it up during resolution (didn't quite know enough | |||
// at the right time). Wonder if we can fix it up late? | |||
boolean fixedUp = false; | |||
public TypeVariableReferenceType( | |||
TypeVariable aTypeVariable, | |||
World aWorld) { | |||
super( | |||
aTypeVariable.getGenericSignature(), | |||
aTypeVariable.getErasureSignature(), | |||
aWorld); | |||
this.typeVariable = aTypeVariable; | |||
this.isExtends = false; | |||
this.isSuper = false; | |||
} | |||
public ReferenceTypeDelegate getDelegate() { | |||
if (delegate==null) | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)typeVariable.getFirstBound())); | |||
return delegate; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
if (typeVariable==null) return super.getUpperBound(); | |||
return typeVariable.getUpperBound(); | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return typeVariable.getLowerBound(); | |||
} | |||
private void setAdditionalInterfaceBoundsFromTypeVar() { | |||
if (typeVariable.getAdditionalInterfaceBounds() == null) { | |||
return; | |||
} else { | |||
UnresolvedType [] ifBounds = typeVariable.getAdditionalInterfaceBounds(); | |||
additionalInterfaceBounds = new ReferenceType[ifBounds.length]; | |||
for (int i = 0; i < ifBounds.length; i++) { | |||
additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i].resolve(getWorld()); | |||
} | |||
} | |||
} | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
UnresolvedType ut = (UnresolvedType) typeBindings.get(getName()); | |||
if (ut!=null) return world.resolve(ut); | |||
return this; | |||
} | |||
public ReferenceType[] getAdditionalBounds() { | |||
if (!resolvedIfBounds) { | |||
setAdditionalInterfaceBoundsFromTypeVar(); | |||
resolvedIfBounds = true; | |||
} | |||
return super.getAdditionalBounds(); | |||
} | |||
public TypeVariable getTypeVariable() { | |||
// if (!fixedUp) throw new BCException("ARGH"); // fix it up now? | |||
return typeVariable; | |||
} | |||
public boolean isTypeVariableReference() { | |||
return true; | |||
} | |||
public String toString() { | |||
return typeVariable.getName(); | |||
} | |||
public boolean isGenericWildcard() { | |||
return false; | |||
} | |||
//public ResolvedType resolve(World world) { | |||
// return super.resolve(world); | |||
//} | |||
public boolean isAnnotation() { | |||
World world = ((ReferenceType)getUpperBound()).getWorld(); | |||
ResolvedType annotationType = ResolvedType.ANNOTATION.resolve(world); | |||
if (getUpperBound() != null && ((ReferenceType)getUpperBound()).isAnnotation()) return true; | |||
ReferenceType[] ifBounds = getAdditionalBounds(); | |||
for (int i = 0; i < ifBounds.length; i++) { | |||
if (ifBounds[i].isAnnotation()) return true; | |||
if (ifBounds[i] == annotationType) return true; // annotation itself does not have the annotation flag set in Java! | |||
} | |||
return false; | |||
} | |||
/** | |||
* return the signature for a *REFERENCE* to a type variable, which is simply: | |||
* Tname; | |||
* there is no bounds info included, that is in the signature of the type variable itself | |||
*/ | |||
public String getSignature() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("T"); | |||
sb.append(typeVariable.getName()); | |||
sb.append(";"); | |||
return sb.toString(); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
super.write(s); | |||
// TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement(); | |||
// if (tvde == null) { | |||
// s.writeInt(TypeVariable.UNKNOWN); | |||
// } else { | |||
// s.writeInt(typeVariable.getDeclaringElementKind()); | |||
// if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) { | |||
// ((UnresolvedType)tvde).write(s); | |||
// } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){ | |||
// // it's a method | |||
// ((ResolvedMember)tvde).write(s); | |||
// } | |||
// } | |||
} | |||
} |
@@ -0,0 +1,914 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002,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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* Andy Clement start of generics upgrade... | |||
* Adrian Colyer - overhaul | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
import org.aspectj.util.GenericSignature; | |||
import org.aspectj.util.GenericSignatureParser; | |||
import org.aspectj.util.GenericSignature.ClassSignature; | |||
import org.aspectj.weaver.tools.Traceable; | |||
/** | |||
* A UnresolvedType represents a type to the weaver. It has a basic signature that knows nothing about type variables, type | |||
* parameters, etc.. UnresolvedTypes are resolved in some World (a repository of types). When a UnresolvedType is resolved it turns | |||
* into a ResolvedType which may be a primitive type, or a ReferenceType. ReferenceTypes may refer to simple, generic, parameterized | |||
* or type-variable based reference types. A ReferenceType is backed by a delegate that provides information about the type based on | |||
* some repository (currently either BCEL or an EclipseSourceType, but in the future we probably need to support java.lang.reflect | |||
* based delegates too). | |||
* | |||
* Every UnresolvedType has a signature, the unique key for the type in the world. | |||
* | |||
* | |||
* TypeXs are fully aware of their complete type information (there is no erasure in the UnresolvedType world). To achieve this, the | |||
* signature of TypeXs combines the basic Java signature and the generic signature information into one complete signature. | |||
* | |||
* The format of a UnresolvedType signature is as follows: | |||
* | |||
* a simple (non-generic, non-parameterized) type has the as its signature the Java signature. e.g. Ljava/lang/String; | |||
* | |||
* a generic type has signature: TypeParamsOpt ClassSig SuperClassSig SuperIntfListOpt | |||
* | |||
* following the Generic signature grammar in the JVM spec., but with the addition of the ClassSignature (which is not in the | |||
* generic signature). In addition type variable names are replaced by a simple number which represents their declaration order in | |||
* the type declaration. | |||
* | |||
* e.g. public class Foo<T extends Number> would have signature: <1:Ljava/lang/Number>Lorg.xyz.Foo;Ljava/lang/Object; | |||
* | |||
* A parameterized type is a distinct type in the world with its own signature following the grammar: | |||
* | |||
* TypeParamsOpt ClassSig<ParamSigList>; | |||
* | |||
* but with the L for the class sig replaced by "P". For example List<String> has signature | |||
* | |||
* Pjava/util/List<Ljava/lang/String>; | |||
* | |||
* and List<T> in the following class : class Foo<T> { List<T> lt; } | |||
* | |||
* has signature: <1:>Pjava/util/List<T1;>; | |||
* | |||
* A typex that represents a type variable has its own unique signature, following the grammar for a FormalTypeParameter in the JVM | |||
* spec. | |||
* | |||
* A generic typex has its true signature and also an erasure signature. Both of these are keys pointing to the same UnresolvedType | |||
* in the world. For example List has signature: | |||
* | |||
* <1:>Ljava/util/List;Ljava/lang/Object; | |||
* | |||
* and the erasure signature | |||
* | |||
* Ljava/util/List; | |||
* | |||
* Generics wildcards introduce their own special signatures for type parameters. The wildcard ? has signature * The wildcard ? | |||
* extends Foo has signature +LFoo; The wildcard ? super Foo has signature -LFoo; | |||
*/ | |||
public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { | |||
// common types referred to by the weaver | |||
public static final UnresolvedType[] NONE = new UnresolvedType[0]; | |||
public static final UnresolvedType OBJECT = forSignature("Ljava/lang/Object;"); | |||
public static final UnresolvedType OBJECTARRAY = forSignature("[Ljava/lang/Object;"); | |||
public static final UnresolvedType CLONEABLE = forSignature("Ljava/lang/Cloneable;"); | |||
public static final UnresolvedType SERIALIZABLE = forSignature("Ljava/io/Serializable;"); | |||
public static final UnresolvedType THROWABLE = forSignature("Ljava/lang/Throwable;"); | |||
public static final UnresolvedType RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;"); | |||
public static final UnresolvedType ERROR = forSignature("Ljava/lang/Error;"); | |||
public static final UnresolvedType AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;"); | |||
public static final UnresolvedType AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;"); | |||
public static final UnresolvedType ENUM = forSignature("Ljava/lang/Enum;"); | |||
public static final UnresolvedType ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;"); | |||
public static final UnresolvedType JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;"); | |||
public static final UnresolvedType JAVA_LANG_CLASS_ARRAY = forSignature("[Ljava/lang/Class;"); | |||
public static final UnresolvedType JAVA_LANG_STRING = forSignature("Ljava/lang/String;"); | |||
public static final UnresolvedType JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;"); | |||
public static final UnresolvedType JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;"); | |||
public static final UnresolvedType JAVA_LANG_ANNOTATION = UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;"); | |||
public static final UnresolvedType SUPPRESS_AJ_WARNINGS = forSignature("Lorg/aspectj/lang/annotation/SuppressAjWarnings;"); | |||
public static final UnresolvedType AT_TARGET = forSignature("Ljava/lang/annotation/Target;"); | |||
public static final UnresolvedType SOMETHING = new UnresolvedType("?"); | |||
public static final UnresolvedType[] ARRAY_WITH_JUST_OBJECT = new UnresolvedType[] { OBJECT }; | |||
public static final UnresolvedType JOINPOINT_STATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;"); | |||
public static final UnresolvedType JOINPOINT_ENCLOSINGSTATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;"); | |||
// this doesn't belong here and will get moved to ResolvedType later in the refactoring | |||
public static final String MISSING_NAME = "@missing@"; | |||
// OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into | |||
// resolvedtype | |||
// that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer questions | |||
protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I? | |||
/** | |||
* THE SIGNATURE - see the comments above for how this is defined | |||
*/ | |||
protected String signature; | |||
/** | |||
* The erasure of the signature. Contains only the Java signature of the type with all supertype, superinterface, type variable, | |||
* and parameter information removed. | |||
*/ | |||
protected String signatureErasure; | |||
/** | |||
* Iff isParameterized(), then these are the type parameters | |||
*/ | |||
protected UnresolvedType[] typeParameters; | |||
/** | |||
* Iff isGeneric(), then these are the type variables declared on the type Iff isParameterized(), then these are the type | |||
* variables bound as parameters in the type | |||
*/ | |||
// OPTIMIZE should be no state in here that will damage whether equals() is correct... | |||
protected TypeVariable[] typeVariables; | |||
public boolean isPrimitiveType() { | |||
return typeKind == TypeKind.PRIMITIVE; | |||
} | |||
public boolean isSimpleType() { | |||
return typeKind == TypeKind.SIMPLE; | |||
} | |||
public boolean isRawType() { | |||
return typeKind == TypeKind.RAW; | |||
} | |||
public boolean isGenericType() { | |||
return typeKind == TypeKind.GENERIC; | |||
} | |||
public boolean isParameterizedType() { | |||
return typeKind == TypeKind.PARAMETERIZED; | |||
} | |||
public boolean isTypeVariableReference() { | |||
return typeKind == TypeKind.TYPE_VARIABLE; | |||
} | |||
public boolean isGenericWildcard() { | |||
return typeKind == TypeKind.WILDCARD; | |||
} | |||
public TypeKind getTypekind() { | |||
return typeKind; | |||
} | |||
// for any reference type, we can get some extra information... | |||
public final boolean isArray() { | |||
return signature.length() > 0 && signature.charAt(0) == '['; | |||
} | |||
/** | |||
* Equality is checked based on the underlying signature. {@link ResolvedType} objects' equals is by reference. | |||
*/ | |||
public boolean equals(Object other) { | |||
if (!(other instanceof UnresolvedType)) | |||
return false; | |||
return signature.equals(((UnresolvedType) other).signature); | |||
} | |||
/** | |||
* Equality is checked based on the underlying signature, so the hash code of a particular type is the hash code of its | |||
* signature string. | |||
*/ | |||
public final int hashCode() { | |||
return signature.hashCode(); | |||
} | |||
protected UnresolvedType(String signature) { | |||
this.signature = signature; | |||
this.signatureErasure = signature; | |||
} | |||
protected UnresolvedType(String signature, String signatureErasure) { | |||
this.signature = signature; | |||
this.signatureErasure = signatureErasure; | |||
} | |||
// called from TypeFactory | |||
public UnresolvedType(String signature, String signatureErasure, UnresolvedType[] typeParams) { | |||
this.signature = signature; | |||
this.signatureErasure = signatureErasure; | |||
this.typeParameters = typeParams; | |||
if (typeParams != null) | |||
this.typeKind = TypeKind.PARAMETERIZED; | |||
} | |||
// ---- Things we can do without a world | |||
/** | |||
* This is the size of this type as used in JVM. | |||
*/ | |||
public int getSize() { | |||
return 1; | |||
} | |||
public static UnresolvedType makeArray(UnresolvedType base, int dims) { | |||
StringBuffer sig = new StringBuffer(); | |||
for (int i = 0; i < dims; i++) | |||
sig.append("["); | |||
sig.append(base.getSignature()); | |||
return UnresolvedType.forSignature(sig.toString()); | |||
} | |||
/** | |||
* NOTE: Use forSignature() if you can, it'll be cheaper ! Constructs a UnresolvedType for a java language type name. For | |||
* example: | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forName("java.lang.Thread[]") | |||
* UnresolvedType.forName("int") | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* Types may equivalently be produced by this or by {@link #forSignature(String)}. | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;") | |||
* UnresolvedType.forName("int").equals(Type.forSignature("I")) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* @param name the java language type name in question. | |||
* @return a type object representing that java language type. | |||
*/ | |||
// OPTIMIZE change users of this to use forSignature, especially for simple cases | |||
public static UnresolvedType forName(String name) { | |||
return forSignature(nameToSignature(name)); | |||
} | |||
/** | |||
* Constructs a UnresolvedType for each java language type name in an incoming array. | |||
* | |||
* @param names an array of java language type names. | |||
* @return an array of UnresolvedType objects. | |||
* @see #forName(String) | |||
*/ | |||
public static UnresolvedType[] forNames(String[] names) { | |||
UnresolvedType[] ret = new UnresolvedType[names.length]; | |||
for (int i = 0, len = names.length; i < len; i++) { | |||
ret[i] = UnresolvedType.forName(names[i]); | |||
} | |||
return ret; | |||
} | |||
public static UnresolvedType forGenericType(String name, TypeVariable[] tvbs, String genericSig) { | |||
// TODO asc generics needs a declared sig | |||
String sig = nameToSignature(name); | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
ret.typeKind = TypeKind.GENERIC; | |||
ret.typeVariables = tvbs; | |||
ret.signatureErasure = sig; | |||
return ret; | |||
} | |||
public static UnresolvedType forGenericTypeSignature(String sig, String declaredGenericSig) { | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
ret.typeKind = TypeKind.GENERIC; | |||
ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig); | |||
GenericSignature.FormalTypeParameter[] ftps = csig.formalTypeParameters; | |||
ret.typeVariables = new TypeVariable[ftps.length]; | |||
for (int i = 0; i < ftps.length; i++) { | |||
GenericSignature.FormalTypeParameter parameter = ftps[i]; | |||
if (parameter.classBound instanceof GenericSignature.ClassTypeSignature) { | |||
GenericSignature.ClassTypeSignature cts = (GenericSignature.ClassTypeSignature) parameter.classBound; | |||
ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, UnresolvedType.forSignature(cts.outerType.identifier | |||
+ ";")); | |||
} else if (parameter.classBound instanceof GenericSignature.TypeVariableSignature) { | |||
GenericSignature.TypeVariableSignature tvs = (GenericSignature.TypeVariableSignature) parameter.classBound; | |||
UnresolvedTypeVariableReferenceType utvrt = new UnresolvedTypeVariableReferenceType(new TypeVariable( | |||
tvs.typeVariableName)); | |||
ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, utvrt); | |||
} else { | |||
throw new BCException( | |||
"UnresolvedType.forGenericTypeSignature(): Do not know how to process type variable bound of type '" | |||
+ parameter.classBound.getClass() + "'. Full signature is '" + sig + "'"); | |||
} | |||
} | |||
ret.signatureErasure = sig; | |||
ret.signature = ret.signatureErasure; | |||
return ret; | |||
} | |||
public static UnresolvedType forGenericTypeVariables(String sig, TypeVariable[] tVars) { | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
ret.typeKind = TypeKind.GENERIC; | |||
ret.typeVariables = tVars; | |||
ret.signatureErasure = sig; | |||
ret.signature = ret.signatureErasure; | |||
return ret; | |||
} | |||
public static UnresolvedType forRawTypeName(String name) { | |||
UnresolvedType ret = UnresolvedType.forName(name); | |||
ret.typeKind = TypeKind.RAW; | |||
return ret; | |||
} | |||
/** | |||
* Creates a new type array with a fresh type appended to the end. | |||
* | |||
* @param types the left hand side of the new array | |||
* @param end the right hand side of the new array | |||
*/ | |||
public static UnresolvedType[] add(UnresolvedType[] types, UnresolvedType end) { | |||
int len = types.length; | |||
UnresolvedType[] ret = new UnresolvedType[len + 1]; | |||
System.arraycopy(types, 0, ret, 0, len); | |||
ret[len] = end; | |||
return ret; | |||
} | |||
/** | |||
* Creates a new type array with a fresh type inserted at the beginning. | |||
* | |||
* | |||
* @param start the left hand side of the new array | |||
* @param types the right hand side of the new array | |||
*/ | |||
public static UnresolvedType[] insert(UnresolvedType start, UnresolvedType[] types) { | |||
int len = types.length; | |||
UnresolvedType[] ret = new UnresolvedType[len + 1]; | |||
ret[0] = start; | |||
System.arraycopy(types, 0, ret, 1, len); | |||
return ret; | |||
} | |||
/** | |||
* Constructs a Type for a JVM bytecode signature string. For example: | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forSignature("[Ljava/lang/Thread;") | |||
* UnresolvedType.forSignature("I"); | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* Types may equivalently be produced by this or by {@link #forName(String)}. | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;") | |||
* UnresolvedType.forName("int").equals(Type.forSignature("I")) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* @param signature the JVM bytecode signature string for the desired type. | |||
* @return a type object represnting that JVM bytecode signature. | |||
*/ | |||
public static UnresolvedType forSignature(String signature) { | |||
switch (signature.charAt(0)) { | |||
case 'B': | |||
return ResolvedType.BYTE; | |||
case 'C': | |||
return ResolvedType.CHAR; | |||
case 'D': | |||
return ResolvedType.DOUBLE; | |||
case 'F': | |||
return ResolvedType.FLOAT; | |||
case 'I': | |||
return ResolvedType.INT; | |||
case 'J': | |||
return ResolvedType.LONG; | |||
case 'L': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case 'P': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case 'S': | |||
return ResolvedType.SHORT; | |||
case 'V': | |||
return ResolvedType.VOID; | |||
case 'Z': | |||
return ResolvedType.BOOLEAN; | |||
case '[': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case '+': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case '-': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case '?': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
case 'T': | |||
return TypeFactory.createTypeFromSignature(signature); | |||
default: | |||
throw new BCException("Bad type signature " + signature); | |||
} | |||
} | |||
/** | |||
* Constructs a UnresolvedType for each JVM bytecode type signature in an incoming array. | |||
* | |||
* @param names an array of JVM bytecode type signatures | |||
* @return an array of UnresolvedType objects. | |||
* @see #forSignature(String) | |||
*/ | |||
public static UnresolvedType[] forSignatures(String[] sigs) { | |||
UnresolvedType[] ret = new UnresolvedType[sigs.length]; | |||
for (int i = 0, len = sigs.length; i < len; i++) { | |||
ret[i] = UnresolvedType.forSignature(sigs[i]); | |||
} | |||
return ret; | |||
} | |||
/** | |||
* Returns the name of this type in java language form (e.g. java.lang.Thread or boolean[]). This produces a more aesthetically | |||
* pleasing string than {@link java.lang.Class#getName()}. | |||
* | |||
* @return the java language name of this type. | |||
*/ | |||
public String getName() { | |||
return signatureToName(signature); | |||
} | |||
public String getSimpleName() { | |||
String name = getRawName(); | |||
int lastDot = name.lastIndexOf('.'); | |||
if (lastDot != -1) { | |||
name = name.substring(lastDot + 1); | |||
} | |||
if (isParameterizedType()) { | |||
StringBuffer sb = new StringBuffer(name); | |||
sb.append("<"); | |||
for (int i = 0; i < (typeParameters.length - 1); i++) { | |||
sb.append(typeParameters[i].getSimpleName()); | |||
sb.append(","); | |||
} | |||
sb.append(typeParameters[typeParameters.length - 1].getSimpleName()); | |||
sb.append(">"); | |||
name = sb.toString(); | |||
} | |||
return name; | |||
} | |||
public String getRawName() { | |||
return signatureToName((signatureErasure == null ? signature : signatureErasure)); | |||
} | |||
public String getBaseName() { | |||
String name = getName(); | |||
if (isParameterizedType() || isGenericType()) { | |||
if (typeParameters == null) | |||
return name; | |||
else | |||
return name.substring(0, name.indexOf("<")); | |||
} else { | |||
return name; | |||
} | |||
} | |||
public String getSimpleBaseName() { | |||
String name = getBaseName(); | |||
int lastDot = name.lastIndexOf('.'); | |||
if (lastDot != -1) { | |||
name = name.substring(lastDot + 1); | |||
} | |||
return name; | |||
} | |||
/** | |||
* Returns an array of strings representing the java langauge names of an array of types. | |||
* | |||
* @param types an array of UnresolvedType objects | |||
* @return an array of Strings fo the java language names of types. | |||
* @see #getName() | |||
*/ | |||
public static String[] getNames(UnresolvedType[] types) { | |||
String[] ret = new String[types.length]; | |||
for (int i = 0, len = types.length; i < len; i++) { | |||
ret[i] = types[i].getName(); | |||
} | |||
return ret; | |||
} | |||
/** | |||
* Returns the name of this type in JVM signature form. For all UnresolvedType t: | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forSignature(t.getSignature()).equals(t) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* and for all String s where s is a lexically valid JVM type signature string: | |||
* | |||
* <blockquote> | |||
* | |||
* <pre> | |||
* UnresolvedType.forSignature(s).getSignature().equals(s) | |||
* </pre> | |||
* | |||
* </blockquote> | |||
* | |||
* @return the java JVM signature string for this type. | |||
*/ | |||
public String getSignature() { | |||
return signature; | |||
} | |||
/** | |||
* For parameterized types, return the signature for the raw type | |||
*/ | |||
public String getErasureSignature() { | |||
if (signatureErasure == null) | |||
return signature; | |||
return signatureErasure; | |||
} | |||
private boolean needsModifiableDelegate = false; | |||
public boolean needsModifiableDelegate() { | |||
return needsModifiableDelegate; | |||
} | |||
public void setNeedsModifiableDelegate(boolean b) { | |||
this.needsModifiableDelegate = b; | |||
} | |||
public UnresolvedType getRawType() { | |||
return UnresolvedType.forSignature(getErasureSignature()); | |||
} | |||
/** | |||
* Returns a UnresolvedType object representing the effective outermost enclosing type for a name type. For all other types, | |||
* this will return the type itself. | |||
* | |||
* The only guarantee is given in JLS 13.1 where code generated according to those rules will have type names that can be split | |||
* apart in this way. | |||
* | |||
* @return the outermost enclosing UnresolvedType object or this. | |||
*/ | |||
public UnresolvedType getOutermostType() { | |||
if (isArray() || isPrimitiveType()) | |||
return this; | |||
String sig = getErasureSignature(); | |||
int dollar = sig.indexOf('$'); | |||
if (dollar != -1) { | |||
return UnresolvedType.forSignature(sig.substring(0, dollar) + ';'); | |||
} else { | |||
return this; | |||
} | |||
} | |||
/** | |||
* Returns a UnresolvedType object representing the component type of this array, or null if this type does not represent an | |||
* array type. | |||
* | |||
* @return the component UnresolvedType object, or null. | |||
*/ | |||
public UnresolvedType getComponentType() { | |||
if (isArray()) { | |||
return forSignature(signature.substring(1)); | |||
} else { | |||
return null; | |||
} | |||
} | |||
/** | |||
* Returns a java language string representation of this type. | |||
*/ | |||
public String toString() { | |||
return getName(); // + " - " + getKind(); | |||
} | |||
public String toDebugString() { | |||
return getName(); | |||
} | |||
// ---- requires worlds | |||
/** | |||
* Returns a resolved version of this type according to a particular world. | |||
* | |||
* @param world thie {@link World} within which to resolve. | |||
* @return a resolved type representing this type in the appropriate world. | |||
*/ | |||
public ResolvedType resolve(World world) { | |||
return world.resolve(this); | |||
} | |||
// ---- helpers | |||
private static String signatureToName(String signature) { | |||
switch (signature.charAt(0)) { | |||
case 'B': | |||
return "byte"; | |||
case 'C': | |||
return "char"; | |||
case 'D': | |||
return "double"; | |||
case 'F': | |||
return "float"; | |||
case 'I': | |||
return "int"; | |||
case 'J': | |||
return "long"; | |||
case 'L': | |||
String name = signature.substring(1, signature.length() - 1).replace('/', '.'); | |||
return name; | |||
case 'T': | |||
StringBuffer nameBuff2 = new StringBuffer(); | |||
int colon = signature.indexOf(";"); | |||
String tvarName = signature.substring(1, colon); | |||
nameBuff2.append(tvarName); | |||
return nameBuff2.toString(); | |||
case 'P': // it's one of our parameterized type sigs | |||
StringBuffer nameBuff = new StringBuffer(); | |||
// signature for parameterized types is e.g. | |||
// List<String> -> Ljava/util/List<Ljava/lang/String;>; | |||
// Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>; | |||
int paramNestLevel = 0; | |||
for (int i = 1; i < signature.length(); i++) { | |||
char c = signature.charAt(i); | |||
switch (c) { | |||
case '/': | |||
nameBuff.append('.'); | |||
break; | |||
case '<': | |||
nameBuff.append("<"); | |||
paramNestLevel++; | |||
StringBuffer innerBuff = new StringBuffer(); | |||
while (paramNestLevel > 0) { | |||
c = signature.charAt(++i); | |||
if (c == '<') | |||
paramNestLevel++; | |||
if (c == '>') | |||
paramNestLevel--; | |||
if (paramNestLevel > 0) | |||
innerBuff.append(c); | |||
if (c == ';' && paramNestLevel == 1) { | |||
nameBuff.append(signatureToName(innerBuff.toString())); | |||
if (signature.charAt(i + 1) != '>') | |||
nameBuff.append(','); | |||
innerBuff = new StringBuffer(); | |||
} | |||
} | |||
nameBuff.append(">"); | |||
break; | |||
case ';': | |||
break; | |||
default: | |||
nameBuff.append(c); | |||
} | |||
} | |||
return nameBuff.toString(); | |||
case 'S': | |||
return "short"; | |||
case 'V': | |||
return "void"; | |||
case 'Z': | |||
return "boolean"; | |||
case '[': | |||
return signatureToName(signature.substring(1, signature.length())) + "[]"; | |||
// case '<': | |||
// // its a generic! | |||
// if (signature.charAt(1)=='>') return signatureToName(signature.substring(2)); | |||
case '+': | |||
return "? extends " + signatureToName(signature.substring(1, signature.length())); | |||
case '-': | |||
return "? super " + signatureToName(signature.substring(1, signature.length())); | |||
case '*': | |||
return "?"; | |||
default: | |||
throw new BCException("Bad type signature: " + signature); | |||
} | |||
} | |||
private static String nameToSignature(String name) { | |||
if (name.equals("byte")) | |||
return "B"; | |||
if (name.equals("char")) | |||
return "C"; | |||
if (name.equals("double")) | |||
return "D"; | |||
if (name.equals("float")) | |||
return "F"; | |||
if (name.equals("int")) | |||
return "I"; | |||
if (name.equals("long")) | |||
return "J"; | |||
if (name.equals("short")) | |||
return "S"; | |||
if (name.equals("boolean")) | |||
return "Z"; | |||
if (name.equals("void")) | |||
return "V"; | |||
if (name.equals("?")) | |||
return name; | |||
if (name.endsWith("[]")) | |||
return "[" + nameToSignature(name.substring(0, name.length() - 2)); | |||
if (name.length() != 0) { | |||
// lots more tests could be made here... | |||
// check if someone is calling us with something that is a signature already | |||
if (name.charAt(0) == '[') { | |||
throw new BCException("Do not call nameToSignature with something that looks like a signature (descriptor): '" | |||
+ name + "'"); | |||
} | |||
if (name.indexOf("<") == -1) { | |||
// not parameterised | |||
return "L" + name.replace('.', '/') + ";"; | |||
} else { | |||
StringBuffer nameBuff = new StringBuffer(); | |||
int nestLevel = 0; | |||
nameBuff.append("P"); | |||
for (int i = 0; i < name.length(); i++) { | |||
char c = name.charAt(i); | |||
switch (c) { | |||
case '.': | |||
nameBuff.append('/'); | |||
break; | |||
case '<': | |||
nameBuff.append("<"); | |||
nestLevel++; | |||
StringBuffer innerBuff = new StringBuffer(); | |||
while (nestLevel > 0) { | |||
c = name.charAt(++i); | |||
if (c == '<') | |||
nestLevel++; | |||
if (c == '>') | |||
nestLevel--; | |||
if (c == ',' && nestLevel == 1) { | |||
nameBuff.append(nameToSignature(innerBuff.toString())); | |||
innerBuff = new StringBuffer(); | |||
} else { | |||
if (nestLevel > 0) | |||
innerBuff.append(c); | |||
} | |||
} | |||
nameBuff.append(nameToSignature(innerBuff.toString())); | |||
nameBuff.append('>'); | |||
break; | |||
case '>': | |||
throw new IllegalStateException("Should by matched by <"); | |||
case ',': | |||
throw new IllegalStateException("Should only happen inside <...>"); | |||
default: | |||
nameBuff.append(c); | |||
} | |||
} | |||
nameBuff.append(";"); | |||
return nameBuff.toString(); | |||
} | |||
} else | |||
throw new BCException("Bad type name: " + name); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeUTF(getSignature()); | |||
} | |||
public static UnresolvedType read(DataInputStream s) throws IOException { | |||
String sig = s.readUTF(); | |||
if (sig.equals(MISSING_NAME)) { | |||
return ResolvedType.MISSING; | |||
} else { | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
return ret; | |||
} | |||
} | |||
public static void writeArray(UnresolvedType[] types, DataOutputStream s) throws IOException { | |||
int len = types.length; | |||
s.writeShort(len); | |||
for (int i = 0; i < len; i++) { | |||
types[i].write(s); | |||
} | |||
} | |||
public static UnresolvedType[] readArray(DataInputStream s) throws IOException { | |||
int len = s.readShort(); | |||
if (len == 0) | |||
return UnresolvedType.NONE; | |||
UnresolvedType[] types = new UnresolvedType[len]; | |||
for (int i = 0; i < len; i++) { | |||
types[i] = UnresolvedType.read(s); | |||
} | |||
return types; | |||
} | |||
public String getNameAsIdentifier() { | |||
return getName().replace('.', '_'); | |||
} | |||
public String getPackageNameAsIdentifier() { | |||
String name = getName(); | |||
int index = name.lastIndexOf('.'); | |||
if (index == -1) { | |||
return ""; | |||
} else { | |||
return name.substring(0, index).replace('.', '_'); | |||
} | |||
} | |||
public String getPackageName() { | |||
String name = getName(); | |||
if (name.indexOf("<") != -1) { | |||
name = name.substring(0, name.indexOf("<")); | |||
} | |||
int index = name.lastIndexOf('.'); | |||
if (index == -1) { | |||
return ""; | |||
} else { | |||
return name.substring(0, index); | |||
} | |||
} | |||
public UnresolvedType[] getTypeParameters() { | |||
return typeParameters == null ? UnresolvedType.NONE : typeParameters; | |||
} | |||
/** | |||
* Doesn't include the package | |||
*/ | |||
public String getClassName() { | |||
String name = getName(); | |||
int index = name.lastIndexOf('.'); | |||
if (index == -1) { | |||
return name; | |||
} else { | |||
return name.substring(index + 1); | |||
} | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
return typeVariables; | |||
} | |||
public static class TypeKind { | |||
// Note: It is not sufficient to say that a parameterized type with no type parameters in fact | |||
// represents a raw type - a parameterized type with no type parameters can represent | |||
// an inner type of a parameterized type that specifies no type parameters of its own. | |||
public final static TypeKind PRIMITIVE = new TypeKind("primitive"); | |||
public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars | |||
public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type | |||
public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type | |||
public final static TypeKind PARAMETERIZED = new TypeKind("parameterized"); // a parameterized type | |||
public final static TypeKind TYPE_VARIABLE = new TypeKind("type_variable"); // a type variable | |||
public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type | |||
public String toString() { | |||
return type; | |||
} | |||
private TypeKind(String type) { | |||
this.type = type; | |||
} | |||
private final String type; | |||
} | |||
public TypeVariable getTypeVariableNamed(String name) { | |||
TypeVariable[] vars = getTypeVariables(); | |||
if (vars == null || vars.length == 0) | |||
return null; | |||
for (int i = 0; i < vars.length; i++) { | |||
TypeVariable aVar = vars[i]; | |||
if (aVar.getName().equals(name)) | |||
return aVar; | |||
} | |||
return null; | |||
} | |||
public String toTraceString() { | |||
return getClass().getName() + "[" + getName() + "]"; | |||
} | |||
/** | |||
* Return a version of this parameterized type in which any type parameters that are type variable references are replaced by | |||
* their matching type variable binding. | |||
*/ | |||
// OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature); | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
/** | |||
* @author colyer | |||
* Represents a type variable encountered in the Eclipse Source world, | |||
* which when resolved will turn into a TypeVariableReferenceType | |||
*/ | |||
public class UnresolvedTypeVariableReferenceType extends UnresolvedType implements TypeVariableReference { | |||
private TypeVariable typeVariable; | |||
// constructor used as place-holder when dealing with circular refs such as Enum | |||
public UnresolvedTypeVariableReferenceType() { | |||
super("Ljava/lang/Object;"); | |||
} | |||
public UnresolvedTypeVariableReferenceType(TypeVariable aTypeVariable) { | |||
super(aTypeVariable.getFirstBound().getSignature()); | |||
this.typeVariable = aTypeVariable; | |||
} | |||
// only used when resolving circular refs... | |||
public void setTypeVariable(TypeVariable aTypeVariable) { | |||
this.signature = "T" + aTypeVariable.getName() + ";"; //aTypeVariable.getUpperBound().getSignature(); | |||
this.typeVariable = aTypeVariable; | |||
this.typeKind=TypeKind.TYPE_VARIABLE; | |||
} | |||
public ResolvedType resolve(World world) { | |||
TypeVariableDeclaringElement typeVariableScope = world.getTypeVariableLookupScope(); | |||
TypeVariable resolvedTypeVariable = null; | |||
TypeVariableReferenceType tvrt = null; | |||
if (typeVariableScope == null) { | |||
// throw new BCException("There is no scope in which to lookup type variables!"); | |||
// FIXME asc correct thing to do is go bang, but to limp along, lets cope with the scope missing | |||
resolvedTypeVariable = typeVariable.resolve(world); | |||
tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world); | |||
} else { | |||
boolean foundOK = false; | |||
resolvedTypeVariable = typeVariableScope.getTypeVariableNamed(typeVariable.getName()); | |||
// FIXME asc remove this when the shared type var stuff is sorted | |||
if (resolvedTypeVariable == null) { | |||
resolvedTypeVariable = typeVariable.resolve(world); | |||
} else { | |||
foundOK = true; | |||
} | |||
tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world); | |||
tvrt.fixedUp = foundOK; | |||
} | |||
return tvrt; | |||
} | |||
public boolean isTypeVariableReference() { | |||
return true; | |||
} | |||
public TypeVariable getTypeVariable() { | |||
return typeVariable; | |||
} | |||
// public String getName() { | |||
// if (typeVariable == null) return "<type variable not set!>"; | |||
// return typeVariable.getDisplayName(); | |||
// } | |||
public String toString() { | |||
if (typeVariable == null) { | |||
return "<type variable not set!>"; | |||
} else { | |||
return "T" + typeVariable.getName() + ";"; | |||
} | |||
} | |||
public String toDebugString() { | |||
return typeVariable.getName(); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
super.write(s); | |||
} | |||
public String getErasureSignature() { | |||
return typeVariable.getFirstBound().getSignature(); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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 | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class Utils { | |||
/** | |||
* Check if the annotations contain a SuppressAjWarnings annotation and if that annotation specifies that the given lint message | |||
* (identified by its key) should be ignored. | |||
* | |||
*/ | |||
public static boolean isSuppressing(AnnotationAJ[] anns, String lintkey) { | |||
if (anns == null) { | |||
return false; | |||
} | |||
// Go through the annotation types on the advice | |||
for (int i = 0; i < anns.length; i++) { | |||
if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(anns[i].getTypeSignature())) { | |||
// Two possibilities: | |||
// 1. there are no values specified (i.e. @SuppressAjWarnings) | |||
// 2. there are values specified (i.e. @SuppressAjWarnings("A") or @SuppressAjWarnings({"A","B"}) | |||
String value = anns[i].getStringFormOfValue("value"); | |||
// Slightly lazy, just doing a string indexof | |||
if (value == null || value.indexOf(lintkey) != -1) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 IBM | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataInputStream; | |||
import java.io.InputStream; | |||
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; | |||
/** | |||
* Lightweight subclass of DataInputStream that knows what version of the weaver was used to construct the data in it. | |||
*/ | |||
public class VersionedDataInputStream extends DataInputStream { | |||
private WeaverVersionInfo version = new WeaverVersionInfo();// assume we are the latest unless something tells us otherwise... | |||
public VersionedDataInputStream(InputStream is) { super(is); } | |||
public int getMajorVersion() { return version.getMajorVersion(); } | |||
public int getMinorVersion() { return version.getMinorVersion(); } | |||
public long getBuildstamp() { return version.getBuildstamp(); } | |||
public void setVersion(WeaverVersionInfo version) { this.version = version; } | |||
} |
@@ -0,0 +1,63 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.lang.ref.WeakReference; | |||
/** | |||
* Wraps a reference to a classloader inside a WeakReference. This should be used where we do not want the existence of a | |||
* classloader reference to prevent garbage collection of that classloader (and possibly an associated weaver instance in the case | |||
* of load time weaving). | |||
* <p> | |||
* In more detail:<br> | |||
* When load time weaving, the class Aj maintains a WeakHashMap from the classloader instance to a weaver instance. The aim is that | |||
* the weaver is around as long as the classloader is and should the classloader be dereferenced then the weaver can also be garbage | |||
* collected. The problem is that if there are many references to the classloader from within the weaver, these are considered hard | |||
* references and cause the classloader to be long lived - even if the user of the classloader has dereferenced it in their code. | |||
* The solution is that the weaver should use instances of WeakClassLoaderReference objects - so that when the users hard reference | |||
* to the classloader goes, nothing in the weaver will cause it to hang around. There is a big assertion here that the | |||
* WeakClassLoaderReference instances will not 'lose' their ClassLoader references until the top level ClassLoader reference is | |||
* null'd. This means there is no need to check for the null case on get() in this WeakReference logic below, because we shouldn't | |||
* be using this weaver if its associated ClassLoader has been collected. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=210470 | |||
* | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class WeakClassLoaderReference { | |||
protected final int hashcode; | |||
private final WeakReference loaderRef; | |||
public WeakClassLoaderReference(ClassLoader loader) { | |||
loaderRef = new WeakReference(loader); | |||
hashcode = loader.hashCode() * 37; | |||
} | |||
public ClassLoader getClassLoader() { | |||
ClassLoader instance = (ClassLoader) loaderRef.get(); | |||
// Assert instance!=null | |||
return instance; | |||
} | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof WeakClassLoaderReference)) | |||
return false; | |||
WeakClassLoaderReference other = (WeakClassLoaderReference) obj; | |||
return (other.hashcode == hashcode); | |||
} | |||
public int hashCode() { | |||
return hashcode; | |||
} | |||
} |
@@ -0,0 +1,210 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM Corporation and others. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* IBM Corporation - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.text.MessageFormat; | |||
import java.util.ResourceBundle; | |||
public class WeaverMessages { | |||
private static ResourceBundle bundle = ResourceBundle.getBundle("org.aspectj.weaver.weaver-messages"); | |||
public static final String ARGS_IN_DECLARE = "argsInDeclare"; | |||
public static final String CFLOW_IN_DECLARE = "cflowInDeclare"; | |||
public static final String IF_IN_DECLARE = "ifInDeclare"; | |||
public static final String THIS_OR_TARGET_IN_DECLARE = "thisOrTargetInDeclare"; | |||
public static final String ABSTRACT_POINTCUT = "abstractPointcut"; | |||
public static final String POINCUT_NOT_CONCRETE = "abstractPointcutNotMadeConcrete"; | |||
public static final String POINTCUT_NOT_VISIBLE = "pointcutNotVisible"; | |||
public static final String CONFLICTING_INHERITED_POINTCUTS = "conflictingInheritedPointcuts"; | |||
public static final String CIRCULAR_POINTCUT = "circularPointcutDeclaration"; | |||
public static final String CANT_FIND_POINTCUT = "cantFindPointcut"; | |||
public static final String EXACT_TYPE_PATTERN_REQD = "exactTypePatternRequired"; | |||
public static final String CANT_BIND_TYPE = "cantBindType"; | |||
public static final String WILDCARD_NOT_ALLOWED = "wildcardTypePatternNotAllowed"; | |||
public static final String FIELDS_CANT_HAVE_VOID_TYPE = "fieldCantBeVoid"; | |||
public static final String NO_NEWARRAY_JOINPOINTS_BY_DEFAULT = "noNewArrayJoinpointsByDefault"; | |||
public static final String UNSUPPORTED_POINTCUT_PRIMITIVE = "unsupportedPointcutPrimitive"; | |||
public static final String MISSING_TYPE_PREVENTS_MATCH = "missingTypePreventsMatch"; | |||
public static final String DECP_OBJECT = "decpObject"; | |||
public static final String CANT_EXTEND_SELF="cantExtendSelf"; | |||
public static final String INTERFACE_CANT_EXTEND_CLASS="interfaceExtendClass"; | |||
public static final String DECP_HIERARCHY_ERROR = "decpHierarchy"; | |||
public static final String MULTIPLE_MATCHES_IN_PRECEDENCE = "multipleMatchesInPrecedence"; | |||
public static final String TWO_STARS_IN_PRECEDENCE = "circularityInPrecedenceStar"; | |||
public static final String CLASSES_IN_PRECEDENCE = "nonAspectTypesInPrecedence"; | |||
public static final String TWO_PATTERN_MATCHES_IN_PRECEDENCE = "circularityInPrecedenceTwo"; | |||
public static final String NOT_THROWABLE = "notThrowable"; | |||
public static final String ITD_CONS_ON_ASPECT = "itdConsOnAspect"; | |||
public static final String ITD_RETURN_TYPE_MISMATCH = "returnTypeMismatch"; | |||
public static final String ITD_PARAM_TYPE_MISMATCH = "paramTypeMismatch"; | |||
public static final String ITD_VISIBILITY_REDUCTION = "visibilityReduction"; | |||
public static final String ITD_DOESNT_THROW = "doesntThrow"; | |||
public static final String ITD_OVERRIDDEN_STATIC = "overriddenStatic"; | |||
public static final String ITD_OVERIDDING_STATIC = "overridingStatic"; | |||
public static final String ITD_CONFLICT = "itdConflict"; | |||
public static final String ITD_MEMBER_CONFLICT = "itdMemberConflict"; | |||
public static final String ITD_NON_EXPOSED_IMPLEMENTOR = "itdNonExposedImplementor"; | |||
public static final String ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE = "itdAbstractMustBePublicOnInterface"; | |||
public static final String CANT_OVERRIDE_FINAL_MEMBER = "cantOverrideFinalMember"; | |||
public static final String NON_VOID_RETURN = "nonVoidReturn"; | |||
public static final String INCOMPATIBLE_RETURN_TYPE="incompatibleReturnType"; | |||
public static final String CANT_THROW_CHECKED = "cantThrowChecked"; | |||
public static final String CIRCULAR_DEPENDENCY = "circularDependency"; | |||
public static final String MISSING_PER_CLAUSE = "missingPerClause"; | |||
public static final String WRONG_PER_CLAUSE = "wrongPerClause"; | |||
public static final String ALREADY_WOVEN = "alreadyWoven"; | |||
public static final String REWEAVABLE_MODE = "reweavableMode"; | |||
public static final String PROCESSING_REWEAVABLE = "processingReweavable"; | |||
public static final String MISSING_REWEAVABLE_TYPE = "missingReweavableType"; | |||
public static final String VERIFIED_REWEAVABLE_TYPE = "verifiedReweavableType"; | |||
public static final String ASPECT_NEEDED = "aspectNeeded"; | |||
public static final String REWEAVABLE_ASPECT_NOT_REGISTERED = "reweavableAspectNotRegistered"; | |||
public static final String CANT_FIND_TYPE = "cantFindType"; | |||
public static final String CANT_FIND_CORE_TYPE = "cantFindCoreType"; | |||
public static final String CANT_FIND_TYPE_WITHINPCD = "cantFindTypeWithinpcd"; | |||
public static final String CANT_FIND_TYPE_DURING_AROUND_WEAVE = "cftDuringAroundWeave"; | |||
public static final String CANT_FIND_TYPE_DURING_AROUND_WEAVE_PREINIT = "cftDuringAroundWeavePreinit"; | |||
public static final String CANT_FIND_TYPE_EXCEPTION_TYPE = "cftExceptionType"; | |||
public static final String CANT_FIND_TYPE_ARG_TYPE = "cftArgType"; | |||
public static final String CANT_FIND_PARENT_TYPE = "cantFindParentType"; | |||
public static final String CANT_FIND_PARENT_TYPE_NO_SUB = "cantFindParentTypeNoSub"; | |||
public static final String CANT_FIND_TYPE_FIELDS = "cantFindTypeFields"; | |||
public static final String CANT_FIND_TYPE_SUPERCLASS = "cantFindTypeSuperclass"; | |||
public static final String CANT_FIND_TYPE_INTERFACES = "cantFindTypeInterfaces"; | |||
public static final String CANT_FIND_TYPE_METHODS = "cantFindTypeMethods"; | |||
public static final String CANT_FIND_TYPE_POINTCUTS = "cantFindTypePointcuts"; | |||
public static final String CANT_FIND_TYPE_MODIFIERS = "cantFindTypeModifiers"; | |||
public static final String CANT_FIND_TYPE_ANNOTATION = "cantFindTypeAnnotation"; | |||
public static final String CANT_FIND_TYPE_ASSIGNABLE = "cantFindTypeAssignable"; | |||
public static final String CANT_FIND_TYPE_COERCEABLE = "cantFindTypeCoerceable"; | |||
public static final String CANT_FIND_TYPE_JOINPOINT = "cantFindTypeJoinPoint"; | |||
public static final String CANT_FIND_TYPE_INTERFACE_METHODS = "cantFindTypeInterfaceMethods"; | |||
public static final String DECP_BINARY_LIMITATION = "decpBinaryLimitation"; | |||
public static final String OVERWRITE_JSR45 = "overwriteJSR45"; | |||
public static final String IF_IN_PERCLAUSE = "ifInPerClause"; | |||
public static final String IF_LEXICALLY_IN_CFLOW = "ifLexicallyInCflow"; | |||
public static final String ONLY_BEFORE_ON_HANDLER = "onlyBeforeOnHandler"; | |||
public static final String NO_AROUND_ON_SYNCHRONIZATION = "noAroundOnSynchronization"; | |||
public static final String AROUND_ON_PREINIT = "aroundOnPreInit"; | |||
public static final String AROUND_ON_INIT = "aroundOnInit"; | |||
public static final String AROUND_ON_INTERFACE_STATICINIT = "aroundOnInterfaceStaticInit"; | |||
public static final String PROBLEM_GENERATING_METHOD = "problemGeneratingMethod"; | |||
public static final String CLASS_TOO_BIG = "classTooBig"; | |||
public static final String ZIPFILE_ENTRY_MISSING = "zipfileEntryMissing"; | |||
public static final String ZIPFILE_ENTRY_INVALID = "zipfileEntryInvalid"; | |||
public static final String DIRECTORY_ENTRY_MISSING = "directoryEntryMissing"; | |||
public static final String OUTJAR_IN_INPUT_PATH = "outjarInInputPath"; | |||
public static final String XLINT_LOAD_ERROR = "problemLoadingXLint"; | |||
public static final String XLINTDEFAULT_LOAD_ERROR = "unableToLoadXLintDefault"; | |||
public static final String XLINTDEFAULT_LOAD_PROBLEM = "errorLoadingXLintDefault"; | |||
public static final String XLINT_KEY_ERROR = "invalidXLintKey"; | |||
public static final String XLINT_VALUE_ERROR = "invalidXLintMessageKind"; | |||
public static final String UNBOUND_FORMAL = "unboundFormalInPC"; | |||
public static final String AMBIGUOUS_BINDING = "ambiguousBindingInPC"; | |||
public static final String AMBIGUOUS_BINDING_IN_OR = "ambiguousBindingInOrPC"; | |||
public static final String NEGATION_DOESNT_ALLOW_BINDING = "negationDoesntAllowBinding"; | |||
// Java5 messages | |||
public static final String ITDC_ON_ENUM_NOT_ALLOWED = "itdcOnEnumNotAllowed"; | |||
public static final String ITDM_ON_ENUM_NOT_ALLOWED = "itdmOnEnumNotAllowed"; | |||
public static final String ITDF_ON_ENUM_NOT_ALLOWED = "itdfOnEnumNotAllowed"; | |||
public static final String CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE = "cantDecpOnEnumToImplInterface"; | |||
public static final String CANT_DECP_ON_ENUM_TO_EXTEND_CLASS = "cantDecpOnEnumToExtendClass"; | |||
public static final String CANT_DECP_TO_MAKE_ENUM_SUPERTYPE = "cantDecpToMakeEnumSupertype"; | |||
public static final String ITDC_ON_ANNOTATION_NOT_ALLOWED = "itdcOnAnnotationNotAllowed"; | |||
public static final String ITDM_ON_ANNOTATION_NOT_ALLOWED = "itdmOnAnnotationNotAllowed"; | |||
public static final String ITDF_ON_ANNOTATION_NOT_ALLOWED = "itdfOnAnnotationNotAllowed"; | |||
public static final String CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE = "cantDecpOnAnnotationToImplInterface"; | |||
public static final String CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS = "cantDecpOnAnnotationToExtendClass"; | |||
public static final String CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE = "cantDecpToMakeAnnotationSupertype"; | |||
public static final String REFERENCE_TO_NON_ANNOTATION_TYPE = "referenceToNonAnnotationType"; | |||
public static final String BINDING_NON_RUNTIME_RETENTION_ANNOTATION = "bindingNonRuntimeRetentionAnnotation"; | |||
public static final String INCORRECT_TARGET_FOR_DECLARE_ANNOTATION = "incorrectTargetForDeclareAnnotation"; | |||
public static final String NO_MATCH_BECAUSE_SOURCE_RETENTION = "noMatchBecauseSourceRetention"; | |||
// Annotation Value messages | |||
public static final String INVALID_ANNOTATION_VALUE = "invalidAnnotationValue"; | |||
public static final String UNKNOWN_ANNOTATION_VALUE = "unknownAnnotationValue"; | |||
// < Java5 messages | |||
public static final String ATANNOTATION_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atannotationNeedsJava5"; | |||
public static final String ATWITHIN_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atwithinNeedsJava5"; | |||
public static final String ATWITHINCODE_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atwithincodeNeedsJava5"; | |||
public static final String ATTHIS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atthisNeedsJava5"; | |||
public static final String ATTARGET_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "attargetNeedsJava5"; | |||
public static final String ATARGS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atargsNeedsJava5"; | |||
public static final String DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtTypeNeedsJava5"; | |||
public static final String DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtMethodNeedsJava5"; | |||
public static final String DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtFieldNeedsJava5"; | |||
public static final String DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtConsNeedsJava5"; | |||
public static final String ANNOTATIONS_NEED_JAVA5 = "annotationsRequireJava5"; | |||
// Generics | |||
public static final String CANT_DECP_MULTIPLE_PARAMETERIZATIONS="cantDecpMultipleParameterizations"; | |||
public static final String HANDLER_PCD_DOESNT_SUPPORT_PARAMETERS="noParameterizedTypePatternInHandler"; | |||
public static final String INCORRECT_NUMBER_OF_TYPE_ARGUMENTS = "incorrectNumberOfTypeArguments"; | |||
public static final String VIOLATES_TYPE_VARIABLE_BOUNDS = "violatesTypeVariableBounds"; | |||
public static final String NO_STATIC_INIT_JPS_FOR_PARAMETERIZED_TYPES = "noStaticInitJPsForParameterizedTypes"; | |||
public static final String NOT_A_GENERIC_TYPE="notAGenericType"; | |||
public static final String WITHIN_PCD_DOESNT_SUPPORT_PARAMETERS="noParameterizedTypePatternInWithin"; | |||
public static final String THIS_AND_TARGET_DONT_SUPPORT_PARAMETERS="noParameterizedTypesInThisAndTarget"; | |||
public static final String GET_AND_SET_DONT_SUPPORT_DEC_TYPE_PARAMETERS="noParameterizedTypesInGetAndSet"; | |||
public static final String NO_INIT_JPS_FOR_PARAMETERIZED_TYPES = "noInitJPsForParameterizedTypes"; | |||
public static final String NO_GENERIC_THROWABLES = "noGenericThrowables"; | |||
public static final String WITHINCODE_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesWithinCode"; | |||
public static final String EXECUTION_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesInExecution"; | |||
public static final String CALL_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesInCall"; | |||
public static final String CANT_REFERENCE_POINTCUT_IN_RAW_TYPE="noRawTypePointcutReferences"; | |||
public static final String HAS_MEMBER_NOT_ENABLED="hasMemberNotEnabled"; | |||
// @AspectJ | |||
public static final String RETURNING_FORMAL_NOT_DECLARED_IN_ADVICE = "returningFormalNotDeclaredInAdvice"; | |||
public static final String THROWN_FORMAL_NOT_DECLARED_IN_ADVICE = "thrownFormalNotDeclaredInAdvice"; | |||
public static String format(String key) { | |||
return bundle.getString(key); | |||
} | |||
public static String format(String key, Object insert) { | |||
return MessageFormat.format(bundle.getString(key),new Object[] {insert}); | |||
} | |||
public static String format(String key, Object insert1, Object insert2) { | |||
return MessageFormat.format(bundle.getString(key),new Object[] {insert1,insert2}); | |||
} | |||
public static String format(String key, Object insert1, Object insert2, Object insert3) { | |||
return MessageFormat.format(bundle.getString(key),new Object[] {insert1, insert2, insert3}); | |||
} | |||
public static String format(String key, Object insert1, Object insert2, Object insert3, Object insert4) { | |||
return MessageFormat.format(bundle.getString(key),new Object[] {insert1, insert2, insert3, insert4}); | |||
} | |||
} |
@@ -0,0 +1,476 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipInputStream; | |||
import org.aspectj.bridge.IMessage; | |||
/** | |||
* WeaverStateInfo represents how a type was processed. It is used by the weaver to determine how a type was previously treated and | |||
* whether reweaving is allowed. The format in the data stream is: | |||
* | |||
* Byte: Kind. UNTOUCHED|WOVEN|EXTENDED - If extended it can have two extra bits set 'REWEAVABLE' and 'REWEAVABLE_COMPRESSION_BIT' | |||
* Short: typeMungerCount - how many type mungers have affected this type <UnresolvedType & ResolvedTypeMunger>: The type mungers | |||
* themselves If we are reweavable then we also have: Short: Number of aspects that touched this type in some way when it was | |||
* previously woven <String> The fully qualified name of each type Int: Length of class file data (i.e. the unwovenclassfile) | |||
* Byte[]: The class file data, compressed if REWEAVABLE_COMPRESSION_BIT set. | |||
*/ | |||
public class WeaverStateInfo { | |||
private List/* Entry */typeMungers; | |||
private boolean oldStyle; | |||
private boolean reweavable; | |||
private boolean reweavableCompressedMode; // If true, unwovenClassFile is uncompressed on read | |||
private boolean reweavableDiffMode; // if true, unwovenClassFile is written and read as a diff | |||
private Set /* String */aspectsAffectingType; // These must exist in the world for reweaving to be valid | |||
private byte[] unwovenClassFile; // Original 'untouched' class file | |||
private static boolean reweavableDefault = true; // ajh02: changed from false; | |||
private static boolean reweavableCompressedModeDefault = false; | |||
private static boolean reweavableDiffModeDefault = true; | |||
// when serializing the WeaverStateInfo we come to adding the reweavable data, | |||
// we'd like to add a diff of the unwovenClassFile and the wovenClassFile, | |||
// but we don't have the wovenClassFile yet as we're still in the process of making it. | |||
// so we put this key there instead as a stub. | |||
// Then when the wovenClassFile has been made, replaceKeyWithDiff is called. | |||
private static byte[] key = { -51, 34, 105, 56, -34, 65, 45, 78, -26, 125, 114, 97, 98, 1, -1, -42 }; | |||
private boolean unwovenClassFileIsADiff = false; | |||
private WeaverStateInfo() { | |||
// this(new ArrayList(), false,reweavableDefault,reweavableCompressedModeDefault,reweavableDiffModeDefault); | |||
} | |||
public WeaverStateInfo(boolean reweavable) { | |||
this(new ArrayList(), false, reweavable, reweavableCompressedModeDefault, reweavableDiffModeDefault); | |||
} | |||
private WeaverStateInfo(List typeMungers, boolean oldStyle, boolean reweavableMode, boolean reweavableCompressedMode, | |||
boolean reweavableDiffMode) { | |||
this.typeMungers = typeMungers; | |||
this.oldStyle = oldStyle; | |||
this.reweavable = reweavableMode; | |||
this.reweavableCompressedMode = reweavableCompressedMode; | |||
this.reweavableDiffMode = reweavableMode ? reweavableDiffMode : false; | |||
this.aspectsAffectingType = new HashSet(); | |||
this.unwovenClassFile = null; | |||
} | |||
public static void setReweavableModeDefaults(boolean mode, boolean compress, boolean diff) { | |||
reweavableDefault = mode; | |||
reweavableCompressedModeDefault = compress; | |||
reweavableDiffModeDefault = diff; | |||
} | |||
private static final int UNTOUCHED = 0, WOVEN = 2, EXTENDED = 3; | |||
// Use 'bits' for these capabilities - only valid in EXTENDED mode | |||
private static final byte REWEAVABLE_BIT = 1 << 4; | |||
private static final byte REWEAVABLE_COMPRESSION_BIT = 1 << 5; | |||
private static final byte REWEAVABLE_DIFF_BIT = 1 << 6; | |||
/** See comments on write() */ | |||
public static final WeaverStateInfo read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
byte b = s.readByte(); | |||
boolean isReweavable = ((b & REWEAVABLE_BIT) != 0); | |||
if (isReweavable) { | |||
b = (byte) (b - REWEAVABLE_BIT); | |||
} | |||
boolean isReweavableCompressed = ((b & REWEAVABLE_COMPRESSION_BIT) != 0); | |||
if (isReweavableCompressed) { | |||
b = (byte) (b - REWEAVABLE_COMPRESSION_BIT); | |||
} | |||
boolean isReweavableDiff = ((b & REWEAVABLE_DIFF_BIT) != 0); | |||
if (isReweavableDiff) { | |||
b = (byte) (b - REWEAVABLE_DIFF_BIT); | |||
} | |||
switch (b) { | |||
case UNTOUCHED: | |||
throw new RuntimeException("unexpected UNWOVEN"); | |||
case WOVEN: | |||
return new WeaverStateInfo(Collections.EMPTY_LIST, true, isReweavable, isReweavableCompressed, isReweavableDiff); | |||
case EXTENDED: | |||
int n = s.readShort(); | |||
List l = new ArrayList(); | |||
for (int i = 0; i < n; i++) { | |||
UnresolvedType aspectType = UnresolvedType.read(s); | |||
ResolvedTypeMunger typeMunger = ResolvedTypeMunger.read(s, context); | |||
l.add(new Entry(aspectType, typeMunger)); | |||
} | |||
WeaverStateInfo wsi = new WeaverStateInfo(l, false, isReweavable, isReweavableCompressed, isReweavableDiff); | |||
readAnyReweavableData(wsi, s); | |||
return wsi; | |||
} | |||
throw new RuntimeException("bad WeaverState.Kind: " + b + ". File was :" | |||
+ (context == null ? "unknown" : context.makeSourceLocation(0, 0).toString())); | |||
} | |||
private static class Entry { | |||
public UnresolvedType aspectType; | |||
public ResolvedTypeMunger typeMunger; | |||
public Entry(UnresolvedType aspectType, ResolvedTypeMunger typeMunger) { | |||
this.aspectType = aspectType; | |||
this.typeMunger = typeMunger; | |||
} | |||
public String toString() { | |||
return "<" + aspectType + ", " + typeMunger + ">"; | |||
} | |||
} | |||
/** | |||
* Serialize the WeaverStateInfo. Various bits are set within the 'kind' flag to indicate the structure of the attribute. In | |||
* reweavable diff mode a 'marker' is inserted at the start of the attribute to indicate where the final calculated diff should | |||
* be inserted. When the key is replaced with the diff, the 'kind' byte moves to the front of the attribute - thats why in the | |||
* read logic you'll see it expecting the kind as the first byte. | |||
*/ | |||
public void write(DataOutputStream s) throws IOException { | |||
if (oldStyle || reweavableCompressedMode) { | |||
throw new RuntimeException("shouldn't be writing this"); | |||
} | |||
byte weaverStateInfoKind = EXTENDED; | |||
if (reweavable) | |||
weaverStateInfoKind |= REWEAVABLE_BIT; | |||
if (reweavableDiffMode) { | |||
s.write(key); // put key in so we can replace it with the diff later | |||
weaverStateInfoKind |= REWEAVABLE_DIFF_BIT; | |||
} | |||
s.writeByte(weaverStateInfoKind); | |||
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); | |||
} | |||
writeAnyReweavableData(this, s); | |||
} | |||
public void addConcreteMunger(ConcreteTypeMunger munger) { | |||
typeMungers.add(new Entry(munger.getAspectType(), munger.getMunger())); | |||
} | |||
public String toString() { | |||
return "WeaverStateInfo(" + typeMungers + ", " + oldStyle + ")"; | |||
} | |||
public List getTypeMungers(ResolvedType onType) { | |||
World world = onType.getWorld(); | |||
List ret = new ArrayList(); | |||
for (Iterator i = typeMungers.iterator(); i.hasNext();) { | |||
Entry entry = (Entry) i.next(); | |||
ResolvedType aspectType = world.resolve(entry.aspectType, true); | |||
if (aspectType.isMissing()) { | |||
world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ASPECT_NEEDED, entry.aspectType, onType), | |||
onType.getSourceLocation(), null); | |||
continue; | |||
} | |||
ret.add(new TemporaryTypeMunger(entry.typeMunger, aspectType)); | |||
} | |||
return ret; | |||
} | |||
public boolean isOldStyle() { | |||
return oldStyle; | |||
} | |||
public byte[] getUnwovenClassFileData(byte wovenClassFile[]) { | |||
if (unwovenClassFileIsADiff) { | |||
unwovenClassFile = applyDiff(wovenClassFile, unwovenClassFile); | |||
unwovenClassFileIsADiff = false; | |||
} | |||
return unwovenClassFile; | |||
} | |||
public void setUnwovenClassFileData(byte[] data) { | |||
unwovenClassFile = data; | |||
} | |||
public boolean isReweavable() { | |||
return reweavable; | |||
} | |||
public void setReweavable(boolean rw) { | |||
reweavable = rw; | |||
} | |||
public void addAspectsAffectingType(Collection /* String */aspects) { | |||
aspectsAffectingType.addAll(aspects); | |||
} | |||
public void addAspectAffectingType(String aspectType) { | |||
aspectsAffectingType.add(aspectType); | |||
} | |||
public Set /* String */getAspectsAffectingType() { | |||
return this.aspectsAffectingType; | |||
} | |||
private static void readAnyReweavableData(WeaverStateInfo wsi, DataInputStream s) throws IOException { | |||
if (wsi.isReweavable()) { | |||
// Load list of aspects that need to exist in the world for reweaving to be 'legal' | |||
int numberAspectsAffectingType = s.readShort(); | |||
for (int i = 0; i < numberAspectsAffectingType; i++) { | |||
wsi.addAspectAffectingType(s.readUTF()); | |||
} | |||
int unwovenClassFileSize = s.readInt(); | |||
byte[] classData = null; | |||
// the unwovenClassFile may have been compressed: | |||
if (wsi.reweavableCompressedMode) { | |||
classData = new byte[unwovenClassFileSize]; | |||
ZipInputStream zis = new ZipInputStream(s); | |||
ZipEntry zen = zis.getNextEntry(); | |||
int current = 0; | |||
int bytesToGo = unwovenClassFileSize; | |||
while (bytesToGo > 0) { | |||
int amount = zis.read(classData, current, bytesToGo); | |||
current += amount; | |||
bytesToGo -= amount; | |||
} | |||
zis.closeEntry(); | |||
if (bytesToGo != 0) | |||
throw new IOException("ERROR whilst reading compressed reweavable data, expected " + unwovenClassFileSize | |||
+ " bytes, only found " + current); | |||
} else { | |||
classData = new byte[unwovenClassFileSize]; | |||
int bytesread = s.read(classData); | |||
if (bytesread != unwovenClassFileSize) | |||
throw new IOException("ERROR whilst reading reweavable data, expected " + unwovenClassFileSize | |||
+ " bytes, only found " + bytesread); | |||
} | |||
// if it was diffMode we'll have to remember to apply the diff if someone | |||
// asks for the unwovenClassFile | |||
wsi.unwovenClassFileIsADiff = wsi.reweavableDiffMode; | |||
wsi.setUnwovenClassFileData(classData); | |||
} | |||
} | |||
/** | |||
* Here is the cleverness for reweavable diff mode. The class file on disk contains, inside the weaverstateinfo attribute, a | |||
* diff that can be applied to 'itself' to recover the original class - which can then be rewoven. | |||
*/ | |||
public byte[] replaceKeyWithDiff(byte wovenClassFile[]) { | |||
// we couldn't have made the diff earlier | |||
// as we didn't have the wovenClassFile | |||
// so we left a key there as a marker to come back to | |||
if (reweavableDiffMode) { | |||
ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); | |||
DataOutputStream s = new DataOutputStream(arrayStream); | |||
int endOfKey = findEndOfKey(wovenClassFile); | |||
int startOfKey = endOfKey - key.length; | |||
// the length of the wsi attribute is written infront of it in the classFile, | |||
// swapping the diff for the key will probably change the length of the wsi, | |||
// so we'll have to fiddle with the four 'int length' bytes | |||
int oldLengthLocation = startOfKey - 4; | |||
int oldLength = readInt(wovenClassFile, oldLengthLocation); | |||
wovenClassFile = deleteInArray(wovenClassFile, startOfKey, endOfKey); // delete the key | |||
byte[] wovenClassFileUpToWSI = new byte[oldLengthLocation]; | |||
System.arraycopy(wovenClassFile, 0, wovenClassFileUpToWSI, 0, oldLengthLocation); | |||
byte[] diff = generateDiff(wovenClassFileUpToWSI, unwovenClassFile); | |||
try { // put the length of the diff infront of the diff | |||
s.writeInt(diff.length); | |||
s.write(diff); | |||
} catch (IOException e) { | |||
} | |||
diff = arrayStream.toByteArray(); | |||
// we have to swap the oldLength for the new one, | |||
// and add the diff, using the oldLength to work out where it should go :) | |||
int newLength = oldLength - key.length + diff.length; | |||
byte newLengthBytes[] = serializeInt(newLength); | |||
// swap in the serialized newLength for the oldOne: | |||
wovenClassFile[oldLengthLocation] = newLengthBytes[0]; | |||
wovenClassFile[oldLengthLocation + 1] = newLengthBytes[1]; | |||
wovenClassFile[oldLengthLocation + 2] = newLengthBytes[2]; | |||
wovenClassFile[oldLengthLocation + 3] = newLengthBytes[3]; | |||
// add the diff | |||
wovenClassFile = insertArray(diff, wovenClassFile, oldLengthLocation + 4 + oldLength - key.length); | |||
} | |||
return wovenClassFile; | |||
} | |||
private static final int findEndOfKey(byte[] wovenClassFile) { | |||
// looks through the classfile backwards (as the attributes are all near the end) | |||
for (int i = wovenClassFile.length - 1; i > 0; i--) | |||
if (endOfKeyHere(wovenClassFile, i)) { | |||
return i + 1; | |||
} | |||
throw new RuntimeException("key not found in wovenClassFile"); // should never happen | |||
} | |||
private static final boolean endOfKeyHere(byte lookIn[], int i) { | |||
for (int j = 0; j < key.length; j++) | |||
if (key[key.length - 1 - j] != lookIn[i - j]) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
private static final byte[] insertArray(byte toInsert[], byte original[], int offset) { | |||
byte result[] = new byte[original.length + toInsert.length]; | |||
System.arraycopy(original, 0, result, 0, offset); | |||
System.arraycopy(toInsert, 0, result, offset, toInsert.length); | |||
System.arraycopy(original, offset, result, offset + toInsert.length, original.length - offset); | |||
return result; | |||
} | |||
private static final int readInt(byte[] a, int offset) { | |||
ByteArrayInputStream b = new ByteArrayInputStream(a, offset, 4); | |||
DataInputStream d = new DataInputStream(b); | |||
int length = -1; | |||
try { | |||
length = d.readInt(); | |||
} catch (IOException e) { | |||
throw (new RuntimeException("readInt called with a bad array or offset")); // should never happen | |||
} | |||
return length; | |||
} | |||
private static final byte[] deleteInArray(byte a[], int start, int end) { | |||
int lengthToDelete = end - start; | |||
byte result[] = new byte[a.length - lengthToDelete]; // make a new array | |||
System.arraycopy(a, 0, result, 0, start); // copy in the bit before the deleted bit | |||
System.arraycopy(a, end, result, start, a.length - end); // copy in the bit after the deleted bit | |||
return result; | |||
} | |||
// ajh02: a quick note about the diff format... | |||
// | |||
// classfiles consist of: | |||
// 8 bytes: magic number and minor and major versions, | |||
// 2 bytes: its constant pool count | |||
// n bytes: the rest of the class file | |||
// | |||
// weaving a classfile never changes the classfile's first 8 bytes, | |||
// and after the constant pool count there's usually a run of bytes that weaving didn't change | |||
// hereafter referred to as the run | |||
// | |||
// so the diff consists of: | |||
// 2 bytes: its constant pool count | |||
// 4 bytes: length of the run | |||
// n bytes: the rest of the unwovenClassFile | |||
byte[] generateDiff(byte[] wovenClassFile, byte[] unWovenClassFile) { | |||
// find how long the run is | |||
int lookingAt = 10; | |||
int shorterLength = (wovenClassFile.length < unWovenClassFile.length) ? wovenClassFile.length : unWovenClassFile.length; | |||
while (lookingAt < shorterLength && (wovenClassFile[lookingAt] == unWovenClassFile[lookingAt])) { | |||
lookingAt++; | |||
} | |||
int lengthInCommon = lookingAt - 10; | |||
byte[] diff = new byte[unWovenClassFile.length - 4 - lengthInCommon]; | |||
// first 2 bytes of the diff are the constant pool count | |||
diff[0] = unWovenClassFile[8]; | |||
diff[1] = unWovenClassFile[9]; | |||
// then 4 bytes saying how long the run is | |||
byte[] lengthInCommonBytes = serializeInt(lengthInCommon); | |||
diff[2] = lengthInCommonBytes[0]; | |||
diff[3] = lengthInCommonBytes[1]; | |||
diff[4] = lengthInCommonBytes[2]; | |||
diff[5] = lengthInCommonBytes[3]; | |||
// then we just dump the rest of the unWovenClassFile verbatim | |||
System.arraycopy(unWovenClassFile, 10 + lengthInCommon, diff, 6, diff.length - 6); | |||
return diff; | |||
} | |||
byte[] applyDiff(byte[] wovenClassFile, byte[] diff) { | |||
int lengthInCommon = readInt(diff, 2); | |||
byte[] unWovenClassFile = new byte[4 + diff.length + lengthInCommon]; | |||
// copy the first 8 bytes from the wovenClassFile | |||
System.arraycopy(wovenClassFile, 0, unWovenClassFile, 0, 8); | |||
// copy the constant pool count from the diff | |||
unWovenClassFile[8] = diff[0]; | |||
unWovenClassFile[9] = diff[1]; | |||
// copy the run from the wovenClassFile | |||
System.arraycopy(wovenClassFile, 10, unWovenClassFile, 10, lengthInCommon); | |||
// copy the stuff after the run from the diff | |||
System.arraycopy(diff, 6, unWovenClassFile, 10 + lengthInCommon, diff.length - 6); | |||
return unWovenClassFile; | |||
} | |||
private byte[] serializeInt(int i) { | |||
ByteArrayOutputStream bos = new ByteArrayOutputStream(4); | |||
DataOutputStream dos = new DataOutputStream(bos); | |||
try { | |||
dos.writeInt(i); | |||
} catch (IOException e) { | |||
} | |||
return bos.toByteArray(); | |||
} | |||
private static void writeAnyReweavableData(WeaverStateInfo wsi, DataOutputStream s) throws IOException { | |||
if (wsi.isReweavable()) { | |||
// Write out list of aspects that must exist next time we try and weave this class | |||
s.writeShort(wsi.aspectsAffectingType.size()); | |||
if (wsi.aspectsAffectingType.size() > 0) { | |||
for (Iterator iter = wsi.aspectsAffectingType.iterator(); iter.hasNext();) { | |||
String type = (String) iter.next(); | |||
s.writeUTF(type); | |||
} | |||
} | |||
byte[] data = wsi.unwovenClassFile; | |||
// if we're not in diffMode, write the unwovenClassFile now, | |||
// otherwise we'll insert it as a diff later | |||
if (!wsi.reweavableDiffMode) { | |||
s.writeInt(data.length); | |||
s.write(wsi.unwovenClassFile); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
/** | |||
* Represents a wildcarded bound for a generic type, this can be unbounded '?' or bounded via extends '? extends Foo' or | |||
* super '? super Foo'. The signature for a ? is in fact "*" and the erasure signature is the upper bound which defaults | |||
* to java.lang.Object if nothing is specified. On resolution, this becomes a BoundedReferenceType | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class WildcardedUnresolvedType extends UnresolvedType { | |||
// TODO does not cope with extra bounds '? extends A & B & C' | |||
public static final int UNBOUND = 0; | |||
public static final int EXTENDS = 1; | |||
public static final int SUPER = 2; | |||
public static final WildcardedUnresolvedType QUESTIONMARK = new WildcardedUnresolvedType("*", UnresolvedType.OBJECT, null); | |||
private int boundKind = UNBOUND; // UNBOUND, EXTENDS, SUPER | |||
private UnresolvedType lowerBound; | |||
private UnresolvedType upperBound; | |||
public WildcardedUnresolvedType(String signature, UnresolvedType upperBound, UnresolvedType lowerBound) { | |||
super(signature, (upperBound == null ? UnresolvedType.OBJECT.signature : upperBound.signatureErasure)); | |||
this.typeKind = TypeKind.WILDCARD; | |||
this.upperBound = upperBound; | |||
this.lowerBound = lowerBound; | |||
if (signature.charAt(0) == '-') boundKind = SUPER; | |||
if (signature.charAt(0) == '+') boundKind = EXTENDS; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public boolean isExtends() { | |||
return boundKind == EXTENDS; | |||
} | |||
public boolean isSuper() { | |||
return boundKind == SUPER; | |||
} | |||
public boolean isUnbound() { | |||
return boundKind == UNBOUND; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
invalidAbsoluteTypeName = warning | |||
invalidWildcardTypeName = ignore | |||
unresolvableMember = warning | |||
typeNotExposedToWeaver = warning | |||
shadowNotInStructure = ignore | |||
unmatchedSuperTypeInCall = warning | |||
canNotImplementLazyTjp = ignore | |||
multipleAdviceStoppingLazyTjp=ignore | |||
noGuardForLazyTjp=ignore | |||
uncheckedAdviceConversion = warning | |||
needsSerialVersionUIDField = ignore | |||
brokeSerialVersionCompatibility = ignore | |||
noInterfaceCtorJoinpoint = warning | |||
noJoinpointsForBridgeMethods = warning | |||
cantMatchArrayTypeOnVarargs = ignore | |||
enumAsTargetForDecpIgnored = warning | |||
annotationAsTargetForDecpIgnored = warning | |||
adviceDidNotMatch = warning | |||
invalidTargetForAnnotation = warning | |||
elementAlreadyAnnotated = warning | |||
runtimeExceptionNotSoftened = warning | |||
uncheckedArgument = warning | |||
noExplicitConstructorCall = warning | |||
aspectExcludedByConfiguration = ignore | |||
unmatchedTargetKind = warning | |||
cantFindType = error | |||
cantFindTypeAffectingJPMatch = warning | |||
unorderedAdviceAtShadow=ignore | |||
swallowedExceptionInCatchBlock=ignore | |||
calculatingSerialVersionUID=ignore | |||
advisingSynchronizedMethods=warning | |||
mustWeaveXmlDefinedAspects=warning | |||
missingAspectForReweaving=error |
@@ -0,0 +1,22 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
public abstract class ASTNode { | |||
public ASTNode() { | |||
super(); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
public class And extends Test { | |||
Test left, right; | |||
public And(Test left, Test right) { | |||
super(); | |||
this.left = left; | |||
this.right = right; | |||
} | |||
public void accept(ITestVisitor v) { | |||
v.visit(this); | |||
} | |||
public String toString() { | |||
return "(" + left + " && " + right + ")"; | |||
} | |||
public boolean equals(Object other) { | |||
if (other instanceof And) { | |||
And o = (And) other; | |||
return o.left.equals(left) && o.right.equals(right); | |||
} else { | |||
return false; | |||
} | |||
} | |||
public Test getLeft() { | |||
return left; | |||
} | |||
public Test getRight() { | |||
return right; | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.Member; | |||
public class Call extends Test { | |||
// assert m.return value is boolean | |||
private final Member method; | |||
private final Expr[] args; | |||
public Call(Member m, Expr[] args) { | |||
super(); | |||
this.method = m; | |||
this.args = args; | |||
} | |||
public void accept(ITestVisitor v) { | |||
v.visit(this); | |||
} | |||
public Expr[] getArgs() { | |||
return args; | |||
} | |||
public Member getMethod() { | |||
return method; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedType; | |||
public class CallExpr extends Expr { | |||
// assert m.return value is boolean | |||
private final Member method; | |||
private final Expr[] args; | |||
private final ResolvedType returnType; // yes, stored in method as well, but that one isn't resolved | |||
public CallExpr(Member m, Expr[] args, ResolvedType returnType) { | |||
super(); | |||
this.method = m; | |||
this.args = args; | |||
this.returnType = returnType; | |||
} | |||
public void accept(IExprVisitor v) { | |||
v.visit(this); | |||
} | |||
public Expr[] getArgs() { | |||
return args; | |||
} | |||
public Member getMethod() { | |||
return method; | |||
} | |||
public ResolvedType getType() { | |||
return returnType; | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedType; | |||
public abstract class Expr extends ASTNode { | |||
public Expr() { | |||
super(); | |||
} | |||
public static final Expr[] NONE = new Expr[0]; | |||
public abstract void accept(IExprVisitor v); | |||
public abstract ResolvedType getType(); | |||
public static CallExpr makeCallExpr(Member member, Expr[] exprs, ResolvedType returnType) { | |||
return new CallExpr(member, exprs, returnType); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedType; | |||
public class FieldGet extends Expr { | |||
Member field; | |||
ResolvedType resolvedType; | |||
public FieldGet(Member field, ResolvedType resolvedType) { | |||
super(); | |||
this.field = field; | |||
this.resolvedType = resolvedType; | |||
} | |||
public ResolvedType getType() { | |||
return resolvedType; | |||
} | |||
public String toString() { | |||
return "(FieldGet " + field + ")"; | |||
} | |||
public void accept(IExprVisitor v) { | |||
v.visit(this); | |||
} | |||
public Member getField() { | |||
return field; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.Member; | |||
public class FieldGetCall extends Test { | |||
// assert m.return value is boolean | |||
private final Member field; | |||
private final Member method; | |||
private final Expr[] args; | |||
public FieldGetCall(Member f, Member m, Expr[] args) { | |||
super(); | |||
this.field = f; | |||
this.method = m; | |||
this.args = args; | |||
} | |||
public void accept(ITestVisitor v) { | |||
v.visit(this); | |||
} | |||
public Expr[] getArgs() { | |||
return args; | |||
} | |||
public Member getMethod() { | |||
return method; | |||
} | |||
public Member getField() { | |||
return field; | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM Corporation and others. | |||
* 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://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* IBM Corporation - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
public class HasAnnotation extends Test { | |||
private Var v; | |||
private ResolvedType annType; | |||
public HasAnnotation(Var v, ResolvedType annType) { | |||
super(); | |||
this.v = v; | |||
this.annType = annType; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ast.Test#accept(org.aspectj.weaver.ast.ITestVisitor) | |||
*/ | |||
public void accept(ITestVisitor v) { | |||
v.visit(this); | |||
} | |||
public String toString() { | |||
return "(" + v + " has annotation @" + annType + ")"; | |||
} | |||
public boolean equals(Object other) { | |||
if (other instanceof HasAnnotation) { | |||
HasAnnotation o = (HasAnnotation) other; | |||
return o.v.equals(v) && o.annType.equals(annType); | |||
} else { | |||
return false; | |||
} | |||
} | |||
public int hashCode() { | |||
return v.hashCode()*37+annType.hashCode(); | |||
} | |||
public Var getVar() { | |||
return v; | |||
} | |||
public UnresolvedType getAnnotationType() { | |||
return annType; | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
/* ******************************************************************* | |||
* 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 Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.ast; | |||
public interface IExprVisitor { | |||
void visit(Var i); | |||
void visit(FieldGet fieldGet); | |||
void visit(CallExpr callExpr); | |||
} |