ICU-6448 Moving ICU TZU from icu4j repository to data repository.

X-SVN-Rev: 26118
This commit is contained in:
Yoshito Umaoka 2009-06-16 18:01:54 +00:00
parent 15d88addbf
commit 711d6680a9
25 changed files with 0 additions and 4889 deletions

2
.gitattributes vendored
View File

@ -270,8 +270,6 @@ icu4j/tools/build/icu4j400.api.gz -text
icu4j/tools/build/icu4j401.api.gz -text
icu4j/tools/build/manifest.stub -text
icu4j/tools/misc/manifest.stub -text
icu4j/tzu/icu.gif -text
icu4j/tzu/manifest.stub -text
tools/release/java/.classpath -text
tools/release/java/.project -text
tools/release/java/Makefile -text

View File

@ -1,33 +0,0 @@
# *******************************************************************************
# * Copyright (C) 2007, International Business Machines Corporation and *
# * others. All Rights Reserved. *
# *******************************************************************************
#
# This file contains the list of directories in the file system that ICUTZU will
# use to search for updatable icu4j jar files. It must be saved in UTF-8 (with
# or without the BOM).
#
# To include all roots of the file system (ie. 'c:\', 'd:\', 'e:\', etc. in Windows
# or '/' in Unix-based systems), insert the following:
# all
#
# To include a directory in the search or to directly include a specific icu4j file,
# insert the directory in the native format with a leading '+'. For example in Windows:
# +C:\ICU4J
# +C:\ICU4J\icu4j.jar
# Or in Unix-based systems:
# +/usr/icu4j
# +/usr/icu4j/icu4j.jar
#
# To exclude a directory or file from the search, do the same as above but with a
# leading '-' instead:
# -C:\ICU4J
# -/usr/icu4j
all
# If you are not using a Unix-based platform, the following lines should be removed:
-/proc
-/dev
-/sys

View File

@ -1,166 +0,0 @@
<!--
*******************************************************************************
* Copyright (C) 2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
-->
<project name="tzu" default="build" basedir=".">
<property environment="env"/>
<property name="tzu.jar.file" value="icutzu.jar"/>
<property name="tzu.src.zip.file" value="icutzu-src.zip"/>
<property name="tzu.bin.zip.file" value="icutzu-bin.zip"/>
<property name="src.dir" value="src"/>
<property name="out.dir" value="out"/>
<property name="bin.dir" value="${out.dir}/bin"/>
<property name="jar.dir" value="${out.dir}/lib"/>
<property name="tzu.dist.dir" value="${out.dir}/dist"/>
<property name="tzu.dist.tmp.dir" value="${tzu.dist.dir}/tmp"/>
<property name="tzu.test.dir" value="${out.dir}/test"/>
<target name="build" depends="_check-icu4j-jar, src-zip, bin-zip"/>
<target name="_check-icu4j-jar">
<available file="${env.ICU4J_JAR}" type="file" property="icu4j.jar.file" value="${env.ICU4J_JAR}"/>
<fail message="Environment variable ICU4J_JAR is not properly set - ${env.ICU4J_JAR}">
<condition>
<not>
<isset property="icu4j.jar.file"/>
</not>
</condition>
</fail>
</target>
<target name="clean" description="Clean up the build outputs">
<delete dir="${out.dir}"/>
</target>
<target name="compile" description="Compile ICUTZU java files">
<mkdir dir="${bin.dir}"/>
<javac srcdir="${src.dir}"
destdir="${bin.dir}"
source="1.3"
target="1.3"
debug="on"
deprecation="off"
encoding="ascii"/>
</target>
<target name="jar" depends="_check-icu4j-jar, compile" description="Create ICUTZU jar file">
<unjar src="${icu4j.jar.file}" dest="${bin.dir}">
<patternset>
<include name="license.html"/>
</patternset>
</unjar>
<mkdir dir="${jar.dir}"/>
<jar jarfile="${jar.dir}/${tzu.jar.file}"
manifest="${basedir}/manifest.stub"
basedir="${bin.dir}"
compress="true"/>
</target>
<target name="src-zip" description="Create ICUTZU distributable source zip file">
<mkdir dir="${tzu.dist.dir}"/>
<zip zipfile="${tzu.dist.dir}/${tzu.src.zip.file}"
basedir="${basedir}"
excludes="${out.dir}/"/>
</target>
<target name="bin-zip" depends="jar" description="Create ICUTZU distributable binary zip file">
<mkdir dir="${tzu.dist.tmp.dir}"/>
<unjar src="${icu4j.jar.file}" dest="${tzu.dist.tmp.dir}">
<patternset>
<include name="com/ibm/icu/impl/data/*/zoneinfo.res"/>
<include name="com/ibm/icu/impl/data/*/metazoneInfo.res"/>
</patternset>
<mapper type="flatten"/>
</unjar>
<copy file="${icu4j.jar.file}" tofile="${tzu.dist.tmp.dir}/icu4j.jar"/>
<mkdir dir="${tzu.dist.dir}"/>
<zip zipfile="${tzu.dist.dir}/${tzu.bin.zip.file}">
<fileset dir="${jar.dir}">
<include name="${tzu.jar.file}"/>
</fileset>
<fileset dir="${basedir}">
<include name="runicutzu*.cmd"/>
<include name="runicutzu*.bat"/>
<include name="runicutzu*.sh"/>
<include name="icu.gif"/>
<include name="DirectorySearch.txt"/>
<include name="readme.html"/>
<include name="icu.css"/>
</fileset>
<fileset dir="${tzu.dist.tmp.dir}">
<include name="**/*"/>
</fileset>
</zip>
</target>
<target name="check" depends="jar" description="Check ICU4J TimeZone Update Utility">
<delete dir="${tzu.test.dir}"/>
<echo>Testing ICUTZU ...</echo>
<mkdir dir="${tzu.test.dir}/scandir"/>
<echo file="${tzu.test.dir}/DirectorySearch.txt">+scandir</echo>
<get dest="${tzu.test.dir}/zoneinfo.res" src="http://icu-project.org/tzdata/2008d/be/zoneinfo.res"/>
<get dest="${tzu.test.dir}/metazoneInfo.res" src="http://icu-project.org/tzdata/2008d/be/metazoneInfo.res"/>
<copy tofile="${tzu.test.dir}/icu4j.jar" file="${icu4j.jar.file}"/>
<copy tofile="${tzu.test.dir}/scandir/target-icu4j.jar" file="${icu4j.jar.file}"/>
<echo>Running ICUTZU in Discovery Mode ...</echo>
<java jar="${jar.dir}/${tzu.jar.file}" fork="true" dir="${tzu.test.dir}" failonerror="true">
<jvmarg value="-Dnogui=true"/>
<jvmarg value="-Ddiscoveronly=true"/>
<jvmarg value="-Dsilentpatch=false"/>
<jvmarg value="-Doffline=true"/>
<arg value="."/>
<arg value="DirectorySearch.txt"/>
<arg value="ICUList.txt"/>
<arg value="zoneinfo.res"/>
<arg value="backup_dir"/>
<arg value="icu.gif"/>
<classpath location="icu4j.jar"/>
</java>
<echo>Running ICUTZU in Patch Mode ...</echo>
<java jar="${jar.dir}/${tzu.jar.file}" fork="true" dir="${tzu.test.dir}" failonerror="true">
<jvmarg value="-Dnogui=true"/>
<jvmarg value="-Ddiscoveronly=false"/>
<jvmarg value="-Dsilentpatch=false"/>
<jvmarg value="-Doffline=true"/>
<arg value="."/>
<arg value="DirectorySearch.txt"/>
<arg value="ICUList.txt"/>
<arg value="zoneinfo.res"/>
<arg value="backup_dir"/>
<arg value="icu.gif"/>
<classpath location="icu4j.jar"/>
</java>
<echo>Comparing results ...</echo>
<unjar src="${tzu.test.dir}/scandir/target-icu4j.jar" dest="${tzu.test.dir}/scandir">
<patternset>
<include name="com/ibm/icu/impl/data/*/zoneinfo.res" />
<include name="com/ibm/icu/impl/data/*/metazoneInfo.res" />
</patternset>
<mapper type="flatten"/>
</unjar>
<condition property="tzu.zoneinfo.match">
<filesmatch file1="${tzu.test.dir}/zoneinfo.res" file2="${tzu.test.dir}/scandir/zoneinfo.res" />
</condition>
<fail unless="tzu.zoneinfo.match"
message="ICUTZU test failed. ${tzu.test.dir}/zoneinfo.res does not match ${tzu.test.dir}/scandir/zoneinfo.res"/>
<condition property="tzu.metazoneinfo.match">
<filesmatch file1="${tzu.test.dir}/metazoneInfo.res" file2="${tzu.test.dir}/scandir/metazoneInfo.res" />
</condition>
<fail unless="tzu.metazoneinfo.match"
message="ICUTZU test failed. ${tzu.bin.dir}/metazoneInfo.res does not match ${tzu.test.dir}/metazoneInfo.res"/>
<echo>ICUTZU test successful.</echo>
</target>
</project>

View File

