Path: blob/master/sourcetools/j9nls/com/ibm/oti/NLSTool/J9NLS.java
6004 views
/*******************************************************************************1* Copyright (c) 2004, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package com.ibm.oti.NLSTool;2223import java.io.BufferedReader;24import java.io.File;25import java.io.FileInputStream;26import java.io.FileNotFoundException;27import java.io.FileOutputStream;28import java.io.FileReader;29import java.io.FileWriter;30import java.io.IOException;31import java.util.Enumeration;32import java.util.Hashtable;33import java.util.Iterator;34import java.util.Properties;35import java.util.Vector;36import java.util.regex.Pattern;3738public class J9NLS implements NLSConstants {39private static final int DIFFERENT_ORDER_FOUND = -1;40private Properties outputProperties;41private File palmResourceFile;42private FileWriter palmResourceWriter;43private Hashtable oldNLSFiles;44private Hashtable localeHashtable;45private Vector nlsInfos;46private int totalMessagesProcessed = 0;47private int totalNLSFilesFound = 0;48private int totalHeaderFilesCreated = 0;49private int totalHeaderFilesSkipped = 0;50private int totalPropertiesFilesCreated = 0;51private int totalPropertiesFilesSkipped = 0;52private int totalPalmFilesCreated = 0;53private int totalPalmFilesSkipped = 0;54private int messageNumber;55private int errorCount = 0;56private String workingDirectory = System.getProperty("user.dir");57private String sourceDirectory = System.getProperty("user.dir");58private String fileSeparator = System.getProperty("file.separator");59private String propertiesFileName = "java.properties"; // default60private String palmResourceFileName = "java.rc"; // default61private String htmlFileName = "properties.html"; // default62private String locale = DEFAULT_LOCALE;63private static boolean debugoutput = false;6465public static void main(String[] args) {66J9NLS j9NLS = new J9NLS();67j9NLS.runMain(args);68}6970public static void dp(String s){71if (debugoutput) {72System.out.println(s);73}74}7576public J9NLS() {77}7879private void runMain(String[] args) {80boolean palmMode = false;81boolean nohtml = false;82String outFileName;8384for (int i = 0; i < args.length; i++) {85String arg = args[i];86if (arg.compareToIgnoreCase("-help") == 0) {87printUsage();88return;89} else if (arg.compareToIgnoreCase("-palm") == 0) {90palmMode = true;91} else if (arg.compareToIgnoreCase("-debug") == 0) {92debugoutput = true;93} else if (arg.compareToIgnoreCase("-nohtml") == 0) {94nohtml = true;95} else if (arg.compareToIgnoreCase("-out") == 0) {96if ((i + 1) >= args.length || args[i + 1].startsWith("-"))97failure("Output file name is not specified.");98else if (!(args[i + 1].endsWith(".rc") || args[i + 1].endsWith(".properties")))99failure("Output file name is not in correct format: " + args[i + 1]);100else101propertiesFileName = args[++i];102} else if (arg.compareToIgnoreCase("-html") == 0) {103if ((i + 1) >= args.length || args[i + 1].startsWith("-"))104failure("HTML file name is not specified.");105else if (!(args[i + 1].endsWith(".html") || args[i + 1].endsWith(".htm"))) {106failure("Output file name is not in correct format: " + args[i + 1]);107} else108htmlFileName = args[++i];109} else if (arg.compareToIgnoreCase("-source") == 0) {110if ((i + 1) >= args.length || args[i + 1].startsWith("-"))111failure("Source directory not specified");112File srcDir = new File(args[++i]);113if (!srcDir.exists() || ! srcDir.isDirectory())114failure("Source directory '" + srcDir + "' does not exist");115116sourceDirectory = srcDir.getAbsolutePath();117} else {118failure("Unrecognized option: " + arg);119}120}121122if (palmMode)123outFileName = palmResourceFileName;124else125outFileName = propertiesFileName;126127nlsInfos = new Vector();128searchNLSFiles();129if (localeHashtable.size() < 1)130failure("Cannot find any NLS files below " + sourceDirectory);131132try {133generatePropertiesFiles(outFileName, palmMode);134if (!nohtml)135new NLSHtmlGenerator().generateHTML(nlsInfos, outFileName, htmlFileName);136} catch (FileNotFoundException fnfe) {137if (debugoutput)138fnfe.printStackTrace();139failure("Caught exception: " + fnfe.getMessage(),true);140} catch (IOException e) {141if (debugoutput)142e.printStackTrace();143failure("Caught exception: " + e.getMessage(),true);144}145summarize();146}147148private void generatePropertiesFiles(String outFileName, boolean palmMode) throws IOException, FileNotFoundException {149String moduleName, headerName;150FileOutputStream out = null;151Hashtable headerHashtable = new Hashtable();152Vector defaultNLSFiles = (Vector) localeHashtable.get(DEFAULT_LOCALE);153StringBuffer buffer = new StringBuffer();154155// Create the output directory if it doesn't exist156File outputDir = new File(workingDirectory + fileSeparator + "nls");157if (!outputDir.exists()) {158dp("Output directory does not exist, creating it");159outputDir.mkdir();160}161162for (Enumeration locales = localeHashtable.keys(); locales.hasMoreElements();) {163locale = (String) locales.nextElement();164Vector nlsFiles = (Vector) localeHashtable.get(locale);165dp("Processing " + nlsFiles.size() + " NLS files for " + getLocaleName(locale)166+ " locale");167168if (!palmMode) {169outputProperties = new Properties();170}171172for (int i = 0; i < nlsFiles.size(); i++) {173NLSInfo nlsInfo = null;174boolean newNLSInfo = false;175messageNumber = 0;176177File nlsFile = (File) nlsFiles.elementAt(i);178String nlsPath = nlsFile.getPath();179Properties nlsProperties = new Properties();180java.io.FileInputStream strm = new java.io.FileInputStream(nlsPath);181nlsProperties.load(strm);182strm.close();183184dp("Processing " + nlsPath);185186validateKeys(nlsPath, nlsProperties);187188moduleName = (String) nlsProperties.get(MODULE_KEY);189if (moduleName.length() != DEFAULT_MODULE_LENGTH)190failure("Module name must be exactly " + DEFAULT_MODULE_LENGTH + " characters long: "191+ moduleName);192193String headerPath = workingDirectory + fileSeparator + "nls" + fileSeparator;194headerName = (String) nlsProperties.get(HEADER_KEY);195196nlsInfo = findNLSInfo(nlsInfos, moduleName, headerName);197if (nlsInfo.getModule() == null)198newNLSInfo = true;199nlsInfo.setModule(moduleName);200nlsInfo.setPath(nlsPath.substring((sourceDirectory + fileSeparator).length()));201nlsInfo.setHeaderName(headerName);202nlsInfo.addLocale(locale);203204HeaderBuffer headerBuffer = new HeaderBuffer(headerName, nlsFile.getName());205headerBuffer.writeHeader(headerName, moduleName);206207compareWithOld(nlsFile, nlsProperties);208compareWithDefault(nlsFile, nlsProperties, defaultNLSFiles);209210Iterator keyIterator = getOrderedKeys(nlsProperties, nlsFile).iterator();211Vector msgInfos = new Vector();212while (keyIterator.hasNext()) {213if (messageNumber >= MAX_NUMBER_OF_MESSAGES_PER_MODULE)214failure(moduleName + " has more messages than the max limit of "215+ MAX_NUMBER_OF_MESSAGES_PER_MODULE);216String key = (String) keyIterator.next();217if (nlsProperties.containsKey(key)) {218String formattedMsgNumber = formatMsgNumber(messageNumber);219String msg = (String) nlsProperties.get(key);220if ((!msg.equals("")) || (locale!="")){221if (palmMode) {222byte[] utf8Msg = msg.getBytes("UTF-8");223buffer.append("HEX \"" + moduleName + "\" ID " + formattedMsgNumber224+ " " + toHexString(utf8Msg) + "\n");225} else {226outputProperties.setProperty(moduleName + formattedMsgNumber, msg);227}228}229msgInfos230.addElement(createMsgInfo(moduleName + formattedMsgNumber, key, msg, nlsProperties));231232if (msg.equals("")) {233headerBuffer.append("#define " + key + "__PREFIX \"" + moduleName + formattedMsgNumber234+ "\"\n");235} else {236headerBuffer.appendMsg(moduleName, key);237}238messageNumber++;239}240}241242nlsInfo.setMsgInfo(msgInfos);243dp(messageNumber + " messages processed from " + nlsPath);244totalMessagesProcessed += messageNumber;245headerBuffer.append("\n#endif\n");246247if (newNLSInfo)248nlsInfos.addElement(nlsInfo);249250if (DEFAULT_LOCALE.equals(locale)) {251/* only output the header once (for the default locale) */252generateHeaderFile(headerHashtable, nlsFile, headerPath, headerBuffer);253}254}255256//check if file already exists on the file system257//if found, compare it with the generated file; if the same, do not overwrite it258//if the file does not exists, write it to disk259if (palmMode) {260palmResourceFile = new File(getNameWithLocale(outFileName, locale));261if (differentFromCopyOnDisk(getNameWithLocale(outFileName, locale), buffer)) {262palmResourceWriter = new FileWriter(palmResourceFile);263palmResourceWriter.write(buffer.toString());264palmResourceWriter.close();265dp("** Generated " + palmResourceFileName + "\n");266totalPalmFilesCreated++;267} else {268dp("** Skipped writing [same as on file system]: " + palmResourceFile);269totalPalmFilesSkipped++;270}271} else {272String fileName = getNameWithLocale(outFileName, locale);273if (propertiesDifferentFromCopyOnDisk(fileName)) {274out = new FileOutputStream(fileName);275outputProperties.store(out, null);276out.flush();277dp("** Generated " + fileName + "\n");278totalPropertiesFilesCreated++;279} else {280dp("** Skipped writing [same as on file system]: " + fileName);281totalPropertiesFilesSkipped++;282}283}284285if (null != out) {286out.close();287}288}289}290291private MsgInfo createMsgInfo(String macro, String key, String msg, Properties nlsProperties) {292MsgInfo msgInfo = new MsgInfo();293msgInfo.setMacro(macro);294msgInfo.setKey(key);295msgInfo.setMsg(msg);296msgInfo.setId(messageNumber);297msgInfo.setExplanation(nlsProperties.getProperty(key + SUFFIX_EXPLANATION));298msgInfo.setSystemAction(nlsProperties.getProperty(key + SUFFIX_SYSTEM_ACTION));299msgInfo.setUserResponse(nlsProperties.getProperty(key + SUFFIX_USER_RESPONSE));300return msgInfo;301}302303/**304* @param nlsPath305* @param nlsProperties306*/307private void validateKeys(String nlsPath, Properties nlsProperties) {308if (!nlsProperties.containsKey(MODULE_KEY))309failure("Module name not found in " + nlsPath + " file");310311if (!nlsProperties.containsKey(HEADER_KEY))312failure("Header file name not found in " + nlsPath + " file");313314for (Enumeration keys = nlsProperties.keys(); keys.hasMoreElements();) {315String key = (String) keys.nextElement();316317if (isSpecialKey(key)) {318String entry = key.substring(0, key.indexOf('.'));319320if (MODULE_KEY.equals(key)) {321// no validation of this key322} else if (HEADER_KEY.equals(key)) {323// no validation of this key324} else {325if (!nlsProperties.containsKey(entry)) {326failure(key + " has no corresponding NLS entry", false);327}328if (329key.endsWith(SUFFIX_EXPLANATION)330|| key.endsWith(SUFFIX_SYSTEM_ACTION)331|| key.endsWith(SUFFIX_USER_RESPONSE)332|| key.endsWith(SUFFIX_LINK)333|| Pattern.matches(".*\\.sample_input_[1-9][0-9]*", key))334{335// key is valid336} else {337failure(key + " is an unrecognized special key. ", false);338339}340}341}342}343344}345346private NLSInfo findNLSInfo(Vector nlsInfos, String moduleName, String headerName) {347for (Enumeration e = nlsInfos.elements(); e.hasMoreElements();) {348NLSInfo nlsInfo = (NLSInfo) e.nextElement();349if (nlsInfo.isSameNLS(moduleName, headerName))350return nlsInfo;351}352return new NLSInfo();353}354355private void compareWithOld(File nlsFile, Properties nlsProperties) throws IOException, FileNotFoundException {356Vector orderedKeys = getOrderedKeys(nlsProperties, nlsFile);357if (oldNLSFiles.containsKey(nlsFile.getName() + ".old")) {358File oldNLSFile = (File) oldNLSFiles.get(nlsFile.getName() + ".old");359Properties oldNLSProperties = new Properties();360java.io.FileInputStream strm = new java.io.FileInputStream(oldNLSFile.getPath());361oldNLSProperties.load(strm);362strm.close();363Vector oldOrderedKeys = getOrderedKeys(oldNLSProperties, oldNLSFile);364dp("Comparing with " + oldNLSFile.getPath());365int compareOrders = compareOrder(oldOrderedKeys, orderedKeys);366if (compareOrders == DIFFERENT_ORDER_FOUND) {367failure("Old messages in " + nlsFile.getPath() + " are different from the ones in "368+ oldNLSFile.getPath(), false);369} else if (compareOrders != 0)370dp(" Found " + compareOrders + " new message(s) in " + nlsFile.getPath());371else372dp(" They are identical to each other.");373}374}375376private void compareWithDefault(File nlsFile, Properties nlsProperties, Vector defaultNLSFiles)377throws FileNotFoundException, IOException {378File defaultNLSFile = findDefault(nlsFile, defaultNLSFiles);379Properties defaultNLSProperties = new Properties();380FileInputStream strm = new java.io.FileInputStream(defaultNLSFile.getPath());381defaultNLSProperties.load(strm);382strm.close();383Vector defaultOrderedKeys = getOrderedKeys(defaultNLSProperties, defaultNLSFile);384Vector defaultMessages = getValuesForKeys(defaultOrderedKeys, defaultNLSFile);385Vector nlsMessages = getValuesForKeys(defaultOrderedKeys, nlsFile);386Iterator nlsKeys = defaultOrderedKeys.iterator();387Iterator defaultIterator = defaultMessages.iterator();388Iterator nlsIterator = nlsMessages.iterator();389while (defaultIterator.hasNext()) {390String key = (String)nlsKeys.next();391String defaultMessage = (String) defaultIterator.next();392String nlsMessage = (String) nlsIterator.next();393if (!"".equals(defaultMessage) && null != nlsMessage) {394if (false == formatSpecifiersAreEquivalent(defaultMessage, nlsMessage))395failure(key + " Message \"" + nlsMessage + "\" in " + nlsFile.getPath() + " is different from \""396+ defaultMessage + "\" in " + defaultNLSFile.getPath(), false);397}398}399}400401private File findDefault(File nlsFile, Vector defaultNLSFiles) {402String nlsFileName = nlsFile.getName();403String defaultNLSFileName = ((nlsFileName.lastIndexOf('_') != -1) ? nlsFileName.substring(0, nlsFileName404.indexOf('_')) : nlsFileName.substring(0, nlsFileName.lastIndexOf('.')))405+ DEFAULT_LOCALE + nlsFileName.substring(nlsFileName.lastIndexOf('.'));406Iterator i = defaultNLSFiles.iterator();407while (i.hasNext()) {408File f = (File) i.next();409if (f != null && f.getName().equals(defaultNLSFileName)) {410return f;411}412}413return null;414}415416private boolean formatSpecifiersAreEquivalent(String oldMessage, String newMessage) {417boolean reorderable = false;418Vector oldFormatSpec = formatSpecifiersOf(oldMessage);419Vector newFormatSpec = formatSpecifiersOf(newMessage);420421if (newFormatSpec.size() != oldFormatSpec.size()) {422return false;423}424425/*426* If the format specifiers contain $ signs, then the specifiers may427* appear in any order within the string. Detect if $ signs are being428* used to decide how the list of specifiers ought to be compared.429*/430for (Iterator iter = oldFormatSpec.iterator(); iter.hasNext();) {431String spec = (String) iter.next();432if (spec.indexOf('$') != -1) {433reorderable = true;434break;435}436}437438if (reorderable) {439for (Iterator iter = oldFormatSpec.iterator(); iter.hasNext();) {440String spec = (String)iter.next();441if (spec.indexOf('$') == -1) {442failure("\"" + oldMessage + "\" includes a mix of ordered and unordered format sepcifiers", false);443}444if (!newFormatSpec.remove(spec)) {445return false;446}447}448return true;449} else {450return oldFormatSpec.equals(newFormatSpec);451}452}453454private Vector formatSpecifiersOf(String s) {455Vector result = new Vector();456457if (null == s)458return result;459460StringBuffer buf = new StringBuffer();461int e = s.length();462int state = 0;463for (int i = 0; i < e; ++i) {464char c = s.charAt(i);465switch (state) {466case 0:467if ('%' == c)468state = 1;469break;470case 1:471if ('%' == c) {472state = 0;473break;474}475buf.append('%');476state = 2;477// FALLTHRU478case 2:479if ("pcsxXuidf".indexOf(c) != -1) {480if ('p' == c)481buf.append("zx");482else if ("csxf".indexOf(c) != -1)483buf.append(c);484else485buf.append('x');486result.add(buf.toString());487buf = new StringBuffer();488state = 0;489} else {490buf.append(c);491}492break;493default:494failure("unknown error extracting format specifiers from " + s);495}496}497498return result;499}500501private Vector getValuesForKeys(Vector keys, File nlsFile) throws FileNotFoundException, IOException {502String nlsPath = nlsFile.getPath();503Properties nlsProperties = new Properties();504java.io.FileInputStream strm = new java.io.FileInputStream(nlsPath);505nlsProperties.load(strm);506strm.close();507508Vector values = new Vector();509Iterator i = keys.iterator();510while (i.hasNext()) {511values.addElement(nlsProperties.get(i.next()));512}513return values;514}515516private boolean isSpecialKey(String key) {517return key.indexOf('.') >= 0;518}519520private int compareOrder(Vector oldOrderedKeys, Vector orderedKeys) {521Iterator iterator = orderedKeys.iterator();522Iterator oldIterator = oldOrderedKeys.iterator();523String key, oldKey;524while (oldIterator.hasNext()) {525if (!iterator.hasNext())526return DIFFERENT_ORDER_FOUND;527else {528key = (String) iterator.next();529oldKey = (String) oldIterator.next();530if (!key.equals(oldKey)) {531dp("Mismatch found: " + key + ", " + oldKey);532return DIFFERENT_ORDER_FOUND;533}534}535}536int toReturn = 0;537while (iterator.hasNext()) {538iterator.next();539toReturn++;540}541return toReturn;542}543544private void generateHeaderFile(Hashtable headerHashtable, File nlsFile, String headerPath,545HeaderBuffer headerBuffer) throws IOException,FileNotFoundException {546if (!headerHashtable.containsKey(headerBuffer.getHeaderName())) {547548StringBuffer buffer = new StringBuffer();549buffer.append(headerBuffer.toString());550551if (differentFromCopyOnDisk(headerPath + headerBuffer.getHeaderName(), buffer)){552File headerFile = new File(headerPath + headerBuffer.getHeaderName());553FileWriter headerFileWriter = new FileWriter(headerFile);554headerFileWriter.write(headerBuffer.toString());555headerHashtable.put(headerPath + headerBuffer.getHeaderName(), headerBuffer);556headerFileWriter.close();557dp("** Generated " + headerFile.getPath());558totalHeaderFilesCreated++;559}else{560totalHeaderFilesSkipped++;561dp("** Skipped writing [same as on file system]: " + headerPath + headerBuffer.getHeaderName());562}563} else {564HeaderBuffer oldBuffer = (HeaderBuffer) headerHashtable.get(headerBuffer.getHeaderName());565if (!oldBuffer.equals(headerBuffer))566failure("Header files generated from " + oldBuffer.getNLSFileName() + " and " + nlsFile.getName()567+ " do not match");568headerBuffer.clear();569}570}571572protected Hashtable searchNLSFiles() {573dp("Searching for nls files...");574Vector dirToSearch = new Vector();575oldNLSFiles = new Hashtable();576localeHashtable = new Hashtable();577dirToSearch.addElement(new File(sourceDirectory + fileSeparator + "nls" + fileSeparator));578String files[];579580while (dirToSearch.size() > 0) {581File dir = (File) dirToSearch.elementAt(0);582dirToSearch.remove(0);583if (!dir.exists() || ! dir.isDirectory()) {584failure("Failed to open directory - " + dir);585}586files = dir.list();587for (int i = 0; i < files.length; i++) {588File file = new File(dir, files[i]);589if (file.isDirectory())590dirToSearch.insertElementAt(file, 0);591else if (file.getName().endsWith(".nls")) {592dp("Found " + file.getPath());593String locale = getLocale(file.getName());594if (!localeHashtable.containsKey(locale)) {595dp("Found a new locale: " + getLocaleName(locale));596Vector temp = new Vector();597temp.add(file);598localeHashtable.put(locale, temp);599} else {600((Vector) localeHashtable.get(locale)).add(file);601}602totalNLSFilesFound++;603} else if (file.getName().endsWith(".nls.old")) {604dp("Found " + file.getPath());605oldNLSFiles.put(file.getName(), file);606}607}608}609dp("");610611return localeHashtable;612}613614private String getKey(String line) {615if (line.indexOf('=') != -1)616return line.substring(0, line.indexOf('='));617else618return null;619}620621protected Vector getOrderedKeys(Properties nlsProperties, File nlsFile) throws IOException {622Vector keys = new Vector();623FileReader nlsFileReader = new FileReader(nlsFile);624BufferedReader bufferedNLSReader = new BufferedReader(nlsFileReader);625String line;626while ((line = bufferedNLSReader.readLine()) != null) {627String key = getKey(line);628if (key != null && !isSpecialKey(key)) {629if (keys.contains(key))630failure("Duplicate keys are found in " + nlsFile.getPath() + ": " + key, false);631if (nlsProperties.containsKey(key))632keys.add(key);633}634}635bufferedNLSReader.close();636637return keys;638}639640private String getNameWithLocale(String fileName, String locale) {641return workingDirectory + fileSeparator + fileName.substring(0, propertiesFileName.lastIndexOf('.')) + locale642+ fileName.substring(propertiesFileName.lastIndexOf('.'));643}644645protected String formatMsgNumber(int msgNumber) {646String currentMsgNumber = String.valueOf(msgNumber);647while (currentMsgNumber.length() < DEFAULT_MESSAGE_NUMBER_LENGTH)648currentMsgNumber = "0" + currentMsgNumber;649return currentMsgNumber;650}651652private String getLocale(String nlsFileName) {653if (nlsFileName.lastIndexOf('_') != -1)654return nlsFileName.substring(nlsFileName.indexOf('_'), nlsFileName.lastIndexOf("."));655else656return DEFAULT_LOCALE;657}658659private String getLocaleName(String locale) {660if (locale.equals(DEFAULT_LOCALE))661return "\'default\'";662else663return "\'" + locale.substring(1) + "\'";664}665666private void summarize() {667System.out.println("\n************************************************\n");668System.out.println("\tTotal # of locales processed:\t\t" + localeHashtable.size());669System.out.println("\tTotal # of NLS Files processed:\t\t" + totalNLSFilesFound);670System.out.println("\tTotal # of messages processed:\t\t" + totalMessagesProcessed + "\n");671System.out.println("\tTotal # of header files generated:\t" + totalHeaderFilesCreated);672if (totalHeaderFilesSkipped > 0) {673System.out.println("\tTotal # of unchanged header files:\t" + totalHeaderFilesSkipped);674}675System.out.println("\tTotal # of properties files generated:\t" + totalPropertiesFilesCreated);676if (totalPropertiesFilesSkipped > 0) {677System.out.println("\tTotal # of unchanged properties files:\t" + totalPropertiesFilesSkipped);678}679if (totalPalmFilesCreated > 0) {680System.out.println("\tTotal # of palm files generated:\t" + totalPalmFilesCreated);681}682if (totalPalmFilesSkipped > 0) {683System.out.println("\tTotal # of unchanged palm files:\t" + totalPalmFilesSkipped);684}685System.out.println("\tTotal # of errors:\t\t\t" + errorCount);686System.out.println("\n************************************************\n");687688if (errorCount > 0) {689System.exit(1);690}691}692693private void printUsage() {694System.out.println("J9 NLS Tool 1.2");695System.out.println("Usage: J9NLS [options]\n");696System.out.println("[options]");697System.out.println(" -help prints this message");698System.out.println(" -out xxx generates output named as xxx");699System.out.println(" -source path to the source directory");700System.out.println(" -[no]html xxx [do not] generates HTML file, which contains output results, named as xxx");701System.out.println(" -palm generates output as Palm resources\n");702System.out.println(" -debug generates informational output\n");703System.out.println("Defaults are:");704System.out.println(" -out " + propertiesFileName + "-html" + htmlFileName);705System.out.println(" -source . ");706}707708private void failure(String msg) {709failure(msg, true);710}711712private void failure(String msg, boolean fatal) {713System.out.println("\n* Failure occured during the process *");714System.out.println("Error: " + msg);715errorCount++;716if (fatal) {717summarize();718}719}720721private class HeaderBuffer {722StringBuffer buffer;723String headerName;724String NLSFileName;725726public HeaderBuffer(String headerName, String NLSFileName) {727this.headerName = headerName;728this.NLSFileName = NLSFileName;729buffer = new StringBuffer("");730}731732public String toString() {733return buffer.toString();734}735736public boolean equals(Object arg) {737HeaderBuffer other = (HeaderBuffer) arg;738if (null != other) {739return other.buffer.toString().equals(buffer.toString());740}741return super.equals(arg);742}743744public void append(String s) {745buffer.append(s);746}747748public void clear() {749buffer.delete(0, buffer.length());750}751752public String getHeaderName() {753return headerName;754}755756public String getNLSFileName() {757return NLSFileName;758}759760private String getAscii(String moduleName) {761String asciiModuleName = "0x";762for (int i = 0; i < moduleName.length(); i++)763asciiModuleName += Integer.toHexString(moduleName.charAt(i));764return asciiModuleName;765}766767public void appendMsg(String moduleName, String key) {768String defModule = key + "__MODULE";769String defID = key + "__ID";770append("#define " + defModule + " " + getAscii(moduleName) + "\n");771append("#define " + defID + " " + messageNumber + "\n");772append("#define " + key + " " + defModule + ", " + defID + "\n");773}774775public void writeHeader(String headerName, String moduleName) {776String header = headerName.replace('.', '_');777append("/*\n");778append(" * Copyright (c) 1991, 2017 IBM Corp. and others\n");779append(" *\n");780append(" * This program and the accompanying materials are made available under\n");781append(" * the terms of the Eclipse Public License 2.0 which accompanies this\n");782append(" * distribution and is available at https://www.eclipse.org/legal/epl-2.0/\n");783append(" * or the Apache License, Version 2.0 which accompanies this distribution and\n");784append(" * is available at https://www.apache.org/licenses/LICENSE-2.0.\n");785append(" *\n");786append(" * This Source Code may also be made available under the following\n");787append(" * Secondary Licenses when the conditions for such availability set\n");788append(" * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU\n");789append(" * General Public License, version 2 with the GNU Classpath\n");790append(" * Exception [1] and GNU General Public License, version 2 with the\n");791append(" * OpenJDK Assembly Exception [2].\n");792append(" *\n");793append(" * [1] https://www.gnu.org/software/classpath/license.html\n");794append(" * [2] http://openjdk.java.net/legal/assembly-exception.html\n");795append(" *\n");796append(" * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception\n");797append(" */\n\n");798append("#ifndef " + header + "\n");799append("#define " + header + "\n\n");800append("#include \"j9port.h\"\n");801append("/* " + getAscii(moduleName) + " = " + moduleName + " */\n\n");802}803}804805private String toHexString(byte[] b) {806final char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };807StringBuffer stringBuffer = new StringBuffer();808for (int i = 0; i < b.length; i++) {809stringBuffer.append("0x");810stringBuffer.append(hexChar[(b[i] & 0xf0) >>> 4]);811stringBuffer.append(hexChar[b[i] & 0x0f]);812stringBuffer.append(' ');813}814return stringBuffer.toString();815}816817/**818* Checks if a file with given name exists on disk. Returns true if it does819* not exist. If the file exists, compares it with generated buffer and820* returns true if they are equals. Also it deletes old file from the file821* system.822*823* @param fileName824* @param buffer825* @return boolean TRUE|FALSE826* @throws FileNotFoundException827* @throws IOException828*/829public static boolean differentFromCopyOnDisk(String fileName, StringBuffer buffer) throws FileNotFoundException, IOException{830File fileOnDisk = new File (fileName);831if (!fileOnDisk.exists()){832return true;833}834835StringBuffer fileBuffer = new StringBuffer();836FileReader fr = new FileReader(fileOnDisk);837char []charArray = new char[1024];838839int numRead = -1;840while ( (numRead = fr.read(charArray)) != -1 ) {841fileBuffer.append(charArray, 0, numRead);842}843844if ( buffer.toString().equals(fileBuffer.toString()) ) {845fr.close();846return false;847}848849fr.close();850851//delete file here, will write new file later852fileOnDisk.delete();853854return true;855}856857/**858* Compares given properties file with the generated properties.859* Returns true if they do not match, otherwise returns false.860* It also deletes the file from the file system, if it exists.861*862* @param fileName863* @return boolean TRUE|FALSE864* @throws FileNotFoundException865* @throws IOException866*/867private boolean propertiesDifferentFromCopyOnDisk(String fileName) throws FileNotFoundException, IOException{868File fileOnDisk = new File(fileName);869if (!fileOnDisk.exists()) {870return true;871}872873//load the file874Properties oldProperties = new Properties();875FileInputStream in = new FileInputStream(fileOnDisk);876oldProperties.load(in);877in.close();878879boolean isDifferent = false;880if (!oldProperties.keySet().equals(outputProperties.keySet())){881isDifferent = true;882}else{883//compare messages884Iterator keyIterator = oldProperties.keySet().iterator();885while (keyIterator.hasNext()){886if (!outputProperties.containsValue(oldProperties.getProperty(String.valueOf(keyIterator.next())))){887isDifferent = true;888break;889}890}891}892893if (isDifferent) {894//delete old file here, will generate new file later895fileOnDisk.delete();896}897898return isDifferent;899}900}901902903