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.List;
import java.util.Map;
import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.TypeSafeEnum;
public abstract class ResolvedTypeMunger {
protected Kind kind;
protected ResolvedMember signature;
protected ResolvedMember declaredSignature;
protected List<String> typeVariableAliases;
private Set<ResolvedMember> superMethodsCalled = Collections.emptySet();
private ISourceLocation location;
private ResolvedType onType = null;
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");
}
}
}
public void setSourceLocation(ISourceLocation isl) {
location = isl;
}
public ISourceLocation getSourceLocation() {
return location;
}
public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
if (onType == null) {
onType = matchType.getWorld().resolve(getDeclaringType());
if (onType.isRawType()) {
onType = onType.getGenericType();
}
}
if (matchType.equals(onType)) {
if (!onType.isExposedToWeaver()) {
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;
}
if (onType.isInterface()) {
return matchType.isTopmostImplementor(onType);
} else {
return false;
}
}
@Override
public String toString() {
return "ResolvedTypeMunger(" + getKind() + ", " + getSignature() + ")";
}
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, false);
} else if (kind == FieldHost) {
return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context);
} else if (kind == MethodDelegate2) {
return MethodDelegateTypeMunger.readMethod(s, context, true);
} else if (kind == InnerClass) {
return NewMemberClassTypeMunger.readInnerClass(s, context);
} else {
throw new RuntimeException("unimplemented");
}
}
protected static Set<ResolvedMember> readSuperMethodsCalled(VersionedDataInputStream s) throws IOException {
Set<ResolvedMember> ret = new HashSet<ResolvedMember>();
int n = -1;
if (s.isAtLeast169()) {
n = s.readByte();
} else {
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 final void writeSuperMethodsCalled(CompressingDataOutputStream s) throws IOException {
if (superMethodsCalled == null || superMethodsCalled.size() == 0) {
s.writeByte(0);
return;
}
List<ResolvedMember> ret = new ArrayList<ResolvedMember>(superMethodsCalled);
Collections.sort(ret);
int n = ret.size();
s.writeByte(n);
for (ResolvedMember m : ret) {
m.write(s);
}
}
protected static ISourceLocation readSourceLocation(VersionedDataInputStream s) throws IOException {
if (s.getMajorVersion() < AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
return null;
}
SourceLocation ret = null;
ObjectInputStream ois = null;
try {
byte b = 0;
if (!s.isAtLeast169() || (b = s.readByte()) == 0) {
ois = new ObjectInputStream(s);
boolean validLocation = (Boolean) ois.readObject();
if (validLocation) {
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());
}
} else {
boolean validLocation = b == 2;
if (validLocation) {
String path = s.readUtf8(s.readShort());
File f = new File(path);
ret = new SourceLocation(f, s.readInt());
int offset = s.readInt();
ret.setOffset(offset);
}
}
} catch (EOFException eof) {
return null;
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
} finally {
if (ois != null) {
ois.close();
}
}
return ret;
}
protected final void writeSourceLocation(CompressingDataOutputStream s) throws IOException {
if (s.canCompress()) {
s.writeByte(1 + (location == null ? 0 : 1));
if (location != null) {
s.writeCompressedPath(location.getSourceFile().getPath());
s.writeInt(location.getLine());
s.writeInt(location.getOffset());
}
} else {
s.writeByte(0);
ObjectOutputStream oos = new ObjectOutputStream(s);
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(CompressingDataOutputStream s) throws IOException;
public Kind getKind() {
return kind;
}
public static class Kind extends TypeSafeEnum {
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;
case 11:
return MethodDelegate2;
case 12:
return InnerClass;
}
throw new BCException("bad kind: " + key);
}
@Override
public String toString() {
if (getName().startsWith(MethodDelegate.getName())) {
return Method.toString();
} else {
return super.toString();
}
}
}
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);
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);
public static final Kind AnnotationOnType = new Kind("AnnotationOnType", 8);
public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);
public static final Kind FieldHost = new Kind("FieldHost", 10);
public static final Kind MethodDelegate2 = new Kind("MethodDelegate2", 11);
public static final Kind InnerClass = new Kind("InnerClass", 12);
public static final String SUPER_DISPATCH_NAME = "superDispatch";
public void setSuperMethodsCalled(Set<ResolvedMember> c) {
this.superMethodsCalled = c;
}
public Set<ResolvedMember> 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<String> readInTypeAliases(VersionedDataInputStream s) throws IOException {
if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
int count = -1;
if (s.isAtLeast169()) {
count = s.readByte();
} else {
count = s.readInt();
}
if (count != 0) {
List<String> aliases = new ArrayList<String>();
for (int i = 0; i < count; i++) {
aliases.add(s.readUTF());
}
return aliases;
}
}
return null;
}
protected final void writeOutTypeAliases(DataOutputStream s) throws IOException {
if (typeVariableAliases == null || typeVariableAliases.size() == 0) {
s.writeByte(0);
} else {
s.writeByte(typeVariableAliases.size());
for (String element : typeVariableAliases) {
s.writeUTF(element);
}
}
}
public List<String> getTypeVariableAliases() {
return typeVariableAliases;
}
protected void setTypeVariableAliases(List<String> typeVariableAliases) {
this.typeVariableAliases = typeVariableAliases;
}
public boolean hasTypeVariableAliases() {
return (typeVariableAliases != null && typeVariableAliases.size() > 0);
}
public boolean sharesTypeVariablesWithGenericType() {
return (typeVariableAliases != null && typeVariableAliases.size() > 0);
}
public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
throw new BCException("Dont call parameterizedFor on a type munger of this kind: " + this.getClass());
}
public void setDeclaredSignature(ResolvedMember rm) {
declaredSignature = rm;
}
public ResolvedMember getDeclaredSignature() {
return declaredSignature;
}
public boolean isLateMunger() {
return false;
}
public boolean existsToSupportShadowMunging() {
return false;
}
public ResolvedTypeMunger parameterizeWith(Map<String, UnresolvedType> m, World w) {
throw new BCException("Dont call parameterizeWith() on a type munger of this kind: " + this.getClass());
}
public UnresolvedType getDeclaringType() {
return getSignature().getDeclaringType();
}
}