ICU-5533 Merge fixes for #5402 #5536 #5615 into 3.6 maintenance stream

X-SVN-Rev: 21127
This commit is contained in:
Yoshito Umaoka 2007-02-26 20:10:40 +00:00
parent 312fe08bd4
commit 376de16039
19 changed files with 1270 additions and 827 deletions

4
.gitattributes vendored
View file

@ -103,8 +103,12 @@ src/com/ibm/icu/dev/tool/docs/icu4j34.api.gz -text
src/com/ibm/icu/dev/tool/docs/icu4j341.api.gz -text
src/com/ibm/icu/dev/tool/docs/icu4j342.api.gz -text
src/com/ibm/icu/dev/tool/docs/icu4j343.api.gz -text
src/com/ibm/icu/impl/DateNumberFormat.java -text
src/com/ibm/icu/impl/ICUCache.java -text
src/com/ibm/icu/impl/SimpleCache.java -text
src/com/ibm/icu/impl/data/icudata.jar -text
src/com/ibm/icu/impl/data/th.brk -text
src/com/ibm/icu/util/CalendarServiceShim.java -text
src/com/ibm/richtext/textapps/resources/unicode.arabic.red -text
src/com/ibm/richtext/textapps/resources/unicode.hebrew.red -text

View file

@ -1,11 +1,11 @@
#*
#*******************************************************************************
#* Copyright (C) 2006, International Business Machines Corporation and *
#* Copyright (C) 2006-2007, International Business Machines Corporation and *
#* others. All Rights Reserved. *
#*******************************************************************************
#* This is the properties file for ICU4J builds.
#*
icu4j.version.string=3.6
icu4j.version.string=3.6.1
icu4j.version.number=36
current.year=2006
icu4j.previous.version.number=34

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2006, International Business Machines Corporation and *
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -820,5 +820,27 @@ public class BreakIteratorTest extends TestFmwk
expected.add("them?");
generalIteratorTest(lineBreak, expected);
}
/**
* Ticket#5615
*/
public void TestT5615() {
com.ibm.icu.util.ULocale[] ulocales = BreakIterator.getAvailableULocales();
int type = 0;
com.ibm.icu.util.ULocale loc = null;
try {
for (int i = 0; i < ulocales.length; i++) {
loc = ulocales[i];
for (type = 0; type <= 4; ++type) {
BreakIterator brk = BreakIterator.getBreakInstance(loc, type);
if (brk == null) {
errln("ERR: Failed to create an instance type: " + type + " / locale: " + loc);
}
}
}
} catch (Exception e) {
errln("ERR: Failed to create an instance type: " + type + " / locale: " + loc + " / exception: " + e.getMessage());
}
}
}

View file

@ -1,7 +1,7 @@
//##header
/*
*******************************************************************************
* Copyright (C) 1996-2006, International Business Machines Corporation and *
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -10,9 +10,10 @@
package com.ibm.icu.dev.test.serializable;
import java.util.Date;
import java.util.Locale;
import java.util.HashMap;
import java.util.Locale;
import com.ibm.icu.impl.DateNumberFormat;
import com.ibm.icu.text.ChineseDateFormat;
import com.ibm.icu.text.ChineseDateFormatSymbols;
import com.ibm.icu.text.DateFormat;
@ -1391,6 +1392,24 @@ public class FormatTests
}
//#endif
public static class DateNumberFormatHandler implements SerializableTest.Handler
{
public Object[] getTestObjects()
{
Locale locales[] = SerializableTest.getLocales();
DateNumberFormat[] dnfmts = new DateNumberFormat[locales.length];
for (int i = 0; i < locales.length; i++) {
ULocale uloc = ULocale.forLocale(locales[i]);
dnfmts[i] = new DateNumberFormat(uloc);
}
return dnfmts;
}
public boolean hasSameBehavior(Object a, Object b) {
return a.equals(b);
}
}
public static void main(String[] args)
{
// nothing needed...

View file

@ -1,7 +1,7 @@
//##header
/*
*******************************************************************************
* Copyright (C) 1996-2006, International Business Machines Corporation and *
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -436,6 +436,7 @@ public class SerializableTest extends TestFmwk.TestGroup
map.put("com.ibm.icu.text.SimpleDateFormat", new FormatTests.SimpleDateFormatHandler());
map.put("com.ibm.icu.text.ChineseDateFormat", new FormatTests.ChineseDateFormatHandler());
map.put("com.ibm.icu.text.ChineseDateFormatSymbols", new FormatTests.ChineseDateFormatSymbolsHandler());
map.put("com.ibm.icu.impl.DateNumberFormat", new FormatTests.DateNumberFormatHandler());
map.put("com.ibm.icu.util.Calendar", new CalendarTests.CalendarHandler());
map.put("com.ibm.icu.util.BuddhistCalendar", new CalendarTests.BuddhistCalendarHandler());

View file

@ -0,0 +1,213 @@
//##header
/*
*******************************************************************************
* Copyright (C) 2007, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.text.FieldPosition;
import java.text.ParsePosition;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
/*
* NumberFormat implementation dedicated/optimized for DateFormat,
* used by SimpleDateFormat implementation.
*/
public final class DateNumberFormat extends NumberFormat {
private static final long serialVersionUID = -6315692826916346953L;
private char zeroDigit;
private char minusSign;
private boolean positiveOnly = false;
private transient char[] decimalBuf = new char[20]; // 20 digits is good enough to store Long.MAX_VALUE
private static SimpleCache CACHE = new SimpleCache();
private int maxIntDigits;
private int minIntDigits;
public DateNumberFormat(ULocale loc) {
initialize(loc);
}
public DateNumberFormat(char zeroDigit, char minusSign) {
this.zeroDigit = zeroDigit;
this.minusSign = minusSign;
}
private void initialize(ULocale loc) {
char[] elems = (char[])CACHE.get(loc);
if (elems == null) {
// Missed cache
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, loc);
String[] numberElements = rb.getStringArray("NumberElements");
elems = new char[2];
elems[0] = numberElements[4].charAt(0);
elems[1] = numberElements[6].charAt(0);
CACHE.put(loc, elems);
}
zeroDigit = elems[0];
minusSign = elems[1];
}
public void setMaximumIntegerDigits(int newValue) {
maxIntDigits = newValue;
}
public int getMaximumIntegerDigits() {
return maxIntDigits;
}
public void setMinimumIntegerDigits(int newValue) {
minIntDigits = newValue;
}
public int getMinimumIntegerDigits() {
return minIntDigits;
}
/* For supporting SimpleDateFormat.parseInt */
public void setParsePositiveOnly(boolean isPositiveOnly) {
positiveOnly = isPositiveOnly;
}
public char getZeroDigit() {
return zeroDigit;
}
public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("StringBuffer format(double, StringBuffer, FieldPostion) is not implemented");
}
public StringBuffer format(long numberL, StringBuffer toAppendTo,
FieldPosition pos) {
if (numberL < 0) {
// negative
toAppendTo.append(minusSign);
}
// Note: NumberFormat used by DateFormat only uses int numbers.
// Remainder operation on 32bit platform using long is significantly slower
// than int. So, this method casts long number into int.
int number = (int)numberL;
int limit = decimalBuf.length < maxIntDigits ? decimalBuf.length : maxIntDigits;
int index = limit - 1;
while (true) {
decimalBuf[index] = (char)((number % 10) + zeroDigit);
number /= 10;
if (index == 0 || number == 0) {
break;
}
index--;
}
int padding = minIntDigits - (limit - index);
for (; padding > 0; padding--) {
decimalBuf[--index] = zeroDigit;
}
int length = limit - index;
toAppendTo.append(decimalBuf, index, length);
pos.setBeginIndex(0);
if (pos.getField() == NumberFormat.INTEGER_FIELD) {
pos.setEndIndex(length);
} else {
pos.setEndIndex(0);
}
return toAppendTo;
}
public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("StringBuffer format(BigInteger, StringBuffer, FieldPostion) is not implemented");
}
//#ifndef FOUNDATION
public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
}
//#endif
public StringBuffer format(BigDecimal number,
StringBuffer toAppendTo, FieldPosition pos) {
throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
}
/*
* Note: This method only parse integer numbers which can be represented by long
*/
public Number parse(String text, ParsePosition parsePosition) {
long num = 0;
boolean sawNumber = false;
boolean negative = false;
int base = parsePosition.getIndex();
int offset = 0;
for (; base + offset < text.length(); offset++) {
char ch = text.charAt(base + offset);
if (offset == 0 && ch == minusSign) {
if (positiveOnly) {
break;
}
negative = true;
} else {
int digit = ch - zeroDigit;
if (digit < 0 || 9 < digit) {
digit = UCharacter.digit(ch);
}
if (0 <= digit && digit <= 9) {
sawNumber = true;
num = num * 10 + digit;
} else {
break;
}
}
}
Number result = null;
if (sawNumber) {
num = negative ? num * (-1) : num;
result = new Long(num);
parsePosition.setIndex(base + offset);
}
return result;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!super.equals(obj)) {
return false;
}
DateNumberFormat other = (DateNumberFormat)obj;
if (this.maxIntDigits == other.maxIntDigits
&& this.minIntDigits == other.minIntDigits
&& this.zeroDigit == other.zeroDigit
&& this.minusSign == other.minusSign
&& this.positiveOnly == other.positiveOnly) {
return true;
}
return false;
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
// re-allocate the work buffer
decimalBuf = new char[20];
}
}
//eof

