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.DescendingVisitor;
  25. import org.apache.bcel.classfile.JavaClass;
  26. import org.apache.tools.ant.util.depend.AbstractAnalyzer;
  27. /**
  28. * An analyzer capable fo traversing all class - class relationships.
  29. *
  30. */
  31. public class FullAnalyzer 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 FullAnalyzer() {
  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. for (Enumeration e = getRootClasses(); e.hasMoreElements();) {
  61. String classname = (String) e.nextElement();
  62. toAnalyze.put(classname, classname);
  63. }
  64. int count = 0;
  65. int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
  66. while (toAnalyze.size() != 0 && count++ < maxCount) {
  67. DependencyVisitor dependencyVisitor = new DependencyVisitor();
  68. for (Enumeration e = toAnalyze.keys(); e.hasMoreElements();) {
  69. String classname = (String) e.nextElement();
  70. dependencies.put(classname, classname);
  71. try {
  72. File container = getClassContainer(classname);
  73. if (container == null) {
  74. continue;
  75. }
  76. containers.put(container, container);
  77. ClassParser parser = null;
  78. if (container.getName().endsWith(".class")) {
  79. parser = new ClassParser(container.getPath());
  80. } else {
  81. parser = new ClassParser(container.getPath(),
  82. classname.replace('.', '/') + ".class");
  83. }
  84. JavaClass javaClass = parser.parse();
  85. DescendingVisitor traverser
  86. = new DescendingVisitor(javaClass, dependencyVisitor);
  87. traverser.visit();
  88. } catch (IOException ioe) {
  89. // ignore
  90. }
  91. }
  92. toAnalyze.clear();
  93. // now recover all the dependencies collected and add to the list.
  94. Enumeration depsEnum = dependencyVisitor.getDependencies();
  95. while (depsEnum.hasMoreElements()) {
  96. String className = (String) depsEnum.nextElement();
  97. if (!dependencies.containsKey(className)) {
  98. toAnalyze.put(className, className);
  99. }
  100. }
  101. }
  102. files.removeAllElements();
  103. for (Enumeration e = containers.keys(); e.hasMoreElements();) {
  104. files.addElement((File) e.nextElement());
  105. }
  106. classes.removeAllElements();
  107. for (Enumeration e = dependencies.keys(); e.hasMoreElements();) {
  108. classes.addElement((String) e.nextElement());
  109. }
  110. }
  111. /**
  112. * Indicate if this analyzer can determine dependent files.
  113. *
  114. * @return true if the analyzer provides dependency file information.
  115. */
  116. protected boolean supportsFileDependencies() {
  117. return true;
  118. }
  119. }