1 /* 2 ***************************************************************************** 3 * Copyright (C) 2000-2007, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ***************************************************************************** 6 */ 7 package com.ibm.rbm; 8 9 10 import java.io.*; 11 import java.util.*; 12 13 import org.apache.xerces.parsers.DOMParser; 14 import org.w3c.dom.*; 15 import org.xml.sax.*; 16 17 /** 18 * RBReporterScaner is a utility class for RBReporter. It creates a report from an xml settings 19 * file that scans code for resources and compares them against a resource bundle. 20 * 21 * @author Jared Jackson 22 * @see com.ibm.rbm.RBReporter 23 */ 24 public class RBReporterScanner { 25 private Bundle bundle; 26 private Document config; 27 private Hashtable fileRules; 28 private Hashtable parseRules; 29 private Hashtable results; 30 private Hashtable missing; 31 private boolean resultsFound; 32 RBReporterScanner(Bundle bundle, File configFile)33 protected RBReporterScanner(Bundle bundle, File configFile) throws IOException { 34 resultsFound = false; 35 this.bundle = bundle; 36 37 try { 38 InputSource is = new InputSource(new FileInputStream(configFile)); 39 DOMParser parser = new DOMParser(); 40 parser.parse(is); 41 config = parser.getDocument(); 42 } catch (SAXException saxe) { 43 throw new IOException("Illegal XML Document: " + saxe.getMessage()); 44 } 45 46 Element root = config.getDocumentElement(); 47 fileRules = getFileRules(root); 48 parseRules = getParseRules(root); 49 50 results = new Hashtable(); 51 Enumeration keys = bundle.allItems.keys(); 52 while (keys.hasMoreElements()) { 53 String key = (String)keys.nextElement(); 54 BundleItem item = (BundleItem)bundle.allItems.get(key); 55 results.put(key, new ScanResult(item)); 56 } 57 58 missing = new Hashtable(); 59 } 60 getNumberResourcesFound()61 protected int getNumberResourcesFound() { 62 return results.size(); 63 } 64 getNumberMissingResources()65 protected int getNumberMissingResources() { 66 return missing.size(); 67 } 68 getNumberUnusedResources()69 protected int getNumberUnusedResources() { 70 int count = 0; 71 Enumeration elems = results.elements(); 72 while (elems.hasMoreElements()) { 73 ScanResult result = (ScanResult)elems.nextElement(); 74 if (result.getOccurances().size() < 1) count++; 75 } 76 return count; 77 } 78 getMissingResources()79 protected Vector getMissingResources() { 80 Enumeration elems = missing.elements(); 81 Vector v = new Vector(); 82 while (elems.hasMoreElements()) 83 v.addElement(elems.nextElement()); 84 return v; 85 } 86 getUnusedResources()87 protected Vector getUnusedResources() { 88 Enumeration elems = results.elements(); 89 Vector v = new Vector(); 90 while (elems.hasMoreElements()) { 91 ScanResult result = (ScanResult)elems.nextElement(); 92 if (result.getOccurances().size() < 1) { 93 v.addElement(result); 94 } 95 } 96 return v; 97 } 98 performScan()99 protected boolean performScan() throws IOException { 100 resultsFound = false; 101 102 Element root = config.getDocumentElement(); 103 NodeList nl = root.getElementsByTagName("Scan"); 104 if (nl.getLength() < 1) return resultsFound; 105 Element scan_elem = (Element)nl.item(0); 106 nl = scan_elem.getElementsByTagName("Directory"); 107 for (int i=0; i < nl.getLength(); i++) { 108 Element dir_elem = (Element)nl.item(i); 109 File directory = new File(dir_elem.getAttribute("location")); 110 boolean recurse = dir_elem.getAttribute("recurse_directories").equalsIgnoreCase("true"); 111 NodeList rules_list = dir_elem.getElementsByTagName("Rules"); 112 if (rules_list.getLength() < 1) continue; 113 Element rules_elem = (Element)rules_list.item(0); 114 NodeList frules_list = rules_elem.getElementsByTagName("ApplyFileRule"); 115 // For each file rule 116 for (int j=0; j < frules_list.getLength(); j++) { 117 Element frule_elem = (Element)frules_list.item(j); 118 FileRule frule = (FileRule)fileRules.get(frule_elem.getAttribute("name")); 119 if (frule == null) continue; 120 NodeList prules_list = frule_elem.getElementsByTagName("ApplyParseRule"); 121 Vector prules_v = new Vector(); 122 // For each parse rule 123 for (int k=0; k < prules_list.getLength(); k++) { 124 Element prule_elem = (Element)prules_list.item(k); 125 ParseRule prule = (ParseRule)parseRules.get(prule_elem.getAttribute("name")); 126 if (prule == null) continue; 127 prules_v.addElement(prule); 128 } 129 if (prules_v.size() < 1) continue; 130 scanDirectory(directory, frule, prules_v, recurse); 131 } 132 } 133 134 return resultsFound; 135 } 136 scanDirectory(File directory, FileRule frule, Vector prules, boolean recurse)137 private void scanDirectory(File directory, FileRule frule, Vector prules, boolean recurse) throws IOException { 138 139 // Recursion step 140 if (recurse) { 141 File children[] = directory.listFiles(new java.io.FileFilter(){ 142 public boolean accept(File f) { 143 return f.isDirectory(); 144 } 145 146 public String getDescription() { 147 return ""; 148 } 149 }); 150 for (int i=0; i < children.length; i++) { 151 File new_directory = children[i]; 152 scanDirectory(new_directory, frule, prules, recurse); 153 } 154 } 155 // Go through each acceptable file 156 File children[] = directory.listFiles(); 157 for (int i=0; i < children.length; i++) { 158 File f = children[i]; 159 if (f.isDirectory() || !(frule.applyRule(f.getName()))) continue; 160 FileReader fr = new FileReader(f); 161 BufferedReader br = new BufferedReader(fr); 162 String line = null; 163 int line_count = 0; 164 // Read the file line by line 165 while ((line = br.readLine()) != null) { 166 line_count++; 167 Vector findings = new Vector(); 168 // Apply all parse rules to each line 169 for (int j=0; j < prules.size(); j++) { 170 ParseRule prule = (ParseRule)prules.elementAt(j); 171 Vector temp_results = prule.applyRule(line); 172 for (int k=0; k < temp_results.size(); k++) { 173 findings.addElement(temp_results.elementAt(k)); 174 } 175 } 176 for (int j=0; j < findings.size(); j++) { 177 String name = (String)findings.elementAt(j); 178 Occurance occ = new Occurance(f.getName(), f.getAbsolutePath(), line_count); 179 // If the name is found in the resource bundles derived hashtable 180 if (results.containsKey(name)) { 181 ScanResult scan_res = (ScanResult)results.get(name); 182 scan_res.addOccurance(occ); 183 } else { 184 // Add it to the missing results 185 ScanResult scan_res = new ScanResult(new BundleItem(null, name, "*unknown*")); 186 scan_res.addOccurance(occ); 187 missing.put(name, scan_res); 188 results.put(name, scan_res); 189 } 190 } 191 } 192 } 193 } 194 getFileRules(Element root)195 private Hashtable getFileRules(Element root) { 196 Hashtable result = new Hashtable(); 197 NodeList frules_list = root.getElementsByTagName("FileRules"); 198 Element frules_elem = null; 199 if (frules_list.getLength() > 0) frules_elem = (Element)frules_list.item(0); 200 if (frules_elem == null) return result; 201 frules_list = frules_elem.getElementsByTagName("FileRule"); 202 for (int i=0; i < frules_list.getLength(); i++) { 203 Element elem = (Element)frules_list.item(i); 204 FileRule frule = new FileRule(elem.getAttribute("name"), elem.getAttribute("starts_with"), 205 elem.getAttribute("ends_with"), elem.getAttribute("contains")); 206 result.put(elem.getAttribute("name"), frule); 207 } 208 return result; 209 } 210 getParseRules(Element root)211 private Hashtable getParseRules(Element root) { 212 Hashtable result = new Hashtable(); 213 NodeList prules_list = root.getElementsByTagName("ParseRules"); 214 Element prules_elem = null; 215 if (prules_list.getLength() > 0) 216 prules_elem = (Element)prules_list.item(0); 217 if (prules_elem == null) 218 return result; 219 prules_list = prules_elem.getElementsByTagName("ParseRule"); 220 for (int i=0; i < prules_list.getLength(); i++) { 221 Element elem = (Element)prules_list.item(i); 222 ParseRule prule = new ParseRule(elem.getAttribute("name"), elem.getAttribute("follows"), 223 elem.getAttribute("precedes")); 224 result.put(elem.getAttribute("name"), prule); 225 } 226 return result; 227 } 228 } 229 230 class FileRule { 231 String name; 232 String starts_with; 233 String ends_with; 234 String contains; 235 FileRule(String name, String starts_with, String ends_with, String contains)236 FileRule(String name, String starts_with, String ends_with, String contains) { 237 this.name = name; 238 this.starts_with = starts_with; 239 this.ends_with = ends_with; 240 this.contains = contains; 241 } 242 applyRule(String source)243 boolean applyRule(String source) { 244 boolean accept = true; 245 if (starts_with != null && starts_with.length() > 0 && !(source.startsWith(starts_with))) accept = false; 246 if (ends_with != null && ends_with.length() > 0 && !(source.endsWith(ends_with))) accept = false; 247 if (contains != null && contains.length() > 0 && source.indexOf(contains) < 0) accept = false; 248 return accept; 249 } 250 } 251 252 class ParseRule { 253 String name; 254 String before; 255 String after; 256 ParseRule(String name, String before, String after)257 ParseRule(String name, String before, String after) { 258 this.name = name; 259 this.before = before; 260 this.after = after; 261 } 262 263 // returns the vector of strings found after before and before after 264 applyRule(String source)265 Vector applyRule(String source) { 266 Vector v = new Vector(); 267 if (before != null && before.length() > 0) { 268 if (after != null && after.length() > 0) { 269 // Both before and after non-empty 270 int before_index = -1; 271 int after_index = -1; 272 while ((before_index = source.indexOf(before, ++before_index)) >= 0) { 273 //before_index = source.indexOf(before, before_index); 274 after_index = -1; 275 after_index = source.indexOf(after, before_index + before.length()+1); 276 if (after_index < 0 || before_index < 0 || before.length() < 0) { 277 break; 278 } 279 v.addElement(source.substring(before_index + before.length(), after_index)); 280 before_index = after_index; 281 } 282 } else { 283 // Before non-empty, after empty 284 int index = -1; 285 while (source.indexOf(before, ++index) >= 0) { 286 index = source.indexOf(before, index); 287 String result = source.substring(index + before.length(), source.length()); 288 if (result != null && result.length() > 0) v.addElement(result); 289 } 290 } 291 } else if (after != null && after.length() > 0) { 292 // Before empty, after not 293 int index = -1; 294 while (source.indexOf(after, ++index) >= 0) { 295 index = source.indexOf(before, index); 296 String result = source.substring(0, index); 297 if (result != null && result.length() > 0) v.addElement(result); 298 } 299 } else { 300 // Before and after empty 301 v.addElement(source); 302 } 303 return v; 304 } 305 }