8000986: Split java.util.spi.CalendarDataProvider into week parameters and field names portions
authorokutsu
Mon, 12 Nov 2012 11:12:29 +0900
changeset 14502 d63fed06fed4
parent 14501 10121b56420c
child 14503 0729d9e57ed5
8000986: Split java.util.spi.CalendarDataProvider into week parameters and field names portions Reviewed-by: naoto
jdk/make/java/java/FILES_java.gmk
jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
jdk/src/share/classes/java/util/Calendar.java
jdk/src/share/classes/java/util/spi/CalendarDataProvider.java
jdk/src/share/classes/java/util/spi/CalendarNameProvider.java
jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java
jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java
jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java
jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java
jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java
jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh
jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java
jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh
jdk/test/java/util/PluggableLocale/GenericTest.java
jdk/test/java/util/PluggableLocale/barprovider.jar
jdk/test/java/util/PluggableLocale/fooprovider.jar
jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java
jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java
jdk/test/java/util/PluggableLocale/providersrc/Makefile
jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider
--- a/jdk/make/java/java/FILES_java.gmk	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/make/java/java/FILES_java.gmk	Mon Nov 12 11:12:29 2012 +0900
@@ -206,6 +206,7 @@
             sun/util/locale/provider/BreakIteratorProviderImpl.java \
             sun/util/locale/provider/CalendarDataProviderImpl.java \
             sun/util/locale/provider/CalendarDataUtility.java \
+            sun/util/locale/provider/CalendarNameProviderImpl.java \
             sun/util/locale/provider/CollationRules.java \
             sun/util/locale/provider/CollatorProviderImpl.java \
             sun/util/locale/provider/CurrencyNameProviderImpl.java \
@@ -396,6 +397,7 @@
     java/util/prefs/Base64.java \
     java/util/prefs/XmlSupport.java \
     java/util/spi/CalendarDataProvider.java \
+    java/util/spi/CalendarNameProvider.java \
     java/util/spi/CurrencyNameProvider.java \
     java/util/spi/LocaleNameProvider.java \
     java/util/spi/LocaleServiceProvider.java \
--- a/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -41,6 +41,7 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReferenceArray;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.TimeZoneNameProvider;
@@ -324,6 +325,30 @@
             }
 
             @Override
+            public int getFirstDayOfWeek(Locale locale) {
+                return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);
+            }
+
+            @Override
+            public int getMinimalDaysInFirstWeek(Locale locale) {
+                return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);
+            }
+        };
+    }
+
+    public static CalendarNameProvider getCalendarNameProvider() {
+        return new CalendarNameProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return getSupportedCalendarLocales();
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                return isSupportedCalendarLocale(locale);
+            }
+
+            @Override
             public String getDisplayName(String calType, int field, int value,
                                          int style, Locale locale) {
                 return null;
@@ -334,16 +359,6 @@
                                          int field, int style, Locale locale) {
                 return null;
             }
-
-            @Override
-            public int getFirstDayOfWeek(Locale locale) {
-                return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);
-            }
-
-            @Override
-            public int getMinimalDaysInFirstWeek(Locale locale) {
-                return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);
-            }
         };
     }
 
--- a/jdk/src/share/classes/java/util/Calendar.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/java/util/Calendar.java	Mon Nov 12 11:12:29 2012 +0900
@@ -2699,12 +2699,9 @@
         /* try to get the Locale data from the cache */
         int[] data = cachedLocaleData.get(desiredLocale);
         if (data == null) {  /* cache miss */
-            LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CalendarDataProvider.class, desiredLocale);
-            CalendarDataProvider provider = adapter.getCalendarDataProvider();
             data = new int[2];
-            data[0] = provider.getFirstDayOfWeek(desiredLocale);
-            data[1] = provider.getMinimalDaysInFirstWeek(desiredLocale);
-            assert data[0] != 0 && data[1] != 0;
+            data[0] = CalendarDataUtility.retrieveFirstDayOfWeek(desiredLocale);
+            data[1] = CalendarDataUtility.retrieveMinimalDaysInFirstWeek(desiredLocale);
             cachedLocaleData.putIfAbsent(desiredLocale, data);
         }
         firstDayOfWeek = data[0];
--- a/jdk/src/share/classes/java/util/spi/CalendarDataProvider.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/java/util/spi/CalendarDataProvider.java	Mon Nov 12 11:12:29 2012 +0900
@@ -26,125 +26,15 @@
 package java.util.spi;
 
 import java.util.Calendar;
