You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ResolvedTypeMunger.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur @AspectJ ITDs
  12. * ******************************************************************/
  13. package org.aspectj.weaver;
  14. import java.io.DataInputStream;
  15. import java.io.DataOutputStream;
  16. import java.io.EOFException;
  17. import java.io.File;
  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.io.ObjectOutputStream;
  21. import java.util.ArrayList;
  22. import java.util.Collections;
  23. import java.util.HashSet;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Set;
  27. import org.aspectj.bridge.ISourceLocation;
  28. import org.aspectj.bridge.SourceLocation;
  29. import org.aspectj.util.TypeSafeEnum;
  30. /** This is an abstraction over method/field introduction. It might not have the chops
  31. * to handle other inter-type declarations. This is the thing that is used on the
  32. * eclipse side and serialized into a ConcreteTypeMunger.
  33. */
  34. public abstract class ResolvedTypeMunger {
  35. protected Kind kind;
  36. protected ResolvedMember signature;
  37. /**
  38. * The declared signature is filled in when a type munger is parameterized for application to
  39. * a particular type. It represents the signature originally declared in the source file.
  40. */
  41. protected ResolvedMember declaredSignature;
  42. // This list records the occurences (in order) of any names specified in the <>
  43. // for a target type for the ITD. So for example, for List<C,B,A> this list
  44. // will be C,B,A - the list is used later to map other occurrences of C,B,A
  45. // across the intertype declaration to the right type variables in the generic
  46. // type upon which the itd is being made.
  47. // might need serializing the class file for binary weaving.
  48. protected List /*String*/ typeVariableAliases;
  49. private Set /* resolvedMembers */ superMethodsCalled = Collections.EMPTY_SET;
  50. private ISourceLocation location; // Lost during serialize/deserialize !
  51. public ResolvedTypeMunger(Kind kind, ResolvedMember signature) {
  52. this.kind = kind;
  53. this.signature = signature;
  54. UnresolvedType declaringType = signature != null ? signature.getDeclaringType() : null;
  55. if (declaringType != null) {
  56. if (declaringType.isRawType()) throw new IllegalStateException("Use generic type, not raw type");
  57. if (declaringType.isParameterizedType()) throw new IllegalStateException("Use generic type, not parameterized type");
  58. }
  59. }
  60. public void setSourceLocation(ISourceLocation isl) {
  61. location = isl;
  62. }
  63. public ISourceLocation getSourceLocation() {
  64. return location;
  65. }
  66. // ----
  67. // fromType is guaranteed to be a non-abstract aspect
  68. public ConcreteTypeMunger concretize(World world, ResolvedType aspectType) {
  69. ConcreteTypeMunger munger = world.concreteTypeMunger(this, aspectType);
  70. return munger;
  71. }
  72. public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
  73. ResolvedType onType = matchType.getWorld().resolve(signature.getDeclaringType());
  74. if (onType.isRawType()) onType = onType.getGenericType();
  75. //System.err.println("matching: " + this + " to " + matchType + " onType = " + onType);
  76. if (matchType.equals(onType)) {
  77. if (!onType.isExposedToWeaver()) {
  78. // if the onType is an interface, and it already has the member we are about
  79. // to munge, then this is ok...
  80. boolean ok = (onType.isInterface() && (onType.lookupMemberWithSupersAndITDs(getSignature()) != null));
  81. if (!ok && onType.getWeaverState() == null) {
  82. if (matchType.getWorld().getLint().typeNotExposedToWeaver.isEnabled()) {
  83. matchType.getWorld().getLint().typeNotExposedToWeaver.signal(
  84. matchType.getName(), signature.getSourceLocation());
  85. }
  86. }
  87. }
  88. return true;
  89. }
  90. //System.err.println("NO MATCH DIRECT");
  91. if (onType.isInterface()) {
  92. return matchType.isTopmostImplementor(onType);
  93. } else {
  94. return false;
  95. }
  96. }
  97. // ----
  98. public String toString() {
  99. return "ResolvedTypeMunger(" + getKind() + ", " + getSignature() +")";
  100. //.superMethodsCalled + ")";
  101. }
  102. // ----
  103. public static ResolvedTypeMunger read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  104. Kind kind = Kind.read(s);
  105. if (kind == Field) {
  106. return NewFieldTypeMunger.readField(s, context);
  107. } else if (kind == Method) {
  108. return NewMethodTypeMunger.readMethod(s, context);
  109. } else if (kind == Constructor) {
  110. return NewConstructorTypeMunger.readConstructor(s, context);
  111. } else if (kind == MethodDelegate) {
  112. return MethodDelegateTypeMunger.readMethod(s, context);
  113. } else if (kind == FieldHost) {
  114. return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context);
  115. } else {
  116. throw new RuntimeException("unimplemented");
  117. }
  118. }
  119. protected static Set readSuperMethodsCalled(VersionedDataInputStream s) throws IOException {
  120. Set ret = new HashSet();
  121. int n = s.readInt();
  122. if (n<0) throw new BCException("Problem deserializing type munger");
  123. for (int i=0; i < n; i++) {
  124. ret.add(ResolvedMemberImpl.readResolvedMember(s, null));
  125. }
  126. return ret;
  127. }
  128. protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException {
  129. if (superMethodsCalled == null || superMethodsCalled.size()==0) {
  130. s.writeInt(0);
  131. return;
  132. }
  133. List ret = new ArrayList(superMethodsCalled);
  134. Collections.sort(ret);
  135. int n = ret.size();
  136. s.writeInt(n);
  137. for (Iterator i = ret.iterator(); i.hasNext(); ) {
  138. ResolvedMember m = (ResolvedMember)i.next();
  139. m.write(s);
  140. }
  141. }
  142. protected static ISourceLocation readSourceLocation(VersionedDataInputStream s) throws IOException {
  143. // Location persistence for type mungers was added after 1.2.1 was shipped...
  144. if (s.getMajorVersion()<AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) return null;
  145. SourceLocation ret = null;
  146. ObjectInputStream ois = null;
  147. try {
  148. // This logic copes with the location missing from the attribute - an EOFException will
  149. // occur on the next line and we ignore it.
  150. ois = new ObjectInputStream(s);
  151. Boolean validLocation = (Boolean)ois.readObject();
  152. if (validLocation.booleanValue()) {
  153. File f = (File) ois.readObject();
  154. Integer ii = (Integer)ois.readObject();
  155. Integer offset = (Integer)ois.readObject();
  156. ret = new SourceLocation(f,ii.intValue());
  157. ret.setOffset(offset.intValue());
  158. }
  159. } catch (EOFException eof) {
  160. return null; // This exception occurs if processing an 'old style' file where the
  161. // type munger attributes don't include the source location.
  162. } catch (IOException ioe) {
  163. // Something went wrong, maybe this is an 'old style' file that doesnt attach locations to mungers?
  164. // (but I thought that was just an EOFException?)
  165. ioe.printStackTrace();
  166. return null;
  167. } catch (ClassNotFoundException e) {
  168. } finally {
  169. if (ois!=null) ois.close();
  170. }
  171. return ret;
  172. }
  173. protected void writeSourceLocation(DataOutputStream s) throws IOException {
  174. ObjectOutputStream oos = new ObjectOutputStream(s);
  175. // oos.writeObject(location);
  176. oos.writeObject(new Boolean(location!=null));
  177. if (location !=null) {
  178. oos.writeObject(location.getSourceFile());
  179. oos.writeObject(new Integer(location.getLine()));
  180. oos.writeObject(new Integer(location.getOffset()));
  181. }
  182. oos.flush();
  183. oos.close();
  184. }
  185. public abstract void write(DataOutputStream s) throws IOException;
  186. public Kind getKind() {
  187. return kind;
  188. }
  189. public static class Kind extends TypeSafeEnum {
  190. /* private */ Kind(String name, int key) {
  191. super(name, key);
  192. }
  193. public static Kind read(DataInputStream s) throws IOException {
  194. int key = s.readByte();
  195. switch(key) {
  196. case 1: return Field;
  197. case 2: return Method;
  198. case 5: return Constructor;
  199. case 9: return MethodDelegate;
  200. case 10: return FieldHost;
  201. }
  202. throw new BCException("bad kind: " + key);
  203. }
  204. public String toString() {
  205. // we want MethodDelegate to appear as Method in WeaveInfo messages
  206. //TODO we may want something for fieldhost ?
  207. if (MethodDelegate.getName().equals(getName())) {
  208. return Method.toString();
  209. } else {
  210. return super.toString();
  211. }
  212. }
  213. }
  214. // ---- fields
  215. public static final Kind Field = new Kind("Field", 1);
  216. public static final Kind Method = new Kind("Method", 2);
  217. public static final Kind Constructor = new Kind("Constructor", 5);
  218. // not serialized, only created during concretization of aspects
  219. public static final Kind PerObjectInterface = new Kind("PerObjectInterface", 3);
  220. public static final Kind PrivilegedAccess = new Kind("PrivilegedAccess", 4);
  221. public static final Kind Parent = new Kind("Parent", 6);
  222. public static final Kind PerTypeWithinInterface = new Kind("PerTypeWithinInterface",7); // PTWIMPL not serialized, used during concretization of aspects
  223. public static final Kind AnnotationOnType = new Kind("AnnotationOnType",8); // not serialized
  224. public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);// serialized, @AJ ITDs
  225. public static final Kind FieldHost = new Kind("FieldHost", 10);// serialized, @AJ ITDs
  226. public static final String SUPER_DISPATCH_NAME = "superDispatch";
  227. public void setSuperMethodsCalled(Set c) {
  228. this.superMethodsCalled = c;
  229. }
  230. public Set getSuperMethodsCalled() {
  231. return superMethodsCalled;
  232. }
  233. public ResolvedMember getSignature() {
  234. return signature;
  235. }
  236. // ----
  237. public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
  238. if ((getSignature() != null) && getSignature().isPublic() && member.equals(getSignature())) {
  239. return getSignature();
  240. }
  241. return null;
  242. }
  243. public boolean changesPublicSignature() {
  244. return kind == Field || kind == Method || kind == Constructor;
  245. }
  246. public boolean needsAccessToTopmostImplementor() {
  247. if (kind == Field) {
  248. return true;
  249. } else if (kind == Method) {
  250. return !signature.isAbstract();
  251. } else {
  252. return false;
  253. }
  254. }
  255. protected static List readInTypeAliases(VersionedDataInputStream s) throws IOException {
  256. if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  257. int count = s.readInt();
  258. List aliases = new ArrayList();
  259. for (int i=0;i<count;i++) {
  260. aliases.add(s.readUTF());
  261. }
  262. return aliases;
  263. }
  264. return null;
  265. }
  266. protected void writeOutTypeAliases(DataOutputStream s) throws IOException {
  267. // Write any type variable aliases
  268. if (typeVariableAliases==null || typeVariableAliases.size()==0) {
  269. s.writeInt(0);
  270. } else {
  271. s.writeInt(typeVariableAliases.size());
  272. for (Iterator iter = typeVariableAliases.iterator(); iter.hasNext();) {
  273. String element = (String) iter.next();
  274. s.writeUTF(element);
  275. }
  276. }
  277. }
  278. public List getTypeVariableAliases() {
  279. return typeVariableAliases;
  280. }
  281. public boolean hasTypeVariableAliases() {
  282. return (typeVariableAliases!=null && typeVariableAliases.size()>0);
  283. }
  284. /**
  285. * return true if type variables are specified with the target type for
  286. * this ITD. e.g. this would return true: "int I<A,B>.m() { return 42; }"
  287. */
  288. public boolean sharesTypeVariablesWithGenericType() {
  289. return (typeVariableAliases!=null && typeVariableAliases.size()>0);
  290. }
  291. /**
  292. * Parameterizes a resolved type munger for a particular usage of
  293. * its target type (this is used when the target type is generic
  294. * and the ITD shares type variables with the target)
  295. * see ConcreteTypeMunger.parameterizedFor
  296. */
  297. public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
  298. throw new BCException("Dont call parameterizedFor on a type munger of this kind: "+this.getClass());
  299. }
  300. // ResolvedType genericType = target;
  301. // if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
  302. // ResolvedMember parameterizedSignature = null;
  303. // // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used
  304. // // in the original ITD declaration to the ones used in the actual target type declaration.
  305. // if (target.isGenericType()) {
  306. // TypeVariable vars[] = target.getTypeVariables();
  307. // UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length];
  308. // for (int i = 0; i < vars.length; i++) {
  309. // varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]);
  310. // }
  311. // parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases);
  312. // } else {
  313. // // For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>)
  314. // parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
  315. // }
  316. // return new NewMethodTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
  317. // }
  318. // /**
  319. // * see ResolvedTypeMunger.parameterizedFor(ResolvedType)
  320. // */
  321. // public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
  322. // ResolvedType genericType = target;
  323. // if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
  324. // ResolvedMember parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
  325. // return new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
  326. // }
  327. public void setDeclaredSignature(ResolvedMember rm) {
  328. declaredSignature = rm;
  329. }
  330. public ResolvedMember getDeclaredSignature() {
  331. return declaredSignature;
  332. }
  333. /**
  334. * A late munger has to be done after shadow munging since which shadows are matched
  335. * can affect the operation of the late munger. e.g. perobjectinterfacemunger
  336. */
  337. public boolean isLateMunger() {
  338. return false;
  339. }
  340. }