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

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