Analyzer.java revision fc340a20c201bec9c0ee31ec16c85766477a1edf
1e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/******************************************************************************* 237115f4ba4f6126b8c3352ac890c653e428a7dd8Marc R. Hoffmann * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors 3e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * All rights reserved. This program and the accompanying materials 4e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * are made available under the terms of the Eclipse Public License v1.0 5e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * which accompanies this distribution, and is available at 6e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * http://www.eclipse.org/legal/epl-v10.html 7e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 8e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Contributors: 9e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Marc R. Hoffmann - initial API and implementation 10e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 11e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *******************************************************************************/ 12e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpackage org.jacoco.core.analysis; 13e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 14e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.File; 15e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.FileInputStream; 16e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.IOException; 17e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.InputStream; 18e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.util.StringTokenizer; 19fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmannimport java.util.zip.GZIPInputStream; 20e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.util.zip.ZipEntry; 21e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.util.zip.ZipInputStream; 22e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 23e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.data.ExecutionData; 24e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.data.ExecutionDataStore; 25adf2bf660e12b3b284eb80965328802101cf6762Marc R. Hoffmannimport org.jacoco.core.internal.ContentTypeDetector; 26fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmannimport org.jacoco.core.internal.Pack200Streams; 27e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.internal.analysis.ClassAnalyzer; 28e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.internal.analysis.StringPool; 29e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.internal.data.CRC64; 30e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.internal.flow.ClassProbesAdapter; 31e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.objectweb.asm.ClassReader; 32e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.objectweb.asm.ClassVisitor; 33e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 34e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/** 35e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * An {@link Analyzer} instance processes a set of Java class files and 36e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * calculates coverage data for them. For each class file the result is reported 37e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * to a given {@link ICoverageVisitor} instance. In addition the 38e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * {@link Analyzer} requires a {@link ExecutionDataStore} instance that holds 39e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * the execution data for the classes to analyze. The {@link Analyzer} offers 40e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * several methods to analyze classes from a variety of sources. 41e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 42e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpublic class Analyzer { 43e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 44e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private final ExecutionDataStore executionData; 45e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 46e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private final ICoverageVisitor coverageVisitor; 47e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 48e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private final StringPool stringPool; 49e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 50e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 51e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Creates a new analyzer reporting to the given output. 52e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 53e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param executionData 54e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * execution data 55e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param coverageVisitor 56e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * the output instance that will coverage data for every analyzed 57e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * class 58e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 59e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public Analyzer(final ExecutionDataStore executionData, 60e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final ICoverageVisitor coverageVisitor) { 61e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov this.executionData = executionData; 62e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov this.coverageVisitor = coverageVisitor; 63e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov this.stringPool = new StringPool(); 64e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 65e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 66e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 67e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Creates an ASM class visitor for analysis. 68e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 69e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param classid 70e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * id of the class calculated with {@link CRC64} 71e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return ASM visitor to write class definition to 72e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 73e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private ClassVisitor createAnalyzingVisitor(final long classid) { 74e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final ExecutionData data = executionData.get(classid); 7527e32e433ba0ac1fdec9290d3454d5b369c969ccMarc R. Hoffmann final boolean[] probes = data == null ? null : data.getProbes(); 7627e32e433ba0ac1fdec9290d3454d5b369c969ccMarc R. Hoffmann final ClassAnalyzer analyzer = new ClassAnalyzer(classid, probes, 77e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov stringPool) { 78e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov @Override 79e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void visitEnd() { 80e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov super.visitEnd(); 81e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov coverageVisitor.visitCoverage(getCoverage()); 82e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 83e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov }; 84e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return new ClassProbesAdapter(analyzer); 85e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 86e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 87e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 88e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes the class given as a ASM reader. 89e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 90e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param reader 91e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * reader with class definitions 92e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 93e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void analyzeClass(final ClassReader reader) { 94e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final ClassVisitor visitor = createAnalyzingVisitor(CRC64 95e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov .checksum(reader.b)); 96e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov reader.accept(visitor, 0); 97e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 98e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 99e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 100e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes the class definition from a given in-memory buffer. 101e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 102e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param buffer 103e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * class definitions 104e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 105e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void analyzeClass(final byte[] buffer) { 106e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov analyzeClass(new ClassReader(buffer)); 107e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 108e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 109e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 110e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes the class definition from a given input stream. 111e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 112e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param input 113e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * stream to read class definition from 114e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 11557f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the stream can't be read 116e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 117e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void analyzeClass(final InputStream input) throws IOException { 118e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov analyzeClass(new ClassReader(input)); 119e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 120e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 121e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 122e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes all classes contained in the ZIP archive (jar, war, ear, etc.) 123e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * given as an input stream. Contained archives are read recursively. 124e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 125e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param input 126e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * ZIP archive data 127e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return number of class files found 128e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 12957f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the stream can't be read 130fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann * @deprecated Use {@link #analyzeAll(InputStream)} instead 131e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 132fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann @Deprecated 133e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public int analyzeArchive(final InputStream input) throws IOException { 134fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzeZip(input); 135e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 136e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 137e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 138e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes all classes found in the given input stream. The input stream 139fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann * may either represent a single class file, a ZIP archive, a Pack200 140fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann * archive or a gzip stream that is searched recursively for class files. 141fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann * All other content types are ignored. 142e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 143e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param input 144e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * input data 145e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return number of class files found 146e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 14757f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the stream can't be read 148e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 149e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public int analyzeAll(final InputStream input) throws IOException { 150e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final ContentTypeDetector detector = new ContentTypeDetector(input); 151e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov switch (detector.getType()) { 152e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov case ContentTypeDetector.CLASSFILE: 153e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov analyzeClass(detector.getInputStream()); 154e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return 1; 155e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov case ContentTypeDetector.ZIPFILE: 156fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzeZip(detector.getInputStream()); 157fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann case ContentTypeDetector.GZFILE: 158fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzeGzip(detector.getInputStream()); 159fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann case ContentTypeDetector.PACK200FILE: 160fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzePack200(detector.getInputStream()); 161e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov default: 162e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return 0; 163e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 164e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 165e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 166e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 167e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes all class files contained in the given file or folder. Class 168e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * files as well as ZIP files are considered. Folders are searched 169e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * recursively. 170e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 171e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param file 172e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * file or folder to look for class files 173e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return number of class files found 174e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 17557f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the file can't be read 176e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 177e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public int analyzeAll(final File file) throws IOException { 178e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov int count = 0; 179e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov if (file.isDirectory()) { 180e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov for (final File f : file.listFiles()) { 181e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov count += analyzeAll(f); 182e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 183e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } else { 184e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final InputStream in = new FileInputStream(file); 185e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov try { 186e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov count += analyzeAll(in); 187e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } finally { 188e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov in.close(); 189e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 190e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 191e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return count; 192e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 193e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 194e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 195e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Analyzes all classes from the given class path. Directories containing 196e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * class files as well as archive files are considered. 197e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 198e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param path 199e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * path definition 200e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param basedir 201e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * optional base directory, if <code>null</code> the current 202e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * working directory is used as the base for relative path 203e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * entries 204e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return number of class files found 205e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 20657f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if a file can't be read 207e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 208e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public int analyzeAll(final String path, final File basedir) 209e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throws IOException { 210e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov int count = 0; 211e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final StringTokenizer st = new StringTokenizer(path, File.pathSeparator); 212e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov while (st.hasMoreTokens()) { 213e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov count += analyzeAll(new File(basedir, st.nextToken())); 214e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 215e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return count; 216e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 217e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 218fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann private int analyzeZip(final InputStream input) throws IOException { 219fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann final ZipInputStream zip = new ZipInputStream(input); 220fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann int count = 0; 221fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann while (true) { 222fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann final ZipEntry entry = zip.getNextEntry(); 223fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann if (entry == null) { 224fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann break; 225fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann } 226fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann count += analyzeAll(zip); 227fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann } 228fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return count; 229fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann } 230fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann 231fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann private int analyzeGzip(final InputStream input) throws IOException { 232fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzeAll(new GZIPInputStream(input)); 233fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann } 234fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann 235fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann private int analyzePack200(final InputStream input) throws IOException { 236fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann return analyzeAll(Pack200Streams.unpack(input)); 237fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann } 238fc340a20c201bec9c0ee31ec16c85766477a1edfMarc R. Hoffmann 239e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov} 240