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.

Type.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package org.aspectj.apache.bcel.generic;
  2. /* ====================================================================
  3. * The Apache Software License, Version 1.1
  4. *
  5. * Copyright (c) 2001 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Apache" and "Apache Software Foundation" and
  28. * "Apache BCEL" must not be used to endorse or promote products
  29. * derived from this software without prior written permission. For
  30. * written permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * "Apache BCEL", nor may "Apache" appear in their name, without
  34. * prior written permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation. For more
  52. * information on the Apache Software Foundation, please see
  53. * <http://www.apache.org/>.
  54. */
  55. import java.util.ArrayList;
  56. import java.util.HashMap;
  57. import java.util.List;
  58. import java.util.Map;
  59. import org.aspectj.apache.bcel.Constants;
  60. import org.aspectj.apache.bcel.ConstantsInitializer;
  61. import org.aspectj.apache.bcel.classfile.ClassFormatException;
  62. import org.aspectj.apache.bcel.classfile.Utility;
  63. /**
  64. * Abstract super class for all possible java types, namely basic types such as int, object types like String and array types, e.g.
  65. * int[]
  66. *
  67. * @version $Id: Type.java,v 1.14 2011/09/28 01:14:54 aclement Exp $
  68. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  69. *
  70. * modified: AndyClement 2-mar-05: Removed unnecessary static and optimized
  71. */
  72. public abstract class Type {
  73. protected byte type;
  74. protected String signature;
  75. /* Predefined constants */
  76. public static final BasicType VOID = new BasicType(Constants.T_VOID);
  77. public static final BasicType BOOLEAN = new BasicType(Constants.T_BOOLEAN);
  78. public static final BasicType INT = new BasicType(Constants.T_INT);
  79. public static final BasicType SHORT = new BasicType(Constants.T_SHORT);
  80. public static final BasicType BYTE = new BasicType(Constants.T_BYTE);
  81. public static final BasicType LONG = new BasicType(Constants.T_LONG);
  82. public static final BasicType DOUBLE = new BasicType(Constants.T_DOUBLE);
  83. public static final BasicType FLOAT = new BasicType(Constants.T_FLOAT);
  84. public static final BasicType CHAR = new BasicType(Constants.T_CHAR);
  85. public static final ObjectType OBJECT = new ObjectType("java.lang.Object");
  86. public static final ObjectType STRING = new ObjectType("java.lang.String");
  87. public static final ArrayType OBJECT_ARRAY = new ArrayType("java.lang.Object",1);
  88. public static final ArrayType STRING_ARRAY = new ArrayType("java.lang.String",1);
  89. public static final ArrayType CLASS_ARRAY = new ArrayType("java.lang.Class",1);
  90. public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
  91. public static final ObjectType STRINGBUILDER = new ObjectType("java.lang.StringBuilder");
  92. public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable");
  93. public static final ObjectType CLASS = new ObjectType("java.lang.Class");
  94. public static final ObjectType INTEGER = new ObjectType("java.lang.Integer");
  95. public static final ObjectType EXCEPTION = new ObjectType("java.lang.Exception");
  96. public static final ObjectType LIST = new ObjectType("java.util.List");
  97. public static final ObjectType ITERATOR = new ObjectType("java.util.Iterator");
  98. public static final Type[] NO_ARGS = new Type[0];
  99. public static final ReferenceType NULL = new ReferenceType() {
  100. };
  101. public static final Type UNKNOWN = new Type(Constants.T_UNKNOWN, "<unknown object>") {
  102. };
  103. public static final Type[] STRINGARRAY1 = new Type[] { STRING };
  104. public static final Type[] STRINGARRAY2 = new Type[] { STRING, STRING };
  105. public static final Type[] STRINGARRAY3 = new Type[] { STRING, STRING, STRING };
  106. public static final Type[] STRINGARRAY4 = new Type[] { STRING, STRING, STRING, STRING };
  107. public static final Type[] STRINGARRAY5 = new Type[] { STRING, STRING, STRING, STRING, STRING };
  108. public static final Type[] STRINGARRAY6 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING };
  109. public static final Type[] STRINGARRAY7 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING, STRING };
  110. private static Map<String, Type> commonTypes = new HashMap<>();
  111. static {
  112. commonTypes.put(STRING.getSignature(), STRING);
  113. commonTypes.put(THROWABLE.getSignature(), THROWABLE);
  114. commonTypes.put(VOID.getSignature(), VOID);
  115. commonTypes.put(BOOLEAN.getSignature(), BOOLEAN);
  116. commonTypes.put(BYTE.getSignature(), BYTE);
  117. commonTypes.put(SHORT.getSignature(), SHORT);
  118. commonTypes.put(CHAR.getSignature(), CHAR);
  119. commonTypes.put(INT.getSignature(), INT);
  120. commonTypes.put(LONG.getSignature(), LONG);
  121. commonTypes.put(DOUBLE.getSignature(), DOUBLE);
  122. commonTypes.put(FLOAT.getSignature(), FLOAT);
  123. commonTypes.put(CLASS.getSignature(), CLASS);
  124. commonTypes.put(OBJECT.getSignature(), OBJECT);
  125. commonTypes.put(STRING_ARRAY.getSignature(), STRING_ARRAY);
  126. commonTypes.put(CLASS_ARRAY.getSignature(), CLASS_ARRAY);
  127. commonTypes.put(OBJECT_ARRAY.getSignature(), OBJECT_ARRAY);
  128. commonTypes.put(INTEGER.getSignature(), INTEGER);
  129. commonTypes.put(EXCEPTION.getSignature(), EXCEPTION);
  130. commonTypes.put(STRINGBUFFER.getSignature(), STRINGBUFFER);
  131. commonTypes.put(STRINGBUILDER.getSignature(), STRINGBUILDER);
  132. commonTypes.put(LIST.getSignature(), LIST);
  133. commonTypes.put(ITERATOR.getSignature(), ITERATOR);
  134. ConstantsInitializer.initialize(); // needs calling because it will not have run properly the first time
  135. }
  136. protected Type(byte t, String s) {
  137. type = t;
  138. signature = s;
  139. }
  140. public String getSignature() {
  141. return signature;
  142. }
  143. public byte getType() {
  144. return type;
  145. }
  146. /**
  147. * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
  148. */
  149. public int getSize() {
  150. switch (type) {
  151. case Constants.T_DOUBLE:
  152. case Constants.T_LONG:
  153. return 2;
  154. case Constants.T_VOID:
  155. return 0;
  156. default:
  157. return 1;
  158. }
  159. }
  160. /**
  161. * @return Type string, e.g. 'int[]'
  162. */
  163. @Override
  164. public String toString() {
  165. return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility
  166. .signatureToString(signature, false);
  167. }
  168. public static final Type getType(String signature) {
  169. Type t = commonTypes.get(signature);
  170. if (t != null) {
  171. return t;
  172. }
  173. byte type = Utility.typeOfSignature(signature);
  174. if (type <= Constants.T_VOID) {
  175. return BasicType.getType(type);
  176. } else if (type == Constants.T_ARRAY) {
  177. int dim = 0;
  178. do {
  179. dim++;
  180. } while (signature.charAt(dim) == '[');
  181. // Recurse, but just once, if the signature is ok
  182. Type componentType = getType(signature.substring(dim));
  183. return new ArrayType(componentType, dim);
  184. } else { // type == T_REFERENCE
  185. // generics awareness
  186. int nextAngly = signature.indexOf('<');
  187. // Format is 'Lblahblah;'
  188. int index = signature.indexOf(';'); // Look for closing ';'
  189. String typeString = null;
  190. if (nextAngly == -1 || nextAngly > index) {
  191. typeString = signature.substring(1, index).replace('/', '.');
  192. } else {
  193. boolean endOfSigReached = false;
  194. int posn = nextAngly;
  195. int genericDepth = 0;
  196. while (!endOfSigReached) {
  197. switch (signature.charAt(posn++)) {
  198. case '<':
  199. genericDepth++;
  200. break;
  201. case '>':
  202. genericDepth--;
  203. break;
  204. case ';':
  205. if (genericDepth == 0) {
  206. endOfSigReached = true;
  207. }
  208. break;
  209. default:
  210. }
  211. }
  212. index = posn - 1;
  213. typeString = signature.substring(1, nextAngly).replace('/', '.');
  214. }
  215. // ObjectType doesn't currently store parameterized info
  216. return new ObjectType(typeString);
  217. }
  218. }
  219. /**
  220. * Convert signature to a Type object.
  221. *
  222. * @param signature signature string such as Ljava/lang/String;
  223. * @return type object
  224. */
  225. public static final TypeHolder getTypeInternal(String signature) throws StringIndexOutOfBoundsException {
  226. byte type = Utility.typeOfSignature(signature);
  227. if (type <= Constants.T_VOID) {
  228. return new TypeHolder(BasicType.getType(type), 1);
  229. } else if (type == Constants.T_ARRAY) {
  230. int dim = 0;
  231. do {
  232. dim++;
  233. } while (signature.charAt(dim) == '[');
  234. // Recurse, but just once, if the signature is ok
  235. TypeHolder th = getTypeInternal(signature.substring(dim));
  236. return new TypeHolder(new ArrayType(th.getType(), dim), dim + th.getConsumed());
  237. } else { // type == T_REFERENCE
  238. // Format is 'Lblahblah;'
  239. int index = signature.indexOf(';'); // Look for closing ';'
  240. if (index < 0) {
  241. throw new ClassFormatException("Invalid signature: " + signature);
  242. }
  243. // generics awareness
  244. int nextAngly = signature.indexOf('<');
  245. String typeString = null;
  246. if (nextAngly == -1 || nextAngly > index) {
  247. typeString = signature.substring(1, index).replace('/', '.');
  248. } else {
  249. boolean endOfSigReached = false;
  250. int posn = nextAngly;
  251. int genericDepth = 0;
  252. while (!endOfSigReached) {
  253. switch (signature.charAt(posn++)) {
  254. case '<':
  255. genericDepth++;
  256. break;
  257. case '>':
  258. genericDepth--;
  259. break;
  260. case ';':
  261. if (genericDepth == 0) {
  262. endOfSigReached = true;
  263. }
  264. break;
  265. default:
  266. }
  267. }
  268. index = posn - 1;
  269. typeString = signature.substring(1, nextAngly).replace('/', '.');
  270. }
  271. // ObjectType doesn't currently store parameterized info
  272. return new TypeHolder(new ObjectType(typeString), index + 1);
  273. }
  274. }
  275. /**
  276. * Convert return value of a method (signature) to a Type object.
  277. *
  278. * @param signature signature string such as (Ljava/lang/String;)V
  279. * @return return type
  280. */
  281. public static Type getReturnType(String signature) {
  282. try {
  283. // Read return type after ')'
  284. int index = signature.lastIndexOf(')') + 1;
  285. return getType(signature.substring(index));
  286. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  287. throw new ClassFormatException("Invalid method signature: " + signature);
  288. }
  289. }
  290. /**
  291. * Convert arguments of a method (signature) to an array of Type objects.
  292. *
  293. * @param signature signature string such as (Ljava/lang/String;)V
  294. * @return array of argument types
  295. */
  296. // OPTIMIZE crap impl
  297. public static Type[] getArgumentTypes(String signature) {
  298. List<Type> argumentTypes = new ArrayList<>();
  299. int index;
  300. Type[] types;
  301. try { // Read all declarations between for `(' and `)'
  302. if (signature.charAt(0) != '(') {
  303. throw new ClassFormatException("Invalid method signature: " + signature);
  304. }
  305. index = 1; // current string position
  306. while (signature.charAt(index) != ')') {
  307. TypeHolder th = getTypeInternal(signature.substring(index));
  308. argumentTypes.add(th.getType());
  309. index += th.getConsumed(); // update position
  310. }
  311. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  312. throw new ClassFormatException("Invalid method signature: " + signature);
  313. }
  314. types = new Type[argumentTypes.size()];
  315. argumentTypes.toArray(types);
  316. return types;
  317. }
  318. /**
  319. * Work out the type of each argument in the signature and return the cumulative sizes of all the types (size means number of
  320. * stack slots it consumes, eg double=2, int=1). Unlike the call above, this does minimal unpacking
  321. */
  322. public static int getArgumentSizes(String signature) {
  323. int size = 0;
  324. if (signature.charAt(0) != '(') {
  325. throw new ClassFormatException("Invalid method signature: " + signature);
  326. }
  327. int index = 1; // current string position
  328. try {
  329. while (signature.charAt(index) != ')') {
  330. byte type = Utility.typeOfSignature(signature.charAt(index));
  331. if (type <= Constants.T_VOID) {
  332. size += BasicType.getType(type).getSize();
  333. index++;
  334. } else if (type == Constants.T_ARRAY) {
  335. int dim = 0;
  336. do {
  337. dim++;
  338. } while (signature.charAt(dim + index) == '[');
  339. TypeHolder th = getTypeInternal(signature.substring(dim + index));
  340. size += 1;
  341. index += dim + th.getConsumed();
  342. } else { // type == T_REFERENCE
  343. // Format is 'Lblahblah;'
  344. int index2 = signature.indexOf(';', index); // Look for closing ';'
  345. // generics awareness
  346. int nextAngly = signature.indexOf('<', index);
  347. if (nextAngly == -1 || nextAngly > index2) {
  348. } else {
  349. boolean endOfSigReached = false;
  350. int posn = nextAngly;
  351. int genericDepth = 0;
  352. while (!endOfSigReached) {
  353. switch (signature.charAt(posn++)) {
  354. case '<':
  355. genericDepth++;
  356. break;
  357. case '>':
  358. genericDepth--;
  359. break;
  360. case ';':
  361. if (genericDepth == 0) {
  362. endOfSigReached = true;
  363. }
  364. break;
  365. default:
  366. }
  367. }
  368. index2 = posn - 1;
  369. }
  370. size++;
  371. index = index2 + 1;
  372. }
  373. }
  374. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  375. throw new ClassFormatException("Invalid method signature: " + signature);
  376. }
  377. return size;
  378. }
  379. /**
  380. * Return the size of the type expressed in the signature. The signature should contain only one type.
  381. */
  382. public static int getTypeSize(String signature) {
  383. byte type = Utility.typeOfSignature(signature.charAt(0));
  384. if (type <= Constants.T_VOID) {
  385. return BasicType.getType(type).getSize();
  386. } else if (type == Constants.T_ARRAY) {
  387. return 1;
  388. } else { // type == T_REFERENCE
  389. return 1;
  390. }
  391. }
  392. /**
  393. * Convert runtime java.lang.Class to BCEL Type object.
  394. *
  395. * @param cl Java class
  396. * @return corresponding Type object
  397. */
  398. public static Type getType(java.lang.Class cl) {
  399. if (cl == null) {
  400. throw new IllegalArgumentException("Class must not be null");
  401. }
  402. /*
  403. * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway.
  404. */
  405. if (cl.isArray()) {
  406. return getType(cl.getName());
  407. } else if (cl.isPrimitive()) {
  408. if (cl == Integer.TYPE) {
  409. return INT;
  410. } else if (cl == Void.TYPE) {
  411. return VOID;
  412. } else if (cl == Double.TYPE) {
  413. return DOUBLE;
  414. } else if (cl == Float.TYPE) {
  415. return FLOAT;
  416. } else if (cl == Boolean.TYPE) {
  417. return BOOLEAN;
  418. } else if (cl == Byte.TYPE) {
  419. return BYTE;
  420. } else if (cl == Short.TYPE) {
  421. return SHORT;
  422. } else if (cl == Byte.TYPE) {
  423. return BYTE;
  424. } else if (cl == Long.TYPE) {
  425. return LONG;
  426. } else if (cl == Character.TYPE) {
  427. return CHAR;
  428. } else {
  429. throw new IllegalStateException("Ooops, what primitive type is " + cl);
  430. }
  431. } else { // "Real" class
  432. return new ObjectType(cl.getName());
  433. }
  434. }
  435. public static String getSignature(java.lang.reflect.Method meth) {
  436. StringBuilder sb = new StringBuilder("(");
  437. Class[] params = meth.getParameterTypes(); // avoid clone
  438. for (Class param : params) {
  439. sb.append(getType(param).getSignature());
  440. }
  441. sb.append(")");
  442. sb.append(getType(meth.getReturnType()).getSignature());
  443. return sb.toString();
  444. }
  445. public static String getSignature(java.lang.reflect.Constructor<?> cons) {
  446. StringBuilder sb = new StringBuilder("(");
  447. Class<?>[] params = cons.getParameterTypes(); // avoid clone
  448. for (Class<?> param : params) {
  449. sb.append(getType(param).getSignature());
  450. }
  451. sb.append(")V");
  452. return sb.toString();
  453. }
  454. public static class TypeHolder {
  455. private Type t;
  456. private int consumed;
  457. public Type getType() {
  458. return t;
  459. }
  460. public int getConsumed() {
  461. return consumed;
  462. }
  463. public TypeHolder(Type t, int i) {
  464. this.t = t;
  465. this.consumed = i;
  466. }
  467. }
  468. }