/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2007 University of Maryland
*
* 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.workflow;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import edu.umd.cs.findbugs.FindBugs;
import edu.umd.cs.findbugs.charsets.UTF8;
import edu.umd.cs.findbugs.charsets.UserTextFile;
import edu.umd.cs.findbugs.config.CommandLine;
import edu.umd.cs.findbugs.util.DualKeyHashMap;
import edu.umd.cs.findbugs.util.Util;
/**
* @author William Pugh
*/
public class CountClassVersions {
public static List<String> readFromStandardInput() throws IOException {
return readFrom(UserTextFile.reader(System.in));
}
public static List<String> readFrom(Reader r) throws IOException {
BufferedReader in = new BufferedReader(r);
List<String> lst = new LinkedList<String>();
while (true) {
String s = in.readLine();
if (s == null)
return lst;
lst.add(s);
}
}
static class CountClassVersionsCommandLine extends CommandLine {
public String prefix = "";
public String inputFileList;
long maxAge = Long.MIN_VALUE;
CountClassVersionsCommandLine() {
addOption("-maxAge", "days", "maximum age in days (ignore jar files older than this");
addOption("-inputFileList", "filename", "text file containing names of jar files");
addOption("-prefix", "class name prefix", "prefix of class names that should be analyzed e.g., edu.umd.cs.)");
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.config.CommandLine#handleOption(java.lang.String,
* java.lang.String)
*/
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
throw new IllegalArgumentException("Unknown option : " + option);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.config.CommandLine#handleOptionWithArgument(java
* .lang.String, java.lang.String)
*/
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
if (option.equals("-prefix"))
prefix = argument;
else if (option.equals("-inputFileList"))
inputFileList = argument;
else if (option.equals("-maxAge"))
maxAge = System.currentTimeMillis() - (24 * 60 * 60 * 1000L) * Integer.parseInt(argument);
else
throw new IllegalArgumentException("Unknown option : " + option);
}
}
public static void main(String args[]) throws Exception {
FindBugs.setNoAnalysis();
CountClassVersionsCommandLine commandLine = new CountClassVersionsCommandLine();
int argCount = commandLine.parse(args, 0, Integer.MAX_VALUE, "Usage: " + CountClassVersions.class.getName()
+ " [options] [<jarFile>+] ");
int analysisClassCount = 0;
List<String> fileList;
if (commandLine.inputFileList != null)
fileList = readFrom(UTF8.fileReader(commandLine.inputFileList));
else if (argCount == args.length)
fileList = readFromStandardInput();
else
fileList = Arrays.asList(args).subList(argCount, args.length - 1);
byte buffer[] = new byte[8192];
MessageDigest digest = Util.getMD5Digest();
DualKeyHashMap<String, String, String> map = new DualKeyHashMap<String, String, String>();
for (String fInName : fileList) {
File f = new File(fInName);
if (f.lastModified() < commandLine.maxAge) {
System.err.println("Skipping " + fInName + ", too old (" + new Date(f.lastModified()) + ")");
continue;
}
System.err.println("Opening " + f);
ZipFile zipInputFile;
try {
zipInputFile = new ZipFile(f);
} catch (IOException e) {
e.printStackTrace();
continue;
}
for (Enumeration<? extends ZipEntry> e = zipInputFile.entries(); e.hasMoreElements();) {
ZipEntry ze = e.nextElement();
if (ze == null)
break;
if (ze.isDirectory())
continue;
String name = ze.getName();
if (!name.endsWith(".class"))
continue;
if (!name.replace('/', '.').startsWith(commandLine.prefix))
continue;
InputStream zipIn = zipInputFile.getInputStream(ze);
while (true) {
int bytesRead = zipIn.read(buffer);
if (bytesRead < 0)
break;
digest.update(buffer, 0, bytesRead);
}
String hash = new BigInteger(1, digest.digest()).toString(16);
map.put(name, hash, fInName);
}
zipInputFile.close();
}
for (String s : map.keySet()) {
Map<String, String> values = map.get(s);
if (values.size() > 1) {
System.out.println(values.size() + "\t" + s + "\t" + values.values());
}
}
}
}