001: /*
002: * Copyright (c) 2001-2007, Jean Tessier
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * * Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * * Neither the name of Jean Tessier nor the names of his contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032:
033: package com.jeantessier.dependencyfinder.ant;
034:
035: import java.io.*;
036: import java.util.*;
037:
038: import org.apache.tools.ant.*;
039: import org.apache.tools.ant.types.*;
040: import org.apache.log4j.*;
041:
042: import com.jeantessier.classreader.*;
043: import com.jeantessier.dependency.*;
044:
045: public class DependencyExtractor extends Task {
046: private String filterIncludes = "//";
047: private String filterExcludes = "";
048: private boolean packageFilter = false;
049: private String packageFilterIncludes = "";
050: private String packageFilterExcludes = "";
051: private boolean classFilter = false;
052: private String classFilterIncludes = "";
053: private String classFilterExcludes = "";
054: private boolean featureFilter = false;
055: private String featureFilterIncludes = "";
056: private String featureFilterExcludes = "";
057:
058: private Path filterIncludesList;
059: private Path filterExcludesList;
060:
061: private boolean xml = false;
062: private boolean minimize = false;
063: private boolean maximize = false;
064: private String encoding = com.jeantessier.dependency.XMLPrinter.DEFAULT_ENCODING;
065: private String dtdPrefix = com.jeantessier.dependency.XMLPrinter.DEFAULT_DTD_PREFIX;
066: private String indentText;
067: private File destfile;
068: private Path path;
069:
070: public String getFilterincludes() {
071: return filterIncludes;
072: }
073:
074: public void setFilterincludes(String filterIncludes) {
075: this .filterIncludes = filterIncludes;
076: }
077:
078: public String getFilterexcludes() {
079: return filterExcludes;
080: }
081:
082: public void setFilterexcludes(String filterExcludes) {
083: this .filterExcludes = filterExcludes;
084: }
085:
086: public boolean getPackagefilter() {
087: return packageFilter;
088: }
089:
090: public void setPackagefilter(boolean packageFilter) {
091: this .packageFilter = packageFilter;
092: }
093:
094: public String getPackagefilterincludes() {
095: return packageFilterIncludes;
096: }
097:
098: public void setPackagefilterincludes(String packageFilterIncludes) {
099: this .packageFilterIncludes = packageFilterIncludes;
100: }
101:
102: public String getPackagefilterexcludes() {
103: return packageFilterExcludes;
104: }
105:
106: public void setPackagefilterexcludes(String packageFilterExcludes) {
107: this .packageFilterExcludes = packageFilterExcludes;
108: }
109:
110: public boolean getClassfilter() {
111: return classFilter;
112: }
113:
114: public void setClassfilter(boolean classFilter) {
115: this .classFilter = classFilter;
116: }
117:
118: public String getClassfilterincludes() {
119: return classFilterIncludes;
120: }
121:
122: public void setClassfilterincludes(String classFilterIncludes) {
123: this .classFilterIncludes = classFilterIncludes;
124: }
125:
126: public String getClassfilterexcludes() {
127: return classFilterExcludes;
128: }
129:
130: public void setClassfilterexcludes(String classFilterExcludes) {
131: this .classFilterExcludes = classFilterExcludes;
132: }
133:
134: public boolean getFeaturefilter() {
135: return featureFilter;
136: }
137:
138: public void setFeaturefilter(boolean featureFilter) {
139: this .featureFilter = featureFilter;
140: }
141:
142: public String getFeaturefilterincludes() {
143: return featureFilterIncludes;
144: }
145:
146: public void setFeaturefilterincludes(String featureFilterIncludes) {
147: this .featureFilterIncludes = featureFilterIncludes;
148: }
149:
150: public String getFeaturefilterexcludes() {
151: return featureFilterExcludes;
152: }
153:
154: public void setFeaturefilterexcludes(String featureFilterExcludes) {
155: this .featureFilterExcludes = featureFilterExcludes;
156: }
157:
158: public Path createFilterincludeslist() {
159: if (filterIncludesList == null) {
160: filterIncludesList = new Path(getProject());
161: }
162:
163: return filterIncludesList;
164: }
165:
166: public Path getFilterincludeslist() {
167: return filterIncludesList;
168: }
169:
170: public Path createFilterexcludeslist() {
171: if (filterExcludesList == null) {
172: filterExcludesList = new Path(getProject());
173: }
174:
175: return filterExcludesList;
176: }
177:
178: public Path getFilterexcludeslist() {
179: return filterExcludesList;
180: }
181:
182: public boolean getXml() {
183: return xml;
184: }
185:
186: public void setXml(boolean xml) {
187: this .xml = xml;
188: }
189:
190: public boolean getMinimize() {
191: return minimize;
192: }
193:
194: public void setMinimize(boolean minimize) {
195: this .minimize = minimize;
196: }
197:
198: public boolean getMaximize() {
199: return maximize;
200: }
201:
202: public void setMaximize(boolean maximize) {
203: this .maximize = maximize;
204: }
205:
206: public String getEncoding() {
207: return encoding;
208: }
209:
210: public void setEncoding(String encoding) {
211: this .encoding = encoding;
212: }
213:
214: public String getDtdprefix() {
215: return dtdPrefix;
216: }
217:
218: public void setDtdprefix(String dtdPrefix) {
219: this .dtdPrefix = dtdPrefix;
220: }
221:
222: public String getIndenttext() {
223: return indentText;
224: }
225:
226: public void setIntenttext(String indentText) {
227: this .indentText = indentText;
228: }
229:
230: public File getDestfile() {
231: return destfile;
232: }
233:
234: public void setDestfile(File destfile) {
235: this .destfile = destfile;
236: }
237:
238: public Path createPath() {
239: if (path == null) {
240: path = new Path(getProject());
241: }
242:
243: return path;
244: }
245:
246: public Path getPath() {
247: return path;
248: }
249:
250: public void execute() throws BuildException {
251: // first off, make sure that we've got what we need
252:
253: if (getPath() == null) {
254: throw new BuildException("path must be set!");
255: }
256:
257: if (getDestfile() == null) {
258: throw new BuildException("destfile must be set!");
259: }
260:
261: if (hasFilterRegularExpressionSwitches()
262: && hasFilterListSwitches()) {
263: throw new BuildException(
264: "Cannot have filter attributes for regular expressions and lists at the same time!");
265: }
266:
267: log("Reading classes from path " + getPath());
268:
269: VerboseListener verboseListener = new VerboseListener(this );
270:
271: NodeFactory factory = new NodeFactory();
272: CodeDependencyCollector collector = new CodeDependencyCollector(
273: factory, getFilterCriteria());
274:
275: ClassfileLoader loader = new TransientClassfileLoader();
276: loader
277: .addLoadListener(new LoadListenerVisitorAdapter(
278: collector));
279: loader.addLoadListener(verboseListener);
280: loader.load(Arrays.asList(getPath().list()));
281:
282: if (getMinimize()) {
283: LinkMinimizer minimizer = new LinkMinimizer();
284: minimizer.traverseNodes(factory.getPackages().values());
285: } else if (getMaximize()) {
286: LinkMaximizer maximizer = new LinkMaximizer();
287: maximizer.traverseNodes(factory.getPackages().values());
288: }
289:
290: log("Saving dependency graph to "
291: + getDestfile().getAbsolutePath());
292:
293: try {
294: PrintWriter out = new PrintWriter(new FileWriter(
295: getDestfile()));
296:
297: com.jeantessier.dependency.Printer printer;
298: if (getXml()) {
299: printer = new com.jeantessier.dependency.XMLPrinter(
300: out, getEncoding(), getDtdprefix());
301: } else {
302: printer = new com.jeantessier.dependency.TextPrinter(
303: out);
304: }
305:
306: if (getIndenttext() != null) {
307: printer.setIndentText(getIndenttext());
308: }
309:
310: printer.traverseNodes(factory.getPackages().values());
311:
312: out.close();
313: } catch (IOException ex) {
314: throw new BuildException(ex);
315: }
316: }
317:
318: protected SelectionCriteria getFilterCriteria()
319: throws BuildException {
320: SelectionCriteria result = new ComprehensiveSelectionCriteria();
321:
322: if (hasFilterRegularExpressionSwitches()) {
323: result = createRegularExpressionFilterCriteria();
324: } else if (hasFilterListSwitches()) {
325: result = createCollectionSelectionCriteria(
326: getFilterincludeslist(), getFilterexcludeslist());
327: }
328:
329: return result;
330: }
331:
332: protected RegularExpressionSelectionCriteria createRegularExpressionFilterCriteria()
333: throws BuildException {
334: RegularExpressionSelectionCriteria result = new RegularExpressionSelectionCriteria();
335:
336: if (getPackagefilter() || getClassfilter()
337: || getFeaturefilter()) {
338: result.setMatchingPackages(getPackagefilter());
339: result.setMatchingClasses(getClassfilter());
340: result.setMatchingFeatures(getFeaturefilter());
341: }
342:
343: result.setGlobalIncludes(getFilterincludes());
344: result.setGlobalExcludes(getFilterexcludes());
345: result.setPackageIncludes(getPackagefilterincludes());
346: result.setPackageExcludes(getPackagefilterexcludes());
347: result.setClassIncludes(getClassfilterincludes());
348: result.setClassExcludes(getClassfilterexcludes());
349: result.setFeatureIncludes(getFeaturefilterincludes());
350: result.setFeatureExcludes(getFeaturefilterexcludes());
351:
352: return result;
353: }
354:
355: private boolean hasFilterRegularExpressionSwitches() {
356: return !getFilterincludes().equals("//")
357: || !getFilterexcludes().equals("")
358: || getPackagefilter()
359: || !getPackagefilterincludes().equals("")
360: || !getPackagefilterexcludes().equals("")
361: || getClassfilter()
362: || !getClassfilterincludes().equals("")
363: || !getClassfilterexcludes().equals("")
364: || getFeaturefilter()
365: || !getFeaturefilterincludes().equals("")
366: || !getFeaturefilterexcludes().equals("");
367: }
368:
369: private boolean hasFilterListSwitches() {
370: return getFilterincludeslist() != null
371: || getFilterexcludeslist() != null;
372: }
373:
374: private CollectionSelectionCriteria createCollectionSelectionCriteria(
375: Path includes, Path excludes) {
376: return new CollectionSelectionCriteria(
377: loadCollection(includes), loadCollection(excludes));
378: }
379:
380: private Collection<String> loadCollection(Path path) {
381: Collection<String> result = null;
382:
383: if (path != null) {
384: result = new HashSet<String>();
385:
386: String[] filenames = path.list();
387: for (int i = 0; i < filenames.length; i++) {
388: BufferedReader reader = null;
389: String line;
390:
391: try {
392: reader = new BufferedReader(new FileReader(
393: filenames[i]));
394: while ((line = reader.readLine()) != null) {
395: result.add(line);
396: }
397: } catch (IOException ex) {
398: Logger.getLogger(getClass()).error(
399: "Couldn't read file " + filenames[i], ex);
400: } finally {
401: try {
402: if (reader != null) {
403: reader.close();
404: }
405: } catch (IOException ex) {
406: Logger.getLogger(getClass()).error(
407: "Couldn't close file " + filenames[i],
408: ex);
409: }
410: }
411: }
412: }
413:
414: return result;
415: }
416: }
|