ICU-7584 Merging the changes done for #4511 into ICU4J 3.2 maintenance branch.

X-SVN-Rev: 27889
diff --git a/build.xml b/build.xml
index faf298f..ab66669 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,7 @@
 <!--
 /*
 *******************************************************************************
-* Copyright (C) 1997-2004, International Business Machines Corporation and    *
+* Copyright (C) 1997-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 * This is the ant build file for ICU4J.  See readme.html for more information.
@@ -231,6 +231,21 @@
             debug="on" deprecation="off"/>
     </target>
 
+    <target name="indices" depends="icudata,tools">
+        <java classname="com.ibm.icu.dev.tool.index.IndexGenerator" classpath="${build.dir}" logError="true">
+            <arg value="${build.dir}/com/ibm/icu/impl/data/icudt32b/" />
+        </java>
+        <java classname="com.ibm.icu.dev.tool.index.IndexGenerator" classpath="${build.dir}" logError="true">
+            <arg value="${build.dir}/com/ibm/icu/impl/data/icudt32b/rbnf" />
+        </java>
+        <java classname="com.ibm.icu.dev.tool.index.IndexGenerator" classpath="${build.dir}" logError="true">
+            <arg value="${build.dir}/com/ibm/icu/impl/data/icudt32b/coll" />
+        </java>
+        <java classname="com.ibm.icu.dev.tool.index.IndexGenerator" classpath="${build.dir}" logError="true">
+            <arg value="${build.dir}/com/ibm/icu/impl/data/icudt32b/translit" />
+        </java>
+    </target>
+
     <target name="one4tools" depends="anthack1,anthack2" if="version.1.4">
         <javac includes="com/ibm/icu/dev/tool/cldr/*.java,com/ibm/icu/dev/localeconverter/docs/*.java,com/ibm/icu/dev/tool/docs/*.java"
             excludes="**/CVS/**/*"
@@ -340,7 +355,7 @@
     <!-- Creates the 3 release jar archives for distribution -->
     <target name="jarRelease" depends="jar,jarSrc,jarDocs"/>
 