@ -1,214 +0,0 @@
/* @override http://icu-project.org/icu.css */
/*
* Default CSS style sheet for the ICU Open Source site
* Copyright (C) 2005-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*/
/* Global styles */
body,p,li,ol,ul,th,td {
font-size: 10pt;
font-family: "Arial", "Helvetica", sans-serif;
}
body {
margin: 10;
}
.mainbody {
padding: 1em;
}
/*
* Customize the headers to have less space around them than usual
*/
h1 {
margin-bottom: 5pt;
margin-top: 5pt;
font-weight: 700;
font-size: 20pt;
font-family: "Arial", "Helvetica", sans-serif;
}
h2 {
margin-bottom: 0pt;
margin-top: 12pt;
font-weight: 700;
font-size: 14pt;
font-family: "Arial", "Helvetica", sans-serif;
}
h3 {
background-color: #666666;
color: White;
margin-bottom: 0pt;
margin-top: 12pt;
padding-left: 0.75em;
font-size: 1em;
font-family: "Arial", "Helvetica", sans-serif;
}
h4 {
margin-bottom: 0pt;
margin-top: 12pt;
font-size: 1em;
font-family: "Arial", "Helvetica", sans-serif;
}
h5, h6 {
margin-bottom: 0pt;
margin-top: 12pt;
padding-left: 0.75em;
font-size: x-small;
font-family: "Arial", "Helvetica", sans-serif;
}
/*
* Navigation sidebar on the left hand of most pages
*/
td.sidebar1 {
background-color: #99CCFF;
font-weight: 700;
margin-top: 0px;
margin-bottom: 0px;
padding-top: 1em;
padding-left: 0.2em;
white-space: nowrap;
}
td.sidebar2 {
background-color: #99CCFF;
margin-top: 0px;
margin-bottom: 0px;
margin-left: 0px;
padding-top: 1px;
padding-bottom: 1px;
padding-left: 1px;
padding-right: 0.5em;
white-space: nowrap;
text-decoration: none;
display: block;
}
td.sidebar2:hover {
background-color: #EEEEFF;
padding-top: 1px;
padding-bottom: 1px;
padding-left: 1px;
padding-right: 0.5em;
}
a.sidebar2 {
text-decoration: none;
display: block;
width: 100%;
}
a.sidebar2:link {
color: #000099;
display: block;
}
a.sidebar2:hover {
background-color: #EEEEFF;
display: block;
}
.underlinehover:hover {
background-color: #EEEEFF;
text-decoration: underline;
}
/* This is the faded header at the top */
td.fadedtop {
background-color: #006699;
background-image: url(http://www.icu-project.org/images/gr100.gif);
}
/* Related site on the left */
p.relatedsite {
color: White;
font-weight: 700;
font-size: 10pt;
margin-top: 1em;
margin-bottom: 0;
padding-left: 0.2em;
white-space: nowrap;
}
/* Related site on the left */
p.sidebar3 {
margin-top: 0.75em;
margin-bottom: 0;
padding-left: 0.8em;
}
a.sidebar3 {
font-size: 0.9em;
text-decoration: none;
}
a.sidebar3:link {
text-decoration: none;
color: White;
}
a.sidebar3:hover {
text-decoration: underline;
}
/* FAQ */
li.faq_contents {
font-weight: 500;
}
p.faq_q {
font-weight: 700;
margin-bottom: 0px;
}
p.faq_a {
margin-top: 0px;
}
/* News items */
table.newsItem {
padding-left: 1em;
padding-right: 1em;
border-width: medium;
}
th.newsItem {
background-color: #666666;
color: White;
}
td.newsItem {
background-color: #CCCCCC;
}
td.release-line,th.release-line {
padding-left: 0.5em;
padding-right: 0.5em;
white-space: nowrap;
border:1px;
}
.note {
font-style: italic;
font-size: small;
margin-left: 1em;
}
samp {
margin-left: 1em;
margin-right: 2em;
border-style: groove;
padding: 1em;
display: block;
background-color: #EEEEEE
}
table.rtable caption {
margin-left: 2px;
margin-right: 2px;
padding: 3px;
font-weight: bold;
background-color: #dee2ff;
text-align: left;
}
table.rtable tr th {
background-color: #dee2ff;
text-align: left;
}
table.rtable tr td {
background-color: #c0c0fd;
padding: 3px;
}

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b7c1a60446893053907f57b52da6ca5792ebc455f487671879ce26acd0d3d30c
size 888

View File

@ -1,12 +0,0 @@
Manifest-Version: 1.0
Main-Class: com.ibm.icu.dev.tool.tzu.ICUTZUMain
Name: com/ibm/icu/dev/tool/tzu
Specification-Title: ICU4J TimeZone Update Utility
Specification-Version: 1.2
Specification-Vendor: ICU
Implementation-Title: ICUTZU
Implementation-Version: 1.2.1
Implementation-Vendor: IBM Corporation
Implementation-Vendor-Id: com.ibm
Copyright-Info: Copyright 2000-2009, International Business Machines Corporation and others. All Rights Reserved.

View File

@ -1,124 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
*******************************************************************************
* Copyright (C) 2000-2006, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="COPYRIGHT" content="Copyright (c) 2007 IBM Corporation and others. All Rights Reserved.">
<meta name="keywords" content="ICUTZU, ICU4J Time Zone Update Utility" />
<title>ICU4J Time Zone Update Utility (ICUTZU)</title>
<link rel="stylesheet" href="icu.css" type="text/css">
</head>
<body>
<h2>ICU4J Time Zone Update Utility (ICUTZU)</h2>
<h3>Contents</h3>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#sysreq">System Requirements</a></li>
<li><a href="#install">Installation</a></li>
<li><a href="#run">Running ICUTZU</a>
<ul>
<li><a href="#gui">Running in GUI Mode</a></li>
<li><a href="#cmd">Running in Command-line Mode</a></li>
</ul>
</li>
<li><a href="#restore">Restoring Changes</a></li>
</ul>
<a name="intro"><h3>Introduction</h3></a>
<!-- any changes to the introduction should also be done in /repos/icuproj/trunk/htdocs/download/icutzu.html -->
<p>ICU4J Time Zone Update Utility (ICUTZU) is a utility that supplies ICU4J jar files with the latest time zone information and daylight savings time changeover dates.</p>
<p>The time zone data is stored in zoneinfo.res files which are generated by the ICU team using the Olson Time Zone Database (<a href="http://www.twinsun.com/tz/tz-link.htm">http://www.twinsun.com/tz/tz-link.htm</a>). Every version of the time zone data corresponds directly to a version of the Olson database. For example "2006a" refers to the first refresh of the Olson database in 2006.</p>
<p>ICUTZU works by searching the file system for ICU4J jar files containing old time zone data, checking online for the newest time zone data and updating the ICU4J jar files accordingly. The user can choose to update from a copy of the time zone data that comes bundled with ICUTZU or from an online copy on the ICU servers.</p>
<a name="sysreq"><h3>System Requirements</h3></a>
<p>ICUTZU will run on any system that ICU4J runs on: Solaris 5.9, 5.10, AIX 5.2, 5.3, RHEL 4, 5, Windows XP, Vista, HP-UX 9000.</p>
<p>ICUTZU also requires Java 1.3 or higher to be installed.</p>
<a name="install"><h3>Installation</h3></a>
<!-- any changes to the installation should also be done in /repos/icuproj/trunk/htdocs/download/icutzu.html -->
<p>Unpack the archive into a directory of your choosing. For Unix-based systems, you will need to set permissions on runicutzu.sh:</p>
<p><code>chmod 755 runicutzu.sh</code></p>
<a name="run"><h3>Running ICUTZU</h3></a>
<a name="gui"><h4>Running in GUI Mode</h4></a>
<ol>
<li><p>To start ICUTZU, double-click <b>icutzu.jar</b> or open a console and type <code>java -jar icutzu.jar</code> .</p></li>
<li>
<p>Specify which paths to search and which paths to exclude from the search. By default, all drives are included in the search.</p>
<ul>
<li><p>To include a path in the search, select <b>Include</b> from the drop-down menu, and either type the path in the text field and press enter, or simply browse for the path.</p></li>
<li><p>To exclude a path from the search, do the same as above, but select <b>Exclude</b> from the drop-down menu.</p></li>
<li><p>To specify whether to search subdirectories, check or uncheck the "Search Subdirectories" option.</p></li>
<li><p>For additional options, right-click the directory list for a context-menu.</p></li>
</ul>
</li>
<li><p>Click <b>Search</b> to begin searching for updatable ICU4J jar files in the directories specified. A new window will pop up during the search with a list of updatable ICU4J jar files found.</p></li>
<li>
<p>Select which ICU4J jar files you wish to update.</p>
<ul><li><p><b>ICU Version</b> refers to the version of the ICU4J jar file itself, and <b>TZ Version</b> refers to version of the time zone data within the jar file.</p></li></ul>
</li>
<li><p>Choose the version of time zone data to update with from the drop down list.</p></li>
<li><p>Click <b>Update</b> to begin updating the selected ICU4J jar files.</p></li>
</ol>
<a name="cmd"><h4>Running in Command-line Mode</h4></a>
<ol>
<li>
<p>Edit the <b>DirectorySearch.txt</b> file and specify which paths ICUTZU will include and exclude in its search. ICUTZU searches directories recursively.</p>
<ul>
<li><p><i>all</i> means include all file system roots in the search (for Windows this will include all drives, for Unix-based systems this will include the root directory).</p></li>
<li><p><i>+path</i> means to include <i>path</i> in the search.</p></li>
<li><p><i>-path</i> means to exclude <i>path</i> in the search.</p></li>
</ul>
</li>
<li>
<p>Edit the <b>runicutzuenv.X</b> file, where X depends on your system (<b>.sh</b> for Unix-based systems, <b>.bat</b> for Windows, <b>.cmd</b> for Windows NT):</p>
<ul><table>
<tr><td valign=top><li><p><b>JAVA_HOME</b>:</td><td>Set this to the path where java is installed on your machine (ie. C:\Program Files\Java\jdk1.5.0 for Windows or /usr/jdk1.5.0 for Unix).</p></li></td></tr>
<tr><td valign=top><li><p><b>NOGUI</b>:</td><td>Set this to <b>true</b> to run in command-line mode. If set to <b>false</b>, ICUTZU will run in <a href="#gui">GUI mode</a> and the DISCOVERONLY option will be ignored.</p></li></td></tr>
<tr><td valign=top><li><p><b>DISCOVERONLY</b>:</td><td>Set this to <b>true</b> the first time ICUTZU is run. When true, ICUTZU will build a list of updatable ICU4J jar files and save it to ICUList.txt. When false, ICUTZU will procede to update the files listed in ICUList.txt.</p></li></td></tr>
<tr><td valign=top><li><p><b>SILENTPATCH</b>:</td><td>Set this to <b>false</b> for normal running, or true to give no output except in the case of an error. This option does not effect the content of the log file.</p></li></td></tr>
<tr><td valign=top><li><p><b>OFFLINE</b>:</td><td>Set this to <b>false</b> for normal running, or true to keep ICUTZU from checking online for the latest time zone data and to use the local copy bundled with ICUTZU instead.</p></li></td></tr>
</table></ul>
</li>
<li><p>Run <b>runicutzu.X</b> where X depends on your system (as above). This will build a list of updatable ICU4J files and save it to ICUList.txt.</p></li>
<li><p>Edit the <b>runicutzuenv.X</b> file again, and set DISCOVERONLY to <b>false</b>..</p></li>
<li><p>Run <b>runicutzu.X</b> again. This will update the files listed in ICUList.txt.</p></li>
</ol>
<a name="restore"><h3>Restoring Changes</h3></a>
<p>
When updating an icu4j jar file, the original file is copied to a backup location which is reported during runtime in the console output (which can also be found in the log file).
<ul>
<li><p>The backup location is of the form <i>[icutzu home]<b>/Temp/</b>[prefix]<b>/</b>[prefix]~[unique id]<b>.jar</b></i>, where <i>[prefix]</i> is the filename of the original icu4j jar file without the .jar at the end.</p></li>
<li><p>The txt file in the same directory that shares the same <i>[unique id]</i> specifies the original location.</p></li>
<li>
<p>Example: If ICUTZU is running from <b>c:\icutzu</b> and updates <b>c:\icu4j_3-6.jar</b>, the backup will be stored in <b>c:\icutzu\icu4j\icu4j_3-6~</b><i>[unique id]</i><b>.jar</b>.</p>
<p>The file <b>c:\icutzu\icu4j\icu4j_3-6~</b><i>[unique id]</i><b>.txt</b> will contain the original path of icu4j_3-6.jar.</p>
</li>
</ul>
</p>
</body>
</html>

View File

@ -1,68 +0,0 @@
@echo off
rem *******************************************************************************
rem * Copyright (C) 2007-2008 International Business Machines Corporation and *
rem * others. All Rights Reserved. *
rem *******************************************************************************
@echo.
@echo *********** Welcome to the ICU4J Time Zone Update Utility (ICUTZU) ***********
rem Set ICUTZU_HOME to the current directory.
set ICUTZU_HOME=%~dp0
@echo ICUTZU Home: %ICUTZU_HOME%
@echo.
rem Make sure certain files are present.
IF NOT EXIST "%ICUTZU_HOME%icutzu.jar" GOTO MissingICUTZUJAR
IF NOT EXIST "%ICUTZU_HOME%icu4j.jar" GOTO MissingICU4JJAR
IF NOT EXIST "%ICUTZU_HOME%runicutzuenv.bat" GOTO MissingICUTZUENV
rem Set environmental variables.
call "%ICUTZU_HOME%runicutzuenv.bat"
IF NOT EXIST "%JAVA_HOME%\bin\java.exe" GOTO MissingJAVAHOME
rem Create a temporary directory if one doesn't exit already.
IF EXIST "%ICUTZU_HOME%Temp" GOTO TempAlreadyExists
mkdir "%ICUTZU_HOME%Temp"
:TempAlreadyExists
rem Run the ICUTZU tool.
@echo.
@echo Launching the ICU4J Time Zone Update Utility (ICUTZU)...
@echo "%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% -Doffline=%OFFLINE% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif
@echo.
"%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% -Doffline=%OFFLINE% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif
IF ERRORLEVEL==0 GOTO Success
GOTO Failure
:MissingICUTZUJAR
@echo The ICU4J Time Zone Update Utility (icutzu.jar) doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingICU4JJAR
@echo ICU for Java (icu4j.jar) doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingICUTZUENV
@echo runicutzuenv.bat file doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingJAVAHOME
@echo java.exe does not exist in %JAVA_HOME%\bin. Please update the JAVA_HOME enviroment variable in runicutzuenv.bat
GOTO Failure
:Success
@echo.
@echo End of ICU4J Time Zone Update Utility (ICUTZU) completed successfully.
GOTO Exit
:Failure
@echo.
@echo ICU4J Time Zone Update Utility (ICUTZU) did not complete successfully.
GOTO Exit
:Exit

View File

@ -1,68 +0,0 @@
@echo off
rem *******************************************************************************
rem * Copyright (C) 2007-2008 International Business Machines Corporation and *
rem * others. All Rights Reserved. *
rem *******************************************************************************
@echo.
@echo *********** Welcome to the ICU4J Time Zone Update Utility (ICUTZU) ***********
rem Set ICUTZU_HOME to the current directory.
set ICUTZU_HOME=/* ENTER YOUR ICUTZU HOME PATH LIKE C:\DESKTOP\ICUTZU\ */
@echo ICUTZU Home: %ICUTZU_HOME%
@echo.
rem Make sure certain files are present.
IF NOT EXIST "%ICUTZU_HOME%icutzu.jar" GOTO MissingICUTZUJAR
IF NOT EXIST "%ICUTZU_HOME%icu4j.jar" GOTO MissingICU4JJAR
IF NOT EXIST "%ICUTZU_HOME%runicutzuenv.cmd" GOTO MissingICUTZUENV
rem Set environmental variables.
call "%ICUTZU_HOME%runicutzuenv.cmd"
IF NOT EXIST "%JAVA_HOME%\bin\java.exe" GOTO MissingJAVAHOME
rem Create a temporary directory if one doesn't exit already.
IF EXIST "%ICUTZU_HOME%Temp" GOTO TempAlreadyExists
mkdir "%ICUTZU_HOME%Temp"
:TempAlreadyExists
rem Run the ICUTZU tool.
@echo.
@echo Launching the ICU4J Time Zone Update Utility (ICUTZU)...
@echo "%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% -Doffline=%OFFLINE% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif
@echo.
"%JAVA_HOME%\bin\java.exe" -cp "%ICUTZU_HOME%icutzu.jar" -Dnogui=%NOGUI% -Ddiscoveronly=%DISCOVERONLY% -Dsilentpatch=%SILENTPATCH% -Doffline=%OFFLINE% com.ibm.icu.dev.tool.tzu.ICUTZUMain "%ICUTZU_HOME%\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif
IF ERRORLEVEL==0 GOTO Success
GOTO Failure
:MissingICUTZUJAR
@echo The ICU4J Time Zone Update Utility (icutzu.jar) doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingICU4JJAR
@echo ICU for Java (icu4j.jar) doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingICUTZUENV
@echo runicutzuenv.cmd file doesn't exist in %ICUTZU_HOME%.
GOTO Failure
:MissingJAVAHOME
@echo java.exe does not exist in %JAVA_HOME%\bin. Please update the JAVA_HOME enviroment variable in runicutzuenv.cmd
GOTO Failure
:Success
@echo.
@echo End of ICU4J Time Zone Update Utility (ICUTZU) completed successfully.
GOTO Exit
:Failure
@echo.
@echo ICU4J Time Zone Update Utility (ICUTZU) did not complete successfully.
GOTO Exit
:Exit

View File

@ -1,73 +0,0 @@
#!/bin/sh
# Copyright (c) 2007-2008 International Business Machines Corporation and others.
# All rights reserved
MissingICUTZUJAR() {
echo "The ICU4J Time Zone Update Utility (icutzu.jar) doesn't exist in $ICUTZU_HOME"
Failure
}
MissingICU4JJAR() {
echo "ICU for Java (icu4j.jar) doesn't exist in $ICUTZU_HOME"
Failure
}
MissingICUTZUENV() {
echo "runicutzuenv.sh file doesn't exist in $ICUTZU_HOME"
Failure
}
MissingJAVAHOME() {
echo "java does not exist in $JAVA_HOME/bin. Please update the JAVA_HOME enviroment variable in runicutzuenv.sh"
Failure
}
Success() {
echo
echo "End of ICU4J Time Zone Update Utility (ICUTZU) completed successfully."
exit 0
}
Failure() {
echo
echo "ICU4J Time Zone Update Utility (ICUTZU) did not complete successfully."
exit -1
}
echo ""
echo "*********** Welcome to the ICU4J Time Zone Update Utility (ICUTZU) ***********"
# Set ICUTZU_HOME to the current directory.
ICUTZU_HOME=`pwd`
echo "ICUTZU Home: $ICUTZU_HOME"
echo
# Make sure certain files are present.
if [ ! -f "$ICUTZU_HOME/icutzu.jar" ] ; then MissingICUTZUJAR ; fi
if [ ! -f "$ICUTZU_HOME/icu4j.jar" ] ; then MissingICU4JJAR ; fi
if [ ! -f "$ICUTZU_HOME/runicutzuenv.sh" ] ; then MissingICUTZUENV ; fi
# Set environmental variables.
. "$ICUTZU_HOME/runicutzuenv.sh"
if [ ! -f "$JAVA_HOME/bin/java" ] ; then MissingJAVAHOME ; fi
# Create a temporary directory if one doesn't exit already.
if [ ! -d "$ICUTZU_HOME/Temp" ] ; then mkdir "$ICUTZU_HOME/Temp" ; fi
# Run the ICUTZU tool.
echo
echo "Launching the ICU4J Time Zone Update Utility (ICUTZU)..."
echo "\"$JAVA_HOME/bin/java\" -cp \"$ICUTZU_HOME/icutzu.jar\" -Dnogui=$NOGUI -Ddiscoveronly=$DISCOVERONLY -Dsilentpatch=$SILENTPATCH -Doffline=$OFFLINE com.ibm.icu.dev.tool.tzu.ICUTZUMain \"$ICUTZU_HOME/\" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif"
echo
"$JAVA_HOME/bin/java" -cp "$ICUTZU_HOME/icutzu.jar" -Dnogui=$NOGUI -Ddiscoveronly=$DISCOVERONLY -Dsilentpatch=$SILENTPATCH -Doffline=$OFFLINE com.ibm.icu.dev.tool.tzu.ICUTZUMain "$ICUTZU_HOME/" DirectorySearch.txt ICUList.txt zoneinfo.res Temp icu.gif
# Test the exit code.
if [ $? -eq "0" ] ; then
Success
else
Failure
fi

View File

@ -1,28 +0,0 @@
@echo off
rem *******************************************************************************
rem * Copyright (C) 2007-2008 International Business Machines Corporation and *
rem * others. All Rights Reserved. *
rem *******************************************************************************
rem Set JAVA_HOME to the Java installation directory.
IF EXIST "%JAVA_HOME%" GOTO Next
set JAVA_HOME=/*ENTER JAVA PATH UPTO JRE*/
:Next
@echo JAVA_HOME=%JAVA_HOME%
rem Set whether the GUI will be run or not.
set NOGUI=true
@echo NOGUI=%NOGUI%
rem Set whether the cmd-line utility will only discover update icu4j files.
set DISCOVERONLY=true
@echo DISCOVERONLY=%DISCOVERONLY%
rem Set whether the cmd-line utility will run silently.
set SILENTPATCH=false
@echo SILENTPATCH=%SILENTPATCH%
rem Set whether the cmd-line utility will not use online sources.
set OFFLINE=false
@echo OFFLINE=%OFFLINE%

View File

@ -1,28 +0,0 @@
@echo off
rem *******************************************************************************
rem * Copyright (C) 2007-2008 International Business Machines Corporation and *
rem * others. All Rights Reserved. *
rem *******************************************************************************
rem Set JAVA_HOME to the Java installation directory.
IF EXIST "%JAVA_HOME%" GOTO Next
set JAVA_HOME=/*ENTER JAVA PATH UPTO JRE*/
:Next
@echo JAVA_HOME=%JAVA_HOME%
rem Set whether the GUI will be run or not.
set NOGUI=true
@echo NOGUI=%NOGUI%
rem Set whether the cmd-line utility will only discover update icu4j files.
set DISCOVERONLY=true
@echo DISCOVERONLY=%DISCOVERONLY%
rem Set whether the cmd-line utility will run silently.
set SILENTPATCH=false
@echo SILENTPATCH=%SILENTPATCH%
rem Set whether the cmd-line utility will not use online sources.
set OFFLINE=false
@echo OFFLINE=%OFFLINE%

View File

@ -1,24 +0,0 @@
# *******************************************************************************
# * Copyright (C) 2007-2008 International Business Machines Corporation and *
# * others. All Rights Reserved. *
# *******************************************************************************
#set java path in JAVA_HOME
JAVA_HOME=/*ENTER JAVA PATH UPTO JRE*/
echo "JAVA_HOME=$JAVA_HOME"
#set NOGUI
NOGUI=true
echo "NOGUI=$NOGUI"
#set DISCOVERONLY
DISCOVERONLY=true
echo "DISCOVERONLY=$DISCOVERONLY"
#set SILENTPATCH
SILENTPATCH=false
echo "SILENTPATCH=$SILENTPATCH"
#set OFFLINE
OFFLINE=false
echo "OFFLINE=$OFFLINE"

View File

@ -1,210 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* Loads the ICUTZU tool, command-line version.
*/
public class CLILoader {
/**
* The filename of the log file in patch mode.
*/
public static final String LOG_FILENAME_PATCH = "icutzu_patch.log";
/**
* The filename of the log file in discovery only mode.
*/
public static final String LOG_FILENAME_DISCOVERYONLY = "icutzu_discovery.log";
/**
* 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.
*/
private Logger logger;
/**
* The file that stores the path list.
*/
private File pathFile = null;
/**
* A glorified list of IncludePath objects representing the list of directories used in
* discovery mode.
*/
private PathModel pathModel;
/**
* The file that stores the result list.
*/
private File resultFile = null;
/**
* A glorified list of ICUFile objects representing the ICU4J jars found in discovery mode and
* used in patch mode.
*/
private ResultModel resultModel;
/**
* A glorified map of Strings to URLs populated by parsing the directory structure in the ICU
* Time Zone repository online and used in patch mode.
*/
private SourceModel sourceModel;
/**
* The local timezone resource file.
*/
private File tzFile = null;
/**
* Entry point for the command-line 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.
*/
public CLILoader(File curDir, File backupDir, File pathFile, File resultFile, File tzFile) {
// determine whether we are running in discover only mode or patch mode
boolean discoverOnly = "true".equalsIgnoreCase(System.getProperty("discoveronly"));
boolean silentPatch = "true".equalsIgnoreCase(System.getProperty("silentpatch"));
File logFile = new File(curDir.getPath(), (discoverOnly ? "icutzu_discover.log"
: "icutzu_patch.log"));
// create the logger based on the silentpatch option
try {
this.logger = Logger.getInstance(logFile, silentPatch ? Logger.QUIET : Logger.NORMAL);
} catch (FileNotFoundException ex) {
System.out.println("Could not open " + logFile.getPath() + " for writing.");
System.exit(-1);
}
this.pathFile = pathFile;
this.resultFile = resultFile;
this.tzFile = tzFile;
this.backupDir = backupDir;
this.curDir = curDir;
// if discoveryonly is enabled, call the search method
// otherwise, call the update method
try {
if (discoverOnly)
search();
else
update();
} catch (IllegalArgumentException ex) {
logger.errorln(ex.getMessage());
} catch (IOException ex) {
logger.errorln(ex.getMessage());
} catch (InterruptedException ex) {
logger.errorln(ex.getMessage());
}
}
/**
* 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("");
logger.printlnToScreen("*********** Command-Line \'Discover Only\'"
+ " Mode Started ***********");
logger.printlnToScreen("");
logger.printlnToScreen("\'Discover Only\' Mode:");
logger.printlnToScreen("In 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 ICUList.txt");
logger.printlnToScreen("");
// initialize the result model and the path model
resultModel = new ResultModel(logger, resultFile);
pathModel = new PathModel(logger, pathFile);
// load paths stored in PathModel.PATHLIST_FILENAME
pathModel.loadPaths();
// perform the search, putting the the results in the result model,
// searching all subdirectories of the included path, using the backup
// directory specified, and without using a status bar (since this is
// command-line)
logger.printlnToScreen("");
logger.printlnToScreen("Search started.");
pathModel.searchAll(resultModel, true, curDir, backupDir);
logger.printlnToScreen("Search ended.");
logger.printlnToScreen("");
// 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 resultFile, populate the tz version list via the web,
* and update all the results with the best available Time Zone data.
*
* @throws IOException
* @throws IllegalArgumentException
* @throws InterruptedException
*/
private void update() throws IOException, IllegalArgumentException, InterruptedException {
logger.printlnToScreen("");
logger.printlnToScreen("*********** Command-Line \'Patch\'" + " Mode Started ***********");
logger.printlnToScreen("");
logger.printlnToScreen("\'Patch\' Mode:");
logger.printlnToScreen("In 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, resultFile);
sourceModel = new SourceModel(logger, tzFile);
// load the results from the result list file
resultModel.loadResults();
// if the offline is not set to true, populate the list of available
// timezone resource versions
if (!"true".equalsIgnoreCase(System.getProperty("offline")))
sourceModel.findSources();
// perform the updates using the best tz version available
resultModel.updateAll(sourceModel.getURL(sourceModel.getSelectedItem()), backupDir);
logger.printlnToScreen("");
logger.printlnToScreen("*********** Command-Line \'Patch\'" + " Mode Ended ***********");
logger.printlnToScreen("");
}
}

View File

@ -1,411 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
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;
/**
* Loads the ICUTZU tool, GUI version.
*/
public class GUILoader {
/**
* The title for the application.
*/
public static final String TITLE = "ICU4J Time Zone Update Utility (ICUTZU)";
/**
* The backup directory to store files.
*/
private File backupDir;
/**
* The tool's home directory.
*/
private File curDir;
/**
* The current logger.
*/
private Logger logger;
/**
* Whether the paths frame has been closed or not.
*/
private boolean pathClosed = false;
/**
* The frame that displays the path model component (<code>pathGUI</code>).
*/
private JFrame pathFrame;
/**
* The component that allows the user to interact with the path model.
*/
private PathComponent pathGUI;
/**
* The path model that stores all the paths and takes care of searching.
*/
private PathModel pathModel;
/**
* Whether the results frame has been closed or not.
*/
private boolean resultClosed = true;
/**
* The frame that displays the result model component (<code>resultGUI</code>).
*/
private JFrame resultFrame;
/**
* The component that allows the user to interact with the result model.
*/
private ResultComponent resultGUI;
/**
* The result model that stores all the results and takes care of updating.
*/
private ResultModel resultModel;
/**
* The source model that stores all the update sources and accesses the repository for more
* sources.
*/
private SourceModel sourceModel;
/**
* The thread that partakes in the searching and updating.
*/
private Thread workerThread = null;
/**
* 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;
// get the icon
Image icon = Toolkit.getDefaultToolkit().getImage(iconFile.getAbsolutePath());
// initialize the path list gui
pathGUI = new PathComponent(this);
pathFrame = new JFrame(TITLE + " - Directories to Search");
pathFrame.getContentPane().add(pathGUI);
pathFrame.pack();
pathFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
pathFrame.setIconImage(icon);
pathFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
if (resultClosed)
System.exit(0);
pathClosed = true;
}
});
// initialize the result list gui
resultGUI = new ResultComponent(this);
resultFrame = new JFrame(TITLE + " - ICU4J Jar Files to Update");
resultFrame.getContentPane().add(resultGUI);
resultFrame.pack();
resultFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
resultFrame.setIconImage(icon);
resultFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
if (pathClosed)
System.exit(0);
resultClosed = true;
makeThreadDead();
}
});
// get the logger instance
try {
File logFile = new File(curDir.getPath(), "icutzugui.log");
logger = Logger.getInstance(logFile, Logger.NORMAL, resultGUI, 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);
}
// 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 {
// do it quietly
int verb = logger.getVerbosity();
logger.setVerbosity(Logger.QUIET);
pathModel.loadPaths();
logger.setVerbosity(verb);
} catch (IOException ex) {
// failed to load the directory search file
pathModel.addAllDrives();
} catch (IllegalArgumentException ex) {
// failed to load the directory search file
pathModel.addAllDrives();
}
// if the offline is not set to true, populate the list of available
// timezone resource versions
if (!"true".equalsIgnoreCase(System.getProperty("offline")))
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);
// show the path list gui
pathFrame.setVisible(true);
}
/**
* Cancels a search.
*/
public void cancelSearch() {
makeThreadDead();
}
/**
* Cancels an update.
*/
public void cancelUpdate() {
makeThreadDead();
}
/**
* 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();
workerThread = new Thread(new Runnable() {
public void run() {
try {
logger.printlnToBoth("Search started ...");
setCancelSearchEnabled(true);
setUpdateEnabled(false);
setSearchEnabled(false);
resultFrame.setVisible(true);
resultClosed = false;
pathModel.search(resultModel, indices, subdirs, curDir, backupDir);
logger.printlnToBoth("Search ended.");
} catch (InterruptedException ex) {
logger.printlnToBoth("Search interrupted.");
}
setSearchEnabled(true);
setUpdateEnabled(true);
setCancelSearchEnabled(false);
}
});
workerThread.start();
}
/**
* Searchs all the paths in the path model.
*
* @param subdirs
* Whether to search subdirectories.
*/
public void searchAll(final boolean subdirs) {
makeThreadDead();
workerThread = new Thread(new Runnable() {
public void run() {
try {
logger.printlnToBoth("Search started ...");
setCancelSearchEnabled(true);
setUpdateEnabled(false);
setSearchEnabled(false);
resultFrame.setVisible(true);
resultClosed = false;
pathModel.searchAll(resultModel, subdirs, curDir, backupDir);
logger.printlnToBoth("Search ended.");
} catch (InterruptedException ex) {
logger.printlnToBoth("Search interrupted.");
}
setSearchEnabled(true);
setUpdateEnabled(true);
setCancelSearchEnabled(false);
}
});
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();
workerThread = new Thread(new Runnable() {
public void run() {
try {
logger.printlnToBoth("Update started ...");
setCancelUpdateEnabled(true);
setUpdateEnabled(false);
setSearchEnabled(false);
resultModel.update(indices, updateURL, backupDir);
logger.printlnToBoth("Update ended.");
} catch (InterruptedException ex) {
// we want to know what was last being updated, so do not
// change the status bar message
// try {
// logger.setStatus("Update interrupted.");
// } catch (InterruptedException e) {
// // once is enough
// }
}
setUpdateEnabled(true);
setSearchEnabled(true);
setCancelUpdateEnabled(false);
}
});
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();
workerThread = new Thread(new Runnable() {
public void run() {
try {
logger.printlnToBoth("Update started ...");
setCancelUpdateEnabled(true);
setUpdateEnabled(false);
setSearchEnabled(false);
resultModel.updateAll(updateURL, backupDir);
logger.printlnToBoth("Update ended.");
} catch (InterruptedException ex) {
// we want to know what was last being updated, so do not
// change the status bar message
// try {
// logger.setStatus("Update interrupted.");
// } catch (InterruptedException e) {
// // once is enough
// }
}
setUpdateEnabled(true);
setSearchEnabled(true);
setCancelUpdateEnabled(false);
}
});
workerThread.start();
}
/**
* 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 -- if an exception was thrown, the worker thread
// must have already been dead, which is perfectly fine
}
}
/**
* 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);
}
/**
* 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);
}
}

View File

@ -1,924 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007-2008, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/**
* 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 {
/**
* ICU version to use if one cannot be found.
*/
public static final String ICU_VERSION_UNKNOWN = "Unknown";
/**
* A directory entry that is found in every updatable ICU4J jar file.
*/
public static final String TZ_ENTRY_DIR = "com/ibm/icu/impl";
/**
* The timezone resource filename.
*/
public static final String TZ_ENTRY_FILENAME = "zoneinfo.res";
/**
* The metazone resource filename.
*/
private static final String MZ_ENTRY_FILENAME = "metazoneInfo.res";
/**
* Key to use when getting the version of a timezone resource.
*/
public static final String TZ_VERSION_KEY = "TZVersion";
/**
* Timezone version to use if one cannot be found.
*/
public static final String TZ_VERSION_UNKNOWN = "Unknown";
/**
* Jar entry path where some files are duplicated. This is an issue with icu4j 3.8.0.
*/
public static final String DUPLICATE_ENTRY_PATH = "com/ibm/icu/impl/duration/impl/data";
/**
* The buffer size to use for copying data.
*/
private static final int BUFFER_SIZE = 1024;
/**
* A map that caches links from URLs to time zone data to their downloaded File counterparts.
*/
private static final Map cacheMap = new HashMap();
/**
* Determines the version of a timezone resource as a standard file without locking the file.
*
* @param tzFile
* The file representing the timezone resource.
* @param logger
* The current logger.
* @return The version of the timezone resource.
*/
public static String findFileTZVersion(File tzFile, Logger logger) {
ICUFile rawTZFile = new ICUFile(logger);
try {
File temp = File.createTempFile("zoneinfo", ".res");
temp.deleteOnExit();
rawTZFile.copyFile(tzFile, temp);
return findTZVersion(temp, logger);
} catch (IOException ex) {
logger.errorln(ex.getMessage());
return null;
}
}
/**
* Determines the version of a timezone resource as a standard file, but locks the file for the
* duration of the program.
*
* @param tzFile
* The file representing the timezone resource.
* @param logger
* The current logger.
* @return The version of the timezone resource.
*/
private static String findTZVersion(File tzFile, Logger logger) {
try {
String filename = tzFile.getName();
String entryname = filename.substring(0, filename.length() - ".res".length());
URL url = new URL(tzFile.getAbsoluteFile().getParentFile().toURL().toString());
ClassLoader loader = new URLClassLoader(new URL[] { url });
// UResourceBundle bundle = UResourceBundle.getBundleInstance("",
// entryname, loader);
URL bundleURL = new URL(new File("icu4j.jar").toURL().toString());
URLClassLoader bundleLoader = new URLClassLoader(new URL[] { bundleURL });
Class bundleClass = bundleLoader.loadClass("com.ibm.icu.util.UResourceBundle");
Method bundleGetInstance = bundleClass.getMethod("getBundleInstance", new Class[] {
String.class, String.class, ClassLoader.class });
Object bundle = bundleGetInstance.invoke(null, new Object[] { "", entryname, loader });
if (bundle != null) {
Method bundleGetString = bundleClass.getMethod("getString",
new Class[] { String.class });
String tzVersion = (String) bundleGetString.invoke(bundle,
new Object[] { TZ_VERSION_KEY });
if (tzVersion != null)
return tzVersion;
}
} catch (MalformedURLException ex) {
// this should never happen
logger.errorln("Internal program error.");
logger.logStackTraceToBoth(ex);
} catch (ClassNotFoundException ex) {
// this would most likely happen when UResourceBundle cannot be
// resolved, which is when icu4j.jar is not where it should be
logger.errorln("icu4j.jar not found");
logger.logStackTraceToBoth(ex);
} catch (NoSuchMethodException ex) {
// this can only be caused by a very unlikely scenario
logger.errorln("icu4j.jar not correct");
logger.logStackTraceToBoth(ex);
} catch (IllegalAccessException ex) {
// this can only be caused by a very unlikely scenario
logger.errorln("icu4j.jar not correct");
logger.logStackTraceToBoth(ex);
} catch (InvocationTargetException ex) {
// if this is holding a MissingResourceException, then this is not
// an error -- some zoneinfo files are missing version numbers
if (!(ex.getTargetException() instanceof MissingResourceException)) {
logger.errorln("icu4j.jar not correct");
logger.logStackTraceToBoth(ex);
}
}
return TZ_VERSION_UNKNOWN;
}
/**
* Finds the jar entry in the jar file that represents a timezone resource and returns it, or
* null if none is found.
*
* @param jar The jar file to search.
* @param entryName The target entry name
*
* @return The jar entry representing the timezone resource in the jar file, or null if none is
* found.
*/
private static JarEntry getTZEntry(JarFile jar, String entryName) {
JarEntry tzEntry = null;
Enumeration e = jar.entries();
while (e.hasMoreElements()) {
tzEntry = (JarEntry) e.nextElement();
if (tzEntry.getName().endsWith(entryName))
return tzEntry;
}
return null;
}
/**
* The ICU4J jar file represented by this ICUFile.
*/
private File icuFile;
/**
* The ICU version of the ICU4J jar.
*/
private String icuVersion;
/**
* The current logger.
*/
private Logger logger;
/**
* The entry for the timezone resource inside the ICU4J jar.
*/
private JarEntry tzEntry;
/**
* The entry for the metazone resource inside the ICU4J jar.
*/
private JarEntry mzEntry;
/**
* The version of the timezone resource inside the ICU4J jar.
*/
private String tzVersion;
/**
* Constructs an ICUFile around a file. See <code>initialize</code> for details.
*
* @param file
* The file to wrap this ICUFile around.
* @param logger
* The current logger.
* @throws IOException
*/
public ICUFile(File file, Logger logger) throws IOException {
initialize(file, logger);
}
/**
* Constructs an ICUFile around a file. See <code>initialize</code> for details.
*
* @param filename
* The file to wrap this ICUFile around.
* @param logger
* The current logger.
* @throws IOException
*/
public ICUFile(String filename, Logger logger) throws IOException {
if (filename == null || filename.trim().length() == 0)
throw new IOException("cannot be blank");
initialize(new File(filename), logger);
}
/**
* Constructs a blank ICUFile. Used internally for timezone resource files that are not
* contained within a jar.
*
* @param logger
* The current logger.
*/
private ICUFile(Logger logger) {
this.logger = logger;
}
/**
* 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.
*/
public boolean equals(Object other) {
return (!(other instanceof ICUFile)) ? false : icuFile.getAbsoluteFile().equals(
((ICUFile) other).icuFile.getAbsoluteFile());
}
/**
* Determines the version of a timezone resource in a jar file without locking the jar file.
*
* @return The version of the timezone resource.
*/
public String findEntryTZVersion() {
try {
File temp = File.createTempFile("zoneinfo", ".res");
temp.deleteOnExit();
copyEntry(icuFile, tzEntry, temp);
return findTZVersion(temp, logger);
} catch (IOException ex) {
logger.errorln(ex.getMessage());
return null;
}
}
/**
* Returns the File object represented by this ICUFile object.
*
* @return The File object represented by this ICUFile object.
*/
public File getFile() {
return icuFile;
}
/**
* Returns the filename of this ICUFile object, without the path.
*
* @return The filename of this ICUFile object, without the path.
*/
public String getFilename() {
return icuFile.getName();
}
/**
* Returns the ICU version of this ICU4J jar.
*
* @return The ICU version of this ICU4J jar.
*/
public String getICUVersion() {
return icuVersion;
}
/**
* Returns the path of this ICUFile object, without the filename.
*
* @return The path of this ICUFile object, without the filename.
*/
public String getPath() {
return icuFile.getAbsoluteFile().getParent();
}
// public static String findURLTZVersion(File tzFile) {
// try {
// File temp = File.createTempFile("zoneinfo", ".res");
// temp.deleteOnExit();
// copyFile(tzFile, temp);
// return findTZVersion(temp);
// } catch (IOException ex) {
// ex.printStackTrace();
// return null;
// }
// }
/**
* Returns the timezone resource version.
*
* @return The timezone resource version.
*/
public String getTZVersion() {
return tzVersion;
}
/**
* Returns the result of getFile().toString().
*
* @return The result of getFile().toString().
*/
public String toString() {
return getFile().toString();
}
/**
* Updates the timezone resource in this ICUFile using <code>insertURL</code> as the source of
* the new timezone resource and the backup directory <code>backupDir</code> to store a copy
* of the ICUFile.
*
* @param insertURL
* The url location of the timezone resource to use.
* @param backupDir
* The directory to store a backup for this ICUFile, or null if no backup.
* @throws IOException
* @throws InterruptedException
*/
public void update(URL insertURL, File backupDir) throws IOException, InterruptedException {
String message = "Updating " + icuFile.getPath() + " ...";
logger.printlnToBoth("");
logger.printlnToBoth(message);
if (!icuFile.canRead() || !icuFile.canWrite())
throw new IOException("Missing permissions for " + icuFile.getPath());
JarEntry[] jarEntries = new JarEntry[2];
URL[] insertURLs = new URL[2];
jarEntries[0] = tzEntry;
insertURLs[0] = getCachedURL(insertURL);
if (insertURLs[0] == null)
throw new IOException(
"Could not download the Time Zone data, skipping update for this jar.");
// Check if metazoneInfo.res is available
String tzURLStr = insertURL.toString();
int lastSlashIdx = tzURLStr.lastIndexOf('/');
if (lastSlashIdx >= 0) {
String mzURLStr = tzURLStr.substring(0, lastSlashIdx + 1) + MZ_ENTRY_FILENAME;
insertURLs[1] = getCachedURL(new URL(mzURLStr));
if (insertURLs[1] != null) {
jarEntries[1] = mzEntry;
}
}
File backupFile = null;
if ((backupFile = createBackupFile(icuFile, backupDir)) == null)
throw new IOException(
"Could not create an empty backup file (the original jar file remains unchanged).");
if (!copyFile(icuFile, backupFile))
throw new IOException(
"Could not copy the original jar file to the backup location (the original jar file remains unchanged).");
logger.printlnToBoth("Backup location: " + backupFile.getPath());
if (!createUpdatedJar(backupFile, icuFile, jarEntries, insertURLs))
throw new IOException(
"Could not create an updated jar file at the original location (the original jar file is at the backup location).");
// get the new timezone resource version
tzVersion = findEntryTZVersion();
message = "Successfully updated " + icuFile.getPath();
logger.printlnToBoth(message);
}
/**
* Copies the jar entry <code>insertEntry</code> in <code>inputFile</code> to
* <code>outputFile</code>.
*
* @param inputFile
* The jar file containing <code>insertEntry</code>.
* @param inputEntry
* The entry to copy.
* @param outputFile
* 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
+ ".");
JarFile jar = null;
InputStream istream = null;
OutputStream ostream = null;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
boolean success = false;
try {
jar = new JarFile(inputFile);
istream = jar.getInputStream(inputEntry);
ostream = new FileOutputStream(outputFile);
while ((bytesRead = istream.read(buffer)) != -1)
ostream.write(buffer, 0, bytesRead);
success = true;
logger.loglnToBoth("Copy successful.");
} catch (IOException ex) {
outputFile.delete();
logger.loglnToBoth("Copy failed.");
logger.logStackTraceToBoth(ex);
} finally {
// safely close the streams
tryClose(jar);
tryClose(istream);
tryClose(ostream);
}
return success;
}
/**
* Copies <code>inputFile</code> to <code>outputFile</code>.
*
* @param inputFile
* The input file.
* @param outputFile
* The output file.
* @return Whether the operation was successful.
*/
private boolean copyFile(File inputFile, File outputFile) {
logger.loglnToBoth("Copying from " + inputFile + " to " + outputFile + ".");
InputStream istream = null;
OutputStream ostream = null;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
boolean success = false;
try {
istream = new FileInputStream(inputFile);
ostream = new FileOutputStream(outputFile);
while ((bytesRead = istream.read(buffer)) != -1)
ostream.write(buffer, 0, bytesRead);
success = true;
logger.loglnToBoth("Copy successful.");
} catch (IOException ex) {
outputFile.delete();
logger.loglnToBoth("Copy failed.");
logger.logStackTraceToBoth(ex);
} finally {
// safely close the streams
tryClose(istream);
tryClose(ostream);
}
return success;
}
/**
* Creates a temporary file for the jar file <code>inputFile</code> under the directory
* <code>backupBase</code> and returns it, or returns null if a temporary file could not be
* created. Does not put any data in the newly created file yet.
*
* @param inputFile
* The file to backup.
* @param backupBase
* The directory where backups are to be stored.
* @return The temporary file that was created.
*/
private File createBackupFile(File inputFile, File backupBase) {
logger.loglnToBoth("Creating backup file for " + inputFile + " at " + backupBase + ".");
String filename = inputFile.getName();
String suffix = ".jar";
String prefix = filename.substring(0, filename.length() - suffix.length());
if (backupBase == null) {
try {
// no backup directory means we need to create a temporary file
// that will be deleted on exit
File backupFile = File.createTempFile(prefix + "~", suffix);
backupFile.deleteOnExit();
return backupFile;
} catch (IOException ex) {
return null;
}
}
File backupFile = null;
File backupDesc = null;
File backupDir = new File(backupBase.getPath(), prefix);
PrintStream ostream = null;
try {
backupBase.mkdir();
backupDir.mkdir();
backupFile = File.createTempFile(prefix + "~", suffix, backupDir);
backupDesc = new File(backupDir.getPath(), backupFile.getName().substring(0,
backupFile.getName().length() - suffix.length())
+ ".txt");
backupDesc.createNewFile();
ostream = new PrintStream(new FileOutputStream(backupDesc));
ostream.println(inputFile.getPath());
logger.loglnToBoth("Successfully created backup file at " + backupFile + ".");
} catch (IOException ex) {
logger.loglnToBoth("Failed to create backup file.");
logger.logStackTraceToBoth(ex);
if (backupFile != null)
backupFile.delete();
if (backupDesc != null)
backupDesc.delete();
backupDir.delete();
backupFile = null;
} finally {
tryClose(ostream);
}
return backupFile;
}
/**
* Copies <code>inputFile</code> to <code>outputFile</code>, replacing
* <code>insertEntry</code> with <code>inputURL</code>.
*
* @param inputFile
* The input jar file.
* @param outputFile
* The output jar file.
* @param insertEntry
* The entry to be replaced.
* @param inputURL
* The URL to use in replacing the entry.
* @return Whether the operation was successful.
*/
private boolean createUpdatedJar(File inputFile, File outputFile, JarEntry[] insertEntries,
URL[] inputURLs) {
logger.loglnToBoth("Copying " + inputFile + " to " + outputFile + ",");
for (int i = 0; i < insertEntries.length; i++) {
if (insertEntries[i] != null) {
logger.loglnToBoth(" replacing " + insertEntries[i] + " with " + inputURLs[i]);
}
}
JarFile jar = null;
JarOutputStream ostream = null;
InputStream istream = null;
InputStream jstream = null;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
boolean success = false;
Set possibleDuplicates = new HashSet();
try {
jar = new JarFile(inputFile);
ostream = new JarOutputStream(new FileOutputStream(outputFile));
Enumeration e = jar.entries();
while (e.hasMoreElements()) {
JarEntry currentEntry = (JarEntry) e.nextElement();
String entryName = currentEntry.getName();
if (entryName.startsWith(DUPLICATE_ENTRY_PATH)) {
if (!possibleDuplicates.contains(entryName)) {
possibleDuplicates.add(entryName);
} else {
// ruh roh, we have a duplicate entry!
// (just ignore it and continue)
logger.printlnToBoth("Warning: Duplicate " + entryName
+ " found. Ignoring the duplicate.");
continue;
}
}
boolean isReplaced = false;
for (int i = 0; i < insertEntries.length; i++) {
if (insertEntries[i] != null) {
if (entryName.equals(insertEntries[i].getName())) {
// if the current entry *is* the one that needs updating write a new entry based
// on the input stream (from the URL)
// currentEntry.setTime(System.currentTimeMillis());
ostream.putNextEntry(new JarEntry(entryName));
URLConnection con = inputURLs[i].openConnection();
con.setRequestProperty("user-agent", System.getProperty("http.agent"));
istream = con.getInputStream();
while ((bytesRead = istream.read(buffer)) != -1) {
ostream.write(buffer, 0, bytesRead);
}
istream.close();
isReplaced = true;
break;
}
}
}
if (!isReplaced) {
// if the current entry isn't the one that needs updating write a copy of the
// old entry from the old file
ostream.putNextEntry(new JarEntry(entryName));
jstream = jar.getInputStream(currentEntry);
while ((bytesRead = jstream.read(buffer)) != -1)
ostream.write(buffer, 0, bytesRead);
jstream.close();
}
}
success = true;
logger.loglnToBoth("Copy successful.");
} catch (IOException ex) {
outputFile.delete();
logger.loglnToBoth("Copy failed:");
logger.logStackTraceToBoth(ex);
} finally {
// safely close the streams
tryClose(istream);
tryClose(ostream);
tryClose(jstream);
tryClose(jar);
}
return success;
}
/**
* Performs the shared work of the constructors. Throws an IOException if <code>file</code>...
* <ul>
* <li>does not exist</li>
* <li>is not a file</li>
* <li>ends with .ear or .war (these file types are unsupported)</li>
* <li>does not end with .jar</li>
* <li>is not updatable according the <code>isUpdatable</code></li>
* <li>is signed.</li>
* </ul>
* If an exception is not thrown, the ICUFile is fully initialized.
*
* @param file
* The file to wrap this ICUFile around.
* @param logger
* The current logger.
* @throws IOException
*/
private void initialize(File file, Logger log) throws IOException {
this.icuFile = file;
this.logger = log;
String message = null;
if (!file.exists()) {
message = "Skipped " + file.getPath() + " (does not exist).";
} 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).";
logger.loglnToBoth(message);
} else if (!file.canRead() || !file.canWrite()) {
message = "Skipped " + file.getPath() + " (missing permissions).";
} 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() + " (cannot update signed jars).";
logger.loglnToBoth(message);
} else if (isEclipseFragment()) {
message = "Skipped " + file.getPath()
+ " (eclipse fragments must be updated through ICU).";
logger.loglnToBoth(message);
}
if (message != null)
throw new IOException(message);
tzVersion = findEntryTZVersion();
}
/**
* 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().indexOf("plugins" + File.separator + "com.ibm.icu.data.update") >= 0 && icuFile
.getName().equalsIgnoreCase("icu-data.jar"));
}
/**
* 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 Main Fragment.
*
* @return Whether the current jar is an Eclipse Fragment.
*/
private boolean isEclipseMainFragment() {
return (icuFile.getPath().indexOf("plugins") >= 0 && icuFile.getName().startsWith(
"com.ibm.icu_"));
}
/**
* Determines whether a timezone resource in a jar file is signed.
*
* @return Whether a timezone resource in a jar file is signed.
*/
private boolean isSigned() {
return tzEntry.getCertificates() != null;
}
/**
* Gathers information on the jar file represented by this ICUFile object and returns whether it
* is an updatable ICU4J jar file.
*
* @return Whether the jar file represented by this ICUFile object is an updatable ICU4J jar
* file.
*/
private boolean isUpdatable() {
JarFile jar = null;
boolean success = false;
try {
// open icuFile as a jar file
jar = new JarFile(icuFile);
// get its manifest to determine the ICU version
Manifest manifest = jar.getManifest();
icuVersion = ICU_VERSION_UNKNOWN;
if (manifest != null) {
Iterator iter = manifest.getEntries().values().iterator();
while (iter.hasNext()) {
Attributes attr = (Attributes) iter.next();
String ver = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
if (ver != null) {
icuVersion = ver;
break;
}
}
}
// 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, TZ_ENTRY_FILENAME)) != null);
// if the jar file contains metazoneInfo.res, initialize mzEntry -
// this is true for ICU4J 3.8.1 or later releases
if (success) {
mzEntry = getTZEntry(jar, MZ_ENTRY_FILENAME);
}
} 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
logger.loglnToBoth("Error reading " + icuFile.getPath() + ".");
logger.logStackTraceToBoth(ex);
} finally {
// close the jar gracefully
if (!tryClose(jar))
logger.errorln("Could not properly close the jar file " + icuFile + ".");
}
// return whether the jar is updatable or not
return success;
}
private URL getCachedURL(URL url) {
File outputFile = (File) cacheMap.get(url);
if (outputFile != null) {
try {
return outputFile.toURL();
} catch (MalformedURLException ex) {
return null;
}
} else {
InputStream istream = null;
OutputStream ostream = null;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
boolean success = false;
try {
String urlStr = url.toString();
int lastSlash = urlStr.lastIndexOf('/');
String fileName = lastSlash >= 0 ? urlStr.substring(lastSlash + 1) : urlStr;
outputFile = File.createTempFile(fileName, null);
outputFile.deleteOnExit();
logger.loglnToBoth("Downloading from " + url + " to " + outputFile.getPath() + ".");
URLConnection con = url.openConnection();
con.setRequestProperty("user-agent", System.getProperty("http.agent"));
istream = con.getInputStream();
ostream = new FileOutputStream(outputFile);
while ((bytesRead = istream.read(buffer)) != -1)
ostream.write(buffer, 0, bytesRead);
success = true;
logger.loglnToBoth("Download successful.");
} catch (IOException ex) {
outputFile.delete();
logger.loglnToBoth("Download failed.");
logger.logStackTraceToBoth(ex);
} finally {
// safely close the streams
tryClose(istream);
tryClose(ostream);
}
try {
return (success && outputFile != null) ? outputFile.toURL() : null;
} catch (MalformedURLException ex) {
return null;
}
}
}
/**
* Tries to close <code>closeable</code> if possible.
*
* @param closeable
* A closeable object
* @return false if an IOException occured, true otherwise.
*/
private boolean tryClose(InputStream closeable) {
if (closeable != null)
try {
closeable.close();
return true;
} catch (IOException ex) {
return false;
}
else
return true;
}
/**
* Tries to close <code>closeable</code> if possible.
*
* @param closeable
* A closeable object
* @return false if an IOException occured, true otherwise.
*/
private boolean tryClose(OutputStream closeable) {
if (closeable != null)
try {
closeable.close();
return true;
} catch (IOException ex) {
return false;
}
else
return true;
}
/**
* Tries to close <code>closeable</code> if possible.
*
* @param closeable
* A closeable object
* @return false if an IOException occured, true otherwise.
*/
private boolean tryClose(JarFile closeable) {
if (closeable != null)
try {
closeable.close();
return true;
} catch (IOException ex) {
return false;
}
else
return true;
}
}

