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.cli;
034:
035: import java.io.*;
036: import java.util.*;
037:
038: import com.jeantessier.classreader.*;
039: import com.jeantessier.commandline.*;
040: import com.jeantessier.metrics.*;
041: import org.apache.log4j.*;
042:
043: public class OOMetrics extends Command {
044: public static final String DEFAULT_PROJECT_NAME = "Project";
045: public static final String DEFAULT_SORT = "name";
046:
047: public OOMetrics() throws CommandLineException {
048: super ("OOMetrics");
049: }
050:
051: protected void showSpecificUsage(PrintStream out) {
052: out.println();
053: out
054: .println("If no files are specified, it processes the current directory.");
055: out.println();
056: out
057: .println("If file is a directory, it is recusively scanned for files");
058: out.println("ending in \".class\".");
059: out.println();
060: out.println("Defaults is text output to the console.");
061: out.println();
062: }
063:
064: protected void populateCommandLineSwitches() {
065: super .populateCommandLineSwitches();
066: populateCommandLineSwitchesForXMLOutput(
067: com.jeantessier.metrics.XMLPrinter.DEFAULT_ENCODING,
068: com.jeantessier.metrics.XMLPrinter.DEFAULT_DTD_PREFIX);
069:
070: getCommandLine().addSingleValueSwitch("project-name",
071: DEFAULT_PROJECT_NAME);
072: getCommandLine().addSingleValueSwitch("default-configuration",
073: true);
074: getCommandLine().addSingleValueSwitch("configuration");
075: getCommandLine().addToggleSwitch("csv");
076: getCommandLine().addToggleSwitch("txt");
077: getCommandLine().addToggleSwitch("xml");
078: getCommandLine().addToggleSwitch("validate");
079: getCommandLine().addToggleSwitch("project");
080: getCommandLine().addToggleSwitch("groups");
081: getCommandLine().addToggleSwitch("classes");
082: getCommandLine().addToggleSwitch("methods");
083: getCommandLine().addMultipleValuesSwitch("scope-includes-list");
084: getCommandLine().addMultipleValuesSwitch("scope-excludes-list");
085: getCommandLine()
086: .addMultipleValuesSwitch("filter-includes-list");
087: getCommandLine()
088: .addMultipleValuesSwitch("filter-excludes-list");
089: getCommandLine().addToggleSwitch("show-all-metrics");
090: getCommandLine().addToggleSwitch("show-empty-metrics");
091: getCommandLine().addToggleSwitch("show-hidden-measurements");
092: getCommandLine().addSingleValueSwitch("sort", DEFAULT_SORT);
093: getCommandLine().addToggleSwitch("expand");
094: getCommandLine().addToggleSwitch("reverse");
095: }
096:
097: protected Collection<CommandLineException> parseCommandLine(
098: String[] args) {
099: Collection<CommandLineException> exceptions = super
100: .parseCommandLine(args);
101:
102: if (!getCommandLine().isPresent("project")
103: && !getCommandLine().isPresent("groups")
104: && !getCommandLine().isPresent("classes")
105: && !getCommandLine().isPresent("methods")) {
106: getCommandLine().getSwitch("project").setValue(true);
107: getCommandLine().getSwitch("groups").setValue(true);
108: getCommandLine().getSwitch("classes").setValue(true);
109: getCommandLine().getSwitch("methods").setValue(true);
110: }
111:
112: int modeSwitch = 0;
113:
114: if (getCommandLine().getToggleSwitch("csv")) {
115: modeSwitch++;
116: }
117: if (getCommandLine().getToggleSwitch("txt")) {
118: modeSwitch++;
119: }
120: if (getCommandLine().getToggleSwitch("xml")) {
121: modeSwitch++;
122: }
123: if (modeSwitch != 1) {
124: exceptions
125: .add(new CommandLineException(
126: "Must have one and only one of -csv, -txt, or -xml"));
127: }
128:
129: return exceptions;
130: }
131:
132: protected void doProcessing() throws Exception {
133: Logger.getLogger(OOMetrics.class).debug("Reading sources ...");
134: getVerboseListener().print("Reading sources ...");
135:
136: List<String> parameters = getCommandLine().getParameters();
137: if (parameters.size() == 0) {
138: parameters.add(".");
139: }
140:
141: ClassfileLoader loader = new AggregatingClassfileLoader();
142: loader.addLoadListener(getVerboseListener());
143: loader.load(parameters);
144:
145: Logger.getLogger(OOMetrics.class).debug(
146: "Reading configuration ...");
147: getVerboseListener().print("Reading configuration ...");
148:
149: String projectName = getCommandLine().getSingleSwitch(
150: "project-name");
151:
152: MetricsFactory factory;
153: if (getCommandLine().isPresent("configuration")) {
154: factory = new MetricsFactory(projectName,
155: new MetricsConfigurationLoader(getCommandLine()
156: .getToggleSwitch("validate"))
157: .load(getCommandLine().getSingleSwitch(
158: "configuration")));
159: } else {
160: factory = new MetricsFactory(projectName,
161: new MetricsConfigurationLoader(getCommandLine()
162: .getToggleSwitch("validate"))
163: .load(getCommandLine().getSingleSwitch(
164: "default-configuration")));
165: }
166:
167: Logger.getLogger(OOMetrics.class)
168: .debug("Computing metrics ...");
169: getVerboseListener().print("Computing metrics ...");
170:
171: com.jeantessier.metrics.MetricsGatherer gatherer = new com.jeantessier.metrics.MetricsGatherer(
172: projectName, factory);
173: if (getCommandLine().isPresent("scope-includes-list")
174: || getCommandLine().isPresent("scope-excludes-list")) {
175: gatherer.setScopeIncludes(createCollection(getCommandLine()
176: .getMultipleSwitch("scope-includes-list"),
177: getCommandLine().getMultipleSwitch(
178: "scope-excludes-list")));
179: }
180: if (getCommandLine().isPresent("filter-includes-list")
181: || getCommandLine().isPresent("filter-excludes-list")) {
182: gatherer
183: .setFilterIncludes(createCollection(
184: getCommandLine().getMultipleSwitch(
185: "filter-includes-list"),
186: getCommandLine().getMultipleSwitch(
187: "filter-excludes-list")));
188: }
189: gatherer.addMetricsListener(getVerboseListener());
190: gatherer.visitClassfiles(loader.getAllClassfiles());
191:
192: if (getCommandLine().isPresent("show-all-metrics")) {
193: Iterator i;
194:
195: i = gatherer.getMetricsFactory().getAllClassMetrics()
196: .iterator();
197: while (i.hasNext()) {
198: gatherer.getMetricsFactory().includeClassMetrics(
199: (Metrics) i.next());
200: }
201:
202: i = gatherer.getMetricsFactory().getAllMethodMetrics()
203: .iterator();
204: while (i.hasNext()) {
205: gatherer.getMetricsFactory().includeMethodMetrics(
206: (Metrics) i.next());
207: }
208: }
209:
210: Logger.getLogger(OOMetrics.class).debug("Printing results ...");
211: getVerboseListener().print("Printing results ...");
212:
213: if (getCommandLine().isPresent("csv")) {
214: printCSVFiles(gatherer.getMetricsFactory());
215: } else if (getCommandLine().isPresent("txt")) {
216: printTextFile(gatherer.getMetricsFactory());
217: } else if (getCommandLine().isPresent("xml")) {
218: printXMLFile(gatherer.getMetricsFactory());
219: }
220:
221: Logger.getLogger(OOMetrics.class).debug("Done.");
222: }
223:
224: private static Collection<String> createCollection(
225: Collection<String> includes, Collection<String> excludes)
226: throws IOException {
227: Collection<String> result = new HashSet<String>();
228:
229: for (String include : includes) {
230: BufferedReader reader = new BufferedReader(new FileReader(
231: include));
232: String line;
233: while ((line = reader.readLine()) != null) {
234: result.add(line);
235: }
236: reader.close();
237: }
238:
239: for (String exclude : excludes) {
240: BufferedReader reader = new BufferedReader(new FileReader(
241: exclude));
242: String line;
243: while ((line = reader.readLine()) != null) {
244: result.remove(line);
245: }
246: reader.close();
247: }
248:
249: return result;
250: }
251:
252: private void printCSVFiles(MetricsFactory factory)
253: throws IOException {
254: MetricsComparator comparator = new MetricsComparator(
255: getCommandLine().getSingleSwitch("sort"));
256: if (getCommandLine().getToggleSwitch("reverse")) {
257: comparator.reverse();
258: }
259:
260: List<Metrics> metrics;
261: com.jeantessier.metrics.Printer printer;
262:
263: if (getCommandLine().getToggleSwitch("project")) {
264: if (getCommandLine().isPresent("out")) {
265: out = new PrintWriter(new FileWriter(getCommandLine()
266: .getSingleSwitch("out")
267: + "_project.csv"));
268: } else {
269: out.println("Project:");
270: }
271:
272: metrics = new ArrayList<Metrics>(factory
273: .getProjectMetrics());
274: Collections.sort(metrics, comparator);
275: printer = new com.jeantessier.metrics.CSVPrinter(out,
276: factory.getConfiguration().getProjectMeasurements());
277: printer.setShowEmptyMetrics(getCommandLine().isPresent(
278: "show-empty-metrics"));
279: printer.setShowHiddenMeasurements(getCommandLine()
280: .isPresent("show-hidden-measurements"));
281: if (getCommandLine().isPresent("indent-text")) {
282: printer.setIndentText(getCommandLine().getSingleSwitch(
283: "indent-text"));
284: }
285:
286: printer.visitMetrics(metrics);
287:
288: if (getCommandLine().isPresent("out")) {
289: out.close();
290: } else {
291: out.println();
292: }
293: }
294:
295: if (getCommandLine().getToggleSwitch("groups")) {
296: if (getCommandLine().isPresent("out")) {
297: out = new PrintWriter(new FileWriter(getCommandLine()
298: .getSingleSwitch("out")
299: + "_groups.csv"));
300: } else {
301: out.println("Packages:");
302: }
303:
304: metrics = new ArrayList<Metrics>(factory.getGroupMetrics());
305: Collections.sort(metrics, comparator);
306: printer = new com.jeantessier.metrics.CSVPrinter(out,
307: factory.getConfiguration().getGroupMeasurements());
308: printer.setShowEmptyMetrics(getCommandLine().isPresent(
309: "show-empty-metrics"));
310: printer.setShowHiddenMeasurements(getCommandLine()
311: .isPresent("show-hidden-measurements"));
312: if (getCommandLine().isPresent("indent-text")) {
313: printer.setIndentText(getCommandLine().getSingleSwitch(
314: "indent-text"));
315: }
316:
317: printer.visitMetrics(metrics);
318:
319: if (getCommandLine().isPresent("out")) {
320: out.close();
321: } else {
322: out.println();
323: }
324: }
325:
326: if (getCommandLine().getToggleSwitch("classes")) {
327: if (getCommandLine().isPresent("out")) {
328: out = new PrintWriter(new FileWriter(getCommandLine()
329: .getSingleSwitch("out")
330: + "_classes.csv"));
331: } else {
332: out.println("Classes:");
333: }
334:
335: metrics = new ArrayList<Metrics>(factory.getClassMetrics());
336: Collections.sort(metrics, comparator);
337: printer = new com.jeantessier.metrics.CSVPrinter(out,
338: factory.getConfiguration().getClassMeasurements());
339: printer.setShowEmptyMetrics(getCommandLine().isPresent(
340: "show-empty-metrics"));
341: printer.setShowHiddenMeasurements(getCommandLine()
342: .isPresent("show-hidden-measurements"));
343: if (getCommandLine().isPresent("indent-text")) {
344: printer.setIndentText(getCommandLine().getSingleSwitch(
345: "indent-text"));
346: }
347:
348: printer.visitMetrics(metrics);
349:
350: if (getCommandLine().isPresent("out")) {
351: out.close();
352: } else {
353: out.println();
354: }
355: }
356:
357: if (getCommandLine().getToggleSwitch("methods")) {
358: if (getCommandLine().isPresent("out")) {
359: out = new PrintWriter(new FileWriter(getCommandLine()
360: .getSingleSwitch("out")
361: + "_methods.csv"));
362: } else {
363: out.println("Methods:");
364: }
365:
366: metrics = new ArrayList<Metrics>(factory.getMethodMetrics());
367: Collections.sort(metrics, comparator);
368: printer = new com.jeantessier.metrics.CSVPrinter(out,
369: factory.getConfiguration().getMethodMeasurements());
370: printer.setShowEmptyMetrics(getCommandLine().isPresent(
371: "show-empty-metrics"));
372: printer.setShowHiddenMeasurements(getCommandLine()
373: .isPresent("show-hidden-measurements"));
374: if (getCommandLine().isPresent("indent-text")) {
375: printer.setIndentText(getCommandLine().getSingleSwitch(
376: "indent-text"));
377: }
378:
379: printer.visitMetrics(metrics);
380:
381: if (getCommandLine().isPresent("out")) {
382: out.close();
383: }
384: }
385: }
386:
387: private void printTextFile(MetricsFactory factory)
388: throws IOException {
389: MetricsComparator comparator = new MetricsComparator(
390: getCommandLine().getSingleSwitch("sort"));
391: if (getCommandLine().getToggleSwitch("reverse")) {
392: comparator.reverse();
393: }
394:
395: List<Metrics> metrics;
396:
397: if (getCommandLine().getToggleSwitch("project")) {
398: out.println("Project metrics");
399: out.println("---------------");
400: metrics = new ArrayList<Metrics>(factory
401: .getProjectMetrics());
402: Collections.sort(metrics, comparator);
403: com.jeantessier.metrics.TextPrinter printer = new com.jeantessier.metrics.TextPrinter(
404: out, factory.getConfiguration()
405: .getProjectMeasurements());
406: printer.setExpandCollectionMeasurements(getCommandLine()
407: .getToggleSwitch("expand"));
408: printer.setShowEmptyMetrics(getCommandLine().isPresent(
409: "show-empty-metrics"));
410: printer.setShowHiddenMeasurements(getCommandLine()
411: .isPresent("show-hidden-measurements"));
412: if (getCommandLine().isPresent("indent-text")) {
413: printer.setIndentText(getCommandLine().getSingleSwitch(
414: "indent-text"));
415: }
416:
417: printer.visitMetrics(metrics);
418:
419: out.println();
420: }
421:
422: if (getCommandLine().getToggleSwitch("groups")) {
423: out.println("Group metrics");
424: out.println("-------------");
425: metrics = new ArrayList<Metrics>(factory.getGroupMetrics());
426: Collections.sort(metrics, comparator);
427: com.jeantessier.metrics.TextPrinter printer = new com.jeantessier.metrics.TextPrinter(
428: out, factory.getConfiguration()
429: .getGroupMeasurements());
430: printer.setExpandCollectionMeasurements(getCommandLine()
431: .getToggleSwitch("expand"));
432: printer.setShowEmptyMetrics(getCommandLine().isPresent(
433: "show-empty-metrics"));
434: printer.setShowHiddenMeasurements(getCommandLine()
435: .isPresent("show-hidden-measurements"));
436: if (getCommandLine().isPresent("indent-text")) {
437: printer.setIndentText(getCommandLine().getSingleSwitch(
438: "indent-text"));
439: }
440:
441: printer.visitMetrics(metrics);
442:
443: out.println();
444: }
445:
446: if (getCommandLine().getToggleSwitch("classes")) {
447: out.println("Class metrics");
448: out.println("-------------");
449: metrics = new ArrayList<Metrics>(factory.getClassMetrics());
450: Collections.sort(metrics, comparator);
451: com.jeantessier.metrics.TextPrinter printer = new com.jeantessier.metrics.TextPrinter(
452: out, factory.getConfiguration()
453: .getClassMeasurements());
454: printer.setExpandCollectionMeasurements(getCommandLine()
455: .getToggleSwitch("expand"));
456: printer.setShowEmptyMetrics(getCommandLine().isPresent(
457: "show-empty-metrics"));
458: printer.setShowHiddenMeasurements(getCommandLine()
459: .isPresent("show-hidden-measurements"));
460: if (getCommandLine().isPresent("indent-text")) {
461: printer.setIndentText(getCommandLine().getSingleSwitch(
462: "indent-text"));
463: }
464:
465: printer.visitMetrics(metrics);
466:
467: out.println();
468: }
469:
470: if (getCommandLine().getToggleSwitch("methods")) {
471: out.println("Method metrics");
472: out.println("--------------");
473: metrics = new ArrayList<Metrics>(factory.getMethodMetrics());
474: Collections.sort(metrics, comparator);
475: com.jeantessier.metrics.TextPrinter printer = new com.jeantessier.metrics.TextPrinter(
476: out, factory.getConfiguration()
477: .getMethodMeasurements());
478: printer.setExpandCollectionMeasurements(getCommandLine()
479: .getToggleSwitch("expand"));
480: printer.setShowEmptyMetrics(getCommandLine().isPresent(
481: "show-empty-metrics"));
482: printer.setShowHiddenMeasurements(getCommandLine()
483: .isPresent("show-hidden-measurements"));
484: if (getCommandLine().isPresent("indent-text")) {
485: printer.setIndentText(getCommandLine().getSingleSwitch(
486: "indent-text"));
487: }
488:
489: printer.visitMetrics(metrics);
490:
491: out.println();
492: }
493:
494: out.close();
495: }
496:
497: private void printXMLFile(MetricsFactory factory)
498: throws IOException {
499: MetricsComparator comparator = new MetricsComparator(
500: getCommandLine().getSingleSwitch("sort"));
501: if (getCommandLine().getToggleSwitch("reverse")) {
502: comparator.reverse();
503: }
504:
505: List<Metrics> metrics;
506: com.jeantessier.metrics.Printer printer;
507:
508: metrics = new ArrayList<Metrics>(factory.getProjectMetrics());
509: Collections.sort(metrics, comparator);
510: printer = new com.jeantessier.metrics.XMLPrinter(out, factory
511: .getConfiguration(), getCommandLine().getSingleSwitch(
512: "encoding"), getCommandLine().getSingleSwitch(
513: "dtd-prefix"));
514: printer.setShowEmptyMetrics(getCommandLine().isPresent(
515: "show-empty-metrics"));
516: printer.setShowHiddenMeasurements(getCommandLine().isPresent(
517: "show-hidden-measurements"));
518: if (getCommandLine().isPresent("indent-text")) {
519: printer.setIndentText(getCommandLine().getSingleSwitch(
520: "indent-text"));
521: }
522:
523: printer.visitMetrics(metrics);
524:
525: out.close();
526: }
527:
528: public static void main(String[] args) throws Exception {
529: new OOMetrics().run(args);
530: }
531: }
|