source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 9.9 KB
Line 
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 */
17package org.apache.tools.ant.util.depend;
18import java.io.File;
19import java.io.IOException;
20import java.util.Enumeration;
21import java.util.Vector;
22import java.util.zip.ZipFile;
23import org.apache.tools.ant.types.Path;
24
25/**
26 * An abstract implementation of the analyzer interface providing support
27 * for the bulk of interface methods.
28 *
29 */
30public abstract class AbstractAnalyzer implements DependencyAnalyzer {
31 /** Maximum number of loops for looking for indirect dependencies. */
32 public static final int MAX_LOOPS = 1000;
33
34 /** The source path for the source files */
35 private Path sourcePath = new Path(null);
36
37 /** The classpath containg dirs and jars of class files */
38 private Path classPath = new Path(null);
39
40 /** The list of root classes */
41 private Vector rootClasses = new Vector();
42
43 /** true if dependencies have been determined */
44 private boolean determined = false;
45
46 /** the list of File objects that the root classes depend upon */
47 private Vector fileDependencies;
48 /** the list of java classes the root classes depend upon */
49 private Vector classDependencies;
50
51 /** true if indirect dependencies should be gathered */
52 private boolean closure = true;
53
54 /** Setup the analyzer */
55 protected AbstractAnalyzer() {
56 reset();
57 }
58
59 /**
60 * Set the closure flag. If this flag is true the analyzer will traverse
61 * all class relationships until it has collected the entire set of
62 * direct and indirect dependencies
63 *
64 * @param closure true if dependencies should be traversed to determine
65 * indirect dependencies.
66 */
67 public void setClosure(boolean closure) {
68 this.closure = closure;
69 }
70
71 /**
72 * Get the list of files in the file system upon which the root classes
73 * depend. The files will be either the classfiles or jar files upon
74 * which the root classes depend.
75 *
76 * @return an enumeration of File instances.
77 */
78 public Enumeration getFileDependencies() {
79 if (!supportsFileDependencies()) {
80 throw new RuntimeException("File dependencies are not supported "
81 + "by this analyzer");
82 }
83 if (!determined) {
84 determineDependencies(fileDependencies, classDependencies);
85 }
86 return fileDependencies.elements();
87 }
88
89 /**
90 * Get the list of classes upon which root classes depend. This is a
91 * list of Java classnames in dot notation.
92 *
93 * @return an enumeration of Strings, each being the name of a Java
94 * class in dot notation.
95 */
96 public Enumeration getClassDependencies() {
97 if (!determined) {
98 determineDependencies(fileDependencies, classDependencies);
99 }
100 return classDependencies.elements();
101 }
102
103 /**
104 * Get the file that contains the class definition
105 *
106 * @param classname the name of the required class
107 * @return the file instance, zip or class, containing the
108 * class or null if the class could not be found.
109 * @exception IOException if the files in the classpath cannot be read.
110 */
111 public File getClassContainer(String classname) throws IOException {
112 String classLocation = classname.replace('.', '/') + ".class";
113 // we look through the classpath elements. If the element is a dir
114 // we look for the file. IF it is a zip, we look for the zip entry
115 return getResourceContainer(classLocation, classPath.list());
116 }
117
118 /**
119 * Get the file that contains the class source.
120 *
121 * @param classname the name of the required class
122 * @return the file instance, zip or java, containing the
123 * source or null if the source for the class could not be found.
124 * @exception IOException if the files in the sourcepath cannot be read.
125 */
126 public File getSourceContainer(String classname) throws IOException {
127 String sourceLocation = classname.replace('.', '/') + ".java";
128
129 // we look through the source path elements. If the element is a dir
130 // we look for the file. If it is a zip, we look for the zip entry.
131 // This isn't normal for source paths but we get it for free
132 return getResourceContainer(sourceLocation, sourcePath.list());
133 }
134
135 /**
136 * Add a source path to the source path used by this analyzer. The
137 * elements in the given path contain the source files for the classes
138 * being analyzed. Not all analyzers will use this information.
139 *
140 * @param sourcePath The Path instance specifying the source path
141 * elements.
142 */
143 public void addSourcePath(Path sourcePath) {
144 if (sourcePath == null) {
145 return;
146 }
147 this.sourcePath.append(sourcePath);
148 this.sourcePath.setProject(sourcePath.getProject());
149 }
150
151 /**
152 * Add a classpath to the classpath being used by the analyzer. The
153 * classpath contains the binary classfiles for the classes being
154 * analyzed The elements may either be the directories or jar files.Not
155 * all analyzers will use this information.
156 *
157 * @param classPath the Path instance specifying the classpath elements
158 */
159 public void addClassPath(Path classPath) {
160 if (classPath == null) {
161 return;
162 }
163
164 this.classPath.append(classPath);
165 this.classPath.setProject(classPath.getProject());
166 }
167
168 /**
169 * Add a root class. The root classes are used to drive the
170 * determination of dependency information. The analyzer will start at
171 * the root classes and add dependencies from there.
172 *
173 * @param className the name of the class in Java dot notation.
174 */
175 public void addRootClass(String className) {
176 if (className == null) {
177 return;
178 }
179 if (!rootClasses.contains(className)) {
180 rootClasses.addElement(className);
181 }
182 }
183
184 /**
185 * Configure an aspect of the analyzer. The set of aspects that are
186 * supported is specific to each analyzer instance.
187 *
188 * @param name the name of the aspect being configured
189 * @param info the configuration info.
190 */
191 public void config(String name, Object info) {
192 // do nothing by default
193 }
194
195 /**
196 * Reset the dependency list. This will reset the determined
197 * dependencies and the also list of root classes.
198 */
199 public void reset() {
200 rootClasses.removeAllElements();
201 determined = false;
202 fileDependencies = new Vector();
203 classDependencies = new Vector();
204 }
205
206 /**
207 * Get an enumeration of the root classes
208 *
209 * @return an enumeration of Strings, each of which is a class name
210 * for a root class.
211 */
212 protected Enumeration getRootClasses() {
213 return rootClasses.elements();
214 }
215
216 /**
217 * Indicate if the analyzer is required to follow
218 * indirect class relationships.
219 *
220 * @return true if indirect relationships should be followed.
221 */
222 protected boolean isClosureRequired() {
223 return closure;
224 }
225
226 /**
227 * Determine the dependencies of the current set of root classes
228 *
229 * @param files a vector into which Files upon which the root classes
230 * depend should be placed.
231 * @param classes a vector of Strings into which the names of classes
232 * upon which the root classes depend should be placed.
233 */
234 protected abstract void determineDependencies(Vector files, Vector classes);
235
236 /**
237 * Indicate if the particular subclass supports file dependency
238 * information.
239 *
240 * @return true if file dependencies are supported.
241 */
242 protected abstract boolean supportsFileDependencies();
243
244 /**
245 * Get the file that contains the resource
246 *
247 * @param resourceLocation the name of the required resource.
248 * @param paths the paths which will be searched for the resource.
249 * @return the file instance, zip or class, containing the
250 * class or null if the class could not be found.
251 * @exception IOException if the files in the given paths cannot be read.
252 */
253 private File getResourceContainer(String resourceLocation, String[] paths)
254 throws IOException {
255 for (int i = 0; i < paths.length; ++i) {
256 File element = new File(paths[i]);
257 if (!element.exists()) {
258 continue;
259 }
260 if (element.isDirectory()) {
261 File resource = new File(element, resourceLocation);
262 if (resource.exists()) {
263 return resource;
264 }
265 } else {
266 // must be a zip of some sort
267 ZipFile zipFile = null;
268 try {
269 zipFile = new ZipFile(element);
270 if (zipFile.getEntry(resourceLocation) != null) {
271 return element;
272 }
273 } finally {
274 if (zipFile != null) {
275 zipFile.close();
276 }
277 }
278 }
279 }
280 return null;
281 }
282}
283
Note: See TracBrowser for help on using the repository browser.