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

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. }