/* * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package org.visage.tools.classreporter; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * @author ksrini */ public class ClassReporter { static boolean debug = false; /** * All this really does is execute a class and create the report file for * the hudson plotter, by harvesting the output of -verbose:class. * usage: -jar="Foo" -build.dir="build_dir" -dist.dir="dist" * -reference.url="http//foobar...job/id" */ private static String visageclassname = "HelloWorld"; private static String jarfilename = null; private static String builddir = "."; private static String distdir = "dist"; private static String referenceurl = "UNKNOWN"; private static final Hashtable<String, String> loadedClasses = new Hashtable<String, String>(); static void generateReports() throws IOException { parseOutput(); // print grand total printReport(new File(builddir, visageclassname + "-Total-classes.txt"), loadedClasses.size()); Hashtable<String, Integer> jarClasses = new Hashtable<String, Integer>(); // compute the totals for each of the jars for (String jarname : loadedClasses.values()) { Integer ivalue = jarClasses.get(jarname); if (ivalue == null) { jarClasses.put(jarname, new Integer(1)); } else { jarClasses.put(jarname, new Integer(ivalue.intValue() + 1)); } } // print the total for each of the jars for (String jarname : jarClasses.keySet()) { printReport(new File(builddir, visageclassname + "-" + jarname + "-classes.txt"), jarClasses.get(jarname).intValue()); } printToCSV(new File(builddir, visageclassname + ".csv")); } static void printToCSV(File csvFile) throws IOException { FileOutputStream fos = new FileOutputStream(csvFile); PrintStream ps = new PrintStream(fos); for (String classname : Collections.list(loadedClasses.keys())) { ps.println(classname + "\t" + loadedClasses.get(classname)); } ps.close(); fos.close(); } static void printReport(File reportFile, int value) throws IOException { FileOutputStream fos = new FileOutputStream(reportFile); PrintStream ps = new PrintStream(fos); ps.println("YVALUE=" + value); ps.println("URL=" + referenceurl); ps.close(); fos.close(); } /* * emit our Visage code */ static void CreateSampleVisage(File visageFile) { FileOutputStream fos = null; PrintStream ps = null; try { fos = new FileOutputStream(visageFile); ps = new PrintStream(fos); ps.println("Visage.println(\"Hello World\");"); } catch (IOException ioe) { Logger.getLogger(ClassReporter.class.getName()).log(Level.SEVERE, null, ioe); } finally { try { if (ps != null) { ps.close(); } if (fos != null) { fos.close(); } } catch (IOException ex) { Logger.getLogger(ClassReporter.class.getName()).log(Level.SEVERE, null, ex); } } doExec(getExe("visagec").getAbsolutePath(), visageFile.getAbsolutePath()); } static String getJarName(String inName) { File f = new File(inName); String jarname = f.getName(); String out = "ANON"; if (inName.contains(".jar")) { out = jarname.substring(0, jarname.indexOf(".jar")); } return out; } static void parseOutput() { List<String> output = null; if (jarfilename == null) { File visageFile = new File(builddir, visageclassname + ".visage"); CreateSampleVisage(visageFile); output = doExec(getExe("visage").getAbsolutePath(), "-cp", builddir, "-verbose:class", visageclassname ); } else { output = doExec(getExe("visage").getAbsolutePath(), "-verbose:class", "-jar", jarfilename ); } for (String x : output) { if (x.startsWith("[Loaded")) { String[] fields = x.split("\\s"); // The last field is the jarname. String jarname = getJarName(fields[fields.length - 1]); loadedClasses.put(fields[1], jarname); } } } static List<String> doExec(String... cmds) { List<String> cmdsList = new ArrayList<String>(); for (String x : cmds) { cmdsList.add(x); } return doExec(cmdsList); } static List<String> doExec(List<String> cmds) { if (debug) { System.out.println("----Execution args----"); for (String x : cmds) { System.out.println(x); } } List<String> outputList = new ArrayList<String>(); ProcessBuilder pb = new ProcessBuilder(cmds); pb = pb.directory(new File(builddir)); FileReader fr = null; BufferedReader rdr = null; try { pb.redirectErrorStream(true); Process p = pb.start(); rdr = new BufferedReader(new InputStreamReader(p.getInputStream())); // note: its a good idea to read the whole stream, half baked // reads can cause undesired side-effects. String in = rdr.readLine(); if (debug) { System.out.println("---output---"); } while (in != null) { if (debug) { System.out.println(in); } outputList.add(in); in = rdr.readLine(); } p.waitFor(); p.destroy(); if (p.exitValue() != 0) { System.out.println("Error: Unexpected exit value " + p.exitValue()); return null; } return outputList; } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex.getMessage()); } finally { if (fr != null) { try { fr.close(); } catch (IOException ioe) { throw new RuntimeException("Error while closing file " + ioe); } } } } static void usage(String msg) { System.err.println(msg); System.exit(1); } static File getExe(String exename) { File bindir = new File(distdir, "bin"); if (System.getProperty("os.name").startsWith("Windows")) { return new File(bindir, exename + ".exe"); } return new File(bindir, exename); } public static void main(String[] args) { try { if (args != null) { for (int i = 0 ; i < args.length ; i++) { if (args[i].startsWith("-jar")) { visageclassname = args[i].substring(args[i].indexOf("=") + 1); if (visageclassname.endsWith(".jar")) { jarfilename=visageclassname; String jfname = new File(jarfilename).getName(); visageclassname = jfname.substring(0, jfname.indexOf(".jar")); } } else if (args[i].startsWith("-build.dir")) { builddir = args[i].substring(args[i].indexOf("=") + 1); } else if (args[i].startsWith("-dist.dir")) { distdir = args[i].substring(args[i].indexOf("=") + 1); } else if (args[i].startsWith("-reference.url")) { referenceurl = args[i].substring(args[i].indexOf("=") + 1); } } } generateReports(); } catch (IOException ex) { Logger.getLogger(ClassReporter.class.getName()).log(Level.SEVERE, null, ex); System.exit(1); } } }