|
What this is
Other links
The source code/* * $Header: /cvsroot/mvnforum/mvnforum/i18n/tool/LocalizingKeyFinder.java,v 1.9 2005/01/28 08:06:02 minhnn Exp $ * $Author: minhnn $ * $Revision: 1.9 $ * $Date: 2005/01/28 08:06:02 $ * * ==================================================================== * * Copyright (C) 2002-2005 by MyVietnam.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * All copyright notices regarding MyVietnam and MyVietnam CoreLib * MUST remain intact in the scripts and source code. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Correspondence and Marketing Questions can be sent to: * info@MyVietnam.net * * @author: Minh Nguyen minhnn@MyVietnam.net * @author: Mai Nguyen mai.nh@MyVietnam.net */ /* * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ //package org.apache.tools.ant.taskdefs.optional.i18n; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Hashtable; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.util.FileUtils; /** * This a a simple finder which find the key are not in a properties file call * bundle file Just find the keys and show its position( file, line in file ). * * @author phongtq@myvietnam.net */ public class LocalizingKeyFinder extends MatchingTask { /** * Family name of resource bundle */ private String bundle; /** * Starting token to identify keys */ private String startToken; /** * Ending token to identify keys */ private String endToken; /** * Resource Bundle file encoding scheme, defaults to srcEncoding */ private String bundleEncoding; /** * Vector to hold source file sets. */ private Vector filesets = new Vector(); /** * Holds key value pairs loaded from resource bundle file */ private Hashtable resourceMap = new Hashtable(); /** * Used to resolve file names. */ private FileUtils fileUtils = FileUtils.newFileUtils(); /** * Has at least one file from the bundle been loaded? */ private boolean loaded = false; /** * Sets Family name of resource bundle; required. */ public void setBundle(String bundle) { this.bundle = bundle; } /** * Sets starting token to identify keys; required. */ public void setStartToken(String startToken) { this.startToken = startToken; } /** * Sets ending token to identify keys; required. */ public void setEndToken(String endToken) { this.endToken = endToken; } /** * Sets Resource Bundle file encoding scheme; optional. Defaults to source file * encoding */ public void setBundleEncoding(String bundleEncoding) { this.bundleEncoding = bundleEncoding; } /** * Adds a set of files to translate as a nested fileset element. */ public void addFileset(FileSet set) { filesets.addElement(set); } /** * Check attributes values, load resource map and translate */ public void execute() throws BuildException { if (bundle == null) { throw new BuildException("The bundle attribute must be set.", getLocation()); } if (startToken == null) { throw new BuildException("The starttoken attribute must be set.", getLocation()); } if (endToken == null) { throw new BuildException("The endtoken attribute must be set.", getLocation()); } if (bundleEncoding == null) { bundleEncoding = "Cp1252"; } loadResourceMaps(); translate(); } /** * Load resource maps based on resource bundle encoding scheme. * The resource bundle lookup searches for resource files with various * suffixes on the basis of (1) the desired locale and (2) the default * locale (basebundlename), in the following order from lower-level * (more specific) to parent-level (less specific): * * basebundlename + "_" + language1 + "_" + country1 + "_" + variant1 * basebundlename + "_" + language1 + "_" + country1 * basebundlename + "_" + language1 * basebundlename * basebundlename + "_" + language2 + "_" + country2 + "_" + variant2 * basebundlename + "_" + language2 + "_" + country2 * basebundlename + "_" + language2 * * To the generated name, a ".properties" string is appeneded and * once this file is located, it is treated just like a properties file * but with bundle encoding also considered while loading. */ private void loadResourceMaps() throws BuildException { processBundle(bundle, true); } /** * Process each file that makes up this bundle. */ private void processBundle(final String bundleFile, final boolean checkLoaded) throws BuildException { final File propsFile = new File(bundleFile + ".properties"); log(propsFile + "[ BUNDLE PROPERTIES FILE ]"); FileInputStream ins = null; try { ins = new FileInputStream(propsFile); loaded = true; log("Using " + propsFile, Project.MSG_DEBUG); loadResourceMap(ins); } catch (IOException ioe) { log(propsFile + " not found.", Project.MSG_DEBUG); if (!loaded && checkLoaded) { throw new BuildException(ioe.getMessage()); } } } /** * Load resourceMap with key value pairs. Values of existing keys are not * overwritten. Bundle's encoding scheme is used. */ private void loadResourceMap(FileInputStream ins) throws BuildException { try { BufferedReader in = null; InputStreamReader isr = new InputStreamReader(ins, bundleEncoding); in = new BufferedReader(isr); String line = null; while ((line = in.readLine()) != null) { //So long as the line isn't empty and isn't a comment... if (line.trim().length() > 1 && ('#' != line.charAt(0) || '!' != line.charAt(0))) { //Legal Key-Value separators are :, = and white space. int sepIndex = line.indexOf('='); if (-1 == sepIndex) { sepIndex = line.indexOf(':'); } if (-1 == sepIndex) { for (int k = 0; k < line.length(); k++) { if (Character.isSpaceChar(line.charAt(k))) { sepIndex = k; break; } } } //Only if we do have a key is there going to be a value if (-1 != sepIndex) { String key = line.substring(0, sepIndex).trim(); String value = line.substring(sepIndex + 1).trim(); //Handle line continuations, if any while (value.endsWith("\\")) { value = value.substring(0, value.length() - 1); if ((line = in.readLine()) != null) { value = value + line.trim(); } else { break; } } if (key.length() > 0) { //Has key already been loaded into resourceMap? if (resourceMap.get(key) == null) { resourceMap.put(key, value); } } } } } if (in != null) { in.close(); } } catch (IOException ioe) { throw new BuildException(ioe.getMessage()); } } /** * Reads source file line by line using the source encoding and searches for * keys that are sandwiched between the startToken and endToken. The values * for these keys are looked up from the hashtable and substituted. If the * hashtable doesn't contain the key, they key itself is used as the value. * Detination files and directories are created as needed. The destination * file is overwritten only if the forceoverwritten attribute is set to true * if the source file or any associated bundle resource file is newer than * the destination file. */ private void translate() throws BuildException { for (int i = 0; i < filesets.size(); i++) { FileSet fs = (FileSet) filesets.elementAt(i); DirectoryScanner ds = fs.getDirectoryScanner(getProject()); String[] srcFiles = ds.getIncludedFiles(); int srcFilesCount = srcFiles.length; if (srcFilesCount == 1) { log("Checking 1 file in " + fs.getDir(getProject()), Project.MSG_INFO ); } else { log("Checking " + srcFilesCount + " files in " + fs.getDir(getProject()), Project.MSG_INFO); } int bugCount = 0; int warningCount = 0; for (int j = 0; j < srcFiles.length; j++) { try { File src = fileUtils.resolveFile(ds.getBasedir(), srcFiles[j]); log("Processing " + srcFiles[j], Project.MSG_DEBUG); FileInputStream fis = new FileInputStream(src); BufferedReader in = new BufferedReader( new InputStreamReader(fis)); String line; int lineNumber = 0; while ((line = in.readLine()) != null) { lineNumber++; int startIndex = -1; int endIndex = -1; // just one key in a line ( maybe no loop is also OK !!) outer : while (true) { startIndex = line.indexOf(startToken, endIndex + 1); if ((startIndex < 0) || (startIndex + 1 >= line.length()) ) { break; } endIndex = line.indexOf(endToken, startIndex + 1); if (endIndex < 0) { log("\nWARNING: Line contains the start key " + "but doesn't have the end key. ", Project.MSG_WARN); log("WARNING: At line " + lineNumber + " in file : " + src, Project.MSG_WARN); warningCount++; break; } startIndex = line.indexOf("\"", startIndex); if (startIndex < 0) { // such as "return MVNForumResourceBundle.getString(locale, this.desc);" if (line.indexOf("this.desc") < 0) { log("WARNING: \"" + line + "\" does not have starting quote", Project.MSG_WARN); warningCount++; } break; } endIndex = line.indexOf("\"", startIndex + 1); if (endIndex < 0) { // such as "return MVNForumResourceBundle.getString(locale, this.desc);" log("WARNING: \"" + line + "\" does not have ending quote", Project.MSG_WARN); warningCount++; break; } String matches = line.substring(startIndex + 1, endIndex); //log("[ MATCH ]::match = " + matches + " resource // = " + (String) resourceMap.get(matches), // Project.MSG_WARN); /** * Note: minhnn I change the code to consider a * valid matches must begin with mvnforum */ String replace = null; replace = (String) resourceMap.get(matches); //log (replace + "[ WHAT IS REPLACE ??]"); if (replace == null) { bugCount++; log("\nERROR: The key \"" + matches + "\" hasn't been defined.", Project.MSG_WARN); log("ERROR: At line " + lineNumber + " in file : " + src, Project.MSG_WARN); replace = matches; } line = line.substring(0, startIndex) + replace + line.substring(endIndex + 1); // minhnn: I dont know if the original code has bug // I changed from "+ 1" to "- 1" and it works well endIndex = startIndex + replace.length() - 1; if (endIndex + 1 >= line.length()) { break; } } } if (in != null) { in.close(); } } catch (IOException ioe) { throw new BuildException(ioe.getMessage(), getLocation()); } } log("\n###########################################"); log("Total error count: " + bugCount); log("Total warning count: " + warningCount); } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.