View file

@ -0,0 +1,8 @@
package com.ibm.icu.impl;
public interface ICUCache {
public static final Object NULL = new Object();
public void clear();
public void put(Object key, Object value);
public Object get(Object key);
}

View file

@ -1,6 +1,6 @@
/**
*******************************************************************************
* Copyright (C) 2001-2006, International Business Machines Corporation and *
* Copyright (C) 2001-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -265,13 +265,16 @@ public class ICULocaleService extends ICUService {
public String currentDescriptor() {
String result = currentID();
if (result != null) {
result = "/" + result;
if (varstart != -1) {
result += primaryID.substring(varstart);
}
StringBuffer buf = new StringBuffer(); // default capacity 16 is usually good enough
if (kind != KIND_ANY) {
result = prefix() + result;
buf.append(prefix());
}
buf.append('/');
buf.append(result);
if (varstart != -1) {
buf.append(primaryID.substring(varstart, primaryID.length()));
}
result = buf.toString();
}
return result;
}

View file

@ -209,7 +209,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
* Returns a string from a string resource type
*
* @return a string
* @see #getBinary
* @see #getBinary()
* @see #getIntVector
* @see #getInt
* @throws MissingResourceException
@ -227,7 +227,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
throw new UResourceTypeMismatchException("");
}
/**
/*
* Returns a string from a string resource type
* @param key The key whose values needs to be fetched
* @return a string
@ -277,7 +277,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
* Returns a 32 bit integer array from a resource.
*
* @return a pointer to a chunk of unsigned bytes which live in a memory mapped/DLL file.
* @see #getBinary
* @see #getBinary()
* @see #getInt
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
@ -292,7 +292,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
*
* @return an integer value
* @see #getIntVector
* @see #getBinary
* @see #getBinary()
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 2.0
@ -307,7 +307,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
*
* @return an integer value
* @see #getIntVector
* @see #getBinary
* @see #getBinary()
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 2.0
@ -656,8 +656,8 @@ public abstract class ICUResourceBundle extends UResourceBundle {
* accessed, then do: <code>
* UResourceBundle bundle = UResourceBundle.getBundleInstance("de__PHONEBOOK");
* ICUResourceBundle result = null;
* if(bundle instanceof ICUListResourceBundle){
* result = ((ICUListResourceBundle) bundle).getWithFallback("collations/default");
* if(bundle instanceof ICUResourceBundle){
* result = ((ICUResourceBundle) bundle).getWithFallback("collations/default");
* }
* </code>
*
@ -930,7 +930,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
// all. gotta be a better way to do this, since to add a locale you have
// to update this list,
// and it's embedded in our binary resources.
ICUResourceBundle bundle = (ICUResourceBundle) createBundle(baseName, ICU_RESOURCE_INDEX, root);
ICUResourceBundle bundle = (ICUResourceBundle) UResourceBundle.instantiateBundle(baseName, ICU_RESOURCE_INDEX, root, true);
bundle = bundle.get(INSTALLED_LOCALES);
int length = bundle.getSize();
@ -952,7 +952,7 @@ public abstract class ICUResourceBundle extends UResourceBundle {
private static final String[] createLocaleNameArray(String baseName,
ClassLoader root) {
ICUResourceBundle bundle = (ICUResourceBundle) createBundle( baseName, ICU_RESOURCE_INDEX, root);
ICUResourceBundle bundle = (ICUResourceBundle) UResourceBundle.instantiateBundle( baseName, ICU_RESOURCE_INDEX, root, true);
bundle = bundle.get(INSTALLED_LOCALES);
int length = bundle.getSize();
int i = 0;

View file

@ -0,0 +1,40 @@
package com.ibm.icu.impl;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SimpleCache implements ICUCache {
public Object get(Object key) {
SoftReference ref = cacheRef;
if (ref != null) {
Map map = (Map)ref.get();
if (map != null) {
return map.get(key);
}
}
return null;
}
public void put(Object key, Object value) {
SoftReference ref = cacheRef;
Map map = null;
if (ref != null) {
map = (Map)ref.get();
}
if (map == null) {
map = Collections.synchronizedMap(new HashMap());
ref = new SoftReference(map);
cacheRef = ref;
}
map.put(key, value);
}
public void clear() {
cacheRef = null;
}
private SoftReference cacheRef = null;
}

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2002-2006, International Business Machines Corporation and *
* Copyright (C) 2002-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -8,14 +8,12 @@ package com.ibm.icu.text;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICULocaleData;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ICUService;
@ -109,9 +107,9 @@ final class BreakIteratorFactory extends BreakIterator.BreakIteratorServiceShim
private static BreakIterator createBreakInstance(ULocale locale, int kind) {
BreakIterator iter = null;
UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BRKITR_BASE_NAME, locale);
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BRKITR_BASE_NAME, locale);
//
// Get the binary rules. These are needed for both normal RulesBasedBreakIterators
@ -119,9 +117,8 @@ final class BreakIteratorFactory extends BreakIterator.BreakIteratorServiceShim
//
InputStream ruleStream = null;
try {
ResourceBundle boundaries = (ResourceBundle)rb.getObject("boundaries");
String typeKey = KIND_NAMES[kind];
String brkfname = boundaries.getString(typeKey);
String brkfname = rb.getStringWithFallback("boundaries/" + typeKey);
String rulesFileName = ICUResourceBundle.ICU_BUNDLE +ICUResourceBundle.ICU_BRKITR_NAME+ "/" + brkfname;
ruleStream = ICUData.getStream(rulesFileName);
}

View file

@ -51,8 +51,7 @@ public class ChineseDateFormat extends SimpleDateFormat {
* @stable ICU 2.0
*/
public ChineseDateFormat(String pattern, Locale locale) {
// TODO: convert to use ULocale
super(pattern, new ChineseDateFormatSymbols(locale), true);
this(pattern, ULocale.forLocale(locale));
}
/**
@ -63,9 +62,8 @@ public class ChineseDateFormat extends SimpleDateFormat {
* @provisional This API might change or be removed in a future release.
*/
public ChineseDateFormat(String pattern, ULocale locale) {
// TODO: convert CDFS to use ULocale
//super(pattern, new ChineseDateFormatSymbols(locale.toLocale()), true);
super(pattern, new ChineseDateFormatSymbols(locale), locale);
super(pattern, new ChineseDateFormatSymbols(locale),
new ChineseCalendar(TimeZone.getDefault(), locale), locale, true);
}
// NOTE: This API still exists; we just inherit it from SimpleDateFormat

