From a6202291e526e07fbc7682cecc1c824af3c626cf Mon Sep 17 00:00:00 2001 From: Andrew J Macheret Date: Wed, 14 Mar 2007 02:23:37 +0000 Subject: [PATCH] ICU-5606 finished everything on the todo lists and then some. X-SVN-Rev: 21240 --- icu4j/build.xml | 3 +- .../com/ibm/icu/dev/tool/tzu/CLILoader.java | 210 ++++++++++++------ .../com/ibm/icu/dev/tool/tzu/GUILoader.java | 180 ++++++++++++--- .../src/com/ibm/icu/dev/tool/tzu/ICUFile.java | 145 +++++++++--- .../ibm/icu/dev/tool/tzu/ICUJarFinder.java | 49 ++-- .../com/ibm/icu/dev/tool/tzu/ICUTZUMain.java | 79 ++++++- .../com/ibm/icu/dev/tool/tzu/IncludePath.java | 12 +- .../src/com/ibm/icu/dev/tool/tzu/Logger.java | 121 +++++++++- .../ibm/icu/dev/tool/tzu/PathComponent.java | 76 ++++--- .../com/ibm/icu/dev/tool/tzu/PathModel.java | 82 ++++--- .../ibm/icu/dev/tool/tzu/ResultComponent.java | 115 ++++++++-- .../com/ibm/icu/dev/tool/tzu/ResultModel.java | 92 +++++--- .../com/ibm/icu/dev/tool/tzu/SourceModel.java | 53 +++-- .../com/ibm/icu/dev/tool/tzu/runicutzu.bat | 6 +- 14 files changed, 887 insertions(+), 336 deletions(-) diff --git a/icu4j/build.xml b/icu4j/build.xml index 15c4d2d8e5..8d6a2ba3b4 100644 --- a/icu4j/build.xml +++ b/icu4j/build.xml @@ -100,7 +100,7 @@ - + @@ -2475,6 +2475,7 @@ + diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/CLILoader.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/CLILoader.java index 44ec47de34..fb299eb414 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/CLILoader.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/CLILoader.java @@ -9,43 +9,44 @@ package com.ibm.icu.dev.tool.tzu; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.net.URL; /** * Loads the ICUTZU tool, command-line version. */ public class CLILoader { /** - * An entry point for the ICUTZU tool that goes directly to command-line. - * Creates a new CLILoader object with args. + * Entry point for the command-line version of the tool. * - * @param args - * Arguments for the constructor. + * @param curDir + * The base directory of the tool. + * @param backupDir + * The location to store backups. + * @param pathFile + * The file to load paths from. + * @param resultFile + * The file to load/save results to/from. + * @param tzFile + * The local timezone resource file. */ - public static void main(String[] args) { - new CLILoader(args); - } - - /** - * Gets the logger instance, gets the backup directory from the arguments, - * - * @param args - * If args contains one element, that element is - * used as the backup directory for ICU4J jars when in patch - * mode. - */ - public CLILoader(String[] args) { + public CLILoader(File curDir, File backupDir, File pathFile, + File resultFile, File tzFile) { // create the logger based on the silentpatch option try { - this.logger = Logger.getInstance(Logger.DEFAULT_FILENAME, "true".equalsIgnoreCase(System - .getProperty("silentpatch")) ? Logger.QUIET : Logger.NORMAL); + this.logger = Logger + .getInstance(Logger.DEFAULT_FILENAME, + "true".equalsIgnoreCase(System + .getProperty("silentpatch")) ? Logger.QUIET + : Logger.NORMAL); } catch (FileNotFoundException ex) { - System.out.println("Could not open " + Logger.DEFAULT_FILENAME + " for writing."); + System.out.println("Could not open " + Logger.DEFAULT_FILENAME + + " for writing."); System.exit(-1); } - // get the backup directory from the arguments if it is in there - backupDir = (args.length == 1) ? new File(args[0]) : null; + this.pathFile = pathFile; + this.resultFile = resultFile; + this.tzFile = tzFile; + this.backupDir = backupDir; // if discoveryonly is enabled, call the search method // otherwise, call the update method @@ -65,26 +66,30 @@ public class CLILoader { } /** - * Discover Only Mode. Load the path list from - * PathModel.PATHLIST_FILENAME and save the path of each - * updatable ICU jar files it finds to - * PathModel.RESULTLIST_FILENAME + * Discover Only Mode. Load the path list from the path file and save the + * path of each updatable ICU jar files it finds to the result list * * @throws IOException * @throws IllegalArgumentException * @throws InterruptedException */ - private void search() throws IOException, IllegalArgumentException, InterruptedException { - logger.printlnToScreen("*********** Command-Line \'Discover Only\' Mode Started ***********"); + private void search() throws IOException, IllegalArgumentException, + InterruptedException { + logger.printlnToScreen(""); + logger.printlnToScreen("*********** Command-Line \'Discover Only\'" + + " Mode Started ***********"); + logger.printlnToScreen(""); logger.printlnToScreen("\'Discover Only\' Mode:"); - logger.printlnToScreen("\tIn this mode, the tool will search for ICU4J jars" + logger.printlnToScreen("\tIn this mode, " + + "the tool will search for ICU4J jars" + " in the directories specified in DirectorySearch.txt" + " and print the ICU4J jars detected and their respective" - + " time zone version to the file SDKList.txt"); + + " time zone version to the file ICUList.txt"); + logger.printlnToScreen(""); // initialize the result model and the path model - resultModel = new ResultModel(logger); - pathModel = new PathModel(logger); + resultModel = new ResultModel(logger, resultFile); + pathModel = new PathModel(logger, pathFile); // load paths stored in PathModel.PATHLIST_FILENAME pathModel.loadPaths(); @@ -93,15 +98,21 @@ public class CLILoader { // searching all subdirectories of the included path, using the backup // directory specified, and without using a status bar (since this is // command-line) - pathModel.searchAll(resultModel, true, backupDir, null); + pathModel.searchAll(resultModel, true, curDir, backupDir); // save the results in PathModel.RESULTLIST_FILENAME resultModel.saveResults(); + + logger.printlnToScreen(""); + logger.printlnToScreen("Please run with DISCOVERYONLY=false" + + " in order to update ICU4J jars listed in ICUList.txt"); + logger.printlnToScreen("*********** Command-Line \'Discover Only\'" + + " Mode Ended ***********"); + logger.printlnToScreen(""); } /** - * Patch Mode. Load all the results from - * PathModel.RESULTLIST_FILENAME, populate the tz version + * Patch Mode. Load all the results from resultFile, populate the tz version * list via the web, and update all the results with the best available Time * Zone data. * @@ -109,17 +120,21 @@ public class CLILoader { * @throws IllegalArgumentException * @throws InterruptedException */ - private void update() throws IOException, IllegalArgumentException, InterruptedException { - logger.printlnToScreen("*********** Command-Line \'Patch\' Mode Started ***********"); + private void update() throws IOException, IllegalArgumentException, + InterruptedException { + logger.printlnToScreen(""); + logger.printlnToScreen("*********** Command-Line \'Patch\'" + + " Mode Started ***********"); logger.printlnToScreen(""); logger.printlnToScreen("\'Patch\' Mode:"); - logger.printlnToScreen("\tIn this mode, the tool patches each of the ICU4J jars" - + " listed in ICUList.txt with the new time zone information."); + logger.printlnToScreen("\tIn this mode, the tool patches each of the" + + " ICU4J jars listed in ICUList.txt with the new time zone" + + " information."); logger.printlnToScreen(""); // initialize the result model and the source model - resultModel = new ResultModel(logger); - sourceModel = new SourceModel(logger); + resultModel = new ResultModel(logger, resultFile); + sourceModel = new SourceModel(logger, tzFile); // load the results from the result list file resultModel.loadResults(); @@ -128,7 +143,13 @@ public class CLILoader { sourceModel.findSources(); // perform the updates using the best tz version available - resultModel.updateAll((URL) sourceModel.getSelectedItem(), backupDir); + resultModel.updateAll( + sourceModel.getURL(sourceModel.getSelectedItem()), backupDir); + + logger.printlnToScreen(""); + logger.printlnToScreen("*********** Command-Line \'Patch\'" + + " Mode Ended ***********"); + logger.printlnToScreen(""); } /** @@ -149,12 +170,32 @@ public class CLILoader { */ private SourceModel sourceModel; + /** + * The file that stores the path list. + */ + private File pathFile = null; + + /** + * The file that stores the result list. + */ + private File resultFile = null; + + /** + * The local timezone resource file. + */ + private File tzFile = null; + /** * The backup directory to use in patch mode, or null if there should be no * backups. */ private File backupDir = null; + /** + * The current directory. + */ + private File curDir = null; + /** * A logger that manages both output to the screen and to the log file. */ @@ -163,7 +204,7 @@ public class CLILoader { /** * Old code... removed for a variety of reasons, but most importantly * because DISCOVERY_ONLY must be implemented correctly and there were - * conflicts with the argument structure. + * conflicts with the old argument structure. * *
      * public CLILoader(String[] args) {
@@ -182,10 +223,13 @@ public class CLILoader {
      *         }
      *         try { // init the
      *             // logger
-     *             logger = Logger.getInstance(Logger.DEFAULT_FILENAME, options[QUIET].doesOccur ? Logger.QUIET
-     *                     : options[VERBOSE].doesOccur ? Logger.VERBOSE : Logger.NORMAL);
+     *             logger = Logger.getInstance(Logger.DEFAULT_FILENAME,
+     *                     options[QUIET].doesOccur ? Logger.QUIET
+     *                             : options[VERBOSE].doesOccur ? Logger.VERBOSE
+     *                                     : Logger.NORMAL);
      *         } catch (FileNotFoundException ex) {
-     *             System.out.println("Could not open " + Logger.DEFAULT_FILENAME + " for writing.");
+     *             System.out.println("Could not open " + Logger.DEFAULT_FILENAME
+     *                     + " for writing.");
      *             System.exit(-1);
      *         }
      *         // create the resultModel, the pathModel, and the sourceModel
@@ -195,8 +239,10 @@ public class CLILoader {
      *         // make sure the result model hides unreadable/unwritable files
      *         resultModel.setHidden(false);
      *         // make sure only there is only one update mode in the options
-     *         int choiceType = (options[OFFLINE].doesOccur ? 1 : 0) + (options[TZVERSION].doesOccur ? 1 : 0)
-     *                 + (options[BEST].doesOccur ? 1 : 0) + (options[DISCOVERONLY].doesOccur ? 1 : 0);
+     *         int choiceType = (options[OFFLINE].doesOccur ? 1 : 0)
+     *                 + (options[TZVERSION].doesOccur ? 1 : 0)
+     *                 + (options[BEST].doesOccur ? 1 : 0)
+     *                 + (options[DISCOVERONLY].doesOccur ? 1 : 0);
      *         if (choiceType > 1)
      *             syntaxError("Options -o (--offline), -t (--tzversion), -b (--best) and -d (--discoveronly) are mutually exclusive");
      *         // make sure that quiet & verbose do not both occur
@@ -227,7 +273,8 @@ public class CLILoader {
      *         // if we're running offline and the local file doesnt exist, we
      *         // can't update anything
      * 
-     *         if (options[OFFLINE].doesOccur && !SourceModel.TZ_LOCAL_FILE.exists() && !options[DISCOVERONLY].doesOccur)
+     *         if (options[OFFLINE].doesOccur && !SourceModel.TZ_LOCAL_FILE.exists()
+     *                 && !options[DISCOVERONLY].doesOccur)
      *             throw new IllegalArgumentException(
      *                     "Running offline mode but local file does not exist (no sources available)");
      *         // if the user did not specify to stay offline, go online and find
@@ -268,19 +315,24 @@ public class CLILoader {
      *         }
      *         // (do nothing in the case of DISCOVERONLY)
      *         // create a reader for user input
-     *         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+     *         BufferedReader reader = new BufferedReader(new InputStreamReader(
+     *                 System.in));
      *         // iterate through each icu4j file in the search results
      *         Iterator resultIter = resultModel.iterator();
      *         while (resultIter.hasNext()) {
      *             try {
      *                 ICUFile entry = (ICUFile) resultIter.next();
      *                 logger.println("", Logger.NORMAL);
-     *                 logger.println("Filename: " + entry.getFile().getName(), Logger.NORMAL);
-     *                 logger.println("Location: " + entry.getFile().getParent(), Logger.NORMAL);
-     *                 logger.println("Current Version: " + entry.getTZVersion(), Logger.NORMAL);
+     *                 logger.println("Filename: " + entry.getFile().getName(),
+     *                         Logger.NORMAL);
+     *                 logger.println("Location: " + entry.getFile().getParent(),
+     *                         Logger.NORMAL);
+     *                 logger.println("Current Version: " + entry.getTZVersion(),
+     *                         Logger.NORMAL);
      * 
      *                 if (!entry.getFile().canRead() || !entry.getFile().canWrite()) {
-     *                     logger.println("Missing permissions for " + entry.getFile().getName() + ".", Logger.NORMAL);
+     *                     logger.println("Missing permissions for "
+     *                             + entry.getFile().getName() + ".", Logger.NORMAL);
      *                     continue;
      *                 }
      * 
@@ -290,7 +342,8 @@ public class CLILoader {
      *                         update(entry, chosenName, chosenURL);
      *                 } else if (choiceType == 1) // confirmation mode
      *                 {
-     *                     String input = askConfirm(chosenName, chosenVersion, entry.getTZVersion(), reader);
+     *                     String input = askConfirm(chosenName, chosenVersion, entry
+     *                             .getTZVersion(), reader);
      * 
      *                     if ("yes".startsWith(input))
      *                         update(entry, chosenName, chosenURL);
@@ -304,7 +357,8 @@ public class CLILoader {
      *                     else if ("local choice".startsWith(input))
      *                         update(entry, getLocalName(), getLocalURL());
      *                     else if (!"none".startsWith(input))
-     *                         update(entry, getTZVersionName(input), getTZVersionURL(input));
+     *                         update(entry, getTZVersionName(input),
+     *                                 getTZVersionURL(input));
      *                     else
      *                         skipUpdate();
      *                 }
@@ -322,14 +376,18 @@ public class CLILoader {
      *     }
      * }
      * 
-     * private String askConfirm(String chosenString, String chosenVersion, String currentVersion, BufferedReader reader)
-     *         throws IOException {
+     * private String askConfirm(String chosenString, String chosenVersion,
+     *         String currentVersion, BufferedReader reader) throws IOException {
      *     int betterness = chosenVersion.compareToIgnoreCase(currentVersion);
      *     if (betterness == 0) {
-     *         logger.println("Updating should have no effect on this file.", Logger.NORMAL);
+     *         logger.println("Updating should have no effect on this file.",
+     *                 Logger.NORMAL);
      *         logger.println("Update anyway?", Logger.NORMAL);
      *     } else if (betterness < 0) {
-     *         logger.println("Warning: The version specified is older than the one present in the file.", Logger.NORMAL);
+     *         logger
+     *                 .println(
+     *                         "Warning: The version specified is older than the one present in the file.",
+     *                         Logger.NORMAL);
      *         logger.println("Update anyway?", Logger.NORMAL);
      *     } else {
      *         logger.println("Update to " + chosenVersion + "?", Logger.NORMAL);
@@ -345,11 +403,14 @@ public class CLILoader {
      * 
      *     logger.println(getLocalName(), Logger.NORMAL);
      *     while (sourceIter.hasNext())
-     *         logger.println(", " + ((Map.Entry) sourceIter.next()).getKey(), Logger.NORMAL);
+     *         logger.println(", " + ((Map.Entry) sourceIter.next()).getKey(),
+     *                 Logger.NORMAL);
      *     logger.println("", Logger.NORMAL);
      * 
-     *     logger.println("Update to which version? [best (default), none, local copy, <specific version above>]",
-     *             Logger.NORMAL);
+     *     logger
+     *             .println(
+     *                     "Update to which version? [best (default), none, local copy, <specific version above>]",
+     *                     Logger.NORMAL);
      *     logger.println(": ", Logger.NORMAL);
      *     return reader.readLine().trim().toLowerCase();
      * }
@@ -402,7 +463,8 @@ public class CLILoader {
      * 
      * private URL getTZVersionURL(String version) {
      *     try {
-     *         return new URL(SourceModel.TZ_BASE_URLSTRING_START + version + SourceModel.TZ_BASE_URLSTRING_END);
+     *         return new URL(SourceModel.TZ_BASE_URLSTRING_START + version
+     *                 + SourceModel.TZ_BASE_URLSTRING_END);
      *     } catch (MalformedURLException ex) {
      *         ex.printStackTrace();
      *         return null;
@@ -417,12 +479,18 @@ public class CLILoader {
      *     throw new IllegalArgumentException("Error in argument list: " + message);
      * }
      * 
-     * private static UOption options[] = new UOption[] { UOption.create("help", '?', UOption.NO_ARG),
-     *         UOption.create("verbose", 'v', UOption.NO_ARG), UOption.create("quiet", 'q', UOption.NO_ARG),
-     *         UOption.create("auto", 'a', UOption.NO_ARG), UOption.create("offline", 'o', UOption.NO_ARG),
-     *         UOption.create("best", 's', UOption.NO_ARG), UOption.create("tzversion", 't', UOption.REQUIRES_ARG),
-     *         UOption.create("recurse", 'r', UOption.NO_ARG), UOption.create("backup", 'b', UOption.REQUIRES_ARG),
-     *         UOption.create("nobackup", 'B', UOption.NO_ARG), UOption.create("discoveronly", 'd', UOption.NO_ARG), };
+     * private static UOption options[] = new UOption[] {
+     *         UOption.create("help", '?', UOption.NO_ARG),
+     *         UOption.create("verbose", 'v', UOption.NO_ARG),
+     *         UOption.create("quiet", 'q', UOption.NO_ARG),
+     *         UOption.create("auto", 'a', UOption.NO_ARG),
+     *         UOption.create("offline", 'o', UOption.NO_ARG),
+     *         UOption.create("best", 's', UOption.NO_ARG),
+     *         UOption.create("tzversion", 't', UOption.REQUIRES_ARG),
+     *         UOption.create("recurse", 'r', UOption.NO_ARG),
+     *         UOption.create("backup", 'b', UOption.REQUIRES_ARG),
+     *         UOption.create("nobackup", 'B', UOption.NO_ARG),
+     *         UOption.create("discoveronly", 'd', UOption.NO_ARG), };
      * 
      * private static final int HELP = 0;
      * 
diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/GUILoader.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/GUILoader.java
index 64d654b2cb..7527fd7230 100644
--- a/icu4j/src/com/ibm/icu/dev/tool/tzu/GUILoader.java
+++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/GUILoader.java
@@ -6,44 +6,56 @@
  */
 package com.ibm.icu.dev.tool.tzu;
 
+import java.awt.Image;
+import java.awt.Toolkit;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.net.URL;
 
 import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 import javax.swing.WindowConstants;
-import javax.swing.text.JTextComponent;
 
+/**
+ * Loads the ICUTZU tool, GUI version.
+ */
 public class GUILoader {
-    public static void main(String[] args) {
-        new GUILoader(args);
-    }
+    /**
+     * Entry point for the GUI version of the tool.
+     * 
+     * @param curDir
+     *            The base directory of the tool.
+     * @param backupDir
+     *            The location to store backups.
+     * @param pathFile
+     *            The file to load paths from.
+     * @param resultFile
+     *            The file to load/save results to/from.
+     * @param tzFile
+     *            The local timezone resource file.
+     * @param iconFile
+     *            The icon file.
+     */
+    public GUILoader(File curDir, File backupDir, File pathFile,
+            File resultFile, File tzFile, File iconFile) {
+        // set the backup dir
+        this.backupDir = backupDir;
+        this.curDir = curDir;
 
-    public GUILoader(String[] args) {
-        try {
-            logger = Logger.getInstance(Logger.DEFAULT_FILENAME, Logger.NORMAL);
-        } catch (FileNotFoundException ex) {
-            String error = "Could not open " + Logger.DEFAULT_FILENAME + " for writing.";
-            System.out.println(error);
-            JOptionPane.showMessageDialog(null, error, TITLE, JOptionPane.ERROR_MESSAGE);
-            System.exit(-1);
-        }
-        resultModel = new ResultModel(logger);
-        pathModel = new PathModel(logger);
-        sourceModel = new SourceModel(logger);
+        // get the icon
+        Image icon = Toolkit.getDefaultToolkit().getImage(iconFile.getPath());
 
-        pathGUI = new PathComponent(this, pathModel);
+        // initialize the path list gui
+        pathGUI = new PathComponent(this);
         pathFrame = new JFrame(TITLE + " - Search Paths");
         pathFrame.getContentPane().add(pathGUI);
         pathFrame.pack();
-        // pathFrame.setLocationRelativeTo(null);
-
         pathFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
+        pathFrame.setIconImage(icon);
         pathFrame.addWindowListener(new WindowAdapter() {
-            @Override
             public void windowClosing(WindowEvent event) {
                 if (resultClosed)
                     System.exit(0);
@@ -51,15 +63,14 @@ public class GUILoader {
             }
         });
 
-        resultGUI = new ResultComponent(this, resultModel, sourceModel);
+        // initialize the result list gui
+        resultGUI = new ResultComponent(this);
         resultFrame = new JFrame(TITLE + " - Updatable ICU4J Jars");
         resultFrame.getContentPane().add(resultGUI);
         resultFrame.pack();
-        // resultFrame.setLocationRelativeTo(null);
-
         resultFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
+        resultFrame.setIconImage(icon);
         resultFrame.addWindowListener(new WindowAdapter() {
-            @Override
             public void windowClosing(WindowEvent event) {
                 if (pathClosed)
                     System.exit(0);
@@ -68,17 +79,59 @@ public class GUILoader {
             }
         });
 
-        statusBar = resultGUI.getStatusBar();
+        // get the logger instance
+        try {
+            logger = Logger.getInstance(Logger.DEFAULT_FILENAME, Logger.NORMAL,
+                    resultGUI.getStatusBar(), pathFrame);
+        } catch (FileNotFoundException ex) {
+            String error = "Could not open " + Logger.DEFAULT_FILENAME
+                    + " for writing.";
+            System.out.println(error);
+            JOptionPane.showMessageDialog(null, error, TITLE,
+                    JOptionPane.ERROR_MESSAGE);
+            System.exit(-1);
+        }
 
-        backupDir = (args.length == 1) ? new File(args[0]) : null;
+        // initialize the models
+        resultModel = new ResultModel(logger, resultFile);
+        pathModel = new PathModel(logger, pathFile);
+        sourceModel = new SourceModel(logger, tzFile);
 
+        // attach the models to the guis
+        resultGUI.setResultModel(resultModel);
+        pathGUI.setPathModel(pathModel);
+        resultGUI.setSourceModel(sourceModel);
+
+        // load all the paths into the path model
+        try {
+            pathModel.loadPaths();
+        } catch (IOException ex) {
+            // failed to load the directory search file
+            pathModel.addAllDrives();
+        } catch (IllegalArgumentException ex) {
+            // failed to load the directory search file
+            pathModel.addAllDrives();
+        }
+
+        // find sources for updating
+        sourceModel.findSources();
+
+        // make sure that search and update cancelation is disabled (since we
+        // are initially neither updating nor searching, so there is nothing to
+        // cancel)
         setCancelSearchEnabled(false);
         setCancelUpdateEnabled(false);
-        pathFrame.setVisible(true);
 
-        sourceModel.findSources();
+        // show the path list gui
+        pathFrame.setVisible(true);
     }
 
+    /**
+     * Searchs all the paths in the path model.
+     * 
+     * @param subdirs
+     *            Whether to search subdirectories.
+     */
     public void searchAll(final boolean subdirs) {
         makeThreadDead();
 
@@ -91,7 +144,8 @@ public class GUILoader {
                 try {
                     resultFrame.setVisible(true);
                     resultClosed = false;
-                    pathModel.searchAll(resultModel, subdirs, backupDir, statusBar);
+                    pathModel
+                            .searchAll(resultModel, subdirs, curDir, backupDir);
                 } catch (InterruptedException ex) { /* i escaped! i'm free! */
                 }
                 setSearchEnabled(true);
@@ -104,6 +158,14 @@ public class GUILoader {
         workerThread.start();
     }
 
+    /**
+     * Searchs the selected paths in the path model.
+     * 
+     * @param indices
+     *            Which paths in the path models to be used in the search.
+     * @param subdirs
+     *            Whether to search subdirectories.
+     */
     public void search(final int[] indices, final boolean subdirs) {
         makeThreadDead();
 
@@ -116,7 +178,8 @@ public class GUILoader {
                 try {
                     resultFrame.setVisible(true);
                     resultClosed = false;
-                    pathModel.search(resultModel, indices, subdirs, backupDir, statusBar);
+                    pathModel.search(resultModel, indices, subdirs, curDir,
+                            backupDir);
                 } catch (InterruptedException ex) { /* i escaped! i'm free! */
                 }
                 setSearchEnabled(true);
@@ -129,6 +192,12 @@ public class GUILoader {
         workerThread.start();
     }
 
+    /**
+     * Updates all the results in the result model.
+     * 
+     * @param updateURL
+     *            The URL to use as the update for each ICU4J jar.
+     */
     public void updateAll(final URL updateURL) {
         makeThreadDead();
 
@@ -152,6 +221,14 @@ public class GUILoader {
         workerThread.start();
     }
 
+    /**
+     * Updates the selected results in the result model.
+     * 
+     * @param indices
+     *            Which ICU4J jars in the result model to be used in the update.
+     * @param updateURL
+     *            The URL to use as the update for each ICU4J jar.
+     */
     public void update(final int[] indices, final URL updateURL) {
         makeThreadDead();
 
@@ -175,37 +252,71 @@ public class GUILoader {
         workerThread.start();
     }
 
+    /**
+     * Cancels a search.
+     */
     public void cancelSearch() {
         makeThreadDead();
     }
 
+    /**
+     * Cancels an update.
+     */
     public void cancelUpdate() {
         makeThreadDead();
     }
 
+    /**
+     * Sets whether the search button should be enabled.
+     * 
+     * @param value
+     *            Whether the search button should be enabled.
+     */
     private void setSearchEnabled(boolean value) {
         pathGUI.setSearchEnabled(value);
     }
 
+    /**
+     * Sets whether the update button should be enabled.
+     * 
+     * @param value
+     *            Whether the update button should be enabled.
+     */
     private void setUpdateEnabled(boolean value) {
         resultGUI.setUpdateEnabled(value);
     }
 
+    /**
+     * Sets whether the cancel search button should be enabled.
+     * 
+     * @param value
+     *            Whether the cancel search button should be enabled.
+     */
     private void setCancelSearchEnabled(boolean value) {
         resultGUI.setCancelSearchEnabled(value);
     }
 
+    /**
+     * Sets whether the cancel update button should be enabled.
+     * 
+     * @param value
+     *            Whether the cancel update button should be enabled.
+     */
     private void setCancelUpdateEnabled(boolean value) {
         resultGUI.setCancelUpdateEnabled(value);
     }
 
+    /**
+     * Interrupts the worker thread and waits for it to finish.
+     */
     private void makeThreadDead() {
         if (workerThread != null)
             try {
                 workerThread.interrupt();
                 workerThread.join();
             } catch (Exception ex) {
-                // do nothing
+                // do nothing -- if an exception was thrown, the worker thread
+                // must have already been dead, which is perfectly fine
             }
     }
 
@@ -231,9 +342,12 @@ public class GUILoader {
 
     private File backupDir;
 
+    private File curDir;
+
     private Logger logger;
 
-    private JTextComponent statusBar;
-
+    /**
+     * The title for the application.
+     */
     public static final String TITLE = "ICUTZU (ICU4J Time Zone Updater)";
 }
diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUFile.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUFile.java
index 69f08e3be1..43aff05152 100644
--- a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUFile.java
+++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUFile.java
@@ -28,11 +28,21 @@ import java.util.jar.Manifest;
 import com.ibm.icu.util.UResourceBundle;
 
 /**
- * A class that represents an updatable ICU4J jar file.
+ * A class that represents an updatable ICU4J jar file. A file is an updatable
+ * ICU4J jar file if it
+ * 
    + *
  • exists
  • + *
  • is a file (ie. not a directory)
  • + *
  • does not end with .ear or .war (these file types are unsupported)
  • + *
  • ends with .jar
  • + *
  • is updatable according the isUpdatable
  • + *
  • is not signed.
  • + *
*/ public class ICUFile { /** - * Constructs a blank ICUFile. Used internally. + * Constructs a blank ICUFile. Used internally for timezone resource files + * that are not contained within a jar. * * @param logger * The current logger. @@ -91,25 +101,36 @@ public class ICUFile { * The current logger. * @throws IOException */ - private void initialize(File file, Logger aLogger) throws IOException { + private void initialize(File file, Logger log) throws IOException { this.icuFile = file; - this.logger = aLogger; + this.logger = log; String message = null; - if (!file.exists()) + if (!file.exists()) { message = "Skipped " + file.getPath() + " (does not exist)."; - else if (!file.isFile()) + } else if (!file.isFile()) { message = "Skipped " + file.getPath() + " (not a file)."; - else if (file.getName().endsWith(".ear") || file.getName().endsWith(".war")) { - message = "Skipped " + file.getPath() + " (this tool does not support .ear and .war files)."; + } else if (file.getName().endsWith(".ear") + || file.getName().endsWith(".war")) { + message = "Skipped " + file.getPath() + + " (this tool does not support .ear and .war files)."; logger.loglnToBoth(message); - } else if (!file.getName().endsWith(".jar")) + logger.showInformationDialog(message); + } else if (!file.getName().endsWith(".jar")) { message = "Skipped " + file.getPath() + " (not a jar file)."; - else if (!isUpdatable()) - message = "Skipped " + file.getPath() + " (not an updatable ICU4J jar)."; - else if (isSigned()) { - message = "Skipped " + file.getPath() + " (signed jar)."; + } else if (!isUpdatable()) { + message = "Skipped " + file.getPath() + + " (not an updatable ICU4J jar)."; + } else if (isSigned()) { + message = "Skipped " + file.getPath() + + " (cannot update signed jars)."; logger.loglnToBoth(message); + logger.showInformationDialog(message); + } else if (isEclipseFragment()) { + message = "Skipped " + file.getPath() + + " (eclipse fragments must be updated through ICU)."; + logger.loglnToBoth(message); + logger.showInformationDialog(message); } if (message != null) @@ -142,10 +163,7 @@ public class ICUFile { * @return The path of this ICUFile object, without the filename. */ public String getPath() { - String path = icuFile.getPath(); - int pos = path.lastIndexOf(File.separator); - path = (pos == -1) ? "" : path.substring(0, pos); - return path; + return icuFile.getParent(); } /** @@ -153,7 +171,6 @@ public class ICUFile { * * @return The result of getFile().toString(). */ - @Override public String toString() { return getFile().toString(); } @@ -178,10 +195,14 @@ public class ICUFile { /** * Compares two ICUFiles by the file they represent. + * + * @param other + * The other ICUFile to compare to. + * @return Whether the files represented by the two ICUFiles are equal. */ - @Override public boolean equals(Object other) { - return (!(other instanceof ICUFile)) ? false : icuFile.equals(((ICUFile) other).icuFile); + return (!(other instanceof ICUFile)) ? false : icuFile + .equals(((ICUFile) other).icuFile); } /** @@ -198,6 +219,9 @@ public class ICUFile { * @throws IOException */ public void update(URL insertURL, File backupDir) throws IOException { + logger.printlnToBoth(""); + logger.printlnToBoth("Updating " + icuFile.toString() + " ..."); + if (!icuFile.canRead() || !icuFile.canWrite()) throw new IOException("Missing permissions for " + icuFile); File backupFile = null; @@ -210,6 +234,8 @@ public class ICUFile { // get the new timezone resource version tzVersion = findEntryTZVersion(); + + logger.printlnToBoth("Successfully updated " + icuFile.toString()); } /** @@ -225,10 +251,12 @@ public class ICUFile { * @return The temporary file that was created. */ private File createBackupFile(File inputFile, File backupBase) { - logger.loglnToBoth("Creating backup file for + " + inputFile + " at " + backupBase + "."); + logger.loglnToBoth("Creating backup file for + " + inputFile + " at " + + backupBase + "."); String filename = inputFile.getName(); String suffix = ".jar"; - String prefix = filename.substring(0, filename.length() - ".jar".length()); + String prefix = filename.substring(0, filename.length() + - ".jar".length()); if (backupBase == null) { try { @@ -242,18 +270,21 @@ public class ICUFile { File backupFile = null; File backupDesc = null; - File backupDir = new File(backupBase.getPath() + File.separator + prefix); + File backupDir = new File(backupBase.getPath() + File.separator + + prefix); PrintStream ostream = null; try { backupBase.mkdir(); backupDir.mkdir(); backupFile = File.createTempFile(prefix, suffix, backupDir); - backupDesc = new File(backupDir.toString() + File.separator + prefix + ".txt"); + backupDesc = new File(backupDir.toString() + File.separator + + prefix + ".txt"); backupDesc.createNewFile(); ostream = new PrintStream(new FileOutputStream(backupDesc)); ostream.println(inputFile.toString()); - logger.loglnToBoth("Successfully created backup file at " + backupFile + "."); + logger.loglnToBoth("Successfully created backup file at " + + backupFile + "."); } catch (IOException ex) { logger.loglnToBoth("Failed to create backup file."); if (backupFile != null) @@ -280,7 +311,8 @@ public class ICUFile { * @return Whether the operation was successful. */ private boolean copyFile(File inputFile, File outputFile) { - logger.loglnToBoth("Copying from " + inputFile + " to " + outputFile + "."); + logger.loglnToBoth("Copying from " + inputFile + " to " + outputFile + + "."); InputStream istream = null; OutputStream ostream = null; byte[] buffer = new byte[BUFFER_SIZE]; @@ -327,8 +359,10 @@ public class ICUFile { * The output file. * @return Whether the operation was successful. */ - private boolean copyEntry(File inputFile, JarEntry inputEntry, File outputFile) { - logger.loglnToBoth("Copying from " + inputFile + "!/" + inputEntry + " to " + outputFile + "."); + private boolean copyEntry(File inputFile, JarEntry inputEntry, + File outputFile) { + logger.loglnToBoth("Copying from " + inputFile + "!/" + inputEntry + + " to " + outputFile + "."); JarFile jar = null; InputStream istream = null; OutputStream ostream = null; @@ -384,9 +418,10 @@ public class ICUFile { * The URL to use in replacing the entry. * @return Whether the operation was successful. */ - private boolean createUpdatedJar(File inputFile, File outputFile, JarEntry insertEntry, URL inputURL) { - logger.loglnToBoth("Copying " + inputFile + " to " + outputFile + ", replacing " + insertEntry + " with " - + inputURL + "."); + private boolean createUpdatedJar(File inputFile, File outputFile, + JarEntry insertEntry, URL inputURL) { + logger.loglnToBoth("Copying " + inputFile + " to " + outputFile + + ", replacing " + insertEntry + " with " + inputURL + "."); JarFile jar = null; JarOutputStream ostream = null; InputStream istream = null; @@ -478,7 +513,8 @@ public class ICUFile { Iterator iter = manifest.getEntries().values().iterator(); while (iter.hasNext()) { Attributes attr = (Attributes) iter.next(); - String ver = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); + String ver = attr + .getValue(Attributes.Name.IMPLEMENTATION_VERSION); if (ver != null) { icuVersion = ver; break; @@ -488,7 +524,8 @@ public class ICUFile { // if the jar's directory structure contains TZ_ENTRY_DIR and there // is a timezone resource in the jar, then the jar is updatable - success = (jar.getJarEntry(TZ_ENTRY_DIR) != null) && ((this.tzEntry = getTZEntry(jar)) != null); + success = (jar.getJarEntry(TZ_ENTRY_DIR) != null) + && ((this.tzEntry = getTZEntry(jar)) != null); } catch (IOException ex) { // unable to create the JarFile or unable to get the Manifest // log the unexplained i/o error, but we must drudge on @@ -535,6 +572,36 @@ public class ICUFile { return tzEntry.getCertificates() != null; } + /** + * Determines whether the current jar is an Eclipse Fragment. + * + * @return Whether the current jar is an Eclipse Fragment. + */ + private boolean isEclipseFragment() { + return (isEclipseDataFragment() || isEclipseMainFragment()); + } + + /** + * Determines whether the current jar is an Eclipse Data Fragment. + * + * @return Whether the current jar is an Eclipse Fragment. + */ + private boolean isEclipseDataFragment() { + return (icuFile.getPath().contains( + "plugins" + File.separator + "com.ibm.icu.data.update") && icuFile + .getName().equals("icu-data.jar")); + } + + /** + * Determines whether the current jar is an Eclipse Main Fragment. + * + * @return Whether the current jar is an Eclipse Fragment. + */ + private boolean isEclipseMainFragment() { + return (icuFile.getPath().contains("plugins") && icuFile.getName() + .startsWith("com.ibm.icu_")); + } + /** * Determines the version of a timezone resource in a jar file without * locking the jar file. @@ -588,15 +655,18 @@ public class ICUFile { private static String findTZVersion(File tzFile) { try { String filename = tzFile.getName(); - String entryname = filename.substring(0, filename.length() - ".res".length()); + String entryname = filename.substring(0, filename.length() + - ".res".length()); URL url = new URL(tzFile.getParentFile().toURL().toString()); ClassLoader loader = new URLClassLoader(new URL[] { url }); - UResourceBundle bundle = UResourceBundle.getBundleInstance("", entryname, loader); + UResourceBundle bundle = UResourceBundle.getBundleInstance("", + entryname, loader); String tzVersion; - if (bundle != null && (tzVersion = bundle.getString(TZ_VERSION_KEY)) != null) + if (bundle != null + && (tzVersion = bundle.getString(TZ_VERSION_KEY)) != null) return tzVersion; } catch (MissingResourceException ex) { // not an error -- some zoneinfo files do not have a version number @@ -653,7 +723,8 @@ public class ICUFile { /** * The timezone resource filename. */ - public static final String TZ_ENTRY_FILENAME = TZ_ENTRY_FILENAME_PREFIX + TZ_ENTRY_FILENAME_EXTENSION; + public static final String TZ_ENTRY_FILENAME = TZ_ENTRY_FILENAME_PREFIX + + TZ_ENTRY_FILENAME_EXTENSION; private static final int BUFFER_SIZE = 1024; diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUJarFinder.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUJarFinder.java index 0313609ff5..7a5c0d6a84 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUJarFinder.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUJarFinder.java @@ -12,8 +12,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import javax.swing.text.JTextComponent; - /** * Finds all updatable ICU4J jars in a set of specified directories. */ @@ -31,21 +29,21 @@ public class ICUJarFinder { * The result model to add any discovered ICU4J jars to. * @param logger * The current logger. - * @param statusBar - * The status bar for status-bar messages, or null if none is - * present. * @param paths * The list of paths to include to and exclude from the search. * @param subdirs * Whether to include subdirectories in the search. + * @param curDir + * The base directory of the tool. * @param backupDir * The backup directory, or null if none. The backup directory is * excluded from the search * @return The same result model as given. * @throws InterruptedException */ - public static ResultModel search(ResultModel resultModel, Logger logger, JTextComponent statusBar, - IncludePath[] paths, boolean subdirs, File backupDir) throws InterruptedException { + public static ResultModel search(ResultModel resultModel, Logger logger, + IncludePath[] paths, boolean subdirs, File curDir, File backupDir) + throws InterruptedException { // sift the included / excluded paths into two seperate arraylists List included = new ArrayList(); List excluded = new ArrayList(); @@ -61,19 +59,16 @@ public class ICUJarFinder { if (backupDir != null) excluded.add(backupDir); - // logger.logln("*************", Logger.VERBOSE); - // logger.logln("Search Paths", Logger.VERBOSE); - // logger.logln("Included:", Logger.VERBOSE); - // for (int i = 0; i < included.size(); i++) - // logger.logln(included.get(i).toString(), Logger.VERBOSE); - // logger.logln("Excluded:", Logger.VERBOSE); - // for (int i = 0; i < excluded.size(); i++) - // logger.logln(excluded.get(i).toString(), Logger.VERBOSE); - // logger.logln("*************", Logger.VERBOSE); + // the icutzu_home dir must be specified, don't search it + excluded.add(curDir); // search each of the included files/directories for (int i = 0; i < included.size(); i++) - search(resultModel, logger, statusBar, (File) included.get(i), excluded, subdirs, 0); + search(resultModel, logger, (File) included.get(i), excluded, + subdirs, 0); + + // finalize the status. + logger.setStatus("Search complete."); // chain the result model return resultModel; @@ -102,8 +97,9 @@ public class ICUJarFinder { * @return The same result model as given. * @throws InterruptedException */ - private static ResultModel search(ResultModel resultModel, Logger logger, JTextComponent statusBar, File file, - List excluded, boolean subdirs, int depth) throws InterruptedException { + private static ResultModel search(ResultModel resultModel, Logger logger, + File file, List excluded, boolean subdirs, int depth) + throws InterruptedException { // check for interruptions if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); @@ -111,21 +107,22 @@ public class ICUJarFinder { // make sure the current file/directory isn't excluded Iterator iter = excluded.iterator(); while (iter.hasNext()) - if (file.getAbsolutePath().equalsIgnoreCase(((File) iter.next()).getAbsolutePath())) + if (file.getAbsolutePath().equalsIgnoreCase( + ((File) iter.next()).getAbsolutePath())) return resultModel; if (file.isDirectory() && (subdirs || depth == 0)) { - // notify the user that something is happening - if (statusBar != null) - statusBar.setText(file.getPath()); - // recurse through each file/directory inside this directory File[] dirlist = file.listFiles(); if (dirlist != null && dirlist.length > 0) { // notify the user that something is happening - logger.printlnToScreen(dirlist[0].getPath()); + if (depth <= 2) { + logger.setStatus(file.getPath()); + logger.printlnToScreen(file.getPath()); + } for (int i = 0; i < dirlist.length; i++) - search(resultModel, logger, statusBar, dirlist[i], excluded, subdirs, depth + 1); + search(resultModel, logger, dirlist[i], excluded, subdirs, + depth + 1); } } else { // attempt to create an ICUFile object on the current file and add diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUTZUMain.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUTZUMain.java index 9964f68249..44c69f4ef5 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUTZUMain.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/ICUTZUMain.java @@ -6,6 +6,8 @@ */ package com.ibm.icu.dev.tool.tzu; +import java.io.File; + /** * Entry point for the ICUTZU tool. */ @@ -14,12 +16,79 @@ public class ICUTZUMain { * Entry point for the ICUTZU tool. * * @param args - * The list of arguments. + * The list of arguments. Should be in the following order: + *
    + *
  • Current directory
  • + *
  • Path list file
  • + *
  • Result list file
  • + *
  • Timezone resource file
  • + *
  • Backup directory
  • + *
+ * All directories and paths should be relative to the given + * current directory. */ public static void main(String[] args) { - if ("true".equals(System.getProperty("nogui"))) - CLILoader.main(args); - else - GUILoader.main(args); + try { + + if (args.length != NUM_ARGS) { + System.err.println("Incorrect number of arguments."); + System.err + .println("Syntax: ICUTZUMain "); + System.exit(-1); + } + + File curDir = new File(args[CUR_DIR]); + File backupDir = new File(args[CUR_DIR] + args[BACKUP_DIR]); + File pathFile = new File(args[CUR_DIR] + args[PATH_FILE]); + File resultFile = new File(args[CUR_DIR] + args[RESULT_FILE]); + File tzFile = new File(args[CUR_DIR] + args[TZ_FILE]); + File iconFile = new File(args[CUR_DIR] + args[ICON_FILE]); + + if ("true".equals(System.getProperty("nogui"))) + new CLILoader(curDir, backupDir, pathFile, resultFile, tzFile); + else + new GUILoader(curDir, backupDir, pathFile, resultFile, tzFile, + iconFile); + } catch (Exception ex) { + // should any unexplained exception occur, we should exit + // abnormally. ideally, this should never happen. + ex.printStackTrace(); + System.exit(-1); + } } + + /** + * Argument number for the current directory. + */ + public static final int CUR_DIR = 0; + + /** + * Argument number for the path list file. + */ + public static final int PATH_FILE = 1; + + /** + * Argument number for the result list file. + */ + public static final int RESULT_FILE = 2; + + /** + * Argument number for the timezone resource file. + */ + public static final int TZ_FILE = 3; + + /** + * Argument number for the backup directory. + */ + public static final int BACKUP_DIR = 4; + + /** + * Argument number for the icon file. + */ + public static final int ICON_FILE = 5; + + /** + * Number of arguments. + */ + public static final int NUM_ARGS = 6; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/IncludePath.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/IncludePath.java index e234c80763..95e6a10891 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/IncludePath.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/IncludePath.java @@ -46,8 +46,9 @@ public class IncludePath { /** * Outputs this IncludePath in the form (+|-)pathstring. + * + * @return The IncludePath as a string. */ - @Override public String toString() { return (include ? '+' : '-') + path.toString(); } @@ -56,10 +57,15 @@ public class IncludePath { * Returns true if the other object is an IncludePath and the path that both * objects represent are the same. It is not required for both IncludePaths * to be included or excluded. + * + * @param other + * The other IncludePath to compare this one to. + * @return Whether the two IncludePaths are considered equal by the criteria + * above. */ - @Override public boolean equals(Object other) { - return !(other instanceof IncludePath) ? false : path.equals(((IncludePath) other).path); + return !(other instanceof IncludePath) ? false : path + .equals(((IncludePath) other).path); } private File path; diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/Logger.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/Logger.java index c00445ac30..f26839d696 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/Logger.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/Logger.java @@ -6,10 +6,14 @@ */ package com.ibm.icu.dev.tool.tzu; +import java.awt.Component; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; +import javax.swing.JLabel; +import javax.swing.JOptionPane; + /** * A singleton object that handles output to the screen and to a log file. Get * the current instance of the logger with getInstance, @@ -24,14 +28,56 @@ public class Logger { * The filename to use for logging output. * @param verbosity * The verbosity for output to the screen. + * @param statusBar + * The status bar for status-bar messages, or null if none is + * present. + * @param dialogParent + * The parent for dialog messages, or null if no dialog messages + * are wanted. * @throws FileNotFoundException */ - private Logger(String filename, int verbosity) throws FileNotFoundException { + private Logger(String filename, int verbosity, JLabel statusBar, + Component dialogParent) throws FileNotFoundException { System.out.println("Log file: " + filename); if (this.log != null) this.log.close(); this.log = new PrintStream(new FileOutputStream(filename)); this.verbosity = verbosity; + this.statusBar = statusBar; + this.dialogParent = dialogParent; + } + + /** + * Gets the instance of the logger, constructing a new one with + * filename and verbosity if one is not + * already constructed. + * + * @param filename + * The filename to use for logging output. + * @param verbosity + * The verbosity for output to the screen. Should be one of the + * following: + *
    + *
  • QUIET
  • + *
  • NORMAL
  • + *
  • VERBOSE
  • + *
+ * @param statusBar + * The status bar for status-bar messages, or null if none is + * present. + * @param dialogParent + * The parent for dialog messages, or null if no dialog messages + * are wanted. + * @return The instance of the logger. + * @throws FileNotFoundException + */ + public static synchronized Logger getInstance(String filename, + int verbosity, JLabel statusBar, Component dialogParent) + throws FileNotFoundException { + if (logger == null) { + logger = new Logger(filename, verbosity, statusBar, dialogParent); + } + return logger; } /** @@ -52,9 +98,10 @@ public class Logger { * @return The instance of the logger. * @throws FileNotFoundException */ - public static synchronized Logger getInstance(String filename, int verbosity) throws FileNotFoundException { + public static synchronized Logger getInstance(String filename, int verbosity) + throws FileNotFoundException { if (logger == null) { - logger = new Logger(filename, verbosity); + logger = new Logger(filename, verbosity, null, null); } return logger; } @@ -81,7 +128,8 @@ public class Logger { * The message to print. */ public void printToScreen(String message) { - System.out.print(message); + if (verbosity >= NORMAL) + System.out.print(message); } /** @@ -91,7 +139,8 @@ public class Logger { * The message to print. */ public void printlnToScreen(String message) { - System.out.println(message); + if (verbosity >= NORMAL) + System.out.println(message); } /** @@ -125,7 +174,8 @@ public class Logger { * The message to print. */ public void logToFile(String message) { - log.print(message); + if (log != null) + log.print(message); } /** @@ -135,7 +185,8 @@ public class Logger { * The message to print. */ public void loglnToFile(String message) { - log.println(message); + if (log != null) + log.println(message); } /** @@ -145,7 +196,8 @@ public class Logger { * The message to print. */ public void printToBoth(String message) { - log.print(message); + printToScreen(message); + logToFile(message); } /** @@ -155,7 +207,8 @@ public class Logger { * The message to print. */ public void printlnToBoth(String message) { - log.println(message); + printlnToScreen(message); + loglnToFile(message); } /** @@ -167,7 +220,8 @@ public class Logger { * The message to print. */ public void logToBoth(String message) { - log.print(message); + logToScreen(message); + logToFile(message); } /** @@ -178,7 +232,8 @@ public class Logger { * The message to print. */ public void loglnToBoth(String message) { - log.println(message); + loglnToScreen(message); + loglnToFile(message); } /** @@ -206,6 +261,44 @@ public class Logger { log.println(message); } + /** + * If dialogParent is not null, brings up an informative dialog about + * something the user should be aware of. + * + * @param message + * The message to the user. + */ + public void showInformationDialog(String message) { + if (dialogParent != null) + JOptionPane.showMessageDialog(dialogParent, message, + "INFORMATION MESSAGE", JOptionPane.INFORMATION_MESSAGE); + } + + /** + * If dialogParent is not null, brings up an warning dialog about something + * the user should be aware of. + * + * @param message + * The message to the user. + */ + public void showWarningDialog(String message) { + if (dialogParent != null) + JOptionPane.showMessageDialog(dialogParent, message, + "WARNING MESSAGE", JOptionPane.WARNING_MESSAGE); + } + + /** + * If the status bar is not null, produces a status message so that the user + * is aware of the current status. + * + * @param message + * The status. + */ + public void setStatus(String message) { + if (statusBar != null) + statusBar.setText(message); + } + /** * Quiet mode. */ @@ -228,7 +321,11 @@ public class Logger { private int verbosity = NORMAL; - private PrintStream log; + private PrintStream log = null; + + private JLabel statusBar = null; + + private Component dialogParent = null; private static Logger logger = null; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/PathComponent.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/PathComponent.java index 3edab7e6c7..d66353f63f 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/PathComponent.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/PathComponent.java @@ -14,7 +14,6 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; -import java.io.IOException; import javax.swing.BoxLayout; import javax.swing.JButton; @@ -31,10 +30,17 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextField; +/** + * The path list GUI component. + */ public class PathComponent extends JComponent { - public PathComponent(final GUILoader owner, final PathModel pathModel) { - this.pathModel = pathModel; - + /** + * Constructs the path list GUI component. + * + * @param owner + * The GUILoader object that ownes this component. + */ + public PathComponent(final GUILoader owner) { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(pathInputPanel); add(new JScrollPane(pathList)); @@ -47,8 +53,6 @@ public class PathComponent extends JComponent { pathOptionPanel.add(pathSubdirOption); pathSearchPanel.add(pathSearchButton); - pathList.setModel(pathModel); - pathChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); pathPopup.add(pathAddAllDrivesItem); @@ -89,12 +93,12 @@ public class PathComponent extends JComponent { private void checkPopup(MouseEvent event) { if (event.isPopupTrigger()) - pathPopup.show((Component) event.getSource(), event.getX(), event.getY()); + pathPopup.show((Component) event.getSource(), event.getX(), + event.getY()); } }); pathList.addKeyListener(new KeyAdapter() { - @Override public void keyPressed(KeyEvent event) { if (event.getKeyCode() == KeyEvent.VK_DELETE) pathModel.remove(pathList.getSelectedIndices()); @@ -115,7 +119,8 @@ public class PathComponent extends JComponent { pathSearchSelectedItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { - owner.search(pathList.getSelectedIndices(), pathSubdirOption.isSelected()); + owner.search(pathList.getSelectedIndices(), pathSubdirOption + .isSelected()); } }); @@ -161,16 +166,6 @@ public class PathComponent extends JComponent { } } }); - - try { - pathModel.loadPaths(); - } catch (IOException ex) { - // failed to load the directory search file - pathModel.addAllDrives(); - } catch (IllegalArgumentException ex) { - // failed to load the directory search file - pathModel.addAllDrives(); - } } private boolean isIncluded() { @@ -179,18 +174,33 @@ public class PathComponent extends JComponent { private void addFile(File file) { if (!pathModel.add(new IncludePath(file, isIncluded()))) - JOptionPane.showMessageDialog(PathComponent.this, - "\"" + file.getPath() + "\" is not a valid file or path.", "Cannot add path/file", - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(PathComponent.this, "\"" + + file.getPath() + "\" is not a valid file or path.", + "Cannot add path/file", JOptionPane.ERROR_MESSAGE); } + /** + * Sets whether the search button should be enabled. + * + * @param value + * Whether the search button should be enabled. + */ public void setSearchEnabled(boolean value) { pathSearchButton.setEnabled(value); } - private JPanel pathInputPanel = new JPanel(); + /** + * Sets the path model. + * + * @param pathModel + * The path model. + */ + public void setPathModel(PathModel pathModel) { + this.pathModel = pathModel; + pathList.setModel(pathModel); + } - // private JPanel pathListPanel = new JPanel(); + private JPanel pathInputPanel = new JPanel(); private JPanel pathOptionPanel = new JPanel(); @@ -198,11 +208,13 @@ public class PathComponent extends JComponent { private JList pathList = new JList(); - private JComboBox pathSignBox = new JComboBox(new Object[] { "Include", "Exclude" }); + private JComboBox pathSignBox = new JComboBox(new Object[] { "Include", + "Exclude" }); private JTextField pathField = new JTextField(30); - private JCheckBox pathSubdirOption = new JCheckBox("Search Subdirectories", true); + private JCheckBox pathSubdirOption = new JCheckBox("Search Subdirectories", + true); private JButton pathBrowseButton = new JButton("Browse..."); @@ -212,17 +224,23 @@ public class PathComponent extends JComponent { private JPopupMenu pathPopup = new JPopupMenu(); - private JMenuItem pathAddAllDrivesItem = new JMenuItem("Add All Drives to List"); + private JMenuItem pathAddAllDrivesItem = new JMenuItem( + "Add All Drives to List"); - private JMenuItem pathRemoveSelectedItem = new JMenuItem("Remove Selected Items"); + private JMenuItem pathRemoveSelectedItem = new JMenuItem( + "Remove Selected Items"); private JMenuItem pathRemoveAllItem = new JMenuItem("Remove All"); - private JMenuItem pathSearchSelectedItem = new JMenuItem("Search Selected Items"); + private JMenuItem pathSearchSelectedItem = new JMenuItem( + "Search Selected Items"); private JMenuItem pathSearchAllItem = new JMenuItem("Search All"); private PathModel pathModel; + /** + * The serializable UID. + */ public static final long serialVersionUID = 1340; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/PathModel.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/PathModel.java index 7a5cbe1d1a..094aaa6f82 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/PathModel.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/PathModel.java @@ -17,7 +17,6 @@ import java.util.Iterator; import java.util.List; import javax.swing.AbstractListModel; -import javax.swing.text.JTextComponent; /** * Represents a list of IncludePaths that is usable by any class that uses @@ -29,11 +28,15 @@ class PathModel extends AbstractListModel { /** * Constructs an empty path model. * + * @param pathFile + * The file to load the path list from. * @param logger * The current logger. */ - public PathModel(Logger logger) { + public PathModel(Logger logger, File pathFile) { this.logger = logger; + this.pathFile = pathFile; + this.pathFilename = pathFile.getName(); } /** @@ -85,7 +88,9 @@ class PathModel extends AbstractListModel { return true; } - return add(new IncludePath(new File(includeFilename.substring(1).trim()), includeFilename.charAt(0) == '+')); + return add(new IncludePath( + new File(includeFilename.substring(1).trim()), includeFilename + .charAt(0) == '+')); } /** @@ -171,14 +176,14 @@ class PathModel extends AbstractListModel { * The indices of the path list to use in the search. * @param subdirs * Whether to search subdiretories. + * @param curDir + * The base directory of the tool. * @param backupDir * Where to store backup files. - * @param statusBar - * The status bar to dispay status. * @throws InterruptedException */ - public void search(ResultModel resultModel, int[] indices, boolean subdirs, File backupDir, JTextComponent statusBar) - throws InterruptedException { + public void search(ResultModel resultModel, int[] indices, boolean subdirs, + File curDir, File backupDir) throws InterruptedException { if (list.size() > 0 && indices.length > 0) { Arrays.sort(indices); int n = indices.length; @@ -192,7 +197,8 @@ class PathModel extends AbstractListModel { else iter.next(); - ICUJarFinder.search(resultModel, logger, statusBar, paths, subdirs, backupDir); + ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, + backupDir); } } @@ -204,34 +210,35 @@ class PathModel extends AbstractListModel { * The result model to store the results of the search. * @param subdirs * Whether to search subdiretories. + * @param curDir + * The base directory of the tool. * @param backupDir * Where to store backup files. - * @param statusBar - * The status bar to dispay status. * @throws InterruptedException */ - public void searchAll(ResultModel resultModel, boolean subdirs, File backupDir, JTextComponent statusBar) - throws InterruptedException { + public void searchAll(ResultModel resultModel, boolean subdirs, + File curDir, File backupDir) throws InterruptedException { if (list.size() > 0) { int n = list.size(); IncludePath[] paths = new IncludePath[n]; Iterator iter = list.iterator(); for (int i = 0; i < n; i++) paths[i] = (IncludePath) iter.next(); - ICUJarFinder.search(resultModel, logger, statusBar, paths, subdirs, backupDir); + ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, + backupDir); } } /** - * Loads a list of paths from PATHLIST_FILENAME. Each path - * must be of the form + * Loads a list of paths from the given path list file. Each path must be of + * the form * * @throws IOException * @throws IllegalArgumentException */ public void loadPaths() throws IOException, IllegalArgumentException { - logger.printlnToScreen("Scanning " + PATHLIST_FILENAME + " file..."); - logger.printlnToScreen(PATHLIST_FILENAME + " file contains"); + logger.printlnToScreen("Scanning " + pathFilename + " file..."); + logger.printlnToScreen(pathFilename + " file contains"); BufferedReader reader = null; int lineNumber = 1; @@ -239,7 +246,7 @@ class PathModel extends AbstractListModel { char sign; try { - reader = new BufferedReader(new FileReader(PATHLIST_FILENAME)); + reader = new BufferedReader(new FileReader(pathFile)); while (reader.ready()) { line = reader.readLine().trim(); @@ -248,20 +255,24 @@ class PathModel extends AbstractListModel { if (sign != '#') { logger.printlnToScreen(line); if (sign != '+' && sign != '-' && !"all".equals(line)) - pathListError("Each path entry must start with a + or - to denote inclusion/exclusion", + pathListError( + "Each path entry must start with a + or - to denote inclusion/exclusion", lineNumber); if (!add(line)) - pathListError("\"" + line.substring(1).trim() - + "\" is not a valid file or directory (perhaps it does not exist?)", lineNumber); + pathListError( + "\"" + + line.substring(1).trim() + + "\" is not a valid file or directory (perhaps it does not exist?)", + lineNumber); } } lineNumber++; } } catch (FileNotFoundException ex) { - pathListError("The " + PATHLIST_FILENAME + " file doesn't exist."); + pathListError("The " + pathFilename + " file doesn't exist."); } catch (IOException ex) { - pathListError("Could not read the " + PATHLIST_FILENAME + " file."); + pathListError("Could not read the " + pathFilename + " file."); } finally { try { if (reader != null) @@ -281,8 +292,10 @@ class PathModel extends AbstractListModel { * The line number to put in the exception. * @throws IllegalArgumentException */ - private static void pathListError(String message, int lineNumber) throws IllegalArgumentException { - throw new IllegalArgumentException("Error in " + PATHLIST_FILENAME + " (line " + lineNumber + "): " + message); + private void pathListError(String message, int lineNumber) + throws IllegalArgumentException { + throw new IllegalArgumentException("Error in " + pathFilename + + " (line " + lineNumber + "): " + message); } /** @@ -292,21 +305,20 @@ class PathModel extends AbstractListModel { * The message to put in the exception. * @throws IOException */ - private static void pathListError(String message) throws IOException { - throw new IOException("Error in " + PATHLIST_FILENAME + ": " + message); + private void pathListError(String message) throws IOException { + throw new IOException("Error in " + pathFilename + ": " + message); } - /** - * The filename of the pathlist file. - */ - public static final String PATHLIST_FILENAME = "DirectorySearch.txt"; + private String pathFilename; + + private File pathFile; + + private List list = new ArrayList(); // list of paths (Files) + + private Logger logger; /** * The serializable UID. */ public static final long serialVersionUID = 1337; - - private List list = new ArrayList(); // list of paths (Files) - - private Logger logger; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultComponent.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultComponent.java index a6488054f9..1d89f61de3 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultComponent.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultComponent.java @@ -24,6 +24,7 @@ import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; +import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -32,30 +33,31 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTable; import javax.swing.JTextField; -import javax.swing.text.JTextComponent; +/** + * The path list GUI component. + */ public class ResultComponent extends JComponent { - public ResultComponent(final GUILoader owner, final ResultModel resultModel, final SourceModel sourceModel) { - this.resultModel = resultModel; - this.sourceModel = sourceModel; - + /** + * @param owner + * The GUILoader object that ownes this component. + */ + public ResultComponent(final GUILoader owner) { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(resultInputPanel); add(new JScrollPane(resultTable)); + add(resultStatusPanel); add(resultOptionPanel); add(resultUpdatePanel); resultInputPanel.add(resultField); resultInputPanel.add(resultBrowseButton); - // resultOptionPanel.add(resultHideOption); + resultStatusPanel.add(statusBar); resultOptionPanel.add(resultSourceList); resultUpdatePanel.add(resultCancelSearchButton); resultUpdatePanel.add(resultUpdateButton); resultUpdatePanel.add(resultCancelUpdateButton); - resultTable.setModel(resultModel); - resultSourceList.setModel(sourceModel); - resultChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); resultPopup.add(resultRemoveSelectedItem); @@ -94,12 +96,12 @@ public class ResultComponent extends JComponent { private void checkPopup(MouseEvent event) { if (event.isPopupTrigger()) - resultPopup.show((Component) event.getSource(), event.getX(), event.getY()); + resultPopup.show((Component) event.getSource(), event + .getX(), event.getY()); } }); resultTable.addKeyListener(new KeyAdapter() { - @Override public void keyPressed(KeyEvent event) { if (event.getKeyCode() == KeyEvent.VK_DELETE) resultModel.remove(resultTable.getSelectedRows()); @@ -120,7 +122,9 @@ public class ResultComponent extends JComponent { resultUpdateSelectedItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { - owner.update(resultTable.getSelectedRows(), getSelectedSource()); + owner + .update(resultTable.getSelectedRows(), + getSelectedSource()); } }); @@ -154,7 +158,8 @@ public class ResultComponent extends JComponent { resultBrowseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { - int returnVal = resultChooser.showOpenDialog(ResultComponent.this); + int returnVal = resultChooser + .showOpenDialog(ResultComponent.this); if (returnVal == JFileChooser.APPROVE_OPTION) addFile(resultChooser.getSelectedFile()); } @@ -162,44 +167,104 @@ public class ResultComponent extends JComponent { resultHideOption.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent event) { - resultModel.setHidden(event.getStateChange() == ItemEvent.SELECTED); + resultModel + .setHidden(event.getStateChange() == ItemEvent.SELECTED); } }); } + /** + * Returns the URL of the currently selected item in the result source list. + * + * @return The URL of the currently selected item in the result source list. + */ private URL getSelectedSource() { return sourceModel.getURL(resultSourceList.getSelectedItem()); } + /** + * Adds a file to the result list. The file must be an updatable ICU4J jar + * by the standards laid out in ICUFile. + * + * @param file + * The file to add. + * @return Whether the file was added successfully. + */ private boolean addFile(File file) { if (!resultModel.add(file)) { - JOptionPane.showMessageDialog(ResultComponent.this, "\"" + file.toString() - + "\" is not an updatable ICU jar file.", "Cannot add file", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(ResultComponent.this, "\"" + + file.toString() + "\" is not an updatable ICU jar file.", + "Cannot add file", JOptionPane.ERROR_MESSAGE); return false; } return true; } + /** + * Sets whether the update button should be enabled. + * + * @param value + * Whether the update button should be enabled. + */ public void setUpdateEnabled(boolean value) { resultUpdateButton.setEnabled(value); } + /** + * Sets whether the cancel search button should be enabled. + * + * @param value + * Whether the cancel search button should be enabled. + */ public void setCancelSearchEnabled(boolean value) { resultCancelSearchButton.setEnabled(value); } + /** + * Sets whether the cancel update button should be enabled. + * + * @param value + * Whether the cancel update button should be enabled. + */ public void setCancelUpdateEnabled(boolean value) { resultCancelUpdateButton.setEnabled(value); } - public JTextComponent getStatusBar() { + /** + * Returns the status bar. + * + * @return The status bar. + */ + public JLabel getStatusBar() { return statusBar; } + /** + * Sets the result model. + * + * @param resultModel + * The result model. + */ + public void setResultModel(ResultModel resultModel) { + this.resultModel = resultModel; + resultTable.setModel(resultModel); + } + + /** + * Sets the source model. + * + * @param sourceModel + * The source model. + */ + public void setSourceModel(SourceModel sourceModel) { + this.sourceModel = sourceModel; + resultSourceList.setModel(sourceModel); + } + private JPanel resultInputPanel = new JPanel(); - // private JPanel resultTablePanel = new JPanel(); + private JPanel resultStatusPanel = new JPanel(); private JPanel resultOptionPanel = new JPanel(); @@ -209,7 +274,8 @@ public class ResultComponent extends JComponent { private JTextField resultField = new JTextField(30); - private JCheckBox resultHideOption = new JCheckBox("Hide Unreadable/Unwritable Files", true); + private JCheckBox resultHideOption = new JCheckBox( + "Hide Unreadable/Unwritable Files", true); private JButton resultBrowseButton = new JButton("Browse..."); @@ -223,11 +289,13 @@ public class ResultComponent extends JComponent { private JPopupMenu resultPopup = new JPopupMenu(); - private JMenuItem resultRemoveSelectedItem = new JMenuItem("Remove Selected Items"); + private JMenuItem resultRemoveSelectedItem = new JMenuItem( + "Remove Selected Items"); private JMenuItem resultRemoveAllItem = new JMenuItem("Remove All"); - private JMenuItem resultUpdateSelectedItem = new JMenuItem("Update Selected Items"); + private JMenuItem resultUpdateSelectedItem = new JMenuItem( + "Update Selected Items"); private JMenuItem resultUpdateAllItem = new JMenuItem("Update All"); @@ -237,7 +305,10 @@ public class ResultComponent extends JComponent { private SourceModel sourceModel; - private JTextComponent statusBar = new JTextField(30); + private JLabel statusBar = new JLabel(); + /** + * The serializable UID. + */ public static final long serialVersionUID = 1341; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultModel.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultModel.java index 376d1bb652..f428009846 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultModel.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/ResultModel.java @@ -31,11 +31,15 @@ class ResultModel extends AbstractTableModel { /** * Constructs an empty result list. * + * @param resultFile + * The file to load and save results from and to. * @param logger * The current logger. */ - public ResultModel(Logger logger) { + public ResultModel(Logger logger, File resultFile) { this.logger = logger; + this.resultFile = resultFile; + this.resultFilename = resultFile.getName(); } /** @@ -64,7 +68,6 @@ class ResultModel extends AbstractTableModel { * The index of the column. * @return COLUMN_NAMES[col] */ - @Override public String getColumnName(int col) { return COLUMN_NAMES[col]; } @@ -264,7 +267,8 @@ class ResultModel extends AbstractTableModel { * The directory in which to store backups. * @throws InterruptedException */ - public void update(int[] indices, URL updateURL, File backupDir) throws InterruptedException { + public void update(int[] indices, URL updateURL, File backupDir) + throws InterruptedException { if (hidden) update(permissibleList, indices, updateURL, backupDir); else @@ -281,7 +285,8 @@ class ResultModel extends AbstractTableModel { * The directory in which to store backups. * @throws InterruptedException */ - public void updateAll(URL updateURL, File backupDir) throws InterruptedException { + public void updateAll(URL updateURL, File backupDir) + throws InterruptedException { if (hidden) updateAll(permissibleList, updateURL, backupDir); else @@ -301,7 +306,8 @@ class ResultModel extends AbstractTableModel { * The directory in which to store backups. * @throws InterruptedException */ - private void update(List list, int[] indices, URL updateURL, File backupDir) throws InterruptedException { + private void update(List list, int[] indices, URL updateURL, File backupDir) + throws InterruptedException { if (list.size() > 0 && indices.length > 0) { Arrays.sort(indices); int n = indices.length; @@ -334,7 +340,8 @@ class ResultModel extends AbstractTableModel { * The directory in which to store backups. * @throws InterruptedException */ - private void updateAll(List list, URL updateURL, File backupDir) throws InterruptedException { + private void updateAll(List list, URL updateURL, File backupDir) + throws InterruptedException { if (list.size() > 0) { int n = list.size(); Iterator iter = list.iterator(); @@ -351,13 +358,16 @@ class ResultModel extends AbstractTableModel { } /** - * Loads a list of ICUFiles from RESULTLIST_FILENAME. Lines - * should be of the form pathstringtzversion. + * Loads a list of ICUFiles from the given result list file. Lines should be + * of the form pathstringtzversion. * * @throws IOException * @throws IllegalArgumentException */ public void loadResults() throws IOException, IllegalArgumentException { + logger.printlnToScreen("Scanning " + resultFilename + " file..."); + logger.printlnToScreen(resultFilename + " file contains"); + BufferedReader reader = null; int lineNumber = 1; String line; @@ -365,24 +375,26 @@ class ResultModel extends AbstractTableModel { String filename; try { - reader = new BufferedReader(new FileReader(RESULTLIST_FILENAME)); + reader = new BufferedReader(new FileReader(resultFile)); while (reader.ready()) { line = reader.readLine().trim(); + logger.printlnToScreen(line); - if (line.length() >= 1 && (tab = line.lastIndexOf('\n')) >= 0) { + if (line.length() >= 1 && (tab = line.lastIndexOf('\t')) >= 0) { if (!add(filename = line.substring(0, tab))) - resultListError(filename + " is not an updatable ICU4J file", lineNumber); + resultListError(filename + + " is not an updatable ICU4J file", lineNumber); } lineNumber++; } } catch (FileNotFoundException ex) { resultListError("The " - + RESULTLIST_FILENAME + + resultFilename + " file doesn't exist. Please re-run the tool with -Ddiscoveronly=true option to generate the list of ICU4J jars."); } catch (IOException ex) { resultListError("Could not read the " - + RESULTLIST_FILENAME + + resultFilename + " file. Please re-run the tool with -Ddiscoveronly=true option to generate the list of ICU4J jars."); } finally { try { @@ -394,27 +406,33 @@ class ResultModel extends AbstractTableModel { } /** - * Saves a list of ICUFiles to RESULTLIST_FILENAME. Lines - * will be of the form pathstringtzversion. + * Saves a list of ICUFiles to the given result list file. Lines will be of + * the form pathstringtzversion. * * @throws IOException * @throws IllegalArgumentException */ public void saveResults() throws IOException, IllegalArgumentException { + logger.printlnToScreen("Saving to file " + resultFilename + " ..."); BufferedWriter writer = null; ICUFile icuFile = null; try { - writer = new BufferedWriter(new FileWriter(RESULTLIST_FILENAME)); - Iterator iter = (hidden ? permissibleList : completeList).iterator(); + writer = new BufferedWriter(new FileWriter(resultFile)); + Iterator iter = (hidden ? permissibleList : completeList) + .iterator(); while (iter.hasNext()) { icuFile = (ICUFile) iter.next(); - writer.write(icuFile.getFile().getPath() + '\t' + icuFile.getTZVersion() + '\n'); + String line = icuFile.getFile().getPath() + '\t' + + icuFile.getTZVersion() + "\n"; + logger.printlnToScreen(line); + writer.write(line); } } catch (FileNotFoundException ex) { - resultListError("Could not create the " + RESULTLIST_FILENAME + " file."); + resultListError("Could not create the " + resultFilename + " file."); } catch (IOException ex) { - resultListError("Could not write to the " + RESULTLIST_FILENAME + " file."); + resultListError("Could not write to the " + resultFilename + + " file."); } finally { try { if (writer != null) @@ -434,8 +452,10 @@ class ResultModel extends AbstractTableModel { * The line number. * @throws IllegalArgumentException */ - private static void resultListError(String message, int lineNumber) throws IllegalArgumentException { - throw new IllegalArgumentException("Error in " + RESULTLIST_FILENAME + " (line " + lineNumber + "): " + message); + private void resultListError(String message, int lineNumber) + throws IllegalArgumentException { + throw new IllegalArgumentException("Error in " + resultFilename + + " (line " + lineNumber + "): " + message); } /** @@ -445,20 +465,15 @@ class ResultModel extends AbstractTableModel { * The message. * @throws IllegalArgumentException */ - private static void resultListError(String message) throws IOException { - throw new IOException("Error in " + RESULTLIST_FILENAME + ": " + message); + private void resultListError(String message) throws IOException { + throw new IOException("Error in " + resultFilename + ": " + message); } - /** - * The filename of the resultlist file. - */ - public static final String RESULTLIST_FILENAME = "ICUList.txt"; - /** * A list of names of the columns in a result model. */ - public static final String[] COLUMN_NAMES = new String[] { "Path", "Name", "ICU Version", "TZ Version", "Readable", - "Writable" }; + public static final String[] COLUMN_NAMES = new String[] { "Path", "Name", + "ICU Version", "TZ Version", "Readable", "Writable" }; /** * The column designating filenames. @@ -490,16 +505,21 @@ class ResultModel extends AbstractTableModel { */ public static final int COLUMN_WRITABLE = 5; - /** - * The serializable UID. - */ - public static final long serialVersionUID = 1338; - private List completeList = new ArrayList(); private List permissibleList = new ArrayList(); private boolean hidden = true; + private File resultFile; + + private String resultFilename; + private Logger logger; + + /** + * The serializable UID. + */ + public static final long serialVersionUID = 1338; + } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/SourceModel.java b/icu4j/src/com/ibm/icu/dev/tool/tzu/SourceModel.java index 9dbe372d55..72510f7f11 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/SourceModel.java +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/SourceModel.java @@ -34,9 +34,11 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { * * @param logger * The current logger. + * @param tzLocalFile + * The local timezone resource file. */ - public SourceModel(Logger logger) { - // this.logger = logger; + public SourceModel(Logger logger, File tzLocalFile) { + this.logger = logger; // if all constants are not yet initialized // (this is where they get initialized) @@ -44,19 +46,24 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { try { TZ_BASE_URL = new URL(TZ_BASE_URLSTRING_START); - if (!TZ_LOCAL_FILE.exists()) { + SourceModel.tzLocalFile = tzLocalFile; + if (!tzLocalFile.exists()) { // not a critical error, but we won't be able to use the // local tz file logger.errorln("Local copy (zoneinfo.res) does not exist"); } else { - TZ_LOCAL_URL = TZ_LOCAL_FILE.toURL(); - TZ_LOCAL_VERSION = ICUFile.findFileTZVersion(TZ_LOCAL_FILE, logger); + TZ_LOCAL_URL = tzLocalFile.toURL(); + TZ_LOCAL_VERSION = ICUFile.findFileTZVersion(tzLocalFile, + logger); if (TZ_LOCAL_VERSION == null) { - logger.errorln("Failed to determine version of local copy"); + logger + .errorln("Failed to determine version of local copy"); TZ_LOCAL_CHOICE = "Local Copy"; } else { - TZ_LOCAL_CHOICE = "Local Copy (" + TZ_LOCAL_VERSION + ")"; + TZ_LOCAL_CHOICE = "Local Copy (" + TZ_LOCAL_VERSION + + ")"; } + selected = TZ_LOCAL_CHOICE; } } catch (MalformedURLException ex) { // this shouldn't happen @@ -73,24 +80,23 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { public void findSources() { BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(TZ_BASE_URL.openStream())); + reader = new BufferedReader(new InputStreamReader(TZ_BASE_URL + .openStream())); // create an html callback function to parse through every list item // (every list item HTMLEditorKit.ParserCallback htmlCallback = new HTMLEditorKit.ParserCallback() { - @Override - public void handleStartTag(HTML.Tag tag, MutableAttributeSet attr, int pos) { + public void handleStartTag(HTML.Tag tag, + MutableAttributeSet attr, int pos) { if (tag == HTML.Tag.LI) listItem = true; } - @Override public void handleEndTag(HTML.Tag tag, int pos) { if (tag == HTML.Tag.LI) listItem = false; } - @Override public void handleText(char[] data, int pos) { if (listItem) { String str = new String(data); @@ -99,13 +105,15 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { if (!"..".equals(str)) try { // add the new item to the map - urlMap.put(str, new URL(TZ_BASE_URLSTRING_START + str + TZ_BASE_URLSTRING_END)); + urlMap.put(str, new URL(TZ_BASE_URLSTRING_START + + str + TZ_BASE_URLSTRING_END)); // update the selected item and fire off an // event selected = urlMap.lastKey(); int index = 0; - for (Iterator iter = urlMap.keySet().iterator(); iter.hasNext();) { + for (Iterator iter = urlMap.keySet().iterator(); iter + .hasNext();) { if (iter.next().equals(str)) index++; } @@ -121,7 +129,13 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { new ParserDelegator().parse(reader, htmlCallback, false); } catch (IOException ex) { - ex.printStackTrace(); + // cannot connect to the repository -- use local version only. + String message = "Failed to connect to the ICU Timezone Repository at " + + TZ_BASE_URL.toString() + + " .\n\n" + + "Check your connection and re-run ICUTZU or continue using the local copy of the timezone update (version " + + TZ_LOCAL_VERSION + ")."; + logger.showInformationDialog(message); } finally { // close the reader gracefully if (reader != null) @@ -230,15 +244,10 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { this.selected = selected; } - /** - * The filename of the local timezone resource file. - */ - public static final String TZ_LOCAL_FILENAME = "zoneinfo.res"; - /** * The local timezone resource file. */ - public static final File TZ_LOCAL_FILE = new File(TZ_LOCAL_FILENAME); + public static File tzLocalFile = null; /** * The version of the local timezone resource file, ie. "2007c". Since the @@ -287,5 +296,5 @@ class SourceModel extends AbstractListModel implements ComboBoxModel { private TreeMap urlMap = new TreeMap(); - // private Logger logger; + private Logger logger; } diff --git a/icu4j/src/com/ibm/icu/dev/tool/tzu/runicutzu.bat b/icu4j/src/com/ibm/icu/dev/tool/tzu/runicutzu.bat index 138ee65284..de9fffeb73 100644 --- a/icu4j/src/com/ibm/icu/dev/tool/tzu/runicutzu.bat +++ b/icu4j/src/com/ibm/icu/dev/tool/tzu/runicutzu.bat @@ -42,14 +42,12 @@ GOTO CollectArguments rem Run the ICUTZU tool. @echo. @echo Launching the ICU4J Time Zone Update Utility (ICUTZU)... -@echo "%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icu4j.jar";"%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%Temp"%ARGS% +@echo "%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icu4j.jar";"%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif%ARGS% @echo. -"%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icu4j.jar";"%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%Temp"%ARGS% +"%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icu4j.jar";"%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif%ARGS% IF ERRORLEVEL==0 GOTO Success GOTO Failure -rem "%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icu4j.jar";"%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% com.ibm.icu.dev.tool.tzu.ICUTZUMain --recurse --auto --backup "%ICUTZU_HOME%Temp"%ARGS% - :MissingICUTZUJAR