1. package com.sun.org.apache.bcel.internal.classfile;
  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 com.sun.org.apache.bcel.internal.Constants;
  56. import com.sun.org.apache.bcel.internal.Repository;
  57. import java.io.*;
  58. import java.util.StringTokenizer;
  59. /**
  60. * Represents a Java class, i.e., the data structures, constant pool,
  61. * fields, methods and commands contained in a Java .class file.
  62. * See <a href="ftp://java.sun.com/docs/specs/">JVM
  63. * specification</a> for details.
  64. *
  65. * @version $Id: JavaClass.java,v 1.1 2003/12/12 08:57:41 rameshm Exp $
  66. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  67. */
  68. public class JavaClass extends AccessFlags implements Cloneable, Node {
  69. private String file_name;
  70. private String package_name;
  71. private String source_file_name = "<Unknown>";
  72. private int class_name_index;
  73. private int superclass_name_index;
  74. private String class_name;
  75. private String superclass_name;
  76. private int major, minor; // Compiler version
  77. private ConstantPool constant_pool; // Constant pool
  78. private int[] interfaces; // implemented interfaces
  79. private String[] interface_names;
  80. private Field[] fields; // Fields, i.e., variables of class
  81. private Method[] methods; // methods defined in the class
  82. private Attribute[] attributes; // attributes defined in the class
  83. private byte source = HEAP; // Generated in memory
  84. public static final byte HEAP = 1;
  85. public static final byte FILE = 2;
  86. public static final byte ZIP = 3;
  87. static boolean debug = false; // Debugging on/off
  88. static char sep = '/'; // directory separator
  89. /**
  90. * Constructor gets all contents as arguments.
  91. *
  92. * @param class_name Class name
  93. * @param superclass_name Superclass name
  94. * @param file_name File name
  95. * @param major Major compiler version
  96. * @param minor Minor compiler version
  97. * @param access_flags Access rights defined by bit flags
  98. * @param constant_pool Array of constants
  99. * @param interfaces Implemented interfaces
  100. * @param fields Class fields
  101. * @param methods Class methods
  102. * @param attributes Class attributes
  103. * @param source Read from file or generated in memory?
  104. */
  105. public JavaClass(int class_name_index,
  106. int superclass_name_index,
  107. String file_name,
  108. int major,
  109. int minor,
  110. int access_flags,
  111. ConstantPool constant_pool,
  112. int[] interfaces,
  113. Field[] fields,
  114. Method[] methods,
  115. Attribute[] attributes,
  116. byte source)
  117. {
  118. if(interfaces == null) // Allowed for backward compatibility
  119. interfaces = new int[0];
  120. if(attributes == null)
  121. this.attributes = new Attribute[0];
  122. if(fields == null)
  123. fields = new Field[0];
  124. if(methods == null)
  125. methods = new Method[0];
  126. this.class_name_index = class_name_index;
  127. this.superclass_name_index = superclass_name_index;
  128. this.file_name = file_name;
  129. this.major = major;
  130. this.minor = minor;
  131. this.access_flags = access_flags;
  132. this.constant_pool = constant_pool;
  133. this.interfaces = interfaces;
  134. this.fields = fields;
  135. this.methods = methods;
  136. this.attributes = attributes;
  137. this.source = source;
  138. // Get source file name if available
  139. for(int i=0; i < attributes.length; i++) {
  140. if(attributes[i] instanceof SourceFile) {
  141. source_file_name = ((SourceFile)attributes[i]).getSourceFileName();
  142. break;
  143. }
  144. }
  145. // Get class name and superclass name
  146. ConstantUtf8 name;
  147. /* According to the specification the following entries must be of type
  148. * `ConstantClass' but we check that anyway via the
  149. * `ConstPool.getConstant' method.
  150. */
  151. class_name = constant_pool.getConstantString(class_name_index,
  152. Constants.CONSTANT_Class);
  153. class_name = Utility.compactClassName(class_name, false);
  154. int index = class_name.lastIndexOf('.');
  155. if(index < 0)
  156. package_name = "";
  157. else
  158. package_name = class_name.substring(0, index);
  159. if(superclass_name_index > 0) { // May be zero -> class is java.lang.Object
  160. superclass_name = constant_pool.getConstantString(superclass_name_index,
  161. Constants.CONSTANT_Class);
  162. superclass_name = Utility.compactClassName(superclass_name, false);
  163. }
  164. else
  165. superclass_name = "java.lang.Object";
  166. interface_names = new String[interfaces.length];
  167. for(int i=0; i < interfaces.length; i++) {
  168. String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
  169. interface_names[i] = Utility.compactClassName(str, false);
  170. }
  171. }
  172. /**
  173. * Constructor gets all contents as arguments.
  174. *
  175. * @param class_name Class name
  176. * @param superclass_name Superclass name
  177. * @param file_name File name
  178. * @param major Major compiler version
  179. * @param minor Minor compiler version
  180. * @param access_flags Access rights defined by bit flags
  181. * @param constant_pool Array of constants
  182. * @param interfaces Implemented interfaces
  183. * @param fields Class fields
  184. * @param methods Class methods
  185. * @param attributes Class attributes
  186. */
  187. public JavaClass(int class_name_index,
  188. int superclass_name_index,
  189. String file_name,
  190. int major,
  191. int minor,
  192. int access_flags,
  193. ConstantPool constant_pool,
  194. int[] interfaces,
  195. Field[] fields,
  196. Method[] methods,
  197. Attribute[] attributes) {
  198. this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
  199. constant_pool, interfaces, fields, methods, attributes, HEAP);
  200. }
  201. /**
  202. * Called by objects that are traversing the nodes of the tree implicitely
  203. * defined by the contents of a Java class. I.e., the hierarchy of methods,
  204. * fields, attributes, etc. spawns a tree of objects.
  205. *
  206. * @param v Visitor object
  207. */
  208. public void accept(Visitor v) {
  209. v.visitJavaClass(this);
  210. }
  211. /* Print debug information depending on `JavaClass.debug'
  212. */
  213. static final void Debug(String str) {
  214. if(debug)
  215. System.out.println(str);
  216. }
  217. /**
  218. * Dump class to a file.
  219. *
  220. * @param file Output file
  221. * @throw IOException
  222. */
  223. public void dump(File file) throws IOException
  224. {
  225. String parent = file.getParent();
  226. if(parent != null) {
  227. File dir = new File(parent);
  228. if(dir != null)
  229. dir.mkdirs();
  230. }
  231. dump(new DataOutputStream(new FileOutputStream(file)));
  232. }
  233. /**
  234. * Dump class to a file named file_name.
  235. *
  236. * @param file_name Output file name
  237. * @exception IOException
  238. */
  239. public void dump(String file_name) throws IOException
  240. {
  241. dump(new File(file_name));
  242. }
  243. /**
  244. * @return class in binary format
  245. */
  246. public byte[] getBytes() {
  247. ByteArrayOutputStream s = new ByteArrayOutputStream();
  248. DataOutputStream ds = new DataOutputStream(s);
  249. try {
  250. dump(ds);
  251. ds.close();
  252. } catch(IOException e) { e.printStackTrace(); }
  253. return s.toByteArray();
  254. }
  255. /**
  256. * Dump Java class to output stream in binary format.
  257. *
  258. * @param file Output stream
  259. * @exception IOException
  260. */
  261. public void dump(OutputStream file) throws IOException {
  262. dump(new DataOutputStream(file));
  263. }
  264. /**
  265. * Dump Java class to output stream in binary format.
  266. *
  267. * @param file Output stream
  268. * @exception IOException
  269. */
  270. public void dump(DataOutputStream file) throws IOException
  271. {
  272. file.writeInt(0xcafebabe);
  273. file.writeShort(minor);
  274. file.writeShort(major);
  275. constant_pool.dump(file);
  276. file.writeShort(access_flags);
  277. file.writeShort(class_name_index);
  278. file.writeShort(superclass_name_index);
  279. file.writeShort(interfaces.length);
  280. for(int i=0; i < interfaces.length; i++)
  281. file.writeShort(interfaces[i]);
  282. file.writeShort(fields.length);
  283. for(int i=0; i < fields.length; i++)
  284. fields[i].dump(file);
  285. file.writeShort(methods.length);
  286. for(int i=0; i < methods.length; i++)
  287. methods[i].dump(file);
  288. if(attributes != null) {
  289. file.writeShort(attributes.length);
  290. for(int i=0; i < attributes.length; i++)
  291. attributes[i].dump(file);
  292. }
  293. else
  294. file.writeShort(0);
  295. file.close();
  296. }
  297. /**
  298. * @return Attributes of the class.
  299. */
  300. public Attribute[] getAttributes() { return attributes; }
  301. /**
  302. * @return Class name.
  303. */
  304. public String getClassName() { return class_name; }
  305. /**
  306. * @return Package name.
  307. */
  308. public String getPackageName() { return package_name; }
  309. /**
  310. * @return Class name index.
  311. */
  312. public int getClassNameIndex() { return class_name_index; }
  313. /**
  314. * @return Constant pool.
  315. */
  316. public ConstantPool getConstantPool() { return constant_pool; }
  317. /**
  318. * @return Fields, i.e., variables of the class.
  319. */
  320. public Field[] getFields() { return fields; }
  321. /**
  322. * @return File name of class, aka SourceFile attribute value
  323. */
  324. public String getFileName() { return file_name; }
  325. /**
  326. * @return Names of implemented interfaces.
  327. */
  328. public String[] getInterfaceNames() { return interface_names; }
  329. /**
  330. * @return Implemented interfaces.
  331. */
  332. public int[] getInterfaces() { return interfaces; }
  333. /**
  334. * @return Major number of compiler version.
  335. */
  336. public int getMajor() { return major; }
  337. /**
  338. * @return Methods of the class.
  339. */
  340. public Method[] getMethods() { return methods; }
  341. /**
  342. * @return Minor number of compiler version.
  343. */
  344. public int getMinor() { return minor; }
  345. /**
  346. * @return sbsolute path to file where this class was read from
  347. */
  348. public String getSourceFileName() { return source_file_name; }
  349. /**
  350. * @return Superclass name.
  351. */
  352. public String getSuperclassName() { return superclass_name; }
  353. /**
  354. * @return Class name index.
  355. */
  356. public int getSuperclassNameIndex() { return superclass_name_index; }
  357. static {
  358. // Debugging ... on/off
  359. //String debug = System.getProperty("JavaClass.debug");
  360. //if(debug != null)
  361. // JavaClass.debug = new Boolean(debug).booleanValue();
  362. // Get path separator either / or \ usually
  363. JavaClass.sep = java.io.File.separatorChar;
  364. }
  365. /**
  366. * @param attributes.
  367. */
  368. public void setAttributes(Attribute[] attributes) {
  369. this.attributes = attributes;
  370. }
  371. /**
  372. * @param class_name.
  373. */
  374. public void setClassName(String class_name) {
  375. this.class_name = class_name;
  376. }
  377. /**
  378. * @param class_name_index.
  379. */
  380. public void setClassNameIndex(int class_name_index) {
  381. this.class_name_index = class_name_index;
  382. }
  383. /**
  384. * @param constant_pool.
  385. */
  386. public void setConstantPool(ConstantPool constant_pool) {
  387. this.constant_pool = constant_pool;
  388. }
  389. /**
  390. * @param fields.
  391. */
  392. public void setFields(Field[] fields) {
  393. this.fields = fields;
  394. }
  395. /**
  396. * Set File name of class, aka SourceFile attribute value
  397. */
  398. public void setFileName(String file_name) {
  399. this.file_name = file_name;
  400. }
  401. /**
  402. * @param interface_names.
  403. */
  404. public void setInterfaceNames(String[] interface_names) {
  405. this.interface_names = interface_names;
  406. }
  407. /**
  408. * @param interfaces.
  409. */
  410. public void setInterfaces(int[] interfaces) {
  411. this.interfaces = interfaces;
  412. }
  413. /**
  414. * @param major.
  415. */
  416. public void setMajor(int major) {
  417. this.major = major;
  418. }
  419. /**
  420. * @param methods.
  421. */
  422. public void setMethods(Method[] methods) {
  423. this.methods = methods;
  424. }
  425. /**
  426. * @param minor.
  427. */
  428. public void setMinor(int minor) {
  429. this.minor = minor;
  430. }
  431. /**
  432. * Set absolute path to file this class was read from.
  433. */
  434. public void setSourceFileName(String source_file_name) {
  435. this.source_file_name = source_file_name;
  436. }
  437. /**
  438. * @param superclass_name.
  439. */
  440. public void setSuperclassName(String superclass_name) {
  441. this.superclass_name = superclass_name;
  442. }
  443. /**
  444. * @param superclass_name_index.
  445. */
  446. public void setSuperclassNameIndex(int superclass_name_index) {
  447. this.superclass_name_index = superclass_name_index;
  448. }
  449. /**
  450. * @return String representing class contents.
  451. */
  452. public String toString() {
  453. String access = Utility.accessToString(access_flags, true);
  454. access = access.equals("")? "" : (access + " ");
  455. StringBuffer buf = new StringBuffer(access +
  456. Utility.classOrInterface(access_flags) +
  457. " " +
  458. class_name + " extends " +
  459. Utility.compactClassName(superclass_name,
  460. false) + '\n');
  461. int size = interfaces.length;
  462. if(size > 0) {
  463. buf.append("implements\t\t");
  464. for(int i=0; i < size; i++) {
  465. buf.append(interface_names[i]);
  466. if(i < size - 1)
  467. buf.append(", ");
  468. }
  469. buf.append('\n');
  470. }
  471. buf.append("filename\t\t" + file_name + '\n');
  472. buf.append("compiled from\t\t" + source_file_name + '\n');
  473. buf.append("compiler version\t" + major + "." + minor + '\n');
  474. buf.append("access flags\t\t" + access_flags + '\n');
  475. buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n");
  476. buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
  477. if(attributes.length > 0) {
  478. buf.append("\nAttribute(s):\n");
  479. for(int i=0; i < attributes.length; i++)
  480. buf.append(indent(attributes[i]));
  481. }
  482. if(fields.length > 0) {
  483. buf.append("\n" + fields.length + " fields:\n");
  484. for(int i=0; i < fields.length; i++)
  485. buf.append("\t" + fields[i] + '\n');
  486. }
  487. if(methods.length > 0) {
  488. buf.append("\n" + methods.length + " methods:\n");
  489. for(int i=0; i < methods.length; i++)
  490. buf.append("\t" + methods[i] + '\n');
  491. }
  492. return buf.toString();
  493. }
  494. private static final String indent(Object obj) {
  495. StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
  496. StringBuffer buf = new StringBuffer();
  497. while(tok.hasMoreTokens())
  498. buf.append("\t" + tok.nextToken() + "\n");
  499. return buf.toString();
  500. }
  501. /**
  502. * @return deep copy of this class
  503. */
  504. public JavaClass copy() {
  505. JavaClass c = null;
  506. try {
  507. c = (JavaClass)clone();
  508. } catch(CloneNotSupportedException e) {}
  509. c.constant_pool = constant_pool.copy();
  510. c.interfaces = (int[])interfaces.clone();
  511. c.interface_names = (String[])interface_names.clone();
  512. c.fields = new Field[fields.length];
  513. for(int i=0; i < fields.length; i++)
  514. c.fields[i] = fields[i].copy(c.constant_pool);
  515. c.methods = new Method[methods.length];
  516. for(int i=0; i < methods.length; i++)
  517. c.methods[i] = methods[i].copy(c.constant_pool);
  518. c.attributes = new Attribute[attributes.length];
  519. for(int i=0; i < attributes.length; i++)
  520. c.attributes[i] = attributes[i].copy(c.constant_pool);
  521. return c;
  522. }
  523. public final boolean instanceOf(JavaClass super_class) {
  524. return Repository.instanceOf(this, super_class);
  525. }
  526. public final boolean isSuper() {
  527. return (access_flags & Constants.ACC_SUPER) != 0;
  528. }
  529. public final boolean isClass() {
  530. return (access_flags & Constants.ACC_INTERFACE) == 0;
  531. }
  532. /** @return returns either HEAP (generated), FILE, or ZIP
  533. */
  534. public final byte getSource() {
  535. return source;
  536. }
  537. }