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 declaringType;
protected UnresolvedType returnType;
protected UnresolvedType[] parameterTypes;
private final String erasedSignature;
private String paramSignature;
private boolean reportedCantFindDeclaringType = false;
private boolean reportedUnresolvableMember = false;
private JoinPointSignatureIterator joinPointSignatures = null;
public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String erasedSignature) {
this.kind = kind;
this.declaringType = declaringType;
this.modifiers = modifiers;
this.name = name;
this.erasedSignature = erasedSignature;
if (kind == FIELD) {
this.returnType = UnresolvedType.forSignature(erasedSignature);
this.parameterTypes = UnresolvedType.NONE;
} else {
Object[] returnAndParams = signatureToTypes(erasedSignature);
this.returnType = (UnresolvedType) returnAndParams[0];
this.parameterTypes = (UnresolvedType[]) returnAndParams[1];
}
}
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.erasedSignature = returnType.getErasureSignature();
} else {
this.erasedSignature = typesToSignature(returnType, parameterTypes, true);
}
}
public ResolvedMember resolve(World world) {
return world.resolve(this);
}
public static String typesToSignature(UnresolvedType returnType, UnresolvedType[] paramTypes, boolean eraseGenerics) {
StringBuilder buf = new StringBuilder();
buf.append("(");
for (UnresolvedType paramType : paramTypes) {
if (eraseGenerics) {
buf.append(paramType.getErasureSignature());
} else {
buf.append(paramType.getSignature());
}
}
buf.append(")");
if (eraseGenerics) {
buf.append(returnType.getErasureSignature());
} else {
buf.append(returnType.getSignature());
}
return buf.toString();
}
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();
}
private static Object[] signatureToTypes(String sig) {
boolean hasParameters = sig.charAt(1) != ')';
if (hasParameters) {
List<UnresolvedType> l = new ArrayList<UnresolvedType>();
int i = 1;
boolean hasAnyAnglies = sig.indexOf('<') != -1;
while (true) {
char c = sig.charAt(i);
if (c == ')') {
break;
}
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 {
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++;
}
i = posn;
l.add(UnresolvedType.forSignature(sig.substring(start, i)));
}
} else if (c == 'T') {
int nextSemicolon = sig.indexOf(';', start);
String nextbit = sig.substring(start, nextSemicolon + 1);
l.add(UnresolvedType.forSignature(nextbit));
i = nextSemicolon + 1;
} else {
i++;
l.add(UnresolvedType.forSignature(sig.substring(start, i)));
}
}
UnresolvedType[] paramTypes = 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 };
}
}
public static MemberImpl field(String declaring, int mods, String name, String signature) {
return field(declaring, mods, UnresolvedType.forSignature(signature), name);
}
public static MemberImpl method(UnresolvedType declaring, int mods, String name, String signature) {
Object[] pair = signatureToTypes(signature);
return method(declaring, mods, (UnresolvedType) pair[0], name, (UnresolvedType[]) pair[1]);
}
public static MemberImpl monitorEnter() {
return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT, Modifier.STATIC, UnresolvedType.VOID, "<lock>",
UnresolvedType.ARRAY_WITH_JUST_OBJECT);
}
public static MemberImpl monitorExit() {
return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT, Modifier.STATIC, UnresolvedType.VOID, "<unlock>",
UnresolvedType.ARRAY_WITH_JUST_OBJECT);
}
public static Member pointcut(UnresolvedType declaring, String name, String signature) {
Object[] pair = signatureToTypes(signature);
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(
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");
}
@Override
public final 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()));
}
public final boolean equalsApartFromDeclaringType(Object other) {
if (!(other instanceof Member)) {
return false;
}
Member o = (Member) other;
return (getKind() == o.getKind() && getName().equals(o.getName()) && getSignature().equals(o.getSignature()));
}
private volatile int hashCode = 0;
@Override
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(Member other) {
Member o = other;
int i = getName().compareTo(o.getName());
if (i != 0) {
return i;
}
return getSignature().compareTo(o.getSignature());
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(returnType.getName());
buf.append(' ');
if (declaringType == null) {
buf.append("<NULL>");
} else {
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 erasedSignature;
}
public int getArity() {
return parameterTypes.length;
}
public String getParameterSignature() {
if (paramSignature == null) {
StringBuilder sb = new StringBuilder("(");
for (UnresolvedType parameterType : parameterTypes) {
sb.append(parameterType.getSignature());
}
paramSignature = sb.append(")").toString();
}
return paramSignature;
}
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...");
}
public Collection<ResolvedType> getDeclaringTypes(World world) {
ResolvedType myType = getDeclaringType().resolve(world);
Collection<ResolvedType> ret = new HashSet<ResolvedType>();
if (kind == CONSTRUCTOR) {
ret.add(myType);
} else if (Modifier.isStatic(modifiers) || kind == FIELD) {
walkUpStatic(ret, myType);
} else {
walkUp(ret, myType);
}
return ret;
}
private boolean walkUp(Collection<ResolvedType> acc, ResolvedType curr) {
if (acc.contains(curr)) {
return true;
}
boolean b = false;
for (Iterator<ResolvedType> i = curr.getDirectSupertypes(); i.hasNext();) {
b |= walkUp(acc, 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<ResolvedType> acc, ResolvedType curr) {
if (curr.lookupMemberNoSupers(this) != null) {
acc.add(curr);
return true;
} else {
boolean b = false;
for (Iterator<ResolvedType> i = curr.getDirectSupertypes(); i.hasNext();) {
b |= walkUpStatic(acc, 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();
}
public JoinPointSignatureIterator getJoinPointSignatures(World inAWorld) {
if (joinPointSignatures == null) {
joinPointSignatures = new JoinPointSignatureIterator(this, inAWorld);
}
joinPointSignatures.reset();
return joinPointSignatures;
}
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;
}
}