/* * FindBugs - Find bugs in Java programs * Copyright (C) 2003-2005 William Pugh * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.umd.cs.findbugs; import java.math.BigInteger; import java.security.MessageDigest; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.BugCollection; import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.PackageStats; import edu.umd.cs.findbugs.PackageStats.ClassStats; import edu.umd.cs.findbugs.SortedBugCollection; import edu.umd.cs.findbugs.SourceLineAnnotation; import edu.umd.cs.findbugs.util.Util; /** * For each source file that has reported bugs, compute a hash of all the issues * reported for that file. These hashes use line numbers, so a change that only * changes the line number of an issue will cause the hash to be different. * * @author William Pugh */ public class FileBugHash { Map<String, StringBuilder> hashes = new LinkedHashMap<String, StringBuilder>(); Map<String, Integer> counts = new HashMap<String, Integer>(); Map<String, Integer> sizes = new HashMap<String, Integer>(); MessageDigest digest = Util.getMD5Digest(); FileBugHash(BugCollection bugs) { for (PackageStats pStat : bugs.getProjectStats().getPackageStats()) for (ClassStats cStat : pStat.getSortedClassStats()) { String path = cStat.getName(); if (path.indexOf('.') == -1) path = cStat.getSourceFile(); else path = path.substring(0, path.lastIndexOf('.') + 1).replace('.', '/') + cStat.getSourceFile(); counts.put(path, 0); Integer size = sizes.get(path); if (size == null) size = 0; sizes.put(path, size + cStat.size()); } for (BugInstance bug : bugs.getCollection()) { SourceLineAnnotation source = bug.getPrimarySourceLineAnnotation(); String packagePath = source.getPackageName().replace('.', '/'); String key; if (packagePath.length() == 0) key = source.getSourceFile(); else key = packagePath + "/" + source.getSourceFile(); StringBuilder buf = hashes.get(key); if (buf == null) { buf = new StringBuilder(); hashes.put(key, buf); } buf.append(bug.getInstanceKey()).append("-").append(source.getStartLine()).append(".") .append(source.getStartBytecode()).append(" "); Integer count = counts.get(key); if (count == null) counts.put(key, 1); else counts.put(key, 1 + count); } } public Collection<String> getSourceFiles() { return counts.keySet(); } public @CheckForNull String getHash(String sourceFile) { StringBuilder rawHash = hashes.get(sourceFile); if (rawHash == null || digest == null) return null; byte[] data = digest.digest(rawHash.toString().getBytes()); String tmp = new BigInteger(1, data).toString(16); if (tmp.length() < 32) tmp = "000000000000000000000000000000000".substring(0, 32 - tmp.length()) + tmp; return tmp; } public int getBugCount(String sourceFile) { Integer count = counts.get(sourceFile); if (count == null) return 0; return count; } public int getSize(String sourceFile) { Integer size = sizes.get(sourceFile); if (size == null) return 0; return size; } public static void main(String args[]) throws Exception { if (args.length > 1 || (args.length > 0 && "-help".equals(args[0]))) { System.err.println("Usage: " + FileBugHash.class.getName() + " [<infile>]"); System.exit(1); } BugCollection origCollection = new SortedBugCollection(); int argCount = 0; if (argCount == args.length) origCollection.readXML(System.in); else origCollection.readXML(args[argCount]); FileBugHash result = compute(origCollection); for (String sourceFile : result.getSourceFiles()) { System.out.println(result.getHash(sourceFile) + "\t" + sourceFile); } } /** * @param origCollection * @return */ public static FileBugHash compute(BugCollection origCollection) { return new FileBugHash(origCollection); } }