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.

AnnotationsAttribute.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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.ByteArrayOutputStream;
  18. import java.io.DataInputStream;
  19. import java.io.IOException;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. import javassist.bytecode.annotation.Annotation;
  23. import javassist.bytecode.annotation.AnnotationMemberValue;
  24. import javassist.bytecode.annotation.AnnotationsWriter;
  25. import javassist.bytecode.annotation.ArrayMemberValue;
  26. import javassist.bytecode.annotation.BooleanMemberValue;
  27. import javassist.bytecode.annotation.ByteMemberValue;
  28. import javassist.bytecode.annotation.CharMemberValue;
  29. import javassist.bytecode.annotation.ClassMemberValue;
  30. import javassist.bytecode.annotation.DoubleMemberValue;
  31. import javassist.bytecode.annotation.EnumMemberValue;
  32. import javassist.bytecode.annotation.FloatMemberValue;
  33. import javassist.bytecode.annotation.IntegerMemberValue;
  34. import javassist.bytecode.annotation.LongMemberValue;
  35. import javassist.bytecode.annotation.MemberValue;
  36. import javassist.bytecode.annotation.ShortMemberValue;
  37. import javassist.bytecode.annotation.StringMemberValue;
  38. /**
  39. * A class representing
  40. * <code>RuntimeVisibleAnnotations_attribute</code> and
  41. * <code>RuntimeInvisibleAnnotations_attribute</code>.
  42. *
  43. * <p>To obtain an AnnotationAttribute object, invoke
  44. * <code>getAttribute(AnnotationsAttribute.visibleTag)</code>
  45. * in <code>ClassFile</code>, <code>MethodInfo</code>,
  46. * or <code>FieldInfo</code>. The obtained attribute is a
  47. * runtime visible annotations attribute.
  48. * If the parameter is
  49. * <code>AnnotationAttribute.invisibleTag</code>, then the obtained
  50. * attribute is a runtime invisible one.
  51. *
  52. * <p>For example,
  53. *
  54. * <pre>
  55. * import javassist.bytecode.annotation.Annotation;
  56. * :
  57. * CtMethod m = ... ;
  58. * MethodInfo minfo = m.getMethodInfo();
  59. * AnnotationsAttribute attr = (AnnotationsAttribute)
  60. * minfo.getAttribute(AnnotationsAttribute.invisibleTag);
  61. * Annotation an = attr.getAnnotation("Author");
  62. * String s = ((StringMemberValue)an.getMemberValue("name")).getValue();
  63. * System.out.println("@Author(name=" + s + ")");
  64. * </pre>
  65. *
  66. * <p>This code snippet retrieves an annotation of the type <code>Author</code>
  67. * from the <code>MethodInfo</code> object specified by <code>minfo</code>.
  68. * Then, it prints the value of <code>name</code> in <code>Author</code>.
  69. *
  70. * <p>If the annotation type <code>Author</code> is annotated by a meta annotation:
  71. *
  72. * <pre>
  73. * &#64;Retention(RetentionPolicy.RUNTIME)
  74. * </pre>
  75. *
  76. * <p>Then <code>Author</code> is visible at runtime. Therefore, the third
  77. * statement of the code snippet above must be changed into:
  78. *
  79. * <pre>
  80. * AnnotationsAttribute attr = (AnnotationsAttribute)
  81. * minfo.getAttribute(AnnotationsAttribute.visibleTag);
  82. * </pre>
  83. *
  84. * <p>The attribute tag must be <code>visibleTag</code> instead of
  85. * <code>invisibleTag</code>.
  86. *
  87. * <p>If the member value of an annotation is not specified, the default value
  88. * is used as that member value. If so, <code>getMemberValue()</code> in
  89. * <code>Annotation</code> returns <code>null</code>
  90. * since the default value is not included in the
  91. * <code>AnnotationsAttribute</code>. It is included in the
  92. * <code>AnnotationDefaultAttribute</code> of the method declared in the
  93. * annotation type.
  94. *
  95. * <p>If you want to record a new AnnotationAttribute object, execute the
  96. * following snippet:
  97. *
  98. * <pre>
  99. * ClassFile cf = ... ;
  100. * ConstPool cp = cf.getConstPool();
  101. * AnnotationsAttribute attr
  102. * = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag);
  103. * Annotation a = new Annotation("Author", cp);
  104. * a.addMemberValue("name", new StringMemberValue("Chiba", cp));
  105. * attr.setAnnotation(a);
  106. * cf.addAttribute(attr);
  107. * cf.setVersionToJava5();
  108. * </pre>
  109. *
  110. * <p>The last statement is necessary if the class file was produced by
  111. * <code>javac</code> of JDK 1.4 or earlier. Otherwise, it is not necessary.
  112. *
  113. * @see AnnotationDefaultAttribute
  114. * @see javassist.bytecode.annotation.Annotation
  115. */
  116. public class AnnotationsAttribute extends AttributeInfo {
  117. /**
  118. * The name of the <code>RuntimeVisibleAnnotations</code> attribute.
  119. */
  120. public static final String visibleTag = "RuntimeVisibleAnnotations";
  121. /**
  122. * The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
  123. */
  124. public static final String invisibleTag = "RuntimeInvisibleAnnotations";
  125. /**
  126. * Constructs a <code>Runtime(In)VisibleAnnotations_attribute</code>.
  127. *
  128. * @param cp constant pool
  129. * @param attrname attribute name (<code>visibleTag</code> or
  130. * <code>invisibleTag</code>).
  131. * @param info the contents of this attribute. It does not
  132. * include <code>attribute_name_index</code> or
  133. * <code>attribute_length</code>.
  134. */
  135. public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info) {
  136. super(cp, attrname, info);
  137. }
  138. /**
  139. * Constructs an empty
  140. * <code>Runtime(In)VisibleAnnotations_attribute</code>.
  141. * A new annotation can be later added to the created attribute
  142. * by <code>setAnnotations()</code>.
  143. *
  144. * @param cp constant pool
  145. * @param attrname attribute name (<code>visibleTag</code> or
  146. * <code>invisibleTag</code>).
  147. * @see #setAnnotations(Annotation[])
  148. */
  149. public AnnotationsAttribute(ConstPool cp, String attrname) {
  150. this(cp, attrname, new byte[] { 0, 0 });
  151. }
  152. /**
  153. * @param n the attribute name.
  154. */
  155. AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
  156. throws IOException
  157. {
  158. super(cp, n, in);
  159. }
  160. /**
  161. * Returns <code>num_annotations</code>.
  162. */
  163. public int numAnnotations() {
  164. return ByteArray.readU16bit(info, 0);
  165. }
  166. /**
  167. * Copies this attribute and returns a new copy.
  168. */
  169. @Override
  170. public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) {
  171. Copier copier = new Copier(info, constPool, newCp, classnames);
  172. try {
  173. copier.annotationArray();
  174. return new AnnotationsAttribute(newCp, getName(), copier.close());
  175. }
  176. catch (Exception e) {
  177. throw new RuntimeException(e);
  178. }
  179. }
  180. /**
  181. * Parses the annotations and returns a data structure representing
  182. * the annotation with the specified type. See also
  183. * <code>getAnnotations()</code> as to the returned data structure.
  184. *
  185. * @param type the annotation type.
  186. * @return null if the specified annotation type is not included.
  187. * @see #getAnnotations()
  188. */
  189. public Annotation getAnnotation(String type) {
  190. Annotation[] annotations = getAnnotations();
  191. for (int i = 0; i < annotations.length; i++) {
  192. if (annotations[i].getTypeName().equals(type))
  193. return annotations[i];
  194. }
  195. return null;
  196. }
  197. /**
  198. * Adds an annotation. If there is an annotation with the same type,
  199. * it is removed before the new annotation is added.
  200. *
  201. * @param annotation the added annotation.
  202. */
  203. public void addAnnotation(Annotation annotation) {
  204. String type = annotation.getTypeName();
  205. Annotation[] annotations = getAnnotations();
  206. for (int i = 0; i < annotations.length; i++) {
  207. if (annotations[i].getTypeName().equals(type)) {
  208. annotations[i] = annotation;
  209. setAnnotations(annotations);
  210. return;
  211. }
  212. }
  213. Annotation[] newlist = new Annotation[annotations.length + 1];
  214. System.arraycopy(annotations, 0, newlist, 0, annotations.length);
  215. newlist[annotations.length] = annotation;
  216. setAnnotations(newlist);
  217. }
  218. /**
  219. * Removes an annotation by type.
  220. * After removing an annotation, if {@link #numAnnotations()} returns 0,
  221. * this annotations attribute has to be removed.
  222. *
  223. * @param type of annotation to remove
  224. * @return whether an annotation with the given type has been removed
  225. * @since 3.21
  226. */
  227. public boolean removeAnnotation(String type) {
  228. Annotation[] annotations = getAnnotations();
  229. for (int i = 0; i < annotations.length; i++) {
  230. if (annotations[i].getTypeName().equals(type)) {
  231. Annotation[] newlist = new Annotation[annotations.length - 1];
  232. System.arraycopy(annotations, 0, newlist, 0, i);
  233. if (i < annotations.length - 1) {
  234. System.arraycopy(annotations, i + 1, newlist, i,
  235. annotations.length - i - 1);
  236. }
  237. setAnnotations(newlist);
  238. return true;
  239. }
  240. }
  241. return false;
  242. }
  243. /**
  244. * Parses the annotations and returns a data structure representing
  245. * that parsed annotations. Note that changes of the node values of the
  246. * returned tree are not reflected on the annotations represented by
  247. * this object unless the tree is copied back to this object by
  248. * <code>setAnnotations()</code>.
  249. *
  250. * @see #setAnnotations(Annotation[])
  251. */
  252. public Annotation[] getAnnotations() {
  253. try {
  254. return new Parser(info, constPool).parseAnnotations();
  255. }
  256. catch (Exception e) {
  257. throw new RuntimeException(e);
  258. }
  259. }
  260. /**
  261. * Changes the annotations represented by this object according to
  262. * the given array of <code>Annotation</code> objects.
  263. *
  264. * @param annotations the data structure representing the
  265. * new annotations.
  266. */
  267. public void setAnnotations(Annotation[] annotations) {
  268. ByteArrayOutputStream output = new ByteArrayOutputStream();
  269. AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
  270. try {
  271. int n = annotations.length;
  272. writer.numAnnotations(n);
  273. for (int i = 0; i < n; ++i)
  274. annotations[i].write(writer);
  275. writer.close();
  276. }
  277. catch (IOException e) {
  278. throw new RuntimeException(e); // should never reach here.
  279. }
  280. set(output.toByteArray());
  281. }
  282. /**
  283. * Changes the annotations. A call to this method is equivalent to:
  284. * <pre>setAnnotations(new Annotation[] { annotation })</pre>
  285. *
  286. * @param annotation the data structure representing
  287. * the new annotation.
  288. */
  289. public void setAnnotation(Annotation annotation) {
  290. setAnnotations(new Annotation[] { annotation });
  291. }
  292. /**
  293. * @param oldname a JVM class name.
  294. * @param newname a JVM class name.
  295. */
  296. @Override
  297. void renameClass(String oldname, String newname) {
  298. Map<String,String> map = new HashMap<String,String>();
  299. map.put(oldname, newname);
  300. renameClass(map);
  301. }
  302. @Override
  303. void renameClass(Map<String,String> classnames) {
  304. Renamer renamer = new Renamer(info, getConstPool(), classnames);
  305. try {
  306. renamer.annotationArray();
  307. } catch (Exception e) {
  308. throw new RuntimeException(e);
  309. }
  310. }
  311. @Override
  312. void getRefClasses(Map<String,String> classnames) { renameClass(classnames); }
  313. /**
  314. * Returns a string representation of this object.
  315. */
  316. @Override
  317. public String toString() {
  318. Annotation[] a = getAnnotations();
  319. StringBuilder sbuf = new StringBuilder();
  320. int i = 0;
  321. while (i < a.length) {
  322. sbuf.append(a[i++].toString());
  323. if (i != a.length)
  324. sbuf.append(", ");
  325. }
  326. return sbuf.toString();
  327. }
  328. static class Walker {
  329. byte[] info;
  330. Walker(byte[] attrInfo) {
  331. info = attrInfo;
  332. }
  333. final void parameters() throws Exception {
  334. int numParam = info[0] & 0xff;
  335. parameters(numParam, 1);
  336. }
  337. void parameters(int numParam, int pos) throws Exception {
  338. for (int i = 0; i < numParam; ++i)
  339. pos = annotationArray(pos);
  340. }
  341. final void annotationArray() throws Exception {
  342. annotationArray(0);
  343. }
  344. final int annotationArray(int pos) throws Exception {
  345. int num = ByteArray.readU16bit(info, pos);
  346. return annotationArray(pos + 2, num);
  347. }
  348. int annotationArray(int pos, int num) throws Exception {
  349. for (int i = 0; i < num; ++i)
  350. pos = annotation(pos);
  351. return pos;
  352. }
  353. final int annotation(int pos) throws Exception {
  354. int type = ByteArray.readU16bit(info, pos);
  355. int numPairs = ByteArray.readU16bit(info, pos + 2);
  356. return annotation(pos + 4, type, numPairs);
  357. }
  358. int annotation(int pos, int type, int numPairs) throws Exception {
  359. for (int j = 0; j < numPairs; ++j)
  360. pos = memberValuePair(pos);
  361. return pos;
  362. }
  363. /**
  364. * {@code element_value_paris}
  365. */
  366. final int memberValuePair(int pos) throws Exception {
  367. int nameIndex = ByteArray.readU16bit(info, pos);
  368. return memberValuePair(pos + 2, nameIndex);
  369. }
  370. /**
  371. * {@code element_value_paris[]}
  372. */
  373. int memberValuePair(int pos, int nameIndex) throws Exception {
  374. return memberValue(pos);
  375. }
  376. /**
  377. * {@code element_value}
  378. */
  379. final int memberValue(int pos) throws Exception {
  380. int tag = info[pos] & 0xff;
  381. if (tag == 'e') {
  382. int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
  383. int constNameIndex = ByteArray.readU16bit(info, pos + 3);
  384. enumMemberValue(pos, typeNameIndex, constNameIndex);
  385. return pos + 5;
  386. }
  387. else if (tag == 'c') {
  388. int index = ByteArray.readU16bit(info, pos + 1);
  389. classMemberValue(pos, index);
  390. return pos + 3;
  391. }
  392. else if (tag == '@')
  393. return annotationMemberValue(pos + 1);
  394. else if (tag == '[') {
  395. int num = ByteArray.readU16bit(info, pos + 1);
  396. return arrayMemberValue(pos + 3, num);
  397. }
  398. else { // primitive types or String.
  399. int index = ByteArray.readU16bit(info, pos + 1);
  400. constValueMember(tag, index);
  401. return pos + 3;
  402. }
  403. }
  404. /**
  405. * {@code const_value_index}
  406. */
  407. void constValueMember(int tag, int index) throws Exception {}
  408. /**
  409. * {@code enum_const_value}
  410. */
  411. void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
  412. throws Exception {
  413. }
  414. /**
  415. * {@code class_info_index}
  416. */
  417. void classMemberValue(int pos, int index) throws Exception {}
  418. /**
  419. * {@code annotation_value}
  420. */
  421. int annotationMemberValue(int pos) throws Exception {
  422. return annotation(pos);
  423. }
  424. /**
  425. * {@code array_value}
  426. */
  427. int arrayMemberValue(int pos, int num) throws Exception {
  428. for (int i = 0; i < num; ++i) {
  429. pos = memberValue(pos);
  430. }
  431. return pos;
  432. }
  433. }
  434. static class Renamer extends Walker {
  435. ConstPool cpool;
  436. Map<String,String> classnames;
  437. /**
  438. * Constructs a renamer. It renames some class names
  439. * into the new names specified by <code>map</code>.
  440. *
  441. * @param info the annotations attribute.
  442. * @param cp the constant pool.
  443. * @param map pairs of replaced and substituted class names.
  444. * It can be null.
  445. */
  446. Renamer(byte[] info, ConstPool cp, Map<String,String> map) {
  447. super(info);
  448. cpool = cp;
  449. classnames = map;
  450. }
  451. @Override
  452. int annotation(int pos, int type, int numPairs) throws Exception {
  453. renameType(pos - 4, type);
  454. return super.annotation(pos, type, numPairs);
  455. }
  456. @Override
  457. void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
  458. throws Exception
  459. {
  460. renameType(pos + 1, typeNameIndex);
  461. super.enumMemberValue(pos, typeNameIndex, constNameIndex);
  462. }
  463. @Override
  464. void classMemberValue(int pos, int index) throws Exception {
  465. renameType(pos + 1, index);
  466. super.classMemberValue(pos, index);
  467. }
  468. private void renameType(int pos, int index) {
  469. String name = cpool.getUtf8Info(index);
  470. String newName = Descriptor.rename(name, classnames);
  471. if (!name.equals(newName)) {
  472. int index2 = cpool.addUtf8Info(newName);
  473. ByteArray.write16bit(index2, info, pos);
  474. }
  475. }
  476. }
  477. static class Copier extends Walker {
  478. ByteArrayOutputStream output;
  479. AnnotationsWriter writer;
  480. ConstPool srcPool, destPool;
  481. Map<String,String> classnames;
  482. /**
  483. * Constructs a copier. This copier renames some class names
  484. * into the new names specified by <code>map</code> when it copies
  485. * an annotation attribute.
  486. *
  487. * @param info the source attribute.
  488. * @param src the constant pool of the source class.
  489. * @param dest the constant pool of the destination class.
  490. * @param map pairs of replaced and substituted class names.
  491. * It can be null.
  492. */
  493. Copier(byte[] info, ConstPool src, ConstPool dest, Map<String,String> map) {
  494. this(info, src, dest, map, true);
  495. }
  496. Copier(byte[] info, ConstPool src, ConstPool dest, Map<String,String> map, boolean makeWriter) {
  497. super(info);
  498. output = new ByteArrayOutputStream();
  499. if (makeWriter)
  500. writer = new AnnotationsWriter(output, dest);
  501. srcPool = src;
  502. destPool = dest;
  503. classnames = map;
  504. }
  505. byte[] close() throws IOException {
  506. writer.close();
  507. return output.toByteArray();
  508. }
  509. @Override
  510. void parameters(int numParam, int pos) throws Exception {
  511. writer.numParameters(numParam);
  512. super.parameters(numParam, pos);
  513. }
  514. @Override
  515. int annotationArray(int pos, int num) throws Exception {
  516. writer.numAnnotations(num);
  517. return super.annotationArray(pos, num);
  518. }
  519. @Override
  520. int annotation(int pos, int type, int numPairs) throws Exception {
  521. writer.annotation(copyType(type), numPairs);
  522. return super.annotation(pos, type, numPairs);
  523. }
  524. @Override
  525. int memberValuePair(int pos, int nameIndex) throws Exception {
  526. writer.memberValuePair(copy(nameIndex));
  527. return super.memberValuePair(pos, nameIndex);
  528. }
  529. @Override
  530. void constValueMember(int tag, int index) throws Exception {
  531. writer.constValueIndex(tag, copy(index));
  532. super.constValueMember(tag, index);
  533. }
  534. @Override
  535. void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
  536. throws Exception
  537. {
  538. writer.enumConstValue(copyType(typeNameIndex), copy(constNameIndex));
  539. super.enumMemberValue(pos, typeNameIndex, constNameIndex);
  540. }
  541. @Override
  542. void classMemberValue(int pos, int index) throws Exception {
  543. writer.classInfoIndex(copyType(index));
  544. super.classMemberValue(pos, index);
  545. }
  546. @Override
  547. int annotationMemberValue(int pos) throws Exception {
  548. writer.annotationValue();
  549. return super.annotationMemberValue(pos);
  550. }
  551. @Override
  552. int arrayMemberValue(int pos, int num) throws Exception {
  553. writer.arrayValue(num);
  554. return super.arrayMemberValue(pos, num);
  555. }
  556. /**
  557. * Copies a constant pool entry into the destination constant pool
  558. * and returns the index of the copied entry.
  559. *
  560. * @param srcIndex the index of the copied entry into the source
  561. * constant pool.
  562. * @return the index of the copied item into the destination
  563. * constant pool.
  564. */
  565. int copy(int srcIndex) {
  566. return srcPool.copy(srcIndex, destPool, classnames);
  567. }
  568. /**
  569. * Copies a constant pool entry into the destination constant pool
  570. * and returns the index of the copied entry. That entry must be
  571. * a Utf8Info representing a class name in the L<class name>; form.
  572. *
  573. * @param srcIndex the index of the copied entry into the source
  574. * constant pool.
  575. * @return the index of the copied item into the destination
  576. * constant pool.
  577. */
  578. int copyType(int srcIndex) {
  579. String name = srcPool.getUtf8Info(srcIndex);
  580. String newName = Descriptor.rename(name, classnames);
  581. return destPool.addUtf8Info(newName);
  582. }
  583. }
  584. static class Parser extends Walker {
  585. ConstPool pool;
  586. Annotation[][] allParams; // all parameters
  587. Annotation[] allAnno; // all annotations
  588. Annotation currentAnno; // current annotation
  589. MemberValue currentMember; // current member
  590. /**
  591. * Constructs a parser. This parser constructs a parse tree of
  592. * the annotations.
  593. *
  594. * @param info the attribute.
  595. * @param src the constant pool.
  596. */
  597. Parser(byte[] info, ConstPool cp) {
  598. super(info);
  599. pool = cp;
  600. }
  601. Annotation[][] parseParameters() throws Exception {
  602. parameters();
  603. return allParams;
  604. }
  605. Annotation[] parseAnnotations() throws Exception {
  606. annotationArray();
  607. return allAnno;
  608. }
  609. MemberValue parseMemberValue() throws Exception {
  610. memberValue(0);
  611. return currentMember;
  612. }
  613. @Override
  614. void parameters(int numParam, int pos) throws Exception {
  615. Annotation[][] params = new Annotation[numParam][];
  616. for (int i = 0; i < numParam; ++i) {
  617. pos = annotationArray(pos);
  618. params[i] = allAnno;
  619. }
  620. allParams = params;
  621. }
  622. @Override
  623. int annotationArray(int pos, int num) throws Exception {
  624. Annotation[] array = new Annotation[num];
  625. for (int i = 0; i < num; ++i) {
  626. pos = annotation(pos);
  627. array[i] = currentAnno;
  628. }
  629. allAnno = array;
  630. return pos;
  631. }
  632. @Override
  633. int annotation(int pos, int type, int numPairs) throws Exception {
  634. currentAnno = new Annotation(type, pool);
  635. return super.annotation(pos, type, numPairs);
  636. }
  637. @Override
  638. int memberValuePair(int pos, int nameIndex) throws Exception {
  639. pos = super.memberValuePair(pos, nameIndex);
  640. currentAnno.addMemberValue(nameIndex, currentMember);
  641. return pos;
  642. }
  643. @Override
  644. void constValueMember(int tag, int index) throws Exception {
  645. MemberValue m;
  646. ConstPool cp = pool;
  647. switch (tag) {
  648. case 'B' :
  649. m = new ByteMemberValue(index, cp);
  650. break;
  651. case 'C' :
  652. m = new CharMemberValue(index, cp);
  653. break;
  654. case 'D' :
  655. m = new DoubleMemberValue(index, cp);
  656. break;
  657. case 'F' :
  658. m = new FloatMemberValue(index, cp);
  659. break;
  660. case 'I' :
  661. m = new IntegerMemberValue(index, cp);
  662. break;
  663. case 'J' :
  664. m = new LongMemberValue(index, cp);
  665. break;
  666. case 'S' :
  667. m = new ShortMemberValue(index, cp);
  668. break;
  669. case 'Z' :
  670. m = new BooleanMemberValue(index, cp);
  671. break;
  672. case 's' :
  673. m = new StringMemberValue(index, cp);
  674. break;
  675. default :
  676. throw new RuntimeException("unknown tag:" + tag);
  677. }
  678. currentMember = m;
  679. super.constValueMember(tag, index);
  680. }
  681. @Override
  682. void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
  683. throws Exception
  684. {
  685. currentMember = new EnumMemberValue(typeNameIndex,
  686. constNameIndex, pool);
  687. super.enumMemberValue(pos, typeNameIndex, constNameIndex);
  688. }
  689. @Override
  690. void classMemberValue(int pos, int index) throws Exception {
  691. currentMember = new ClassMemberValue(index, pool);
  692. super.classMemberValue(pos, index);
  693. }
  694. @Override
  695. int annotationMemberValue(int pos) throws Exception {
  696. Annotation anno = currentAnno;
  697. pos = super.annotationMemberValue(pos);
  698. currentMember = new AnnotationMemberValue(currentAnno, pool);
  699. currentAnno = anno;
  700. return pos;
  701. }
  702. @Override
  703. int arrayMemberValue(int pos, int num) throws Exception {
  704. ArrayMemberValue amv = new ArrayMemberValue(pool);
  705. MemberValue[] elements = new MemberValue[num];
  706. for (int i = 0; i < num; ++i) {
  707. pos = memberValue(pos);
  708. elements[i] = currentMember;
  709. }
  710. amv.setValue(elements);
  711. currentMember = amv;
  712. return pos;
  713. }
  714. }
  715. }