1. /*
  2. * Copyright 2002,2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.util.depend.bcel;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.util.Enumeration;
  21. import java.util.Hashtable;
  22. import java.util.Vector;
  23. import org.apache.bcel.classfile.ClassParser;
  24. import org.apache.bcel.classfile.JavaClass;
  25. import org.apache.tools.ant.util.depend.AbstractAnalyzer;
  26. /**
  27. * A dependency analyzer which returns superclass and superinterface
  28. * dependencies.
  29. *
  30. */
  31. public class AncestorAnalyzer extends AbstractAnalyzer {
  32. /**
  33. * Default constructor
  34. *
  35. * Causes the BCEL classes to load to ensure BCEL dependencies can
  36. * be satisfied
  37. */
  38. public AncestorAnalyzer() {
  39. // force BCEL classes to load now
  40. try {
  41. new ClassParser("force");
  42. } catch (IOException e) {
  43. // ignore
  44. }
  45. }
  46. /**
  47. * Determine the dependencies of the configured root classes.
  48. *
  49. * @param files a vector to be populated with the files which contain
  50. * the dependency classes
  51. * @param classes a vector to be populated with the names of the
  52. * depencency classes.
  53. */
  54. protected void determineDependencies(Vector files, Vector classes) {
  55. // we get the root classes and build up a set of
  56. // classes upon which they depend
  57. Hashtable dependencies = new Hashtable();
  58. Hashtable containers = new Hashtable();
  59. Hashtable toAnalyze = new Hashtable();
  60. Hashtable nextAnalyze = new Hashtable();
  61. for (Enumeration e = getRootClasses(); e.hasMoreElements();) {
  62. String classname = (String) e.nextElement();
  63. toAnalyze.put(classname, classname);
  64. }
  65. int count = 0;
  66. int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
  67. while (toAnalyze.size() != 0 && count++ < maxCount) {
  68. nextAnalyze.clear();
  69. for (Enumeration e = toAnalyze.keys(); e.hasMoreElements();) {
  70. String classname = (String) e.nextElement();
  71. dependencies.put(classname, classname);
  72. try {
  73. File container = getClassContainer(classname);
  74. if (container == null) {
  75. continue;
  76. }
  77. containers.put(container, container);
  78. ClassParser parser = null;
  79. if (container.getName().endsWith(".class")) {
  80. parser = new ClassParser(container.getPath());
  81. } else {
  82. parser = new ClassParser(container.getPath(),
  83. classname.replace('.', '/') + ".class");
  84. }
  85. JavaClass javaClass = parser.parse();
  86. String[] interfaces = javaClass.getInterfaceNames();
  87. for (int i = 0; i < interfaces.length; ++i) {
  88. String interfaceName = interfaces[i];
  89. if (!dependencies.containsKey(interfaceName)) {
  90. nextAnalyze.put(interfaceName, interfaceName);
  91. }
  92. }
  93. if (javaClass.isClass()) {
  94. String superClass = javaClass.getSuperclassName();
  95. if (!dependencies.containsKey(superClass)) {
  96. nextAnalyze.put(superClass, superClass);
  97. }
  98. }
  99. } catch (IOException ioe) {
  100. // ignore
  101. }
  102. }
  103. Hashtable temp = toAnalyze;
  104. toAnalyze = nextAnalyze;
  105. nextAnalyze = temp;
  106. }
  107. files.removeAllElements();
  108. for (Enumeration e = containers.keys(); e.hasMoreElements();) {
  109. files.addElement((File) e.nextElement());
  110. }
  111. classes.removeAllElements();
  112. for (Enumeration e = dependencies.keys(); e.hasMoreElements();) {
  113. classes.addElement((String) e.nextElement());
  114. }
  115. }
  116. /**
  117. * Indicate if this analyzer can determine dependent files.
  118. *
  119. * @return true if the analyzer provides dependency file information.
  120. */
  121. protected boolean supportsFileDependencies() {
  122. return true;
  123. }
  124. }