View File

@ -1,214 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Finds all updatable ICU4J jars in a set of specified directories.
*/
public class ICUJarFinder {
/**
* The delay in milliseconds between showing directories to the command line user.
*/
public static final long DELAY = 5000; // 5 seconds
/**
* The delay in milliseconds between showing directories to the command line user.
*/
public static long lastShowtime = 0; // 5 seconds
/**
* Searchs the directories / files represented in <code>paths</code> for valid ICU4J jars. The
* logic for determining if a file is an ICU4J jar is taken care of by the constructor of
* ICUFile. The resulting ICUFile's are then added to the result model.
*
* @param resultModel
* The result model to add any discovered ICU4J jars to.
* @param logger
* The current logger.
* @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, 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();
for (int i = 0; i < paths.length; i++) {
IncludePath path = paths[i];
File file = path.getPath();
try {
file = file.getCanonicalFile();
} catch (IOException ex) {
// recover in the simplest way, but report the error
file = file.getAbsoluteFile();
logger.errorln(ex.getMessage());
}
if (path.isIncluded())
included.add(file);
else
excluded.add(file);
}
// if the backup dir is specified, don't search it
if (backupDir != null) {
File file = backupDir;
try {
file = file.getCanonicalFile();
} catch (IOException ex) {
// recover in the simplest way, but report the error
file = file.getAbsoluteFile();
logger.errorln(ex.getMessage());
}
excluded.add(file);
}
// exclude the icu4j.jar that comes with this tool
File file = new File(curDir.getPath(), "icu4j.jar");
try {
file = file.getCanonicalFile();
} catch (IOException ex) {
// recover in the simplest way, but report the error
file = file.getAbsoluteFile();
logger.errorln(ex.getMessage());
}
excluded.add(file);
// search each of the included files/directories
for (int i = 0; i < included.size(); i++)
search(resultModel, logger, (File) included.get(i), excluded, subdirs, 0);
// chain the result model
return resultModel;
}
/**
* Checks a specific file. If the file is an ICU4J jar that can be updated, then the ICUFile
* representing that file is added to the result model. If the file is a directory, the
* directory is then recursed.
*
* @param resultModel
* 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 file
* The current file to check or directory to search.
* @param excluded
* The list of all directories excluded in the search.
* @param subdirs
* Whether to include subdirectories in the search.
* @param depth
* The current depth of the search.
* @return The same result model as given.
* @throws InterruptedException
*/
private static ResultModel search(ResultModel resultModel, Logger logger, File file,
List excluded, boolean subdirs, int depth) throws InterruptedException {
// ensure we are not following a symbolic link
if (isSymbolic(file))
return resultModel;
// ensure that the file is in canonical form
try {
file = file.getCanonicalFile();
} catch (IOException ex) {
logger.errorln(ex.getMessage());
return resultModel;
}
// check for interruptions
if (Thread.currentThread().isInterrupted())
throw new InterruptedException();
// make sure the current file/directory isn't excluded
Iterator iter = excluded.iterator();
while (iter.hasNext())
if (file.equals(((File) iter.next())))
return resultModel;
if ((subdirs || depth == 0) && file.isDirectory()) {
// 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
long curTime = System.currentTimeMillis();
if (depth <= 1 || curTime - lastShowtime > DELAY) {
lastShowtime = curTime;
logger.printlnToScreen(file.getPath());
// give a chance for the UI to display the message
if (Thread.currentThread().isInterrupted())
throw new InterruptedException();
Thread.sleep(0);
}
// recurse
for (int i = 0; i < dirlist.length; i++)
search(resultModel, logger, dirlist[i], excluded, subdirs, depth + 1);
}
} else {
// attempt to create an ICUFile object on the current file and add
// it to the result model if possible
try {
// if the file/directory is an ICU jar file that we can
// update, add it to the results
resultModel.add(new ICUFile(file, logger));
logger.printlnToBoth("Added " + file.getPath());
} catch (IOException ex) {
// if it's not an ICU jar file that we can update, ignore it
}
}
// chain the result model
return resultModel;
}
/**
* Tests whether a file is a symbolic link by comparing the absolute path with the canonical
* path.
*
* @param file
* The file to check.
* @return Whether the file is a symbolic link.
*/
private static boolean isSymbolic(File file) {
try {
File parent = file.getParentFile();
if (parent == null)
parent = new File(".");
File betterFile = new File(parent.getCanonicalPath(), file.getName());
return !betterFile.getAbsoluteFile().equals(betterFile.getCanonicalFile());
} catch (IOException ex) {
// if getCanonicalFile throws an IOException for this file, we won't
// want to dig into this path
return false;
}
}
/**
* An empty constructor that restricts construction.
*/
private ICUJarFinder() {
}
}