-import java.util.Map;
 import java.util.Locale;
 
 /**
- * An abstract class for service providers that provide localized {@link
- * Calendar} parameters and string representations (display names) of {@code
- * Calendar} field values.
- *
- * <p><a name="calendartypes"><b>Calendar Types</b></a>
- *
- * <p>Calendar types are used to specify calendar systems for which the {@link
- * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link
- * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide
- * calendar field value names. See {@link Calendar#getCalendarType()} for details.
- *
- * <p><b>Calendar Fields</b>
- *
- * <p>Calendar fields are specified with the constants defined in {@link
- * Calendar}. The following are calendar-common fields and their values to be
- * supported for each calendar system.
- *
- * <table style="border-bottom:1px solid" border="1" cellpadding="3" cellspacing="0" summary="Field values">
- *   <tr>
- *     <th>Field</th>
- *     <th>Value</th>
- *     <th>Description</th>
- *   </tr>
- *   <tr>
- *     <td valign="top">{@link Calendar#MONTH}</td>
- *     <td valign="top">{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}</td>
- *     <td>Month numbering is 0-based (e.g., 0 - January, ..., 11 -
- *         December). Some calendar systems have 13 months. Month
- *         names need to be supported in both the formatting and
- *         stand-alone forms if required by the supported locales. If there's
- *         no distinction in the two forms, the same names should be returned
- *         in both of the forms.</td>
- *   </tr>
- *   <tr>
- *     <td valign="top">{@link Calendar#DAY_OF_WEEK}</td>
- *     <td valign="top">{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}</td>
- *     <td>Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday,
- *         ..., 7 - Saturday).</td>
- *   </tr>
- *   <tr>
- *     <td valign="top">{@link Calendar#AM_PM}</td>
- *     <td valign="top">{@link Calendar#AM} to {@link Calendar#PM}</td>
- *     <td>0 - AM, 1 - PM</td>
- *   </tr>
- * </table>
- *
- * <p style="margin-top:20px">The following are calendar-specific fields and their values to be supported.
- *
- * <table style="border-bottom:1px solid" border="1" cellpadding="3" cellspacing="0" summary="Calendar type and field values">
- *   <tr>
- *     <th>Calendar Type</th>
- *     <th>Field</th>
- *     <th>Value</th>
- *     <th>Description</th>
- *   </tr>
- *   <tr>
- *     <td rowspan="2" valign="top">{@code "gregory"}</td>
- *     <td rowspan="2" valign="top">{@link Calendar#ERA}</td>
- *     <td>0</td>
- *     <td>{@link java.util.GregorianCalendar#BC} (BCE)</td>
- *   </tr>
- *   <tr>
- *     <td>1</td>
- *     <td>{@link java.util.GregorianCalendar#AD} (CE)</td>
- *   </tr>
- *   <tr>
- *     <td rowspan="2" valign="top">{@code "buddhist"}</td>
- *     <td rowspan="2" valign="top">{@link Calendar#ERA}</td>
- *     <td>0</td>
- *     <td>BC (BCE)</td>
- *   </tr>
- *   <tr>
- *     <td>1</td>
- *     <td>B.E. (Buddhist Era)</td>
- *   </tr>
- *   <tr>
- *     <td rowspan="6" valign="top">{@code "japanese"}</td>
- *     <td rowspan="5" valign="top">{@link Calendar#ERA}</td>
- *     <td>0</td>
- *     <td>Seireki (Before Meiji)</td>
- *   </tr>
- *   <tr>
- *     <td>1</td>
- *     <td>Meiji</td>
- *   </tr>
- *   <tr>
- *     <td>2</td>
- *     <td>Taisho</td>
- *   </tr>
- *   <tr>
- *     <td>3</td>
- *     <td>Showa</td>
- *   </tr>
- *   <tr>
- *     <td>4</td>
- *     <td >Heisei</td>
- *   </tr>
- *   <tr>
- *     <td>{@link Calendar#YEAR}</td>
- *     <td>1</td>
- *     <td>the first year in each era. It should be returned when a long
- *     style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is
- *     specified. See also the <a href="../../text/SimpleDateFormat.html#year">
- *     Year representation in {@code SimpleDateFormat}</a>.</td>
- *   </tr>
- * </table>
- *
- * <p>Calendar field value names for {@code "gregory"} must be consistent with
- * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}.
- *
- * <p>Time zone names are supported by {@link TimeZoneNameProvider}.
+ * An abstract class for service providers that provide locale-dependent {@link
+ * Calendar} parameters.
  *
  * @author Masayoshi Okutsu
  * @since 1.8
- * @see Locale#getUnicodeLocaleType(String)
+ * @see CalendarNameProvider
  */
 public abstract class CalendarDataProvider extends LocaleServiceProvider {
 
@@ -188,112 +78,4 @@
      * @see java.util.Calendar#getMinimalDaysInFirstWeek()
      */
     public abstract int getMinimalDaysInFirstWeek(Locale locale);
-
-    /**
-     * Returns the string representation (display name) of the calendar
-     * <code>field value</code> in the given <code>style</code> and
-     * <code>locale</code>.  If no string representation is
-     * applicable, <code>null</code> is returned.
-     *
-     * <p>{@code field} is a {@code Calendar} field index, such as {@link
-     * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET}, are <em>not</em> supported by this
-     * method. {@code null} must be returned if any time zone fields are
-     * specified.
-     *
-     * <p>{@code value} is the numeric representation of the {@code field} value.
-     * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid
-     * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}
-     * (inclusive).
-     *
-     * <p>{@code style} gives the style of the string representation. It is one
-     * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}),
-     * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT}
-     * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}.
-     *
-     * <p>For example, the following call will return {@code "Sunday"}.
-     * <pre>
-     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
-     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
-     * </pre>
-     *
-     * @param calendarType
-     *              the calendar type. (Any calendar type given by {@code locale}
-     *              is ignored.)
-     * @param field
-     *              the {@code Calendar} field index,
-     *              such as {@link Calendar#DAY_OF_WEEK}
-     * @param value
-     *              the value of the {@code Calendar field},
-     *              such as {@link Calendar#MONDAY}
-     * @param style
-     *              the string representation style: one of {@link
-     *              Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}),
-     *              {@link Calendar#SHORT_STANDALONE}, {@link
-     *              Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or
-     *              {@link Calendar#LONG_STANDALONE}
-     * @param locale
-     *              the desired locale
-     * @return the string representation of the {@code field value}, or {@code
-     *         null} if the string representation is not applicable or
-     *         the given calendar type is unknown
-     * @throws IllegalArgumentException
-     *         if {@code field} or {@code style} is invalid
-     * @throws NullPointerException if {@code locale} is {@code null}
-     * @see TimeZoneNameProvider
-     * @see java.util.Calendar#get(int)
-     * @see java.util.Calendar#getDisplayName(int, int, Locale)
-     */
-    public abstract String getDisplayName(String calendarType,
-                                          int field, int value,
-                                          int style, Locale locale);
-
-    /**
-     * Returns a {@code Map} containing all string representations (display
-     * names) of the {@code Calendar} {@code field} in the given {@code style}
-     * and {@code locale} and their corresponding field values.
-     *
-     * <p>{@code field} is a {@code Calendar} field index, such as {@link
-     * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET}, are <em>not</em> supported by this
-     * method. {@code null} must be returned if any time zone fields are specified.
-     *
-     * <p>{@code style} gives the style of the string representation. It must be
-     * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link
-     * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link
-     * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link
-     * Calendar#LONG_STANDALONE}.
-     *
-     * <p>For example, the following call will return a {@code Map} containing
-     * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link
-     * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY},
-     * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on.
-     * <pre>
-     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
-     * </pre>
-     *
-     * @param calendarType
-     *              the calendar type. (Any calendar type given by {@code locale}
-     *              is ignored.)
-     * @param field
-     *              the calendar field for which the display names are returned
-     * @param style
-     *              the style applied to the display names; one of
-     *              {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT}
-     *              ({@link Calendar#SHORT SHORT}), {@link
-     *              Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT}
-     *              ({@link Calendar#LONG LONG}), or {@link
-     *              Calendar#LONG_STANDALONE}.
-     * @param locale
-     *              the desired locale
-     * @return a {@code Map} containing all display names of {@code field} in
-     *         {@code style} and {@code locale} and their {@code field} values,
-     *         or {@code null} if no display names are defined for {@code field}
-     * @throws NullPointerException
-     *         if {@code locale} is {@code null}
-     * @see Calendar#getDisplayNames(int, int, Locale)
-     */
-    public abstract Map<String, Integer> getDisplayNames(String calendarType,
-                                                         int field, int style,
-                                                         Locale locale);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2012, 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 java.util.spi;
+
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * An abstract class for service providers that provide localized string
+ * representations (display names) of {@code Calendar} field values.
+ *
+ * <p><a name="calendartypes"><b>Calendar Types</b></a>
+ *
+ * <p>Calendar types are used to specify calendar systems for which the {@link
+ * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link
+ * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide
+ * calendar field value names. See {@link Calendar#getCalendarType()} for details.
+ *
+ * <p><b>Calendar Fields</b>
+ *
+ * <p>Calendar fields are specified with the constants defined in {@link
+ * Calendar}. The following are calendar-common fields and their values to be
+ * supported for each calendar system.
+ *
+ * <table style="border-bottom:1px solid" border="1" cellpadding="3" cellspacing="0" summary="Field values">
+ *   <tr>
+ *     <th>Field</th>
+ *     <th>Value</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td valign="top">{@link Calendar#MONTH}</td>
+ *     <td valign="top">{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}</td>
+ *     <td>Month numbering is 0-based (e.g., 0 - January, ..., 11 -
+ *         December). Some calendar systems have 13 months. Month
+ *         names need to be supported in both the formatting and
+ *         stand-alone forms if required by the supported locales. If there's
+ *         no distinction in the two forms, the same names should be returned
+ *         in both of the forms.</td>
+ *   </tr>
+ *   <tr>
+ *     <td valign="top">{@link Calendar#DAY_OF_WEEK}</td>
+ *     <td valign="top">{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}</td>
+ *     <td>Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday,
+ *         ..., 7 - Saturday).</td>
+ *   </tr>
+ *   <tr>
+ *     <td valign="top">{@link Calendar#AM_PM}</td>
+ *     <td valign="top">{@link Calendar#AM} to {@link Calendar#PM}</td>
+ *     <td>0 - AM, 1 - PM</td>
+ *   </tr>
+ * </table>
+ *
+ * <p style="margin-top:20px">The following are calendar-specific fields and their values to be supported.
+ *
+ * <table style="border-bottom:1px solid" border="1" cellpadding="3" cellspacing="0" summary="Calendar type and field values">
+ *   <tr>
+ *     <th>Calendar Type</th>
+ *     <th>Field</th>
+ *     <th>Value</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="2" valign="top">{@code "gregory"}</td>
+ *     <td rowspan="2" valign="top">{@link Calendar#ERA}</td>
+ *     <td>0</td>
+ *     <td>{@link java.util.GregorianCalendar#BC} (BCE)</td>
+ *   </tr>
+ *   <tr>
+ *     <td>1</td>
+ *     <td>{@link java.util.GregorianCalendar#AD} (CE)</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="2" valign="top">{@code "buddhist"}</td>
+ *     <td rowspan="2" valign="top">{@link Calendar#ERA}</td>
+ *     <td>0</td>
+ *     <td>BC (BCE)</td>
+ *   </tr>
+ *   <tr>
+ *     <td>1</td>
+ *     <td>B.E. (Buddhist Era)</td>
+ *   </tr>
+ *   <tr>
+ *     <td rowspan="6" valign="top">{@code "japanese"}</td>
+ *     <td rowspan="5" valign="top">{@link Calendar#ERA}</td>
+ *     <td>0</td>
+ *     <td>Seireki (Before Meiji)</td>
+ *   </tr>
+ *   <tr>
+ *     <td>1</td>
+ *     <td>Meiji</td>
+ *   </tr>
+ *   <tr>
+ *     <td>2</td>
+ *     <td>Taisho</td>
+ *   </tr>
+ *   <tr>
+ *     <td>3</td>
+ *     <td>Showa</td>
+ *   </tr>
+ *   <tr>
+ *     <td>4</td>
+ *     <td >Heisei</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@link Calendar#YEAR}</td>
+ *     <td>1</td>
+ *     <td>the first year in each era. It should be returned when a long
+ *     style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is
+ *     specified. See also the <a href="../../text/SimpleDateFormat.html#year">
+ *     Year representation in {@code SimpleDateFormat}</a>.</td>
+ *   </tr>
+ * </table>
+ *
+ * <p>Calendar field value names for {@code "gregory"} must be consistent with
+ * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}.
+ *
+ * <p>Time zone names are supported by {@link TimeZoneNameProvider}.
+ *
+ * @author Masayoshi Okutsu
+ * @since 1.8
+ * @see CalendarDataProvider
+ * @see Locale#getUnicodeLocaleType(String)
+ */
+public abstract class CalendarNameProvider extends LocaleServiceProvider {
+    /**
+     * Sole constructor. (For invocation by subclass constructors, typically
+     * implicit.)
+     */
+    protected CalendarNameProvider() {
+    }
+
+    /**
+     * Returns the string representation (display name) of the calendar
+     * <code>field value</code> in the given <code>style</code> and
+     * <code>locale</code>.  If no string representation is
+     * applicable, <code>null</code> is returned.
+     *
+     * <p>{@code field} is a {@code Calendar} field index, such as {@link
+     * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET}, are <em>not</em> supported by this
+     * method. {@code null} must be returned if any time zone fields are
+     * specified.
+     *
+     * <p>{@code value} is the numeric representation of the {@code field} value.
+     * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid
+     * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}
+     * (inclusive).
+     *
+     * <p>{@code style} gives the style of the string representation. It is one
+     * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}),
+     * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT}
+     * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}.
+     *
+     * <p>For example, the following call will return {@code "Sunday"}.
+     * <pre>
+     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
+     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
+     * </pre>
+     *
+     * @param calendarType
+     *              the calendar type. (Any calendar type given by {@code locale}
+     *              is ignored.)
+     * @param field
+     *              the {@code Calendar} field index,
+     *              such as {@link Calendar#DAY_OF_WEEK}
+     * @param value
+     *              the value of the {@code Calendar field},
+     *              such as {@link Calendar#MONDAY}
+     * @param style
+     *              the string representation style: one of {@link
+     *              Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}),
+     *              {@link Calendar#SHORT_STANDALONE}, {@link
+     *              Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or
+     *              {@link Calendar#LONG_STANDALONE}
+     * @param locale
+     *              the desired locale
+     * @return the string representation of the {@code field value}, or {@code
+     *         null} if the string representation is not applicable or
+     *         the given calendar type is unknown
+     * @throws IllegalArgumentException
+     *         if {@code field} or {@code style} is invalid
+     * @throws NullPointerException if {@code locale} is {@code null}
+     * @see TimeZoneNameProvider
+     * @see java.util.Calendar#get(int)
+     * @see java.util.Calendar#getDisplayName(int, int, Locale)
+     */
+    public abstract String getDisplayName(String calendarType,
+                                          int field, int value,
+                                          int style, Locale locale);
+
+    /**
+     * Returns a {@code Map} containing all string representations (display
+     * names) of the {@code Calendar} {@code field} in the given {@code style}
+     * and {@code locale} and their corresponding field values.
+     *
+     * <p>{@code field} is a {@code Calendar} field index, such as {@link
+     * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET}, are <em>not</em> supported by this
+     * method. {@code null} must be returned if any time zone fields are specified.
+     *
+     * <p>{@code style} gives the style of the string representation. It must be
+     * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link
+     * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link
+     * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link
+     * Calendar#LONG_STANDALONE}.
+     *
+     * <p>For example, the following call will return a {@code Map} containing
+     * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link
+     * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY},
+     * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on.
+     * <pre>
+     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
+     * </pre>
+     *
+     * @param calendarType
+     *              the calendar type. (Any calendar type given by {@code locale}
+     *              is ignored.)
+     * @param field
+     *              the calendar field for which the display names are returned
+     * @param style
+     *              the style applied to the display names; one of
+     *              {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT}
+     *              ({@link Calendar#SHORT SHORT}), {@link
+     *              Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT}
+     *              ({@link Calendar#LONG LONG}), or {@link
+     *              Calendar#LONG_STANDALONE}.
+     * @param locale
+     *              the desired locale
+     * @return a {@code Map} containing all display names of {@code field} in
+     *         {@code style} and {@code locale} and their {@code field} values,
+     *         or {@code null} if no display names are defined for {@code field}
+     * @throws NullPointerException
+     *         if {@code locale} is {@code null}
+     * @see Calendar#getDisplayNames(int, int, Locale)
+     */
+    public abstract Map<String, Integer> getDisplayNames(String calendarType,
+                                                         int field, int style,
+                                                         Locale locale);
+}
--- a/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Mon Nov 12 11:12:29 2012 +0900
@@ -38,6 +38,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
@@ -135,6 +136,10 @@
         return getLocaleServiceProvider(CalendarDataProvider.class);
     }
 
+    @Override
+    public CalendarNameProvider getCalendarNameProvider() {
+        return getLocaleServiceProvider(CalendarNameProvider.class);
+    }
 
     @Override
     public LocaleResources getLocaleResources(Locale locale) {
--- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -24,10 +24,9 @@
  */
 package sun.util.locale.provider;
 
+import java.util.Calendar;
 import static java.util.Calendar.*;
-import java.util.HashMap;
 import java.util.Locale;
-import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.spi.CalendarDataProvider;
@@ -59,115 +58,11 @@
     }
 
     @Override
-    public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
-        String name = null;
-        String key = getKey(calendarType, field, style);
-        if (key != null) {
-            ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
-            if (rb.containsKey(key)) {
-                String[] strings = rb.getStringArray(key);
-                if (strings.length > 0) {
-                    if (field == DAY_OF_WEEK || field == YEAR) {
-                        --value;
-                    }
-                    name = strings[value];
-                    // If name is empty in standalone, try its `format' style.
-                    if (name.length() == 0
-                            && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) {
-                        name = getDisplayName(calendarType, field, value,
-                                              style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT,
-                                              locale);
-                    }
-                }
-            }
-        }
-        return name;
-    }
-
-    @Override
-    public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
-        Map<String, Integer> names;
-        if (style == ALL_STYLES) {
-            names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale);
-            if (field != AM_PM) {
-                for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) {
-                    names.putAll(getDisplayNamesImpl(calendarType, field, st, locale));
-                }
-            }
-        } else {
-            // specific style
-            names = getDisplayNamesImpl(calendarType, field, style, locale);
-        }
-        return names.isEmpty() ? null : names;
-    }
-
-    private Map<String, Integer> getDisplayNamesImpl(String calendarType, int field,
-                                                     int style, Locale locale) {
-        String key = getKey(calendarType, field, style);
-        Map<String, Integer> map = new HashMap<>();
-        if (key != null) {
-            ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
-            if (rb.containsKey(key)) {
-                String[] strings = rb.getStringArray(key);
-                if (field == YEAR) {
-                    if (strings.length > 0) {
-                        map.put(strings[0], 1);
-                    }
-                } else {
-                    int base = (field == DAY_OF_WEEK) ? 1 : 0;
-                    for (int i = 0; i < strings.length; i++) {
-                        String name = strings[i];
-                        // Ignore any empty string (some standalone month names
-                        // are not defined)
-                        if (name.length() == 0) {
-                            continue;
-                        }
-                        map.put(name, base + i);
-                    }
-                }
-            }
-        }
-        return map;
-    }
-
-    @Override
     public Locale[] getAvailableLocales() {
         return LocaleProviderAdapter.toLocaleArray(langtags);
     }
 
     @Override
-    public boolean isSupportedLocale(Locale locale) {
-        if (Locale.ROOT.equals(locale)) {
-            return true;
-        }
-        String calendarType = null;
-        if (locale.hasExtensions()) {
-            calendarType = locale.getUnicodeLocaleType("ca");
-            locale = locale.stripExtensions();
-        }
-
-        if (calendarType != null) {
-            switch (calendarType) {
-            case "buddhist":
-            case "japanese":
-            case "gregory":
-                break;
-            default:
-                // Unknown calendar type
-                return false;
-            }
-        }
-        if (langtags.contains(locale.toLanguageTag())) {
-            return true;
-        }
-        if (type == LocaleProviderAdapter.Type.JRE) {
-            String oldname = locale.toString().replace('_', '-');
-            return langtags.contains(oldname);
-        }
-        return false;
-    }
-
-    @Override
     public Set<String> getAvailableLanguageTags() {
         return langtags;
     }
@@ -178,49 +73,6 @@
             String firstday = rb.getString(key);
             return Integer.parseInt(firstday);
         }
-        // Note that the base bundle of CLDR doesn't have the Calendar week parameters.
         return 0;
     }
-
-    private String getKey(String type, int field, int style) {
-        boolean standalone = (style & 0x8000) != 0;
-        style &= ~0x8000;
-
-        if ("gregory".equals(type)) {
-            type = null;
-        }
-
-        StringBuilder key = new StringBuilder();
-        switch (field) {
-        case ERA:
-            if (type != null) {
-                key.append(type).append('.');
-            }
-            if (style == SHORT) {
-                key.append("short.");
-            }
-            key.append("Eras");
-            break;
-
-        case YEAR:
-            key.append(type).append(".FirstYear");
-            break;
-
-        case MONTH:
-            if (standalone) {
-                key.append("standalone.");
-            }
-            key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames");
-            break;
-
-        case DAY_OF_WEEK:
-            key.append(style == SHORT ? "DayAbbreviations" : "DayNames");
-            break;
-
-        case AM_PM:
-            key.append("AmPmMarkers");
-            break;
-        }
-        return key.length() > 0 ? key.toString() : null;
-    }
 }
--- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java	Mon Nov 12 11:12:29 2012 +0900
@@ -25,9 +25,12 @@
 
 package sun.util.locale.provider;
 
+import java.util.Calendar;
+import static java.util.Calendar.*;
 import java.util.Locale;
 import java.util.Map;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 
 /**
  * {@code CalendarDataUtility} is a utility class for calling the
@@ -44,16 +47,32 @@
     private CalendarDataUtility() {
     }
 
+    public static int retrieveFirstDayOfWeek(Locale locale) {
+        LocaleServiceProviderPool pool =
+                LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
+        Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
+                                                locale, FIRST_DAY_OF_WEEK);
+        return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY;
+    }
+
+    public static int retrieveMinimalDaysInFirstWeek(Locale locale) {
+        LocaleServiceProviderPool pool =
+                LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
+        Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
+                                                locale, MINIMAL_DAYS_IN_FIRST_WEEK);
+        return (value != null && (value >= 1 && value <= 7)) ? value : 1;
+    }
+
     public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) {
         LocaleServiceProviderPool pool =
-                LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
+                LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
         return pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, id,
                                        field, value, style);
     }
 
     public static Map<String, Integer> retrieveFieldValueNames(String id, int field, int style, Locale locale) {
         LocaleServiceProviderPool pool =
-            LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
+            LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
         return pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, id, field, style);
     }
 
@@ -62,13 +81,13 @@
      * implementation.
      */
     private static class CalendarFieldValueNameGetter
-        implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarDataProvider,
+        implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarNameProvider,
                                                                    String> {
         private static final CalendarFieldValueNameGetter INSTANCE =
             new CalendarFieldValueNameGetter();
 
         @Override
-        public String getObject(CalendarDataProvider calendarDataProvider,
+        public String getObject(CalendarNameProvider calendarNameProvider,
                                 Locale locale,
                                 String requestID, // calendarType
                                 Object... params) {
@@ -76,7 +95,7 @@
             int field = (int) params[0];
             int value = (int) params[1];
             int style = (int) params[2];
-            return calendarDataProvider.getDisplayName(requestID, field, value, style, locale);
+            return calendarNameProvider.getDisplayName(requestID, field, value, style, locale);
         }
     }
 
@@ -85,20 +104,47 @@
      * implementation.
      */
     private static class CalendarFieldValueNamesMapGetter
-        implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarDataProvider,
+        implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarNameProvider,
                                                                    Map<String, Integer>> {
         private static final CalendarFieldValueNamesMapGetter INSTANCE =
             new CalendarFieldValueNamesMapGetter();
 
         @Override
-        public Map<String, Integer> getObject(CalendarDataProvider calendarDataProvider,
+        public Map<String, Integer> getObject(CalendarNameProvider calendarNameProvider,
                                               Locale locale,
                                               String requestID, // calendarType
                                               Object... params) {
             assert params.length == 2;
             int field = (int) params[0];
             int style = (int) params[1];
-            return calendarDataProvider.getDisplayNames(requestID, field, style, locale);
+            return calendarNameProvider.getDisplayNames(requestID, field, style, locale);
+        }
+    }
+
+     private static class CalendarWeekParameterGetter
+        implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarDataProvider,
+                                                                   Integer> {
+        private static final CalendarWeekParameterGetter INSTANCE =
+            new CalendarWeekParameterGetter();
+
+        @Override
+        public Integer getObject(CalendarDataProvider calendarDataProvider,
+                                 Locale locale,
+                                 String requestID,    // resource key
+                                 Object... params) {
+            assert params.length == 0;
+            int value;
+            switch (requestID) {
+            case FIRST_DAY_OF_WEEK:
+                value = calendarDataProvider.getFirstDayOfWeek(locale);
+                break;
+            case MINIMAL_DAYS_IN_FIRST_WEEK:
+                value = calendarDataProvider.getMinimalDaysInFirstWeek(locale);
+                break;
+            default:
+                throw new InternalError("invalid requestID: " + requestID);
+            }
+            return (value != 0) ? value : null;
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2012, 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 static java.util.Calendar.*;
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.spi.CalendarNameProvider;
+
+/**
+ * Concrete implementation of the  {@link java.util.spi.CalendarDataProvider
+ * CalendarDataProvider} class for the JRE LocaleProviderAdapter.
+ *
+ * @author Masayoshi Okutsu
+ * @author Naoto Sato
+ */
+public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags {
+    private final LocaleProviderAdapter.Type type;
+    private final Set<String> langtags;
+
+    public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
+        this.type = type;
+        this.langtags = langtags;
+    }
+
+    @Override
+    public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
+        String name = null;
+        String key = getKey(calendarType, field, style);
+        if (key != null) {
+            ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
+            if (rb.containsKey(key)) {
+                String[] strings = rb.getStringArray(key);
+                if (strings.length > 0) {
+                    if (field == DAY_OF_WEEK || field == YEAR) {
+                        --value;
+                    }
+                    name = strings[value];
+                    // If name is empty in standalone, try its `format' style.
+                    if (name.length() == 0
+                            && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) {
+                        name = getDisplayName(calendarType, field, value,
+                                              style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT,
+                                              locale);
+                    }
+                }
+            }
+        }
+        return name;
+    }
+
+    @Override
+    public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
+        Map<String, Integer> names;
+        if (style == ALL_STYLES) {
+            names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale);
+            if (field != AM_PM) {
+                for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) {
+                    names.putAll(getDisplayNamesImpl(calendarType, field, st, locale));
+                }
+            }
+        } else {
+            // specific style
+            names = getDisplayNamesImpl(calendarType, field, style, locale);
+        }
+        return names.isEmpty() ? null : names;
+    }
+
+    private Map<String, Integer> getDisplayNamesImpl(String calendarType, int field,
+                                                     int style, Locale locale) {
+        String key = getKey(calendarType, field, style);
+        Map<String, Integer> map = new TreeMap<>(LengthBasedComparator.INSTANCE);
+        if (key != null) {
+            ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
+            if (rb.containsKey(key)) {
+                String[] strings = rb.getStringArray(key);
+                if (field == YEAR) {
+                    if (strings.length > 0) {
+                        map.put(strings[0], 1);
+                    }
+                } else {
+                    int base = (field == DAY_OF_WEEK) ? 1 : 0;
+                    for (int i = 0; i < strings.length; i++) {
+                        String name = strings[i];
+                        // Ignore any empty string (some standalone month names
+                        // are not defined)
+                        if (name.length() == 0) {
+                            continue;
+                        }
+                        map.put(name, base + i);
+                    }
+                }
+            }
+        }
+        return map;
+    }
+
+    /**
+     * Comparator implementation for TreeMap which iterates keys from longest
+     * to shortest.
+     */
+    private static class LengthBasedComparator implements Comparator<String> {
+        private static final LengthBasedComparator INSTANCE = new LengthBasedComparator();
+
+        private LengthBasedComparator() {
+        }
+
+        @Override
+        public int compare(String o1, String o2) {
+            int n = o2.length() - o1.length();
+            return (n == 0) ? o1.compareTo(o2) : n;
+        }
+    }
+
+    @Override
+    public Locale[] getAvailableLocales() {
+        return LocaleProviderAdapter.toLocaleArray(langtags);
+    }
+
+    @Override
+    public boolean isSupportedLocale(Locale locale) {
+        if (Locale.ROOT.equals(locale)) {
+            return true;
+        }
+        String calendarType = null;
+        if (locale.hasExtensions()) {
+            calendarType = locale.getUnicodeLocaleType("ca");
+            locale = locale.stripExtensions();
+        }
+
+        if (calendarType != null) {
+            switch (calendarType) {
+            case "buddhist":
+            case "japanese":
+            case "gregory":
+                break;
+            default:
+                // Unknown calendar type
+                return false;
+            }
+        }
+        if (langtags.contains(locale.toLanguageTag())) {
+            return true;
+        }
+        if (type == LocaleProviderAdapter.Type.JRE) {
+            String oldname = locale.toString().replace('_', '-');
+            return langtags.contains(oldname);
+        }
+        return false;
+    }
+
+    @Override
+    public Set<String> getAvailableLanguageTags() {
+        return langtags;
+    }
+
+    private int getIntData(String key, Locale locale) {
+        ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getCalendarData(locale);
+        if (rb.containsKey(key)) {
+            String firstday = rb.getString(key);
+            return Integer.parseInt(firstday);
+        }
+        // Note that the base bundle of CLDR doesn't have the Calendar week parameters.
+        return 0;
+    }
+
+    private String getKey(String type, int field, int style) {
+        boolean standalone = (style & 0x8000) != 0;
+        style &= ~0x8000;
+
+        if ("gregory".equals(type)) {
+            type = null;
+        }
+
+        StringBuilder key = new StringBuilder();
+        switch (field) {
+        case ERA:
+            if (type != null) {
+                key.append(type).append('.');
+            }
+            if (style == SHORT) {
+                key.append("short.");
+            }
+            key.append("Eras");
+            break;
+
+        case YEAR:
+            key.append(type).append(".FirstYear");
+            break;
+
+        case MONTH:
+            if (standalone) {
+                key.append("standalone.");
+            }
+            key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames");
+            break;
+
+        case DAY_OF_WEEK:
+            key.append(style == SHORT ? "DayAbbreviations" : "DayNames");
+            break;
+
+        case AM_PM:
+            key.append("AmPmMarkers");
+            break;
+        }
+        return key.length() > 0 ? key.toString() : null;
+    }
+}
--- a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Mon Nov 12 11:12:29 2012 +0900
@@ -41,6 +41,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
@@ -101,6 +102,8 @@
             return (P) getTimeZoneNameProvider();
         case "CalendarDataProvider":
             return (P) getCalendarDataProvider();
+        case "CalendarNameProvider":
+            return (P) getCalendarNameProvider();
         default:
             throw new InternalError("should not come down here");
         }
