ICU-5606 finished everything on the todo lists and then some.

X-SVN-Rev: 21240
This commit is contained in:
Andrew J Macheret 2007-03-14 02:23:37 +00:00
parent 82f6e65e1b
commit a6202291e5
14 changed files with 887 additions and 336 deletions

View File

@ -100,7 +100,7 @@
<property name="ime.indic.manifest" value="${src.dir}/com/ibm/icu/dev/tool/ime/indic/manifest.stub"/>
<property name="zip.file" value="../icu4j${DSTAMP}.zip"/>
<property name="zipSrc.file" value="../icu4jSrc${DSTAMP}.zip"/>
<property name="tzu.bin.dir" value="${basedir}/ICU4JTZU"/>
<property name="tzu.bin.dir" value="${basedir}/icu4jtzu"/>
<property name="tzujar.file" value="${tzu.bin.dir}/icutzu.jar"/>
<property file="build.properties" />
<!-- fix the data folder every time there is a version update-->
@ -2475,6 +2475,7 @@
<fileset dir="${src.dir}/com/ibm/icu/dev/tool/tzu">
<include name="*.bat"/>
<include name="*.sh"/>
<include name="*.gif"/>
</fileset>
<fileset dir="${basedir}">
<include name="${jar.file}"/>

View File

@ -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 <code>CLILoader</code> object with <code>args</code>.
* 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 <code>args</code> 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
* <code>PathModel.PATHLIST_FILENAME</code> and save the path of each
* updatable ICU jar files it finds to
* <code>PathModel.RESULTLIST_FILENAME</code>
* 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
* <code>PathModel.RESULTLIST_FILENAME</code>, 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.
*
* <pre>
* 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(&quot;Could not open &quot; + Logger.DEFAULT_FILENAME + &quot; for writing.&quot;);
* System.out.println(&quot;Could not open &quot; + Logger.DEFAULT_FILENAME
* + &quot; for writing.&quot;);
* 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 &gt; 1)
* syntaxError(&quot;Options -o (--offline), -t (--tzversion), -b (--best) and -d (--discoveronly) are mutually exclusive&quot;);
* // make sure that quiet &amp; 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 &amp;&amp; !SourceModel.TZ_LOCAL_FILE.exists() &amp;&amp; !options[DISCOVERONLY].doesOccur)
* if (options[OFFLINE].doesOccur &amp;&amp; !SourceModel.TZ_LOCAL_FILE.exists()
* &amp;&amp; !options[DISCOVERONLY].doesOccur)
* throw new IllegalArgumentException(
* &quot;Running offline mode but local file does not exist (no sources available)&quot;);
* // 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(&quot;&quot;, Logger.NORMAL);
* logger.println(&quot;Filename: &quot; + entry.getFile().getName(), Logger.NORMAL);
* logger.println(&quot;Location: &quot; + entry.getFile().getParent(), Logger.NORMAL);
* logger.println(&quot;Current Version: &quot; + entry.getTZVersion(), Logger.NORMAL);
* logger.println(&quot;Filename: &quot; + entry.getFile().getName(),
* Logger.NORMAL);
* logger.println(&quot;Location: &quot; + entry.getFile().getParent(),
* Logger.NORMAL);
* logger.println(&quot;Current Version: &quot; + entry.getTZVersion(),
* Logger.NORMAL);
*
* if (!entry.getFile().canRead() || !entry.getFile().canWrite()) {
* logger.println(&quot;Missing permissions for &quot; + entry.getFile().getName() + &quot;.&quot;, Logger.NORMAL);
* logger.println(&quot;Missing permissions for &quot;
* + entry.getFile().getName() + &quot;.&quot;, 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 (&quot;yes&quot;.startsWith(input))
* update(entry, chosenName, chosenURL);
@ -304,7 +357,8 @@ public class CLILoader {
* else if (&quot;local choice&quot;.startsWith(input))
* update(entry, getLocalName(), getLocalURL());
* else if (!&quot;none&quot;.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(&quot;Updating should have no effect on this file.&quot;, Logger.NORMAL);
* logger.println(&quot;Updating should have no effect on this file.&quot;,
* Logger.NORMAL);
* logger.println(&quot;Update anyway?&quot;, Logger.NORMAL);
* } else if (betterness &lt; 0) {
* logger.println(&quot;Warning: The version specified is older than the one present in the file.&quot;, Logger.NORMAL);
* logger
* .println(
* &quot;Warning: The version specified is older than the one present in the file.&quot;,
* Logger.NORMAL);
* logger.println(&quot;Update anyway?&quot;, Logger.NORMAL);
* } else {
* logger.println(&quot;Update to &quot; + chosenVersion + &quot;?&quot;, Logger.NORMAL);
@ -345,11 +403,14 @@ public class CLILoader {
*
* logger.println(getLocalName(), Logger.NORMAL);
* while (sourceIter.hasNext())
* logger.println(&quot;, &quot; + ((Map.Entry) sourceIter.next()).getKey(), Logger.NORMAL);
* logger.println(&quot;, &quot; + ((Map.Entry) sourceIter.next()).getKey(),
* Logger.NORMAL);
* logger.println(&quot;&quot;, Logger.NORMAL);
*
* logger.println(&quot;Update to which version? [best (default), none, local copy, &lt;specific version above&gt;]&quot;,
* Logger.NORMAL);
* logger
* .println(
* &quot;Update to which version? [best (default), none, local copy, &lt;specific version above&gt;]&quot;,
* Logger.NORMAL);
* logger.println(&quot;: &quot;, 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(&quot;Error in argument list: &quot; + message);
* }
*
* private static UOption options[] = new UOption[] { UOption.create(&quot;help&quot;, '?', UOption.NO_ARG),
* UOption.create(&quot;verbose&quot;, 'v', UOption.NO_ARG), UOption.create(&quot;quiet&quot;, 'q', UOption.NO_ARG),
* UOption.create(&quot;auto&quot;, 'a', UOption.NO_ARG), UOption.create(&quot;offline&quot;, 'o', UOption.NO_ARG),
* UOption.create(&quot;best&quot;, 's', UOption.NO_ARG), UOption.create(&quot;tzversion&quot;, 't', UOption.REQUIRES_ARG),
* UOption.create(&quot;recurse&quot;, 'r', UOption.NO_ARG), UOption.create(&quot;backup&quot;, 'b', UOption.REQUIRES_ARG),
* UOption.create(&quot;nobackup&quot;, 'B', UOption.NO_ARG), UOption.create(&quot;discoveronly&quot;, 'd', UOption.NO_ARG), };
* private static UOption options[] = new UOption[] {
* UOption.create(&quot;help&quot;, '?', UOption.NO_ARG),
* UOption.create(&quot;verbose&quot;, 'v', UOption.NO_ARG),
* UOption.create(&quot;quiet&quot;, 'q', UOption.NO_ARG),
* UOption.create(&quot;auto&quot;, 'a', UOption.NO_ARG),
* UOption.create(&quot;offline&quot;, 'o', UOption.NO_ARG),
* UOption.create(&quot;best&quot;, 's', UOption.NO_ARG),
* UOption.create(&quot;tzversion&quot;, 't', UOption.REQUIRES_ARG),
* UOption.create(&quot;recurse&quot;, 'r', UOption.NO_ARG),
* UOption.create(&quot;backup&quot;, 'b', UOption.REQUIRES_ARG),
* UOption.create(&quot;nobackup&quot;, 'B', UOption.NO_ARG),
* UOption.create(&quot;discoveronly&quot;, 'd', UOption.NO_ARG), };
*
* private static final int HELP = 0;
*

View File

@ -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)";
}

View File

@ -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
* <ul>
* <li>exists</li>
* <li>is a file (ie. not a directory)</li>
* <li>does not end with .ear or .war (these file types are unsupported)</li>
* <li>ends with .jar</li>
* <li>is updatable according the <code>isUpdatable</code></li>
* <li>is not signed.</li>
* </ul>
*/
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;

View File

@ -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

View File

@ -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:
* <ul>
* <li>Current directory</li>
* <li>Path list file</li>
* <li>Result list file</li>
* <li>Timezone resource file</li>
* <li>Backup directory</li>
* </ul>
* 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 <cur dir> <path file> <result file> <tz file> <backup dir>");
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;
}

View File

@ -46,8 +46,9 @@ public class IncludePath {
/**
* Outputs this IncludePath in the form (<b>+</b>|<b>-</b>)<i>pathstring</i>.
*
* @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;

View File

@ -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 <code>getInstance</code>,
@ -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
* <code>filename</code> and <code>verbosity</code> 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:
* <ul>
* <li>QUIET</li>
* <li>NORMAL</li>
* <li>VERBOSE</li>
* </ul>
* @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;
}

View File

@ -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;
}

View File

@ -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 <code>PATHLIST_FILENAME</code>. 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;
}

View File

@ -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;
}

View File

@ -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 <code>COLUMN_NAMES[col]</code>
*/
@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 <code>RESULTLIST_FILENAME</code>. Lines
* should be of the form <b><i>pathstring</i><tab><i>tzversion</i></b>.
* Loads a list of ICUFiles from the given result list file. Lines should be
* of the form <b><i>pathstring</i><tab><i>tzversion</i></b>.
*
* @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 <code>RESULTLIST_FILENAME</code>. Lines
* will be of the form <b><i>pathstring</i><tab><i>tzversion</i></b>.
* Saves a list of ICUFiles to the given result list file. Lines will be of
* the form <b><i>pathstring</i><tab><i>tzversion</i></b>.
*
* @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;
}

View File

@ -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;
}

View File

@ -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