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.

TypeX.java 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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.DataInputStream;
  14. import java.io.DataOutputStream;
  15. import java.io.IOException;
  16. import java.util.Iterator;
  17. public class TypeX implements AnnotatedElement {
  18. /**
  19. * This is the bytecode string representation of this Type
  20. */
  21. protected String signature;
  22. /**
  23. * If this is a parameterized type, these are its parameters
  24. */
  25. protected TypeX[] typeParameters;
  26. /**
  27. * @param signature the bytecode string representation of this Type
  28. */
  29. protected TypeX(String signature) {
  30. super();
  31. this.signature = signature;
  32. }
  33. // ---- Things we can do without a world
  34. /**
  35. * This is the size of this type as used in JVM.
  36. */
  37. public int getSize() {
  38. return 1;
  39. }
  40. /**
  41. * Equality is checked based on the underlying signature.
  42. * {@link ResolvedType} objects' equals is by reference.
  43. */
  44. public boolean equals(Object other) {
  45. if (! (other instanceof TypeX)) return false;
  46. return signature.equals(((TypeX) other).signature);
  47. }
  48. /**
  49. * Equality is checked based on the underlying signature, so the hash code
  50. * of a particular type is the hash code of its signature string.
  51. */
  52. public final int hashCode() {
  53. return signature.hashCode();
  54. }
  55. public static TypeX makeArray(TypeX base, int dims) {
  56. StringBuffer sig = new StringBuffer();
  57. for (int i=0; i < dims; i++) sig.append("[");
  58. sig.append(base.getSignature());
  59. return TypeX.forSignature(sig.toString());
  60. }
  61. /**
  62. * NOTE: Use forSignature() if you can, it'll be cheaper !
  63. * Constructs a TypeX for a java language type name. For example:
  64. *
  65. * <blockquote><pre>
  66. * TypeX.forName("java.lang.Thread[]")
  67. * TypeX.forName("int")
  68. * </pre></blockquote>
  69. *
  70. * Types may equivalently be produced by this or by {@link #forSignature(String)}.
  71. *
  72. * <blockquote><pre>
  73. * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  74. * TypeX.forName("int").equals(Type.forSignature("I"))
  75. * </pre></blockquote>
  76. *
  77. * @param name the java language type name in question.
  78. * @return a type object representing that java language type.
  79. */
  80. public static TypeX forName(String name) {
  81. return forSignature(nameToSignature(name));
  82. }
  83. /** Constructs a TypeX for each java language type name in an incoming array.
  84. *
  85. * @param names an array of java language type names.
  86. * @return an array of TypeX objects.
  87. * @see #forName(String)
  88. */
  89. public static TypeX[] forNames(String[] names) {
  90. TypeX[] ret = new TypeX[names.length];
  91. for (int i = 0, len = names.length; i < len; i++) {
  92. ret[i] = TypeX.forName(names[i]);
  93. }
  94. return ret;
  95. }
  96. /**
  97. * Makes a parameterized type with the given name
  98. * and parameterized type names.
  99. */
  100. public static TypeX forParameterizedTypeNames(String name, String[] paramTypeNames) {
  101. TypeX ret = TypeX.forName(name);
  102. ret.typeParameters = new TypeX[paramTypeNames.length];
  103. for (int i = 0; i < paramTypeNames.length; i++) {
  104. ret.typeParameters[i] = TypeX.forName(paramTypeNames[i]);
  105. }
  106. // sig for e.g. List<String> is Ljava/util/List<Ljava/lang/String;>;
  107. StringBuffer sigAddition = new StringBuffer();
  108. sigAddition.append("<");
  109. for (int i = 0; i < ret.typeParameters.length; i++) {
  110. sigAddition.append(ret.typeParameters[i].signature);
  111. sigAddition.append(">");
  112. sigAddition.append(";");
  113. }
  114. ret.signature = ret.signature + sigAddition.toString();
  115. return ret;
  116. }
  117. /**
  118. * Creates a new type array with a fresh type appended to the end.
  119. *
  120. * @param types the left hand side of the new array
  121. * @param end the right hand side of the new array
  122. */
  123. public static TypeX[] add(TypeX[] types, TypeX end) {
  124. int len = types.length;
  125. TypeX[] ret = new TypeX[len + 1];
  126. System.arraycopy(types, 0, ret, 0, len);
  127. ret[len] = end;
  128. return ret;
  129. }
  130. /**
  131. * Creates a new type array with a fresh type inserted at the beginning.
  132. *
  133. *
  134. * @param start the left hand side of the new array
  135. * @param types the right hand side of the new array
  136. */
  137. public static TypeX[] insert(TypeX start, TypeX[] types) {
  138. int len = types.length;
  139. TypeX[] ret = new TypeX[len + 1];
  140. ret[0] = start;
  141. System.arraycopy(types, 0, ret, 1, len);
  142. return ret;
  143. }
  144. /**
  145. * Constructs a Type for a JVM bytecode signature string. For example:
  146. *
  147. * <blockquote><pre>
  148. * TypeX.forSignature("[Ljava/lang/Thread;")
  149. * TypeX.forSignature("I");
  150. * </pre></blockquote>
  151. *
  152. * Types may equivalently be produced by this or by {@link #forName(String)}.
  153. *
  154. * <blockquote><pre>
  155. * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  156. * TypeX.forName("int").equals(Type.forSignature("I"))
  157. * </pre></blockquote>
  158. *
  159. * @param signature the JVM bytecode signature string for the desired type.
  160. * @return a type object represnting that JVM bytecode signature.
  161. */
  162. public static TypeX forSignature(String signature) {
  163. switch (signature.charAt(0)) {
  164. case 'B': return ResolvedTypeX.BYTE;
  165. case 'C': return ResolvedTypeX.CHAR;
  166. case 'D': return ResolvedTypeX.DOUBLE;
  167. case 'F': return ResolvedTypeX.FLOAT;
  168. case 'I': return ResolvedTypeX.INT;
  169. case 'J': return ResolvedTypeX.LONG;
  170. case 'L':
  171. return new TypeX(signature);
  172. case 'S': return ResolvedTypeX.SHORT;
  173. case 'V': return ResolvedTypeX.VOID;
  174. case 'Z': return ResolvedTypeX.BOOLEAN;
  175. case '[':
  176. return new TypeX(signature);
  177. default:
  178. throw new BCException("Bad type signature " + signature);
  179. }
  180. }
  181. /** Constructs a TypeX for each JVM bytecode type signature in an incoming array.
  182. *
  183. * @param names an array of JVM bytecode type signatures
  184. * @return an array of TypeX objects.
  185. * @see #forSignature(String)
  186. */
  187. public static TypeX[] forSignatures(String[] sigs) {
  188. TypeX[] ret = new TypeX[sigs.length];
  189. for (int i = 0, len = sigs.length; i < len; i++) {
  190. ret[i] = TypeX.forSignature(sigs[i]);
  191. }
  192. return ret;
  193. }
  194. /**
  195. * Returns the name of this type in java language form. For all
  196. * TypeX t:
  197. *
  198. * <blockquote><pre>
  199. * TypeX.forName(t.getName()).equals(t)
  200. * </pre></blockquote>
  201. *
  202. * and for all String s where s is a lexically valid java language typename:
  203. *
  204. * <blockquote><pre>
  205. * TypeX.forName(s).getName().equals(s)
  206. * </pre></blockquote>
  207. *
  208. * This produces a more esthetically pleasing string than
  209. * {@link java.lang.Class#getName()}.
  210. *
  211. * @return the java language name of this type.
  212. */
  213. public String getName() {
  214. return signatureToName(signature);
  215. }
  216. public String getBaseName() {
  217. String name = getName();
  218. if (isParameterized()) {
  219. return name.substring(0,name.indexOf("<"));
  220. } else {
  221. return name;
  222. }
  223. }
  224. /**
  225. * Returns an array of strings representing the java langauge names of
  226. * an array of types.
  227. *
  228. * @param types an array of TypeX objects
  229. * @return an array of Strings fo the java language names of types.
  230. * @see #getName()
  231. */
  232. public static String[] getNames(TypeX[] types) {
  233. String[] ret = new String[types.length];
  234. for (int i = 0, len = types.length; i < len; i++) {
  235. ret[i] = types[i].getName();
  236. }
  237. return ret;
  238. }
  239. /**
  240. * Returns the name of this type in JVM signature form. For all
  241. * TypeX t:
  242. *
  243. * <blockquote><pre>
  244. * TypeX.forSignature(t.getSignature()).equals(t)
  245. * </pre></blockquote>
  246. *
  247. * and for all String s where s is a lexically valid JVM type signature string:
  248. *
  249. * <blockquote><pre>
  250. * TypeX.forSignature(s).getSignature().equals(s)
  251. * </pre></blockquote>
  252. *
  253. * @return the java JVM signature string for this type.
  254. */
  255. public String getSignature() {
  256. return signature;
  257. }
  258. /**
  259. * Determins if this represents an array type.
  260. *
  261. * @return true iff this represents an array type.
  262. */
  263. public final boolean isArray() {
  264. return signature.startsWith("[");
  265. }
  266. /**
  267. * Determines if this represents a parameterized type.
  268. */
  269. public final boolean isParameterized() {
  270. return signature.indexOf("<") != -1;
  271. //(typeParameters != null) && (typeParameters.length > 0);
  272. }
  273. /**
  274. * Returns a TypeX object representing the effective outermost enclosing type
  275. * for a name type. For all other types, this will return the type itself.
  276. *
  277. * The only guarantee is given in JLS 13.1 where code generated according to
  278. * those rules will have type names that can be split apart in this way.
  279. * @return the outermost enclosing TypeX object or this.
  280. */
  281. public TypeX getOutermostType() {
  282. if (isArray() || isPrimitive()) return this;
  283. String sig = getSignature();
  284. int dollar = sig.indexOf('$');
  285. if (dollar != -1) {
  286. return TypeX.forSignature(sig.substring(0, dollar) + ';');
  287. } else {
  288. return this;
  289. }
  290. }
  291. /**
  292. * Returns a TypeX object representing the component type of this array, or
  293. * null if this type does not represent an array type.
  294. *
  295. * @return the component TypeX object, or null.
  296. */
  297. public TypeX getComponentType() {
  298. if (isArray()) {
  299. return forSignature(signature.substring(1));
  300. } else {
  301. return null;
  302. }
  303. }
  304. /**
  305. * Determines if this represents a primitive type. A primitive type
  306. * is one of nine predefined resolved types.
  307. *
  308. * @return true iff this type represents a primitive type
  309. *
  310. * @see ResolvedTypeX#Boolean
  311. * @see ResolvedTypeX#Character
  312. * @see ResolvedTypeX#Byte
  313. * @see ResolvedTypeX#Short
  314. * @see ResolvedTypeX#Integer
  315. * @see ResolvedTypeX#Long
  316. * @see ResolvedTypeX#Float
  317. * @see ResolvedTypeX#Double
  318. * @see ResolvedTypeX#Void
  319. */
  320. public boolean isPrimitive() {
  321. return false;
  322. }
  323. /**
  324. * Returns a java language string representation of this type.
  325. */
  326. public String toString() {
  327. return getName();
  328. }
  329. // ---- requires worlds
  330. /**
  331. * Types may have pointcuts just as they have methods and fields.
  332. */
  333. public ResolvedPointcutDefinition findPointcut(String name, World world) {
  334. return world.findPointcut(this, name);
  335. }
  336. /**
  337. * Determines if variables of this type could be assigned values of another
  338. * with lots of help.
  339. * java.lang.Object is convertable from all types.
  340. * A primitive type is convertable from X iff it's assignable from X.
  341. * A reference type is convertable from X iff it's coerceable from X.
  342. * In other words, X isConvertableFrom Y iff the compiler thinks that _some_ value of Y
  343. * could be assignable to a variable of type X without loss of precision.
  344. *
  345. * @param other the other type
  346. * @param world the {@link World} in which the possible assignment should be checked.
  347. * @return true iff variables of this type could be assigned values of other with possible conversion
  348. */
  349. public final boolean isConvertableFrom(TypeX other, World world) {
  350. if (this.equals(OBJECT)) return true;
  351. if (this.isPrimitive() || other.isPrimitive()) return this.isAssignableFrom(other, world);
  352. return this.isCoerceableFrom(other, world);
  353. }
  354. /**
  355. * Determines if variables of this type could be assigned values of another
  356. * without any conversion computation of any kind. For primitive types
  357. * this means equality, and for reference types it means assignability.
  358. *
  359. * @param other the other type
  360. * @param world the {@link World} in which the possible assignment should be checked.
  361. * @return true iff variables of this type could be assigned values of other without any conversion computation
  362. */
  363. public boolean needsNoConversionFrom(TypeX other, World world) {
  364. // primitives override this method, so we know we're not primitive.
  365. // So if the other is primitive, don't bother asking the world anything.
  366. if (other.isPrimitive()) return false;
  367. return world.needsNoConversionFrom(this, other);
  368. }
  369. /**
  370. * Determines if the variables of this type could be assigned values
  371. * of another type without casting. This still allows for assignment conversion
  372. * as per JLS 2ed 5.2. For object types, this means supertypeOrEqual(THIS, OTHER).
  373. *
  374. * @param other the other type
  375. * @param world the {@link World} in which the possible assignment should be checked.
  376. * @return true iff variables of this type could be assigned values of other without casting
  377. * @exception NullPointerException if other is null
  378. */
  379. public boolean isAssignableFrom(TypeX other, World world) {
  380. // primitives override this method, so we know we're not primitive.
  381. // So if the other is primitive, don't bother asking the world anything.
  382. if (other.isPrimitive() && !world.behaveInJava5Way) return false;
  383. return world.isAssignableFrom(this, other);
  384. }
  385. /**
  386. * Determines if values of another type could possibly be cast to
  387. * this type. The rules followed are from JLS 2ed 5.5, "Casting Conversion".
  388. *
  389. * <p> This method should be commutative, i.e., for all TypeX a, b and all World w:
  390. *
  391. * <blockquote><pre>
  392. * a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
  393. * </pre></blockquote>
  394. *
  395. * @param other the other type
  396. * @param world the {@link World} in which the possible coersion should be checked.
  397. * @return true iff values of other could possibly be cast to this type.
  398. * @exception NullPointerException if other is null.
  399. */
  400. public boolean isCoerceableFrom(TypeX other, World world) {
  401. // primitives override this method, so we know we're not primitive.
  402. // So if the other is primitive, don't bother asking the world anything.
  403. if (other.isPrimitive()) return false;
  404. return world.isCoerceableFrom(this, other);
  405. }
  406. /**
  407. * Determines if this represents an interface type.
  408. *
  409. * @param world the {@link World} in which we should check.
  410. * @return true iff this represents an interface type.
  411. */
  412. public final boolean isInterface(World world) {
  413. return world.resolve(this).isInterface();
  414. }
  415. /**
  416. * Determines if this represents a class type.
  417. *
  418. * @param world the {@link World} in which we should check.
  419. * @return true iff this represents a class type.
  420. */
  421. public final boolean isClass(World world) {
  422. return world.resolve(this).isClass();
  423. }
  424. /**
  425. * Determines if this class represents an enum type.
  426. */
  427. public final boolean isEnum(World world) {
  428. return world.resolve(this).isEnum();
  429. }
  430. /**
  431. * Determines if this class represents an annotation type.
  432. */
  433. public final boolean isAnnotation(World world) {
  434. return world.resolve(this).isAnnotation();
  435. }
  436. /**
  437. * Determine if this class represents an annotation type that has runtime retention
  438. */
  439. public final boolean isAnnotationWithRuntimeRetention(World world) {
  440. return world.resolve(this).isAnnotationWithRuntimeRetention();
  441. }
  442. /**
  443. * Determines if this represents an aspect type.
  444. *
  445. * @param world the {@link World} in which we should check.
  446. * @return true iff this represents an aspect type.
  447. */
  448. public final boolean isAspect(World world) {
  449. return world.resolve(this).isAspect();
  450. }
  451. /**
  452. * Returns a TypeX object representing the superclass of this type, or null.
  453. * If this represents a java.lang.Object, a primitive type, or void, this
  454. * method returns null.
  455. *
  456. * <p>
  457. * This differs from {@link java.lang.class#getSuperclass()} in that
  458. * this returns a TypeX object representing java.lang.Object for interfaces instead
  459. * of returning null.
  460. *
  461. * @param world the {@link World} in which the lookup should be made.
  462. * @return this type's superclass, or null if none exists.
  463. */
  464. public TypeX getSuperclass(World world) {
  465. return world.getSuperclass(this);
  466. }
  467. /**
  468. * Returns an array of TypeX objects representing the declared interfaces
  469. * of this type.
  470. *
  471. * <p>
  472. * If this object represents a class, the declared interfaces are those it
  473. * implements. If this object represents an interface, the declared interfaces
  474. * are those it extends. If this object represents a primitive, an empty
  475. * array is returned. If this object represents an array, an array
  476. * containing types for java.lang.Cloneable and java.io.Serializable is returned.
  477. *
  478. * @param world the {@link World} in which the lookup should be made.
  479. * @return an iterator through the declared interfaces of this type.
  480. */
  481. public TypeX[] getDeclaredInterfaces(World world) {
  482. return world.getDeclaredInterfaces(this);
  483. }
  484. /**
  485. * Returns an iterator through TypeX objects representing all the direct
  486. * supertypes of this type. That is, through the superclass, if any, and
  487. * all declared interfaces.
  488. *
  489. * @param world the {@link World} in which the lookup should be made.
  490. * @return an iterator through the direct supertypes of this type.
  491. */
  492. public Iterator getDirectSupertypes(World world) {
  493. return world.resolve(this).getDirectSupertypes();
  494. }
  495. /**
  496. * Returns the modifiers for this type.
  497. *
  498. * See {@link java.lang.Class#getModifiers()} for a description
  499. * of the weirdness of this methods on primitives and arrays.
  500. *
  501. * @param world the {@link World} in which the lookup is made.
  502. * @return an int representing the modifiers for this type
  503. * @see java.lang.reflect.Modifier
  504. */
  505. public int getModifiers(World world) {
  506. return world.getModifiers(this);
  507. }
  508. /**
  509. * Returns an array representing the declared fields of this object. This may include
  510. * non-user-visible fields.
  511. * This method returns an
  512. * empty array if it represents an array type or a primitive type, so
  513. * the implicit length field of arrays is just that, implicit.
  514. *
  515. * @param world the {@link World} in which the lookup is done.
  516. * @return the array representing the declared fields of this type
  517. */
  518. public ResolvedMember[] getDeclaredFields(World world) {
  519. return world.getDeclaredFields(this);
  520. }
  521. /**
  522. * Returns an array representing the declared methods of this object. This includes
  523. * constructors and the static initialzation method. This also includes all
  524. * shadowMungers in an aspect. So it may include more than the user-visible methods.
  525. * This method returns an
  526. * empty array if it represents an array type or a primitive type.
  527. *
  528. * @param world the {@link World} in which the lookup is done.
  529. * @return the array representing the declared methods of this type
  530. */
  531. public ResolvedMember[] getDeclaredMethods(World world) {
  532. return world.getDeclaredMethods(this);
  533. }
  534. /**
  535. * Returns an array representing the declared pointcuts of this object.
  536. * This method returns an
  537. * empty array if it represents an array type or a primitive type.
  538. *
  539. * @param world the {@link World} in which the lookup is done.
  540. * @return the array representing the declared pointcuts of this type
  541. */
  542. public ResolvedMember[] getDeclaredPointcuts(World world) {
  543. return world.getDeclaredPointcuts(this);
  544. }
  545. /**
  546. * Returns a resolved version of this type according to a particular world.
  547. *
  548. * @param world thie {@link World} within which to resolve.
  549. * @return a resolved type representing this type in the appropriate world.
  550. */
  551. public ResolvedTypeX resolve(World world) {
  552. return world.resolve(this);
  553. }
  554. public boolean hasAnnotation(TypeX ofType) {
  555. throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
  556. }
  557. /* (non-Javadoc)
  558. * @see org.aspectj.weaver.AnnotatedElement#getAnnotationTypes()
  559. */
  560. public ResolvedTypeX[] getAnnotationTypes() {
  561. throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
  562. }
  563. // ---- fields
  564. public static final TypeX[] NONE = new TypeX[0];
  565. public static final TypeX OBJECT = forSignature("Ljava/lang/Object;");
  566. public static final TypeX OBJECTARRAY = forSignature("[Ljava/lang/Object;");
  567. public static final TypeX CLONEABLE = forSignature("Ljava/lang/Cloneable;");
  568. public static final TypeX SERIALIZABLE = forSignature("Ljava/io/Serializable;");
  569. public static final TypeX THROWABLE = forSignature("Ljava/lang/Throwable;");
  570. public static final TypeX RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;");
  571. public static final TypeX ERROR = forSignature("Ljava/lang/Error;");
  572. public static final TypeX AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
  573. public static final TypeX AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
  574. public static final TypeX ENUM = forSignature("Ljava/lang/Enum;");
  575. public static final TypeX ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;");
  576. public static final TypeX JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;");
  577. public static final TypeX JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;");
  578. public static final TypeX JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;");
  579. public static final TypeX SUPPRESS_AJ_WARNINGS = forSignature("Lorg/aspectj/lang/annotation/SuppressAjWarnings;");
  580. public static final TypeX AT_TARGET = forSignature("Ljava/lang/annotation/Target;");
  581. // ---- helpers
  582. private static String signatureToName(String signature) {
  583. switch (signature.charAt(0)) {
  584. case 'B': return "byte";
  585. case 'C': return "char";
  586. case 'D': return "double";
  587. case 'F': return "float";
  588. case 'I': return "int";
  589. case 'J': return "long";
  590. case 'L':
  591. String name = signature.substring(1, signature.length() - 1).replace('/', '.');
  592. if (name.indexOf("<") == -1) return name;
  593. // signature for parameterized types is e.g.
  594. // List<String> -> Ljava/util/List<Ljava/lang/String;>;
  595. // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
  596. StringBuffer nameBuff = new StringBuffer();
  597. boolean justSeenLeftArrowChar = false;
  598. boolean justSeenSemiColon= false;
  599. int paramNestLevel = 0;
  600. for (int i = 0 ; i < name.length(); i++) {
  601. char c = name.charAt(i);
  602. switch (c) {
  603. case '<' :
  604. justSeenLeftArrowChar = true;
  605. paramNestLevel++;
  606. nameBuff.append(c);
  607. break;
  608. case ';' :
  609. justSeenSemiColon = true;
  610. break;
  611. case '>' :
  612. paramNestLevel--;
  613. nameBuff.append(c);
  614. break;
  615. case 'L' :
  616. if (justSeenLeftArrowChar) {
  617. justSeenLeftArrowChar = false;
  618. break;
  619. }
  620. if (justSeenSemiColon) {
  621. nameBuff.append(",");
  622. } else {
  623. nameBuff.append("L");
  624. }
  625. break;
  626. default:
  627. justSeenSemiColon = false;
  628. justSeenLeftArrowChar = false;
  629. nameBuff.append(c);
  630. }
  631. }
  632. return nameBuff.toString();
  633. case 'S': return "short";
  634. case 'V': return "void";
  635. case 'Z': return "boolean";
  636. case '[':
  637. return signatureToName(signature.substring(1, signature.length())) + "[]";
  638. default:
  639. throw new BCException("Bad type signature: " + signature);
  640. }
  641. }
  642. private static String nameToSignature(String name) {
  643. if (name.equals("byte")) return "B";
  644. if (name.equals("char")) return "C";
  645. if (name.equals("double")) return "D";
  646. if (name.equals("float")) return "F";
  647. if (name.equals("int")) return "I";
  648. if (name.equals("long")) return "J";
  649. if (name.equals("short")) return "S";
  650. if (name.equals("boolean")) return "Z";
  651. if (name.equals("void")) return "V";
  652. if (name.endsWith("[]"))
  653. return "[" + nameToSignature(name.substring(0, name.length() - 2));
  654. if (name.length() != 0) {
  655. // lots more tests could be made here...
  656. // 1) If it is already an array type, do not mess with it.
  657. if (name.charAt(0)=='[' && name.charAt(name.length()-1)==';') return name;
  658. else {
  659. if (name.indexOf("<") == -1) {
  660. // not parameterised
  661. return "L" + name.replace('.', '/') + ";";
  662. } else {
  663. StringBuffer nameBuff = new StringBuffer();
  664. nameBuff.append("L");
  665. for (int i = 0; i < name.length(); i++) {
  666. char c = name.charAt(i);
  667. switch (c) {
  668. case '.' : nameBuff.append('/'); break;
  669. case '<' : nameBuff.append("<L"); break;
  670. case '>' : nameBuff.append(";>"); break;
  671. case ',' : nameBuff.append(";L"); break;
  672. default: nameBuff.append(c);
  673. }
  674. }
  675. nameBuff.append(";");
  676. return nameBuff.toString();
  677. }
  678. }
  679. }
  680. else
  681. throw new BCException("Bad type name: " + name);
  682. }
  683. public void write(DataOutputStream s) throws IOException {
  684. s.writeUTF(signature);
  685. }
  686. public static TypeX read(DataInputStream s) throws IOException {
  687. String sig = s.readUTF();
  688. if (sig.equals(MISSING_NAME)) {
  689. return ResolvedTypeX.MISSING;
  690. } else {
  691. return TypeX.forSignature(sig);
  692. }
  693. }
  694. public static void writeArray(TypeX[] types, DataOutputStream s) throws IOException {
  695. int len = types.length;
  696. s.writeShort(len);
  697. for (int i=0; i < len; i++) {
  698. types[i].write(s);
  699. }
  700. }
  701. public static TypeX[] readArray(DataInputStream s) throws IOException {
  702. int len = s.readShort();
  703. TypeX[] types = new TypeX[len];
  704. for (int i=0; i < len; i++) {
  705. types[i] = TypeX.read(s);
  706. }
  707. return types;
  708. }
  709. /**
  710. * For debugging purposes
  711. */
  712. public void dump(World world) {
  713. if (isAspect(world)) System.out.print("aspect ");
  714. else if (isInterface(world)) System.out.print("interface ");
  715. else if (isClass(world)) System.out.print("class ");
  716. System.out.println(toString());
  717. dumpResolvedMembers("fields", getDeclaredFields(world));
  718. dumpResolvedMembers("methods", getDeclaredMethods(world));
  719. dumpResolvedMembers("pointcuts", getDeclaredPointcuts(world));
  720. }
  721. private void dumpResolvedMembers(String label, ResolvedMember[] l) {
  722. final String indent = " ";
  723. System.out.println(label);
  724. if (l == null) {
  725. System.out.println(indent + "null");
  726. return;
  727. }
  728. for (int i=0, len=l.length; i < len; i++) {
  729. System.out.println(indent + l[i]);
  730. }
  731. }
  732. // ----
  733. public String getNameAsIdentifier() {
  734. return getName().replace('.', '_');
  735. }
  736. public String getPackageNameAsIdentifier() {
  737. String name = getName();
  738. int index = name.lastIndexOf('.');
  739. if (index == -1) {
  740. return "";
  741. } else {
  742. return name.substring(0, index).replace('.', '_');
  743. }
  744. }
  745. public String getPackageName() {
  746. String name = getName();
  747. int index = name.lastIndexOf('.');
  748. if (index == -1) {
  749. return null;
  750. } else {
  751. return name.substring(0, index);
  752. }
  753. }
  754. public TypeX[] getTypeParameters() {
  755. return typeParameters == null ? new TypeX[0] : typeParameters;
  756. }
  757. /**
  758. * Doesn't include the package
  759. */
  760. public String getClassName() {
  761. String name = getName();
  762. int index = name.lastIndexOf('.');
  763. if (index == -1) {
  764. return name;
  765. } else {
  766. return name.substring(index+1);
  767. }
  768. }
  769. public static final String MISSING_NAME = "<missing>";
  770. }