View File

@ -1,121 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007-2008, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
/**
* Entry point for the ICUTZU tool.
*/
public class ICUTZUMain {
/**
* Argument number for the backup directory.
*/
public static final int BACKUP_DIR = 4;
/**
* Argument number for the current directory.
*/
public static final int CUR_DIR = 0;
/**
* Argument number for the icon file.
*/
public static final int ICON_FILE = 5;
/**
* Number of arguments.
*/
public static final int NUM_ARGS = 6;
/**
* 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;
/**
* Entry point for the ICUTZU tool.
*
* @param args
* 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) {
try {
// TODO: fix this to properly set the user agent
String agent = "ICUTZU/1.2 (" + System.getProperty("os.name") + " "
+ System.getProperty("os.version") + "; " + Locale.getDefault().toString()
+ ")";
System.setProperty("http.agent", agent);
if (args.length == 0) {
// in the case of running without commandline options
File curDir = new File(".");
try {
curDir = curDir.getCanonicalFile();
} catch (IOException ex) {
curDir = curDir.getAbsoluteFile();
}
new GUILoader(curDir, new File("Temp").getAbsoluteFile(), new File(
"DirectorySearch.txt").getAbsoluteFile(), new File("ICUList.txt")
.getAbsoluteFile(), new File("zoneinfo.res").getAbsoluteFile(), new File(
"icu.gif").getAbsoluteFile());
return;
} else 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);
} else {
File curDir = new File(args[CUR_DIR]);
try {
curDir = curDir.getCanonicalFile();
} catch (IOException ex) {
curDir = curDir.getAbsoluteFile();
}
File backupDir = new File(curDir, args[BACKUP_DIR]).getAbsoluteFile();
File pathFile = new File(curDir, args[PATH_FILE]).getAbsoluteFile();
File resultFile = new File(curDir, args[RESULT_FILE]).getAbsoluteFile();
File tzFile = new File(curDir, args[TZ_FILE]).getAbsoluteFile();
File iconFile = new File(curDir, args[ICON_FILE]).getAbsoluteFile();
if ("true".equalsIgnoreCase(System.getProperty("nogui")))
new CLILoader(curDir, backupDir, pathFile, resultFile, tzFile);
else
new GUILoader(curDir, backupDir, pathFile, resultFile, tzFile, iconFile);
}
} catch (Throwable ex) {
// should any unexplained exception occur, we should exit
// abnormally. ideally, this should never happen.
System.err.println("Internal program error.");
ex.printStackTrace();
System.exit(-1);
}
}
}

View File

@ -1,78 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.File;
/**
* Represents a path and whether it should be included or excluded.
*/
public class IncludePath {
/**
* Whether to include or exclude the path represented by this IncludePath.
*/
private boolean include;
/**
* The path represented by this IncludePath.
*/
private File path;
/**
* Constructs an IncludePath around a file or directory and whether it should be included or
* excluded.
*
* @param path
* The file / directory to be used.
* @param include
* Whether the file should be included / excluded.
*/
public IncludePath(File path, boolean include) {
this.path = path;
this.include = include;
}
/**
* 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.
*/
public boolean equals(Object other) {
return !(other instanceof IncludePath) ? false : path.getAbsoluteFile().equals(
((IncludePath) other).path.getAbsoluteFile());
}
/**
* Returns the path of this IncludePath.
*
* @return The path of this IncludePath.
*/
public File getPath() {
return path;
}
/**
* Returns whether the path is included or not.
*
* @return Whether the path is included or not.
*/
public boolean isIncluded() {
return include;
}
/**
* Outputs this IncludePath in the form (<b>+</b>|<b>-</b>)<i>pathstring</i>.
*
* @return The IncludePath as a string.
*/
public String toString() {
return (include ? '+' : '-') + path.toString();
}
}

View File

@ -1,319 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.awt.Component;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Date;
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> and use the output functions to output to the
* screen, the log file, the status bar, and in dialog messages.
*/
public class Logger {
/**
* A default name to use for creating a log file.
*/
public static final String DEFAULT_FILENAME = "icutzu.log";
/**
* The single instance of the logger.
*/
private static Logger logger = null;
/**
* Normal mode.
*/
public static final int NORMAL = 0;
/**
* Quiet mode.
*/
public static final int QUIET = -1;
/**
* Verbose mode.
*/
public static final int VERBOSE = 1;
/**
* 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 logFile
* The file 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>
* @return The instance of the logger.
* @throws FileNotFoundException
*/
public static synchronized Logger getInstance(File logFile, int verbosity)
throws FileNotFoundException {
if (logger == null) {
logger = new Logger(logFile, verbosity, null, null);
}
return logger;
}
/**
* Gets the instance of the logger, constructing a new one with <code>filename</code> and
* <code>verbosity</code> if one is not already constructed. If a statusbar is given, status
* messages will be sent to it. If a dialogParent is specified, dialog messages will be
* displayed.
*
* @param logFile
* The file 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(File logFile, int verbosity,
ResultComponent statusComponent, Component dialogParent) throws FileNotFoundException {
if (logger == null) {
logger = new Logger(logFile, verbosity, statusComponent, dialogParent);
}
return logger;
}
/**
* The parent to use when displaying a dialog.
*/
private Component dialogParent = null;
/**
* The means of output to the log file.
*/
private PrintStream fileStream = null;
/**
* The status bar to display status messages.
*/
private ResultComponent statusComponent = null;
/**
* The verbosity of the logger.
*/
private int verbosity = NORMAL;
/**
* Constructs a logger that outputs to the filename specified and outputs to the screen with the
* specified verbosity. Used internally.
*
* @param filename
* 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(File logFile, int verbosity, ResultComponent statusComponent,
Component dialogParent) throws FileNotFoundException {
if (this.fileStream != null)
this.fileStream.close();
this.fileStream = new PrintStream(new FileOutputStream(logFile.toString(), true));
this.verbosity = verbosity;
this.statusComponent = statusComponent;
this.dialogParent = dialogParent;
this.fileStream.println();
this.fileStream.println("##### " + new Date() + " #####");
this.fileStream.println();
}
/**
* Prints an error message to the screen and to the log.
*
* @param message
* The message to print.
*/
public void error(String message) {
if (statusComponent != null)
statusComponent.addStatusMessage(message);
System.err.print(message);
if (fileStream != null)
fileStream.print(message);
}
/**
* Prints an error message to the screen and to the log, and terminates the line.
*
* @param message
* The message to print.
*/
public void errorln(String message) {
if (statusComponent != null)
statusComponent.addStatusMessage(message);
System.err.println(message);
if (fileStream != null)
fileStream.println(message);
}
/**
* Returns the current allowed verbosity.
*
* @return The current allowed verbosity for output to the screen. Should be one of the
* following:
* <ul>
* <li>QUIET</li>
* <li>NORMAL</li>
* <li>VERBOSE</li>
* </ul>
*/
public int getVerbosity() {
return verbosity;
}
/**
* Sets the allowed verbosity.
*
* @param verbosity
* The desired allowed verbosity for output to the screen. Should be one of the
* following:
* <ul>
* <li>QUIET</li>
* <li>NORMAL</li>
* <li>VERBOSE</li>
* </ul>
*/
public void setVerbosity(int verbosity) {
this.verbosity = verbosity;
}
/**
* Logs a message to the screen if the logger is in a mode higher than normal mode (ie.
* VERBOSE), and always logs the message to the file.
*
* @param message
* The message to print.
*/
public void loglnToBoth(String message) {
loglnToScreen(message);
loglnToFile(message);
}
/**
* Logs a message to the file used by this logger, and terminates the line.
*
* @param message
* The message to print.
*/
public void loglnToFile(String message) {
if (fileStream != null)
fileStream.println(message);
}
/**
* Logs a message to the screen if the logger is in a mode higher than normal mode (ie.
* VERBOSE), and terminates the line.
*
* @param message
* The message to print.
*/
public void loglnToScreen(String message) {
if (verbosity > NORMAL) {
if (statusComponent != null)
statusComponent.addStatusMessage(message);
System.out.println(message);
}
}
/**
* Prints a message to the screen and to the log.
*
* @param message
* The message to print.
*/
public void logStackTraceToBoth(Exception ex) {
logStackTraceToScreen(ex);
logStackTraceToFile(ex);
}
/**
* Logs the stack trace to the file.
*
* @param ex
* The exception
*/
public void logStackTraceToFile(Exception ex) {
if (fileStream != null)
ex.printStackTrace(fileStream);
}
/**
* Logs the stack trace to the file.
*
* @param ex
* The exception
*/
public void logStackTraceToScreen(Exception ex) {
if (verbosity > NORMAL)
ex.printStackTrace(System.out);
}
/**
* Prints a message to the screen and to the log, and terminates the line.
*
* @param message
* The message to print.
*/
public void printlnToBoth(String message) {
printlnToScreen(message);
loglnToFile(message);
}
/**
* Prints a message to the screen, and terminates the line.
*
* @param message
* The message to print.
*/
public void printlnToScreen(String message) {
if (verbosity >= NORMAL) {
if (statusComponent != null)
statusComponent.addStatusMessage(message);
System.out.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);
}
}

View File

@ -1,349 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.awt.Component;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
/**
* The path list GUI component.
*/
public class PathComponent extends JComponent {
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1340;
/**
* A menu item for <code>pathPopup</code> to add all drives to the path model.
*/
private JMenuItem pathAddAllDrivesItem = new JMenuItem("Add All Drives to List");
/**
* The browse button where the user can browse for a particular path.
*/
private JButton pathBrowseButton = new JButton("Browse...");
/**
* A menu item that copies the selected filenames to the clipboard.
*/
private JMenuItem pathCopyItem = new JMenuItem("Copy selected");
/**
* The browse dialog that pops up when the browse button is clicked.
*/
private JFileChooser pathChooser = new JFileChooser();
/**
* The field where the user can enter a path.
*/
private JTextField pathField = new JTextField(30);
/**
* The label for path input field.
*/
private JLabel pathInputLabel = new JLabel("Include/exclude a directory or a file:");
/**
* The label for the path list.
*/
private JLabel pathListLabel = new JLabel("Directories to search and ICU4J jar files to check:");
/**
* The panel to hold the input components.
*/
private JPanel pathInputPanel = new JPanel();
/**
* The JList that holds the path model.
*/
private JList pathList = new JList();
/**
* The path model that stores all the paths.
*/
private PathModel pathModel;
/**
* The panel to hold the output components.
*/
private JPanel pathOptionPanel = new JPanel();
/**
* The context menu for extra options.
*/
private JPopupMenu pathPopup = new JPopupMenu();
/**
* A menu item for <code>pathPopup</code> to remove all paths from the path model.
*/
private JMenuItem pathRemoveAllItem = new JMenuItem("Remove All");
/**
* A menu item for <code>pathPopup</code> to remove the selected paths from the path model.
*/
private JMenuItem pathRemoveSelectedItem = new JMenuItem("Remove Selected Items");
/**
* A menu item for <code>pathPopup</code> to begin a search on the selected paths in the path
* model.
*/
private JMenuItem pathSearchAllItem = new JMenuItem("Search All");
/**
* The search button that starts the search on the selected paths (or all the paths if none are
* selected).
*/
private JButton pathSearchAllButton = new JButton("Search All");
/**
* The panel to hold the search components.
*/
private JPanel pathSearchPanel = new JPanel();
/**
* A menu item for <code>pathPopup</code> to begin a search on all paths in the path model.
*/
private JMenuItem pathSearchSelectedItem = new JMenuItem("Search Selected Items");
/**
* The combobox where a user specifies whether to include or to exclude an entered path.
*/
private JComboBox pathSignBox = new JComboBox(new Object[] { "Include", "Exclude" });
/**
* The checkbox where the user can specify whether or not to search subdirectories. Set to true
* by default.
*/
private JCheckBox pathSubdirOption = new JCheckBox("Search Subdirectories", true);
/**
* Preferred starting number of rows in the table.
*/
public static final int PATH_LIST_ROWS_PREFERRED = 5;
/**
* Constructs the path list GUI component.
*
* @param owner
* The GUILoader object that ownes this component.
*/
public PathComponent(final GUILoader owner) {
pathList.setVisibleRowCount(PATH_LIST_ROWS_PREFERRED);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(pathInputPanel);
add(pathListLabel);
add(new JScrollPane(pathList));
add(pathOptionPanel);
add(pathSearchPanel);
JPanel pathInputSubPanel = new JPanel();
pathInputPanel.setLayout(new BoxLayout(pathInputPanel, BoxLayout.Y_AXIS));
pathInputPanel.add(pathInputLabel);
pathInputPanel.add(pathInputSubPanel);
pathInputSubPanel.add(pathSignBox);
pathInputSubPanel.add(pathField);
pathInputSubPanel.add(pathBrowseButton);
pathOptionPanel.add(pathSubdirOption);
pathSearchPanel.add(pathSearchAllButton);
pathChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
pathPopup.add(pathCopyItem);
pathPopup.add(new JSeparator());
pathPopup.add(pathAddAllDrivesItem);
pathPopup.add(pathRemoveSelectedItem);
pathPopup.add(pathRemoveAllItem);
pathPopup.add(new JSeparator());
pathPopup.add(pathSearchSelectedItem);
pathPopup.add(pathSearchAllItem);
pathField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
addFile(new File(pathField.getText().trim()));
pathField.selectAll();
}
});
pathList.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent event) {
checkPopup(event);
}
public void mouseEntered(MouseEvent event) {
checkPopup(event);
}
public void mouseExited(MouseEvent event) {
checkPopup(event);
}
public void mousePressed(MouseEvent event) {
checkPopup(event);
}
public void mouseReleased(MouseEvent event) {
checkPopup(event);
}
private void checkPopup(MouseEvent event) {
if (event.isPopupTrigger())
pathPopup.show((Component) event.getSource(), event.getX(), event.getY());
}
});
pathList.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
int code = event.getKeyCode();
if (code == KeyEvent.VK_DELETE || code == KeyEvent.VK_BACK_SPACE)
pathModel.remove(pathList.getSelectedIndices());
}
});
pathCopyItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String selection = "";
int[] rows = pathList.getSelectedIndices();
for (int i = 0; i < rows.length; i++) {
String includePathString = pathModel.getElementAt(rows[i]).toString();
// get rid of a + or - at the begining of includePathString
// if one exists
if (includePathString.length() > 0
&& (includePathString.charAt(0) == '+' || includePathString.charAt(0) == '-'))
includePathString = includePathString.substring(1);
selection += includePathString + "\n";
}
getToolkit().getSystemClipboard().setContents(new StringSelection(selection), null);
}
});
pathRemoveSelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
pathModel.remove(pathList.getSelectedIndices());
}
});
pathRemoveAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
pathModel.removeAll();
}
});
pathSearchSelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.search(pathList.getSelectedIndices(), pathSubdirOption.isSelected());
}
});
pathSearchAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.searchAll(pathSubdirOption.isSelected());
}
});
pathSearchAllButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.searchAll(pathSubdirOption.isSelected());
}
});
pathAddAllDrivesItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
pathModel.addAllDrives();
}
});
pathBrowseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// set the chooser's intial path to be whatever is in the text
// field
File path = new File(pathField.getText().trim());
if (path.exists())
pathChooser.setSelectedFile(path);
// run the chooser dialog
int returnVal = pathChooser.showOpenDialog(PathComponent.this);
// on an accept, add the path to the model and set the text
// field to it
if (returnVal == JFileChooser.APPROVE_OPTION) {
path = pathChooser.getSelectedFile();
addFile(path);
pathField.setText(path.getPath());
}
}
});
}
/**
* Sets the path model.
*
* @param pathModel
* The path model.
*/
public void setPathModel(PathModel pathModel) {
this.pathModel = pathModel;
pathList.setModel(pathModel);
}
/**
* Sets whether the search button should be enabled.
*
* @param value
* Whether the search button should be enabled.
*/
public void setSearchEnabled(boolean value) {
pathSearchAllButton.setEnabled(value);
}
/**
* Attempts to add a path to the path model.
*
* @param file
* The path to add.
*/
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);
}
/**
* Returns whether the user has specified to include or to exclude the entered path.
*
* @return Whether the user has specified to include or to exclude the entered path.
*/
private boolean isIncluded() {
return ((String) pathSignBox.getSelectedItem()).equals("Include");
}
}

