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.

CtConstructor.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2003 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. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist;
  16. import javassist.bytecode.*;
  17. import javassist.compiler.Javac;
  18. import javassist.compiler.CompileError;
  19. import javassist.expr.ExprEditor;
  20. /* Some methods do nothing except calling the super's method.
  21. * They might seem redundant but they are necessary so that javadoc
  22. * includes the description of those methods in the page of this class.
  23. */
  24. /**
  25. * An instance of CtConstructor represents a constructor.
  26. * It may represent a static constructor
  27. * (class initializer). To distinguish a constructor and a class
  28. * initializer, call <code>isClassInitializer()</code>.
  29. *
  30. * @see CtClass#getDeclaredConstructors()
  31. * @see CtClass#getClassInitializer()
  32. * @see CtNewConstructor
  33. */
  34. public final class CtConstructor extends CtBehavior {
  35. protected CtConstructor next;
  36. protected CtConstructor(MethodInfo minfo, CtClass declaring) {
  37. super(declaring, minfo);
  38. next = null;
  39. }
  40. /**
  41. * Creates a constructor with no constructor body.
  42. * The created constructor
  43. * must be added to a class with <code>CtClass.addConstructor()</code>.
  44. *
  45. * <p>The created constructor does not include a constructor body,
  46. * must be specified with <code>setBody()</code>.
  47. *
  48. * @param declaring the class to which the created method is added.
  49. * @param parameters a list of the parameter types
  50. *
  51. * @see CtClass#addConstructor(CtConstructor)
  52. * @see CtConstructor#setBody(String)
  53. * @see CtConstructor#setBody(CtConstructor,ClassMap)
  54. */
  55. public CtConstructor(CtClass[] parameters, CtClass declaring) {
  56. this((MethodInfo)null, declaring);
  57. ConstPool cp = declaring.getClassFile2().getConstPool();
  58. String desc = Descriptor.ofConstructor(parameters);
  59. methodInfo = new MethodInfo(cp, "<init>", desc);
  60. setModifiers(Modifier.PUBLIC);
  61. }
  62. /**
  63. * Creates a copy of a <code>CtConstructor</code> object.
  64. * The created constructor must be
  65. * added to a class with <code>CtClass.addConstructor()</code>.
  66. *
  67. * <p>All occurrences of class names in the created constructor
  68. * are replaced with names specified by
  69. * <code>map</code> if <code>map</code> is not <code>null</code>.
  70. *
  71. * <p>By default, all the occurrences of the names of the class
  72. * declaring <code>src</code> and the superclass are replaced
  73. * with the name of the class and the superclass that
  74. * the created constructor is added to.
  75. * This is done whichever <code>map</code> is null or not.
  76. * To prevent this replacement, call <code>ClassMap.fix()</code>.
  77. *
  78. * <p><b>Note:</b> if the <code>.class</code> notation (for example,
  79. * <code>String.class</code>) is included in an expression, the
  80. * Javac compiler may produce a helper method.
  81. * Since this constructor never
  82. * copies this helper method, the programmers have the responsiblity of
  83. * copying it. Otherwise, use <code>Class.forName()</code> in the
  84. * expression.
  85. *
  86. * @param src the source method.
  87. * @param declaring the class to which the created method is added.
  88. * @param map the hashtable associating original class names
  89. * with substituted names.
  90. * It can be <code>null</code>.
  91. *
  92. * @see CtClass#addConstructor(CtConstructor)
  93. * @see ClassMap#fix(String)
  94. */
  95. public CtConstructor(CtConstructor src, CtClass declaring, ClassMap map)
  96. throws CannotCompileException
  97. {
  98. this((MethodInfo)null, declaring);
  99. MethodInfo srcInfo = src.methodInfo;
  100. CtClass srcClass = src.getDeclaringClass();
  101. ConstPool cp = declaring.getClassFile2().getConstPool();
  102. if (map == null)
  103. map = new ClassMap();
  104. map.put(srcClass.getName(), declaring.getName());
  105. try {
  106. boolean patch = false;
  107. CtClass srcSuper = srcClass.getSuperclass();
  108. String destSuperName = declaring.getSuperclass().getName();
  109. if (srcSuper != null) {
  110. String srcSuperName = srcSuper.getName();
  111. if (!srcSuperName.equals(destSuperName))
  112. if (srcSuperName.equals(CtClass.javaLangObject))
  113. patch = true;
  114. else
  115. map.put(srcSuperName, destSuperName);
  116. }
  117. methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
  118. if (patch)
  119. methodInfo.setSuperclass(destSuperName);
  120. }
  121. catch (NotFoundException e) {
  122. throw new CannotCompileException(e);
  123. }
  124. catch (BadBytecode e) {
  125. throw new CannotCompileException(e);
  126. }
  127. }
  128. static CtConstructor append(CtConstructor list, CtConstructor tail) {
  129. tail.next = null;
  130. if (list == null)
  131. return tail;
  132. else {
  133. CtConstructor lst = list;
  134. while (lst.next != null)
  135. lst = lst.next;
  136. lst.next = tail;
  137. return list;
  138. }
  139. }
  140. static int count(CtConstructor m) {
  141. int n = 0;
  142. while (m != null) {
  143. ++n;
  144. m = m.next;
  145. }
  146. return n;
  147. }
  148. /**
  149. * Returns the MethodInfo representing the constructor in the
  150. * class file.
  151. */
  152. public MethodInfo getMethodInfo() {
  153. return super.getMethodInfo();
  154. }
  155. /**
  156. * Returns true if this object represents a constructor.
  157. */
  158. public boolean isConstructor() {
  159. return methodInfo.isConstructor();
  160. }
  161. /**
  162. * Returns true if this object represents a static initializer.
  163. */
  164. public boolean isClassInitializer() {
  165. return methodInfo.isStaticInitializer();
  166. }
  167. /**
  168. * Obtains the encoded modifiers of the constructor.
  169. *
  170. * @return modifiers encoded with
  171. * <code>javassist.Modifier</code>.
  172. * @see Modifier
  173. */
  174. public int getModifiers() {
  175. return super.getModifiers();
  176. }
  177. /**
  178. * Sets the encoded modifiers of the constructor.
  179. *
  180. * @see Modifier
  181. */
  182. public void setModifiers(int mod) {
  183. super.setModifiers(mod);
  184. }
  185. /**
  186. * Obtains the name of this constructor.
  187. * It is the same as the simple name of the class declaring this
  188. * constructor. If this object represents a class initializer,
  189. * then this method returns <code>"&lt;clinit&gt;"</code>.
  190. */
  191. public String getName() {
  192. if (methodInfo.isStaticInitializer())
  193. return MethodInfo.nameClinit;
  194. else
  195. return declaringClass.getName();
  196. }
  197. /**
  198. * Returns the class that declares this constructor.
  199. */
  200. public CtClass getDeclaringClass() {
  201. return super.getDeclaringClass();
  202. }
  203. /**
  204. * Obtains parameter types of this constructor.
  205. */
  206. public CtClass[] getParameterTypes() throws NotFoundException {
  207. return super.getParameterTypes();
  208. }
  209. /**
  210. * Returns the character string representing the parameter types.
  211. * If two constructors have the same parameter types,
  212. * <code>getSignature()</code> returns the same string.
  213. */
  214. public String getSignature() {
  215. return super.getSignature();
  216. }
  217. /**
  218. * Obtains exceptions that this constructor may throw.
  219. */
  220. public CtClass[] getExceptionTypes() throws NotFoundException {
  221. return super.getExceptionTypes();
  222. }
  223. /**
  224. * Sets exceptions that this constructor may throw.
  225. */
  226. public void setExceptionTypes(CtClass[] types)
  227. throws NotFoundException
  228. {
  229. super.setExceptionTypes(types);
  230. }
  231. /**
  232. * Returns true if the constructor is the default one.
  233. */
  234. public boolean isEmpty() {
  235. CodeAttribute ca = getMethodInfo2().getCodeAttribute();
  236. if (ca == null)
  237. return false; // native or abstract??
  238. // they are not allowed, though.
  239. ConstPool cp = ca.getConstPool();
  240. CodeIterator it = ca.iterator();
  241. try {
  242. int pos, desc;
  243. return it.byteAt(it.next()) == Opcode.ALOAD_0
  244. && it.byteAt(pos = it.next()) == Opcode.INVOKESPECIAL
  245. && (desc = cp.isConstructor(CtClass.javaLangObject,
  246. it.u16bitAt(pos + 1))) != 0
  247. && cp.getUtf8Info(desc).equals("()V")
  248. && it.byteAt(it.next()) == Opcode.RETURN
  249. && !it.hasNext();
  250. }
  251. catch (BadBytecode e) {}
  252. return false;
  253. }
  254. /**
  255. * Sets a constructor body.
  256. *
  257. * @param src the source code representing the constructor body.
  258. * It must be a single statement or block.
  259. */
  260. public void setBody(String src) throws CannotCompileException {
  261. super.setBody(src);
  262. }
  263. /**
  264. * Copies a constructor body from another constructor.
  265. *
  266. * <p>All occurrences of the class names in the copied body
  267. * are replaced with the names specified by
  268. * <code>map</code> if <code>map</code> is not <code>null</code>.
  269. *
  270. * @param src the method that the body is copied from.
  271. * @param map the hashtable associating original class names
  272. * with substituted names.
  273. * It can be <code>null</code>.
  274. */
  275. public void setBody(CtConstructor src, ClassMap map)
  276. throws CannotCompileException
  277. {
  278. setBody0(src.declaringClass, src.methodInfo,
  279. declaringClass, methodInfo, map);
  280. }
  281. /**
  282. * Obtains an attribute with the given name.
  283. * If that attribute is not found in the class file, this
  284. * method returns null.
  285. *
  286. * @param name attribute name
  287. */
  288. public byte[] getAttribute(String name) {
  289. return super.getAttribute(name);
  290. }
  291. /**
  292. * Adds an attribute. The attribute is saved in the class file.
  293. *
  294. * @param name attribute name
  295. * @param data attribute value
  296. */
  297. public void setAttribute(String name, byte[] data) {
  298. super.setAttribute(name, data);
  299. }
  300. /**
  301. * Declares to use <code>$cflow</code> for this constructor.
  302. * If <code>$cflow</code> is used, the class files modified
  303. * with Javassist requires a support class
  304. * <code>javassist.runtime.Cflow</code> at runtime
  305. * (other Javassist classes are not required at runtime).
  306. *
  307. * <p>Every <code>$cflow</code> variable is given a unique name.
  308. * For example, if the given name is <code>"Point.paint"</code>,
  309. * then the variable is indicated by <code>$cflow(Point.paint)</code>.
  310. *
  311. * @param name <code>$cflow</code> name. It can include
  312. * alphabets, numbers, <code>_</code>,
  313. * <code>$</code>, and <code>.</code> (dot).
  314. *
  315. * @see javassist.runtime.Cflow
  316. */
  317. public void useCflow(String name) throws CannotCompileException {
  318. super.useCflow(name);
  319. }
  320. /**
  321. * Modifies the constructor body.
  322. *
  323. * @param converter specifies how to modify.
  324. */
  325. public void instrument(CodeConverter converter)
  326. throws CannotCompileException
  327. {
  328. super.instrument(converter);
  329. }
  330. /**
  331. * Modifies the constructor body.
  332. *
  333. * @param editor specifies how to modify.
  334. */
  335. public void instrument(ExprEditor editor)
  336. throws CannotCompileException
  337. {
  338. super.instrument(editor);
  339. }
  340. /**
  341. * Inserts bytecode at the beginning of the constructor body.
  342. * Since the bytecode is inserted before a constructor in the super
  343. * class or this class is called, the bytecode is subject
  344. * to constraints described
  345. * in Section 4.8.2 of The Java Virtual Machine Specification (2nd ed).
  346. * For example, it cannot access instance members although it can access
  347. * static members.
  348. *
  349. * @param src the source code representing the inserted bytecode.
  350. * It must be a single statement or block.
  351. */
  352. public void insertBefore(String src) throws CannotCompileException {
  353. super.insertBefore(src);
  354. }
  355. /**
  356. * Inserts bytecode just after another constructor in the super class
  357. * or this class is called.
  358. *
  359. * @param src the source code representing the inserted bytecode.
  360. * It must be a single statement or block.
  361. */
  362. public void insertBeforeBody(String src) throws CannotCompileException {
  363. declaringClass.checkModify();
  364. CodeAttribute ca = methodInfo.getCodeAttribute();
  365. CodeIterator iterator = ca.iterator();
  366. Bytecode b = new Bytecode(methodInfo.getConstPool(),
  367. ca.getMaxStack(), ca.getMaxLocals());
  368. b.setStackDepth(ca.getMaxStack());
  369. Javac jv = new Javac(b, declaringClass);
  370. try {
  371. jv.recordParams(getParameterTypes(), false);
  372. jv.compileStmnt(src);
  373. ca.setMaxStack(b.getMaxStack());
  374. ca.setMaxLocals(b.getMaxLocals());
  375. iterator.skipConstructor();
  376. int pos = iterator.insertEx(b.get());
  377. iterator.insert(b.getExceptionTable(), pos);
  378. }
  379. catch (NotFoundException e) {
  380. throw new CannotCompileException(e);
  381. }
  382. catch (CompileError e) {
  383. throw new CannotCompileException(e);
  384. }
  385. catch (BadBytecode e) {
  386. throw new CannotCompileException(e);
  387. }
  388. }
  389. /**
  390. * Inserts bytecode at the end of the constructor body.
  391. * The bytecode is inserted just before every return insturction.
  392. * It is not executed when an exception is thrown.
  393. *
  394. * @param src the source code representing the inserted bytecode.
  395. * It must be a single statement or block.
  396. */
  397. public void insertAfter(String src)
  398. throws CannotCompileException
  399. {
  400. super.insertAfter(src);
  401. }
  402. /**
  403. * Inserts bytecode at the end of the constructor body.
  404. * The bytecode is inserted just before every return insturction.
  405. *
  406. * @param src the source code representing the inserted bytecode.
  407. * It must be a single statement or block.
  408. * @param asFinally true if the inserted bytecode is executed
  409. * not only when the transfer normally returns
  410. * but also when an exception is thrown.
  411. */
  412. public void insertAfter(String src, boolean asFinally)
  413. throws CannotCompileException
  414. {
  415. super.insertAfter(src, asFinally);
  416. }
  417. /**
  418. * Adds a catch clause that handles an exception thrown in the
  419. * constructor body.
  420. * The catch clause must end with a return or throw statement.
  421. *
  422. * @param src the source code representing the catch clause.
  423. * It must be a single statement or block.
  424. * @param exceptionType the type of the exception handled by the
  425. * catch clause.
  426. */
  427. public void addCatch(String src, CtClass exceptionType)
  428. throws CannotCompileException
  429. {
  430. super.addCatch(src, exceptionType);
  431. }
  432. }