-    <target name="jar" depends="core" description="build full 'icu4j.jar' jar file">
+    <target name="jar" depends="core,indices" description="build full 'icu4j.jar' jar file">
         <jar jarfile="${jar.file}"
             compress="true"
             includes="com/ibm/icu/util/**/*,com/ibm/icu/text/**/*,com/ibm/icu/math/**/*,com/ibm/icu/impl/**/*,com/ibm/icu/lang/**/*"
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
index c5a19cc..f69b72a 100755
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2000-2004, International Business Machines Corporation and    *
+ * Copyright (C) 2000-2010, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -835,7 +835,7 @@
 
     public void TestStepwise()
     {
-        findBoundariesStepwise(1997, ONE_DAY, safeGetTimeZone("EST"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, safeGetTimeZone("EST"), 0);
         // disabled Oct 2003 aliu; ACT could mean anything, depending on the underlying JDK, as of 2.8
         // findBoundariesStepwise(1997, ONE_DAY, safeGetTimeZone("ACT"), 2);
         findBoundariesStepwise(1997, ONE_DAY, safeGetTimeZone("America/Phoenix"), 0); // Added 3Jan01
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
index 1a1609a..a784031 100755
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2000-2004, International Business Machines Corporation and    *
+ * Copyright (C) 2000-2010, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -99,13 +99,13 @@
             new ZoneDescriptor("AST", -540, true),
             new ZoneDescriptor("PST", -480, true),
             new ZoneDescriptor("PNT", -420, false),
-            new ZoneDescriptor("MST", -420, true),
+            new ZoneDescriptor("MST", -420, false),
             new ZoneDescriptor("CST", -360, true),
-            new ZoneDescriptor("IET", -300, false),
-            new ZoneDescriptor("EST", -300, true),
+            new ZoneDescriptor("IET", -300, true),
+            new ZoneDescriptor("EST", -300, false),
             new ZoneDescriptor("PRT", -240, false),
             new ZoneDescriptor("CNT", -210, true),
-            new ZoneDescriptor("AGT", -180, false),
+            new ZoneDescriptor("AGT", -180, true),
             new ZoneDescriptor("BET", -180, true),
             // new ZoneDescriptor("CAT", -60, false), // Wrong:
             // As of bug 4130885, fix CAT (Central Africa)
diff --git a/src/com/ibm/icu/dev/tool/index/IndexGenerator.java b/src/com/ibm/icu/dev/tool/index/IndexGenerator.java
new file mode 100644
index 0000000..5e02295
--- /dev/null
+++ b/src/com/ibm/icu/dev/tool/index/IndexGenerator.java
@@ -0,0 +1,80 @@
+/**
+*******************************************************************************
+* Copyright (C) 2005-2010, International Business Machines Corporation and    *
+* others. All Rights Reserved.                                                *
+*******************************************************************************
+*/
+package com.ibm.icu.dev.tool.index;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class IndexGenerator {
+    
+    private final static String stoplist = ",char.res,CurrencyData.res,invuca.res,line.res,line_th.res,pnames.res,res_index.res,sent.res,title.res,ucadata.res,ucase.res,uidna.res,unames.res,unorm.res,uprops.res,word.res,word_ja.res,word_POSIX.res,word_th.res";
+
+    public static void main(String[] args) {
+	if (args.length < 1) {
+	    usage("too few arguments");
+	}
+
+	File inDir = new File(args[0]);
+	if (!inDir.isDirectory() || !inDir.exists()) {
+	    usage("first argument '" + inDir + "' must be existing directory");
+	}
+
+	File outDir = inDir;
+	if (args.length > 1) {
+	    outDir = new File(args[1]);
+	    if (!outDir.isDirectory() || !outDir.exists()) {
+		usage("second argument must be existing directory");
+	    }
+	}
+	    
+	DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US);
+	DateFormat copyfmt = new SimpleDateFormat("'# Copyright (C) 'yyyy' IBM Inc.  All Rights Reserved.'");
+
+	try {
+	    File outFile = new File(outDir, "res_index.txt");
+	    PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
+	    Date now = new Date();
+	    pw.println("# Generated by " + IndexGenerator.class.getName() + " on " + fmt.format(now));
+	    pw.println("# from contents of " + inDir.getCanonicalPath());
+	    pw.println(copyfmt.format(now));
+	    File[] files = inDir.listFiles();
+	    int count = 0;
+	    if (files != null) {
+		for (int i = 0; i < files.length; i++){
+		    if (!files[i].isDirectory()) {
+			String name = "," + files[i].getName(); // add ',' to get exact match
+			if (name.endsWith(".res") && stoplist.indexOf(name) == -1) {
+			    pw.println(name.substring(1, name.lastIndexOf('.'))); // 1 to trim off ','
+			    ++count;
+			}
+		    }
+		}
+	    }
+	    pw.println("# Found " + count + " files");
+	    pw.println("# End of file");
+	    if (count == 0) {
+		System.err.println("Warning: matched no files");
+	    } 
+	    pw.close();
+	}
+	catch (IOException e) {
+	    usage(e.getMessage());
+	}
+    }
+
+    private static void usage(String msg) {
+	if (msg != null) {
+	    System.err.println("Error: " + msg);
+	}
+	System.out.println("Usage: IndexGenerator inDir outDir");
+	System.out.println("  inDir is an existing directory whose locale-based resources are to be enumerated");
+	System.out.println("  outDir is an existing directory in which the res_index.txt file will be placed");
+	throw new InternalError("Usage");
+    }
+}
+	
diff --git a/src/com/ibm/icu/impl/ICUResourceBundle.java b/src/com/ibm/icu/impl/ICUResourceBundle.java
index 420425d..fc4bb4e 100644
--- a/src/com/ibm/icu/impl/ICUResourceBundle.java
+++ b/src/com/ibm/icu/impl/ICUResourceBundle.java
@@ -1,13 +1,17 @@
 /*
 ******************************************************************************
-* Copyright (C) 2004, International Business Machines Corporation and        *
+* Copyright (C) 2004-2010, International Business Machines Corporation and   *
 * others. All Rights Reserved.                                               *
 ******************************************************************************
 */
 
 package com.ibm.icu.impl;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
 import java.lang.ref.SoftReference;
 import java.net.JarURLConnection;
 import java.net.URL;
@@ -26,6 +30,9 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
+import java.util.regex.Pattern;
+
+import com.ibm.icu.impl.URLHandler.URLVisitor;
 import com.ibm.icu.util.StringTokenizer;
 import com.ibm.icu.util.ULocale;
 import com.ibm.icu.util.UResourceBundle;
@@ -842,68 +849,55 @@
         return locales;
     }
 