@@ -117,6 +120,7 @@
     private volatile LocaleNameProvider localeNameProvider = null;
     private volatile TimeZoneNameProvider timeZoneNameProvider = null;
     private volatile CalendarDataProvider calendarDataProvider = null;
+    private volatile CalendarNameProvider calendarNameProvider = null;
 
     /*
      * Getter methods for java.text.spi.* providers
@@ -252,11 +256,9 @@
     @Override
     public CalendarDataProvider getCalendarDataProvider() {
         if (calendarDataProvider == null) {
-            Set<String> set = new HashSet<>();
-            set.addAll(getLanguageTagSet("FormatData"));
-            set.addAll(getLanguageTagSet("CalendarData"));
-            CalendarDataProvider provider = new CalendarDataProviderImpl(getAdapterType(),
-                                                                         set);
+            CalendarDataProvider provider;
+            provider = new CalendarDataProviderImpl(getAdapterType(),
+                                                    getLanguageTagSet("CalendarData"));
             synchronized (this) {
                 if (calendarDataProvider == null) {
                     calendarDataProvider = provider;
@@ -267,6 +269,21 @@
     }
 
     @Override
+    public CalendarNameProvider getCalendarNameProvider() {
+        if (calendarNameProvider == null) {
+            CalendarNameProvider provider;
+            provider = new CalendarNameProviderImpl(getAdapterType(),
+                                                    getLanguageTagSet("FormatData"));
+            synchronized (this) {
+                if (calendarNameProvider == null) {
+                    calendarNameProvider = provider;
+                }
+            }
+        }
+        return calendarNameProvider;
+    }
+
+    @Override
     public LocaleResources getLocaleResources(Locale locale) {
         LocaleResources lr = localeResourcesMap.get(locale);
         if (lr == null) {
--- a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Mon Nov 12 11:12:29 2012 +0900
@@ -38,6 +38,7 @@
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
@@ -387,6 +388,14 @@
      */
     public abstract CalendarDataProvider getCalendarDataProvider();
 
