/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo 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 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.netbeans.lib.cvsclient.commandLine.command; import java.io.File; import java.io.PrintStream; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.ResourceBundle; import org.netbeans.lib.cvsclient.command.Command; import org.netbeans.lib.cvsclient.command.FileInfoContainer; import org.netbeans.lib.cvsclient.command.GlobalOptions; import org.netbeans.lib.cvsclient.command.annotate.AnnotateCommand; import org.netbeans.lib.cvsclient.command.annotate.AnnotateInformation; import org.netbeans.lib.cvsclient.command.annotate.AnnotateLine; import org.netbeans.lib.cvsclient.commandLine.GetOpt; import org.netbeans.lib.cvsclient.commandLine.ListenerProvider; import org.netbeans.lib.cvsclient.event.CVSAdapter; import org.netbeans.lib.cvsclient.event.CVSListener; /** * The locbundlecheck command * * @author Milos Kleint */ public class locbundlecheck extends CVSAdapter implements CommandProvider { /** * A constructor that is used to create the CommandProvider. */ public locbundlecheck() { } @Override public String getName() { return "locbundlecheck"; // NOI18N } @Override public String[] getSynonyms() { return new String[] { "lbch", "lbcheck" }; // NOI18N } @Override public String getUsage() { return ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString("locbundlecheck.usage"); // NOI18N } @Override public void printShortDescription(PrintStream out) { String msg = ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString( "locbundlecheck.shortDescription"); // NOI18N out.print(msg); } @Override public void printLongDescription(PrintStream out) { String msg = ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString( "locbundlecheck.longDescription"); // NOI18N out.println(msg); } @Override public Command createCommand(String[] args, int index, GlobalOptions gopt, String workDir) { LocBundleAnnotateCommand command = new LocBundleAnnotateCommand(); final String getOptString = command.getOptString(); GetOpt go = new GetOpt(args, getOptString + "i:"); int ch = -1; go.optIndexSet(index); boolean usagePrint = false; String arg; String localization = null; while ((ch = go.getopt()) != GetOpt.optEOF) { if (ch == 'i') { localization = go.optArgGet(); command.setLocalization(localization); } else { boolean ok = command.setCVSCommand((char) ch, go.optArgGet()); if (!ok) { usagePrint = true; } } } if (usagePrint || localization == null) { throw new IllegalArgumentException(getUsage()); } int fileArgsIndex = go.optIndexGet(); // test if we have been passed any file arguments if (fileArgsIndex < args.length) { Collection fls = new ArrayList(); // send the arguments as absolute paths if (workDir == null) { workDir = System.getProperty("user.dir"); } command.setWorkDir(workDir); File workingDir = new File(workDir); for (int i = fileArgsIndex; i < args.length; i++) { File fl = new File(workingDir, args[i]); // System.out.println("file=" + fl); if (fl.exists() && fl.isDirectory()) { addFilesInDir(fls, fl, localization); } else if (fl.exists() && fl.getName().endsWith(".properties")) { addFiles(fls, fl, localization); } else { throw new IllegalArgumentException(); } } if (fls.size() > 0) { File[] fileArgs = new File[fls.size()]; fileArgs = (File[]) fls.toArray(fileArgs); command.setFiles(fileArgs); } else { throw new IllegalArgumentException(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.no_file_spec")); } } return command; } private static void addFiles(Collection fileList, File origFile, String localization) { String origPath = origFile.getAbsolutePath(); String enarg = origPath.substring(0, origPath.length() - ".properties".length()) + "_" + localization + ".properties"; // System.out.println("enarg=" + enarg); File addfl = new File(enarg); fileList.add(origFile); if (addfl.exists()) { fileList.add(addfl); } else { // TODO } } private static void addFilesInDir(Collection fileList, File origFile, String localization) { File[] files = origFile.listFiles(); if (files != null && files.length > 0) { for (int i = 0; i < files.length; i++) { if (files[i].exists() && files[i].isDirectory()) { addFilesInDir(fileList, files[i], localization); } else if (files[i].exists() && "Bundle.properties".equals(files[i].getName())) { addFiles(fileList, files[i], localization); } } } } private PrintStream out; private PrintStream err; private int realEnd = 0; private HashMap originalBundles; private HashMap localizedBundles; private String local; private String workDir; /** * A constructor that is used to create the CVSAdapter. */ locbundlecheck(PrintStream stdout, PrintStream stderr, String localization, String workDir) { out = stdout; err = stderr; originalBundles = new HashMap(); localizedBundles = new HashMap(); local = localization; this.workDir = workDir; } @Override public void fileInfoGenerated(org.netbeans.lib.cvsclient.event.FileInfoEvent e) { // out.println("annotated " + e.getInfoContainer().getFile()); FileInfoContainer cont = e.getInfoContainer(); if (cont.getFile().getName().indexOf("_" + local) >= 0) { localizedBundles.put(cont.getFile().getAbsolutePath(), cont); } else { originalBundles.put(cont.getFile().getAbsolutePath(), cont); } // out.println("orig size=" + originalBundles.keySet().size() + " loc size=" + localizedBundles.keySet().size()); if (realEnd == 2) { // generate output. // out.println("generating output...."); generateOutput(); } } @Override public void commandTerminated(org.netbeans.lib.cvsclient.event.TerminationEvent e) { if (realEnd == 0) { // now the event is triggered because of the validresponses request realEnd = 1; return; } realEnd = 2; // the second time it's the real end. waiting for the last info object to be received. // out.println("finish=" + e.isError()); } private void generateOutput() { Iterator it = originalBundles.keySet().iterator(); while (it.hasNext()) { String origPath = (String) it.next(); int dotIndex = origPath.lastIndexOf("."); if (dotIndex < 0) { throw new IllegalStateException(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.illegal_state")); } String locPath = origPath.substring(0, dotIndex) + "_" + local + origPath.substring(dotIndex); // System.out.println("locpath=" + locPath); AnnotateInformation origInfo = (AnnotateInformation) originalBundles.get(origPath); AnnotateInformation locInfo = (AnnotateInformation) localizedBundles.get(locPath); if (locInfo == null) { out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.noLocalizedFile"), new Object[] { origPath })); continue; } // remove from locl bundles to figure out what was removed in the original.. localizedBundles.remove(locPath); HashMap origPropMap = createPropMap(origInfo); HashMap locPropMap = createPropMap(locInfo); String printFile = origPath; if (origPath.startsWith(workDir)) { printFile = origPath.substring(workDir.length()); if (printFile.startsWith("/") || printFile.startsWith("\\")) { printFile = printFile.substring(1); } } out.println(MessageFormat.format( ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle").getString("locbundlecheck.File"), new Object[] { printFile })); Iterator propIt = origPropMap.keySet().iterator(); while (propIt.hasNext()) { String prop = (String) propIt.next(); AnnotateLine origLine = (AnnotateLine) origPropMap.get(prop); AnnotateLine locLine = (AnnotateLine) locPropMap.get(prop); if (locLine == null) { out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.propMissing"), new Object[] { prop })); continue; } // System.out.println("prop=" + prop); // System.out.println("orig date:" + origLine.getDate()); // System.out.println("loc date:" + locLine.getDate()); if (origLine.getDate().compareTo(locLine.getDate()) > 0) { out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.prop_updated"), new Object[] { prop })); } } } if (localizedBundles.size() > 0) { Iterator locIt = localizedBundles.keySet().iterator(); while (locIt.hasNext()) { String prop = (String) locIt.next(); out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle") .getString("locbundlecheck.prop_removed"), new Object[] { prop })); } } } private HashMap createPropMap(AnnotateInformation info) { HashMap propMap = new HashMap(); AnnotateLine line = info.getFirstLine(); while (line != null) { String content = line.getContent(); if (content.startsWith("#")) { // ignore commented lines. line = info.getNextLine(); continue; } int index = content.indexOf('='); if (index > 0) { String key = content.substring(0, index); propMap.put(key, line); } else { // TODO.. for properties that span across multiple lines, one should take all lines into account } line = info.getNextLine(); } return propMap; } private static class LocBundleAnnotateCommand extends AnnotateCommand implements ListenerProvider { private String loc; private String workDir; @Override public CVSListener createCVSListener(PrintStream stdout, PrintStream stderr) { return new locbundlecheck(stdout, stderr, loc, workDir); } public void setLocalization(String loc) { this.loc = loc; } public void setWorkDir(String dir) { workDir = dir; } } }