📄 sortedbugcollection.java
字号:
/* * FindBugs - Find bugs in Java programs * Copyright (C) 2003-2005 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;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.Reader;import java.io.StringWriter;import java.math.BigInteger;import java.security.MessageDigest;import java.util.Collection;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.SortedSet;import java.util.TreeMap;import java.util.TreeSet;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.zip.GZIPInputStream;import javax.xml.transform.TransformerException;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.DocumentFactory;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.XMLReaderFactory;import edu.umd.cs.findbugs.annotations.CheckForNull;import edu.umd.cs.findbugs.annotations.NonNull;import edu.umd.cs.findbugs.ba.AnalysisContext;import edu.umd.cs.findbugs.ba.MissingClassException;import edu.umd.cs.findbugs.model.ClassFeatureSet;import edu.umd.cs.findbugs.util.Util;import edu.umd.cs.findbugs.xml.Dom4JXMLOutput;import edu.umd.cs.findbugs.xml.OutputStreamXMLOutput;import edu.umd.cs.findbugs.xml.XMLAttributeList;import edu.umd.cs.findbugs.xml.XMLOutput;import edu.umd.cs.findbugs.xml.XMLOutputUtil;/** * An implementation of {@link BugCollection} that keeps the BugInstances * sorted by class (using the native comparison ordering of BugInstance's * compareTo() method as a tie-breaker). * * @see BugInstance * @author David Hovemeyer */public class SortedBugCollection implements BugCollection { long analysisTimestamp = System.currentTimeMillis(); String analysisVersion = Version.RELEASE; private boolean withMessages = false; private static final boolean REPORT_SUMMARY_HTML = SystemProperties.getBoolean("findbugs.report.SummaryHTML"); public long getAnalysisTimestamp() { return analysisTimestamp; } public void setAnalysisTimestamp(long timestamp) { analysisTimestamp = timestamp; } /** * Add a Collection of BugInstances to this BugCollection object. * This just calls add(BugInstance) for each instance in the input collection. * * @param collection the Collection of BugInstances to add */ public void addAll(Collection<BugInstance> collection) { for (BugInstance aCollection : collection) { add(aCollection); } } /** * Add a Collection of BugInstances to this BugCollection object. * * @param collection the Collection of BugInstances to add * @param updateActiveTime true if active time of added BugInstances should * be updated to match collection: false if not */ public void addAll(Collection<BugInstance> collection, boolean updateActiveTime) { for (BugInstance warning : collection) { add(warning, updateActiveTime); } } /** * Add a BugInstance to this BugCollection. * This just calls add(bugInstance, true). * * @param bugInstance the BugInstance * @return true if the BugInstance was added, or false if a matching * BugInstance was already in the BugCollection */ public boolean add(BugInstance bugInstance) { return add(bugInstance, true); } /** * Add an analysis error. * * @param message the error message */ public void addError(String message) { addError(message, null); } /** * Get the current AppVersion. */ public AppVersion getCurrentAppVersion() { return new AppVersion(getSequenceNumber()) .setReleaseName(getReleaseName()) .setTimestamp(getTimestamp()) .setNumClasses(getProjectStats().getNumClasses()) .setCodeSize(getProjectStats().getCodeSize()); } /** * Read XML data from given file into this object, * populating given Project as a side effect. * * @param fileName name of the file to read * @param project the Project */ public void readXML(String fileName, Project project) throws IOException, DocumentException { readXML(new File(fileName), project); } /** * Read XML data from given file into this object, * populating given Project as a side effect. * * @param file the file * @param project the Project */ public void readXML(File file, Project project) throws IOException, DocumentException { InputStream in = new BufferedInputStream(new FileInputStream(file)); if (file.getName().endsWith(".gz")) in = new GZIPInputStream(in); readXML(in, project, file); } /** * Read XML data from given input stream into this * object, populating the Project as a side effect. * An attempt will be made to close the input stream * (even if an exception is thrown). * * @param in the InputStream * @param project the Project */ public void readXML(InputStream in, Project project, File base) throws IOException, DocumentException { if (in == null) throw new IllegalArgumentException(); try { if (project == null) throw new IllegalArgumentException(); doReadXML(in, project, base); } finally { in.close(); } } public void readXML(InputStream in, Project project) throws IOException, DocumentException { doReadXML(in, project, null); } private void doReadXML(InputStream in, Project project, File base) throws IOException, DocumentException { checkInputStream(in); try { SAXBugCollectionHandler handler = new SAXBugCollectionHandler(this, project, base); XMLReader xr = null; if (true) try { xr = XMLReaderFactory.createXMLReader(); } catch (SAXException e) { AnalysisContext.logError("Couldn't create XMLReaderFactory", e); } if (xr == null) { xr = new org.dom4j.io.aelfred.SAXDriver(); } xr.setContentHandler(handler); xr.setErrorHandler(handler); Reader reader = Util.getReader(in); xr.parse(new InputSource(reader)); } catch (SAXParseException e) { throw new DocumentException("Parse error at line " + e.getLineNumber() + " : " + e.getColumnNumber(), e); } catch (SAXException e) { // FIXME: throw SAXException from method? throw new DocumentException("Sax error ", e); } finally { in.close(); } // Presumably, project is now up-to-date project.setModified(false); } /** * Write this BugCollection to a file as XML. * * @param fileName the file to write to * @param project the Project from which the BugCollection was generated */ public void writeXML(String fileName, Project project) throws IOException { BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName)); writeXML(out, project); } /** * Write this BugCollection to a file as XML. * * @param file the file to write to * @param project the Project from which the BugCollection was generated */ public void writeXML(File file, Project project) throws IOException { BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); writeXML(out, project); } /** * Convert the BugCollection into a dom4j Document object. * * @param project the Project from which the BugCollection was generated * @return the Document representing the BugCollection as a dom4j tree */ public Document toDocument(Project project) { if (project == null) throw new NullPointerException("No project"); DocumentFactory docFactory = new DocumentFactory(); Document document = docFactory.createDocument(); Dom4JXMLOutput treeBuilder = new Dom4JXMLOutput(document); try { writeXML(treeBuilder, project); } catch (IOException e) { // Can't happen } return document; } /** * Write the BugCollection to given output stream as XML. * The output stream will be closed, even if an exception is thrown. * * @param out the OutputStream to write to * @param project the Project from which the BugCollection was generated */ public void writeXML(OutputStream out, Project project) throws IOException { XMLOutput xmlOutput; if (project == null) throw new NullPointerException("No project"); if (withMessages) xmlOutput= new OutputStreamXMLOutput(out, "http://findbugs.sourceforge.net/xsl/default.xsl"); else xmlOutput= new OutputStreamXMLOutput(out); writeXML(xmlOutput, project); } public void writePrologue(XMLOutput xmlOutput, Project project) throws IOException { xmlOutput.beginDocument(); xmlOutput.openTag(ROOT_ELEMENT_NAME, new XMLAttributeList() .addAttribute("version", analysisVersion) .addAttribute("sequence",String.valueOf(getSequenceNumber())) .addAttribute("timestamp", String.valueOf(getTimestamp())) .addAttribute("analysisTimestamp", String.valueOf(getAnalysisTimestamp())) .addAttribute("release", getReleaseName()) ); project.writeXML(xmlOutput); } private String getQuickInstanceHash(BugInstance bugInstance) { String hash = bugInstance.getInstanceHash(); if (hash != null) return hash; MessageDigest digest = null; try { digest = MessageDigest.getInstance("MD5"); } catch (Exception e2) { // OK, we won't digest assert true; } hash = bugInstance.getInstanceKey(); if (digest != null) { byte [] data = digest.digest(hash.getBytes()); String tmp = new BigInteger(1,data).toString(16); if (false) System.out.println(hash + " -> " + tmp); hash = tmp; } bugInstance.setInstanceHash(hash); return hash; } public void computeBugHashes() { if (preciseHashOccurrenceNumbersAvailable) return; invalidateHashes(); MessageDigest digest = null; try { digest = MessageDigest.getInstance("MD5"); } catch (Exception e2) { // OK, we won't digest } HashMap<String, Integer> seen = new HashMap<String, Integer>(); for(BugInstance bugInstance : getCollection()) { String hash = bugInstance.getInstanceHash(); if (hash == null) { hash = bugInstance.getInstanceKey(); if (digest != null) { byte [] data = digest.digest(hash.getBytes()); String tmp = new BigInteger(1,data).toString(16); if (false) System.out.println(hash + " -> " + tmp); hash = tmp; } bugInstance.setInstanceHash(hash); } Integer count = seen.get(hash); if (count == null) { bugInstance.setInstanceOccurrenceNum(0); seen.put(hash,0); } else { bugInstance.setInstanceOccurrenceNum(count+1); seen.put(hash, count+1); } } for(BugInstance bugInstance : getCollection()) bugInstance.setInstanceOccurrenceMax(seen.get(bugInstance.getInstanceHash())); preciseHashOccurrenceNumbersAvailable = true; } /** * Write the BugCollection to an XMLOutput object. * The finish() method of the XMLOutput object is guaranteed * to be called. * * <p> * To write the SummaryHTML element, set property * findbugs.report.SummaryHTML to "true". * </p> * * @param xmlOutput the XMLOutput object * @param project the Project from which the BugCollection was generated */ public void writeXML(XMLOutput xmlOutput, @NonNull Project project) throws IOException { if (project == null) throw new NullPointerException("No project"); try { writePrologue(xmlOutput, project); if (withMessages) computeBugHashes(); // Write BugInstances for(BugInstance bugInstance : getCollection()) bugInstance.writeXML(xmlOutput, withMessages); writeEpilogue(xmlOutput); } finally { xmlOutput.finish(); } } public void writeEpilogue(XMLOutput xmlOutput) throws IOException { if (withMessages) { writeBugCategories( xmlOutput); writeBugPatterns( xmlOutput); writeBugCodes( xmlOutput); } // Errors, missing classes emitErrors(xmlOutput); // Statistics getProjectStats().writeXML(xmlOutput);// // Class and method hashes// xmlOutput.openTag(CLASS_HASHES_ELEMENT_NAME);// for (Iterator<ClassHash> i = classHashIterator(); i.hasNext();) {// ClassHash classHash = i.next();// classHash.writeXML(xmlOutput);// }// xmlOutput.closeTag(CLASS_HASHES_ELEMENT_NAME); // Class features xmlOutput.openTag("ClassFeatures"); for (Iterator<ClassFeatureSet> i = classFeatureSetIterator(); i.hasNext();) { ClassFeatureSet classFeatureSet = i.next(); classFeatureSet.writeXML(xmlOutput); } xmlOutput.closeTag("ClassFeatures"); // AppVersions xmlOutput.openTag(HISTORY_ELEMENT_NAME); for (Iterator<AppVersion> i = appVersionIterator(); i.hasNext();) { AppVersion appVersion = i.next(); appVersion.writeXML(xmlOutput); } xmlOutput.closeTag(HISTORY_ELEMENT_NAME); // Summary HTML if ( REPORT_SUMMARY_HTML ) { String html = getSummaryHTML(); if (html != null && !html.equals("")) { xmlOutput.openTag(SUMMARY_HTML_ELEMENT_NAME); xmlOutput.writeCDATA(html); xmlOutput.closeTag(SUMMARY_HTML_ELEMENT_NAME); } } xmlOutput.closeTag(ROOT_ELEMENT_NAME); } private void writeBugPatterns(XMLOutput xmlOutput) throws IOException { // Find bug types reported Set<String> bugTypeSet = new HashSet<String>(); for (Iterator<BugInstance> i = iterator(); i.hasNext();) { BugInstance bugInstance = i.next(); BugPattern bugPattern = bugInstance.getBugPattern(); if (bugPattern != null) { bugTypeSet.add(bugPattern.getType()); } } // Emit element describing each reported bug pattern for (String bugType : bugTypeSet) { BugPattern bugPattern = I18N.instance().lookupBugPattern(bugType); if (bugPattern == null) continue; XMLAttributeList attributeList = new XMLAttributeList(); attributeList.addAttribute("type", bugType); attributeList.addAttribute("abbrev", bugPattern.getAbbrev()); attributeList.addAttribute("category", bugPattern.getCategory()); xmlOutput.openTag("BugPattern", attributeList); xmlOutput.openTag("ShortDescription"); xmlOutput.writeText(bugPattern.getShortDescription()); xmlOutput.closeTag("ShortDescription"); xmlOutput.openTag("Details"); xmlOutput.writeCDATA(bugPattern.getDetailText()); xmlOutput.closeTag("Details"); xmlOutput.closeTag("BugPattern"); } } private void writeBugCodes(XMLOutput xmlOutput) throws IOException { // Find bug codes reported Set<String> bugCodeSet = new HashSet<String>(); for (Iterator<BugInstance> i = iterator(); i.hasNext();) { BugInstance bugInstance = i.next(); String bugCode = bugInstance.getAbbrev(); if (bugCode != null) { bugCodeSet.add(bugCode); } } // Emit element describing each reported bug code for (String bugCode : bugCodeSet) { String bugCodeDescription = I18N.instance().getBugTypeDescription(bugCode); if (bugCodeDescription == null) continue; XMLAttributeList attributeList = new XMLAttributeList(); attributeList.addAttribute("abbrev", bugCode); xmlOutput.openTag("BugCode", attributeList); xmlOutput.openTag("Description"); xmlOutput.writeText(bugCodeDescription); xmlOutput.closeTag("Description"); xmlOutput.closeTag("BugCode");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -