提交 f257643d 编写于 作者: N naoto

8008576: Calendar mismatch using Host LocaleProviderAdapter

Reviewed-by: okutsu
上级 5b2c05ff
...@@ -209,6 +209,7 @@ JAVA_JAVA_java = \ ...@@ -209,6 +209,7 @@ JAVA_JAVA_java = \
sun/util/locale/provider/CalendarDataProviderImpl.java \ sun/util/locale/provider/CalendarDataProviderImpl.java \
sun/util/locale/provider/CalendarDataUtility.java \ sun/util/locale/provider/CalendarDataUtility.java \
sun/util/locale/provider/CalendarNameProviderImpl.java \ sun/util/locale/provider/CalendarNameProviderImpl.java \
sun/util/locale/provider/CalendarProviderImpl.java \
sun/util/locale/provider/CollationRules.java \ sun/util/locale/provider/CollationRules.java \
sun/util/locale/provider/CollatorProviderImpl.java \ sun/util/locale/provider/CollatorProviderImpl.java \
sun/util/locale/provider/CurrencyNameProviderImpl.java \ sun/util/locale/provider/CurrencyNameProviderImpl.java \
...@@ -232,6 +233,7 @@ JAVA_JAVA_java = \ ...@@ -232,6 +233,7 @@ JAVA_JAVA_java = \
sun/util/locale/provider/SPILocaleProviderAdapter.java \ sun/util/locale/provider/SPILocaleProviderAdapter.java \
sun/util/locale/provider/TimeZoneNameProviderImpl.java \ sun/util/locale/provider/TimeZoneNameProviderImpl.java \
sun/util/locale/provider/TimeZoneNameUtility.java \ sun/util/locale/provider/TimeZoneNameUtility.java \
sun/util/spi/CalendarProvider.java \
java/util/LocaleISOData.java \ java/util/LocaleISOData.java \
sun/util/cldr/CLDRLocaleProviderAdapter.java \ sun/util/cldr/CLDRLocaleProviderAdapter.java \
java/util/MissingResourceException.java \ java/util/MissingResourceException.java \
......
...@@ -32,11 +32,13 @@ import java.text.spi.DateFormatSymbolsProvider; ...@@ -32,11 +32,13 @@ import java.text.spi.DateFormatSymbolsProvider;
import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider;
import java.text.spi.NumberFormatProvider; import java.text.spi.NumberFormatProvider;
import java.util.Collections; import java.util.Collections;
import java.util.Calendar;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle.Control; import java.util.ResourceBundle.Control;
import java.util.Set; import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.atomic.AtomicReferenceArray;
...@@ -45,6 +47,7 @@ import java.util.spi.CalendarNameProvider; ...@@ -45,6 +47,7 @@ import java.util.spi.CalendarNameProvider;
import java.util.spi.CurrencyNameProvider; import java.util.spi.CurrencyNameProvider;
import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleNameProvider;
import java.util.spi.TimeZoneNameProvider; import java.util.spi.TimeZoneNameProvider;
import sun.util.spi.CalendarProvider;
/** /**
* LocaleProviderAdapter implementation for the Mac OS X locale data * LocaleProviderAdapter implementation for the Mac OS X locale data
...@@ -94,17 +97,56 @@ public class HostLocaleProviderAdapterImpl { ...@@ -94,17 +97,56 @@ public class HostLocaleProviderAdapterImpl {
private static final Set<Locale> supportedLocaleSet; private static final Set<Locale> supportedLocaleSet;
static { static {
Set<Locale> tmpSet = new HashSet<Locale>(); Set<Locale> tmpSet = new HashSet<>();
// Assuming the default locales do not include any extensions, so // Assuming the default locales do not include any extensions, so
// no stripping is needed here. // no stripping is needed here.
Locale l = Locale.forLanguageTag(getDefaultLocale(CAT_FORMAT).replaceAll("_","-")); Locale l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_FORMAT));
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
l = Locale.forLanguageTag(getDefaultLocale(CAT_DISPLAY).replaceAll("_","-")); l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_DISPLAY));
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
supportedLocaleSet = Collections.unmodifiableSet(tmpSet); supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
} }
private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]); private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);
@SuppressWarnings("fallthrough")
private static Locale convertMacOSXLocaleToJavaLocale(String macosxloc) {
// MacOSX may return ICU notation, here is the quote from CFLocale doc:
// "The corresponding value is a CFString containing the POSIX locale
// identifier as used by ICU, such as "ja_JP". If you have a variant
// locale or a different currency or calendar, it can be as complex as
// "en_US_POSIX@calendar=japanese;currency=EUR" or
// "az_Cyrl_AZ@calendar=buddhist;currency=JPY".
String[] tmp = macosxloc.split("@");
String langTag = tmp[0].replace('_', '-');
if (tmp.length > 1) {
String[] ext = tmp[1].split(";");
for (String keyval : ext) {
// We are only interested in "calendar" value for now.
if (keyval.startsWith("calendar=")) {
String calid = keyval.substring(keyval.indexOf('=')+1);
switch (calid) {
case "gregorian":
langTag += "-u-ca-gregory";
break;
case "japanese":
// Tweak for ja_JP_JP
if (tmp[0].equals("ja_JP")) {
return JRELocaleConstants.JA_JP_JP;
}
// fall through
default:
langTag += "-u-ca-" + calid;
break;
}
}
}
}
return Locale.forLanguageTag(langTag);
}
public static DateFormatProvider getDateFormatProvider() { public static DateFormatProvider getDateFormatProvider() {
return new DateFormatProvider() { return new DateFormatProvider() {
...@@ -170,9 +212,8 @@ public class HostLocaleProviderAdapterImpl { ...@@ -170,9 +212,8 @@ public class HostLocaleProviderAdapterImpl {
if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) { if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) {
return supportedLocale; return supportedLocale;
} }
return new Locale[0];
return new Locale[0]; }
}
@Override @Override
public boolean isSupportedLocale(Locale locale) { public boolean isSupportedLocale(Locale locale) {
...@@ -362,6 +403,30 @@ public class HostLocaleProviderAdapterImpl { ...@@ -362,6 +403,30 @@ public class HostLocaleProviderAdapterImpl {
}; };
} }
public static CalendarProvider getCalendarProvider() {
return new CalendarProvider() {
@Override
public Locale[] getAvailableLocales() {
return getSupportedCalendarLocales();
}
@Override
public boolean isSupportedLocale(Locale locale) {
return isSupportedCalendarLocale(locale);
}
@Override
public Calendar getInstance(TimeZone zone, Locale locale) {
return new Calendar.Builder()
.setLocale(locale)
.setCalendarType(getCalendarID(locale.toLanguageTag()))
.setTimeZone(zone)
.setInstant(System.currentTimeMillis())
.build();
}
};
}
public static CurrencyNameProvider getCurrencyNameProvider() { public static CurrencyNameProvider getCurrencyNameProvider() {
return new CurrencyNameProvider() { return new CurrencyNameProvider() {
@Override @Override
...@@ -455,23 +520,20 @@ public class HostLocaleProviderAdapterImpl { ...@@ -455,23 +520,20 @@ public class HostLocaleProviderAdapterImpl {
} }
private static boolean isSupportedCalendarLocale(Locale locale) { private static boolean isSupportedCalendarLocale(Locale locale) {
// special case for ja_JP_JP
if (JRELocaleConstants.JA_JP_JP.equals(locale)) {
return isJapaneseCalendar();
}
Locale base = locale.stripExtensions(); Locale base = locale.stripExtensions();
if (!supportedLocaleSet.contains(base)) { if (!supportedLocaleSet.contains(base)) {
return false; return false;
} }
String caltype = locale.getUnicodeLocaleType("ca"); String requestedCalType = locale.getUnicodeLocaleType("ca");
if (caltype == null) { String nativeCalType =
return true; getCalendarID(locale.toLanguageTag()).replaceFirst("gregorian", "gregory");
}
return caltype.replaceFirst("gregory", "gregorian").equals( if (requestedCalType == null) {
getCalendarID(locale.toLanguageTag())); return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
} else {
return requestedCalType.equals(nativeCalType);
}
} }
private static boolean isJapaneseCalendar() { private static boolean isJapaneseCalendar() {
...@@ -479,18 +541,15 @@ public class HostLocaleProviderAdapterImpl { ...@@ -479,18 +541,15 @@ public class HostLocaleProviderAdapterImpl {
} }
private static Locale getCalendarLocale(Locale locale) { private static Locale getCalendarLocale(Locale locale) {
Locale.Builder lb = new Locale.Builder().setLocale(locale); String nativeCalType = getCalendarID(locale.toLanguageTag())
String calid = getCalendarID(locale.toLanguageTag()); .replaceFirst("gregorian", "gregory");
switch (calid) { if (Calendar.getAvailableCalendarTypes().contains(nativeCalType)) {
case "gregorian": return new Locale.Builder()
calid = "gregory"; .setLocale(locale)
// FALL THROUGH! .setUnicodeLocaleKeyword("ca", nativeCalType)
case "japanese": .build();
case "buddhist": } else {
lb.setUnicodeLocaleKeyword("ca", calid); return locale;
return lb.build();
default:
return locale;
} }
} }
......
...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap; ...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap;
import sun.util.BuddhistCalendar; import sun.util.BuddhistCalendar;
import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfo;
import sun.util.locale.provider.CalendarDataUtility; import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.spi.CalendarProvider;
/** /**
* The <code>Calendar</code> class is an abstract class that provides methods * The <code>Calendar</code> class is an abstract class that provides methods
...@@ -1608,9 +1610,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -1608,9 +1610,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
*/ */
public static Calendar getInstance() public static Calendar getInstance()
{ {
Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT)); return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
cal.sharedZone = true;
return cal;
} }
/** /**
...@@ -1637,9 +1637,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -1637,9 +1637,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
*/ */
public static Calendar getInstance(Locale aLocale) public static Calendar getInstance(Locale aLocale)
{ {
Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale); return createCalendar(TimeZone.getDefault(), aLocale);
cal.sharedZone = true;
return cal;
} }
/** /**
...@@ -1660,6 +1658,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -1660,6 +1658,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
private static Calendar createCalendar(TimeZone zone, private static Calendar createCalendar(TimeZone zone,
Locale aLocale) Locale aLocale)
{ {
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null; Calendar cal = null;
if (aLocale.hasExtensions()) { if (aLocale.hasExtensions()) {
......
...@@ -134,7 +134,7 @@ public class LanguageTag { ...@@ -134,7 +134,7 @@ public class LanguageTag {
} }
/* /*
* BNF in RFC5464 * BNF in RFC5646
* *
* Language-Tag = langtag ; normal language tags * Language-Tag = langtag ; normal language tags
* / privateuse ; private use tag * / privateuse ; private use tag
......
...@@ -43,6 +43,7 @@ import java.util.spi.CurrencyNameProvider; ...@@ -43,6 +43,7 @@ import java.util.spi.CurrencyNameProvider;
import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleNameProvider;
import java.util.spi.LocaleServiceProvider; import java.util.spi.LocaleServiceProvider;
import java.util.spi.TimeZoneNameProvider; import java.util.spi.TimeZoneNameProvider;
import sun.util.spi.CalendarProvider;
/** /**
* An abstract parent class for the * An abstract parent class for the
...@@ -140,6 +141,14 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { ...@@ -140,6 +141,14 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
return getLocaleServiceProvider(CalendarNameProvider.class); return getLocaleServiceProvider(CalendarNameProvider.class);
} }
/**
* Getter methods for sun.util.spi.* providers
*/
@Override
public CalendarProvider getCalendarProvider() {
return getLocaleServiceProvider(CalendarProvider.class);
}
@Override @Override
public LocaleResources getLocaleResources(Locale locale) { public LocaleResources getLocaleResources(Locale locale) {
return null; return null;
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.util.locale.provider;
import java.util.Calendar;
import java.util.Calendar.Builder;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import sun.util.spi.CalendarProvider;
/**
* Concrete implementation of the {@link sun.util.spi.CalendarProvider
* CalendarProvider} class for the JRE LocaleProviderAdapter.
*
* @author Naoto Sato
*/
public class CalendarProviderImpl extends CalendarProvider implements AvailableLanguageTags {
private final LocaleProviderAdapter.Type type;
private final Set<String> langtags;
public CalendarProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
this.type = type;
this.langtags = langtags;
}
/**
* Returns an array of all locales for which this locale service provider
* can provide localized objects or names.
*
* @return An array of all locales for which this locale service provider
* can provide localized objects or names.
*/
@Override
public Locale[] getAvailableLocales() {
return LocaleProviderAdapter.toLocaleArray(langtags);
}
@Override
public boolean isSupportedLocale(Locale locale) {
// Support any locales.
return true;
}
/**
* Returns a new <code>Calendar</code> instance for the
* specified locale.
*
* @param zone the time zone
* @param locale the desired locale
* @exception NullPointerException if <code>locale</code> is null
* @exception IllegalArgumentException if <code>locale</code> isn't
* one of the locales returned from
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
* getAvailableLocales()}.
* @return a <code>Calendar</code> instance.
* @see java.util.Calendar#getInstance(java.util.Locale)
*/
@Override
public Calendar getInstance(TimeZone zone, Locale locale) {
return new Calendar.Builder()
.setLocale(locale)
.setTimeZone(zone)
.setInstant(System.currentTimeMillis())
.build();
}
@Override
public Set<String> getAvailableLanguageTags() {
return langtags;
}
}
...@@ -34,10 +34,12 @@ import java.text.spi.DateFormatProvider; ...@@ -34,10 +34,12 @@ import java.text.spi.DateFormatProvider;
import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DateFormatSymbolsProvider;
import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider;
import java.text.spi.NumberFormatProvider; import java.text.spi.NumberFormatProvider;
import java.util.Calendar;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.spi.CalendarDataProvider; import java.util.spi.CalendarDataProvider;
...@@ -47,6 +49,7 @@ import java.util.spi.LocaleNameProvider; ...@@ -47,6 +49,7 @@ import java.util.spi.LocaleNameProvider;
import java.util.spi.LocaleServiceProvider; import java.util.spi.LocaleServiceProvider;
import java.util.spi.TimeZoneNameProvider; import java.util.spi.TimeZoneNameProvider;
import sun.util.resources.LocaleData; import sun.util.resources.LocaleData;
import sun.util.spi.CalendarProvider;
/** /**
* LocaleProviderAdapter implementation for the legacy JRE locale data. * LocaleProviderAdapter implementation for the legacy JRE locale data.
...@@ -104,6 +107,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R ...@@ -104,6 +107,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
return (P) getCalendarDataProvider(); return (P) getCalendarDataProvider();
case "CalendarNameProvider": case "CalendarNameProvider":
return (P) getCalendarNameProvider(); return (P) getCalendarNameProvider();
case "CalendarProvider":
return (P) getCalendarProvider();
default: default:
throw new InternalError("should not come down here"); throw new InternalError("should not come down here");
} }
...@@ -122,6 +127,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R ...@@ -122,6 +127,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
private volatile CalendarDataProvider calendarDataProvider = null; private volatile CalendarDataProvider calendarDataProvider = null;
private volatile CalendarNameProvider calendarNameProvider = null; private volatile CalendarNameProvider calendarNameProvider = null;
private volatile CalendarProvider calendarProvider = null;
/* /*
* Getter methods for java.text.spi.* providers * Getter methods for java.text.spi.* providers
*/ */
...@@ -283,6 +290,23 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R ...@@ -283,6 +290,23 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
return calendarNameProvider; return calendarNameProvider;
} }
/**
* Getter methods for sun.util.spi.* providers
*/
@Override
public CalendarProvider getCalendarProvider() {
if (calendarProvider == null) {
CalendarProvider provider = new CalendarProviderImpl(getAdapterType(),
getLanguageTagSet("CalendarData"));
synchronized (this) {
if (calendarProvider == null) {
calendarProvider = provider;
}
}
}
return calendarProvider;
}
@Override @Override
public LocaleResources getLocaleResources(Locale locale) { public LocaleResources getLocaleResources(Locale locale) {
LocaleResources lr = localeResourcesMap.get(locale); LocaleResources lr = localeResourcesMap.get(locale);
......
...@@ -47,6 +47,7 @@ import java.util.spi.LocaleNameProvider; ...@@ -47,6 +47,7 @@ import java.util.spi.LocaleNameProvider;
import java.util.spi.LocaleServiceProvider; import java.util.spi.LocaleServiceProvider;
import java.util.spi.TimeZoneNameProvider; import java.util.spi.TimeZoneNameProvider;
import sun.util.cldr.CLDRLocaleProviderAdapter; import sun.util.cldr.CLDRLocaleProviderAdapter;
import sun.util.spi.CalendarProvider;
/** /**
* The LocaleProviderAdapter abstract class. * The LocaleProviderAdapter abstract class.
...@@ -295,7 +296,10 @@ public abstract class LocaleProviderAdapter { ...@@ -295,7 +296,10 @@ public abstract class LocaleProviderAdapter {
} }
if (type == Type.JRE) { if (type == Type.JRE) {
String oldname = locale.toString().replace('_', '-'); String oldname = locale.toString().replace('_', '-');
return langtags.contains(oldname); return langtags.contains(oldname) ||
"ja-JP-JP".equals(oldname) ||
"th-TH-TH".equals(oldname) ||
"no-NO-NY".equals(oldname);
} }
return false; return false;
} }
...@@ -422,6 +426,14 @@ public abstract class LocaleProviderAdapter { ...@@ -422,6 +426,14 @@ public abstract class LocaleProviderAdapter {
*/ */
public abstract CalendarNameProvider getCalendarNameProvider(); public abstract CalendarNameProvider getCalendarNameProvider();
/**
* Returns a CalendarProvider for this LocaleProviderAdapter, or null if no
* CalendarProvider is available.
*
* @return a CalendarProvider
*/
public abstract CalendarProvider getCalendarProvider();
public abstract LocaleResources getLocaleResources(Locale locale); public abstract LocaleResources getLocaleResources(Locale locale);
public abstract Locale[] getAvailableLocales(); public abstract Locale[] getAvailableLocales();
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.util.spi;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.spi.LocaleServiceProvider;
/**
* An abstract class for service providers that
* provide instances of the
* {@link java.util.Calendar Calendar} class.
*
* @since 1.8
*/
public abstract class CalendarProvider extends LocaleServiceProvider {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected CalendarProvider() {
}
/**
* Returns a new <code>Calendar</code> instance for the
* specified locale.
*
* @param zone the time zone
* @param locale the desired locale
* @exception NullPointerException if <code>locale</code> is null
* @exception IllegalArgumentException if <code>locale</code> isn't
* one of the locales returned from
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
* getAvailableLocales()}.
* @return a <code>Calendar</code> instance.
* @see java.util.Calendar#getInstance(java.util.Locale)
*/
public abstract Calendar getInstance(TimeZone zone, Locale locale);
}
...@@ -35,17 +35,20 @@ import java.text.spi.DateFormatProvider; ...@@ -35,17 +35,20 @@ import java.text.spi.DateFormatProvider;
import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DateFormatSymbolsProvider;
import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider;
import java.text.spi.NumberFormatProvider; import java.text.spi.NumberFormatProvider;
import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle.Control; import java.util.ResourceBundle.Control;
import java.util.Set; import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.spi.CalendarDataProvider; import java.util.spi.CalendarDataProvider;
import java.util.spi.CalendarNameProvider; import java.util.spi.CalendarNameProvider;
import sun.util.spi.CalendarProvider;
/** /**
* LocaleProviderdapter implementation for the Windows locale data. * LocaleProviderdapter implementation for the Windows locale data.
...@@ -98,9 +101,9 @@ public class HostLocaleProviderAdapterImpl { ...@@ -98,9 +101,9 @@ public class HostLocaleProviderAdapterImpl {
if (initialize()) { if (initialize()) {
// Assuming the default locales do not include any extensions, so // Assuming the default locales do not include any extensions, so
// no stripping is needed here. // no stripping is needed here.
Locale l = Locale.forLanguageTag(getDefaultLocale(CAT_FORMAT).replaceAll("_","-")); Locale l = Locale.forLanguageTag(getDefaultLocale(CAT_FORMAT).replace('_', '-'));
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
l = Locale.forLanguageTag(getDefaultLocale(CAT_DISPLAY).replaceAll("_","-")); l = Locale.forLanguageTag(getDefaultLocale(CAT_DISPLAY).replace('_', '-'));
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
} }
supportedLocaleSet = Collections.unmodifiableSet(tmpSet); supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
...@@ -173,24 +176,12 @@ public class HostLocaleProviderAdapterImpl { ...@@ -173,24 +176,12 @@ public class HostLocaleProviderAdapterImpl {
@Override @Override
public Locale[] getAvailableLocales() { public Locale[] getAvailableLocales() {
if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) { return getSupportedCalendarLocales();
return supportedLocale;
}
return new Locale[0];
} }
@Override @Override
public boolean isSupportedLocale(Locale locale) { public boolean isSupportedLocale(Locale locale) {
// Only supports the locale with Gregorian calendar return isSupportedCalendarLocale(locale);
if (supportedLocale.length != 0) {
int calid = getCalendarID(locale.toLanguageTag());
if (calid > 0 && calid < calIDToLDML.length) {
return calIDToLDML[calid].startsWith("gregory");
}
}
return false;
} }
@Override @Override
...@@ -380,6 +371,29 @@ public class HostLocaleProviderAdapterImpl { ...@@ -380,6 +371,29 @@ public class HostLocaleProviderAdapterImpl {
}; };
} }
public static CalendarProvider getCalendarProvider() {
return new CalendarProvider() {
@Override
public Locale[] getAvailableLocales() {
return getSupportedCalendarLocales();
}
@Override
public boolean isSupportedLocale(Locale locale) {
return isSupportedCalendarLocale(locale);
}
@Override
public Calendar getInstance(TimeZone zone, Locale locale) {
return new Calendar.Builder()
.setLocale(getCalendarLocale(locale))
.setTimeZone(zone)
.setInstant(System.currentTimeMillis())
.build();
}
};
}
private static String convertDateTimePattern(String winPattern) { private static String convertDateTimePattern(String winPattern) {
String ret = winPattern.replaceAll("dddd", "EEEE"); String ret = winPattern.replaceAll("dddd", "EEEE");
ret = ret.replaceAll("ddd", "EEE"); ret = ret.replaceAll("ddd", "EEE");
...@@ -401,24 +415,21 @@ public class HostLocaleProviderAdapterImpl { ...@@ -401,24 +415,21 @@ public class HostLocaleProviderAdapterImpl {
} }
private static boolean isSupportedCalendarLocale(Locale locale) { private static boolean isSupportedCalendarLocale(Locale locale) {
// special case for ja_JP_JP
if (JRELocaleConstants.JA_JP_JP.equals(locale)) {
return isJapaneseCalendar();
}
Locale base = locale.stripExtensions(); Locale base = locale.stripExtensions();
if (!supportedLocaleSet.contains(base)) { if (!supportedLocaleSet.contains(base)) {
return false; return false;
} }
String caltype = locale.getUnicodeLocaleType("ca"); String requestedCalType = locale.getUnicodeLocaleType("ca");
if (caltype == null) { String nativeCalType =
return true; calIDToLDML[getCalendarID(locale.toLanguageTag())]
} .replaceFirst("_.*", ""); // remove locale part.
return caltype.equals( if (requestedCalType == null) {
calIDToLDML[getCalendarID(locale.toLanguageTag())] return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
.replaceFirst("_.*", "")); } else {
return requestedCalType.equals(nativeCalType);
}
} }
private static Locale[] getSupportedNativeDigitLocales() { private static Locale[] getSupportedNativeDigitLocales() {
......
...@@ -611,7 +611,12 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterIm ...@@ -611,7 +611,12 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterIm
int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) { int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) {
if (pGetLocaleInfoEx) { if (pGetLocaleInfoEx) {
return pGetLocaleInfoEx((LPWSTR)langtag, type, data, buflen); if (wcscmp(L"und", (LPWSTR)langtag) == 0) {
// defaults to "en"
return pGetLocaleInfoEx(L"en", type, data, buflen);
} else {
return pGetLocaleInfoEx((LPWSTR)langtag, type, data, buflen);
}
} else { } else {
// If we ever wanted to support WinXP, we will need extra module from // If we ever wanted to support WinXP, we will need extra module from
// MS... // MS...
...@@ -622,7 +627,12 @@ int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buf ...@@ -622,7 +627,12 @@ int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buf
int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val) { int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val) {
if (pGetCalendarInfoEx) { if (pGetCalendarInfoEx) {
return pGetCalendarInfoEx((LPWSTR)langtag, id, reserved, type, data, buflen, val); if (wcscmp(L"und", (LPWSTR)langtag) == 0) {
// defaults to "en"
return pGetCalendarInfoEx(L"en", id, reserved, type, data, buflen, val);
} else {
return pGetCalendarInfoEx((LPWSTR)langtag, id, reserved, type, data, buflen, val);
}
} else { } else {
// If we ever wanted to support WinXP, we will need extra module from // If we ever wanted to support WinXP, we will need extra module from
// MS... // MS...
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册