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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  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 ObjectType OBJECT_ARRAY = new ObjectType("java.lang.Object[]");
  88. public static final ObjectType STRING_ARRAY = new ObjectType("java.lang.String[]");
  89. public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
  90. public static final ObjectType STRINGBUILDER = new ObjectType("java.lang.StringBuilder");
  91. public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable");
  92. public static final ObjectType CLASS = new ObjectType("java.lang.Class");
  93. public static final ObjectType INTEGER = new ObjectType("java.lang.Integer");
  94. public static final ObjectType EXCEPTION = new ObjectType("java.lang.Exception");
  95. public static final ObjectType LIST = new ObjectType("java.util.List");
  96. public static final ObjectType ITERATOR = new ObjectType("java.util.Iterator");
  97. public static final Type[] NO_ARGS = new Type[0];
  98. public static final ReferenceType NULL = new ReferenceType() {
  99. };
  100. public static final Type UNKNOWN = new Type(Constants.T_UNKNOWN, "<unknown object>") {
  101. };
  102. public static final Type[] STRINGARRAY1 = new Type[] { STRING };
  103. public static final Type[] STRINGARRAY2 = new Type[] { STRING, STRING };
  104. public static final Type[] STRINGARRAY3 = new Type[] { STRING, STRING, STRING };
  105. public static final Type[] STRINGARRAY4 = new Type[] { STRING, STRING, STRING, STRING };
  106. public static final Type[] STRINGARRAY5 = new Type[] { STRING, STRING, STRING, STRING, STRING };
  107. public static final Type[] STRINGARRAY6 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING };
  108. public static final Type[] STRINGARRAY7 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING, STRING };
  109. private static Map<String, Type> commonTypes = new HashMap<String, Type>();
  110. static {
  111. commonTypes.put(STRING.getSignature(), STRING);
  112. commonTypes.put(THROWABLE.getSignature(), THROWABLE);
  113. commonTypes.put(VOID.getSignature(), VOID);
  114. commonTypes.put(BOOLEAN.getSignature(), BOOLEAN);
  115. commonTypes.put(BYTE.getSignature(), BYTE);
  116. commonTypes.put(SHORT.getSignature(), SHORT);
  117. commonTypes.put(CHAR.getSignature(), CHAR);
  118. commonTypes.put(INT.getSignature(), INT);
  119. commonTypes.put(LONG.getSignature(), LONG);
  120. commonTypes.put(DOUBLE.getSignature(), DOUBLE);
  121. commonTypes.put(FLOAT.getSignature(), FLOAT);
  122. commonTypes.put(CLASS.getSignature(), CLASS);
  123. commonTypes.put(OBJECT.getSignature(), OBJECT);
  124. commonTypes.put(STRING_ARRAY.getSignature(), STRING_ARRAY);
  125. commonTypes.put(OBJECT_ARRAY.getSignature(), OBJECT_ARRAY);
  126. commonTypes.put(INTEGER.getSignature(), INTEGER);
  127. commonTypes.put(EXCEPTION.getSignature(), EXCEPTION);
  128. commonTypes.put(STRINGBUFFER.getSignature(), STRINGBUFFER);
  129. commonTypes.put(STRINGBUILDER.getSignature(), STRINGBUILDER);
  130. commonTypes.put(LIST.getSignature(), LIST);
  131. commonTypes.put(ITERATOR.getSignature(), ITERATOR);
  132. ConstantsInitializer.initialize(); // needs calling because it will not have run properly the first time
  133. }
  134. protected Type(byte t, String s) {
  135. type = t;
  136. signature = s;
  137. }
  138. public String getSignature() {
  139. return signature;
  140. }
  141. public byte getType() {
  142. return type;
  143. }
  144. /**
  145. * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
  146. */
  147. public int getSize() {
  148. switch (type) {
  149. case Constants.T_DOUBLE:
  150. case Constants.T_LONG:
  151. return 2;
  152. case Constants.T_VOID:
  153. return 0;
  154. default:
  155. return 1;
  156. }
  157. }
  158. /**
  159. * @return Type string, e.g. 'int[]'
  160. */
  161. @Override
  162. public String toString() {
  163. return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility
  164. .signatureToString(signature, false);
  165. }
  166. public static final Type getType(String signature) {
  167. Type t = commonTypes.get(signature);
  168. if (t != null) {
  169. return t;
  170. }
  171. byte type = Utility.typeOfSignature(signature);
  172. if (type <= Constants.T_VOID) {
  173. return BasicType.getType(type);
  174. } else if (type == Constants.T_ARRAY) {
  175. int dim = 0;
  176. do {
  177. dim++;
  178. } while (signature.charAt(dim) == '[');
  179. // Recurse, but just once, if the signature is ok
  180. Type componentType = getType(signature.substring(dim));
  181. return new ArrayType(componentType, dim);
  182. } else { // type == T_REFERENCE
  183. // generics awareness
  184. int nextAngly = signature.indexOf('<');
  185. // Format is 'Lblahblah;'
  186. int index = signature.indexOf(';'); // Look for closing ';'
  187. String typeString = null;
  188. if (nextAngly == -1 || nextAngly > index) {
  189. typeString = signature.substring(1, index).replace('/', '.');
  190. } else {
  191. boolean endOfSigReached = false;
  192. int posn = nextAngly;
  193. int genericDepth = 0;
  194. while (!endOfSigReached) {
  195. switch (signature.charAt(posn++)) {
  196. case '<':
  197. genericDepth++;
  198. break;
  199. case '>':
  200. genericDepth--;
  201. break;
  202. case ';':
  203. if (genericDepth == 0) {
  204. endOfSigReached = true;
  205. }
  206. break;
  207. default:
  208. }
  209. }
  210. index = posn - 1;
  211. typeString = signature.substring(1, nextAngly).replace('/', '.');
  212. }
  213. // ObjectType doesn't currently store parameterized info
  214. return new ObjectType(typeString);
  215. }
  216. }
  217. /**
  218. * Convert signature to a Type object.
  219. *
  220. * @param signature signature string such as Ljava/lang/String;
  221. * @return type object
  222. */
  223. public static final TypeHolder getTypeInternal(String signature) throws StringIndexOutOfBoundsException {
  224. byte type = Utility.typeOfSignature(signature);
  225. if (type <= Constants.T_VOID) {
  226. return new TypeHolder(BasicType.getType(type), 1);
  227. } else if (type == Constants.T_ARRAY) {
  228. int dim = 0;
  229. do {
  230. dim++;
  231. } while (signature.charAt(dim) == '[');
  232. // Recurse, but just once, if the signature is ok
  233. TypeHolder th = getTypeInternal(signature.substring(dim));
  234. return new TypeHolder(new ArrayType(th.getType(), dim), dim + th.getConsumed());
  235. } else { // type == T_REFERENCE
  236. // Format is 'Lblahblah;'
  237. int index = signature.indexOf(';'); // Look for closing ';'
  238. if (index < 0) {
  239. throw new ClassFormatException("Invalid signature: " + signature);
  240. }
  241. // generics awareness
  242. int nextAngly = signature.indexOf('<');
  243. String typeString = null;
  244. if (nextAngly == -1 || nextAngly > index) {
  245. typeString = signature.substring(1, index).replace('/', '.');
  246. } else {
  247. boolean endOfSigReached = false;
  248. int posn = nextAngly;
  249. int genericDepth = 0;
  250. while (!endOfSigReached) {
  251. switch (signature.charAt(posn++)) {
  252. case '<':
  253. genericDepth++;
  254. break;
  255. case '>':
  256. genericDepth--;
  257. break;
  258. case ';':
  259. if (genericDepth == 0) {
  260. endOfSigReached = true;
  261. }
  262. break;
  263. default:
  264. }
  265. }
  266. index = posn - 1;
  267. typeString = signature.substring(1, nextAngly).replace('/', '.');
  268. }
  269. // ObjectType doesn't currently store parameterized info
  270. return new TypeHolder(new ObjectType(typeString), index + 1);
  271. }
  272. }
  273. /**
  274. * Convert return value of a method (signature) to a Type object.
  275. *
  276. * @param signature signature string such as (Ljava/lang/String;)V
  277. * @return return type
  278. */
  279. public static Type getReturnType(String signature) {
  280. try {
  281. // Read return type after ')'
  282. int index = signature.lastIndexOf(')') + 1;
  283. return getType(signature.substring(index));
  284. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  285. throw new ClassFormatException("Invalid method signature: " + signature);
  286. }
  287. }
  288. /**
  289. * Convert arguments of a method (signature) to an array of Type objects.
  290. *
  291. * @param signature signature string such as (Ljava/lang/String;)V
  292. * @return array of argument types
  293. */
  294. // OPTIMIZE crap impl
  295. public static Type[] getArgumentTypes(String signature) {
  296. List<Type> argumentTypes = new ArrayList<Type>();
  297. int index;
  298. Type[] types;
  299. try { // Read all declarations between for `(' and `)'
  300. if (signature.charAt(0) != '(') {
  301. throw new ClassFormatException("Invalid method signature: " + signature);
  302. }
  303. index = 1; // current string position
  304. while (signature.charAt(index) != ')') {
  305. TypeHolder th = getTypeInternal(signature.substring(index));
  306. argumentTypes.add(th.getType());
  307. index += th.getConsumed(); // update position
  308. }
  309. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  310. throw new ClassFormatException("Invalid method signature: " + signature);
  311. }
  312. types = new Type[argumentTypes.size()];
  313. argumentTypes.toArray(types);
  314. return types;
  315. }
  316. /**
  317. * Work out the type of each argument in the signature and return the cumulative sizes of all the types (size means number of
  318. * stack slots it consumes, eg double=2, int=1). Unlike the call above, this does minimal unpacking
  319. */
  320. public static int getArgumentSizes(String signature) {
  321. int size = 0;
  322. if (signature.charAt(0) != '(') {
  323. throw new ClassFormatException("Invalid method signature: " + signature);
  324. }
  325. int index = 1; // current string position
  326. try {
  327. while (signature.charAt(index) != ')') {
  328. byte type = Utility.typeOfSignature(signature.charAt(index));
  329. if (type <= Constants.T_VOID) {
  330. size += BasicType.getType(type).getSize();
  331. index++;
  332. } else if (type == Constants.T_ARRAY) {
  333. int dim = 0;
  334. do {
  335. dim++;
  336. } while (signature.charAt(dim + index) == '[');
  337. TypeHolder th = getTypeInternal(signature.substring(dim + index));
  338. size += 1;
  339. index += dim + th.getConsumed();
  340. } else { // type == T_REFERENCE
  341. // Format is 'Lblahblah;'
  342. int index2 = signature.indexOf(';', index); // Look for closing ';'
  343. // generics awareness
  344. int nextAngly = signature.indexOf('<', index);
  345. if (nextAngly == -1 || nextAngly > index2) {
  346. } else {
  347. boolean endOfSigReached = false;
  348. int posn = nextAngly;
  349. int genericDepth = 0;
  350. while (!endOfSigReached) {
  351. switch (signature.charAt(posn++)) {
  352. case '<':
  353. genericDepth++;
  354. break;
  355. case '>':
  356. genericDepth--;
  357. break;
  358. case ';':
  359. if (genericDepth == 0) {
  360. endOfSigReached = true;
  361. }
  362. break;
  363. default:
  364. }
  365. }
  366. index2 = posn - 1;
  367. }
  368. size++;
  369. index = index2 + 1;
  370. }
  371. }
  372. } catch (StringIndexOutOfBoundsException e) { // Should never occur
  373. throw new ClassFormatException("Invalid method signature: " + signature);
  374. }
  375. return size;
  376. }
  377. /**
  378. * Return the size of the type expressed in the signature. The signature should contain only one type.
  379. */
  380. public static int getTypeSize(String signature) {
  381. byte type = Utility.typeOfSignature(signature.charAt(0));
  382. if (type <= Constants.T_VOID) {
  383. return BasicType.getType(type).getSize();
  384. } else if (type == Constants.T_ARRAY) {
  385. return 1;
  386. } else { // type == T_REFERENCE
  387. return 1;
  388. }
  389. }
  390. /**
  391. * Convert runtime java.lang.Class to BCEL Type object.
  392. *
  393. * @param cl Java class
  394. * @return corresponding Type object
  395. */
  396. public static Type getType(java.lang.Class cl) {
  397. if (cl == null) {
  398. throw new IllegalArgumentException("Class must not be null");
  399. }
  400. /*
  401. * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway.
  402. */
  403. if (cl.isArray()) {
  404. return getType(cl.getName());
  405. } else if (cl.isPrimitive()) {
  406. if (cl == Integer.TYPE) {
  407. return INT;
  408. } else if (cl == Void.TYPE) {
  409. return VOID;
  410. } else if (cl == Double.TYPE) {
  411. return DOUBLE;
  412. } else if (cl == Float.TYPE) {
  413. return FLOAT;
  414. } else if (cl == Boolean.TYPE) {
  415. return BOOLEAN;
  416. } else if (cl == Byte.TYPE) {
  417. return BYTE;
  418. } else if (cl == Short.TYPE) {
  419. return SHORT;
  420. } else if (cl == Byte.TYPE) {
  421. return BYTE;
  422. } else if (cl == Long.TYPE) {
  423. return LONG;
  424. } else if (cl == Character.TYPE) {
  425. return CHAR;
  426. } else {
  427. throw new IllegalStateException("Ooops, what primitive type is " + cl);
  428. }
  429. } else { // "Real" class
  430. return new ObjectType(cl.getName());
  431. }
  432. }
  433. public static String getSignature(java.lang.reflect.Method meth) {
  434. StringBuffer sb = new StringBuffer("(");
  435. Class[] params = meth.getParameterTypes(); // avoid clone
  436. for (int j = 0; j < params.length; j++) {
  437. sb.append(getType(params[j]).getSignature());
  438. }
  439. sb.append(")");
  440. sb.append(getType(meth.getReturnType()).getSignature());
  441. return sb.toString();
  442. }
  443. public static String getSignature(java.lang.reflect.Constructor<?> cons) {
  444. StringBuffer sb = new StringBuffer("(");
  445. Class<?>[] params = cons.getParameterTypes(); // avoid clone
  446. for (int j = 0; j < params.length; j++) {
  447. sb.append(getType(params[j]).getSignature());
  448. }
  449. sb.append(")V");
  450. return sb.toString();
  451. }
  452. public static class TypeHolder {
  453. private Type t;
  454. private int consumed;
  455. public Type getType() {
  456. return t;
  457. }
  458. public int getConsumed() {
  459. return consumed;
  460. }
  461. public TypeHolder(Type t, int i) {
  462. this.t = t;
  463. this.consumed = i;
  464. }
  465. }
  466. }