+    /**
+     * Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no
+     * CalendarNameProvider is available.
+     *
+     * @return a CalendarNameProvider
+     */
+    public abstract CalendarNameProvider getCalendarNameProvider();
+
     public abstract LocaleResources getLocaleResources(Locale locale);
 
     public abstract LocaleData getLocaleData();
--- a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java	Mon Nov 12 11:12:29 2012 +0900
@@ -28,11 +28,29 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import java.text.*;
-import java.text.spi.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.spi.*;
+import java.text.BreakIterator;
+import java.text.Collator;
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.spi.BreakIteratorProvider;
+import java.text.spi.CollatorProvider;
+import java.text.spi.DateFormatProvider;
+import java.text.spi.DateFormatSymbolsProvider;
+import java.text.spi.DecimalFormatSymbolsProvider;
+import java.text.spi.NumberFormatProvider;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
+import java.util.spi.CurrencyNameProvider;
+import java.util.spi.LocaleNameProvider;
+import java.util.spi.LocaleServiceProvider;
+import java.util.spi.TimeZoneNameProvider;
 
 /**
  * LocaleProviderAdapter implementation for the installed SPI implementations.
@@ -411,12 +429,39 @@
             assert cdp != null;
             return cdp.getMinimalDaysInFirstWeek(locale);
         }
+    }
+
+    static class CalendarNameProviderDelegate extends CalendarNameProvider
+                                       implements Delegate<CalendarNameProvider> {
+        private ConcurrentMap<Locale, CalendarNameProvider> map = new ConcurrentHashMap<>();
+
+        @Override
+        public void addImpl(CalendarNameProvider impl) {
+            for (Locale l : impl.getAvailableLocales()) {
+                map.put(l, impl);
+            }
+        }
+
+        @Override
+        public CalendarNameProvider getImpl(Locale locale) {
+            return SPILocaleProviderAdapter.getImpl(map, locale);
+        }
+
+        @Override
+        public Locale[] getAvailableLocales() {
+            return map.keySet().toArray(new Locale[0]);
+        }
+
+        @Override
+        public boolean isSupportedLocale(Locale locale) {
+            return map.containsKey(locale);
+        }
 
         @Override
         public String getDisplayName(String calendarType,
                                               int field, int value,
                                               int style, Locale locale) {
-            CalendarDataProvider cdp = getImpl(locale);
+            CalendarNameProvider cdp = getImpl(locale);
             assert cdp != null;
             return cdp.getDisplayName(calendarType, field, value, style, locale);
         }
@@ -425,7 +470,7 @@
         public Map<String, Integer> getDisplayNames(String calendarType,
                                                              int field, int style,
                                                              Locale locale) {
-            CalendarDataProvider cdp = getImpl(locale);
+            CalendarNameProvider cdp = getImpl(locale);
             assert cdp != null;
             return cdp.getDisplayNames(calendarType, field, style, locale);
         }
--- a/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -25,7 +25,12 @@
 package sun.util.locale.provider;
 
 import java.lang.ref.SoftReference;
-import java.text.*;
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
 import java.text.spi.DateFormatProvider;
 import java.text.spi.DateFormatSymbolsProvider;
 import java.text.spi.DecimalFormatSymbolsProvider;
@@ -34,12 +39,13 @@
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
+import java.util.ResourceBundle.Control;
 import java.util.Set;
-import java.util.ResourceBundle.Control;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReferenceArray;
 import java.util.spi.CalendarDataProvider;
+import java.util.spi.CalendarNameProvider;
 
 /**
  * LocaleProviderdapter implementation for the Windows locale data.
@@ -88,7 +94,7 @@
 
     private static final Set<Locale> supportedLocaleSet;
     static {
-        Set<Locale> tmpSet = new HashSet<Locale>();
+        Set<Locale> tmpSet = new HashSet<>();
         if (initialize()) {
             // Assuming the default locales do not include any extensions, so
             // no stripping is needed here.
@@ -258,7 +264,7 @@
 
                 if (ref == null || (patterns = ref.get()) == null) {
                     String langtag = locale.toLanguageTag();
-                    patterns = new AtomicReferenceArray<String>(NF_MAX+1);
+                    patterns = new AtomicReferenceArray<>(NF_MAX+1);
                     for (int i = 0; i <= NF_MAX; i++) {
                         patterns.compareAndSet(i, null, getNumberPattern(i, langtag));
                     }
@@ -330,18 +336,6 @@
             }
 
             @Override
-            public String getDisplayName(String calType, int field, int value,
-                                         int style, Locale locale) {
-                return null;
-            }
-
-            @Override
-            public Map<String, Integer> getDisplayNames(String calType,
-                                         int field, int style, Locale locale) {
-                return null;
-            }
-
-            @Override
             public int getFirstDayOfWeek(Locale locale) {
                 int first = getCalendarDataValue(
                                  removeExtensions(locale).toLanguageTag(),
@@ -360,6 +354,32 @@
         };
     }
 
+    public static CalendarNameProvider getCalendarNameProvider() {
+        return new CalendarNameProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return getSupportedCalendarLocales();
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                return isSupportedCalendarLocale(locale);
+            }
+
+            @Override
+            public String getDisplayName(String calType, int field, int value,
+                                         int style, Locale locale) {
+                return null;
+            }
+
+            @Override
+            public Map<String, Integer> getDisplayNames(String calType,
+                                         int field, int style, Locale locale) {
+                return null;
+            }
+        };
+    }
+
     private static String convertDateTimePattern(String winPattern) {
         String ret = winPattern.replaceAll("dddd", "EEEE");
         ret = ret.replaceAll("ddd", "EEE");
--- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java	Mon Nov 12 11:12:29 2012 +0900
@@ -36,17 +36,11 @@
  *
  * Test strategy:
  * com.bar.CalendarDataProviderImpl supports only ja_JP_kids locale. It returns
- * month names only in full-width digits, followed by "gatsu" in Hiragana if
- * it's a long style, and also returns unusual week parameter values, WEDNESDAY
- * - first day of week, 7 - minimal days in the first week.  The standalone
- * styles are used because DateFormatSymbols has precedence for the format
- * styles.
+ * unusual week parameter values, WEDNESDAY - first day of week, 7 - minimal
+ * days in the first week.
  *
  * A Calendar instance created with ja_JP_kids should use the week parameters
- * provided by com.bar.CalendarDataProviderImpl. Calendar.getDisplayName(s)
- * should be called with kids to get the month names provided by
- * com.bar.CalendarDataProviderImpl. Other display names should be the same as
- * what a Calendar constructed with ja_JP returns.
+ * provided by com.bar.CalendarDataProviderImpl.
  */
 public class CalendarDataProviderTest {
 
@@ -62,45 +56,6 @@
         // check the week parameters
         checkResult("firstDayOfWeek", kcal.getFirstDayOfWeek(), WEDNESDAY);
         checkResult("minimalDaysInFirstWeek", kcal.getMinimalDaysInFirstWeek(), 7);
-
-        // check month names and week day names
-        Map<String, Integer> mapAllStyles = new HashMap<>();
-        for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) {
-            // Check month names provided by com.bar.CalendarDataProviderImpl
-            Map<String, Integer> map = new HashMap<>();
-            for (int month = JANUARY; month <= DECEMBER; month++) {
-                kcal.set(DAY_OF_MONTH, 1);
-                kcal.set(MONTH, month);
-                kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions...
-                kcal.getTimeInMillis();
-                String name = kcal.getDisplayName(MONTH, style, kids);
-                checkResult("Month name",
-                            name,
-                            CalendarDataProviderImpl.toMonthName(kcal.get(MONTH) + 1, style));
-
-                // Builds the map with name to its integer value.
-                map.put(name, kcal.get(MONTH));
-            }
-            checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map",
-                        kcal.getDisplayNames(MONTH, style, kids), map);
-            mapAllStyles.putAll(map);
-            if (style == LONG_STANDALONE) {
-                checkResult("Short and long month names map",
-                            kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles);
-            }
-
-            // Check week names: kcal and jcal should return the same names and maps.
-            for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
-                kcal.set(DAY_OF_WEEK, dow);
-                jcal.setTimeInMillis(kcal.getTimeInMillis());
-                String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids);
-                checkResult("Day of week name", name,
-                                                jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN));
-            }
-            checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids),
-                                                   jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN));
-        }
-
     }
 
     private <T> void checkResult(String msg, T got, T expected) {
--- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh	Mon Nov 12 11:12:29 2012 +0900
@@ -23,6 +23,6 @@
 #!/bin/sh
 #
 # @test
-# @bug 7058206
+# @bug 7058207 8000986
 # @summary CalendarDataProvider tests
 # @run shell ExecTest.sh bar CalendarDataProviderTest true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+/*
+ *
+ */
+
+import java.text.*;
+import java.util.*;
+import static java.util.Calendar.*;
+import sun.util.locale.provider.*;
+import sun.util.resources.*;
+import com.bar.CalendarNameProviderImpl;
+
+/**
+ * Test case for CalendarNameProvider.
+ *
+ * Test strategy:
+ * com.bar.CalendarNameProviderImpl supports only ja_JP_kids locale. It returns
+ * month names only in full-width digits, followed by "gatsu" in Hiragana if
+ * it's a long style. The standalone styles are used because DateFormatSymbols
+ * has precedence for the format styles.
+ *
+ * Calendar.getDisplayName(s) should be called with kids to get the month
+ * names provided by com.bar.CalendarNameProviderImpl. Other display names
+ * should be the same as what a Calendar constructed with ja_JP returns.
+ */
+public class CalendarNameProviderTest {
+
+    public static void main(String[] s) {
+        new CalendarNameProviderTest().test();
+    }
+
+    void test() {
+        Locale kids = new Locale("ja", "JP", "kids"); // test provider's supported locale
+        Calendar kcal = Calendar.getInstance(kids);
+        Calendar jcal = Calendar.getInstance(Locale.JAPAN);
+
+        // check month names and week day names
+        Map<String, Integer> mapAllStyles = new HashMap<>();
+        for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) {
+            // Check month names provided by com.bar.CalendarNameProviderImpl
+            Map<String, Integer> map = new HashMap<>();
+            for (int month = JANUARY; month <= DECEMBER; month++) {
+                kcal.set(DAY_OF_MONTH, 1);
+                kcal.set(MONTH, month);
+                kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions...
+                kcal.getTimeInMillis();
+                String name = kcal.getDisplayName(MONTH, style, kids);
+                checkResult("Month name",
+                            name,
+                            CalendarNameProviderImpl.toMonthName(kcal.get(MONTH) + 1, style));
+
+                // Builds the map with name to its integer value.
+                map.put(name, kcal.get(MONTH));
+            }
+            checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map",
+                        kcal.getDisplayNames(MONTH, style, kids), map);
+            mapAllStyles.putAll(map);
+            if (style == LONG_STANDALONE) {
+                checkResult("Short and long month names map",
+                            kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles);
+            }
+
+            // Check week names: kcal and jcal should return the same names and maps.
+            for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+                kcal.set(DAY_OF_WEEK, dow);
+                jcal.setTimeInMillis(kcal.getTimeInMillis());
+                String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids);
+                checkResult("Day of week name", name,
+                                                jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN));
+            }
+            checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids),
+                                                   jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN));
+        }
+
+    }
+
+    private <T> void checkResult(String msg, T got, T expected) {
+        if (!expected.equals(got)) {
+            String s = String.format("%s: got='%s', expected='%s'", msg, got, expected);
+            throw new RuntimeException(s);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,27 @@
+# 
+# Copyright (c) 2012, 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.
+# 
+# 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.
+#
+
+# @test
+# @bug 8000986
+# @summary CalendarNameProvider tests
+# @run shell ExecTest.sh bar CalendarNameProviderTest true
--- a/jdk/test/java/util/PluggableLocale/GenericTest.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/test/java/util/PluggableLocale/GenericTest.java	Mon Nov 12 11:12:29 2012 +0900
@@ -42,6 +42,7 @@
     com.bar.LocaleNameProviderImpl localeNP = new com.bar.LocaleNameProviderImpl();
     com.bar.TimeZoneNameProviderImpl tzNP = new com.bar.TimeZoneNameProviderImpl();
     com.bar.CalendarDataProviderImpl calDataP = new com.bar.CalendarDataProviderImpl();
+    com.bar.CalendarNameProviderImpl calNameP = new com.bar.CalendarNameProviderImpl();
 
     public static void main(String[] s) {
         new GenericTest();
@@ -73,6 +74,7 @@
         expected.addAll(Arrays.asList(localeNP.getAvailableLocales()));
         expected.addAll(Arrays.asList(tzNP.getAvailableLocales()));
         expected.addAll(Arrays.asList(calDataP.getAvailableLocales()));
+        expected.addAll(Arrays.asList(calNameP.getAvailableLocales()));
         if (!result.equals(expected)) {
             throw new RuntimeException("Locale.getAvailableLocales() does not return the union of locales: diff="
                                        + getDiff(result, expected));
Binary file jdk/test/java/util/PluggableLocale/barprovider.jar has changed
Binary file jdk/test/java/util/PluggableLocale/fooprovider.jar has changed
--- a/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -48,65 +48,7 @@
     }
 
     @Override
-    public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
-        if (calendarType == null || locale == null) {
-            throw new NullPointerException();
-        }
-        if (!Utils.supportsLocale(Arrays.asList(avail), locale)) {
-            throw new IllegalArgumentException("locale is not one of available locales: "+ locale);
-        }
-        if (field != MONTH) {
-            return null;
-        }
-        return toMonthName(value + 1, style);
-    }
-
-    @Override
-    public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
-        if (calendarType == null || locale == null) {
-            throw new NullPointerException();
-        }
-        if (!Utils.supportsLocale(Arrays.asList(avail), locale)) {
-            throw new IllegalArgumentException("locale is not one of available locales: " + locale);
-        }
-        if (field != MONTH) {
-            return null;
-        }
-        Map<String, Integer> map = new HashMap<>();
-        if (style == LONG_STANDALONE) {
-            style = LONG;
-        } else if (style == SHORT_STANDALONE) {
-            style = SHORT;
-        }
-        for (int month = JANUARY; month <= DECEMBER; month++) {
-            if (style == ALL_STYLES || style == LONG) {
-                map.put(toMonthName(month + 1, LONG), month);
-            }
-            if (style == ALL_STYLES || style == SHORT) {
-                map.put(toMonthName(month + 1, SHORT), month);
-            }
-        }
-        return map;
-    }
-
-    @Override
     public Locale[] getAvailableLocales() {
         return avail.clone();
     }
-
-    // month is 1-based.
-    public static String toMonthName(int month, int style) {
-        StringBuilder sb = new StringBuilder();
-        if (month >= 10) {
-            sb.append((char)(FULLWIDTH_ZERO + 1));
-            sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10)));
-        } else {
-            sb.appendCodePoint((char)(FULLWIDTH_ZERO + month));
-        }
-        if (style == SHORT || style == SHORT_STANDALONE) {
-            return sb.toString(); // full-width digit(s)
-        }
-        sb.append("\u304c\u3064"); // + "gatsu" in Hiragana
-        return sb.toString();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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 com.bar;
+
+import com.foobar.Utils;
+import java.util.Arrays;
+import static java.util.Calendar.*;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.spi.CalendarNameProvider;
+
+public class CalendarNameProviderImpl extends CalendarNameProvider {
+    static final char FULLWIDTH_ZERO = '\uff10';
+    static final Locale[] avail = {
+        new Locale("ja", "JP", "kids"),
+    };
+
+    @Override
+    public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
+        if (calendarType == null || locale == null) {
+            throw new NullPointerException();
+        }
+        if (!Utils.supportsLocale(Arrays.asList(avail), locale)) {
+            throw new IllegalArgumentException("locale is not one of available locales: "+ locale);
+        }
+        if (field != MONTH) {
+            return null;
+        }
+        return toMonthName(value + 1, style);
+    }
+
+    @Override
+    public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
+        if (calendarType == null || locale == null) {
+            throw new NullPointerException();
+        }
+        if (!Utils.supportsLocale(Arrays.asList(avail), locale)) {
+            throw new IllegalArgumentException("locale is not one of available locales: " + locale);
+        }
+        if (field != MONTH) {
+            return null;
+        }
+        Map<String, Integer> map = new HashMap<>();
+        if (style == LONG_STANDALONE) {
+            style = LONG;
+        } else if (style == SHORT_STANDALONE) {
+            style = SHORT;
+        }
+        for (int month = JANUARY; month <= DECEMBER; month++) {
+            if (style == ALL_STYLES || style == LONG) {
+                map.put(toMonthName(month + 1, LONG), month);
+            }
+            if (style == ALL_STYLES || style == SHORT) {
+                map.put(toMonthName(month + 1, SHORT), month);
+            }
+        }
+        return map;
+    }
+
+    @Override
+    public Locale[] getAvailableLocales() {
+        return avail.clone();
+    }
+
+    // month is 1-based.
+    public static String toMonthName(int month, int style) {
+        StringBuilder sb = new StringBuilder();
+        if (month >= 10) {
+            sb.append((char)(FULLWIDTH_ZERO + 1));
+            sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10)));
+        } else {
+            sb.appendCodePoint((char)(FULLWIDTH_ZERO + month));
+        }
+        if (style == SHORT || style == SHORT_STANDALONE) {
+            return sb.toString(); // full-width digit(s)
+        }
+        sb.append("\u304c\u3064"); // + "gatsu" in Hiragana
+        return sb.toString();
+    }
+}
--- a/jdk/test/java/util/PluggableLocale/providersrc/Makefile	Sun Nov 11 10:05:37 2012 +0000
+++ b/jdk/test/java/util/PluggableLocale/providersrc/Makefile	Mon Nov 12 11:12:29 2012 +0900
@@ -20,7 +20,8 @@
 	java.util.spi.CurrencyNameProvider \
 	java.util.spi.TimeZoneNameProvider \
 	java.util.spi.LocaleNameProvider \
-	java.util.spi.CalendarDataProvider
+	java.util.spi.CalendarDataProvider \
+	java.util.spi.CalendarNameProvider
 
 FOOFILES_JAVA = \
     BreakIteratorProviderImpl.java \
@@ -39,6 +40,7 @@
     TimeZoneNameProviderImpl.java \
     LocaleNameProviderImpl.java \
     CalendarDataProviderImpl.java \
+    CalendarNameProviderImpl.java \
     Utils.java
 
 BARFILES_PROPERTIES = \
@@ -68,3 +70,8 @@
 	cp $(BARFILES_PROPERTIES) $(BARDIR)/com/bar
 	rm -f $(DESTDIR)/barprovider.jar
 	$(BINDIR)/jar  cvf $(DESTDIR)/barprovider.jar -C $(BARDIR) .
+
+clean:
+	rm -rf $(BARDIR) $(FOODIR)
+
+.PHONY: all clean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider	Mon Nov 12 11:12:29 2012 +0900
@@ -0,0 +1,7 @@
+#
+#
+#
+# fully-qualified name of the java.util.spi.CalendarNameProvider
+# implementation class
+#
+com.bar.CalendarNameProviderImpl