/* ***************************************************************************** * Copyright (C) 2000-2002, International Business Machines Corporation and * * others. All Rights Reserved. * ***************************************************************************** * * $Source: /xsrl/Nsvn/icu/unicodetools/com/ibm/rbm/RBReporterScanner.java,v $ * $Date: 2002/05/20 18:53:09 $ * $Revision: 1.1 $ * ***************************************************************************** */ package com.ibm.rbm; import javax.swing.*; import java.awt.*; import javax.swing.event.*; import javax.swing.filechooser.*; import java.awt.event.*; import java.io.*; import java.util.*; import org.apache.xerces.parsers.*; import org.apache.xerces.dom.*; import org.apache.xml.serialize.*; import org.w3c.dom.*; import org.xml.sax.*; /** * RBReporterScaner is a utility class for RBReporter. It creates a report from an xml settings * file that scans code for resources and compares them against a resource bundle. * * @author Jared Jackson - Email: jjared@almaden.ibm.com * @see com.ibm.rbm.RBReporter */ public class RBReporterScanner { private Bundle bundle; private DocumentImpl config; private Hashtable fileRules; private Hashtable parseRules; private Hashtable results; private Hashtable missing; private boolean resultsFound; protected RBReporterScanner(Bundle bundle, File configFile) throws IOException { resultsFound = false; this.bundle = bundle; try { InputSource is = new InputSource(new FileInputStream(configFile)); DOMParser parser = new DOMParser(); parser.parse(is); config = (DocumentImpl)parser.getDocument(); } catch (SAXException saxe) { throw new IOException("Illegal XML Document: " + saxe.getMessage()); } ElementImpl root = (ElementImpl)config.getDocumentElement(); fileRules = getFileRules(root); parseRules = getParseRules(root); results = new Hashtable(); Enumeration enum = bundle.allItems.keys(); while (enum.hasMoreElements()) { String key = (String)enum.nextElement(); BundleItem item = (BundleItem)bundle.allItems.get(key); results.put(key, new ScanResult(item)); } missing = new Hashtable(); } protected int getNumberResourcesFound() { return results.size(); } protected int getNumberMissingResources() { return missing.size(); } protected int getNumberUnusedResources() { int count = 0; Enumeration enum = results.elements(); while (enum.hasMoreElements()) { ScanResult result = (ScanResult)enum.nextElement(); if (result.getOccurances().size() < 1) count++; } return count; } protected Vector getMissingResources() { Enumeration enum = missing.elements(); Vector v = new Vector(); while (enum.hasMoreElements()) v.addElement(enum.nextElement()); return v; } protected Vector getUnusedResources() { Enumeration enum = results.elements(); Vector v = new Vector(); while (enum.hasMoreElements()) { ScanResult result = (ScanResult)enum.nextElement(); if (result.getOccurances().size() < 1) { v.addElement(result); } } return v; } protected boolean performScan() throws IOException { resultsFound = false; ElementImpl root = (ElementImpl)config.getDocumentElement(); NodeList nl = root.getElementsByTagName("Scan"); if (nl.getLength() < 1) return resultsFound; ElementImpl scan_elem = (ElementImpl)nl.item(0); nl = scan_elem.getElementsByTagName("Directory"); for (int i=0; i < nl.getLength(); i++) { ElementImpl dir_elem = (ElementImpl)nl.item(i); File directory = new File(dir_elem.getAttribute("location")); boolean recurse = dir_elem.getAttribute("recurse_directories").equalsIgnoreCase("true"); NodeList rules_list = dir_elem.getElementsByTagName("Rules"); if (rules_list.getLength() < 1) continue; ElementImpl rules_elem = (ElementImpl)rules_list.item(0); NodeList frules_list = rules_elem.getElementsByTagName("ApplyFileRule"); // For each file rule for (int j=0; j < frules_list.getLength(); j++) { ElementImpl frule_elem = (ElementImpl)frules_list.item(j); FileRule frule = (FileRule)fileRules.get(frule_elem.getAttribute("name")); if (frule == null) continue; NodeList prules_list = frule_elem.getElementsByTagName("ApplyParseRule"); Vector prules_v = new Vector(); // For each parse rule for (int k=0; k < prules_list.getLength(); k++) { ElementImpl prule_elem = (ElementImpl)prules_list.item(k); ParseRule prule = (ParseRule)parseRules.get(prule_elem.getAttribute("name")); if (prule == null) continue; prules_v.addElement(prule); } if (prules_v.size() < 1) continue; scanDirectory(directory, frule, prules_v, recurse); } } return resultsFound; } private void scanDirectory(File directory, FileRule frule, Vector prules, boolean recurse) throws IOException { // Recursion step if (recurse) { File children[] = directory.listFiles(new java.io.FileFilter(){ public boolean accept(File f) { if (f.isDirectory()) return true; else return false; } public String getDescription() { return ""; } }); for (int i=0; i < children.length; i++) { File new_directory = children[i]; scanDirectory(new_directory, frule, prules, recurse); } } // Go through each acceptable file File children[] = directory.listFiles(); for (int i=0; i < children.length; i++) { File f = children[i]; if (f.isDirectory() || !(frule.applyRule(f.getName()))) continue; FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); String line = null; int line_count = 0; // Read the file line by line while ((line = br.readLine()) != null) { line_count++; Vector findings = new Vector(); // Apply all parse rules to each line for (int j=0; j < prules.size(); j++) { ParseRule prule = (ParseRule)prules.elementAt(j); Vector temp_results = prule.applyRule(line); for (int k=0; k < temp_results.size(); k++) { findings.addElement(temp_results.elementAt(k)); } } for (int j=0; j < findings.size(); j++) { String name = (String)findings.elementAt(j); Occurance occ = new Occurance(f.getName(), f.getAbsolutePath(), line_count); // If the name is found in the resource bundles derived hashtable if (results.containsKey(name)) { ScanResult scan_res = (ScanResult)results.get(name); scan_res.addOccurance(occ); } else { // Add it to the missing results ScanResult scan_res = new ScanResult(new BundleItem(null, name, "*unknown*")); scan_res.addOccurance(occ); missing.put(name, scan_res); results.put(name, scan_res); } } } } } private Hashtable getFileRules(ElementImpl root) { Hashtable result = new Hashtable(); NodeList frules_list = root.getElementsByTagName("FileRules"); ElementImpl frules_elem = null; if (frules_list.getLength() > 0) frules_elem = (ElementImpl)frules_list.item(0); if (frules_elem == null) return result; frules_list = frules_elem.getElementsByTagName("FileRule"); for (int i=0; i < frules_list.getLength(); i++) { ElementImpl elem = (ElementImpl)frules_list.item(i); FileRule frule = new FileRule(elem.getAttribute("name"), elem.getAttribute("starts_with"), elem.getAttribute("ends_with"), elem.getAttribute("contains")); result.put(elem.getAttribute("name"), frule); } return result; } private Hashtable getParseRules(ElementImpl root) { Hashtable result = new Hashtable(); NodeList prules_list = root.getElementsByTagName("ParseRules"); ElementImpl prules_elem = null; if (prules_list.getLength() > 0) prules_elem = (ElementImpl)prules_list.item(0); if (prules_elem == null) return result; prules_list = prules_elem.getElementsByTagName("ParseRule"); for (int i=0; i < prules_list.getLength(); i++) { ElementImpl elem = (ElementImpl)prules_list.item(i); ParseRule prule = new ParseRule(elem.getAttribute("name"), elem.getAttribute("follows"), elem.getAttribute("precedes")); result.put(elem.getAttribute("name"), prule); } return result; } } class FileRule { String name; String starts_with; String ends_with; String contains; FileRule(String name, String starts_with, String ends_with, String contains) { this.name = name; this.starts_with = starts_with; this.ends_with = ends_with; this.contains = contains; } boolean applyRule(String source) { boolean accept = true; if (starts_with != null && starts_with.length() > 0 && !(source.startsWith(starts_with))) accept = false; if (ends_with != null && ends_with.length() > 0 && !(source.endsWith(ends_with))) accept = false; if (contains != null && contains.length() > 0 && source.indexOf(contains) < 0) accept = false; return accept; } } class ParseRule { String name; String before; String after; ParseRule(String name, String before, String after) { this.name = name; this.before = before; this.after = after; } // returns the vector of strings found after before and before after Vector applyRule(String source) { Vector v = new Vector(); if (before != null && before.length() > 0) { if (after != null && after.length() > 0) { // Both before and after non-empty int before_index = -1; int after_index = -1; while ((before_index = source.indexOf(before, ++before_index)) >= 0) { //before_index = source.indexOf(before, before_index); after_index = -1; after_index = source.indexOf(after, before_index + before.length()+1); if (after_index < 0 || before_index < 0 || before.length() < 0) break; else { v.addElement(source.substring(before_index + before.length(), after_index)); before_index = after_index; } } } else { // Before non-empty, after empty int index = -1; while (source.indexOf(before, ++index) >= 0) { index = source.indexOf(before, index); String result = source.substring(index + before.length(), source.length()); if (result != null && result.length() > 0) v.addElement(result); } } } else if (after != null && after.length() > 0) { // Before empty, after not int index = -1; while (source.indexOf(after, ++index) >= 0) { index = source.indexOf(before, index); String result = source.substring(0, index); if (result != null && result.length() > 0) v.addElement(result); } } else { // Before and after empty v.addElement(source); } return v; } }