1. package com.sun.org.apache.bcel.internal;
  2. /* ====================================================================
  3. * The Apache Software License, Version 1.1
  4. *
  5. * Copyright (c) 2001 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Apache" and "Apache Software Foundation" and
  28. * "Apache BCEL" must not be used to endorse or promote products
  29. * derived from this software without prior written permission. For
  30. * written permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * "Apache BCEL", nor may "Apache" appear in their name, without
  34. * prior written permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation. For more
  52. * information on the Apache Software Foundation, please see
  53. * <http://www.apache.org/>.
  54. */
  55. import com.sun.org.apache.bcel.internal.classfile.*;
  56. import com.sun.org.apache.bcel.internal.util.*;
  57. import java.util.HashMap;
  58. import java.io.*;
  59. /**
  60. * Repository maintains informations about class interdependencies, e.g.
  61. * whether a class is a sub-class of another. JavaClass objects are put
  62. * into a cache which can be purged with clearCache().
  63. *
  64. * All JavaClass objects used as arguments must have been obtained via
  65. * the repository or been added with addClass() manually. This is
  66. * because we have to check for object identity (==).
  67. *
  68. * @version $Id: Repository.java,v 1.1.1.1 2001/10/29 19:59:57 jvanzyl Exp $
  69. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A
  70. */
  71. public abstract class Repository {
  72. private static ClassPath class_path = new ClassPath();
  73. private static HashMap classes;
  74. private static JavaClass OBJECT; // should be final ...
  75. static { clearCache(); }
  76. /** @return class object for given fully qualified class name.
  77. */
  78. public static JavaClass lookupClass(String class_name) {
  79. if(class_name == null || class_name.equals(""))
  80. throw new RuntimeException("Invalid class name");
  81. class_name = class_name.replace('/', '.');
  82. JavaClass clazz = (JavaClass)classes.get(class_name);
  83. if(clazz == null) {
  84. try {
  85. InputStream is = class_path.getInputStream(class_name);
  86. clazz = new ClassParser(is, class_name).parse();
  87. class_name = clazz.getClassName();
  88. } catch(IOException e) { return null; }
  89. classes.put(class_name, clazz);
  90. }
  91. return clazz;
  92. }
  93. /** @return class file object for given Java class.
  94. */
  95. public static ClassPath.ClassFile lookupClassFile(String class_name) {
  96. try {
  97. return class_path.getClassFile(class_name);
  98. } catch(IOException e) { return null; }
  99. }
  100. /** Clear the repository.
  101. */
  102. public static void clearCache() {
  103. classes = new HashMap();
  104. OBJECT = lookupClass("java.lang.Object");
  105. if(OBJECT == null)
  106. System.err.println("Warning: java.lang.Object not found on CLASSPATH!");
  107. else
  108. classes.put("java.lang.Object", OBJECT);
  109. }
  110. /**
  111. * Add clazz to repository if there isn't an equally named class already in there.
  112. *
  113. * @return old entry in repository
  114. */
  115. public static JavaClass addClass(JavaClass clazz) {
  116. String name = clazz.getClassName();
  117. JavaClass cl = (JavaClass)classes.get(name);
  118. if(cl == null)
  119. classes.put(name, cl = clazz);
  120. return cl;
  121. }
  122. /**
  123. * Remove class with given (fully qualifid) name from repository.
  124. */
  125. public static void removeClass(String clazz) {
  126. classes.remove(clazz);
  127. }
  128. /**
  129. * Remove given class from repository.
  130. */
  131. public static void removeClass(JavaClass clazz) {
  132. removeClass(clazz.getClassName());
  133. }
  134. private static final JavaClass getSuperClass(JavaClass clazz) {
  135. if(clazz == OBJECT)
  136. return null;
  137. return lookupClass(clazz.getSuperclassName());
  138. }
  139. /**
  140. * @return list of super classes of clazz in ascending order, i.e.,
  141. * Object is always the last element
  142. */
  143. public static JavaClass[] getSuperClasses(JavaClass clazz) {
  144. ClassVector vec = new ClassVector();
  145. for(clazz = getSuperClass(clazz); clazz != null; clazz = getSuperClass(clazz))
  146. vec.addElement(clazz);
  147. return vec.toArray();
  148. }
  149. /**
  150. * @return list of super classes of clazz in ascending order, i.e.,
  151. * Object is always the last element. "null", if clazz cannot be found.
  152. */
  153. public static JavaClass[] getSuperClasses(String class_name) {
  154. JavaClass jc = lookupClass(class_name);
  155. return (jc == null? null : getSuperClasses(jc));
  156. }
  157. /**
  158. * @return all interfaces implemented by class and its super
  159. * classes and the interfaces that those interfaces extend, and so on
  160. */
  161. public static JavaClass[] getInterfaces(JavaClass clazz) {
  162. ClassVector vec = new ClassVector();
  163. ClassQueue queue = new ClassQueue();
  164. queue.enqueue(clazz);
  165. while(!queue.empty()) {
  166. clazz = queue.dequeue();
  167. String s = clazz.getSuperclassName();
  168. String[] interfaces = clazz.getInterfaceNames();
  169. if(clazz.isInterface())
  170. vec.addElement(clazz);
  171. else if(!s.equals("java.lang.Object"))
  172. queue.enqueue(lookupClass(s));
  173. for(int i=0; i < interfaces.length; i++)
  174. queue.enqueue(lookupClass(interfaces[i]));
  175. }
  176. return vec.toArray();
  177. }
  178. /**
  179. * @return all interfaces implemented by class and its super
  180. * classes and the interfaces that extend those interfaces, and so on
  181. */
  182. public static JavaClass[] getInterfaces(String class_name) {
  183. return getInterfaces(lookupClass(class_name));
  184. }
  185. /**
  186. * @return true, if clazz is an instance of super_class
  187. */
  188. public static boolean instanceOf(JavaClass clazz, JavaClass super_class) {
  189. if(clazz == super_class)
  190. return true;
  191. JavaClass[] super_classes = getSuperClasses(clazz);
  192. for(int i=0; i < super_classes.length; i++)
  193. if(super_classes[i] == super_class)
  194. return true;
  195. if(super_class.isInterface())
  196. return implementationOf(clazz, super_class);
  197. return false;
  198. }
  199. /**
  200. * @return true, if clazz is an instance of super_class
  201. */
  202. public static boolean instanceOf(String clazz, String super_class) {
  203. return instanceOf(lookupClass(clazz), lookupClass(super_class));
  204. }
  205. /**
  206. * @return true, if clazz is an instance of super_class
  207. */
  208. public static boolean instanceOf(JavaClass clazz, String super_class) {
  209. return instanceOf(clazz, lookupClass(super_class));
  210. }
  211. /**
  212. * @return true, if clazz is an instance of super_class
  213. */
  214. public static boolean instanceOf(String clazz, JavaClass super_class) {
  215. return instanceOf(lookupClass(clazz), super_class);
  216. }
  217. /**
  218. * @return true, if clazz is an implementation of interface inter
  219. */
  220. public static boolean implementationOf(JavaClass clazz, JavaClass inter) {
  221. if(clazz == inter)
  222. return true;
  223. JavaClass[] super_interfaces = getInterfaces(clazz);
  224. for(int i=0; i < super_interfaces.length; i++)
  225. if(super_interfaces[i] == inter)
  226. return true;
  227. return false;
  228. }
  229. /**
  230. * @return true, if clazz is an implementation of interface inter
  231. */
  232. public static boolean implementationOf(String clazz, String inter) {
  233. return implementationOf(lookupClass(clazz), lookupClass(inter));
  234. }
  235. /**
  236. * @return true, if clazz is an implementation of interface inter
  237. */
  238. public static boolean implementationOf(JavaClass clazz, String inter) {
  239. return implementationOf(clazz, lookupClass(inter));
  240. }
  241. /**
  242. * @return true, if clazz is an implementation of interface inter
  243. */
  244. public static boolean implementationOf(String clazz, JavaClass inter) {
  245. return implementationOf(lookupClass(clazz), inter);
  246. }
  247. }