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.

JavaClass.java 22KB

3 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
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. package org.aspectj.apache.bcel.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 java.io.ByteArrayOutputStream;
  56. import java.io.DataOutputStream;
  57. import java.io.File;
  58. import java.io.FileOutputStream;
  59. import java.io.IOException;
  60. import java.io.OutputStream;
  61. import java.util.ArrayList;
  62. import java.util.Collection;
  63. import java.util.Collections;
  64. import java.util.LinkedList;
  65. import java.util.List;
  66. import java.util.Queue;
  67. import java.util.StringTokenizer;
  68. import org.aspectj.apache.bcel.Constants;
  69. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  70. import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos;
  71. import org.aspectj.apache.bcel.generic.Type;
  72. import org.aspectj.apache.bcel.util.SyntheticRepository;
  73. /**
  74. * Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java .class file.
  75. * See <a href="ftp://java.sun.com/docs/specs/">JVM specification</a> for details.
  76. *
  77. * The intent of this class is to represent a parsed or otherwise existing class file. Those interested in programatically
  78. * generating classes should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
  79. *
  80. * @version $Id: JavaClass.java,v 1.22 2009/09/15 19:40:14 aclement Exp $
  81. * @see org.aspectj.apache.bcel.generic.ClassGen
  82. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  83. */
  84. public class JavaClass extends Modifiers implements Cloneable, Node {
  85. private static final String[] NoInterfaceNames = new String[0];
  86. private static final Field[] NoFields = new Field[0];
  87. private static final Method[] NoMethod = new Method[0];
  88. private static final int[] NoInterfaceIndices = new int[0];
  89. private static final Attribute[] NoAttributes = new Attribute[0];
  90. private String fileName;
  91. private String packageName;
  92. private String sourcefileName;
  93. private int classnameIdx;
  94. private int superclassnameIdx;
  95. private String classname;
  96. private String superclassname;
  97. private int major, minor;
  98. private ConstantPool cpool;
  99. private int[] interfaces;
  100. private String[] interfacenames;
  101. private Field[] fields;
  102. private Method[] methods;
  103. private Attribute[] attributes;
  104. private AnnotationGen[] annotations;
  105. private boolean isGeneric = false;
  106. private boolean isAnonymous = false;
  107. private boolean isNested = false;
  108. private boolean computedNestedTypeStatus = false;
  109. // Annotations are collected from certain attributes, don't do it more than necessary!
  110. private boolean annotationsOutOfDate = true;
  111. // state for dealing with generic signature string
  112. private String signatureAttributeString = null;
  113. private Signature signatureAttribute = null;
  114. private boolean searchedForSignatureAttribute = false;
  115. /**
  116. * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any better.
  117. */
  118. private transient org.aspectj.apache.bcel.util.Repository repository = null;
  119. public JavaClass(int classnameIndex, int superclassnameIndex, String filename, int major, int minor, int access_flags,
  120. ConstantPool cpool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes) {
  121. if (interfaces == null) {
  122. interfaces = NoInterfaceIndices;
  123. }
  124. this.classnameIdx = classnameIndex;
  125. this.superclassnameIdx = superclassnameIndex;
  126. this.fileName = filename;
  127. this.major = major;
  128. this.minor = minor;
  129. this.modifiers = access_flags;
  130. this.cpool = cpool;
  131. this.interfaces = interfaces;
  132. this.fields = (fields == null ? NoFields : fields);
  133. this.methods = (methods == null ? NoMethod : methods);
  134. this.attributes = (attributes == null ? NoAttributes : attributes);
  135. annotationsOutOfDate = true;
  136. // Get source file name if available
  137. SourceFile sfAttribute = AttributeUtils.getSourceFileAttribute(attributes);
  138. sourcefileName = sfAttribute == null ? "<Unknown>" : sfAttribute.getSourceFileName();
  139. /*
  140. * According to the specification the following entries must be of type `ConstantClass' but we check that anyway via the
  141. * `ConstPool.getConstant' method.
  142. */
  143. classname = cpool.getConstantString(classnameIndex, Constants.CONSTANT_Class);
  144. classname = Utility.compactClassName(classname, false);
  145. int index = classname.lastIndexOf('.');
  146. if (index < 0) {
  147. packageName = "";
  148. } else {
  149. packageName = classname.substring(0, index);
  150. }
  151. if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object
  152. superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class);
  153. superclassname = Utility.compactClassName(superclassname, false);
  154. } else {
  155. superclassname = "java.lang.Object";
  156. }
  157. if (interfaces.length == 0) {
  158. interfacenames = NoInterfaceNames;
  159. } else {
  160. interfacenames = new String[interfaces.length];
  161. for (int i = 0; i < interfaces.length; i++) {
  162. String str = cpool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
  163. interfacenames[i] = Utility.compactClassName(str, false);
  164. }
  165. }
  166. }
  167. /**
  168. * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class. I.e., the
  169. * hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  170. *
  171. * @param v Visitor object
  172. */
  173. public void accept(ClassVisitor v) {
  174. v.visitJavaClass(this);
  175. }
  176. /**
  177. * Dump class to a file.
  178. *
  179. * @param file Output file
  180. * @throws IOException
  181. */
  182. public void dump(File file) throws IOException {
  183. String parent = file.getParent();
  184. if (parent != null) {
  185. File dir = new File(parent);
  186. dir.mkdirs();
  187. }
  188. dump(new DataOutputStream(new FileOutputStream(file)));
  189. }
  190. /**
  191. * Dump class to a file named file_name.
  192. *
  193. * @param file_name Output file name
  194. * @exception IOException
  195. */
  196. public void dump(String file_name) throws IOException {
  197. dump(new File(file_name));
  198. }
  199. /**
  200. * @return class in binary format
  201. */
  202. public byte[] getBytes() {
  203. ByteArrayOutputStream s = new ByteArrayOutputStream();
  204. DataOutputStream ds = new DataOutputStream(s);
  205. try {
  206. dump(ds);
  207. } catch (IOException e) {
  208. e.printStackTrace();
  209. } finally {
  210. try {
  211. ds.close();
  212. } catch (IOException e2) {
  213. e2.printStackTrace();
  214. }
  215. }
  216. return s.toByteArray();
  217. }
  218. /**
  219. * Dump Java class to output stream in binary format.
  220. */
  221. public void dump(OutputStream file) throws IOException {
  222. dump(new DataOutputStream(file));
  223. }
  224. /**
  225. * Dump Java class to output stream in binary format.
  226. */
  227. public void dump(DataOutputStream file) throws IOException {
  228. file.writeInt(0xcafebabe);
  229. file.writeShort(minor);
  230. file.writeShort(major);
  231. cpool.dump(file);
  232. file.writeShort(modifiers);
  233. file.writeShort(classnameIdx);
  234. file.writeShort(superclassnameIdx);
  235. file.writeShort(interfaces.length);
  236. for (int anInterface : interfaces) {
  237. file.writeShort(anInterface);
  238. }
  239. file.writeShort(fields.length);
  240. for (Field field : fields) {
  241. field.dump(file);
  242. }
  243. file.writeShort(methods.length);
  244. for (Method method : methods) {
  245. method.dump(file);
  246. }
  247. AttributeUtils.writeAttributes(attributes, file);
  248. file.close();
  249. }
  250. public Attribute[] getAttributes() {
  251. return attributes;
  252. }
  253. public AnnotationGen[] getAnnotations() {
  254. if (annotationsOutOfDate) {
  255. // Find attributes that contain annotation data
  256. List<AnnotationGen> accumulatedAnnotations = new ArrayList<>();
  257. for (Attribute attribute : attributes) {
  258. if (attribute instanceof RuntimeAnnos) {
  259. RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) attribute;
  260. accumulatedAnnotations.addAll(runtimeAnnotations.getAnnotations());
  261. }
  262. }
  263. annotations = accumulatedAnnotations.toArray(new AnnotationGen[] {});
  264. annotationsOutOfDate = false;
  265. }
  266. return annotations;
  267. }
  268. /**
  269. * @return Class name.
  270. */
  271. public String getClassName() {
  272. return classname;
  273. }
  274. /**
  275. * @return Package name.
  276. */
  277. public String getPackageName() {
  278. return packageName;
  279. }
  280. public int getClassNameIndex() {
  281. return classnameIdx;
  282. }
  283. public ConstantPool getConstantPool() {
  284. return cpool;
  285. }
  286. /**
  287. * @return Fields, i.e., variables of the class. Like the JVM spec mandates for the classfile format, these fields are those
  288. * specific to this class, and not those of the superclass or superinterfaces.
  289. */
  290. public Field[] getFields() {
  291. return fields;
  292. }
  293. /**
  294. * @return File name of class, aka SourceFile attribute value
  295. */
  296. public String getFileName() {
  297. return fileName;
  298. }
  299. /**
  300. * @return Names of implemented interfaces.
  301. */
  302. public String[] getInterfaceNames() {
  303. return interfacenames;
  304. }
  305. /**
  306. * @return Indices in constant pool of implemented interfaces.
  307. */
  308. public int[] getInterfaceIndices() {
  309. return interfaces;
  310. }
  311. public int getMajor() {
  312. return major;
  313. }
  314. /**
  315. * @return Methods of the class.
  316. */
  317. public Method[] getMethods() {
  318. return methods;
  319. }
  320. /**
  321. * @return A org.aspectj.apache.bcel.classfile.Method corresponding to java.lang.reflect.Method if any
  322. */
  323. public Method getMethod(java.lang.reflect.Method m) {
  324. for (Method method : methods) {
  325. if (m.getName().equals(method.getName()) && m.getModifiers() == method.getModifiers()
  326. && Type.getSignature(m).equals(method.getSignature())) {
  327. return method;
  328. }
  329. }
  330. return null;
  331. }
  332. public Method getMethod(java.lang.reflect.Constructor<?> c) {
  333. for (Method method : methods) {
  334. if (method.getName().equals("<init>") && c.getModifiers() == method.getModifiers()
  335. && Type.getSignature(c).equals(method.getSignature())) {
  336. return method;
  337. }
  338. }
  339. return null;
  340. }
  341. public Field getField(java.lang.reflect.Field field) {
  342. String fieldName = field.getName();
  343. for (Field f : fields) {
  344. if (f.getName().equals(fieldName)) {
  345. return f;
  346. }
  347. }
  348. return null;
  349. }
  350. /**
  351. * @return Minor number of class file version.
  352. */
  353. public int getMinor() {
  354. return minor;
  355. }
  356. /**
  357. * @return sbsolute path to file where this class was read from
  358. */
  359. public String getSourceFileName() {
  360. return sourcefileName;
  361. }
  362. /**
  363. * @return Superclass name.
  364. */
  365. public String getSuperclassName() {
  366. return superclassname;
  367. }
  368. /**
  369. * @return Class name index.
  370. */
  371. public int getSuperclassNameIndex() {
  372. return superclassnameIdx;
  373. }
  374. /**
  375. * @param attributes .
  376. */
  377. public void setAttributes(Attribute[] attributes) {
  378. this.attributes = attributes;
  379. annotationsOutOfDate = true;
  380. }
  381. /**
  382. * @param class_name .
  383. */
  384. public void setClassName(String class_name) {
  385. this.classname = class_name;
  386. }
  387. /**
  388. * @param class_name_index .
  389. */
  390. public void setClassNameIndex(int class_name_index) {
  391. this.classnameIdx = class_name_index;
  392. }
  393. /**
  394. * @param constant_pool .
  395. */
  396. public void setConstantPool(ConstantPool constant_pool) {
  397. this.cpool = constant_pool;
  398. }
  399. /**
  400. * @param fields .
  401. */
  402. public void setFields(Field[] fields) {
  403. this.fields = fields;
  404. }
  405. /**
  406. * Set File name of class, aka SourceFile attribute value
  407. */
  408. public void setFileName(String file_name) {
  409. this.fileName = file_name;
  410. }
  411. /**
  412. * @param interface_names .
  413. */
  414. public void setInterfaceNames(String[] interface_names) {
  415. this.interfacenames = interface_names;
  416. }
  417. /**
  418. * @param interfaces .
  419. */
  420. public void setInterfaces(int[] interfaces) {
  421. this.interfaces = interfaces;
  422. }
  423. public void setMajor(int major) {
  424. this.major = major;
  425. }
  426. public void setMethods(Method[] methods) {
  427. this.methods = methods;
  428. }
  429. public void setMinor(int minor) {
  430. this.minor = minor;
  431. }
  432. /**
  433. * Set absolute path to file this class was read from.
  434. */
  435. public void setSourceFileName(String source_file_name) {
  436. this.sourcefileName = source_file_name;
  437. }
  438. /**
  439. * @param superclass_name .
  440. */
  441. public void setSuperclassName(String superclass_name) {
  442. this.superclassname = superclass_name;
  443. }
  444. /**
  445. * @param superclass_name_index .
  446. */
  447. public void setSuperclassNameIndex(int superclass_name_index) {
  448. this.superclassnameIdx = superclass_name_index;
  449. }
  450. /**
  451. * @return String representing class contents.
  452. */
  453. @Override
  454. public String toString() {
  455. String access = Utility.accessToString(modifiers, true);
  456. access = access.equals("") ? "" : access + " ";
  457. StringBuilder buf = new StringBuilder(access + Utility.classOrInterface(modifiers) + " " + classname + " extends "
  458. + Utility.compactClassName(superclassname, false) + '\n');
  459. int size = interfaces.length;
  460. if (size > 0) {
  461. buf.append("implements\t\t");
  462. for (int i = 0; i < size; i++) {
  463. buf.append(interfacenames[i]);
  464. if (i < size - 1) {
  465. buf.append(", ");
  466. }
  467. }
  468. buf.append('\n');
  469. }
  470. buf.append("filename\t\t" + fileName + '\n');
  471. buf.append("compiled from\t\t" + sourcefileName + '\n');
  472. buf.append("compiler version\t" + major + "." + minor + '\n');
  473. buf.append("access flags\t\t" + modifiers + '\n');
  474. buf.append("constant pool\t\t" + cpool.getLength() + " entries\n");
  475. buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
  476. if (attributes.length > 0) {
  477. buf.append("\nAttribute(s):\n");
  478. for (Attribute attribute : attributes) {
  479. buf.append(indent(attribute));
  480. }
  481. }
  482. if (annotations != null && annotations.length > 0) {
  483. buf.append("\nAnnotation(s):\n");
  484. for (AnnotationGen annotation : annotations) {
  485. buf.append(indent(annotation));
  486. }
  487. }
  488. if (fields.length > 0) {
  489. buf.append("\n" + fields.length + " fields:\n");
  490. for (Field field : fields) {
  491. buf.append("\t" + field + '\n');
  492. }
  493. }
  494. if (methods.length > 0) {
  495. buf.append("\n" + methods.length + " methods:\n");
  496. for (Method method : methods) {
  497. buf.append("\t" + method + '\n');
  498. }
  499. }
  500. return buf.toString();
  501. }
  502. private static final String indent(Object obj) {
  503. StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
  504. StringBuilder buf = new StringBuilder();
  505. while (tok.hasMoreTokens()) {
  506. buf.append("\t" + tok.nextToken() + "\n");
  507. }
  508. return buf.toString();
  509. }
  510. public final boolean isSuper() {
  511. return (modifiers & Constants.ACC_SUPER) != 0;
  512. }
  513. public final boolean isClass() {
  514. return (modifiers & Constants.ACC_INTERFACE) == 0;
  515. }
  516. public final boolean isAnonymous() {
  517. computeNestedTypeStatus();
  518. return this.isAnonymous;
  519. }
  520. public final boolean isNested() {
  521. computeNestedTypeStatus();
  522. return this.isNested;
  523. }
  524. private final void computeNestedTypeStatus() {
  525. if (computedNestedTypeStatus) {
  526. return;
  527. }
  528. // Attribute[] attrs = attributes.getAttributes();
  529. for (Attribute attribute : attributes) {
  530. if (attribute instanceof InnerClasses) {
  531. InnerClass[] innerClasses = ((InnerClasses) attribute).getInnerClasses();
  532. for (InnerClass innerClass : innerClasses) {
  533. boolean innerClassAttributeRefersToMe = false;
  534. String inner_class_name = cpool.getConstantString(innerClass.getInnerClassIndex(),
  535. Constants.CONSTANT_Class);
  536. inner_class_name = Utility.compactClassName(inner_class_name);
  537. if (inner_class_name.equals(getClassName())) {
  538. innerClassAttributeRefersToMe = true;
  539. }
  540. if (innerClassAttributeRefersToMe) {
  541. this.isNested = true;
  542. if (innerClass.getInnerNameIndex() == 0) {
  543. this.isAnonymous = true;
  544. }
  545. }
  546. }
  547. }
  548. }
  549. this.computedNestedTypeStatus = true;
  550. }
  551. // J5SUPPORT:
  552. /**
  553. * Returns true if this class represents an annotation, i.e. it was a 'public @interface blahblah' declaration
  554. */
  555. public final boolean isAnnotation() {
  556. return (modifiers & Constants.ACC_ANNOTATION) != 0;
  557. }
  558. /**
  559. * Returns true if this class represents an enum type
  560. */
  561. public final boolean isEnum() {
  562. return (modifiers & Constants.ACC_ENUM) != 0;
  563. }
  564. /********************* New repository functionality *********************/
  565. /**
  566. * Gets the ClassRepository which holds its definition. By default this is the same as SyntheticRepository.getInstance();
  567. */
  568. public org.aspectj.apache.bcel.util.Repository getRepository() {
  569. if (repository == null) {
  570. repository = SyntheticRepository.getInstance();
  571. }
  572. return repository;
  573. }
  574. /**
  575. * Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done.
  576. */
  577. public void setRepository(org.aspectj.apache.bcel.util.Repository repository) {
  578. this.repository = repository;
  579. }
  580. /**
  581. * Equivalent to runtime "instanceof" operator.
  582. *
  583. * @return true if this JavaClass is derived from teh super class
  584. */
  585. public final boolean instanceOf(JavaClass super_class) {
  586. if (this.equals(super_class)) {
  587. return true;
  588. }
  589. JavaClass[] super_classes = getSuperClasses();
  590. for (JavaClass superClass : super_classes) {
  591. if (superClass.equals(super_class)) {
  592. return true;
  593. }
  594. }
  595. if (super_class.isInterface()) {
  596. return implementationOf(super_class);
  597. }
  598. return false;
  599. }
  600. /**
  601. * @return true, if clazz is an implementation of interface inter
  602. */
  603. public boolean implementationOf(JavaClass inter) {
  604. if (!inter.isInterface()) {
  605. throw new IllegalArgumentException(inter.getClassName() + " is no interface");
  606. }
  607. if (this.equals(inter)) {
  608. return true;
  609. }
  610. Collection<JavaClass> superInterfaces = getAllInterfaces();
  611. for (JavaClass superInterface : superInterfaces) {
  612. if (superInterface.equals(inter)) {
  613. return true;
  614. }
  615. }
  616. // for (int i = 0; i < super_interfaces.length; i++) {
  617. // if (super_interfaces[i].equals(inter)) {
  618. // return true;
  619. // }
  620. // }
  621. return false;
  622. }
  623. /**
  624. * @return the superclass for this JavaClass object, or null if this is java.lang.Object
  625. */
  626. public JavaClass getSuperClass() {
  627. if ("java.lang.Object".equals(getClassName())) {
  628. return null;
  629. }
  630. try {
  631. return getRepository().loadClass(getSuperclassName());
  632. } catch (ClassNotFoundException e) {
  633. System.err.println(e);
  634. return null;
  635. }
  636. }
  637. /**
  638. * @return list of super classes of this class in ascending order, i.e., java.lang.Object is always the last element
  639. */
  640. public JavaClass[] getSuperClasses() {
  641. JavaClass clazz = this;
  642. List<JavaClass> vec = new ArrayList<>();
  643. for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
  644. vec.add(clazz);
  645. }
  646. return vec.toArray(new JavaClass[0]);
  647. }
  648. /**
  649. * Get interfaces directly implemented by this JavaClass.
  650. */
  651. public JavaClass[] getInterfaces() {
  652. String[] interfaces = getInterfaceNames();
  653. JavaClass[] classes = new JavaClass[interfaces.length];
  654. try {
  655. for (int i = 0; i < interfaces.length; i++) {
  656. classes[i] = getRepository().loadClass(interfaces[i]);
  657. }
  658. } catch (ClassNotFoundException e) {
  659. System.err.println(e);
  660. return null;
  661. }
  662. return classes;
  663. }
  664. /**
  665. * Get all interfaces implemented by this JavaClass (transitively).
  666. */
  667. public Collection<JavaClass> getAllInterfaces() {
  668. Queue<JavaClass> queue = new LinkedList<>();
  669. List<JavaClass> interfaceList = new ArrayList<>();
  670. queue.add(this);
  671. while (!queue.isEmpty()) {
  672. JavaClass clazz = queue.remove();
  673. JavaClass souper = clazz.getSuperClass();
  674. JavaClass[] interfaces = clazz.getInterfaces();
  675. if (clazz.isInterface()) {
  676. interfaceList.add(clazz);
  677. } else {
  678. if (souper != null) {
  679. queue.add(souper);
  680. }
  681. }
  682. Collections.addAll(queue, interfaces);
  683. }
  684. return interfaceList;
  685. // return interfaceList.toArray(new JavaClass[interfaceList.size()]);
  686. }
  687. /**
  688. * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
  689. * Ljava/util/Vector; the signature attribute will tell us e.g. "<E:>Ljava/lang/Object". We can learn the type variable names,
  690. * their bounds, and the true superclass and superinterface types (including any parameterizations) Coded for performance -
  691. * searches for the attribute only when requested - only searches for it once.
  692. */
  693. public final String getGenericSignature() {
  694. loadGenericSignatureInfoIfNecessary();
  695. return signatureAttributeString;
  696. }
  697. public boolean isGeneric() {
  698. loadGenericSignatureInfoIfNecessary();
  699. return isGeneric;
  700. }
  701. private void loadGenericSignatureInfoIfNecessary() {
  702. if (!searchedForSignatureAttribute) {
  703. signatureAttribute = AttributeUtils.getSignatureAttribute(attributes);
  704. signatureAttributeString = signatureAttribute == null ? null : signatureAttribute.getSignature();
  705. isGeneric = signatureAttribute != null && signatureAttributeString.charAt(0) == '<';
  706. searchedForSignatureAttribute = true;
  707. }
  708. }
  709. public final Signature getSignatureAttribute() {
  710. loadGenericSignatureInfoIfNecessary();
  711. return signatureAttribute;
  712. }
  713. }