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.

TypeAnnotationGen.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /* *******************************************************************
  2. * Copyright (c) 2013 VMware
  3. *
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * Andy Clement initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.apache.bcel.classfile.annotation;
  14. import java.io.DataInputStream;
  15. import java.io.DataOutputStream;
  16. import java.io.IOException;
  17. import org.aspectj.apache.bcel.classfile.ConstantPool;
  18. public class TypeAnnotationGen {
  19. public static final TypeAnnotationGen[] NO_TYPE_ANNOTATIONS = new TypeAnnotationGen[0];
  20. public static final int[] NO_TYPE_PATH = new int[0];
  21. private ConstantPool cpool;
  22. private TypeAnnotationGen(ConstantPool cpool) {
  23. this.cpool = cpool;
  24. }
  25. private int targetType;
  26. private int[] typePath;
  27. private AnnotationGen annotation;
  28. private int info; // meaning varies depending on target type
  29. private int info2; // meaning varies depending on target type
  30. private int[] localVarTarget;
  31. // target type constants
  32. public final static int CLASS_TYPE_PARAMETER = 0x00;
  33. public final static int METHOD_TYPE_PARAMETER = 0x01;
  34. public final static int CLASS_EXTENDS = 0x10;
  35. public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
  36. public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
  37. public final static int FIELD = 0x13;
  38. public final static int METHOD_RETURN = 0x14;
  39. public final static int METHOD_RECEIVER = 0x15;
  40. public final static int METHOD_FORMAL_PARAMETER = 0x16;
  41. public final static int THROWS = 0x17;
  42. public final static int LOCAL_VARIABLE = 0x40;
  43. public final static int RESOURCE_VARIABLE = 0x41;
  44. public final static int EXCEPTION_PARAMETER = 0x42;
  45. public final static int INSTANCEOF = 0x43;
  46. public final static int NEW = 0x44;
  47. public final static int CONSTRUCTOR_REFERENCE = 0x45;
  48. public final static int METHOD_REFERENCE = 0x46;
  49. public final static int CAST = 0x47;
  50. public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
  51. public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
  52. public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
  53. public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
  54. // type path entry kinds
  55. public final static int TYPE_PATH_ENTRY_KIND_ARRAY = 0;
  56. public final static int TYPE_PATH_ENTRY_KIND_INNER_TYPE = 1;
  57. public final static int TYPE_PATH_ENTRY_KIND_WILDCARD = 2;
  58. public final static int TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT = 3;
  59. public static TypeAnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean isVisible) throws IOException {
  60. TypeAnnotationGen typeAnno = new TypeAnnotationGen(cpool);
  61. typeAnno.targetType = dis.readUnsignedByte();
  62. // read target_info
  63. switch (typeAnno.targetType) {
  64. case CLASS_TYPE_PARAMETER:
  65. typeAnno.info = dis.readUnsignedByte();// type_parameter_index
  66. break;
  67. case METHOD_TYPE_PARAMETER:
  68. typeAnno.info = dis.readUnsignedByte(); // type_parameter_index
  69. break;
  70. case CLASS_EXTENDS:
  71. int superTypeIndex = dis.readUnsignedShort();
  72. if (superTypeIndex == 65535) {
  73. typeAnno.info = -1;
  74. } else {
  75. typeAnno.info = superTypeIndex;
  76. }
  77. break;
  78. case CLASS_TYPE_PARAMETER_BOUND:
  79. case METHOD_TYPE_PARAMETER_BOUND:
  80. typeAnno.info = dis.readUnsignedByte(); // type_parameter_index
  81. typeAnno.info2 = dis.readUnsignedByte(); // bound_index;
  82. break;
  83. case FIELD:
  84. case METHOD_RETURN:
  85. case METHOD_RECEIVER:
  86. break;
  87. case METHOD_FORMAL_PARAMETER:
  88. typeAnno.info = dis.readUnsignedByte(); // method_formal_parameter_index
  89. break;
  90. case THROWS:
  91. typeAnno.info = dis.readUnsignedShort(); // throws_type_index
  92. break;
  93. case LOCAL_VARIABLE:
  94. case RESOURCE_VARIABLE:
  95. typeAnno.localVarTarget = readLocalVarTarget(dis);
  96. break;
  97. case EXCEPTION_PARAMETER:
  98. // TODO should be a SHORT according to the spec but byte for now because of javac (b90)
  99. typeAnno.info = dis.readUnsignedByte(); // exception_table_index
  100. break;
  101. case INSTANCEOF:
  102. case NEW:
  103. case CONSTRUCTOR_REFERENCE:
  104. case METHOD_REFERENCE:
  105. typeAnno.info = dis.readUnsignedShort(); // offset
  106. break;
  107. case CAST:
  108. case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
  109. case METHOD_INVOCATION_TYPE_ARGUMENT:
  110. case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
  111. case METHOD_REFERENCE_TYPE_ARGUMENT:
  112. typeAnno.info = dis.readUnsignedShort(); // offset
  113. typeAnno.info2 = dis.readUnsignedByte(); // type_argument_index
  114. break;
  115. default:
  116. throw new IllegalStateException("nyi "+typeAnno.targetType);
  117. }
  118. int typepathlength = dis.readUnsignedByte();
  119. if (typepathlength==0) {
  120. typeAnno.typePath = NO_TYPE_PATH;
  121. } else {
  122. typeAnno.typePath = new int[typepathlength*2];
  123. for (int i=0, max = typepathlength*2; i<max; i++) {
  124. typeAnno.typePath[i] = dis.readUnsignedByte();
  125. }
  126. }
  127. typeAnno.annotation = AnnotationGen.read(dis, cpool, isVisible);
  128. return typeAnno;
  129. }
  130. public static int[] readLocalVarTarget(DataInputStream dis) throws IOException {
  131. int tableLength = dis.readUnsignedShort();
  132. int[] table = new int[tableLength*3];
  133. int count = 0;
  134. for (int i=0;i<tableLength;i++) {
  135. table[count++]=dis.readUnsignedShort(); // start_pc
  136. table[count++]=dis.readUnsignedShort(); // length
  137. table[count++]=dis.readUnsignedShort(); // index
  138. }
  139. return table;
  140. }
  141. public void dump(DataOutputStream dos) throws IOException {
  142. dos.writeByte(targetType);
  143. switch (targetType) {
  144. case CLASS_TYPE_PARAMETER:
  145. dos.writeByte(this.info); // type_parameter_index
  146. break;
  147. case METHOD_TYPE_PARAMETER:
  148. dos.writeByte(info); // type_parameter_index
  149. break;
  150. case CLASS_EXTENDS:
  151. dos.writeShort(info); // supertype_index
  152. break;
  153. case CLASS_TYPE_PARAMETER_BOUND:
  154. case METHOD_TYPE_PARAMETER_BOUND:
  155. dos.writeByte(info); // type_parameter_index
  156. dos.writeByte(info2); // bound_index;
  157. break;
  158. case FIELD:
  159. case METHOD_RETURN:
  160. case METHOD_RECEIVER:
  161. break;
  162. case METHOD_FORMAL_PARAMETER:
  163. dos.writeByte(info); // method_formal_parameter_index
  164. break;
  165. case THROWS:
  166. dos.writeShort(info); // throws_type_index
  167. break;
  168. case LOCAL_VARIABLE:
  169. case RESOURCE_VARIABLE:
  170. dos.writeShort(localVarTarget.length/3);
  171. for (int j : localVarTarget) {
  172. dos.writeShort(j);
  173. }
  174. break;
  175. case EXCEPTION_PARAMETER:
  176. // TODO should be a SHORT according to the spec but byte for now because of javac (b90)
  177. dos.writeByte(info); // exception_table_index
  178. break;
  179. case INSTANCEOF:
  180. case NEW:
  181. case CONSTRUCTOR_REFERENCE:
  182. case METHOD_REFERENCE:
  183. dos.writeShort(info); // offset
  184. break;
  185. case CAST:
  186. case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
  187. case METHOD_INVOCATION_TYPE_ARGUMENT:
  188. case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
  189. case METHOD_REFERENCE_TYPE_ARGUMENT:
  190. dos.writeShort(info); // offset
  191. dos.writeByte(info); // type_argument_index
  192. break;
  193. default:
  194. throw new IllegalStateException("nyi "+targetType);
  195. }
  196. dos.writeByte(typePath.length);
  197. for (int j : typePath) {
  198. dos.writeByte(j);
  199. }
  200. annotation.dump(dos);
  201. }
  202. public int getSupertypeIndex() {
  203. assert (targetType==CLASS_EXTENDS);
  204. return info;
  205. }
  206. public int getOffset() {
  207. assert (targetType==INSTANCEOF || targetType==NEW || targetType==CONSTRUCTOR_REFERENCE || targetType==METHOD_REFERENCE ||
  208. targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ||
  209. targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ||
  210. targetType==METHOD_REFERENCE_TYPE_ARGUMENT);
  211. return info;
  212. }
  213. public int getTypeParameterIndex() {
  214. assert (targetType==CLASS_TYPE_PARAMETER || targetType==METHOD_TYPE_PARAMETER ||
  215. targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND);
  216. return info;
  217. }
  218. public int getTypeArgumentIndex() {
  219. assert (targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ||
  220. targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT || targetType==METHOD_REFERENCE_TYPE_ARGUMENT);
  221. return info2;
  222. }
  223. public int getBoundIndex() {
  224. assert (targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND);
  225. return info2;
  226. }
  227. public int getMethodFormalParameterIndex() {
  228. assert (targetType==METHOD_FORMAL_PARAMETER);
  229. return info;
  230. }
  231. public int getThrowsTypeIndex() {
  232. assert (targetType==THROWS);
  233. return info;
  234. }
  235. public int[] getLocalVarTarget() {
  236. assert (targetType==LOCAL_VARIABLE||targetType==RESOURCE_VARIABLE);
  237. return localVarTarget;
  238. }
  239. public int getExceptionTableIndex() {
  240. assert (targetType==EXCEPTION_PARAMETER);
  241. return info;
  242. }
  243. public int getTargetType() {
  244. return targetType;
  245. }
  246. public AnnotationGen getAnnotation() {
  247. return annotation;
  248. }
  249. // @Override
  250. // public String toString() {
  251. // StringBuffer s = new StringBuffer();
  252. // s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {");
  253. // for (int i = 0; i < pairs.size(); i++) {
  254. // s.append(pairs.get(i));
  255. // if (i + 1 < pairs.size())
  256. // s.append(",");
  257. // }
  258. // s.append("}]");
  259. // return s.toString();
  260. // }
  261. //
  262. // public String toShortString() {
  263. // StringBuffer s = new StringBuffer();
  264. // s.append("@" + getTypeName() + "(");
  265. // for (int i = 0; i < pairs.size(); i++) {
  266. // s.append(pairs.get(i));
  267. // if (i + 1 < pairs.size())
  268. // s.append(",");
  269. // }
  270. // s.append(")");
  271. // return s.toString();
  272. // }
  273. //
  274. // private void isRuntimeVisible(boolean b) {
  275. // isRuntimeVisible = b;
  276. // }
  277. //
  278. // public boolean isRuntimeVisible() {
  279. // return isRuntimeVisible;
  280. // }
  281. //
  282. // /**
  283. // * @return true if the annotation has a value with the specified name and (toString'd) value
  284. // */
  285. // public boolean hasNameValuePair(String name, String value) {
  286. // for (NameValuePair pair : pairs) {
  287. // if (pair.getNameString().equals(name)) {
  288. // if (pair.getValue().stringifyValue().equals(value)) {
  289. // return true;
  290. // }
  291. // }
  292. // }
  293. // return false;
  294. // }
  295. //
  296. // /**
  297. // * @return true if the annotation has a value with the specified name
  298. // */
  299. // public boolean hasNamedValue(String name) {
  300. // for (NameValuePair pair : pairs) {
  301. // if (pair.getNameString().equals(name)) {
  302. // return true;
  303. // }
  304. // }
  305. // return false;
  306. // }
  307. // public TypeAnnotationGen(TypeAnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) {
  308. // this.cpool = cpool;
  309. // if (copyPoolEntries) {
  310. // typeIndex = cpool.addUtf8(a.getTypeSignature());
  311. // } else {
  312. // typeIndex = a.getTypeIndex();
  313. // }
  314. // isRuntimeVisible = a.isRuntimeVisible();
  315. // pairs = copyValues(a.getValues(), cpool, copyPoolEntries);
  316. // }
  317. //
  318. // private List<NameValuePair> copyValues(List<NameValuePair> in, ConstantPool cpool, boolean copyPoolEntries) {
  319. // List<NameValuePair> out = new ArrayList<NameValuePair>();
  320. // for (NameValuePair nvp : in) {
  321. // out.add(new NameValuePair(nvp, cpool, copyPoolEntries));
  322. // }
  323. // return out;
  324. // }
  325. //
  326. //
  327. // /**
  328. // * Retrieve an immutable version of this AnnotationGen
  329. // */
  330. // public TypeAnnotationGen(ObjectType type, List<NameValuePair> pairs, boolean runtimeVisible, ConstantPool cpool) {
  331. // this.cpool = cpool;
  332. // if (type != null) {
  333. // this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects
  334. // }
  335. // this.pairs = pairs;
  336. // isRuntimeVisible = runtimeVisible;
  337. // }
  338. //
  339. public int[] getTypePath() {
  340. return typePath;
  341. }
  342. public String getTypePathString() {
  343. return toTypePathString(typePath);
  344. }
  345. public static String toTypePathString(int[] typepath) {
  346. StringBuilder sb = new StringBuilder();
  347. int count = 0;
  348. sb.append("[");
  349. while (count < typepath.length) {
  350. if (count>0) sb.append(",");
  351. switch (typepath[count++]) {
  352. case TYPE_PATH_ENTRY_KIND_ARRAY:
  353. sb.append("ARRAY");
  354. count++;
  355. break;
  356. case TYPE_PATH_ENTRY_KIND_INNER_TYPE:
  357. sb.append("INNER_TYPE");
  358. count++;
  359. break;
  360. case TYPE_PATH_ENTRY_KIND_WILDCARD:
  361. sb.append("WILDCARD");
  362. count++;
  363. break;
  364. case TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT:
  365. sb.append("TYPE_ARGUMENT(").append(typepath[count++]).append(")");
  366. break;
  367. }
  368. }
  369. sb.append("]");
  370. return sb.toString();
  371. }
  372. }