KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > tools > xml > CheckMessages


1 /*
2  * Check FindBugs XML message files
3  * Copyright (C) 2004, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.tools.xml;
21
22 import java.io.File JavaDoc;
23 import java.net.MalformedURLException JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import org.dom4j.Attribute;
29 import org.dom4j.Document;
30 import org.dom4j.DocumentException;
31 import org.dom4j.Element;
32 import org.dom4j.Node;
33 import org.dom4j.io.SAXReader;
34
35 /**
36  * Ensure that the XML messages files in a FindBugs plugin
37  * are valid and complete.
38  */

39 public class CheckMessages {
40
41     private static class CheckMessagesException extends DocumentException {
42         /**
43          *
44          */

45         private static final long serialVersionUID = 1L;
46
47         public CheckMessagesException(String JavaDoc msg, XMLFile xmlFile, Node node) {
48             super("In " + xmlFile.getFilename() + ", " + node.toString() + ": " + msg);
49         }
50
51         public CheckMessagesException(String JavaDoc msg, XMLFile xmlFile) {
52             super("In " + xmlFile.getFilename() + ": " + msg);
53         }
54     }
55
56     private static class XMLFile {
57         private String JavaDoc filename;
58         private Document document;
59
60         public XMLFile(String JavaDoc filename) throws DocumentException, MalformedURLException JavaDoc {
61             this.filename = filename;
62
63             File JavaDoc file = new File JavaDoc(filename);
64             SAXReader saxReader = new SAXReader();
65             this.document = saxReader.read(file);
66         }
67
68         public String JavaDoc getFilename() { return filename; }
69
70         public Document getDocument() { return document; }
71
72         /**
73          * Get iterator over Nodes selected by
74          * given XPath expression.
75          */

76         public Iterator JavaDoc<Node> xpathIterator(String JavaDoc xpath) {
77             return document.selectNodes(xpath).iterator();
78         }
79
80         /**
81          * Build collection of the values of given attribute
82          * in all nodes matching given XPath expression.
83          */

84         public Set JavaDoc<String JavaDoc> collectAttributes(String JavaDoc xpath, String JavaDoc attrName)
85             throws DocumentException {
86             Set JavaDoc<String JavaDoc> result = new HashSet JavaDoc<String JavaDoc>();
87
88             for (Iterator JavaDoc<Node> i = xpathIterator(xpath); i.hasNext(); ) {
89                 Node node = i.next();
90                 String JavaDoc value = checkAttribute(node, attrName).getValue();
91                 result.add(value);
92             }
93
94             return result;
95         }
96
97         public Attribute checkAttribute(Node node, String JavaDoc attrName) throws DocumentException {
98             if (!(node instanceof Element))
99                 throw new CheckMessagesException("Node is not an element", this, node);
100             Element element = (Element) node;
101             Attribute attr = element.attribute(attrName);
102             if (attr == null)
103                 throw new CheckMessagesException("Missing " + attrName + " attribute", this, node);
104             return attr;
105         }
106
107         public Element checkElement(Node node, String JavaDoc elementName) throws DocumentException {
108             if (!(node instanceof Element))
109                 throw new CheckMessagesException("Node is not an element", this, node);
110             Element element = (Element) node;
111             Element child = element.element(elementName);
112             if (child == null)
113                 throw new CheckMessagesException("Missing " + elementName + " element", this, node);
114             return child;
115         }
116
117         public String JavaDoc checkNonEmptyText(Node node) throws DocumentException {
118             if (!(node instanceof Element))
119                 throw new CheckMessagesException("Node is not an element", this, node);
120             Element element = (Element) node;
121             String JavaDoc text = element.getText();
122             if (text.equals(""))
123                 throw new CheckMessagesException("Empty text in element", this, node);
124             return text;
125         }
126     }
127
128     private Set JavaDoc<String JavaDoc> declaredDetectorsSet;
129     private Set JavaDoc<String JavaDoc> declaredAbbrevsSet;
130
131     public CheckMessages(String JavaDoc pluginDescriptorFilename)
132         throws DocumentException, MalformedURLException JavaDoc {
133
134         XMLFile pluginDescriptorDoc = new XMLFile(pluginDescriptorFilename);
135
136         declaredDetectorsSet =
137             pluginDescriptorDoc.collectAttributes("/FindbugsPlugin/Detector", "class");
138
139         declaredAbbrevsSet =
140             pluginDescriptorDoc.collectAttributes("/FindbugsPlugin/BugPattern", "abbrev");
141     }
142
143     /**
144      * Check given messages file for validity.
145      * @throws DocumentException if the messages file is invalid
146      */

147     public void checkMessages(XMLFile messagesDoc) throws DocumentException {
148         // Detector elements must all have a class attribute
149
// and details child element.
150
for (Iterator JavaDoc<Node> i = messagesDoc.xpathIterator("/MessageCollection/Detector"); i.hasNext(); ) {
151             Node node = i.next();
152             messagesDoc.checkAttribute(node, "class");
153             messagesDoc.checkElement(node, "Details");
154         }
155
156         // BugPattern elements must all have type attribute
157
// and ShortDescription, LongDescription, and Details
158
// child elements.
159
for (Iterator JavaDoc<Node> i = messagesDoc.xpathIterator("/MessageCollection/BugPattern"); i.hasNext(); ) {
160             Node node = i.next();
161             messagesDoc.checkAttribute(node, "type");
162             messagesDoc.checkElement(node, "ShortDescription");
163             messagesDoc.checkElement(node, "LongDescription");
164             messagesDoc.checkElement(node, "Details");
165         }
166
167         // BugCode elements must contain abbrev attribute
168
// and have non-empty text
169
for (Iterator JavaDoc<Node> i = messagesDoc.xpathIterator("/MessageCollection/BugCode"); i.hasNext(); ) {
170             Node node = i.next();
171             messagesDoc.checkAttribute(node, "abbrev");
172             messagesDoc.checkNonEmptyText(node);
173         }
174
175         // Check that all Detectors are described
176
Set JavaDoc<String JavaDoc> describedDetectorsSet =
177             messagesDoc.collectAttributes("/MessageCollection/Detector", "class");
178         checkDescribed("Bug detectors not described by Detector elements",
179             messagesDoc, declaredDetectorsSet, describedDetectorsSet);
180
181         // Check that all BugCodes are described
182
Set JavaDoc<String JavaDoc> describedAbbrevsSet =
183             messagesDoc.collectAttributes("/MessageCollection/BugCode", "abbrev");
184         checkDescribed("Abbreviations not described by BugCode elements",
185             messagesDoc, declaredAbbrevsSet, describedAbbrevsSet);
186     }
187
188     public void checkDescribed(String JavaDoc description, XMLFile xmlFile,
189         Set JavaDoc<String JavaDoc> declared, Set JavaDoc<String JavaDoc> described) throws DocumentException {
190
191         Set JavaDoc<String JavaDoc> notDescribed = new HashSet JavaDoc<String JavaDoc>();
192         notDescribed.addAll(declared);
193         notDescribed.removeAll(described);
194
195         if (!notDescribed.isEmpty())
196             throw new CheckMessagesException(description + ": " + notDescribed.toString(), xmlFile);
197     }
198
199     public static void main(String JavaDoc[] argv) throws Exception JavaDoc {
200         if (argv.length < 2) {
201             System.err.println("Usage: " + CheckMessages.class.getName() +
202                 " <plugin descriptor xml> <bug description xml> [<bug description xml>...]");
203             System.exit(1);
204         }
205
206         String JavaDoc pluginDescriptor = argv[0];
207
208         try {
209             CheckMessages checkMessages = new CheckMessages(pluginDescriptor);
210             for (int i = 1; i < argv.length; ++i) {
211                 String JavaDoc messagesFile = argv[i];
212                 System.out.println("Checking messages file " + messagesFile);
213                 checkMessages.checkMessages(new XMLFile(messagesFile));
214             }
215         } catch (DocumentException e) {
216             System.err.println("Could not verify messages files: " + e.getMessage());
217             System.exit(1);
218         }
219
220         System.out.println("Messages files look OK!");
221     }
222 }
223
224 // vim:ts=3
225
Popular Tags