View file

@ -92,4 +92,11 @@ public class ChineseDateFormatSymbols extends DateFormatSymbols {
super.initializeData(loc, calData);
isLeapMonth = calData.getStringArray("isLeapMonth");
}
void initializeData(DateFormatSymbols dfs) {
super.initializeData(dfs);
if (dfs instanceof ChineseDateFormatSymbols) {
this.isLeapMonth = ((ChineseDateFormatSymbols)dfs).isLeapMonth;
}
}
}

View file

@ -1,33 +1,33 @@
/*
*******************************************************************************
* Copyright (C) 1996-2006, International Business Machines Corporation and *
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.text;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.TextTrieMap;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.impl.ZoneMeta;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.impl.SoftCache;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.TextTrieMap;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.ZoneMeta;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
/**
* <code>DateFormatSymbols</code> is a public class for encapsulating
* localizable date-time formatting data, such as the names of the
@ -826,7 +826,6 @@ public class DateFormatSymbols implements Serializable, Cloneable {
{
try {
DateFormatSymbols other = (DateFormatSymbols)super.clone();
copyMembers(this, other);
return other;
} catch (CloneNotSupportedException e) {
///CLOVER:OFF
@ -897,6 +896,10 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* Useful constant for defining timezone offsets.
*/
static final int millisPerHour = 60*60*1000;
// DateFormatSymbols cache
private static ICUCache DFSCACHE = new SimpleCache();
/**
*
* @param desiredLocale
@ -905,10 +908,54 @@ public class DateFormatSymbols implements Serializable, Cloneable {
*/
protected void initializeData(ULocale desiredLocale, String type)
{
CalendarData calData = new CalendarData(desiredLocale, type);
initializeData(desiredLocale, calData);
String key = desiredLocale.toString() + "+" + type;
DateFormatSymbols dfs = (DateFormatSymbols)DFSCACHE.get(key);
if (dfs == null) {
// Initialize data from scratch put a clone of this instance into the cache
CalendarData calData = new CalendarData(desiredLocale, type);
initializeData(desiredLocale, calData);
dfs = (DateFormatSymbols)this.clone();
DFSCACHE.put(key, dfs);
} else {
initializeData(dfs);
}
}
/*
* Initialize format symbols using another instance.
*
* TODO Clean up initialization methods for subclasses
*/
void initializeData(DateFormatSymbols dfs) {
this.eras = dfs.eras;
this.eraNames = dfs.eraNames;
this.narrowEras = dfs.narrowEras;
this.months = dfs.months;
this.shortMonths = dfs.shortMonths;
this.narrowMonths = dfs.narrowMonths;
this.standaloneMonths = dfs.standaloneMonths;
this.standaloneShortMonths = dfs.standaloneShortMonths;
this.standaloneNarrowMonths = dfs.standaloneNarrowMonths;
this.weekdays = dfs.weekdays;
this.shortWeekdays = dfs.shortWeekdays;
this.narrowWeekdays = dfs.narrowWeekdays;
this.standaloneWeekdays = dfs.standaloneWeekdays;
this.standaloneShortWeekdays = dfs.standaloneShortWeekdays;
this.standaloneNarrowWeekdays = dfs.standaloneNarrowWeekdays;
this.ampms = dfs.ampms;
this.shortQuarters = dfs.shortQuarters;
this.quarters = dfs.quarters;
this.standaloneShortQuarters = dfs.standaloneShortQuarters;
this.standaloneQuarters = dfs.standaloneQuarters;
this.zoneStrings = dfs.zoneStrings; // always null at initialization time for now
this.localPatternChars = dfs.localPatternChars;
this.actualLocale = dfs.actualLocale;
this.validLocale = dfs.validLocale;
this.requestedLocale = dfs.requestedLocale;
}
/**
*
* @param desiredLocale
@ -1243,7 +1290,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
/**
* A cache for ZoneItemInfo objects, shared by class instances.
*/
private static SoftCache zoneItemInfoCache = new SoftCache();
private static ICUCache zoneItemInfoCache = new SimpleCache();
/**
* A ZoneItemInfo instance which holds custom timezone strings
@ -1461,7 +1508,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
TIMEZONE_EXEMPLAR_CITY = 6,
TIMEZONE_COUNT = 7;
/**
/*
* Package private: used by SimpleDateFormat
* Gets the index for the given time zone ID to obtain the timezone
* strings for formatting. The time zone ID is just for programmatic
@ -1471,7 +1518,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* the given time zone ID can't be located in the DateFormatSymbols object.
* @see com.ibm.icu.util.SimpleTimeZone
*/
final int getZoneIndex(String ID) {
/* final int getZoneIndex(String ID) {
int result = _getZoneIndex(ID);
if (result >= 0) {
return result;
@ -1490,23 +1537,22 @@ public class DateFormatSymbols implements Serializable, Cloneable {
}
}
return -1;
}
}*/
/**
/*
* Lookup the given ID. Do NOT do an equivalency search.
*/
private int _getZoneIndex(String ID)
/* private int _getZoneIndex(String ID)
{
for (int index=0; index<zoneStrings.length; index++) {
if (ID.equalsIgnoreCase(zoneStrings[index][0])) return index;
}
return -1;
}
}*/
/**
* Clones an array of Strings.
* @param srcArray the source array to be cloned.
* @param count the number of elements in the given source array.
* @return a cloned array.
*/
private final String[] duplicate(String[] srcArray)
@ -1522,36 +1568,6 @@ public class DateFormatSymbols implements Serializable, Cloneable {
return aCopy;
}
/**
* Clones all the data members from the source DateFormatSymbols to
* the target DateFormatSymbols. This is only for subclasses.
* @param src the source DateFormatSymbols.
* @param dst the target DateFormatSymbols.
*/
private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
{
dst.eras = duplicate(src.eras);
dst.eraNames = duplicate(src.eraNames);
dst.months = duplicate(src.months);
dst.shortMonths = duplicate(src.shortMonths);
dst.narrowMonths = duplicate(src.narrowMonths);
dst.standaloneMonths = duplicate(src.standaloneMonths);
dst.standaloneShortMonths = duplicate(src.standaloneShortMonths);
dst.standaloneNarrowMonths = duplicate(src.standaloneNarrowMonths);
dst.weekdays = duplicate(src.weekdays);
dst.shortWeekdays = duplicate(src.shortWeekdays);
dst.narrowWeekdays = duplicate(src.narrowWeekdays);
dst.standaloneWeekdays = duplicate(src.standaloneWeekdays);
dst.standaloneShortWeekdays = duplicate(src.standaloneShortWeekdays);
dst.standaloneNarrowWeekdays = duplicate(src.standaloneNarrowWeekdays);
dst.ampms = duplicate(src.ampms);
if (src.zoneStrings != null) {
dst.zoneStrings = duplicate(src.zoneStrings);
}
dst.requestedLocale = new ULocale(src.requestedLocale.toString());
dst.localPatternChars = new String (src.localPatternChars);
}
/**
* Compares the equality of the two arrays of String.
* @param current this String array.
@ -1728,7 +1744,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* Fetch a custom calendar's DateFormatSymbols out of the given resource
* bundle. Symbols that are not overridden are inherited from the
* default DateFormatSymbols for the locale.
* @see DateFormatSymbols#DateFormatSymbols
* @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
* @stable ICU 2.0
*/
public DateFormatSymbols(ResourceBundle bundle, Locale locale) {
@ -1739,7 +1755,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* Fetch a custom calendar's DateFormatSymbols out of the given resource
* bundle. Symbols that are not overridden are inherited from the
* default DateFormatSymbols for the locale.
* @see DateFormatSymbols#DateFormatSymbols
* @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
* @draft ICU 3.2
* @provisional This API might change or be removed in a future release.
*/

File diff suppressed because it is too large Load diff

View file

@ -1,43 +1,29 @@
/*
* Copyright (C) 1996-2006, International Business Machines
* Copyright (C) 1996-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*/
package com.ibm.icu.util;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ICUService.Factory;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.BuddhistCalendar;
import com.ibm.icu.util.ChineseCalendar;
import com.ibm.icu.util.CopticCalendar;
import com.ibm.icu.util.EthiopicCalendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.HebrewCalendar;
import com.ibm.icu.util.IslamicCalendar;
import com.ibm.icu.util.JapaneseCalendar;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.SimpleDateFormat;
/**
* <code>Calendar</code> is an abstract base class for converting between
* a <code>Date</code> object and a set of integer fields such as
@ -1576,7 +1562,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance()
{
return getInstance(TimeZone.getDefault(), ULocale.getDefault(), null);
return getInstanceInternal(null, null);
}
/**
@ -1587,7 +1573,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance(TimeZone zone)
{
return getInstance(zone, ULocale.getDefault(), null);
return getInstanceInternal(zone, null);
}
/**
@ -1598,7 +1584,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance(Locale aLocale)
{
return getInstance(TimeZone.getDefault(), ULocale.forLocale(aLocale), null);
return getInstanceInternal(null, ULocale.forLocale(aLocale));
}
/**
@ -1610,7 +1596,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance(ULocale locale)
{
return getInstance(TimeZone.getDefault(), locale, null);
return getInstanceInternal(null, locale);
}
/**
@ -1622,7 +1608,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance(TimeZone zone,
Locale aLocale) {
return getInstance(zone, ULocale.forLocale(aLocale), null);
return getInstanceInternal(zone, ULocale.forLocale(aLocale));
}
/**
@ -1635,69 +1621,26 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static synchronized Calendar getInstance(TimeZone zone,
ULocale locale) {
return getInstance(zone, locale, null);
return getInstanceInternal(zone, locale);
}
// ==== Factory Stuff ====
///CLOVER:OFF
/**
* Return a calendar of for the TimeZone and locale. If factoryName is
* not null, looks in the collection of CalendarFactories for a match
* and uses that factory to instantiate the calendar. Otherwise, it
* uses the default factory that has been registered for the locale.
* @prototype
*/
/* public */ static synchronized Calendar getInstance(TimeZone zone,
ULocale locale,
String factoryName)
{
CalendarFactory factory = null;
if (factoryName != null) {
factory = (CalendarFactory)getFactoryMap().get(factoryName);
/*
* All getInstance implementations call this private method to create a new
* Calendar instance.
*/
private static Calendar getInstanceInternal(TimeZone tz, ULocale locale) {
if (locale == null) {
locale = ULocale.getDefault();
}
ULocale[] actualReturn = new ULocale[1];
if (factory == null && service != null) {
factory = (CalendarFactory)service.get(locale, actualReturn);
}
if (factory == null) {
int calType = getCalendarType(locale);
switch (calType) {
case BUDDHIST:
return new BuddhistCalendar(zone, locale);
case CHINESE:
return new ChineseCalendar(zone, locale);
case COPTIC:
return new CopticCalendar(zone, locale);
case ETHIOPIC:
return new EthiopicCalendar(zone, locale);
case GREGORIAN:
return new GregorianCalendar(zone, locale);
case HEBREW:
return new HebrewCalendar(zone, locale);
case ISLAMIC:
case ISLAMIC_CIVIL: {
IslamicCalendar result = new IslamicCalendar(zone, locale);
result.setCivil(calType == ISLAMIC_CIVIL);
return result;
}
case JAPANESE:
return new JapaneseCalendar(zone, locale);
default:
throw new IllegalStateException();
}
} else {
Calendar result = factory.create(zone, locale);
// TODO: get the actual/valid locale properly
ULocale uloc = actualReturn[0];
result.setLocale(uloc, uloc);
return result;
if (tz == null) {
tz = TimeZone.getDefault();
}
Calendar cal = getShim().createInstance(locale);
cal.setTimeZone(tz);
cal.setTimeInMillis(System.currentTimeMillis());
return cal;
}
private static final int BUDDHIST = 0;
private static final int CHINESE = 1;
private static final int COPTIC = 2;
@ -1735,7 +1678,6 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
return GREGORIAN;
}
///CLOVER:ON
/**
* Gets the list of locales for which Calendars are installed.
* @return the list of locales for which Calendars are installed.
@ -1743,9 +1685,10 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static Locale[] getAvailableLocales()
{
return service == null
? ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME)
: service.getAvailableLocales();
if (shim == null) {
return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
}
return getShim().getAvailableLocales();
}
/**
@ -1756,75 +1699,103 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
*/
public static ULocale[] getAvailableULocales()
{
return service == null
? ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME)
: service.getAvailableULocales();
if (shim == null) {
return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
}
return getShim().getAvailableULocales();
}
// ==== Factory Stuff ====
/**
* A CalendarFactory is used to register new calendar implementation.
* The factory should be able to create a calendar instance for the
* specified locale.
*
* @prototype
*/
/* public */ static abstract class CalendarFactory {
public boolean visible() {
return true;
}
public abstract Set getSupportedLocaleNames();
public Calendar createCalendar(ULocale loc) {
return null;
}
protected CalendarFactory() {
}
}
// shim so we can build without service code
static abstract class CalendarShim {
abstract Locale[] getAvailableLocales();
abstract ULocale[] getAvailableULocales();
abstract Object registerFactory(CalendarFactory factory);
abstract boolean unregister(Object k);
abstract Calendar createInstance(ULocale l);
}
private static CalendarShim shim;
private static CalendarShim getShim() {
if (shim == null) {
try {
Class cls = Class.forName("com.ibm.icu.util.CalendarServiceShim");
shim = (CalendarShim)cls.newInstance();
}
catch (MissingResourceException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
return shim;
}
static Calendar createInstance(ULocale locale) {
int calType = getCalendarType(locale);
TimeZone zone = TimeZone.getDefault();
switch (calType) {
case BUDDHIST:
return new BuddhistCalendar(zone, locale);
case CHINESE:
return new ChineseCalendar(zone, locale);
case COPTIC:
return new CopticCalendar(zone, locale);
case ETHIOPIC:
return new EthiopicCalendar(zone, locale);
case GREGORIAN:
return new GregorianCalendar(zone, locale);
case HEBREW:
return new HebrewCalendar(zone, locale);
case ISLAMIC:
case ISLAMIC_CIVIL: {
IslamicCalendar result = new IslamicCalendar(zone, locale);
result.setCivil(calType == ISLAMIC_CIVIL);
return result;
}
case JAPANESE:
return new JapaneseCalendar(zone, locale);
default:
throw new IllegalStateException();
}
}
///CLOVER:OFF
private static Map factoryMap;
private static Map getFactoryMap() {
if (factoryMap == null) {
Map m = new HashMap(5);
/*
addFactory(m, BuddhistCalendar.factory());
addFactory(m, ChineseCalendar.factory());
addFactory(m, GregorianCalendar.factory());
addFactory(m, HebrewCalendar.factory());
addFactory(m, IslamicCalendar.factory());
addFactory(m, JapaneseCalendar.factory());
*/
factoryMap = m;
}
return factoryMap;
}
// Never used -- why is this here? Alan 2003-05
// private static void addFactory(Map m, CalendarFactory f) {
// m.put(f.factoryName(), f);
// }
/**
* Return a set of all the registered calendar factory names.
* @prototype
*/
/* public */ static Set getCalendarFactoryNames() {
return Collections.unmodifiableSet(getFactoryMap().keySet());
}
/**
* Register a new CalendarFactory. getInstance(TimeZone, ULocale, String) will
* try to locate a registered factories matching the factoryName. Only registered
* factories will be found.
* @prototype
*/
private static void registerFactory(CalendarFactory factory) {
/* public */ static Object registerFactory(CalendarFactory factory) {
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
throw new IllegalArgumentException("factory must not be null");
}
getFactoryMap().put(factory.factoryName(), factory);
}
/**
* Convenience override of register(CalendarFactory, ULocale, boolean);
* @prototype
*/
/* public */ static Object register(CalendarFactory factory, ULocale locale) {
return register(factory, locale, true);
}
/**
* Registers a default CalendarFactory for the provided locale.
* If the factory has not already been registered with
* registerFactory, it will be.
* @prototype
*/
/* public */ static Object register(CalendarFactory factory, ULocale locale, boolean visible) {
if (factory == null) {
throw new IllegalArgumentException("calendar must not be null");
}
registerFactory(factory);
return getService().registerObject(factory, locale, visible);
return getShim().registerFactory(factory);
}
/**
@ -1833,20 +1804,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
* @prototype
*/
/* public */ static boolean unregister(Object registryKey) {
return service == null
? false
: service.unregisterFactory((Factory)registryKey);
if (registryKey == null) {
throw new IllegalArgumentException("registryKey must not be null");
}
if (shim == null) {
return false;
}
return shim.unregister(registryKey);
}
private static ICULocaleService service = null;
private static ICULocaleService getService() {
synchronized (Calendar.class) {
if (service == null) {
service = new ICULocaleService("Calendar");
}
}
return service;
}
///CLOVER:ON
// ==== End of factory Stuff ====
@ -3048,51 +3016,96 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
* @provisional This API might change or be removed in a future release.
*/
protected DateFormat handleGetDateFormat(String pattern, ULocale locale) {
DateFormatSymbols symbols = new DateFormatSymbols(this, locale);
return new SimpleDateFormat(pattern, symbols, locale);
FormatConfiguration fmtConfig = new FormatConfiguration();
fmtConfig.pattern = pattern;
fmtConfig.formatData = new DateFormatSymbols(this, locale);
fmtConfig.loc = locale;
fmtConfig.cal = this;
return SimpleDateFormat.getInstance(fmtConfig);
}
static private DateFormat formatHelper(Calendar cal, ULocale loc,
int dateStyle, int timeStyle)
{
// See if there are any custom resources for this calendar
// If not, just use the default DateFormat
DateFormat result = null;
// date format pattern cache
private static final ICUCache PATTERN_CACHE = new SimpleCache();
// final fallback patterns
private static final String[] DEFAULT_PATTERNS = {
"HH:mm:ss z",
"HH:mm:ss z",
"HH:mm:ss",
"HH:mm",
"EEEE, yyyy MMMM dd",
"yyyy MMMM d",
"yyyy MMM d",
"yy/MM/dd",
"{1} {0}"
};
static private DateFormat formatHelper(Calendar cal, ULocale loc, int dateStyle, int timeStyle) {
// First, try to get a pattern from PATTERN_CACHE
String key = loc.toString() + cal.getType();
String[] patterns = (String[])PATTERN_CACHE.get(key);
if (patterns == null) {
// Cache missed. Get one from bundle
try {
CalendarData calData = new CalendarData(loc, cal.getType());
String[] patterns = calData.get("DateTimePatterns").getStringArray();
String pattern = null;
if ((timeStyle >= 0) && (dateStyle >= 0)) {
Object[] dateTimeArgs = { patterns[timeStyle],
patterns[dateStyle + 4] };
pattern = MessageFormat.format(patterns[8], dateTimeArgs);
}
else if (timeStyle >= 0) {
pattern = patterns[timeStyle];
}
else if (dateStyle >= 0) {
pattern = patterns[dateStyle + 4];
}
else {
throw new IllegalArgumentException("No date or time style specified");
}
result = cal.handleGetDateFormat(pattern, loc);
patterns = calData.get("DateTimePatterns").getStringArray();
} catch (MissingResourceException e) {
// !!! need dateformat subclass appropriate to calendar type here!
// No custom patterns
// !!! note: possible circularity here, if getDateTimeInstance calls us because of
// loc specifying a calendar.
result = DateFormat.getDateTimeInstance(dateStyle, timeStyle, loc);
DateFormatSymbols symbols = new DateFormatSymbols(cal, loc);
((SimpleDateFormat) result).setDateFormatSymbols(symbols); // aliu
patterns = DEFAULT_PATTERNS;
}
PATTERN_CACHE.put(key, patterns);
}
// Resolve a pattern for the date/time style
String pattern = null;
if ((timeStyle >= 0) && (dateStyle >= 0)) {
pattern = MessageFormat.format(patterns[8],
new Object[] {patterns[timeStyle], patterns[dateStyle + 4]});
} else if (timeStyle >= 0) {
pattern = patterns[timeStyle];
} else if (dateStyle >= 0) {
pattern = patterns[dateStyle + 4];
} else {
throw new IllegalArgumentException("No date or time style specified");
}
DateFormat result = cal.handleGetDateFormat(pattern, loc);
result.setCalendar(cal);
return result;
}
/**
* An instance of FormatConfiguration represents calendar specific
* date format configuration and used for calling the ICU private
* SimpleDateFormat factory method.
*
* @internal
* @deprecated This API is ICU internal only.
*/
public static class FormatConfiguration {
private String pattern;
private DateFormatSymbols formatData;
private Calendar cal;
private ULocale loc;
// Only Calendar can instantiate
private FormatConfiguration() {
}
public String getPatternString() {
return pattern;
}
public Calendar getCalendar() {
return cal;
}
public ULocale getLocale() {
return loc;
}
public DateFormatSymbols getDateFormatSymbols() {
return formatData;
}
}
//-------------------------------------------------------------------------
// Protected utility methods for use by subclasses. These are very handy
// for implementing add, roll, and computeFields.

View file

@ -0,0 +1,107 @@
/*
* Copyright (C) 2007, International Business Machines
* Corporation and others. All Rights Reserved.
*/
package com.ibm.icu.util;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Set;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ICUService;
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
import com.ibm.icu.impl.ICUService.Factory;
import com.ibm.icu.impl.ICUService.Key;
import com.ibm.icu.util.Calendar.CalendarFactory;
class CalendarServiceShim extends Calendar.CalendarShim {
Locale[] getAvailableLocales() {
if (service.isDefault()) {
return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
}
return service.getAvailableLocales();
}
ULocale[] getAvailableULocales() {
if (service.isDefault()) {
return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
}
return service.getAvailableULocales();
}
private static final class CalFactory extends LocaleKeyFactory {
private CalendarFactory delegate;
CalFactory(CalendarFactory delegate) {
super(delegate.visible() ? VISIBLE : INVISIBLE);
this.delegate = delegate;
}
public Object create(Key key, ICUService service) {
if (handlesKey(key)) {
LocaleKey lkey = (LocaleKey)key;
ULocale loc = lkey.canonicalLocale();
Object result = delegate.createCalendar(loc);
if (result == null) {
result = service.getKey(key, null, this);
}
return result;
}
return null;
}
protected Set getSupportedIDs() {
return delegate.getSupportedLocaleNames();
}
}
Calendar createInstance(ULocale desiredLocale) {
ULocale[] actualLoc = new ULocale[1];
if (desiredLocale.equals(ULocale.ROOT)) {
desiredLocale = ULocale.ROOT;
}
Calendar cal = (Calendar)service.get(desiredLocale, actualLoc);
if (cal == null) {
throw new MissingResourceException("Unable to construct Calendar", "", "");
}
cal = (Calendar)cal.clone();
/* !!! TODO !!! actualLoc returned by service is not properly set.
* When this Calendar object is being created, cal.setLocale is called
* and proper actual locale is set at that time. Revisit this later.
* -yoshito
*/
/*
ULocale uloc = actualLoc[0];
cal.setLocale(uloc, uloc); // service make no distinction between actual and valid
*/
return cal;
}
Object registerFactory(CalendarFactory factory) {
return service.registerFactory(new CalFactory(factory));
}
boolean unregister(Object k) {
return service.unregisterFactory((Factory)k);
}
private static class CalService extends ICULocaleService {
CalService() {
super("Calendar");
class RBCalendarFactory extends ICUResourceBundleFactory {
protected Object handleCreate(ULocale loc, int kind, ICUService sercice) {
return Calendar.createInstance(loc);
}
}
this.registerFactory(new RBCalendarFactory());
markDefault();
}
}
private static ICULocaleService service = new CalService();
}

View file

@ -8,6 +8,7 @@
package com.ibm.icu.util;
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@ -16,12 +17,11 @@ import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.TreeMap;
import java.lang.ref.SoftReference;
import com.ibm.icu.impl.LocaleUtility;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.LocaleUtility;
import com.ibm.icu.lang.UCharacter;
/**
* A class analogous to {@link java.util.Locale} that provides additional
* support for ICU protocol. In ICU 3.0 this class is enhanced to support
@ -232,30 +232,7 @@ public final class ULocale implements Serializable {
*/
public static final ULocale ROOT = new ULocale("root", EMPTY_LOCALE);
private static final HashMap CACHE = new HashMap(20);
static {
CACHE.put(EMPTY_LOCALE, ROOT);
CACHE.put(Locale.ENGLISH, ENGLISH);
CACHE.put(Locale.FRENCH, FRENCH);
CACHE.put(Locale.GERMAN, GERMAN);
CACHE.put(Locale.ITALIAN, ITALIAN);
CACHE.put(Locale.JAPANESE, JAPANESE);
CACHE.put(Locale.KOREAN, KOREAN);
CACHE.put(Locale.CHINESE, CHINESE);
CACHE.put(Locale.SIMPLIFIED_CHINESE, SIMPLIFIED_CHINESE);
CACHE.put(Locale.TRADITIONAL_CHINESE, TRADITIONAL_CHINESE);
CACHE.put(Locale.FRANCE, FRANCE);
CACHE.put(Locale.GERMANY, GERMANY);
CACHE.put(Locale.ITALY, ITALY);
CACHE.put(Locale.JAPAN, JAPAN);
CACHE.put(Locale.KOREA, KOREA);
CACHE.put(Locale.CHINA, CHINA);
CACHE.put(Locale.TAIWAN, TAIWAN);
CACHE.put(Locale.UK, UK);
CACHE.put(Locale.US, US);
CACHE.put(Locale.CANADA, CANADA);
CACHE.put(Locale.CANADA_FRENCH, CANADA_FRENCH);
}
private static final SimpleCache CACHE = new SimpleCache();
/**
* Cache the locale.
@ -749,14 +726,19 @@ public final class ULocale implements Serializable {
if (loc == null) {
return null;
}
if (loc.toString().length() == 0) {
return ROOT;
}
ULocale result = (ULocale)CACHE.get(loc);
if (result == null && defaultULocale != null && loc == defaultULocale.locale) {
if (result == null) {
if (defaultULocale != null && loc == defaultULocale.locale) {
result = defaultULocale;
} else {
result = new ULocale(loc.toString(), loc);
String locStr = loc.toString();
if (locStr.length() == 0) {
result = ROOT;
} else {
result = new ULocale(locStr, loc);
}
}
CACHE.put(loc, result);
}
return result;
}
@ -863,10 +845,12 @@ public final class ULocale implements Serializable {
return locale;
}
private static SoftReference nameCacheRef = new SoftReference(Collections.synchronizedMap(new HashMap()));
/**
* Keep our own default ULocale.
*/
private static ULocale defaultULocale;
private static Locale defaultLocale = Locale.getDefault();
private static ULocale defaultULocale = new ULocale(defaultLocale);
/**
* Returns the current default ULocale.
@ -874,8 +858,9 @@ public final class ULocale implements Serializable {
*/
public static ULocale getDefault() {
synchronized (ULocale.class) {
Locale defaultLocale = Locale.getDefault();
if (defaultULocale == null || defaultULocale.toLocale() != defaultLocale) {
Locale currentDefault = Locale.getDefault();
if (defaultLocale != currentDefault) {
defaultLocale = currentDefault;
defaultULocale = new ULocale(defaultLocale);
}
return defaultULocale;
@ -892,7 +877,7 @@ public final class ULocale implements Serializable {
* if a security manager exists and its
* <code>checkPermission</code> method doesn't allow the operation.
* @throws NullPointerException if <code>newLocale</code> is null
* @see SecurityManager#checkPermission
* @see SecurityManager#checkPermission(java.security.Permission)
* @see java.util.PropertyPermission
* @stable ICU 3.0
*/
@ -974,7 +959,8 @@ public final class ULocale implements Serializable {
/**
* Returns the language code for this locale, which will either be the empty string
* or a lowercase ISO 639 code.
* @see #getDisplayLanguage
* @see #getDisplayLanguage()
* @see #getDisplayLanguage(ULocale)
* @stable ICU 3.0
*/
public String getLanguage() {
@ -985,7 +971,8 @@ public final class ULocale implements Serializable {
* Returns the language code for the locale ID,
* which will either be the empty string
* or a lowercase ISO 639 code.
* @see #getDisplayLanguage
* @see #getDisplayLanguage()
* @see #getDisplayLanguage(ULocale)
* @stable ICU 3.0
*/
public static String getLanguage(String localeID) {
@ -994,7 +981,8 @@ public final class ULocale implements Serializable {
/**
* Returns the script code for this locale, which might be the empty string.
* @see #getDisplayScript
* @see #getDisplayScript()
* @see #getDisplayScript(ULocale)
* @stable ICU 3.0
*/
public String getScript() {
@ -1003,7 +991,8 @@ public final class ULocale implements Serializable {
/**
* Returns the script code for the specified locale, which might be the empty string.
* @see #getDisplayScript
* @see #getDisplayScript()
* @see #getDisplayScript(ULocale)
* @stable ICU 3.0
*/
public static String getScript(String localeID) {
@ -1013,7 +1002,8 @@ public final class ULocale implements Serializable {
/**
* Returns the country/region code for this locale, which will either be the empty string
* or an uppercase ISO 3166 2-letter code.
* @see #getDisplayCountry
* @see #getDisplayCountry()
* @see #getDisplayCountry(ULocale)
* @stable ICU 3.0
*/
public String getCountry() {
@ -1024,7 +1014,8 @@ public final class ULocale implements Serializable {
* Returns the country/region code for this locale, which will either be the empty string
* or an uppercase ISO 3166 2-letter code.
* @param localeID
* @see #getDisplayCountry
* @see #getDisplayCountry()
* @see #getDisplayCountry(ULocale)
* @stable ICU 3.0
*/
public static String getCountry(String localeID) {
@ -1033,7 +1024,8 @@ public final class ULocale implements Serializable {
/**
* Returns the variant code for this locale, which might be the empty string.
* @see #getDisplayVariant
* @see #getDisplayVariant()
* @see #getDisplayVariant(ULocale)
* @stable ICU 3.0
*/
public String getVariant() {
@ -1042,7 +1034,8 @@ public final class ULocale implements Serializable {
/**
* Returns the variant code for the specified locale, which might be the empty string.
* @see #getDisplayVariant
* @see #getDisplayVariant()
* @see #getDisplayVariant(ULocale)
* @stable ICU 3.0
*/
public static String getVariant(String localeID) {
@ -1135,7 +1128,6 @@ public final class ULocale implements Serializable {
}
return name;
}
private static SoftReference nameCacheRef = new SoftReference(Collections.synchronizedMap(new HashMap()));
/**
* Returns a string representation of this object.
@ -1319,12 +1311,12 @@ public final class ULocale implements Serializable {
return index >= id.length || isTerminator(id[index]);
}
/**
/*
* Returns true if the character is an id separator (underscore or hyphen).
*/
private boolean isIDSeparator(char c) {
/* private boolean isIDSeparator(char c) {
return c == UNDERSCORE || c == HYPHEN;
}
}*/
/**
* Returns true if the character is a terminator (keyword separator, dot, or DONE).
@ -2009,7 +2001,7 @@ public final class ULocale implements Serializable {
return parser.getName();
}
/**
/*
* Given a locale id, a keyword, and a value, return a new locale id with an updated
* keyword and value, if the keyword does not already have a value. The keyword and
* value must not be null or empty.
@ -2019,11 +2011,11 @@ public final class ULocale implements Serializable {
* @return the updated locale id
* @internal
*/
private static String defaultKeywordValue(String localeID, String keyword, String value) {
/* private static String defaultKeywordValue(String localeID, String keyword, String value) {
IDParser parser = new IDParser(localeID);
parser.defaultKeywordValue(keyword, value);
return parser.getName();
}
}*/
/**
* Returns a three-letter abbreviation for this locale's language. If the locale
@ -2392,7 +2384,7 @@ public final class ULocale implements Serializable {
* Returns a keyword localized for display in the default locale.
* @param keyword the keyword to be displayed.
* @return the localized keyword name.
* @see #getKeywords
* @see #getKeywords()
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword) {
@ -2404,7 +2396,7 @@ public final class ULocale implements Serializable {
* @param keyword the keyword to be displayed.
* @param displayLocaleID the id of the locale in which to display the keyword.
* @return the localized keyword name.
* @see #getKeywords
* @see #getKeywords(String)
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword, String displayLocaleID) {
@ -2416,7 +2408,7 @@ public final class ULocale implements Serializable {
* @param keyword the keyword to be displayed.
* @param displayLocale the locale in which to display the keyword.
* @return the localized keyword name.
* @see #getKeywords
* @see #getKeywords(String)
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword, ULocale displayLocale) {
@ -2681,7 +2673,6 @@ public final class ULocale implements Serializable {
final int l = acceptLanguageList.length();
int n;
int last=-1;
for(n=0;n<l;n++) {
int itemEnd = acceptLanguageList.indexOf(',',n);
if(itemEnd == -1) {

View file

@ -8,13 +8,17 @@
package com.ibm.icu.util;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Vector;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ICUResourceBundleImpl;
import com.ibm.icu.impl.ICUResourceBundleReader;
import com.ibm.icu.impl.ResourceBundleWrapper;
import com.ibm.icu.util.ULocale;
@ -277,17 +281,21 @@ public abstract class UResourceBundle extends ResourceBundle{
* @internal revisit for ICU 3.6
* @deprecated This API is ICU internal only.
*/
protected static synchronized void addToCache(ClassLoader cl, String fullName, ULocale defaultLocale, UResourceBundle b){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
addToCache((ResourceCacheKey)cacheKey.clone(), b);
protected static void addToCache(ClassLoader cl, String fullName, ULocale defaultLocale, UResourceBundle b){
synchronized(cacheKey){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
addToCache((ResourceCacheKey)cacheKey.clone(), b);
}
}
/**
* @internal revisit for ICU 3.6
* @deprecated This API is ICU internal only.
*/
protected static synchronized UResourceBundle loadFromCache(ClassLoader cl, String fullName, ULocale defaultLocale){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
return loadFromCache(cacheKey);
protected static UResourceBundle loadFromCache(ClassLoader cl, String fullName, ULocale defaultLocale){
synchronized(cacheKey){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
return loadFromCache(cacheKey);
}
}
private static UResourceBundle loadFromCache(ResourceCacheKey key) {
if (BUNDLE_CACHE != null) {
@ -364,7 +372,7 @@ public abstract class UResourceBundle extends ResourceBundle{
}
}
///CLOVER:ON
private void setKeyValues(ClassLoader root, String searchName, ULocale defaultLocale) {
private synchronized void setKeyValues(ClassLoader root, String searchName, ULocale defaultLocale) {
this.searchName = searchName;
hashCodeCache = searchName.hashCode();
this.defaultLocale = defaultLocale;
@ -378,11 +386,9 @@ public abstract class UResourceBundle extends ResourceBundle{
hashCodeCache ^= root.hashCode();
}
}
///CLOVER:OFF
private void clear() {
/*private void clear() {
setKeyValues(null, "", null);
}
///CLOVER:ON
}*/
}
private static final ResourceCacheKey cacheKey = new ResourceCacheKey();
@ -411,14 +417,13 @@ public abstract class UResourceBundle extends ResourceBundle{
if (rootType == null) {
String rootLocale = (baseName.indexOf('.')==-1) ? "root" : "";
int rt = ROOT_MISSING;
UResourceBundle b = null;
int rt = ROOT_MISSING; // value set on success
try{
b = ICUResourceBundle.getBundleInstance(baseName, rootLocale, root, true);
ICUResourceBundle.getBundleInstance(baseName, rootLocale, root, true);
rt = ROOT_ICU;
}catch(MissingResourceException ex){
try{
b = ResourceBundleWrapper.getBundleInstance(baseName, rootLocale, root, true);
ResourceBundleWrapper.getBundleInstance(baseName, rootLocale, root, true);
rt = ROOT_JAVA;
}catch(MissingResourceException e){
//throw away the exception
@ -459,9 +464,8 @@ public abstract class UResourceBundle extends ResourceBundle{
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
protected static synchronized UResourceBundle instantiateBundle(
String baseName, String localeName, ClassLoader root, boolean disableFallback)
{
protected static UResourceBundle instantiateBundle(String baseName, String localeName,
ClassLoader root, boolean disableFallback){
UResourceBundle b = null;
int rootType = getRootType(baseName, root);
@ -472,13 +476,14 @@ public abstract class UResourceBundle extends ResourceBundle{
case ROOT_ICU:
if(disableFallback) {
String fullName = ICUResourceBundleReader.getFullName(baseName, localeName);
cacheKey.setKeyValues(root, fullName, defaultLocale);
b = loadFromCache(cacheKey);
synchronized(cacheKey){
cacheKey.setKeyValues(root, fullName, defaultLocale);
b = loadFromCache(cacheKey);
}
if (b == null) {
b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
cacheKey.setKeyValues(root, fullName, defaultLocale);
//cacheKey.setKeyValues(root, fullName, defaultLocale);
addToCache(cacheKey, b);
}
} else {
@ -501,7 +506,7 @@ public abstract class UResourceBundle extends ResourceBundle{
return b;
}
}
/**
* @internal
* @deprecated This API is ICU internal only.