001: /*
002: *****************************************************************************
003: * Copyright (C) 2000-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *****************************************************************************
006: */
007: package com.ibm.rbm;
008:
009: import java.io.*;
010: import java.util.*;
011:
012: import org.apache.xerces.parsers.DOMParser;
013: import org.w3c.dom.*;
014: import org.xml.sax.*;
015:
016: /**
017: * RBReporterScaner is a utility class for RBReporter. It creates a report from an xml settings
018: * file that scans code for resources and compares them against a resource bundle.
019: *
020: * @author Jared Jackson
021: * @see com.ibm.rbm.RBReporter
022: */
023: public class RBReporterScanner {
024: private Bundle bundle;
025: private Document config;
026: private Hashtable fileRules;
027: private Hashtable parseRules;
028: private Hashtable results;
029: private Hashtable missing;
030: private boolean resultsFound;
031:
032: protected RBReporterScanner(Bundle bundle, File configFile) throws IOException {
033: resultsFound = false;
034: this .bundle = bundle;
035:
036: try {
037: InputSource is = new InputSource(new FileInputStream(configFile));
038: DOMParser parser = new DOMParser();
039: parser.parse(is);
040: config = parser.getDocument();
041: } catch (SAXException saxe) {
042: throw new IOException("Illegal XML Document: " + saxe.getMessage());
043: }
044:
045: Element root = config.getDocumentElement();
046: fileRules = getFileRules(root);
047: parseRules = getParseRules(root);
048:
049: results = new Hashtable();
050: Enumeration enum = bundle.allItems.keys();
051: while (enum.hasMoreElements()) {
052: String key = (String)enum.nextElement();
053: BundleItem item = (BundleItem)bundle.allItems.get(key);
054: results.put(key, new ScanResult(item));
055: }
056:
057: missing = new Hashtable();
058: }
059:
060: protected int getNumberResourcesFound() {
061: return results.size();
062: }
063:
064: protected int getNumberMissingResources() {
065: return missing.size();
066: }
067:
068: protected int getNumberUnusedResources() {
069: int count = 0;
070: Enumeration enum = results.elements();
071: while (enum.hasMoreElements()) {
072: ScanResult result = (ScanResult)enum.nextElement();
073: if (result.getOccurances().size() < 1) count++;
074: }
075: return count;
076: }
077:
078: protected Vector getMissingResources() {
079: Enumeration enum = missing.elements();
080: Vector v = new Vector();
081: while (enum.hasMoreElements()) v.addElement(enum.nextElement());
082: return v;
083: }
084:
085: protected Vector getUnusedResources() {
086: Enumeration enum = results.elements();
087: Vector v = new Vector();
088: while (enum.hasMoreElements()) {
089: ScanResult result = (ScanResult)enum.nextElement();
090: if (result.getOccurances().size() < 1) {
091: v.addElement(result);
092: }
093: }
094: return v;
095: }
096:
097: protected boolean performScan() throws IOException {
098: resultsFound = false;
099:
100: Element root = config.getDocumentElement();
101: NodeList nl = root.getElementsByTagName("Scan");
102: if (nl.getLength() < 1)
103: return resultsFound;
104: Element scan_elem = (Element) nl.item(0);
105: nl = scan_elem.getElementsByTagName("Directory");
106: for (int i = 0; i < nl.getLength(); i++) {
107: Element dir_elem = (Element) nl.item(i);
108: File directory = new File(dir_elem.getAttribute("location"));
109: boolean recurse = dir_elem.getAttribute(
110: "recurse_directories").equalsIgnoreCase("true");
111: NodeList rules_list = dir_elem
112: .getElementsByTagName("Rules");
113: if (rules_list.getLength() < 1)
114: continue;
115: Element rules_elem = (Element) rules_list.item(0);
116: NodeList frules_list = rules_elem
117: .getElementsByTagName("ApplyFileRule");
118: // For each file rule
119: for (int j = 0; j < frules_list.getLength(); j++) {
120: Element frule_elem = (Element) frules_list.item(j);
121: FileRule frule = (FileRule) fileRules.get(frule_elem
122: .getAttribute("name"));
123: if (frule == null)
124: continue;
125: NodeList prules_list = frule_elem
126: .getElementsByTagName("ApplyParseRule");
127: Vector prules_v = new Vector();
128: // For each parse rule
129: for (int k = 0; k < prules_list.getLength(); k++) {
130: Element prule_elem = (Element) prules_list.item(k);
131: ParseRule prule = (ParseRule) parseRules
132: .get(prule_elem.getAttribute("name"));
133: if (prule == null)
134: continue;
135: prules_v.addElement(prule);
136: }
137: if (prules_v.size() < 1)
138: continue;
139: scanDirectory(directory, frule, prules_v, recurse);
140: }
141: }
142:
143: return resultsFound;
144: }
145:
146: private void scanDirectory(File directory, FileRule frule,
147: Vector prules, boolean recurse) throws IOException {
148:
149: // Recursion step
150: if (recurse) {
151: File children[] = directory
152: .listFiles(new java.io.FileFilter() {
153: public boolean accept(File f) {
154: return f.isDirectory();
155: }
156:
157: public String getDescription() {
158: return "";
159: }
160: });
161: for (int i = 0; i < children.length; i++) {
162: File new_directory = children[i];
163: scanDirectory(new_directory, frule, prules, recurse);
164: }
165: }
166: // Go through each acceptable file
167: File children[] = directory.listFiles();
168: for (int i = 0; i < children.length; i++) {
169: File f = children[i];
170: if (f.isDirectory() || !(frule.applyRule(f.getName())))
171: continue;
172: FileReader fr = new FileReader(f);
173: BufferedReader br = new BufferedReader(fr);
174: String line = null;
175: int line_count = 0;
176: // Read the file line by line
177: while ((line = br.readLine()) != null) {
178: line_count++;
179: Vector findings = new Vector();
180: // Apply all parse rules to each line
181: for (int j = 0; j < prules.size(); j++) {
182: ParseRule prule = (ParseRule) prules.elementAt(j);
183: Vector temp_results = prule.applyRule(line);
184: for (int k = 0; k < temp_results.size(); k++) {
185: findings.addElement(temp_results.elementAt(k));
186: }
187: }
188: for (int j = 0; j < findings.size(); j++) {
189: String name = (String) findings.elementAt(j);
190: Occurance occ = new Occurance(f.getName(), f
191: .getAbsolutePath(), line_count);
192: // If the name is found in the resource bundles derived hashtable
193: if (results.containsKey(name)) {
194: ScanResult scan_res = (ScanResult) results
195: .get(name);
196: scan_res.addOccurance(occ);
197: } else {
198: // Add it to the missing results
199: ScanResult scan_res = new ScanResult(
200: new BundleItem(null, name, "*unknown*"));
201: scan_res.addOccurance(occ);
202: missing.put(name, scan_res);
203: results.put(name, scan_res);
204: }
205: }
206: }
207: }
208: }
209:
210: private Hashtable getFileRules(Element root) {
211: Hashtable result = new Hashtable();
212: NodeList frules_list = root.getElementsByTagName("FileRules");
213: Element frules_elem = null;
214: if (frules_list.getLength() > 0)
215: frules_elem = (Element) frules_list.item(0);
216: if (frules_elem == null)
217: return result;
218: frules_list = frules_elem.getElementsByTagName("FileRule");
219: for (int i = 0; i < frules_list.getLength(); i++) {
220: Element elem = (Element) frules_list.item(i);
221: FileRule frule = new FileRule(elem.getAttribute("name"),
222: elem.getAttribute("starts_with"), elem
223: .getAttribute("ends_with"), elem
224: .getAttribute("contains"));
225: result.put(elem.getAttribute("name"), frule);
226: }
227: return result;
228: }
229:
230: private Hashtable getParseRules(Element root) {
231: Hashtable result = new Hashtable();
232: NodeList prules_list = root.getElementsByTagName("ParseRules");
233: Element prules_elem = null;
234: if (prules_list.getLength() > 0)
235: prules_elem = (Element) prules_list.item(0);
236: if (prules_elem == null)
237: return result;
238: prules_list = prules_elem.getElementsByTagName("ParseRule");
239: for (int i = 0; i < prules_list.getLength(); i++) {
240: Element elem = (Element) prules_list.item(i);
241: ParseRule prule = new ParseRule(elem.getAttribute("name"),
242: elem.getAttribute("follows"), elem
243: .getAttribute("precedes"));
244: result.put(elem.getAttribute("name"), prule);
245: }
246: return result;
247: }
248: }
249:
250: class FileRule {
251: String name;
252: String starts_with;
253: String ends_with;
254: String contains;
255:
256: FileRule(String name, String starts_with, String ends_with,
257: String contains) {
258: this .name = name;
259: this .starts_with = starts_with;
260: this .ends_with = ends_with;
261: this .contains = contains;
262: }
263:
264: boolean applyRule(String source) {
265: boolean accept = true;
266: if (starts_with != null && starts_with.length() > 0
267: && !(source.startsWith(starts_with)))
268: accept = false;
269: if (ends_with != null && ends_with.length() > 0
270: && !(source.endsWith(ends_with)))
271: accept = false;
272: if (contains != null && contains.length() > 0
273: && source.indexOf(contains) < 0)
274: accept = false;
275: return accept;
276: }
277: }
278:
279: class ParseRule {
280: String name;
281: String before;
282: String after;
283:
284: ParseRule(String name, String before, String after) {
285: this .name = name;
286: this .before = before;
287: this .after = after;
288: }
289:
290: // returns the vector of strings found after before and before after
291:
292: Vector applyRule(String source) {
293: Vector v = new Vector();
294: if (before != null && before.length() > 0) {
295: if (after != null && after.length() > 0) {
296: // Both before and after non-empty
297: int before_index = -1;
298: int after_index = -1;
299: while ((before_index = source.indexOf(before,
300: ++before_index)) >= 0) {
301: //before_index = source.indexOf(before, before_index);
302: after_index = -1;
303: after_index = source.indexOf(after, before_index
304: + before.length() + 1);
305: if (after_index < 0 || before_index < 0
306: || before.length() < 0) {
307: break;
308: }
309: v.addElement(source.substring(before_index
310: + before.length(), after_index));
311: before_index = after_index;
312: }
313: } else {
314: // Before non-empty, after empty
315: int index = -1;
316: while (source.indexOf(before, ++index) >= 0) {
317: index = source.indexOf(before, index);
318: String result = source.substring(index
319: + before.length(), source.length());
320: if (result != null && result.length() > 0)
321: v.addElement(result);
322: }
323: }
324: } else if (after != null && after.length() > 0) {
325: // Before empty, after not
326: int index = -1;
327: while (source.indexOf(after, ++index) >= 0) {
328: index = source.indexOf(before, index);
329: String result = source.substring(0, index);
330: if (result != null && result.length() > 0)
331: v.addElement(result);
332: }
333: } else {
334: // Before and after empty
335: v.addElement(source);
336: }
337: return v;
338: }
339: }
|