View File

@ -1,328 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.AbstractListModel;
/**
* Represents a list of IncludePaths that is usable by any class that uses AbstractListModels (such
* as a JList in swing). Also contains methods to begin a search on those paths using ICUJarFinder
* and placing the results in a ResultModel, and methods to load a path list from a file.
*/
class PathModel extends AbstractListModel {
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1337;
/**
* The list of paths as IncludePaths.
*/
private List list = new ArrayList();
/**
* The current logger.
*/
private Logger logger;
/**
* The paths file where the paths are stored.
*/
private File pathListFile;
/**
* The filename of the paths file where the paths are stored.
*/
private String pathListFilename;
/**
* Constructs an empty path model.
*
* @param pathFile
* The file to load the path list from.
* @param logger
* The current logger.
*/
public PathModel(Logger logger, File pathFile) {
this.logger = logger;
this.pathListFile = pathFile;
this.pathListFilename = pathFile.getName();
}
/**
* Adds an IncludePath to the path list if it exists and is unique.
*
* @param path
* An existing path.
* @return Whether or not the given IncludePath exists.
*/
public boolean add(IncludePath path) {
remove(path);
if (path.getPath().exists()) {
list.add(path);
int index = list.size() - 1;
fireIntervalAdded(this, index, index);
return true;
}
return false;
}
/**
* Adds a filename to the path list if it is valid and unique. The filename must either be of
* the form (<b>+</b>|<b>-</b>)<i>pathstring</i> and exist, or of the form <b>all</b>. In
* the case of the latter, all drives are added to the path list.
*
* @param includeFilename
* A filename in the form above.
* @return Whether or not <code>includeFilename</code> is both of the form detailed above and
* exists.
*/
public boolean add(String includeFilename) {
if ("all".equalsIgnoreCase(includeFilename)) {
logger
.printlnToScreen("The tool will search all drives for ICU4J jars except any excluded directories specified");
addAllDrives();
return true;
}
return add(new IncludePath(new File(includeFilename.substring(1).trim()), includeFilename
.charAt(0) == '+'));
}
/**
* Adds all drives to the path list.
*/
public void addAllDrives() {
File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++)
add(new IncludePath(roots[i], true));
}
/**
* Returns the path at the element at a particular index of the path list.
*
* @param index
* The index of the element of the path list to return.
* @return The path at the specified index of the path list. Guaranteed to always be an
* IncludePath.
*/
public Object getElementAt(int index) {
return list.get(index);
}
/**
* Returns the size of the path list.
*
* @return The size of the path list.
*/
public int getSize() {
return (list == null) ? 0 : list.size();
}
/**
* Returns an iterator of the path list.
*
* @return An iterator of the path list.
*/
public Iterator iterator() {
return list.iterator();
}
/**
* 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.printlnToBoth("Scanning " + pathListFilename + " file...");
logger.loglnToBoth(pathListFilename + " file contains");
BufferedReader reader = null;
int lineNumber = 0;
String line;
char sign;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(pathListFile),
"UTF-8"), 4 * 1024);
while ((line = reader.readLine()) != null) {
if (line.length() >= 1 && line.charAt(0) == '\ufeff')
line = line.substring(1);
line = line.trim();
lineNumber++;
if (line.length() >= 1 && (sign = line.charAt(0)) != '#') {
if (sign != '+' && sign != '-' && !"all".equalsIgnoreCase(line)) {
String error = "Each path entry must start with a + or - to denote inclusion/exclusion";
pathListError(error, lineNumber);
continue;
}
if (!add(line)) {
String error = line.substring(1).trim()
+ " is not a valid file or directory (perhaps it does not exist?)";
pathListError(error, lineNumber);
continue;
}
logger.printlnToBoth(line);
}
}
logger.printlnToBoth("Scanning " + pathListFilename + " complete.");
} catch (FileNotFoundException ex) {
pathListError("The " + pathListFilename + " file doesn't exist.");
} catch (IOException ex) {
pathListError("Could not read the " + pathListFilename + " file.");
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException ex) {
}
}
}
/**
* Removes a path from the path list. Since there are no duplicates in the path list, this
* method either removes a single path or removes none.
*
* @param path
* The path to remove from the path list.
*/
public void remove(IncludePath path) {
int index = list.indexOf(path);
if (index != -1) {
list.remove(index);
fireIntervalRemoved(this, index, index);
}
}
/**
* Removes a selection of paths from the path list by index.
*
* @param indices
* The indices of the path list to remove.
*/
public void remove(int[] indices) {
if (list.size() > 0 && indices.length > 0) {
Arrays.sort(indices);
int max = indices[indices.length - 1];
int min = indices[0];
for (int i = indices.length - 1; i >= 0; i--)
list.remove(indices[i]);
fireIntervalRemoved(this, min, max);
}
}
/**
* Clears the path list.
*/
public void removeAll() {
if (list.size() > 0) {
int index = list.size() - 1;
list.clear();
fireIntervalRemoved(this, 0, index);
}
}
/**
* Searches a selection of paths in the path list for updatable ICU4J jars. Results are added to
* the result model. The indices provided are the indices of the path list to search.
*
* @param resultModel
* The result model to store the results of the search.
* @param indices
* 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.
* @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;
IncludePath[] paths = new IncludePath[n];
int k = 0;
Iterator iter = iterator();
for (int i = 0; k < n && iter.hasNext(); i++)
if (i == indices[k])
paths[k++] = (IncludePath) iter.next();
else
iter.next();
ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, backupDir);
}
}
/**
* Searches each path in the path list for updatable ICU4J jars. Results are added to the result
* model.
*
* @param resultModel
* 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.
* @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 = iterator();
for (int i = 0; i < n; i++)
paths[i] = (IncludePath) iter.next();
ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, backupDir);
}
}
/**
* Throws an IOException with the specified message.
*
* @param message
* The message to put in the exception.
* @throws IOException
*/
private void pathListError(String message) throws IOException {
throw new IOException("Error in " + pathListFilename + ": " + message);
}
/**
* Logs as an error a specified message and line number.
*
* @param message
* The message to put in the exception.
* @param lineNumber
* The line number to put in the exception.
*/
private void pathListError(String message, int lineNumber) {
logger.printlnToBoth("Error in " + pathListFilename + " (line " + lineNumber + "): "
+ message);
}
}

