Package org.aspectj.weaver

Source Code of org.aspectj.weaver.ResolvedTypeMunger$Kind

/* *******************************************************************
* 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.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<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");
      }
    }
    // 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) {
    if (onType == null) {
      onType = matchType.getWorld().resolve(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;
    }
  }

  // ----

  @Override
  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, 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 {
    // 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.
      byte b = 0;
      // if we aren't on 1.6.9 or we are on 1.6.9 but not compressed, then read as object stream
      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; // 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 final void writeSourceLocation(CompressingDataOutputStream s) throws IOException {
    if (s.canCompress()) {
      s.writeByte(1 + (location == null ? 0 : 1)); // 1==compressed no location 2==compressed with location
      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 {
    /* 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;
      case 11:
        return MethodDelegate2;
      case 12:
        return InnerClass;
      }
      throw new BCException("bad kind: " + key);
    }

    @Override
    public String toString() {
      // we want MethodDelegate to appear as Method in WeaveInfo messages
      // TODO we may want something for fieldhost ?
      if (getName().startsWith(MethodDelegate.getName())) {// startsWith will cover MethodDelegate2 as well
        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);
  // PTWIMPL not serialized, used during concretization of aspects
  public static final Kind PerTypeWithinInterface = new Kind("PerTypeWithinInterface", 7);
  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 Kind MethodDelegate2 = new Kind("MethodDelegate2", 11);// serialized, @AJ ITDs
  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 {
    // Write any type variable aliases
    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);
  }

  /**
   * 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<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();
  }

}
TOP

Related Classes of org.aspectj.weaver.ResolvedTypeMunger$Kind

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.