ICU-4907 modifications for eclipse/1.3/foundation compatibility

X-SVN-Rev: 18926
This commit is contained in:
Doug Felt 2005-12-24 00:58:51 +00:00
parent a435304124
commit e55c681e6a

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2004, International Business Machines Corporation and *
* Copyright (C) 2005, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -23,50 +23,274 @@ import java.util.*;
public class ICUJDKCompare {
static final boolean DEBUG = false;
static final Class[] pairClasses = {
com.ibm.icu.lang.UCharacter.class, java.lang.Character.class,
com.ibm.icu.lang.UCharacter.UnicodeBlock.class, java.lang.Character.UnicodeBlock.class,
com.ibm.icu.text.BreakIterator.class, java.text.BreakIterator.class,
com.ibm.icu.text.Collator.class, java.text.Collator.class,
com.ibm.icu.text.DateFormat.class, java.text.DateFormat.class,
com.ibm.icu.text.DateFormatSymbols.class, java.text.DateFormatSymbols.class,
com.ibm.icu.text.DecimalFormat.class, java.text.DecimalFormat.class,
com.ibm.icu.text.DecimalFormatSymbols.class, java.text.DecimalFormatSymbols.class,
com.ibm.icu.text.UFormat.class, java.text.Format.class,
com.ibm.icu.text.MessageFormat.class, java.text.MessageFormat.class,
com.ibm.icu.text.NumberFormat.class, java.text.NumberFormat.class,
com.ibm.icu.text.SimpleDateFormat.class, java.text.SimpleDateFormat.class,
com.ibm.icu.util.Calendar.class, java.util.Calendar.class,
com.ibm.icu.util.Currency.class, java.util.Currency.class,
com.ibm.icu.util.GregorianCalendar.class, java.util.GregorianCalendar.class,
com.ibm.icu.util.SimpleTimeZone.class, java.util.SimpleTimeZone.class,
com.ibm.icu.util.TimeZone.class, java.util.TimeZone.class,
com.ibm.icu.util.ULocale.class, java.util.Locale.class,
com.ibm.icu.util.UResourceBundle.class, java.util.ResourceBundle.class
// set up defaults
private static final String kSrcPrefix = "java.";
private static final String kTrgPrefix = "com.ibm.icu.";
private static final String[] kPairInfo = {
"lang.Character/UCharacter",
"lang.Character$UnicodeBlock/UCharacter$UnicodeBlock",
"text.BreakIterator",
"text.Collator",
"text.DateFormat",
"text.DateFormatSymbols",
"text.DecimalFormat",
"text.DecimalFormatSymbols",
"text.Format/UFormat",
"text.MessageFormat",
"text.NumberFormat",
"text.SimpleDateFormat",
"util.Calendar",
"util.Currency",
"util.GregorianCalendar",
"util.SimpleTimeZone",
"util.TimeZone",
"util.Locale/ULocale",
"util.ResourceBundle/UResourceBundle",
};
static final String[] pairs = new String[pairClasses.length];
static {
for (int i = 0; i < pairs.length; ++i) {
pairs[i] = pairClasses[i].getName();
}
private static final String[] kIgnore = new String[] {
"lang.Character <init> charValue compareTo MAX_VALUE MIN_VALUE TYPE",
"lang.Character$UnicodeBlock SURROGATES_AREA",
"util.Calendar FIELD_COUNT",
"util.GregorianCalendar FIELD_COUNT",
"util.SimpleTimeZone STANDARD_TIME UTC_TIME WALL_TIME",
};
private PrintWriter pw;
private String srcPrefix;
private String trgPrefix;
private Class[] classPairs;
private String[] namePairs;
private String[] ignore;
private boolean swap;
private boolean signature;
// call System.exit with non-zero if there were some missing APIs
public static void main(String[] args) {
System.exit(doMain(args));
}
public static void main(String[] args) {
System.out.println("ICU and Java API Comparison");
System.out.println("ICU Version " + com.ibm.icu.util.VersionInfo.ICU_VERSION);
System.out.println("JDK Version " + System.getProperty("java.version"));
// return non-zero if there were some missing APIs
public static int doMain(String[] args) {
ICUJDKCompare p = new ICUJDKCompare();
p.setOutputWriter(new PrintWriter(System.out));
p.setup(args);
return p.process();
}
for (int i = 0; i < pairs.length; i += 2) {
try {
compare(pairClasses[i], pairClasses[i+1]);
}
catch (Exception e) {
System.out.println("exception: " + e);
System.out.println("between " + pairs[i] + " and " + pairs[i+1]);
e.printStackTrace();
// setters
public ICUJDKCompare setOutputWriter(PrintWriter pw) {
this.pw = pw;
return this;
}
public ICUJDKCompare setSrcPrefix(String srcPrefix) {
this.srcPrefix = srcPrefix;
return this;
}
public ICUJDKCompare setTrgPrefix(String trgPrefix) {
this.trgPrefix = trgPrefix;
return this;
}
public ICUJDKCompare setClassPairs(Class[] classPairs) {
this.classPairs = classPairs;
return this;
}
public ICUJDKCompare setNamePairs(String[] namePairs) {
this.namePairs = namePairs;
return this;
}
public ICUJDKCompare setIgnore(String[] ignore) {
this.ignore = ignore;
return this;
}
public ICUJDKCompare setSwap(boolean swap) {
this.swap = swap;
return this;
}
public ICUJDKCompare setup(String[] args) {
String namelist = null;
String ignorelist = null;
for (int i = 0; i < args.length; ++i) {
String arg = args[i];
if (arg.equals("-swap")) {
swap = true;
} else if (arg.equals("-srcPrefix:")) {
srcPrefix = args[++i];
if (!srcPrefix.endsWith(".")) {
srcPrefix += '.';
}
} else if (arg.equals("-trgPrefix:")) {
trgPrefix = args[++i];
if (!trgPrefix.endsWith(".")) {
trgPrefix += '.';
}
} else if (arg.equals("-names:")) {
namelist = args[++i];
} else if (arg.equals("-ignore:")) {
ignorelist = args[++i];
} else {
System.err.println("unrecognized argument: " + arg);
throw new InternalError();
}
}
if (ignorelist != null) {
if (ignorelist.charAt(0) == '@') { // a file containing ignoreinfo
try {
ArrayList nl = new ArrayList();
File f = new File(namelist.substring(1));
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line = null;
while (null != (line = br.readLine())) {
nl.add(line);
}
ignore = (String[])nl.toArray(new String[nl.size()]);
}
catch (Exception e) {
System.err.println(e);
throw new InternalError();
}
} else { // a list of ignoreinfo separated by semicolons
ignore = ignorelist.split("\\s*;\\s*");
}
}
if (namelist != null) {
String[] names = null;
if (namelist.charAt(0) == '@') { // a file
try {
ArrayList nl = new ArrayList();
File f = new File(namelist.substring(1));
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line = null;
while (null != (line = br.readLine())) {
nl.add(line);
}
names = (String[])nl.toArray(new String[nl.size()]);
}
catch (Exception e) {
System.err.println(e);
throw new InternalError();
}
} else { // a list of names separated by semicolons
names = namelist.split("\\s*;\\s*");
}
processPairInfo(names);
}
return this;
}
private void processPairInfo(String[] names) {
ArrayList cl = new ArrayList();
ArrayList nl = new ArrayList();
for (int i = 0; i < names.length; ++i) {
String name = names[i];
String srcName = srcPrefix;
String trgName = trgPrefix;
int n = name.indexOf('/');
if (n == -1) {
srcName += name;
trgName += name;
} else {
String srcSuffix = name.substring(0, n).trim();
String trgSuffix = name.substring(n+1).trim();
int jx = srcSuffix.length()+1;
int ix = trgSuffix.length()+1;
while (ix != -1) {
jx = srcSuffix.lastIndexOf('.', jx-1);
ix = trgSuffix.lastIndexOf('.', ix-1);
}
srcName += srcSuffix;
trgName += srcSuffix.substring(0, jx+1) + trgSuffix;
}
try {
Class jc = Class.forName(srcName);
Class ic = Class.forName(trgName);
cl.add(ic);
cl.add(jc);
nl.add(ic.getName());
nl.add(jc.getName());
}
catch (Exception e) {
if (false) System.err.println("can't load class: " + e.getMessage());
}
}
classPairs = (Class[])cl.toArray(new Class[cl.size()]);
namePairs = (String[])nl.toArray(new String[nl.size()]);
}
private void println(String s) {
if (pw != null) pw.println(s);
}
private void flush() {
if (pw != null) pw.flush();
}
public int process() {
// set defaults
if (srcPrefix == null) {
srcPrefix = kSrcPrefix;
}
if (trgPrefix == null) {
trgPrefix = kTrgPrefix;
}
if (classPairs == null) {
processPairInfo(kPairInfo);
}
if (ignore == null) {
ignore = kIgnore;
}
println("ICU and Java API Comparison");
String ICU_VERSION = "unknown";
try {
Class cls = Class.forName("com.ibm.icu.util.VersionInfo");
Field fld = cls.getField("ICU_VERSION");
ICU_VERSION = fld.get(null).toString();
}
catch (Exception e) {
if (DEBUG) System.err.println("can't get VersionInfo: " + e.getMessage());
}
println("ICU Version " + ICU_VERSION);
println("JDK Version " + System.getProperty("java.version"));
int errorCount = 0;
for (int i = 0; i < classPairs.length; i += 2) {
try {
if (swap) {
errorCount += compare(classPairs[i+1], classPairs[i]);
} else {
errorCount += compare(classPairs[i], classPairs[i+1]);
}
}
catch (Exception e) {
System.err.println("exception: " + e);
System.err.println("between " + namePairs[i] + " and " + namePairs[i+1]);
e.printStackTrace();
errorCount += 1;
}
}
return errorCount;
}
static class MorC {
@ -96,12 +320,18 @@ public class ICUJDKCompare {
String getName() {
return mref == null ? "<init>" : mref.getName();
}
String getSignature() {
return mref == null ? cref.toString() : mref.toString();
}
}
static void compare(Class class1, Class class2) throws Exception {
private int compare(Class class1, Class class2) throws Exception {
String n1 = class1.getName();
String n2 = class2.getName();
println("\ncompare " + n1 + " <> " + n2);
MorC[] conss1 = getMorCArray(class1.getConstructors());
MorC[] conss2 = getMorCArray(class2.getConstructors());
@ -120,32 +350,35 @@ public class ICUJDKCompare {
Set set1 = getFieldSet(fields1);
Set set2 = getFieldSet(fields2);
PrintWriter pw = new PrintWriter(System.out);
Map diffConss = diffMethodMaps(cmap2, cmap1);
Map diffMeths = diffMethodMaps(map2, map1);
Set diffFields = diffFieldSets(set2, set1);
Map diffConss = diffMethodMaps(cmap2, cmap1);
Map diffMeths = diffMethodMaps(map2, map1);
Set diffFields = diffFieldSets(set2, set1);
diffConss = removeIgnored(n2, diffConss);
diffMeths = removeIgnored(n2, diffMeths);
diffFields = removeIgnored(n2, diffFields);
if (diffConss.size() + diffMeths.size() + diffFields.size() > 0) {
pw.println("\n============\nAPI in " + n2 + " missing from " + n1);
if (diffConss.size() > 0) {
pw.println("\nCONSTRUCTORS");
dumpMethodMap(diffConss, pw);
int result = diffConss.size() + diffMeths.size() + diffFields.size();
if (result > 0 && pw != null) {
pw.println("Public API in " + n2 + " but not in " + n1);
if (diffConss.size() > 0) {
pw.println("CONSTRUCTORS");
dumpMethodMap(diffConss, pw);
}
if (diffMeths.size() > 0) {
pw.println("METHODS");
dumpMethodMap(diffMeths, pw);
}
if (diffFields.size() > 0) {
pw.println("FIELDS");
dumpFieldSet(diffFields, pw);
}
}
if (diffMeths.size() > 0) {
pw.println("\nMETHODS");
dumpMethodMap(diffMeths, pw);
}
if (diffFields.size() > 0) {
pw.println("\nFIELDS");
dumpFieldSet(diffFields, pw);
}
} else {
pw.println("\n" + n1 + " OK");
}
return result;
}
static final class MethodRecord {
final class MethodRecord {
MorC[] overrides;
MethodRecord(MorC m) {
@ -223,7 +456,7 @@ public class ICUJDKCompare {
return result;
}
void msg(MorC t, MorC m, String msg) {
void debugmsg(MorC t, MorC m, String msg) {
StringBuffer buf = new StringBuffer();
buf.append(t.getName());
buf.append(" ");
@ -238,20 +471,20 @@ public class ICUJDKCompare {
boolean handles(MorC t, MorC m) {
// relevant modifiers must match
if ((t.getModifiers() & MOD_MASK) != (m.getModifiers() & MOD_MASK)) {
if (DEBUG) msg(t, m, "modifier mismatch");
if (DEBUG) debugmsg(t, m, "modifier mismatch");
return false;
}
Class tr = pairClassEquivalent(t.getReturnType());
Class mr = pairClassEquivalent(m.getReturnType());
if (!assignableFrom(mr, tr)) { // t return type must be same or narrower than m
if (DEBUG) msg(t, m, "return value mismatch");
if (DEBUG) debugmsg(t, m, "return value mismatch");
return false;
}
Class[] tts = t.getParameterTypes();
Class[] mts = m.getParameterTypes();
if (tts.length != mts.length) {
if (DEBUG) msg(t, m, "param count mismatch");
if (DEBUG) debugmsg(t, m, "param count mismatch");
return false;
}
@ -259,7 +492,7 @@ public class ICUJDKCompare {
Class tc = pairClassEquivalent(tts[i]);
Class mc = pairClassEquivalent(mts[i]);
if (!assignableFrom(tc, mc)) { // m param must be same or narrower than t
if (DEBUG) msg(t, m, "parameter " + i + " mismatch, " +
if (DEBUG) debugmsg(t, m, "parameter " + i + " mismatch, " +
tts[i].getName() + " not assignable from " + mts[i].getName());
return false;
}
@ -272,13 +505,16 @@ public class ICUJDKCompare {
if (mod != 0) {
buf.append(Modifier.toString(mod) + " ");
}
buf.append(m.getReturnType().getName() + " (");
buf.append(nameOf(m.getReturnType()));
buf.append(" ");
buf.append(m.getName());
buf.append("(");
Class[] ptypes = m.getParameterTypes();
for (int j = 0; j < ptypes.length; ++j) {
if (j > 0) {
buf.append(", ");
}
buf.append(ptypes[j].getName());
buf.append(nameOf(ptypes[j]));
}
buf.append(')');
}
@ -298,6 +534,14 @@ public class ICUJDKCompare {
}
}
public static String nameOf(Class c) {
if (c.isArray()) {
return nameOf(c.getComponentType()) + "[]";
}
String name = c.getName();
return name.substring(name.lastIndexOf('.') + 1);
}
static MorC[] getMorCArray(Constructor[] cons) {
MorC[] result = new MorC[cons.length];
for (int i = 0 ; i < cons.length; ++i) {
@ -314,7 +558,7 @@ public class ICUJDKCompare {
return result;
}
static Map getMethodMap(MorC[] meths) {
private Map getMethodMap(MorC[] meths) {
Map result = new TreeMap();
for (int i = 0; i < meths.length; ++i) {
MorC m = meths[i];
@ -330,13 +574,16 @@ public class ICUJDKCompare {
return result;
}
static void dumpMethodMap(Map m, PrintWriter out) {
private void dumpMethodMap(Map m, PrintWriter pw) {
Iterator iter = m.entrySet().iterator();
while (iter.hasNext()) {
MethodRecord mr = (MethodRecord)((Map.Entry)iter.next()).getValue();
out.println(mr);
dumpMethodRecord((MethodRecord)((Map.Entry)iter.next()).getValue());
}
out.flush();
pw.flush();
}
private void dumpMethodRecord(MethodRecord mr) {
pw.println(mr.toString());
}
static Map diffMethodMaps(Map m1, Map m2) {
@ -346,6 +593,87 @@ public class ICUJDKCompare {
return result;
}
private Map removeIgnored(String name, Map m1) {
if (ignore == null) {
return m1;
}
if (name.startsWith(srcPrefix)) {
name = name.substring(srcPrefix.length());
}
name += " "; // to avoid accidental prefix of nested class name
// prune ignore list to relevant items
ArrayList il = null;
for (int i = 0; i < ignore.length; ++i) {
String s = ignore[i];
if (s.startsWith(name)) {
if (il == null) {
il = new ArrayList();
}
il.add(s);
}
}
if (il == null) {
return m1;
}
Map result = new TreeMap(((TreeMap)m1).comparator());
result.putAll(m1);
Iterator iter = result.entrySet().iterator();
loop: while (iter.hasNext()) {
Map.Entry e = (Map.Entry)iter.next();
String key = (String)e.getKey();
for (int i = 0; i < il.size(); ++i) {
String ig = (String)il.get(i);
if (ig.indexOf(" " + key) != 0) {
iter.remove();
continue loop;
}
}
}
return result;
}
private Set removeIgnored(String name, Set s1) {
if (ignore == null) {
return s1;
}
if (name.startsWith(srcPrefix)) {
name = name.substring(srcPrefix.length());
}
name += " "; // to avoid accidental prefix of nested class name
// prune ignore list to relevant items
ArrayList il = null;
for (int i = 0; i < ignore.length; ++i) {
String s = ignore[i];
if (s.startsWith(name)) {
if (il == null) {
il = new ArrayList();
}
il.add(s);
}
}
if (il == null) {
return s1;
}
Set result = (Set)((TreeSet)s1).clone();
Iterator iter = result.iterator();
loop: while (iter.hasNext()) {
String key = (String)iter.next();
String fieldname = key.substring(0, key.indexOf(' '));
for (int i = 0; i < il.size(); ++i) {
String ig = (String)il.get(i);
if (ig.indexOf(" " + fieldname) != 0) {
iter.remove();
continue loop;
}
}
}
return result;
}
static final boolean[][] assignmentMap = {
// bool char byte short int long float double void
{ true, false, false, false, false, false, false, false, false }, // boolean
@ -388,17 +716,20 @@ public class ICUJDKCompare {
return lhs.isAssignableFrom(rhs);
}
static String toString(Field f) {
private String toString(Field f) {
StringBuffer buf = new StringBuffer(f.getName());
int mod = f.getModifiers() & MOD_MASK;
if (mod != 0) {
buf.append(" " + Modifier.toString(mod));
}
buf.append(" " + pairEquivalent(f.getType().getName()));
buf.append(" ");
String n = pairEquivalent(f.getType().getName());
n = n.substring(n.lastIndexOf('.') + 1);
buf.append(n);
return buf.toString();
}
static Set getFieldSet(Field[] fs) {
private Set getFieldSet(Field[] fs) {
Set set = new TreeSet();
for (int i = 0; i < fs.length; ++i) {
set.add(toString(fs[i]));
@ -412,7 +743,7 @@ public class ICUJDKCompare {
return result;
}
static void dumpFieldSet(Set s, PrintWriter pw) {
private void dumpFieldSet(Set s, PrintWriter pw) {
Iterator iter = s.iterator();
while (iter.hasNext()) {
pw.println(iter.next());
@ -421,19 +752,26 @@ public class ICUJDKCompare {
}
// given a target string, if it matches the first of one of our pairs, return the second
static String pairEquivalent(String target) {
for (int i = 0; i < pairs.length; i += 2) {
if (target.equals(pairs[i])) {
return pairs[i+1];
// or vice-versa if swap is true
private String pairEquivalent(String target) {
for (int i = 0; i < namePairs.length; i += 2) {
if (swap) {
if (target.equals(namePairs[i+1])) {
return namePairs[i];
}
} else {
if (target.equals(namePairs[i])) {
return namePairs[i+1];
}
}
}
return target;
}
static Class pairClassEquivalent(Class target) {
for (int i = 0; i < pairClasses.length; i += 2) {
if (target.equals(pairClasses[i])) {
return pairClasses[i+1];
private Class pairClassEquivalent(Class target) {
for (int i = 0; i < classPairs.length; i += 2) {
if (target.equals(classPairs[i])) {
return classPairs[i+1];
}
}
return target;