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

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
9 years ago
9 years ago
14 years ago
14 years ago
14 years ago
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. }