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 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;
  }
}
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.