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.

AjAttribute.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  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. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.io.ByteArrayInputStream;
  14. import java.io.ByteArrayOutputStream;
  15. import java.io.DataOutputStream;
  16. import java.io.IOException;
  17. import org.aspectj.bridge.IMessageHandler;
  18. import org.aspectj.bridge.MessageUtil;
  19. import org.aspectj.util.FileUtil;
  20. import org.aspectj.weaver.patterns.Declare;
  21. import org.aspectj.weaver.patterns.PerClause;
  22. import org.aspectj.weaver.patterns.Pointcut;
  23. /**
  24. * These attributes are written to and read from .class files (see the JVM spec).
  25. *
  26. * <p>Each member or type can have a number of AjAttributes. Each
  27. * such attribute is in 1-1 correspondence with an Unknown bcel attribute.
  28. * Creating one of these does NOTHING to the underlying thing, so if you really
  29. * want to add an attribute to a particular thing, well, you'd better actually do that.
  30. *
  31. * @author Erik Hilsdale
  32. * @author Jim Hugunin
  33. */
  34. public abstract class AjAttribute {
  35. public static final String AttributePrefix = "org.aspectj.weaver";
  36. protected abstract void write(DataOutputStream s) throws IOException;
  37. public abstract String getNameString();
  38. public char[] getNameChars() {
  39. return getNameString().toCharArray();
  40. }
  41. /**
  42. * Just writes the contents
  43. */
  44. public byte[] getBytes() {
  45. try {
  46. ByteArrayOutputStream b0 = new ByteArrayOutputStream();
  47. DataOutputStream s0 = new DataOutputStream(b0);
  48. write(s0);
  49. return b0.toByteArray();
  50. } catch (IOException e) {
  51. // shouldn't happen with ByteArrayOutputStreams
  52. throw new RuntimeException("sanity check");
  53. }
  54. }
  55. /**
  56. * Writes the full attribute, i.e. name_index, length, and contents
  57. */
  58. public byte[] getAllBytes(short nameIndex) {
  59. try {
  60. byte[] bytes = getBytes();
  61. ByteArrayOutputStream b0 = new ByteArrayOutputStream();
  62. DataOutputStream s0 = new DataOutputStream(b0);
  63. s0.writeShort(nameIndex);
  64. s0.writeInt(bytes.length);
  65. s0.write(bytes);
  66. return b0.toByteArray();
  67. } catch (IOException e) {
  68. // shouldn't happen with ByteArrayOutputStreams
  69. throw new RuntimeException("sanity check");
  70. }
  71. }
  72. public static AjAttribute read(AjAttribute.WeaverVersionInfo v, String name, byte[] bytes, ISourceContext context,IMessageHandler msgHandler) {
  73. try {
  74. if (bytes == null) bytes = new byte[0];
  75. VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(bytes));
  76. s.setVersion(v);
  77. if (name.equals(Aspect.AttributeName)) {
  78. return new Aspect(PerClause.readPerClause(s, context));
  79. } else if (name.equals(MethodDeclarationLineNumberAttribute.AttributeName)) {
  80. return MethodDeclarationLineNumberAttribute.read(s);
  81. } else if (name.equals(WeaverState.AttributeName)) {
  82. return new WeaverState(WeaverStateInfo.read(s, context));
  83. } else if (name.equals(WeaverVersionInfo.AttributeName)) {
  84. return WeaverVersionInfo.read(s);
  85. } else if (name.equals(AdviceAttribute.AttributeName)) {
  86. return AdviceAttribute.read(s, context);
  87. } else if (name.equals(PointcutDeclarationAttribute.AttributeName)) {
  88. return new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context));
  89. } else if (name.equals(TypeMunger.AttributeName)) {
  90. return new TypeMunger(ResolvedTypeMunger.read(s, context));
  91. } else if (name.equals(AjSynthetic.AttributeName)) {
  92. return new AjSynthetic();
  93. } else if (name.equals(DeclareAttribute.AttributeName)) {
  94. return new DeclareAttribute(Declare.read(s, context));
  95. } else if (name.equals(PrivilegedAttribute.AttributeName)) {
  96. return PrivilegedAttribute.read(s, context);
  97. } else if (name.equals(SourceContextAttribute.AttributeName)) {
  98. return SourceContextAttribute.read(s);
  99. } else if (name.equals(EffectiveSignatureAttribute.AttributeName)) {
  100. return EffectiveSignatureAttribute.read(s, context);
  101. } else {
  102. // We have to tell the user about this...
  103. if (msgHandler == null) throw new BCException("unknown attribute" + name);
  104. msgHandler.handleMessage(MessageUtil.warn("unknown attribute encountered "+name));
  105. return null;
  106. }
  107. } catch (IOException e) {
  108. throw new BCException("malformed " + name + " attribute " + e);
  109. }
  110. }
  111. //----
  112. /** Synthetic members should have NO advice put on them or on their contents.
  113. * This attribute is currently unused as we consider all members starting
  114. * with NameMangler.PREFIX to automatically be synthetic. As we use this we might
  115. * find that we want multiple
  116. * kinds of synthetic. In particular, if we want to treat the call to a synthetic getter
  117. * (say, of an introduced field) as a field reference itself, then a method might want
  118. * a particular kind of AjSynthetic attribute that also includes a signature of what
  119. * it stands for.
  120. */
  121. public static class AjSynthetic extends AjAttribute {
  122. public static final String AttributeName = "org.aspectj.weaver.AjSynthetic";
  123. public String getNameString() {
  124. return AttributeName;
  125. }
  126. // private ResolvedTypeMunger munger;
  127. public AjSynthetic() {}
  128. public void write(DataOutputStream s) throws IOException {}
  129. }
  130. public static class TypeMunger extends AjAttribute {
  131. public static final String AttributeName = "org.aspectj.weaver.TypeMunger";
  132. public String getNameString() {
  133. return AttributeName;
  134. }
  135. private ResolvedTypeMunger munger;
  136. public TypeMunger(ResolvedTypeMunger munger) {
  137. this.munger = munger;
  138. }
  139. public void write(DataOutputStream s) throws IOException {
  140. munger.write(s);
  141. }
  142. public ConcreteTypeMunger reify(World world, ResolvedTypeX aspectType) {
  143. return world.concreteTypeMunger(munger, aspectType);
  144. }
  145. }
  146. public static class WeaverState extends AjAttribute {
  147. public static final String AttributeName = "org.aspectj.weaver.WeaverState";
  148. public String getNameString() {
  149. return AttributeName;
  150. }
  151. private WeaverStateInfo kind;
  152. public WeaverState(WeaverStateInfo kind) {
  153. this.kind = kind;
  154. }
  155. public void write(DataOutputStream s) throws IOException {
  156. kind.write(s);
  157. }
  158. public WeaverStateInfo reify() {
  159. return kind;
  160. }
  161. }
  162. public static class WeaverVersionInfo extends AjAttribute {
  163. public static final String AttributeName = "org.aspectj.weaver.WeaverVersion";
  164. // If you change the format of an AspectJ class file, you have two options:
  165. // - changing the minor version means you have not added anything that prevents
  166. // previous versions of the weaver from operating (e.g. MethodDeclarationLineNumber attribute)
  167. // - changing the major version means you have added something that prevents previous
  168. // versions of the weaver from operating correctly.
  169. //
  170. // The user will get a warning for any org.aspectj.weaver attributes the weaver does
  171. // not recognize.
  172. // When we don't know ... (i.e. pre 1.2.1)
  173. public static short WEAVER_VERSION_MAJOR_UNKNOWN = 0;
  174. public static short WEAVER_VERSION_MINOR_UNKNOWN = 0;
  175. // These are the weaver major/minor numbers for AspectJ 1.2.1
  176. public static short WEAVER_VERSION_MAJOR_AJ121 = 1;
  177. public static short WEAVER_VERSION_MINOR_AJ121 = 0;
  178. // These are the weaver major/minor numbers for AspectJ 1.5.0
  179. public static short WEAVER_VERSION_MAJOR_AJ150 = 2;
  180. public static short WEAVER_VERSION_MINOR_AJ150 = 0;
  181. // These are the weaver major/minor versions for *this* weaver
  182. private static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ150;
  183. private static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ150;
  184. public static final WeaverVersionInfo UNKNOWN =
  185. new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN,WEAVER_VERSION_MINOR_UNKNOWN);
  186. // These are the versions read in from a particular class file.
  187. private short major_version;
  188. private short minor_version;
  189. public String getNameString() {
  190. return AttributeName;
  191. }
  192. // Default ctor uses the current version numbers
  193. public WeaverVersionInfo() {
  194. this.major_version = CURRENT_VERSION_MAJOR;
  195. this.minor_version = CURRENT_VERSION_MINOR;
  196. }
  197. public WeaverVersionInfo(short major,short minor) {
  198. major_version = major;
  199. minor_version = minor;
  200. }
  201. public void write(DataOutputStream s) throws IOException {
  202. s.writeShort(CURRENT_VERSION_MAJOR);
  203. s.writeShort(CURRENT_VERSION_MINOR);
  204. }
  205. public static WeaverVersionInfo read(VersionedDataInputStream s) throws IOException {
  206. short major = s.readShort();
  207. short minor = s.readShort();
  208. WeaverVersionInfo wvi = new WeaverVersionInfo(major,minor);
  209. // s.setVersion(wvi);
  210. return wvi;
  211. }
  212. public short getMajorVersion() {
  213. return major_version;
  214. }
  215. public short getMinorVersion() {
  216. return minor_version;
  217. }
  218. public static short getCurrentWeaverMajorVersion() {
  219. return CURRENT_VERSION_MAJOR;
  220. }
  221. public static short getCurrentWeaverMinorVersion() {
  222. return CURRENT_VERSION_MINOR;
  223. }
  224. public String toString() {
  225. return major_version+"."+minor_version;
  226. }
  227. public static String toCurrentVersionString() {
  228. return CURRENT_VERSION_MAJOR+"."+CURRENT_VERSION_MINOR;
  229. }
  230. }
  231. public static class SourceContextAttribute extends AjAttribute {
  232. public static final String AttributeName = "org.aspectj.weaver.SourceContext";
  233. public String getNameString() {
  234. return AttributeName;
  235. }
  236. private String sourceFileName;
  237. private int[] lineBreaks;
  238. public SourceContextAttribute(String sourceFileName, int[] lineBreaks) {
  239. this.sourceFileName = sourceFileName;
  240. this.lineBreaks = lineBreaks;
  241. }
  242. public void write(DataOutputStream s) throws IOException {
  243. s.writeUTF(sourceFileName);
  244. FileUtil.writeIntArray(lineBreaks, s);
  245. }
  246. public static SourceContextAttribute read(VersionedDataInputStream s) throws IOException {
  247. return new SourceContextAttribute(s.readUTF(), FileUtil.readIntArray(s));
  248. }
  249. public int[] getLineBreaks() {
  250. return lineBreaks;
  251. }
  252. public String getSourceFileName() {
  253. return sourceFileName;
  254. }
  255. }
  256. public static class MethodDeclarationLineNumberAttribute extends AjAttribute {
  257. public static final String AttributeName = "org.aspectj.weaver.MethodDeclarationLineNumber";
  258. public String getNameString() {
  259. return AttributeName;
  260. }
  261. private int lineNumber;
  262. public MethodDeclarationLineNumberAttribute(int line) {
  263. this.lineNumber = line;
  264. }
  265. public int getLineNumber() { return lineNumber; }
  266. public void write(DataOutputStream s) throws IOException {
  267. s.writeInt(lineNumber);
  268. }
  269. public static MethodDeclarationLineNumberAttribute read(VersionedDataInputStream s) throws IOException {
  270. return new MethodDeclarationLineNumberAttribute(s.readInt());
  271. }
  272. public String toString() {
  273. return AttributeName + ": " + lineNumber;
  274. }
  275. }
  276. public static class PointcutDeclarationAttribute extends AjAttribute {
  277. public static final String AttributeName = "org.aspectj.weaver.PointcutDeclaration";
  278. public String getNameString() {
  279. return AttributeName;
  280. }
  281. private ResolvedPointcutDefinition pointcutDef;
  282. public PointcutDeclarationAttribute(ResolvedPointcutDefinition pointcutDef) {
  283. this.pointcutDef = pointcutDef;
  284. }
  285. public void write(DataOutputStream s) throws IOException {
  286. pointcutDef.write(s);
  287. }
  288. public ResolvedPointcutDefinition reify() {
  289. return pointcutDef;
  290. }
  291. }
  292. public static class DeclareAttribute extends AjAttribute {
  293. public static final String AttributeName = "org.aspectj.weaver.Declare";
  294. public String getNameString() {
  295. return AttributeName;
  296. }
  297. private Declare declare;
  298. public DeclareAttribute(Declare declare) {
  299. this.declare = declare;
  300. }
  301. public void write(DataOutputStream s) throws IOException {
  302. declare.write(s);
  303. }
  304. public Declare getDeclare() {
  305. return declare;
  306. }
  307. }
  308. public static class AdviceAttribute extends AjAttribute {
  309. public static final String AttributeName = "org.aspectj.weaver.Advice";
  310. public String getNameString() {
  311. return AttributeName;
  312. }
  313. private AdviceKind kind;
  314. private Pointcut pointcut;
  315. private int extraParameterFlags;
  316. private int start;
  317. private int end;
  318. private ISourceContext sourceContext;
  319. // these are only used by around advice
  320. private boolean proceedInInners;
  321. private ResolvedMember[] proceedCallSignatures; // size == # of proceed calls in body
  322. private boolean[] formalsUnchangedToProceed; // size == formals.size
  323. private TypeX[] declaredExceptions;
  324. /**
  325. * @param lexicalPosition must be greater than the lexicalPosition
  326. * of any advice declared before this one in an aspect, otherwise,
  327. * it can be any value.
  328. */
  329. public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags,
  330. int start, int end, ISourceContext sourceContext) {
  331. this.kind = kind;
  332. this.pointcut = pointcut;
  333. this.extraParameterFlags = extraArgumentFlags;
  334. this.start = start;
  335. this.end = end;
  336. this.sourceContext = sourceContext;
  337. //XXX put this back when testing works better (or fails better)
  338. //if (kind == AdviceKind.Around) throw new IllegalArgumentException("not for around");
  339. }
  340. public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags,
  341. int start, int end, ISourceContext sourceContext,
  342. boolean proceedInInners, ResolvedMember[] proceedCallSignatures,
  343. boolean[] formalsUnchangedToProceed, TypeX[] declaredExceptions) {
  344. this.kind = kind;
  345. this.pointcut = pointcut;
  346. this.extraParameterFlags = extraArgumentFlags;
  347. this.start = start;
  348. this.end = end;
  349. this.sourceContext = sourceContext;
  350. if (kind != AdviceKind.Around) throw new IllegalArgumentException("only for around");
  351. this.proceedInInners = proceedInInners;
  352. this.proceedCallSignatures = proceedCallSignatures;
  353. this.formalsUnchangedToProceed = formalsUnchangedToProceed;
  354. this.declaredExceptions = declaredExceptions;
  355. }
  356. public static AdviceAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  357. AdviceKind kind = AdviceKind.read(s);
  358. if (kind == AdviceKind.Around) {
  359. return new AdviceAttribute(
  360. kind,
  361. Pointcut.read(s, context),
  362. s.readByte(),
  363. s.readInt(), s.readInt(), context,
  364. s.readBoolean(),
  365. ResolvedMember.readResolvedMemberArray(s, context),
  366. FileUtil.readBooleanArray(s),
  367. TypeX.readArray(s));
  368. } else {
  369. return new AdviceAttribute(
  370. kind,
  371. Pointcut.read(s, context),
  372. s.readByte(),
  373. s.readInt(), s.readInt(), context);
  374. }
  375. }
  376. public void write(DataOutputStream s) throws IOException {
  377. kind.write(s);
  378. pointcut.write(s);
  379. s.writeByte(extraParameterFlags);
  380. s.writeInt(start);
  381. s.writeInt(end);
  382. if (kind == AdviceKind.Around) {
  383. s.writeBoolean(proceedInInners);
  384. ResolvedMember.writeArray(proceedCallSignatures, s);
  385. FileUtil.writeBooleanArray(formalsUnchangedToProceed, s);
  386. TypeX.writeArray(declaredExceptions, s);
  387. }
  388. }
  389. public Advice reify(Member signature, World world) {
  390. return world.concreteAdvice(this, pointcut, signature);
  391. }
  392. public String toString() {
  393. return "AdviceAttribute(" + kind + ", " + pointcut + ", " +
  394. extraParameterFlags + ", " + start+")";
  395. }
  396. public int getExtraParameterFlags() {
  397. return extraParameterFlags;
  398. }
  399. public AdviceKind getKind() {
  400. return kind;
  401. }
  402. public Pointcut getPointcut() {
  403. return pointcut;
  404. }
  405. public TypeX[] getDeclaredExceptions() {
  406. return declaredExceptions;
  407. }
  408. public boolean[] getFormalsUnchangedToProceed() {
  409. return formalsUnchangedToProceed;
  410. }
  411. public ResolvedMember[] getProceedCallSignatures() {
  412. return proceedCallSignatures;
  413. }
  414. public boolean isProceedInInners() {
  415. return proceedInInners;
  416. }
  417. public int getEnd() {
  418. return end;
  419. }
  420. public ISourceContext getSourceContext() {
  421. return sourceContext;
  422. }
  423. public int getStart() {
  424. return start;
  425. }
  426. }
  427. public static class Aspect extends AjAttribute {
  428. public static final String AttributeName = "org.aspectj.weaver.Aspect";
  429. public String getNameString() {
  430. return AttributeName;
  431. }
  432. private PerClause perClause;
  433. public Aspect(PerClause perClause) {
  434. this.perClause = perClause;
  435. }
  436. public PerClause reify(ResolvedTypeX inAspect) {
  437. //XXXperClause.concretize(inAspect);
  438. return perClause;
  439. }
  440. public void write(DataOutputStream s) throws IOException {
  441. perClause.write(s);
  442. }
  443. }
  444. public static class PrivilegedAttribute extends AjAttribute {
  445. public static final String AttributeName = "org.aspectj.weaver.Privileged";
  446. public String getNameString() {
  447. return AttributeName;
  448. }
  449. private ResolvedMember[] accessedMembers;
  450. public PrivilegedAttribute(ResolvedMember[] accessedMembers) {
  451. this.accessedMembers = accessedMembers;
  452. }
  453. public void write(DataOutputStream s) throws IOException {
  454. ResolvedMember.writeArray(accessedMembers, s);
  455. }
  456. public ResolvedMember[] getAccessedMembers() {
  457. return accessedMembers;
  458. }
  459. public static PrivilegedAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  460. return new PrivilegedAttribute(ResolvedMember.readResolvedMemberArray(s, context));
  461. }
  462. }
  463. public static class EffectiveSignatureAttribute extends AjAttribute {
  464. public static final String AttributeName = "org.aspectj.weaver.EffectiveSignature";
  465. public String getNameString() {
  466. return AttributeName;
  467. }
  468. private ResolvedMember effectiveSignature;
  469. private Shadow.Kind shadowKind;
  470. private boolean weaveBody;
  471. public EffectiveSignatureAttribute(ResolvedMember effectiveSignature, Shadow.Kind shadowKind, boolean weaveBody) {
  472. this.effectiveSignature = effectiveSignature;
  473. this.shadowKind = shadowKind;
  474. this.weaveBody = weaveBody;
  475. }
  476. public void write(DataOutputStream s) throws IOException {
  477. effectiveSignature.write(s);
  478. shadowKind.write(s);
  479. s.writeBoolean(weaveBody);
  480. }
  481. public static EffectiveSignatureAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  482. return new EffectiveSignatureAttribute(
  483. ResolvedMember.readResolvedMember(s, context),
  484. Shadow.Kind.read(s),
  485. s.readBoolean());
  486. }
  487. public ResolvedMember getEffectiveSignature() {
  488. return effectiveSignature;
  489. }
  490. public String toString() {
  491. return "EffectiveSignatureAttribute(" + effectiveSignature + ", " + shadowKind + ")";
  492. }
  493. public Shadow.Kind getShadowKind() {
  494. return shadowKind;
  495. }
  496. public boolean isWeaveBody() {
  497. return weaveBody;
  498. }
  499. }
  500. }