-    private static final ArrayList createFullLocaleNameArray(final String baseName, final ClassLoader root){
-        final ArrayList list = new ArrayList();
+    private static final ArrayList createFullLocaleNameArray(
+            final String baseName, final ClassLoader root) {
 
-        java.security.AccessController.
-            doPrivileged(new java.security.PrivilegedAction() {
-                    public Object run() {
-                        URL url = root.getResource(baseName);
+        ArrayList list = (ArrayList) java.security.AccessController
+            .doPrivileged(new java.security.PrivilegedAction() {
+                public Object run() {
+                    // WebSphere class loader will return null for a raw
+                    // directory name without trailing slash
+                    String bn = baseName.endsWith("/")
+                        ? baseName
+                        : baseName + "/";
 
-                        if (!url.getProtocol().equalsIgnoreCase("jar")) {
-                            // assume a file
-                            File file = new File(url.getPath());
-                            File[] files = file.listFiles();
-                            if (files != null) {
-                                // then it's a directory...
-                                for (int i = 0; i < files.length; i++){
-                                    if (!files[i].isDirectory()) {
-                                        String name = files[i].getName();
-                                        if (name.indexOf("res_index") < 0) {
-                                            name = name.substring(0, name.lastIndexOf('.'));
-                                            list.add(name);
-                                        }
-                                    }
-                                }
-                            } else {
-                                // we failed to recognize the url!
-                            }
-                        } else {
-                            // otherwise its a jar file...
-                            try {
-                                String fileName = url.getPath();
-                                int ix = fileName.indexOf("!/");
-                                if (ix >= 0) {
-                                    fileName = fileName.substring(ix + 2); // truncate after "!/"
-                                }
-                                JarURLConnection conn = (JarURLConnection)url.openConnection();
-                                JarFile jarFile = conn.getJarFile();
-                                Enumeration entries = jarFile.entries();
-                                while (entries.hasMoreElements()) {
-                                    JarEntry entry = (JarEntry)entries.nextElement();
-                                    if (!entry.isDirectory()) {
-                                        String name = entry.getName();
-                                        if (name.startsWith(fileName)) {
-                                            name = name.substring(fileName.length() + 1);
-                                            if (name.indexOf('/') == -1 && name.endsWith(".res")) {
-                                                name = name.substring(0, name.lastIndexOf('.'));
-                                                list.add(name);
-                                            }
-                                        }
-                                    }
+                    // look for prebuilt indices first
+                    try {
+                        InputStream s = root.getResourceAsStream(bn + ICU_RESOURCE_INDEX + ".txt");
+                        if (s != null) {
+                            ArrayList list = new ArrayList();
+                            BufferedReader br = new BufferedReader(new InputStreamReader(s, "ASCII"));
+                            String line;
+                            while ((line = br.readLine()) != null) {
+                                if (line.length() != 0 && !line.startsWith("#")) {
+                                    list.add(line);
                                 }
                             }
-                            catch (Exception e) {
-                                if (DEBUG){
-                                    System.out.println("icurb jar error: " + e);
-                                    Thread.dumpStack();
-                                }
-                            }
+                            return list;
                         }
-
-                        return null;
+                    } catch (IOException e) {
+                        // swallow it
                     }
-                });
+
+                    URL url = root.getResource(bn);
+                    URLHandler handler = URLHandler.get(url);
+                    if (handler != null) {
+                        final ArrayList list = new ArrayList();
+                        URLVisitor v = new URLVisitor() {
+                            private Pattern p = Pattern.compile(".*\\.res");
+                            public void visit(String s) {
+                                if (p.matcher(s).matches() && !"res_index.res".equals(s)) {
+                                    list.add(s.substring(0, s.length() - 4)); // strip '.res'
+                                }
+                            }
+                        };
+                        handler.guide(v, false);
+                        return list;
+                    }
+
+                    return null;
+                }
+            });
 
         return list;
     }
diff --git a/src/com/ibm/icu/impl/URLHandler.java b/src/com/ibm/icu/impl/URLHandler.java
new file mode 100644
index 0000000..0a3d21c
--- /dev/null
+++ b/src/com/ibm/icu/impl/URLHandler.java
@@ -0,0 +1,205 @@
+/*
+******************************************************************************
+* Copyright (C) 2005-2010, International Business Machines Corporation and   *
+* others. All Rights Reserved.                                               *
+******************************************************************************
+*/
+
+package com.ibm.icu.impl;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public abstract class URLHandler {
+    public static final String PROPNAME = "urlhandler.props";
+
+    private static final Map handlers;
+
+    private static final boolean DEBUG = ICUDebug.enabled("URLHandler");
+
+    static {
+	Map h = null;
+	try {
+	    InputStream is = URLHandler.class.getResourceAsStream(PROPNAME);
+	    if (is == null) {
+		is = ClassLoader.getSystemClassLoader().getResourceAsStream(PROPNAME);
+	    }
+	    if (is != null) {
+		Class[] params = { URL.class };
+		BufferedReader br = new BufferedReader(new InputStreamReader(is));
+		for (String line = br.readLine(); line != null; line = br.readLine()) {
+		    line = line.trim();
+		    if (line.length() == 0 || line.charAt(0) == '#') {
+			continue;
+		    }
+		    int ix = line.indexOf('=');
+		    if (ix == -1) {
+			if (DEBUG) System.err.println("bad urlhandler line: '" + line + "'");
+			break;
+		    }
+		    String key = line.substring(0, ix).trim();
+		    String value = line.substring(ix+1).trim();
+
+		    try {
+			Class cl = Class.forName(value);
+			Method m = cl.getDeclaredMethod("get", params);
+			if (h == null) {
+			    h = new HashMap();
+			}
+			h.put(key, m);
+		    }
+		    catch (ClassNotFoundException e) {
+			if (DEBUG) System.err.println(e);
+		    }
+		    catch(NoSuchMethodException e) {
+			if (DEBUG) System.err.println(e);
+		    }
+		    catch(SecurityException e) {
+			if (DEBUG) System.err.println(e);
+		    }
+		}
+	    }
+	} catch (Throwable t) {
+	    if (DEBUG) System.err.println(t);
+	}
+	handlers = h;
+    }
+
+    public static URLHandler get(URL url) {
+	if (url == null) {
+	    return null;
+	}
+	String protocol = url.getProtocol();
+	if (handlers != null) {
+	    Method m = (Method)handlers.get(protocol);
+	    if (m != null) {
+		try {
+		    URLHandler handler = (URLHandler)m.invoke(null, new Object[] { url });
+		    if (handler != null) {
+			return handler;
+		    }
+		}
+		catch(IllegalAccessException e) {
+		    if (DEBUG) System.err.println(e);
+		}
+		catch(IllegalArgumentException e) {
+		    if (DEBUG) System.err.println(e);
+		}
+		catch(InvocationTargetException e) {
+		    if (DEBUG) System.err.println(e);
+		}
+	    }
+	}
+
+	return getDefault(url);
+    }
+
+    protected static URLHandler getDefault(URL url) {
+	String protocol = url.getProtocol();
+	if (protocol.equals("file")) {
+	    return new FileURLHandler(url);
+	} else if (protocol.equals("jar")) {
+	    return new JarURLHandler(url);
+	} else {
+	    return null;
+	}
+    }
+
+    private static class FileURLHandler extends URLHandler {
+	File file;
+
+	FileURLHandler(URL url) {
+	    file = new File(url.getPath());
+	    if (!file.exists()) {
+		if (DEBUG) System.err.println("file does not exist");
+		throw new IllegalArgumentException();
+	    }
+	}
+
+	public void guide(URLVisitor v, boolean recurse) {
+	    if (file.isDirectory()) {
+		process(v, recurse, file.listFiles());
+	    } else {
+		v.visit(file.getName());
+	    }
+	}
+
+	private void process(URLVisitor v, boolean recurse, File[] files) {
+	    for (int i = 0; i < files.length; i++) {
+		File f = files[i];
+		if (f.isDirectory()) {
+		    if (recurse) {
+			process(v, recurse, f.listFiles());
+		    }
+		} else {
+		    v.visit(f.getName());
+		}
+	    }
+	}
+    }
+
+    private static class JarURLHandler extends URLHandler {
+	JarFile jarFile;
+	String prefix;
+
+	JarURLHandler(URL url) {
+	    try {
+		prefix = url.getPath();
+		int ix = prefix.indexOf("!/");
+		if (ix >= 0) {
+		    prefix = prefix.substring(ix + 2); // truncate after "!/"
+		}
+		JarURLConnection conn = (JarURLConnection)url.openConnection();
+		jarFile = conn.getJarFile();
+	    }
+	    catch (Exception e) {
+		if (DEBUG) System.err.println("icurb jar error: " + e);
+		throw new IllegalArgumentException("jar error: " + e.getMessage());
+	    }
+	}
+
+	public void guide(URLVisitor v, boolean recurse) {
+	    try {
+		Enumeration entries = jarFile.entries();
+		while (entries.hasMoreElements()) {
+		    JarEntry entry = (JarEntry)entries.nextElement();
+		    if (!entry.isDirectory()) { // skip just directory paths
+			String name = entry.getName();
+			if (name.startsWith(prefix)) {
+			    name = name.substring(prefix.length());
+			    int ix = name.lastIndexOf('/');
+			    if (ix != -1) {
+				if (!recurse) {
+				    continue;
+				}
+				name = name.substring(ix+1);
+			    }
+			    v.visit(name);
+			}
+		    }
+		}
+	    }
+	    catch (Exception e) {
+		if (DEBUG) System.err.println("icurb jar error: " + e);
+	    }
+	}
+    }
+
+    public abstract void guide(URLVisitor visitor, boolean recurse);
+
+    public interface URLVisitor {
+	void visit(String str);
+    }
+}
+
diff --git a/src/com/ibm/icu/manifest.module.stub b/src/com/ibm/icu/manifest.module.stub
index a065463..5a5d92c 100644
--- a/src/com/ibm/icu/manifest.module.stub
+++ b/src/com/ibm/icu/manifest.module.stub
@@ -5,10 +5,10 @@
 Specification-Version: 3.2
 Specification-Vendor: ICU
 Implementation-Title: Modularized ICU for Java
-Implementation-Version: 3.2.0
+Implementation-Version: 3.2.0.1
 Implementation-Vendor: IBM Corporation
 Implementation-Vendor-Id: com.ibm
-Copyright-Info: Copyright (c) 2000-2004, International Business Machines Corporation and others.  All Rights Reserved.
+Copyright-Info: Copyright (c) 2000-2010, International Business Machines Corporation and others.  All Rights Reserved.
 Sealed: false
 
 
diff --git a/src/com/ibm/icu/manifest.stub b/src/com/ibm/icu/manifest.stub
index 923982a..d7d1f2e 100644
--- a/src/com/ibm/icu/manifest.stub
+++ b/src/com/ibm/icu/manifest.stub
@@ -5,8 +5,8 @@
 Specification-Version: 3.2
 Specification-Vendor: ICU
 Implementation-Title: ICU for Java
-Implementation-Version: 3.2.0
+Implementation-Version: 3.2.0.1
 Implementation-Vendor: IBM Corporation
 Implementation-Vendor-Id: com.ibm
-Copyright-Info: Copyright (c) 2000-2004, International Business Machines Corporation and others.  All Rights Reserved.
+Copyright-Info: Copyright (c) 2000-2010, International Business Machines Corporation and others.  All Rights Reserved.
 Sealed: false