Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

TypeX.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.io.*;
  14. import java.lang.reflect.Modifier;
  15. import java.util.Iterator;
  16. import org.aspectj.weaver.patterns.PerClause;
  17. public class TypeX {
  18. /**
  19. * This is the bytecode string representation of this Type
  20. */
  21. protected String signature;
  22. /**
  23. * @param signature the bytecode string representation of this Type
  24. */
  25. protected TypeX(String signature) {
  26. super();
  27. this.signature = signature;
  28. }
  29. // ---- Things we can do without a world
  30. /**
  31. * This is the size of this type as used in JVM.
  32. */
  33. public int getSize() {
  34. return 1;
  35. }
  36. /**
  37. * Equality is checked based on the underlying signature.
  38. * {@link ResolvedType} objects' equals is by reference.
  39. */
  40. public boolean equals(Object other) {
  41. if (! (other instanceof TypeX)) return false;
  42. return signature.equals(((TypeX) other).signature);
  43. }
  44. /**
  45. * Equality is checked based on the underlying signature, so the hash code
  46. * of a particular type is the hash code of its signature string.
  47. */
  48. public final int hashCode() {
  49. return signature.hashCode();
  50. }
  51. public static TypeX makeArray(TypeX base, int dims) {
  52. StringBuffer sig = new StringBuffer();
  53. for (int i=0; i < dims; i++) sig.append("[");
  54. sig.append(base.getSignature());
  55. return TypeX.forSignature(sig.toString());
  56. }
  57. /**
  58. * Constructs a TypeX for a java language type name. For example:
  59. *
  60. * <blockquote><pre>
  61. * TypeX.forName("java.lang.Thread[]")
  62. * TypeX.forName("int")
  63. * </pre></blockquote>
  64. *
  65. * Types may equivalently be produced by this or by {@link #forSignature(String)}.
  66. *
  67. * <blockquote><pre>
  68. * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  69. * TypeX.forName("int").equals(Type.forSignature("I"))
  70. * </pre></blockquote>
  71. *
  72. * @param name the java language type name in question.
  73. * @return a type object representing that java language type.
  74. */
  75. public static TypeX forName(String name) {
  76. return forSignature(nameToSignature(name));
  77. }
  78. /** Constructs a TypeX for each java language type name in an incoming array.
  79. *
  80. * @param names an array of java language type names.
  81. * @return an array of TypeX objects.
  82. * @see #forName(String)
  83. */
  84. public static TypeX[] forNames(String[] names) {
  85. TypeX[] ret = new TypeX[names.length];
  86. for (int i = 0, len = names.length; i < len; i++) {
  87. ret[i] = TypeX.forName(names[i]);
  88. }
  89. return ret;
  90. }
  91. /**
  92. * Creates a new type array with a fresh type appended to the end.
  93. *
  94. * @param types the left hand side of the new array
  95. * @param end the right hand side of the new array
  96. */
  97. public static TypeX[] add(TypeX[] types, TypeX end) {
  98. int len = types.length;
  99. TypeX[] ret = new TypeX[len + 1];
  100. System.arraycopy(types, 0, ret, 0, len);
  101. ret[len] = end;
  102. return ret;
  103. }
  104. /**
  105. * Creates a new type array with a fresh type inserted at the beginning.
  106. *
  107. *
  108. * @param start the left hand side of the new array
  109. * @param types the right hand side of the new array
  110. */
  111. public static TypeX[] insert(TypeX start, TypeX[] types) {
  112. int len = types.length;
  113. TypeX[] ret = new TypeX[len + 1];
  114. ret[0] = start;
  115. System.arraycopy(types, 0, ret, 1, len);
  116. return ret;
  117. }
  118. /**
  119. * Constructs a Type for a JVM bytecode signature string. For example:
  120. *
  121. * <blockquote><pre>
  122. * TypeX.forSignature("[Ljava/lang/Thread;")
  123. * TypeX.forSignature("I");
  124. * </pre></blockquote>
  125. *
  126. * Types may equivalently be produced by this or by {@link #forName(String)}.
  127. *
  128. * <blockquote><pre>
  129. * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  130. * TypeX.forName("int").equals(Type.forSignature("I"))
  131. * </pre></blockquote>
  132. *
  133. * @param signature the JVM bytecode signature string for the desired type.
  134. * @return a type object represnting that JVM bytecode signature.
  135. */
  136. public static TypeX forSignature(String signature) {
  137. switch (signature.charAt(0)) {
  138. case 'B': return ResolvedTypeX.BYTE;
  139. case 'C': return ResolvedTypeX.CHAR;
  140. case 'D': return ResolvedTypeX.DOUBLE;
  141. case 'F': return ResolvedTypeX.FLOAT;
  142. case 'I': return ResolvedTypeX.INT;
  143. case 'J': return ResolvedTypeX.LONG;
  144. case 'L':
  145. return new TypeX(signature);
  146. case 'S': return ResolvedTypeX.SHORT;
  147. case 'V': return ResolvedTypeX.VOID;
  148. case 'Z': return ResolvedTypeX.BOOLEAN;
  149. case '[':
  150. return new TypeX(signature);
  151. default:
  152. throw new BCException("Bad type signature " + signature);
  153. }
  154. }
  155. /** Constructs a TypeX for each JVM bytecode type signature in an incoming array.
  156. *
  157. * @param names an array of JVM bytecode type signatures
  158. * @return an array of TypeX objects.
  159. * @see #forSignature(String)
  160. */
  161. public static TypeX[] forSignatures(String[] sigs) {
  162. TypeX[] ret = new TypeX[sigs.length];
  163. for (int i = 0, len = sigs.length; i < len; i++) {
  164. ret[i] = TypeX.forSignature(sigs[i]);
  165. }
  166. return ret;
  167. }
  168. /**
  169. * Returns the name of this type in java language form. For all
  170. * TypeX t:
  171. *
  172. * <blockquote><pre>
  173. * TypeX.forName(t.getName()).equals(t)
  174. * </pre></blockquote>
  175. *
  176. * and for all String s where s is a lexically valid java language typename:
  177. *
  178. * <blockquote><pre>
  179. * TypeX.forName(s).getName().equals(s)
  180. * </pre></blockquote>
  181. *
  182. * This produces a more esthetically pleasing string than
  183. * {@link java.lang.Class#getName()}.
  184. *
  185. * @return the java language name of this type.
  186. */
  187. public String getName() {
  188. return signatureToName(signature);
  189. }
  190. /**
  191. * Returns an array of strings representing the java langauge names of
  192. * an array of types.
  193. *
  194. * @param types an array of TypeX objects
  195. * @return an array of Strings fo the java language names of types.
  196. * @see #getName()
  197. */
  198. public static String[] getNames(TypeX[] types) {
  199. String[] ret = new String[types.length];
  200. for (int i = 0, len = types.length; i < len; i++) {
  201. ret[i] = types[i].getName();
  202. }
  203. return ret;
  204. }
  205. /**
  206. * Returns the name of this type in JVM signature form. For all
  207. * TypeX t:
  208. *
  209. * <blockquote><pre>
  210. * TypeX.forSignature(t.getSignature()).equals(t)
  211. * </pre></blockquote>
  212. *
  213. * and for all String s where s is a lexically valid JVM type signature string:
  214. *
  215. * <blockquote><pre>
  216. * TypeX.forSignature(s).getSignature().equals(s)
  217. * </pre></blockquote>
  218. *
  219. * @return the java JVM signature string for this type.
  220. */
  221. public String getSignature() {
  222. return signature;
  223. }
  224. /**
  225. * Determins if this represents an array type.
  226. *
  227. * @return true iff this represents an array type.
  228. */
  229. public final boolean isArray() {
  230. return signature.startsWith("[");
  231. }
  232. /**
  233. * Returns a TypeX object representing the declaring type of this type, or
  234. * null if this type does not represent a non-package-level-type.
  235. *
  236. * <strong>Warning</strong>: This is guaranteed to work for all member types.
  237. * For anonymous/local types, the only guarantee is given in JLS 13.1, where
  238. * it guarantees that if you call getDeclaringType() repeatedly, you will eventually
  239. * get the top-level class, but it does not say anything about classes in between.
  240. *
  241. * @return the declaring TypeX object, or null.
  242. */
  243. public TypeX getDeclaringType() {
  244. if (isArray()) return null;
  245. String name = getName();
  246. int lastDollar = name.lastIndexOf('$');
  247. if (lastDollar != -1) {
  248. return TypeX.forName(name.substring(0, lastDollar));
  249. } else {
  250. return null;
  251. }
  252. }
  253. /**
  254. * Returns a TypeX object representing the component type of this array, or
  255. * null if this type does not represent an array type.
  256. *
  257. * @return the component TypeX object, or null.
  258. */
  259. public TypeX getComponentType() {
  260. if (isArray()) {
  261. return forSignature(signature.substring(1));
  262. } else {
  263. return null;
  264. }
  265. }
  266. /**
  267. * Determines if this represents a primitive type. A primitive type
  268. * is one of nine predefined resolved types.
  269. *
  270. * @return true iff this type represents a primitive type
  271. *
  272. * @see ResolvedTypeX#Boolean
  273. * @see ResolvedTypeX#Character
  274. * @see ResolvedTypeX#Byte
  275. * @see ResolvedTypeX#Short
  276. * @see ResolvedTypeX#Integer
  277. * @see ResolvedTypeX#Long
  278. * @see ResolvedTypeX#Float
  279. * @see ResolvedTypeX#Double
  280. * @see ResolvedTypeX#Void
  281. */
  282. public boolean isPrimitive() {
  283. return false;
  284. }
  285. /**
  286. * Returns a java language string representation of this type.
  287. */
  288. public String toString() {
  289. return getName();
  290. }
  291. // ---- requires worlds
  292. /**
  293. * Types may have pointcuts just as they have methods and fields.
  294. */
  295. public ResolvedPointcutDefinition findPointcut(String name, World world) {
  296. return world.findPointcut(this, name);
  297. }
  298. /**
  299. * Determines if variables of this type could be assigned values of another
  300. * with lots of help. This is the same as isCoercableFrom, but java.lang.Object
  301. * is convertable from and to all types.
  302. *
  303. * @param other the other type
  304. * @param world the {@link World} in which the possible assignment should be checked.
  305. * @return true iff variables of this type could be assigned values of other with possible conversion
  306. */
  307. public final boolean isConvertableFrom(TypeX other, World world) {
  308. if (this.equals(OBJECT) || other.equals(OBJECT)) return true;
  309. return this.isCoerceableFrom(other, world);
  310. }
  311. /**
  312. * Determines if variables of this type could be assigned values of another
  313. * without any conversion computation of any kind. For primitive types
  314. * this means equality, and for reference types it means assignability.
  315. *
  316. * @param other the other type
  317. * @param world the {@link World} in which the possible assignment should be checked.
  318. * @return true iff variables of this type could be assigned values of other without any conversion computation
  319. */
  320. public boolean needsNoConversionFrom(TypeX other, World world) {
  321. // primitives override this method, so we know we're not primitive.
  322. // So if the other is primitive, don't bother asking the world anything.
  323. if (other.isPrimitive()) return false;
  324. return world.needsNoConversionFrom(this, other);
  325. }
  326. /**
  327. * Determines if the variables of this type could be assigned values
  328. * of another type without casting. This still allows for assignment conversion
  329. * as per JLS 2ed 5.2.
  330. *
  331. * @param other the other type
  332. * @param world the {@link World} in which the possible assignment should be checked.
  333. * @return true iff variables of this type could be assigned values of other without casting
  334. * @exception NullPointerException if other is null
  335. */
  336. public boolean isAssignableFrom(TypeX other, World world) {
  337. // primitives override this method, so we know we're not primitive.
  338. // So if the other is primitive, don't bother asking the world anything.
  339. if (other.isPrimitive()) return false;
  340. return world.isAssignableFrom(this, other);
  341. }
  342. /**
  343. * Determines if values of another type could possibly be cast to
  344. * this type. The rules followed are from JLS 2ed 5.5, "Casting Conversion".
  345. *
  346. * <p> This method should be commutative, i.e., for all TypeX a, b and all World w:
  347. *
  348. * <blockquote><pre>
  349. * a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
  350. * </pre></blockquote>
  351. *
  352. * @param other the other type
  353. * @param world the {@link World} in which the possible coersion should be checked.
  354. * @return true iff values of other could possibly be cast to this type.
  355. * @exception NullPointerException if other is null.
  356. */
  357. public boolean isCoerceableFrom(TypeX other, World world) {
  358. // primitives override this method, so we know we're not primitive.
  359. // So if the other is primitive, don't bother asking the world anything.
  360. if (other.isPrimitive()) return false;
  361. return world.isCoerceableFrom(this, other);
  362. }
  363. /**
  364. * Determines if this represents an interface type.
  365. *
  366. * @param world the {@link World} in which we should check.
  367. * @return true iff this represents an interface type.
  368. */
  369. public final boolean isInterface(World world) {
  370. return world.resolve(this).isInterface();
  371. }
  372. /**
  373. * Determines if this represents a class type.
  374. *
  375. * @param world the {@link World} in which we should check.
  376. * @return true iff this represents a class type.
  377. */
  378. public final boolean isClass(World world) {
  379. return world.resolve(this).isClass();
  380. }
  381. /**
  382. * Determines if this represents an aspect type.
  383. *
  384. * @param world the {@link World} in which we should check.
  385. * @return true iff this represents an aspect type.
  386. */
  387. public final boolean isAspect(World world) {
  388. return world.resolve(this).isAspect();
  389. }
  390. /**
  391. * Returns a TypeX object representing the superclass of this type, or null.
  392. * If this represents a java.lang.Object, a primitive type, or void, this
  393. * method returns null.
  394. *
  395. * <p>
  396. * This differs from {@link java.lang.class#getSuperclass()} in that
  397. * this returns a TypeX object representing java.lang.Object for interfaces instead
  398. * of returning null.
  399. *
  400. * @param world the {@link World} in which the lookup should be made.
  401. * @return this type's superclass, or null if none exists.
  402. */
  403. public TypeX getSuperclass(World world) {
  404. return world.getSuperclass(this);
  405. }
  406. /**
  407. * Returns an array of TypeX objects representing the declared interfaces
  408. * of this type.
  409. *
  410. * <p>
  411. * If this object represents a class, the declared interfaces are those it
  412. * implements. If this object represents an interface, the declared interfaces
  413. * are those it extends. If this object represents a primitive, an empty
  414. * array is returned. If this object represents an array, an array
  415. * containing types for java.lang.Cloneable and java.io.Serializable is returned.
  416. *
  417. * @param world the {@link World} in which the lookup should be made.
  418. * @return an iterator through the declared interfaces of this type.
  419. */
  420. public TypeX[] getDeclaredInterfaces(World world) {
  421. return world.getDeclaredInterfaces(this);
  422. }
  423. /**
  424. * Returns an iterator through TypeX objects representing all the direct
  425. * supertypes of this type. That is, through the superclass, if any, and
  426. * all declared interfaces.
  427. *
  428. * @param world the {@link World} in which the lookup should be made.
  429. * @return an iterator through the direct supertypes of this type.
  430. */
  431. public Iterator getDirectSupertypes(World world) {
  432. return world.resolve(this).getDirectSupertypes();
  433. }
  434. /**
  435. * Returns the modifiers for this type.
  436. *
  437. * See {@link java.lang.Class#getModifiers()} for a description
  438. * of the weirdness of this methods on primitives and arrays.
  439. *
  440. * @param world the {@link World} in which the lookup is made.
  441. * @return an int representing the modifiers for this type
  442. * @see java.lang.reflect.Modifier
  443. */
  444. public int getModifiers(World world) {
  445. return world.getModifiers(this);
  446. }
  447. /**
  448. * Returns an array representing the declared fields of this object. This may include
  449. * non-user-visible fields.
  450. * This method returns an
  451. * empty array if it represents an array type or a primitive type, so
  452. * the implicit length field of arrays is just that, implicit.
  453. *
  454. * @param world the {@link World} in which the lookup is done.
  455. * @return the array representing the declared fields of this type
  456. */
  457. public ResolvedMember[] getDeclaredFields(World world) {
  458. return world.getDeclaredFields(this);
  459. }
  460. /**
  461. * Returns an array representing the declared methods of this object. This includes
  462. * constructors and the static initialzation method. This also includes all
  463. * shadowMungers in an aspect. So it may include more than the user-visible methods.
  464. * This method returns an
  465. * empty array if it represents an array type or a primitive type.
  466. *
  467. * @param world the {@link World} in which the lookup is done.
  468. * @return the array representing the declared methods of this type
  469. */
  470. public ResolvedMember[] getDeclaredMethods(World world) {
  471. return world.getDeclaredMethods(this);
  472. }
  473. /**
  474. * Returns an array representing the declared pointcuts of this object.
  475. * This method returns an
  476. * empty array if it represents an array type or a primitive type.
  477. *
  478. * @param world the {@link World} in which the lookup is done.
  479. * @return the array representing the declared pointcuts of this type
  480. */
  481. public ResolvedMember[] getDeclaredPointcuts(World world) {
  482. return world.getDeclaredPointcuts(this);
  483. }
  484. /**
  485. * Returns a resolved version of this type according to a particular world.
  486. *
  487. * @param world thie {@link World} within which to resolve.
  488. * @return a resolved type representing this type in the appropriate world.
  489. */
  490. public ResolvedTypeX resolve(World world) {
  491. return world.resolve(this);
  492. }
  493. // ---- fields
  494. public static final TypeX[] NONE = new TypeX[0];
  495. public static final TypeX OBJECT = forSignature("Ljava/lang/Object;");
  496. public static final TypeX OBJECTARRAY = forSignature("[Ljava/lang/Object;");
  497. public static final TypeX CLONEABLE = forSignature("Ljava/lang/Cloneable;");
  498. public static final TypeX SERIALIZABLE = forSignature("Ljava/io/Serializable;");
  499. public static final TypeX THROWABLE = forSignature("Ljava/lang/Throwable;");
  500. // ---- helpers
  501. private static String signatureToName(String signature) {
  502. switch (signature.charAt(0)) {
  503. case 'B': return "byte";
  504. case 'C': return "char";
  505. case 'D': return "double";
  506. case 'F': return "float";
  507. case 'I': return "int";
  508. case 'J': return "long";
  509. case 'L':
  510. return signature.substring(1, signature.length() - 1).replace('/', '.');
  511. case 'S': return "short";
  512. case 'V': return "void";
  513. case 'Z': return "boolean";
  514. case '[':
  515. return signatureToName(signature.substring(1, signature.length())) + "[]";
  516. default:
  517. throw new BCException("Bad type signature: " + signature);
  518. }
  519. }
  520. private static String nameToSignature(String name) {
  521. if (name.equals("byte")) return "B";
  522. if (name.equals("char")) return "C";
  523. if (name.equals("double")) return "D";
  524. if (name.equals("float")) return "F";
  525. if (name.equals("int")) return "I";
  526. if (name.equals("long")) return "J";
  527. if (name.equals("short")) return "S";
  528. if (name.equals("boolean")) return "Z";
  529. if (name.equals("void")) return "V";
  530. if (name.endsWith("[]"))
  531. return "[" + nameToSignature(name.substring(0, name.length() - 2));
  532. if (name.length() != 0) // lots more tests could be made here...
  533. return "L" + name.replace('.', '/') + ";";
  534. else
  535. throw new BCException("Bad type name: " + name);
  536. }
  537. public void write(DataOutputStream s) throws IOException {
  538. s.writeUTF(signature);
  539. }
  540. public static TypeX read(DataInputStream s) throws IOException {
  541. String sig = s.readUTF();
  542. if (sig.equals(MISSING_NAME)) {
  543. return ResolvedTypeX.MISSING;
  544. } else {
  545. return TypeX.forSignature(sig);
  546. }
  547. }
  548. public static void write(TypeX[] types, DataOutputStream s) throws IOException {
  549. int len = types.length;
  550. s.writeShort(len);
  551. for (int i=0; i < len; i++) {
  552. types[i].write(s);
  553. }
  554. }
  555. public static TypeX[] readArray(DataInputStream s) throws IOException {
  556. int len = s.readShort();
  557. TypeX[] types = new TypeX[len];
  558. for (int i=0; i < len; i++) {
  559. types[i] = TypeX.read(s);
  560. }
  561. return types;
  562. }
  563. /**
  564. * For debugging purposes
  565. */
  566. public void dump(World world) {
  567. if (isAspect(world)) System.out.print("aspect ");
  568. else if (isInterface(world)) System.out.print("interface ");
  569. else if (isClass(world)) System.out.print("class ");
  570. System.out.println(toString());
  571. dumpResolvedMembers("fields", getDeclaredFields(world));
  572. dumpResolvedMembers("methods", getDeclaredMethods(world));
  573. dumpResolvedMembers("pointcuts", getDeclaredPointcuts(world));
  574. }
  575. private void dumpResolvedMembers(String label, ResolvedMember[] l) {
  576. final String indent = " ";
  577. System.out.println(label);
  578. if (l == null) {
  579. System.out.println(indent + "null");
  580. return;
  581. }
  582. for (int i=0, len=l.length; i < len; i++) {
  583. System.out.println(indent + l[i]);
  584. }
  585. }
  586. // ----
  587. public String getNameAsIdentifier() {
  588. return getName().replace('.', '_');
  589. }
  590. public String getPackageNameAsIdentifier() {
  591. String name = getName();
  592. int index = name.lastIndexOf('.');
  593. if (index == -1) {
  594. return "";
  595. } else {
  596. return name.substring(0, index).replace('.', '_');
  597. }
  598. }
  599. public String getPackageName() {
  600. String name = getName();
  601. int index = name.lastIndexOf('.');
  602. if (index == -1) {
  603. return null;
  604. } else {
  605. return name.substring(0, index);
  606. }
  607. }
  608. public String getClassName() {
  609. String name = getName();
  610. int index = name.lastIndexOf('.');
  611. if (index == -1) {
  612. return name;
  613. } else {
  614. return name.substring(index+1);
  615. }
  616. }
  617. public static final String MISSING_NAME = "<missing>";
  618. }