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:
041:import com.jeantessier.classreader.*;
042:import com.jeantessier.text.*;
043:
044:public class ClassMetrics extends Task {
045: private boolean list = false;
046: private boolean instructionCounts = false;
047: private File destfile;
048: private Path path;
049:
050: public boolean getList() {
051: return list;
052: }
053:
054: public void setList(boolean list) {
055: this .list = list;
056: }
057:
058: public boolean getInstructioncounts() {
059: return instructionCounts;
060: }
061:
062: public void setInstructioncounts(boolean instructionCounts) {
063: this .instructionCounts = instructionCounts;
064: }
065:
066: public File getDestfile() {
067: return destfile;
068: }
069:
070: public void setDestfile(File destfile) {
071: this .destfile = destfile;
072: }
073:
074: public Path createPath() {
075: if (path == null) {
076: path = new Path(getProject());
077: }
078:
079: return path;
080: }
081:
082: public Path getPath() {
083: return path;
084: }
085:
086: public void execute() throws BuildException {
087: // first off, make sure that we've got what we need
088:
089: if (getPath() == null) {
090: throw new BuildException("path must be set!");
091: }
092:
093: if (getDestfile() == null) {
094: throw new BuildException("destfile must be set!");
095: }
096:
097: log("Reading classes from path " + getPath());
098:
099: VerboseListener verboseListener = new VerboseListener(this );
100:
101: MetricsGatherer metrics = new MetricsGatherer();
102:
103: ClassfileLoader loader = new TransientClassfileLoader();
104: loader.addLoadListener(verboseListener);
105: loader.addLoadListener(new LoadListenerVisitorAdapter(metrics));
106: loader.load(Arrays.asList(getPath().list()));
107:
108: log("Saving class metrics to " + getDestfile().getAbsolutePath());
109:
110: try {
111: PrintWriter out = new PrintWriter(new FileWriter(getDestfile()));
112:
113: out.println(metrics.getClasses().size() + " class(es)");
114: if (getList()) {
115: for (Object o : metrics.getClasses()) {
116: out.println(" " + o);
117: }
118: }
119:
120: out.println(metrics.getInterfaces().size() + " interface(s)");
121: if (getList()) {
122: for (Object o : metrics.getInterfaces()) {
123: out.println(" " + o);
124: }
125: }
126:
127: out.println();
128: out.println(metrics.getMethods().size() + " method(s) (average " + (metrics.getMethods().size() / (metrics.getClasses().size() + (double) metrics.getInterfaces().size())) + " per class/interface)");
129: out.println(metrics.getFields().size() + " field(s) (average " + (metrics.getFields().size() / (metrics.getClasses().size() + (double) metrics.getInterfaces().size())) + " per class/interface)");
130: out.println();
131:
132: printCFM(out, " synthetic element(s)", metrics.getSyntheticClasses(), metrics.getSyntheticFields(), metrics.getSyntheticMethods());
133: printCFM(out, " deprecated element(s)", metrics.getDeprecatedClasses(), metrics.getDeprecatedFields(), metrics.getDeprecatedMethods());
134: printCFMIC(out, " public element(s)", metrics.getPublicClasses(), metrics.getPublicFields(), metrics.getPublicMethods(), metrics.getPublicInnerClasses());
135: printFMIC(out, " protected element(s)", metrics.getProtectedFields(), metrics.getProtectedMethods(), metrics.getProtectedInnerClasses());
136: printFMIC(out, " private element(s)", metrics.getPrivateFields(), metrics.getPrivateMethods(), metrics.getPrivateInnerClasses());
137: printCFMIC(out, " package element(s)", metrics.getPackageClasses(), metrics.getPackageFields(), metrics.getPackageMethods(), metrics.getPackageInnerClasses());
138: printCMIC(out, " abstract element(s)", metrics.getAbstractClasses(), metrics.getAbstractMethods(), metrics.getAbstractInnerClasses());
139:
140: printFMIC(out, " static element(s)", metrics.getStaticFields(), metrics.getStaticMethods(), metrics.getStaticInnerClasses());
141: printCFMIC(out, " final element(s)", metrics.getFinalClasses(), metrics.getFinalFields(), metrics.getFinalMethods(), metrics.getFinalInnerClasses());
142:
143: out.println(metrics.getSynchronizedMethods().size() + " synchronized method(s)");
144: if (getList()) {
145: for (Object o : metrics.getSynchronizedMethods()) {
146: out.println(" " + o);
147: }
148: }
149:
150: out.println(metrics.getNativeMethods().size() + " native method(s)");
151: if (getList()) {
152: for (Object o : metrics.getNativeMethods()) {
153: out.println(" " + o);
154: }
155: }
156:
157: out.println(metrics.getVolatileFields().size() + " volatile field(s)");
158: if (getList()) {
159: for (Object o : metrics.getVolatileFields()) {
160: out.println(" " + o);
161: }
162: }
163:
164: out.println(metrics.getTransientFields().size() + " transient field(s)");
165: if (getList()) {
166: for (Object o : metrics.getTransientFields()) {
167: out.println(" " + o);
168: }
169: }
170:
171: out.println(metrics.getCustomAttributes().size() + " custom attribute(s)");
172: if (getList()) {
173: for (Object o : metrics.getCustomAttributes()) {
174: out.println(" " + o);
175: }
176: }
177:
178: if (getInstructioncounts()) {
179: out.println();
180: out.println("Instruction counts:");
181: for (int opcode=0; opcode<256; opcode++) {
182: out.print(" 0x");
183: Hex.print(out, (byte) opcode);
184: out.println(" " + Instruction.getMnemonic(opcode) + ": " + metrics.getInstructionCounts()[opcode]);
185: }
186: }
187:
188: out.close();
189: } catch (IOException ex) {
190: throw new BuildException(ex);
191: }
192: }
193:
194: private void printCMIC(PrintWriter out, String label, Collection classes, Collection methods, Collection innerClasses) {
195: out.println((classes.size() +
196: methods.size() +
197: innerClasses.size()) + label);
198: if (getList()) {
199:
200: out.println(" " + classes.size() + " class(es)");
201: for (Object aClass : classes) {
202: out.println(" " + aClass);
203: }
204:
205: out.println(" " + methods.size() + " method(s)");
206: for (Object method : methods) {
207: out.println(" " + method);
208: }
209:
210: out.println(" " + innerClasses.size() + " inner class(es)");
211: for (Object innerClass : innerClasses) {
212: out.println(" " + innerClass);
213: }
214: } else {
215: out.println(" " + classes.size() + " class(es)");
216: out.println(" " + methods.size() + " method(s)");
217: out.println(" " + innerClasses.size() + " inner class(es)");
218: }
219: }
220:
221: private void printCFMIC(PrintWriter out, String label, Collection classes, Collection fields, Collection methods, Collection innerClasses) {
222: out.println((classes.size() +
223: fields.size() +
224: methods.size() +
225: innerClasses.size()) + label);
226: if (getList()) {
227: out.println(" " + classes.size() + " class(es)");
228: for (Object aClass : classes) {
229: out.println(" " + aClass);
230: }
231:
232: out.println(" " + fields.size() + " field(s)");
233: for (Object field : fields) {
234: out.println(" " + field);
235: }
236:
237: out.println(" " + methods.size() + " method(s)");
238: for (Object method : methods) {
239: out.println(" " + method);
240: }
241:
242: out.println(" " + innerClasses.size() + " inner class(es)");
243: for (Object innerClass : innerClasses) {
244: out.println(" " + innerClass);
245: }
246: } else {
247: out.println(" " + classes.size() + " class(es)");
248: out.println(" " + fields.size() + " fields(s)");
249: out.println(" " + methods.size() + " method(s)");
250: out.println(" " + innerClasses.size() + " inner class(es)");
251: }
252: }
253:
254: private void printCFM(PrintWriter out, String label, Collection classes, Collection fields, Collection methods) {
255: out.println((classes.size() +
256: fields.size() +
257: methods.size()) + label);
258: if (getList()) {
259: out.println(" " + classes.size() + " class(es)");
260: for (Object aClass : classes) {
261: out.println(" " + aClass);
262: }
263:
264: out.println(" " + fields.size() + " field(s)");
265: for (Object field : fields) {
266: out.println(" " + field);
267: }
268:
269: out.println(" " + methods.size() + " method(s)");
270: for (Object method : methods) {
271: out.println(" " + method);
272: }
273: } else {
274: out.println(" " + classes.size() + " class(es)");
275: out.println(" " + fields.size() + " fields(s)");
276: out.println(" " + methods.size() + " method(s)");
277: }
278: }
279:
280: private void printFMIC(PrintWriter out, String label, Collection fields, Collection methods, Collection innerClasses) {
281: out.println((fields.size() +
282: methods.size() +
283: innerClasses.size()) + label);
284: if (getList()) {
285: out.println(" " + fields.size() + " field(s)");
286: for (Object field : fields) {
287: out.println(" " + field);
288: }
289:
290: out.println(" " + methods.size() + " method(s)");
291: for (Object method : methods) {
292: out.println(" " + method);
293: }
294:
295: out.println(" " + innerClasses.size() + " inner class(es)");
296: for (Object innerClass : innerClasses) {
297: out.println(" " + innerClass);
298: }
299: } else {
300: out.println(" " + fields.size() + " fields(s)");
301: out.println(" " + methods.size() + " method(s)");
302: out.println(" " + innerClasses.size() + " inner class(es)");
303: }
304: }
305:}
|