package org.rhq.enterprise.gui.legacy.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ApplicationResourcesTest { class BundleLeveragingFilenameFilter implements FilenameFilter { public boolean accept(File dir, String name) { if (dir.isHidden()) { return false; } if (dir.getAbsolutePath().endsWith("target")) { return false; } if (dir.getAbsolutePath().endsWith("svn")) { return false; } if (name.endsWith("svn")) { return false; } if (name.endsWith("class")) { return false; } return true; } } class PropertyFile implements Comparable<PropertyFile> { public final String property; public final String file; public PropertyFile(String property, String file) { this.file = file; this.property = property; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((file == null) ? 0 : file.hashCode()); result = prime * result + ((property == null) ? 0 : property.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PropertyFile other = (PropertyFile) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (file == null) { if (other.file != null) return false; } else if (!file.equals(other.file)) return false; if (property == null) { if (other.property != null) return false; } else if (!property.equals(other.property)) return false; return true; } private ApplicationResourcesTest getOuterType() { return ApplicationResourcesTest.this; } public int compareTo(PropertyFile o) { int result = this.property.compareTo(o.property); if (result != 0) { return result; } return this.file.compareTo(o.file); } } Pattern patternXHTML = Pattern.compile("" + // ".*" + // some number of leading characters "[\\$|#]" + // starting with a dollar sign or #, the characters supported by UEL "\\{" + // wrapped in curly braces "msg" + // followed by the literal 'msg' "\\[" + // and then brackets "(" + // start capture group "[^\\]]+" + // one or more characters up to the first close brace ")" + // finish capture group "\\]" + // and closing brackets "\\}" + // and closing curly ".*", // some number of trailing characters Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern patternJAVA = null; Pattern patternJSP = Pattern.compile("" + // ".*?" + // some number of leading characters "fmt\\:message" + // starting with 'fmt:message' literal "\\s+?" + // then some whitespace "key=" + // and the 'key' attribute, with an equals sign, and open double-quote "\"" + // an opening double-quote "(" + // start capture group "[^\"]+" + // one or more characters up to the first closing double-quote ")" + // finish capture group "\"", // a closing double-quote //"\\s*" + // then some optional whitespace //" />", // and closing tag Pattern.CASE_INSENSITIVE | Pattern.DOTALL); public void test() { File modulesDir = new File("F:\\ws\\rhq\\trunk\\modules"); List<File> toSearch = new LinkedList<File>(); toSearch.add(modulesDir); FilenameFilter filter = new BundleLeveragingFilenameFilter(); Map<PropertyFile, Integer> counts = new HashMap<PropertyFile, Integer>(); int found = 0; int matches = 0; while (toSearch.size() > 0) { File nextFile = toSearch.remove(0); if (nextFile.isDirectory()) { for (File child : nextFile.listFiles(filter)) { toSearch.add(child); } } else if (nextFile.isFile()) { found++; //System.out.println("Search: " + nextFile.getAbsolutePath()); String path = nextFile.getAbsolutePath(); int extPos = path.lastIndexOf('.'); String ext = path.substring(extPos + 1); Pattern pattern = null; if (ext.equals("xhtml")) { pattern = patternXHTML; } else if (ext.equals("java")) { pattern = patternJAVA; } else if (ext.equals("jsp")) { pattern = patternJSP; } if (pattern != null) { matches += process(nextFile, pattern, counts); } } } List<PropertyFile> propertyNames = new ArrayList<PropertyFile>(counts.keySet()); Collections.sort(propertyNames); for (PropertyFile pf : propertyNames) { int count = counts.get(pf); System.out.println("count: " + count + ", property: " + pf.property + ", file: " + pf.file); } Properties propertiesBundle = new Properties(); File propertyBundleFile = new File( "F:/ws/rhq/trunk/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties"); FileInputStream propertyBundleInputStream = null; try { propertyBundleInputStream = new FileInputStream(propertyBundleFile); propertiesBundle.load(propertyBundleInputStream); } catch (Exception e) { System.out.println("Could not load properties from file '" + propertyBundleFile.getAbsolutePath() + "'"); return; } finally { if (propertyBundleInputStream != null) { try { propertyBundleInputStream.close(); } catch (Exception e) { System.out.println("Could not close bundle file '" + propertyBundleFile.getAbsolutePath() + "'"); } } } List<String> extraProperties = new ArrayList<String>(); // found in bundle, not in source List<String> missingProperties = new ArrayList<String>(); // found in source, not in bundle Set<String> bundlePropertyNames = stringPropertyNames(propertiesBundle); Set<String> foundPropertyNames = new HashSet<String>(); for (PropertyFile pf : counts.keySet()) { foundPropertyNames.add(pf.property); if (bundlePropertyNames.contains(pf.property) == false && missingProperties.contains(pf.property) == false) { missingProperties.add(pf.property); } } int shortBundleNames = 0; for (String bundlePropertyName : bundlePropertyNames) { if (foundPropertyNames.contains(bundlePropertyName) == false && extraProperties.contains(bundlePropertyName) == false) { extraProperties.add(bundlePropertyName); } if (bundlePropertyName.split("\\.").length == 1) { shortBundleNames++; } } Collections.sort(extraProperties); Collections.sort(missingProperties); for (String extraProperty : extraProperties) { if (extraProperty.toLowerCase().indexOf("") != -1) { System.out.println("Extra: " + extraProperty); } } /* for (String missingProperty : missingProperties) { System.out.println("Missing: " + missingProperty); } */ System.out.println("Found " + found + " files"); System.out.println("Found " + matches + " matches"); System.out.println("Found " + extraProperties.size() + " extra"); System.out.println("Found " + missingProperties.size() + " missing"); System.out.println("Found " + shortBundleNames + " short bundle names"); System.out.println("Found " + bundlePropertyNames.size() + " total bundle names"); } // alternative to using Properties.stringPropertyNames but it works on JDK 5 private Set<String> stringPropertyNames(Properties propertiesBundle) { HashSet<String> tmpSet = new HashSet<String>(); for (Enumeration<?> allNames = propertiesBundle.propertyNames(); allNames.hasMoreElements();) { Object name = allNames.nextElement(); tmpSet.add(name.toString()); } return tmpSet; } private int process(File f, Pattern pattern, Map<PropertyFile, Integer> properties) { BufferedReader lineReader = null; int matches = 0; try { lineReader = new BufferedReader(new FileReader(f)); String nextLine = null; while ((nextLine = lineReader.readLine()) != null) { Matcher matcher = pattern.matcher(nextLine); if (matcher.find()) { //System.out.println("Matched line '" + nextLine + "' in file '" + f + "'"); String propertyCapture = matcher.group(1); boolean startQuote = propertyCapture.startsWith("'") || propertyCapture.startsWith("\""); boolean endQuote = propertyCapture.endsWith("'") || propertyCapture.endsWith("\""); if (startQuote && endQuote) { propertyCapture = propertyCapture.substring(1, propertyCapture.length() - 1); } else if (startQuote) { propertyCapture = propertyCapture.substring(1, propertyCapture.length()); } else if (endQuote) { propertyCapture = propertyCapture.substring(0, propertyCapture.length() - 1); } PropertyFile nextCount = new PropertyFile(propertyCapture, f.getAbsolutePath()); if (properties.containsKey(nextCount)) { int count = properties.get(nextCount); properties.put(nextCount, count + 1); } else { properties.put(nextCount, 1); matches++; } } else if (nextLine.indexOf("msg") != -1) { System.out.println("No match, but found '" + nextLine + "'"); } } } catch (Exception e) { System.out.println("Error opening file '" + f + "': " + e.getMessage()); } finally { if (lineReader != null) { try { lineReader.close(); } catch (Exception e) { System.out.println("Error closing file '" + f + "': " + e.getMessage()); } } } return matches; } // \$ \{ msg \[ " [(^\])] " \] \} public static void main(String[] args) { ApplicationResourcesTest tester = new ApplicationResourcesTest(); tester.test(); } }