123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * 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.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");
- }
- }
-
- 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();
- 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;
- }
- }
|