View File

@ -1,358 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.awt.Component;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.net.URL;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
/**
* The path list GUI component.
*/
public class ResultComponent extends JComponent {
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1341;
/**
* A cancel search button to cancel a search if one is currently occuring.
*/
private JButton resultCancelSearchButton = new JButton("Stop Search");
/**
* A cancel update button to cancel an update if one is currently occuring.
*/
private JButton resultCancelUpdateButton = new JButton("Stop Update");
/**
* The dialog that comes up when the browse button is clicked.
*/
private JFileChooser resultChooser = new JFileChooser();
/**
* A menu item for copying a filename to the clipboard.
*/
private JMenuItem resultCopyItem = new JMenuItem("Copy Selected");
/**
* The model for all the results from a search.
*/
private ResultModel resultModel;
/**
* The panel where option components are shown.
*/
private JPanel resultOptionPanel = new JPanel();
/**
* The context menu that pops up with more options.
*/
private JPopupMenu resultPopup = new JPopupMenu();
/**
* A menu item for <code>pathPopup</code> to remove all files from the result model.
*/
private JMenuItem resultRemoveAllItem = new JMenuItem("Remove All");
/**
* A menu item for <code>pathPopup</code> to remove the selected files from the result model.
*/
private JMenuItem resultRemoveSelectedItem = new JMenuItem("Remove Selected Items");
/**
* The label for the result source list.
*/
private JLabel resultSourceLabel = new JLabel("New Time Zone Version: ");
/**
* The combobox for choosing which timezone resource on the web to use in an update.
*/
private JComboBox resultSourceList = new JComboBox();
/**
* The label for the path list.
*/
private JLabel resultTableLabel = new JLabel("ICU4J Jar Files found:");
/**
* The table where the result model is shown.
*/
private JTable resultTable = new JTable();
/**
* A menu item for <code>pathPopup</code> to update all files in the result model.
*/
private JMenuItem resultUpdateAllItem = new JMenuItem("Update All");
/**
* An update button to update the selected files, or all files if none are selected.
*/
private JButton resultUpdateSelectedButton = new JButton("Update Selected");
/**
* The panel where update components are shown.
*/
private JPanel resultUpdatePanel = new JPanel();
/**
* A menu item for <code>pathPopup</code> to update the selected files in the result model.
*/
private JMenuItem resultUpdateSelectedItem = new JMenuItem("Update Selected Items");
/**
* The model for all the timezone resources on the web.
*/
private SourceModel sourceModel;
/**
* The status bar for status messages.
*/
private JTextArea statusLog = new JTextArea(STATUS_BAR_ROWS_PREFERRED,
STATUS_BAR_COLUMNS_PREFERRED);
/**
* Preferred starting number of rows in the table.
*/
public static final int RESULT_TABLE_ROWS_PREFERRED = 4;
/**
* Preferred starting number of rows in the table.
*/
public static final int STATUS_BAR_ROWS_PREFERRED = 4;
/**
* Preferred starting number of rows in the table.
*/
public static final int STATUS_BAR_COLUMNS_PREFERRED = 48;
/**
* @param owner
* The GUILoader object that ownes this component.
*/
public ResultComponent(final GUILoader owner) {
java.awt.Dimension tableSize = resultTable.getPreferredScrollableViewportSize();
tableSize.height = RESULT_TABLE_ROWS_PREFERRED * resultTable.getRowHeight();
resultTable.setPreferredScrollableViewportSize(tableSize);
statusLog.setEditable(false);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(resultTableLabel);
add(new JScrollPane(resultTable));
add(new JScrollPane(statusLog, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
add(resultOptionPanel);
add(resultUpdatePanel);
resultOptionPanel.add(resultSourceLabel);
resultOptionPanel.add(resultSourceList);
resultUpdatePanel.add(resultCancelSearchButton);
resultUpdatePanel.add(resultUpdateSelectedButton);
resultUpdatePanel.add(resultCancelUpdateButton);
resultChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
resultPopup.add(resultCopyItem);
resultPopup.add(new JSeparator());
resultPopup.add(resultRemoveSelectedItem);
resultPopup.add(resultRemoveAllItem);
resultPopup.add(new JSeparator());
resultPopup.add(resultUpdateSelectedItem);
resultPopup.add(resultUpdateAllItem);
resultTable.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent event) {
checkPopup(event);
}
public void mouseEntered(MouseEvent event) {
checkPopup(event);
}
public void mouseExited(MouseEvent event) {
checkPopup(event);
}
public void mousePressed(MouseEvent event) {
checkPopup(event);
}
public void mouseReleased(MouseEvent event) {
checkPopup(event);
}
private void checkPopup(MouseEvent event) {
if (event.isPopupTrigger())
resultPopup.show((Component) event.getSource(), event.getX(), event.getY());
}
});
resultTable.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
int code = event.getKeyCode();
if (code == KeyEvent.VK_DELETE || code == KeyEvent.VK_BACK_SPACE)
resultModel.remove(resultTable.getSelectedRows());
}
});
resultCopyItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String selection = "";
int[] rows = resultTable.getSelectedRows();
for (int i = 0; i < rows.length; i++)
selection += new File(resultModel.getValueAt(rows[i],
ResultModel.COLUMN_FILE_PATH).toString(), resultModel.getValueAt(
rows[i], ResultModel.COLUMN_FILE_NAME).toString()).toString()
+ "\n";
getToolkit().getSystemClipboard().setContents(new StringSelection(selection), null);
}
});
resultRemoveSelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
resultModel.remove(resultTable.getSelectedRows());
}
});
resultRemoveAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
resultModel.removeAll();
}
});
resultUpdateSelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.update(resultTable.getSelectedRows(), getSelectedSource());
}
});
resultUpdateAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.updateAll(getSelectedSource());
}
});
resultUpdateSelectedButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
int[] indices = resultTable.getSelectedRows();
if (indices.length > 0)
owner.update(indices, getSelectedSource());
}
});
resultCancelSearchButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.cancelSearch();
}
});
resultCancelUpdateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
owner.cancelUpdate();
}
});
}
/**
* Adds the status to the statusbar.
*
* @param status
* The current status.
*/
public void addStatusMessage(String status) {
String text = statusLog.getText();
if (text == null || text.trim().length() == 0)
statusLog.setText(status);
else
statusLog.append("\n" + status);
statusLog.setCaretPosition(statusLog.getText().length());
}
/**
* 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);
}
/**
* 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);
}
/**
* Sets whether the update button should be enabled.
*
* @param value
* Whether the update button should be enabled.
*/
public void setUpdateEnabled(boolean value) {
resultUpdateSelectedButton.setEnabled(value);
}
/**
* 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());
}
}

View File

@ -1,430 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.table.AbstractTableModel;
/**
* Represents a list of ICUFiles that is usable by any class that uses AbstractTableModels (such as
* a JTable in swing). Also contains methods to begin updates on those ICUFiles and methods to load
* and save a result list from and to a file.
*/
class ResultModel extends AbstractTableModel {
/**
* The column designating filenames.
*/
public static final int COLUMN_FILE_NAME = 0;
/**
* The column designating file paths.
*/
public static final int COLUMN_FILE_PATH = 1;
/**
* The column designating ICU versions.
*/
public static final int COLUMN_ICU_VERSION = 2;
/**
* The column designating timezone verisons.
*/
public static final int COLUMN_TZ_VERSION = 3;
/**
* A list of names of the columns in a result model.
*/
public static final String[] COLUMN_NAMES = new String[] { "Filename", "Path", "ICU Version",
"TZ Version" };
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1338;
/**
* The list of ICUFiles represented by this result model.
*/
private List icuFileList = new ArrayList();
/**
* The current logger.
*/
private Logger logger;
/**
* The result list file where results are saved and stored.
*/
private File resultListFile;
/**
* The filename of the result list file where results are saved and stored.
*/
private String resultListFilename;
/**
* 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, File resultFile) {
this.logger = logger;
this.resultListFile = resultFile;
this.resultListFilename = resultFile.getName();
}
/**
* Adds a file to the ICUFile list.
*
* @param file
* The file.
* @return Whether the file was added successfully (which is determined by if it is an updatable
* ICU4J jar).
*/
public boolean add(File file) {
try {
ICUFile icuFile = new ICUFile(file, logger);
add(icuFile);
return true;
} catch (IOException ex) {
return false;
}
}
/**
* Adds a file to the ICUFile list.
*
* @param icuFile
* The file.
*/
public void add(ICUFile icuFile) {
remove(icuFile.getFile());
icuFileList.add(icuFile);
int index = icuFileList.size() - 1;
fireTableRowsInserted(index, index);
}
/**
* Adds a file to the ICUFile list.
*
* @param filename
* The name of the file.
* @return Whether the file was added successfully (which is determined by if it is an updatable
* ICU4J jar).
*/
public boolean add(String filename) {
return add(new File(filename));
}
/**
* Returns the number of columns for each represented ICUFile.
*
* @return The number of columns for each represented ICUFile.
*/
public int getColumnCount() {
return COLUMN_NAMES.length;
}
/**
* Returns the column names as stored in COLUMN_NAMES.
*
* @param col
* The index of the column.
* @return <code>COLUMN_NAMES[col]</code>
*/
public String getColumnName(int col) {
return COLUMN_NAMES[col];
}
/**
* Returns the number of ICUFiles represented.
*
* @return The number of ICUFiles represented.
*/
public int getRowCount() {
return (icuFileList == null) ? 0 : icuFileList.size();
}
/**
* Returns the item at the given row and column. The row determines which ICUFile is used, and
* the column determines which piece of data should be used.
*
* @param row
* Which ICU file to use.
* @param col
* Which piece of data to use. Should be one of the following:
* <ul>
* <li>COLUMN_FILE_PATH</li>
* <li>COLUMN_ICU_VERSION</li>
* <li>COLUMN_TZ_VERSION</li>
* </ul>
* @return The item at the given row and column. Will always be a String.
*/
public Object getValueAt(int row, int col) {
ICUFile icuFile = ((ICUFile) icuFileList.get(row));
switch (col) {
case COLUMN_FILE_NAME:
return icuFile.getFilename();
case COLUMN_FILE_PATH:
return icuFile.getPath();
case COLUMN_ICU_VERSION:
return icuFile.getICUVersion();
case COLUMN_TZ_VERSION:
return icuFile.getTZVersion();
default:
return null;
}
}
/**
* Returns an iterator on the list of ICUFiles.
*
* @return An iterator on the list of ICUFiles.
*/
public Iterator iterator() {
return icuFileList.iterator();
}
/**
* 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 " + resultListFilename + " file...");
logger.printlnToScreen(resultListFilename + " file contains");
BufferedReader reader = null;
int lineNumber = 1;
String line;
int tab;
String filename;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(resultListFile),
"UTF-8"), 4 * 1024);
while ((line = reader.readLine()) != null) {
if (line.length() >= 1 && line.charAt(0) == '\ufeff')
line = line.substring(1);
line = line.trim();
logger.printlnToScreen(line);
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);
}
lineNumber++;
}
} catch (FileNotFoundException ex) {
resultListError("The "
+ resultListFilename
+ " 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 "
+ resultListFilename
+ " file. Please re-run the tool with -Ddiscoveronly=true option to generate the list of ICU4J jars.");
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException ex) {
}
}
}
/**
* Removes a file from the ICUFile list.
*
* @param file
* The file to remove.
*/
public void remove(File file) {
if (icuFileList.size() > 0) {
Iterator iter = iterator();
int i = 0;
while (iter.hasNext()) {
ICUFile icuFile = (ICUFile) iter.next();
if (icuFile.getFile().getAbsoluteFile().equals(file.getAbsoluteFile())) {
icuFileList.remove(icuFile);
fireTableRowsDeleted(i, i);
return;
}
i++;
}
}
}
/**
* Removes a selection of files from the ICUFile list.
*
* @param indices
* The indices of the files to remove.
*/
public void remove(int[] indices) {
if (icuFileList.size() > 0 && indices.length > 0) {
Arrays.sort(indices);
for (int i = indices.length - 1; i >= 0; i--) {
icuFileList.remove(indices[i]);
fireTableRowsDeleted(indices[i], indices[i]);
}
}
}
/**
* Clears the ICUFile list.
*/
public void removeAll() {
if (icuFileList.size() > 0) {
int lastIndex = icuFileList.size() - 1;
icuFileList.clear();
fireTableRowsDeleted(0, lastIndex);
}
}
/**
* 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 " + resultListFilename + " ...");
BufferedWriter writer = null;
ICUFile icuFile = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(resultListFile), "UTF-8"), 4 * 1024);
Iterator iter = iterator();
while (iter.hasNext()) {
icuFile = (ICUFile) iter.next();
String line = icuFile.getFile().getPath() + '\t' + icuFile.getTZVersion();
logger.printlnToScreen(line);
writer.write(line);
}
} catch (FileNotFoundException ex) {
resultListError("Could not create the " + resultListFilename + " file.");
} catch (IOException ex) {
resultListError("Could not write to the " + resultListFilename + " file.");
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException ex) {
}
}
}
/**
* Updates a selection of the ICUFiles given a URL as the source of the update and a backup
* directory as a place to store a copy of the un-updated file.
*
* @param indices
* The indices of the ICUFiles to update.
* @param updateURL
* The URL to use a source of the update.
* @param backupDir
* The directory in which to store backups.
* @throws InterruptedException
*/
public int update(int[] indices, URL updateURL, File backupDir) throws InterruptedException {
int numberFailed = 0;
if (icuFileList.size() > 0 && indices.length > 0) {
Arrays.sort(indices);
int n = indices.length;
int k = 0;
Iterator iter = iterator();
for (int i = 0; k < n && iter.hasNext(); i++)
if (i == indices[k])
try {
// update the file
((ICUFile) iter.next()).update(updateURL, backupDir);
fireTableRowsUpdated(i, i);
k++;
} catch (IOException ex) {
// could not update the jar
logger.errorln(ex.getMessage());
numberFailed++;
}
else
iter.next();
}
return numberFailed;
}
/**
* Updates all of the ICUFiles given a URL as the source of the update and a backup directory as
* a place to store a copy of the un-updated file.
*
* @param updateURL
* The URL to use a source of the update.
* @param backupDir
* The directory in which to store backups.
* @throws InterruptedException
*/
public int updateAll(URL updateURL, File backupDir) throws InterruptedException {
int numberFailed = 0;
if (icuFileList.size() > 0) {
int n = icuFileList.size();
Iterator iter = iterator();
for (int i = 0; i < n; i++)
try {
((ICUFile) iter.next()).update(updateURL, backupDir);
fireTableRowsUpdated(i, i);
} catch (IOException ex) {
// could not update the jar
logger.errorln(ex.getMessage());
numberFailed++;
}
}
return numberFailed;
}
/**
* Throws an IllegalArgumentException with the given message.
*
* @param message
* The message.
* @throws IllegalArgumentException
*/
private void resultListError(String message) throws IOException {
throw new IOException("Error in " + resultListFilename + ": " + message);
}
/**
* Logs as an error a given message and line number.
*
* @param message
* The message.
* @param lineNumber
* The line number.
*/
private void resultListError(String message, int lineNumber) {
logger.errorln("Error in " + resultListFilename + " (line " + lineNumber + "): " + message);
}
}

