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 23KB

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