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.text.*;
040:import com.jeantessier.commandline.*;
041:
042:public class ClassMetrics extends Command {
043: private boolean list;
044:
045: public ClassMetrics() throws CommandLineException {
046: super ("ClassMetrics");
047: }
048:
049: protected void showSpecificUsage(PrintStream out) {
050: System.err.println();
051: System.err.println("If no files are specified, it processes the current directory.");
052: System.err.println();
053: System.err.println("If file is a directory, it is recusively scanned for files");
054: System.err.println("ending in \".class\".");
055: System.err.println();
056: System.err.println("Defaults is text output to the console.");
057: System.err.println();
058: }
059:
060: protected void populateCommandLineSwitches() {
061: super .populateCommandLineSwitches();
062:
063: getCommandLine().addToggleSwitch("list");
064: getCommandLine().addToggleSwitch("instruction-counts");
065: }
066:
067: public void doProcessing() throws Exception {
068: list = getCommandLine().getToggleSwitch("list");
069:
070: List<String> parameters = getCommandLine().getParameters();
071: if (parameters.size() == 0) {
072: parameters.add(".");
073: }
074:
075: MetricsGatherer metrics = new MetricsGatherer();
076:
077: ClassfileLoader loader = new TransientClassfileLoader();
078: loader.addLoadListener(getVerboseListener());
079: loader.addLoadListener(new LoadListenerVisitorAdapter(metrics));
080: loader.load(parameters);
081:
082: getVerboseListener().print("Printing report ...");
083:
084: out.println(metrics.getClasses().size() + " class(es)");
085: if (list) {
086: for (Object o : metrics.getClasses()) {
087: out.println(" " + o);
088: }
089: }
090:
091: out.println(metrics.getInterfaces().size() + " interface(s)");
092: if (list) {
093: for (Object o : metrics.getInterfaces()) {
094: out.println(" " + o);
095: }
096: }
097:
098: out.println();
099: out.println(metrics.getMethods().size() + " method(s) (average " + (metrics.getMethods().size() / (metrics.getClasses().size() + (double) metrics.getInterfaces().size())) + " per class/interface)");
100: out.println(metrics.getFields().size() + " field(s) (average " + (metrics.getFields().size() / (metrics.getClasses().size() + (double) metrics.getInterfaces().size())) + " per class/interface)");
101: out.println();
102:
103: printCFM(" synthetic element(s)", metrics.getSyntheticClasses(), metrics.getSyntheticFields(), metrics.getSyntheticMethods());
104: printCFM(" deprecated element(s)", metrics.getDeprecatedClasses(), metrics.getDeprecatedFields(), metrics.getDeprecatedMethods());
105: printCFMIC(" public element(s)", metrics.getPublicClasses(), metrics.getPublicFields(), metrics.getPublicMethods(), metrics.getPublicInnerClasses());
106: printFMIC(" protected element(s)", metrics.getProtectedFields(), metrics.getProtectedMethods(), metrics.getProtectedInnerClasses());
107: printFMIC(" private element(s)", metrics.getPrivateFields(), metrics.getPrivateMethods(), metrics.getPrivateInnerClasses());
108: printCFMIC(" package element(s)", metrics.getPackageClasses(), metrics.getPackageFields(), metrics.getPackageMethods(), metrics.getPackageInnerClasses());
109: printCMIC(" abstract element(s)", metrics.getAbstractClasses(), metrics.getAbstractMethods(), metrics.getAbstractInnerClasses());
110:
111: printFMIC(" static element(s)", metrics.getStaticFields(), metrics.getStaticMethods(), metrics.getStaticInnerClasses());
112: printCFMIC(" final element(s)", metrics.getFinalClasses(), metrics.getFinalFields(), metrics.getFinalMethods(), metrics.getFinalInnerClasses());
113:
114: out.println(metrics.getSynchronizedMethods().size() + " synchronized method(s)");
115: if (list) {
116: for (Object o : metrics.getSynchronizedMethods()) {
117: out.println(" " + o);
118: }
119: }
120:
121: out.println(metrics.getNativeMethods().size() + " native method(s)");
122: if (list) {
123: for (Object o : metrics.getNativeMethods()) {
124: out.println(" " + o);
125: }
126: }
127:
128: out.println(metrics.getVolatileFields().size() + " volatile field(s)");
129: if (list) {
130: for (Object o : metrics.getVolatileFields()) {
131: out.println(" " + o);
132: }
133: }
134:
135: out.println(metrics.getTransientFields().size() + " transient field(s)");
136: if (list) {
137: for (Object o : metrics.getTransientFields()) {
138: out.println(" " + o);
139: }
140: }
141:
142: out.println(metrics.getCustomAttributes().size() + " custom attribute(s)");
143: if (list) {
144: for (Object o : metrics.getCustomAttributes()) {
145: out.println(" " + o);
146: }
147: }
148:
149: if (getCommandLine().getToggleSwitch("instruction-counts")) {
150: out.println();
151: out.println("Instruction counts:");
152: for (int opcode=0; opcode<256; opcode++) {
153: out.print(" 0x");
154: Hex.print(out, (byte) opcode);
155: out.println(" " + Instruction.getMnemonic(opcode) + ": " + metrics.getInstructionCounts()[opcode]);
156: }
157: }
158: }
159:
160: private void printCMIC(String label, Collection classes, Collection methods, Collection innerClasses) {
161: out.println((classes.size() +
162: methods.size() +
163: innerClasses.size()) + label);
164: if (list) {
165: out.println(" " + classes.size() + " class(es)");
166: for (Object aClass : classes) {
167: out.println(" " + aClass);
168: }
169:
170: out.println(" " + methods.size() + " method(s)");
171: for (Object method : methods) {
172: out.println(" " + method);
173: }
174:
175: out.println(" " + innerClasses.size() + " inner class(es)");
176: for (Object innerClass : innerClasses) {
177: out.println(" " + innerClass);
178: }
179: } else {
180: out.println(" " + classes.size() + " class(es)");
181: out.println(" " + methods.size() + " method(s)");
182: out.println(" " + innerClasses.size() + " inner class(es)");
183: }
184: }
185:
186: private void printCFMIC(String label, Collection classes, Collection fields, Collection methods, Collection innerClasses) {
187: out.println((classes.size() +
188: fields.size() +
189: methods.size() +
190: innerClasses.size()) + label);
191: if (list) {
192: out.println(" " + classes.size() + " class(es)");
193: for (Object aClass : classes) {
194: out.println(" " + aClass);
195: }
196:
197: out.println(" " + fields.size() + " field(s)");
198: for (Object field : fields) {
199: out.println(" " + field);
200: }
201:
202: out.println(" " + methods.size() + " method(s)");
203: for (Object method : methods) {
204: out.println(" " + method);
205: }
206:
207: out.println(" " + innerClasses.size() + " inner class(es)");
208: for (Object innerClass : innerClasses) {
209: out.println(" " + innerClass);
210: }
211: } else {
212: out.println(" " + classes.size() + " class(es)");
213: out.println(" " + fields.size() + " fields(s)");
214: out.println(" " + methods.size() + " method(s)");
215: out.println(" " + innerClasses.size() + " inner class(es)");
216: }
217: }
218:
219: private void printCFM(String label, Collection classes, Collection fields, Collection methods) {
220: out.println((classes.size() +
221: fields.size() +
222: methods.size()) + label);
223: if (list) {
224: out.println(" " + classes.size() + " class(es)");
225: for (Object aClass : classes) {
226: out.println(" " + aClass);
227: }
228:
229: out.println(" " + fields.size() + " field(s)");
230: for (Object field : fields) {
231: out.println(" " + field);
232: }
233:
234: out.println(" " + methods.size() + " method(s)");
235: for (Object method : methods) {
236: out.println(" " + method);
237: }
238: } else {
239: out.println(" " + classes.size() + " class(es)");
240: out.println(" " + fields.size() + " fields(s)");
241: out.println(" " + methods.size() + " method(s)");
242: }
243: }
244:
245: private void printFMIC(String label, Collection fields, Collection methods, Collection innerClasses) {
246: out.println((fields.size() +
247: methods.size() +
248: innerClasses.size()) + label);
249: if (list) {
250: out.println(" " + fields.size() + " field(s)");
251: for (Object field : fields) {
252: out.println(" " + field);
253: }
254:
255: out.println(" " + methods.size() + " method(s)");
256: for (Object method : methods) {
257: out.println(" " + method);
258: }
259:
260: out.println(" " + innerClasses.size() + " inner class(es)");
261: for (Object innerClass : innerClasses) {
262: out.println(" " + innerClass);
263: }
264: } else {
265: out.println(" " + fields.size() + " fields(s)");
266: out.println(" " + methods.size() + " method(s)");
267: out.println(" " + innerClasses.size() + " inner class(es)");
268: }
269: }
270:
271: public static void main(String[] args) throws Exception {
272: new ClassMetrics().run(args);
273: }
274:}
|