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.

SignatureAttribute.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later,
  9. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.bytecode;
  17. import java.io.DataInputStream;
  18. import java.io.IOException;
  19. import java.util.ArrayList;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Map;
  23. import javassist.CtClass;
  24. /**
  25. * <code>Signature_attribute</code>.
  26. */
  27. public class SignatureAttribute extends AttributeInfo {
  28. /**
  29. * The name of this attribute <code>"Signature"</code>.
  30. */
  31. public static final String tag = "Signature";
  32. SignatureAttribute(ConstPool cp, int n, DataInputStream in)
  33. throws IOException
  34. {
  35. super(cp, n, in);
  36. }
  37. /**
  38. * Constructs a <code>Signature</code> attribute.
  39. *
  40. * @param cp a constant pool table.
  41. * @param signature the signature represented by this attribute.
  42. */
  43. public SignatureAttribute(ConstPool cp, String signature) {
  44. super(cp, tag);
  45. int index = cp.addUtf8Info(signature);
  46. byte[] bvalue = new byte[2];
  47. bvalue[0] = (byte)(index >>> 8);
  48. bvalue[1] = (byte)index;
  49. set(bvalue);
  50. }
  51. /**
  52. * Returns the generic signature indicated by <code>signature_index</code>.
  53. *
  54. * @see #toClassSignature(String)
  55. * @see #toMethodSignature(String)
  56. * @see #toFieldSignature(String)
  57. */
  58. public String getSignature() {
  59. return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
  60. }
  61. /**
  62. * Sets <code>signature_index</code> to the index of the given generic signature,
  63. * which is added to a constant pool.
  64. *
  65. * @param sig new signature.
  66. * @since 3.11
  67. */
  68. public void setSignature(String sig) {
  69. int index = getConstPool().addUtf8Info(sig);
  70. ByteArray.write16bit(index, info, 0);
  71. }
  72. /**
  73. * Makes a copy. Class names are replaced according to the
  74. * given <code>Map</code> object.
  75. *
  76. * @param newCp the constant pool table used by the new copy.
  77. * @param classnames pairs of replaced and substituted
  78. * class names.
  79. */
  80. @Override
  81. public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) {
  82. return new SignatureAttribute(newCp, getSignature());
  83. }
  84. @Override
  85. void renameClass(String oldname, String newname) {
  86. String sig = renameClass(getSignature(), oldname, newname);
  87. setSignature(sig);
  88. }
  89. @Override
  90. void renameClass(Map<String,String> classnames) {
  91. String sig = renameClass(getSignature(), classnames);
  92. setSignature(sig);
  93. }
  94. static String renameClass(String desc, String oldname, String newname) {
  95. Map<String,String> map = new HashMap<String,String>();
  96. map.put(oldname, newname);
  97. return renameClass(desc, map);
  98. }
  99. static String renameClass(String desc, Map<String,String> map) {
  100. if (map == null)
  101. return desc;
  102. StringBuilder newdesc = new StringBuilder();
  103. int head = 0;
  104. int i = 0;
  105. for (;;) {
  106. int j = desc.indexOf('L', i);
  107. if (j < 0)
  108. break;
  109. int k = desc.indexOf(';', j);
  110. if (k < 0)
  111. break;
  112. int l = desc.indexOf('<', j);
  113. int classEndIndex;
  114. char classEndChar;
  115. if (l < 0 || k < l) {
  116. classEndIndex = k;
  117. classEndChar = ';';
  118. } else {
  119. classEndIndex = l;
  120. classEndChar = '<';
  121. }
  122. i = classEndIndex + 1;
  123. String name = desc.substring(j + 1, classEndIndex);
  124. String name2 = map.get(name);
  125. if (name2 != null) {
  126. newdesc.append(desc.substring(head, j));
  127. newdesc.append('L');
  128. newdesc.append(name2);
  129. newdesc.append(classEndChar);
  130. head = i;
  131. }
  132. }
  133. if (head == 0)
  134. return desc;
  135. int len = desc.length();
  136. if (head < len)
  137. newdesc.append(desc.substring(head, len));
  138. return newdesc.toString();
  139. }
  140. @SuppressWarnings("unused")
  141. private static boolean isNamePart(int c) {
  142. return c != ';' && c != '<';
  143. }
  144. static private class Cursor {
  145. int position = 0;
  146. int indexOf(String s, int ch) throws BadBytecode {
  147. int i = s.indexOf(ch, position);
  148. if (i < 0)
  149. throw error(s);
  150. position = i + 1;
  151. return i;
  152. }
  153. }
  154. /**
  155. * Class signature.
  156. */
  157. public static class ClassSignature {
  158. TypeParameter[] params;
  159. ClassType superClass;
  160. ClassType[] interfaces;
  161. /**
  162. * Constructs a class signature.
  163. *
  164. * @param params type parameters.
  165. * @param superClass the super class.
  166. * @param interfaces the interface types.
  167. */
  168. public ClassSignature(TypeParameter[] params, ClassType superClass, ClassType[] interfaces) {
  169. this.params = params == null ? new TypeParameter[0] : params;
  170. this.superClass = superClass == null ? ClassType.OBJECT : superClass;
  171. this.interfaces = interfaces == null ? new ClassType[0] : interfaces;
  172. }
  173. /**
  174. * Constructs a class signature.
  175. *
  176. * @param p type parameters.
  177. */
  178. public ClassSignature(TypeParameter[] p) {
  179. this(p, null, null);
  180. }
  181. /**
  182. * Returns the type parameters.
  183. *
  184. * @return a zero-length array if the type parameters are not specified.
  185. */
  186. public TypeParameter[] getParameters() {
  187. return params;
  188. }
  189. /**
  190. * Returns the super class.
  191. */
  192. public ClassType getSuperClass() { return superClass; }
  193. /**
  194. * Returns the super interfaces.
  195. *
  196. * @return a zero-length array if the super interfaces are not specified.
  197. */
  198. public ClassType[] getInterfaces() { return interfaces; }
  199. /**
  200. * Returns the string representation.
  201. */
  202. @Override
  203. public String toString() {
  204. StringBuffer sbuf = new StringBuffer();
  205. TypeParameter.toString(sbuf, params);
  206. sbuf.append(" extends ").append(superClass);
  207. if (interfaces.length > 0) {
  208. sbuf.append(" implements ");
  209. Type.toString(sbuf, interfaces);
  210. }
  211. return sbuf.toString();
  212. }
  213. /**
  214. * Returns the encoded string representing the method type signature.
  215. */
  216. public String encode() {
  217. StringBuffer sbuf = new StringBuffer();
  218. if (params.length > 0) {
  219. sbuf.append('<');
  220. for (int i = 0; i < params.length; i++)
  221. params[i].encode(sbuf);
  222. sbuf.append('>');
  223. }
  224. superClass.encode(sbuf);
  225. for (int i = 0; i < interfaces.length; i++)
  226. interfaces[i].encode(sbuf);
  227. return sbuf.toString();
  228. }
  229. }
  230. /**
  231. * Method type signature.
  232. */
  233. public static class MethodSignature {
  234. TypeParameter[] typeParams;
  235. Type[] params;
  236. Type retType;
  237. ObjectType[] exceptions;
  238. /**
  239. * Constructs a method type signature. Any parameter can be null
  240. * to represent <code>void</code> or nothing.
  241. *
  242. * @param tp type parameters.
  243. * @param params parameter types.
  244. * @param ret a return type, or null if the return type is <code>void</code>.
  245. * @param ex exception types.
  246. */
  247. public MethodSignature(TypeParameter[] tp, Type[] params, Type ret, ObjectType[] ex) {
  248. typeParams = tp == null ? new TypeParameter[0] : tp;
  249. this.params = params == null ? new Type[0] : params;
  250. retType = ret == null ? new BaseType("void") : ret;
  251. exceptions = ex == null ? new ObjectType[0] : ex;
  252. }
  253. /**
  254. * Returns the formal type parameters.
  255. *
  256. * @return a zero-length array if the type parameters are not specified.
  257. */
  258. public TypeParameter[] getTypeParameters() { return typeParams; }
  259. /**
  260. * Returns the types of the formal parameters.
  261. *
  262. * @return a zero-length array if no formal parameter is taken.
  263. */
  264. public Type[] getParameterTypes() { return params; }
  265. /**
  266. * Returns the type of the returned value.
  267. */
  268. public Type getReturnType() { return retType; }
  269. /**
  270. * Returns the types of the exceptions that may be thrown.
  271. *
  272. * @return a zero-length array if exceptions are never thrown or
  273. * the exception types are not parameterized types or type variables.
  274. */
  275. public ObjectType[] getExceptionTypes() { return exceptions; }
  276. /**
  277. * Returns the string representation.
  278. */
  279. @Override
  280. public String toString() {
  281. StringBuffer sbuf = new StringBuffer();
  282. TypeParameter.toString(sbuf, typeParams);
  283. sbuf.append(" (");
  284. Type.toString(sbuf, params);
  285. sbuf.append(") ");
  286. sbuf.append(retType);
  287. if (exceptions.length > 0) {
  288. sbuf.append(" throws ");
  289. Type.toString(sbuf, exceptions);
  290. }
  291. return sbuf.toString();
  292. }
  293. /**
  294. * Returns the encoded string representing the method type signature.
  295. */
  296. public String encode() {
  297. StringBuffer sbuf = new StringBuffer();
  298. if (typeParams.length > 0) {
  299. sbuf.append('<');
  300. for (int i = 0; i < typeParams.length; i++)
  301. typeParams[i].encode(sbuf);
  302. sbuf.append('>');
  303. }
  304. sbuf.append('(');
  305. for (int i = 0; i < params.length; i++)
  306. params[i].encode(sbuf);
  307. sbuf.append(')');
  308. retType.encode(sbuf);
  309. if (exceptions.length > 0)
  310. for (int i = 0; i < exceptions.length; i++) {
  311. sbuf.append('^');
  312. exceptions[i].encode(sbuf);
  313. }
  314. return sbuf.toString();
  315. }
  316. }
  317. /**
  318. * Formal type parameters.
  319. *
  320. * @see TypeArgument
  321. */
  322. public static class TypeParameter {
  323. String name;
  324. ObjectType superClass;
  325. ObjectType[] superInterfaces;
  326. TypeParameter(String sig, int nb, int ne, ObjectType sc, ObjectType[] si) {
  327. name = sig.substring(nb, ne);
  328. superClass = sc;
  329. superInterfaces = si;
  330. }
  331. /**
  332. * Constructs a <code>TypeParameter</code> representing a type parametre
  333. * like <code>&lt;T extends ... &gt;</code>.
  334. *
  335. * @param name parameter name.
  336. * @param superClass an upper bound class-type (or null).
  337. * @param superInterfaces an upper bound interface-type (or null).
  338. */
  339. public TypeParameter(String name, ObjectType superClass, ObjectType[] superInterfaces) {
  340. this.name = name;
  341. this.superClass = superClass;
  342. if (superInterfaces == null)
  343. this.superInterfaces = new ObjectType[0];
  344. else
  345. this.superInterfaces = superInterfaces;
  346. }
  347. /**
  348. * Constructs a <code>TypeParameter</code> representing a type parameter
  349. * like <code>&lt;T&gt;</code>.
  350. *
  351. * @param name parameter name.
  352. */
  353. public TypeParameter(String name) {
  354. this(name, null, null);
  355. }
  356. /**
  357. * Returns the name of the type parameter.
  358. */
  359. public String getName() {
  360. return name;
  361. }
  362. /**
  363. * Returns the class bound of this parameter.
  364. */
  365. public ObjectType getClassBound() { return superClass; }
  366. /**
  367. * Returns the interface bound of this parameter.
  368. *
  369. * @return a zero-length array if the interface bound is not specified.
  370. */
  371. public ObjectType[] getInterfaceBound() { return superInterfaces; }
  372. /**
  373. * Returns the string representation.
  374. */
  375. @Override
  376. public String toString() {
  377. StringBuffer sbuf = new StringBuffer(getName());
  378. if (superClass != null)
  379. sbuf.append(" extends ").append(superClass.toString());
  380. int len = superInterfaces.length;
  381. if (len > 0) {
  382. for (int i = 0; i < len; i++) {
  383. if (i > 0 || superClass != null)
  384. sbuf.append(" & ");
  385. else
  386. sbuf.append(" extends ");
  387. sbuf.append(superInterfaces[i].toString());
  388. }
  389. }
  390. return sbuf.toString();
  391. }
  392. static void toString(StringBuffer sbuf, TypeParameter[] tp) {
  393. sbuf.append('<');
  394. for (int i = 0; i < tp.length; i++) {
  395. if (i > 0)
  396. sbuf.append(", ");
  397. sbuf.append(tp[i]);
  398. }
  399. sbuf.append('>');
  400. }
  401. void encode(StringBuffer sb) {
  402. sb.append(name);
  403. if (superClass == null)
  404. sb.append(":Ljava/lang/Object;");
  405. else {
  406. sb.append(':');
  407. superClass.encode(sb);
  408. }
  409. for (int i = 0; i < superInterfaces.length; i++) {
  410. sb.append(':');
  411. superInterfaces[i].encode(sb);
  412. }
  413. }
  414. }
  415. /**
  416. * Type argument.
  417. *
  418. * @see TypeParameter
  419. */
  420. public static class TypeArgument {
  421. ObjectType arg;
  422. char wildcard;
  423. TypeArgument(ObjectType a, char w) {
  424. arg = a;
  425. wildcard = w;
  426. }
  427. /**
  428. * Constructs a <code>TypeArgument</code>.
  429. * A type argument is <code>&lt;String&gt;</code>, <code>&lt;int[]&gt;</code>,
  430. * or a type variable <code>&lt;T&gt;</code>, etc.
  431. *
  432. * @param t a class type, an array type, or a type variable.
  433. */
  434. public TypeArgument(ObjectType t) {
  435. this(t, ' ');
  436. }
  437. /**
  438. * Constructs a <code>TypeArgument</code> representing <code>&lt;?&gt;</code>.
  439. */
  440. public TypeArgument() {
  441. this(null, '*');
  442. }
  443. /**
  444. * A factory method constructing a <code>TypeArgument</code> with an upper bound.
  445. * It represents <code>&lt;? extends ... &gt;</code>
  446. *
  447. * @param t an upper bound type.
  448. */
  449. public static TypeArgument subclassOf(ObjectType t) {
  450. return new TypeArgument(t, '+');
  451. }
  452. /**
  453. * A factory method constructing a <code>TypeArgument</code> with an lower bound.
  454. * It represents <code>&lt;? super ... &gt;</code>
  455. *
  456. * @param t an lower bbound type.
  457. */
  458. public static TypeArgument superOf(ObjectType t) {
  459. return new TypeArgument(t, '-');
  460. }
  461. /**
  462. * Returns the kind of this type argument.
  463. *
  464. * @return <code>' '</code> (not-wildcard), <code>'*'</code> (wildcard), <code>'+'</code> (wildcard with
  465. * upper bound), or <code>'-'</code> (wildcard with lower bound).
  466. */
  467. public char getKind() { return wildcard; }
  468. /**
  469. * Returns true if this type argument is a wildcard type
  470. * such as <code>?</code>, <code>? extends String</code>, or <code>? super Integer</code>.
  471. */
  472. public boolean isWildcard() { return wildcard != ' '; }
  473. /**
  474. * Returns the type represented by this argument
  475. * if the argument is not a wildcard type. Otherwise, this method
  476. * returns the upper bound (if the kind is '+'),
  477. * the lower bound (if the kind is '-'), or null (if the upper or lower
  478. * bound is not specified).
  479. */
  480. public ObjectType getType() { return arg; }
  481. /**
  482. * Returns the string representation.
  483. */
  484. @Override
  485. public String toString() {
  486. if (wildcard == '*')
  487. return "?";
  488. String type = arg.toString();
  489. if (wildcard == ' ')
  490. return type;
  491. else if (wildcard == '+')
  492. return "? extends " + type;
  493. else
  494. return "? super " + type;
  495. }
  496. static void encode(StringBuffer sb, TypeArgument[] args) {
  497. sb.append('<');
  498. for (int i = 0; i < args.length; i++) {
  499. TypeArgument ta = args[i];
  500. if (ta.isWildcard())
  501. sb.append(ta.wildcard);
  502. if (ta.getType() != null)
  503. ta.getType().encode(sb);
  504. }
  505. sb.append('>');
  506. }
  507. }
  508. /**
  509. * Primitive types and object types.
  510. */
  511. public static abstract class Type {
  512. abstract void encode(StringBuffer sb);
  513. static void toString(StringBuffer sbuf, Type[] ts) {
  514. for (int i = 0; i < ts.length; i++) {
  515. if (i > 0)
  516. sbuf.append(", ");
  517. sbuf.append(ts[i]);
  518. }
  519. }
  520. /**
  521. * Returns the type name in the JVM internal style.
  522. * For example, if the type is a nested class {@code foo.Bar.Baz},
  523. * then {@code foo.Bar$Baz} is returned.
  524. */
  525. public String jvmTypeName() { return toString(); }
  526. }
  527. /**
  528. * Primitive types.
  529. */
  530. public static class BaseType extends Type {
  531. char descriptor;
  532. BaseType(char c) { descriptor = c; }
  533. /**
  534. * Constructs a <code>BaseType</code>.
  535. *
  536. * @param typeName <code>void</code>, <code>int</code>, ...
  537. */
  538. public BaseType(String typeName) {
  539. this(Descriptor.of(typeName).charAt(0));
  540. }
  541. /**
  542. * Returns the descriptor representing this primitive type.
  543. *
  544. * @see javassist.bytecode.Descriptor
  545. */
  546. public char getDescriptor() { return descriptor; }
  547. /**
  548. * Returns the <code>CtClass</code> representing this
  549. * primitive type.
  550. */
  551. public CtClass getCtlass() {
  552. return Descriptor.toPrimitiveClass(descriptor);
  553. }
  554. /**
  555. * Returns the string representation.
  556. */
  557. @Override
  558. public String toString() {
  559. return Descriptor.toClassName(Character.toString(descriptor));
  560. }
  561. @Override
  562. void encode(StringBuffer sb) {
  563. sb.append(descriptor);
  564. }
  565. }
  566. /**
  567. * Class types, array types, and type variables.
  568. * This class is also used for representing a field type.
  569. */
  570. public static abstract class ObjectType extends Type {
  571. /**
  572. * Returns the encoded string representing the object type signature.
  573. */
  574. public String encode() {
  575. StringBuffer sb = new StringBuffer();
  576. encode(sb);
  577. return sb.toString();
  578. }
  579. }
  580. /**
  581. * Class types.
  582. */
  583. public static class ClassType extends ObjectType {
  584. String name;
  585. TypeArgument[] arguments;
  586. static ClassType make(String s, int b, int e,
  587. TypeArgument[] targs, ClassType parent) {
  588. if (parent == null)
  589. return new ClassType(s, b, e, targs);
  590. return new NestedClassType(s, b, e, targs, parent);
  591. }
  592. ClassType(String signature, int begin, int end, TypeArgument[] targs) {
  593. name = signature.substring(begin, end).replace('/', '.');
  594. arguments = targs;
  595. }
  596. /**
  597. * A class type representing <code>java.lang.Object</code>.
  598. */
  599. public static ClassType OBJECT = new ClassType("java.lang.Object", null);
  600. /**
  601. * Constructs a <code>ClassType</code>. It represents
  602. * the name of a non-nested class.
  603. *
  604. * @param className a fully qualified class name.
  605. * @param args type arguments or null.
  606. */
  607. public ClassType(String className, TypeArgument[] args) {
  608. name = className;
  609. arguments = args;
  610. }
  611. /**
  612. * Constructs a <code>ClassType</code>. It represents
  613. * the name of a non-nested class.
  614. *
  615. * @param className a fully qualified class name.
  616. */
  617. public ClassType(String className) {
  618. this(className, null);
  619. }
  620. /**
  621. * Returns the class name.
  622. */
  623. public String getName() {
  624. return name;
  625. }
  626. /**
  627. * Returns the type arguments.
  628. *
  629. * @return null if no type arguments are given to this class.
  630. */
  631. public TypeArgument[] getTypeArguments() { return arguments; }
  632. /**
  633. * If this class is a member of another class, returns the
  634. * class in which this class is declared.
  635. *
  636. * @return null if this class is not a member of another class.
  637. */
  638. public ClassType getDeclaringClass() { return null; }
  639. /**
  640. * Returns the string representation.
  641. */
  642. @Override
  643. public String toString() {
  644. StringBuffer sbuf = new StringBuffer();
  645. ClassType parent = getDeclaringClass();
  646. if (parent != null)
  647. sbuf.append(parent.toString()).append('.');
  648. return toString2(sbuf);
  649. }
  650. private String toString2(StringBuffer sbuf) {
  651. sbuf.append(name);
  652. if (arguments != null) {
  653. sbuf.append('<');
  654. int n = arguments.length;
  655. for (int i = 0; i < n; i++) {
  656. if (i > 0)
  657. sbuf.append(", ");
  658. sbuf.append(arguments[i].toString());
  659. }
  660. sbuf.append('>');
  661. }
  662. return sbuf.toString();
  663. }
  664. /**
  665. * Returns the type name in the JVM internal style.
  666. * For example, if the type is a nested class {@code foo.Bar.Baz},
  667. * then {@code foo.Bar$Baz} is returned.
  668. */
  669. @Override
  670. public String jvmTypeName() {
  671. StringBuffer sbuf = new StringBuffer();
  672. ClassType parent = getDeclaringClass();
  673. if (parent != null)
  674. sbuf.append(parent.jvmTypeName()).append('$');
  675. return toString2(sbuf);
  676. }
  677. @Override
  678. void encode(StringBuffer sb) {
  679. sb.append('L');
  680. encode2(sb);
  681. sb.append(';');
  682. }
  683. void encode2(StringBuffer sb) {
  684. ClassType parent = getDeclaringClass();
  685. if (parent != null) {
  686. parent.encode2(sb);
  687. sb.append('$');
  688. }
  689. sb.append(name.replace('.', '/'));
  690. if (arguments != null)
  691. TypeArgument.encode(sb, arguments);
  692. }
  693. }
  694. /**
  695. * Nested class types.
  696. */
  697. public static class NestedClassType extends ClassType {
  698. ClassType parent;
  699. NestedClassType(String s, int b, int e,
  700. TypeArgument[] targs, ClassType p) {
  701. super(s, b, e, targs);
  702. parent = p;
  703. }
  704. /**
  705. * Constructs a <code>NestedClassType</code>.
  706. *
  707. * @param parent the class surrounding this class type.
  708. * @param className a simple class name. It does not include
  709. * a package name or a parent's class name.
  710. * @param args type parameters or null.
  711. */
  712. public NestedClassType(ClassType parent, String className, TypeArgument[] args) {
  713. super(className, args);
  714. this.parent = parent;
  715. }
  716. /**
  717. * Returns the class that declares this nested class.
  718. * This nested class is a member of that declaring class.
  719. */
  720. @Override
  721. public ClassType getDeclaringClass() { return parent; }
  722. }
  723. /**
  724. * Array types.
  725. */
  726. public static class ArrayType extends ObjectType {
  727. int dim;
  728. Type componentType;
  729. /**
  730. * Constructs an <code>ArrayType</code>.
  731. *
  732. * @param d dimension.
  733. * @param comp the component type.
  734. */
  735. public ArrayType(int d, Type comp) {
  736. dim = d;
  737. componentType = comp;
  738. }
  739. /**
  740. * Returns the dimension of the array.
  741. */
  742. public int getDimension() { return dim; }
  743. /**
  744. * Returns the component type.
  745. */
  746. public Type getComponentType() {
  747. return componentType;
  748. }
  749. /**
  750. * Returns the string representation.
  751. */
  752. @Override
  753. public String toString() {
  754. StringBuffer sbuf = new StringBuffer(componentType.toString());
  755. for (int i = 0; i < dim; i++)
  756. sbuf.append("[]");
  757. return sbuf.toString();
  758. }
  759. @Override
  760. void encode(StringBuffer sb) {
  761. for (int i = 0; i < dim; i++)
  762. sb.append('[');
  763. componentType.encode(sb);
  764. }
  765. }
  766. /**
  767. * Type variables.
  768. */
  769. public static class TypeVariable extends ObjectType {
  770. String name;
  771. TypeVariable(String sig, int begin, int end) {
  772. name = sig.substring(begin, end);
  773. }
  774. /**
  775. * Constructs a <code>TypeVariable</code>.
  776. *
  777. * @param name the name of a type variable.
  778. */
  779. public TypeVariable(String name) {
  780. this.name = name;
  781. }
  782. /**
  783. * Returns the variable name.
  784. */
  785. public String getName() {
  786. return name;
  787. }
  788. /**
  789. * Returns the string representation.
  790. */
  791. @Override
  792. public String toString() {
  793. return name;
  794. }
  795. @Override
  796. void encode(StringBuffer sb) {
  797. sb.append('T').append(name).append(';');
  798. }
  799. }
  800. /**
  801. * Parses the given signature string as a class signature.
  802. *
  803. * @param sig the signature obtained from the <code>SignatureAttribute</code>
  804. * of a <code>ClassFile</code>.
  805. * @return a tree-like data structure representing a class signature. It provides
  806. * convenient accessor methods.
  807. * @throws BadBytecode thrown when a syntactical error is found.
  808. * @see #getSignature()
  809. * @since 3.5
  810. */
  811. public static ClassSignature toClassSignature(String sig) throws BadBytecode {
  812. try {
  813. return parseSig(sig);
  814. }
  815. catch (IndexOutOfBoundsException e) {
  816. throw error(sig);
  817. }
  818. }
  819. /**
  820. * Parses the given signature string as a method type signature.
  821. *
  822. * @param sig the signature obtained from the <code>SignatureAttribute</code>
  823. * of a <code>MethodInfo</code>.
  824. * @return @return a tree-like data structure representing a method signature. It provides
  825. * convenient accessor methods.
  826. * @throws BadBytecode thrown when a syntactical error is found.
  827. * @see #getSignature()
  828. * @since 3.5
  829. */
  830. public static MethodSignature toMethodSignature(String sig) throws BadBytecode {
  831. try {
  832. return parseMethodSig(sig);
  833. }
  834. catch (IndexOutOfBoundsException e) {
  835. throw error(sig);
  836. }
  837. }
  838. /**
  839. * Parses the given signature string as a field type signature.
  840. *
  841. * @param sig the signature string obtained from the <code>SignatureAttribute</code>
  842. * of a <code>FieldInfo</code>.
  843. * @return the field type signature.
  844. * @throws BadBytecode thrown when a syntactical error is found.
  845. * @see #getSignature()
  846. * @since 3.5
  847. */
  848. public static ObjectType toFieldSignature(String sig) throws BadBytecode {
  849. try {
  850. return parseObjectType(sig, new Cursor(), false);
  851. }
  852. catch (IndexOutOfBoundsException e) {
  853. throw error(sig);
  854. }
  855. }
  856. /**
  857. * Parses the given signature string as a type signature.
  858. * The type signature is either the field type signature or a base type
  859. * descriptor including <code>void</code> type.
  860. *
  861. * @throws BadBytecode thrown when a syntactical error is found.
  862. * @since 3.18
  863. */
  864. public static Type toTypeSignature(String sig) throws BadBytecode {
  865. try {
  866. return parseType(sig, new Cursor());
  867. }
  868. catch (IndexOutOfBoundsException e) {
  869. throw error(sig);
  870. }
  871. }
  872. private static ClassSignature parseSig(String sig)
  873. throws BadBytecode, IndexOutOfBoundsException
  874. {
  875. Cursor cur = new Cursor();
  876. TypeParameter[] tp = parseTypeParams(sig, cur);
  877. ClassType superClass = parseClassType(sig, cur);
  878. int sigLen = sig.length();
  879. List<ClassType> ifArray = new ArrayList<ClassType>();
  880. while (cur.position < sigLen && sig.charAt(cur.position) == 'L')
  881. ifArray.add(parseClassType(sig, cur));
  882. ClassType[] ifs
  883. = ifArray.toArray(new ClassType[ifArray.size()]);
  884. return new ClassSignature(tp, superClass, ifs);
  885. }
  886. private static MethodSignature parseMethodSig(String sig)
  887. throws BadBytecode
  888. {
  889. Cursor cur = new Cursor();
  890. TypeParameter[] tp = parseTypeParams(sig, cur);
  891. if (sig.charAt(cur.position++) != '(')
  892. throw error(sig);
  893. List<Type> params = new ArrayList<Type>();
  894. while (sig.charAt(cur.position) != ')') {
  895. Type t = parseType(sig, cur);
  896. params.add(t);
  897. }
  898. cur.position++;
  899. Type ret = parseType(sig, cur);
  900. int sigLen = sig.length();
  901. List<ObjectType> exceptions = new ArrayList<ObjectType>();
  902. while (cur.position < sigLen && sig.charAt(cur.position) == '^') {
  903. cur.position++;
  904. ObjectType t = parseObjectType(sig, cur, false);
  905. if (t instanceof ArrayType)
  906. throw error(sig);
  907. exceptions.add(t);
  908. }
  909. Type[] p = params.toArray(new Type[params.size()]);
  910. ObjectType[] ex = exceptions.toArray(new ObjectType[exceptions.size()]);
  911. return new MethodSignature(tp, p, ret, ex);
  912. }
  913. private static TypeParameter[] parseTypeParams(String sig, Cursor cur)
  914. throws BadBytecode
  915. {
  916. List<TypeParameter> typeParam = new ArrayList<TypeParameter>();
  917. if (sig.charAt(cur.position) == '<') {
  918. cur.position++;
  919. while (sig.charAt(cur.position) != '>') {
  920. int nameBegin = cur.position;
  921. int nameEnd = cur.indexOf(sig, ':');
  922. ObjectType classBound = parseObjectType(sig, cur, true);
  923. List<ObjectType> ifBound = new ArrayList<ObjectType>();
  924. while (sig.charAt(cur.position) == ':') {
  925. cur.position++;
  926. ObjectType t = parseObjectType(sig, cur, false);
  927. ifBound.add(t);
  928. }
  929. TypeParameter p = new TypeParameter(sig, nameBegin, nameEnd,
  930. classBound, ifBound.toArray(new ObjectType[ifBound.size()]));
  931. typeParam.add(p);
  932. }
  933. cur.position++;
  934. }
  935. return typeParam.toArray(new TypeParameter[typeParam.size()]);
  936. }
  937. private static ObjectType parseObjectType(String sig, Cursor c, boolean dontThrow)
  938. throws BadBytecode
  939. {
  940. int i;
  941. int begin = c.position;
  942. switch (sig.charAt(begin)) {
  943. case 'L' :
  944. return parseClassType2(sig, c, null);
  945. case 'T' :
  946. i = c.indexOf(sig, ';');
  947. return new TypeVariable(sig, begin + 1, i);
  948. case '[' :
  949. return parseArray(sig, c);
  950. default :
  951. if (dontThrow)
  952. return null;
  953. throw error(sig);
  954. }
  955. }
  956. private static ClassType parseClassType(String sig, Cursor c)
  957. throws BadBytecode
  958. {
  959. if (sig.charAt(c.position) == 'L')
  960. return parseClassType2(sig, c, null);
  961. throw error(sig);
  962. }
  963. private static ClassType parseClassType2(String sig, Cursor c, ClassType parent)
  964. throws BadBytecode
  965. {
  966. int start = ++c.position;
  967. char t;
  968. do {
  969. t = sig.charAt(c.position++);
  970. } while (t != '$' && t != '<' && t != ';');
  971. int end = c.position - 1;
  972. TypeArgument[] targs;
  973. if (t == '<') {
  974. targs = parseTypeArgs(sig, c);
  975. t = sig.charAt(c.position++);
  976. }
  977. else
  978. targs = null;
  979. ClassType thisClass = ClassType.make(sig, start, end, targs, parent);
  980. if (t == '$' || t == '.') {
  981. c.position--;
  982. return parseClassType2(sig, c, thisClass);
  983. }
  984. return thisClass;
  985. }
  986. private static TypeArgument[] parseTypeArgs(String sig, Cursor c) throws BadBytecode {
  987. List<TypeArgument> args = new ArrayList<TypeArgument>();
  988. char t;
  989. while ((t = sig.charAt(c.position++)) != '>') {
  990. TypeArgument ta;
  991. if (t == '*' )
  992. ta = new TypeArgument(null, '*');
  993. else {
  994. if (t != '+' && t != '-') {
  995. t = ' ';
  996. c.position--;
  997. }
  998. ta = new TypeArgument(parseObjectType(sig, c, false), t);
  999. }
  1000. args.add(ta);
  1001. }
  1002. return args.toArray(new TypeArgument[args.size()]);
  1003. }
  1004. private static ObjectType parseArray(String sig, Cursor c) throws BadBytecode {
  1005. int dim = 1;
  1006. while (sig.charAt(++c.position) == '[')
  1007. dim++;
  1008. return new ArrayType(dim, parseType(sig, c));
  1009. }
  1010. private static Type parseType(String sig, Cursor c) throws BadBytecode {
  1011. Type t = parseObjectType(sig, c, true);
  1012. if (t == null)
  1013. t = new BaseType(sig.charAt(c.position++));
  1014. return t;
  1015. }
  1016. private static BadBytecode error(String sig) {
  1017. return new BadBytecode("bad signature: " + sig);
  1018. }
  1019. }