View File

@ -1,304 +0,0 @@
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.TreeMap;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
/**
* Represents a map of timezone version names to urls where they can be found that is usable by any
* class that uses AbstractListModels (such as a JList or JCombobox in swing). Also contains methods
* to begin a search for sources on the ICU Timezone Repository.
*/
class SourceModel extends AbstractListModel implements ComboBoxModel {
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1339;
/**
* The URL of the ICU Timezone Repository. In order to catch a MalformedURLException, this field
* must be initialized by the constructor.
*/
public static URL TZ_BASE_URL = null;
/**
* The end of a URL string to any timezone resource in the ICU Timezone Repository meant for
* ICU4J.
*/
public static final String TZ_BASE_URLSTRING_END = "/be/zoneinfo.res";
/**
* The URL string of the ICU Timezone Repository.
*/
public static final String TZ_BASE_URLSTRING_START = "http://icu-project.org/tzdata/";
/**
* The readable name of the local timezone resource file, ie. "Local Copy" or "Local Copy
* (2007c)". Since the version is determined by a <code>ICUFile.findFileTZVersion</code>,
* this field must be initialized by the constructor.
*/
public static String TZ_LOCAL_CHOICE = null;
/**
* The URL of the local timezone resource file. In order to catch a MalformedURLException, this
* field must be initialized by the constructor.
*/
public static URL TZ_LOCAL_URL = null;
/**
* The version of the local timezone resource file, ie. "2007c". Since the version is determined
* by a <code>ICUFile.findFileTZVersion</code>, this field must be initialized by the
* constructor.
*/
public static String TZ_LOCAL_VERSION = null;
/**
* The local timezone resource file.
*/
public static File tzLocalFile = null;
/**
* The current logger.
*/
private Logger logger;
/**
* The currently selected timezone resource name. Initially set to <code>TZ_LOCAL_CHOICE</code>.
*/
private Object selected = TZ_LOCAL_CHOICE;
/**
* The map of timezone resource names to their respective URL locations.
*/
private TreeMap urlMap = new TreeMap();
/**
* Constructs a source model.
*
* @param logger
* The current logger.
* @param tzLocalFile
* The local timezone resource file.
*/
public SourceModel(Logger logger, File tzLocalFile) {
this.logger = logger;
// if all constants are not yet initialized
// (this is where they get initialized)
if (TZ_BASE_URL == null) {
try {
TZ_BASE_URL = new URL(TZ_BASE_URLSTRING_START);
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 (perhaps you are not running icutzu from the correct directory?)");
} else {
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");
TZ_LOCAL_CHOICE = "Local Copy";
} else {
TZ_LOCAL_CHOICE = "Local Copy (" + TZ_LOCAL_VERSION + ")";
}
selected = TZ_LOCAL_CHOICE;
}
} catch (MalformedURLException ex) {
// this shouldn't happen
logger.errorln("Internal program error.");
ex.printStackTrace();
}
}
}
/**
* Gathers all the names and urls of timezone resources available on the ICU Timezone
* Repository. Also sets the selected item in this list to be the best timezone version
* available.
*/
public void findSources() {
BufferedReader reader = null;
try {
URLConnection con = TZ_BASE_URL.openConnection();
con.setRequestProperty("user-agent", System.getProperty("http.agent"));
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
// create an html callback function to parse through every list item
// (every list item
HTMLEditorKit.ParserCallback htmlCallback = new HTMLEditorKit.ParserCallback() {
private boolean listItem = false;
public void handleEndTag(HTML.Tag tag, int pos) {
if (tag == HTML.Tag.LI)
listItem = false;
}
public void handleStartTag(HTML.Tag tag, MutableAttributeSet attr, int pos) {
if (tag == HTML.Tag.LI)
listItem = true;
}
public void handleText(char[] data, int pos) {
if (listItem) {
String str = new String(data);
if (str.charAt(str.length() - 1) == '/')
str = str.substring(0, str.length() - 1);
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));
// update the selected item and fire off an
// event
selected = urlMap.lastKey();
int index = 0;
for (Iterator iter = urlMap.keySet().iterator(); iter.hasNext();) {
if (iter.next().equals(str))
index++;
}
fireIntervalAdded(this, index, index);
} catch (MalformedURLException ex) {
logger.errorln("Internal program error.");
ex.printStackTrace();
}
}
}
};
new ParserDelegator().parse(reader, htmlCallback, false);
} catch (IOException ex) {
// 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)
try {
reader.close();
} catch (IOException ex) {
}
}
}
/**
* Returns the name of the timezone resource at the given index.
*
* @param index
* The given index.
* @return The name of the timezone resource at the given index.
*/
public Object getElementAt(int index) {
if (index == 0)
return TZ_LOCAL_CHOICE;
else if (index < 0 || index > urlMap.size())
return null;
else {
Iterator iter = urlMap.keySet().iterator();
for (int i = 1; i < index; i++)
iter.next();
return iter.next();
}
}
/**
* Returns the selected timezone resource name. If <code>setSelectedItem</code> is never
* called externally, then this is also the best available timezone resource (the most recent
* version).
*
* @return The selected timezone resource name.
*/
public Object getSelectedItem() {
return selected;
}
/**
* Gets the number of timezone resources currently stored by the source model. There will always
* be at least one.
*
* @return The number of timezone resources.
*/
public int getSize() {
// the added size (+1) is due to the local copy not being inside the map
return urlMap.size() + 1;
}
/**
* Returns the URL mapped to by the given timezone resource name.
*
* @param choice
* The version name, which should be a String.
* @return The URL mapped to by the given timezone resource name.
*/
public URL getURL(Object choice) {
if (choice == null || !(choice instanceof String))
return null;
else if (TZ_LOCAL_CHOICE.equalsIgnoreCase((String) choice))
return TZ_LOCAL_URL;
else
return (URL) urlMap.get(choice);
}
/**
* Returns the version of a timezone resource with the given name. Usually this is exactly the
* same as the name, but if the name is <code>TZ_LOCAL_CHOICE</code> (ignoring case), then the
* version is <code>TZ_LOCAL_VERSION</code>.
*
* @param choice
* The version name, which should be a String.
* @return The URL mapped to by the given version name.
*/
public String getVersion(Object choice) {
if (choice == null || !(choice instanceof String))
return null;
else if (TZ_LOCAL_CHOICE.equalsIgnoreCase((String) choice))
return TZ_LOCAL_VERSION;
else
return (String) choice;
}
/**
* Returns an iterator on the entry set of the url map. Each item iterated will be of type
* Map.Entry, whos key is a String and value is a URL.
*
* @return An iterator as described above.
*/
public Iterator iterator() {
return urlMap.entrySet().iterator();
}
/**
* Sets the selected timezone resource name.
*
* @param selected
* The timezone resource name to be selected.
*/
public void setSelectedItem(Object selected) {
this.selected = selected;
}
}