001: package tide.exttools.findbugs;
002:
003: import java.io.*;
004: import java.util.*;
005: import org.xml.sax.*;
006: import org.xml.sax.helpers.DefaultHandler;
007: import javax.xml.parsers.SAXParserFactory; //import javax.xml.parsers.ParserConfigurationException;
008: import javax.xml.parsers.SAXParser;
009: import snow.utils.storage.FileUtils;
010:
011: /**
012: Reads the xml bugs database and produce an output
013: */
014: public class FindBugsReader extends DefaultHandler {
015: private final static boolean debug = false;
016:
017: // the error messages read from the messages.xml file (present in the findbug source project)
018: private final StringBuilder summaryHTML = new StringBuilder();
019: private boolean summaryHTMLPart = false;
020:
021: private final StringBuilder readChars = new StringBuilder();
022:
023: private final List<FindBugsTag.AnalysisError> analysisErrors = new ArrayList<FindBugsTag.AnalysisError>();
024: private final List<FindBugsTag.MissingClass> missingClasses = new ArrayList<FindBugsTag.MissingClass>();
025:
026: Errors errors = new Errors();
027: boolean isInErrors = false;
028:
029: private final FindBugsSummary findBugsSummary = new FindBugsSummary();
030: boolean isInSummary = false;
031:
032: private final Map<String, Integer> priorityCount = new Hashtable<String, Integer>();
033: private final Map<String, Integer> categoryCount = new Hashtable<String, Integer>();
034:
035: //int showPrioritiesUpTo = 3;
036:
037: public FindBugsReader(final File fileToRead) throws Exception {
038: // this.showPrioritiesUpTo = showPrioritiesUpTo;
039:
040: this .ignored = 0;
041:
042: // Use the default (non-validating) parser
043: SAXParserFactory factory = SAXParserFactory.newInstance();
044:
045: // Parse the file
046: SAXParser saxParser = factory.newSAXParser();
047: saxParser.parse(fileToRead.getAbsolutePath(), this );
048: }
049:
050: public String toStringStatShort() {
051:
052: StringBuilder sb = new StringBuilder();
053: sb.append("" + this .bugs.size() + " bugs: (");
054: Vector<String> keys = new Vector<String>(this .priorityCount
055: .keySet());
056: Collections.sort(keys);
057: for (String cat : keys) {
058: sb.append("prior " + cat + ": " + priorityCount.get(cat)
059: + ", ");
060: }
061: sb.setLength(sb.length() - 2);
062: sb.append(")");
063: return sb.toString();
064: }
065:
066: public String toStringStatistics() {
067: StringBuilder sb = new StringBuilder();
068:
069: sb.append("" + bugs.size() + " possible bugs were detected");
070: if (ignored > 0) {
071: sb.append("" + ignored + " ignored messages");
072: }
073: //sb.append("\r\nAll encountered categories=\r\n"+includeTree);
074:
075: if (bugs.isEmpty())
076: return "No bugs found";
077:
078: if (this .analysisErrors.size() > 0) {
079: sb.append("\r\n\r\n" + this .analysisErrors.size()
080: + " Analysis errors: ");
081: for (FindBugsTag.AnalysisError ae : analysisErrors) {
082: sb.append("\r\n" + ae.toString());
083: }
084: }
085:
086: if (this .missingClasses.size() > 0) {
087: sb.append("\r\n\r\n" + this .missingClasses.size()
088: + " Missing classes");
089: for (FindBugsTag.MissingClass mc : missingClasses) {
090: sb.append("\r\n" + mc.toString());
091: }
092: }
093:
094: sb.append("\r\n\r\nPriorities count:");
095: Vector<String> keys = new Vector<String>(this .priorityCount
096: .keySet());
097: Collections.sort(keys);
098: for (String cat : keys) {
099: int cnt = priorityCount.get(cat);
100: sb.append("\r\n\tpriority " + cat + ": \t" + cnt);
101: }
102:
103: // categories overview categoryCount
104: sb.append("\r\n\r\nCategories count:");
105: keys = new Vector<String>(this .categoryCount.keySet());
106: Collections.sort(keys);
107: for (String cati : keys) {
108: int cnt = categoryCount.get(cati);
109: sb.append("\r\n\t" + cnt + ": \t" + cati);
110: }
111:
112: return sb.toString();
113: }
114:
115: @Override
116: public String toString() {
117: StringBuilder sb = new StringBuilder();//"==================== FindBugs Result =====================\r\n");
118:
119: sb.append(toStringStatistics());
120:
121: //sb.append("\r\n");
122:
123: for (BugInstance b : bugs) {
124: sb.append("\r\n" + b.toString()); // messages
125: }
126:
127: return sb.toString();
128: }
129:
130: private final List<BugInstance> bugs = new Vector<BugInstance>();
131:
132: public List<BugInstance> getBugs() {
133: return bugs;
134: }
135:
136: //===========================================================
137: // SAX DocumentHandler methods
138: //===========================================================
139:
140: @Override
141: public void startDocument() {
142: }
143:
144: @Override
145: public void endDocument() {
146: }
147:
148: private BugInstance actualBug = null;
149:
150: @Override
151: public void startElement(String namespaceURI, String lName, // local name
152: String qName, // qualified name
153: Attributes attrs) throws SAXException {
154: if (qName.equals("BugCollection") || qName.equals("Project")) {
155: } else if (qName.equals("BugInstance")) {
156: // create a new bug instance
157: actualBug = new BugInstance(qName, attrs);
158: } else if (qName.equals("Errors")) {
159: isInErrors = true;
160: }
161: /* else if(qName.equals("MissingClass"))
162: {
163: // empty the buffer to catch the message
164: String lr = this.getLastReadChars().trim();
165: if(lr.length()>0)
166: {
167: System.out.println(""+lr.length()+" unread chars (MissingClass)");
168: }
169: }*/
170: else if (qName.equals("AnalysisError")) {
171: // empty the buffer to catch the message
172: String lr = this .getLastReadChars().trim();
173: if (lr.length() > 0) {
174: if (debug)
175: System.out.println("" + lr.length()
176: + " unread chars (AnalysisError)");
177: }
178: } else if (qName.equals("SummaryHTML")) {
179: this .summaryHTMLPart = true;
180: } else if (qName.equals("FindBugsSummary")) {
181: isInSummary = true;
182: } else // delegates
183: {
184: // add data
185: if (actualBug != null) {
186: actualBug.startElement(namespaceURI, lName, qName,
187: attrs);
188: } else if (isInSummary) {
189: this .findBugsSummary.startElement(namespaceURI, lName,
190: qName, attrs);
191: } else if (isInErrors) {
192: this .errors.startElement(namespaceURI, lName, qName,
193: attrs);
194: } else {
195: if (debug) {
196: System.out.println("\n<? " + qName + ">");
197: if (lName.length() > 0)
198: System.out.println(" local name=" + lName);
199: if (namespaceURI.length() > 0)
200: System.out.println(" name space="
201: + namespaceURI);
202: for (int i = 0; i < attrs.getLength(); i++) {
203: String qname = attrs.getQName(i);
204: String val = attrs.getValue(qname);
205: System.out.println(" Attr " + qname + "= "
206: + val);
207: }
208: }
209: }
210: }
211: }
212:
213: int ignored = 0;
214:
215: @Override
216: public void endElement(String namespaceURI, String sName, // simple name
217: String qName // qualified name
218: ) throws SAXException {
219: if (qName.equals("BugCollection") || qName.equals("Project")) {
220: } else if (qName.equals("BugInstance")) {
221: if (actualBug != null) {
222: boolean accept = true;
223: /*
224: if(actualBug.getPriority()>this.showPrioritiesUpTo)
225: {
226: accept = false;
227: }*/
228:
229: if (accept) {
230: bugs.add(actualBug);
231:
232: // count
233: if (!this .priorityCount
234: .containsKey(actualBug.priority)) {
235: priorityCount.put(actualBug.priority, 1);
236: } else {
237: int n = priorityCount.get(actualBug.priority);
238: priorityCount.put(actualBug.priority, n + 1);
239: }
240:
241: if (!categoryCount.containsKey(actualBug.category)) {
242: categoryCount.put(actualBug.category, 1);
243: } else {
244: categoryCount
245: .put(actualBug.category, categoryCount
246: .get(actualBug.category) + 1);
247: }
248: } else {
249: ignored++;
250: }
251:
252: actualBug = null;
253: }
254: } else if (qName.equals("Errors")) {
255: this .isInErrors = false;
256: } else if (qName.equals("AnalysisError")) {
257: analysisErrors.add(new FindBugsTag.AnalysisError(
258: getLastReadChars()));
259: } else if (qName.equals("SummaryHTML")) {
260: // save to file
261: //
262: this .summaryHTMLPart = false;
263:
264: try {
265: FileUtils.saveToFile(this .summaryHTML.toString(),
266: new File("c:/temp/sp.html"));
267: } catch (Exception e) {
268: e.printStackTrace();
269: }
270: } else if (qName.equals("FindBugsSummary")) {
271: this .isInSummary = false;
272: } else {
273: // delegates
274: if (actualBug != null) {
275: actualBug.endElement(namespaceURI, sName, qName);
276: } else if (isInSummary) {
277: this .findBugsSummary.endElement(namespaceURI, sName,
278: qName);
279: } else if (isInErrors) {
280: this .errors.endElement(namespaceURI, sName, qName);
281: } else {
282: if (debug) {
283: System.out.println("End of ? " + qName);
284: }
285: }
286: }
287:
288: }
289:
290: private String getLastReadChars() {
291: String read = this .readChars.toString();
292: this .readChars.delete(0, readChars.length()); // erase
293: return read;
294: }
295:
296: @Override
297: public void characters(char[] buf, int offset, int len)
298: throws SAXException {
299: if (this .actualBug != null) {
300: actualBug.characters(buf, offset, len);
301: return;
302: }
303:
304: String s = new String(buf, offset, len);
305: //System.out.print("Chars="+s);
306: if (summaryHTMLPart) {
307: summaryHTML.append(s);
308: }
309:
310: else {
311: readChars.append(s);
312: /* if(s.trim().length()>0)
313: {
314: System.out.println("Chars: "+s);
315: }*/
316: }
317: }
318:
319: }
|