# HG changeset patch # User mchung # Date 1513898329 28800 # Node ID b6fc9a193661c7273e4edb5d9b79c209bc6e695f # Parent b95b08f3e1a83fc8f7b56a2e6f65f9948732c8a2 8193767: Improve javadoc in ResourceBundle working with modules Reviewed-by: alanb, naoto diff -r b95b08f3e1a8 -r b6fc9a193661 src/java.base/share/classes/java/util/ResourceBundle.java --- a/src/java.base/share/classes/java/util/ResourceBundle.java Sat Jan 13 16:47:11 2018 +0000 +++ b/src/java.base/share/classes/java/util/ResourceBundle.java Thu Dec 21 15:18:49 2017 -0800 @@ -204,58 +204,70 @@ * known concrete subclasses {@code ListResourceBundle} and * {@code PropertyResourceBundle} are thread-safe. * - *
A {@linkplain ResourceBundleProvider resource bundle provider} can + * provide resource bundles in any format such XML which replaces the need + * of {@link Control ResourceBundle.Control}. + * + *
The {@code getBundle} factory methods with no {@code Control} parameter + * locate and load resource bundles from + * {@linkplain ResourceBundleProvider service providers}. + * It may continue the search as if calling {@link Module#getResourceAsStream(String)} + * to find the named resource from a given module and calling + * {@link ClassLoader#getResourceAsStream(String)}; refer to + * the specification of the {@code getBundle} method for details. + * Only non-encapsulated resource bundles of "{@code java.class}" + * or "{@code java.properties}" format are searched. * - *
If the caller module is a + * + * resource bundle provider, it does not fall back to the + * class loader search. + * + *
- * In named modules, the loaded service providers for the given base name are - * used to load resource bundles. If no service provider is available, or if - * none of the service providers returns a resource bundle and the caller module - * doesn't have its own service provider, the {@code getBundle} factory method - * searches for resource bundles that are local in the caller module and that - * are visible to the class loader of the caller module. The resource bundle - * formats for local module searching are "java.class" and "java.properties". + * A common format of resource bundles is in {@linkplain PropertyResourceBundle + * .properties} file format. Typically {@code .properties} resource bundles + * are packaged in a JAR file. Resource bundle only JAR file can be readily + * deployed as an + * automatic module. For example, if the JAR file contains the + * entry "{@code p/q/Foo_ja.properties}" and no {@code .class} entry, + * when resolved and defined as an automatic module, no package is derived + * for this module. This allows resource bundles in {@code .properties} + * format packaged in one or more JAR files that may contain entries + * in the same directory and can be resolved successfully as + * automatic modules. * *
{@link ResourceBundle.Control} is designed for an application deployed + * in an unnamed module, for example to support resource bundles in + * non-standard formats or package localized resources in a non-traditional + * convention. {@link ResourceBundleProvider} is the replacement for + * {@code ResourceBundle.Control} when migrating to modules. + * {@code UnsupportedOperationException} will be thrown when a factory + * method that takes the {@code ResourceBundle.Control} parameter is called. + * *
For the {@code getBundle} factory * methods that take no {@link Control} instance, their default behavior of resource bundle loading @@ -815,14 +835,10 @@ /** * Gets a resource bundle using the specified base name, the default locale, - * and the caller's class loader. Calling this method is equivalent to calling + * and the caller module. Calling this method is equivalent to calling *
- *- * except thatgetBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())
, + *getBundle(baseName, Locale.getDefault(), callerModule)
, *
getClassLoader()
is run with the security
- * privileges of ResourceBundle
.
- * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
- * for a complete description of the search and instantiation strategy.
*
* @param baseName the base name of the resource bundle, a fully qualified class name
* @exception java.lang.NullPointerException
@@ -830,6 +846,9 @@
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and the default locale
+ *
+ * @see Resource Bundle Search and Loading Strategy
+ * @see Resource Bundles and Named Modules
*/
@CallerSensitive
public static final ResourceBundle getBundle(String baseName)
@@ -887,14 +906,10 @@
/**
* Gets a resource bundle using the specified base name and locale,
- * and the caller's class loader. Calling this method is equivalent to calling
+ * and the caller module. Calling this method is equivalent to calling
* - *- * except thatgetBundle(baseName, locale, this.getClass().getClassLoader())
, + *getBundle(baseName, locale, callerModule)
, *
getClassLoader()
is run with the security
- * privileges of ResourceBundle
.
- * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
- * for a complete description of the search and instantiation strategy.
*
* @param baseName
* the base name of the resource bundle, a fully qualified class name
@@ -905,6 +920,9 @@
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
+ *
+ * @see Resource Bundle Search and Loading Strategy
+ * @see Resource Bundles and Named Modules
*/
@CallerSensitive
public static final ResourceBundle getBundle(String baseName,
@@ -922,19 +940,6 @@
* getBundle(baseName, Locale.getDefault(), module)
*
*
- * Resource bundles in named modules may be encapsulated. When
- * the resource bundle is loaded from a provider, the caller module
- * must have an appropriate uses clause in its module descriptor
- * to declare that the module uses implementations of
- * {@code Resource bundles in named modules may be encapsulated. When
- * the resource bundle is loaded from a provider, the caller module
+ * the resource bundle is loaded from a
+ * {@linkplain ResourceBundleProvider service provider}, the caller module
* must have an appropriate uses clause in its module descriptor
- * to declare that the module uses implementations of
- * {@code This method behaves the same as calling
- * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
- * default instance of {@link Control} unless another {@link Control} is
- * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
+ * When this method is called from a named module and the given
+ * loader is the class loader of the caller module, this is equivalent
+ * to calling:
+ * The following describes the default
- * behavior.
+ * behavior. The following describes the default behavior.
*
*
- * Resource bundles in a named module are private to that module. If
- * the caller is in a named module, this method will find resource bundles
- * from the service providers of {@link java.util.spi.ResourceBundleProvider}
- * if any. Otherwise, it will load the resource bundles that are visible to
- * the given {@code loader} (refer to the
- * Resource Bundles in Named Modules section
- * for details).
- * If the caller is in a named module and the given {@code loader} is
- * different than the caller's class loader, or if the caller is not in
- * a named module, this method will not find resource bundles from named
- * modules.
+ * Resource Bundle Search and Loading Strategy
*
* Note:The {@link ResourceBundle.Control} is designed for an application deployed
+ * in an unnamed module, for example to support resource bundles in
+ * non-standard formats or package localized resources in a non-traditional
+ * convention. {@link ResourceBundleProvider} is the replacement for
+ * {@code ResourceBundle.Control} when migrating to modules.
+ * {@code UnsupportedOperationException} will be thrown when a factory
+ * method that takes the {@code ResourceBundle.Control} parameter is called.
*
* In addition to the callback methods, the {@link
* #toBundleName(String, Locale) toBundleName} and {@link
@@ -2501,8 +2516,8 @@
* }
*
*
- * @apiNote {@code ResourceBundle.Control} is not supported
- * in named modules. If the {@code ResourceBundle.getBundle} method with
+ * @apiNote {@code ResourceBundle.Control} is not supported
+ * in named modules. If the {@code ResourceBundle.getBundle} method with
* a {@code ResourceBundle.Control} is called in a named module, the method
* will throw an {@link UnsupportedOperationException}. Any service providers
* of {@link ResourceBundleControlProvider} are ignored in named modules.
diff -r b95b08f3e1a8 -r b6fc9a193661 src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java
--- a/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java Sat Jan 13 16:47:11 2018 +0000
+++ b/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java Thu Dec 21 15:18:49 2017 -0800
@@ -45,42 +45,46 @@
*
*
* Resource bundles can be packaged in one or more
- * named modules, bundle modules. The consumer of the
+ * named modules, service provider modules. The consumer of the
* resource bundle is the one calling {@link ResourceBundle#getBundle(String)}.
* In order for the consumer module to load a resource bundle
* "{@code com.example.app.MyResources}" provided by another module,
* it will use the {@linkplain java.util.ServiceLoader service loader}
- * mechanism. A service interface named "{@code com.example.app.MyResourcesProvider}"
- * must be defined and a bundle provider module will provide an
- * implementation class of "{@code com.example.app.MyResourcesProvider}"
+ * mechanism. A service interface named "{@code com.example.app.spi.MyResourcesProvider}"
+ * must be defined and a service provider module will provide an
+ * implementation class of "{@code com.example.app.spi.MyResourcesProvider}"
* as follows:
*
- *
- * For example, if the base name is "com.example.app.MyResources",
- * {@code com.example.app.spi.MyResourcesProvider} will be the provider service type:
- *
- * This providers's {@link #getBundle(String, Locale) getBundle} method is called
- * through the resource bundle loading process instead of {@link
- * java.util.ResourceBundle.Control#newBundle(String, Locale, String, ClassLoader, boolean)
- * ResourceBundle.Control.newBundle()}. Refer to {@link ResourceBundle} for
- * details.
+ * A provider can provide more than one services, each of which is a service
+ * for a resource bundle of a different base name.
+ *
+ * {@link AbstractResourceBundleProvider}
+ * provides the basic implementation for {@code ResourceBundleProvider}
+ * and a subclass can override the {@link
+ * AbstractResourceBundleProvider#toBundleName(String, Locale) toBundleName}
+ * method to return a provider-specific location of the resource to be loaded,
+ * for example, per-language package.
+ * A provider can override {@link #getBundle ResourceBundleProvider.getBundle}
+ * method for example to only search the known supported locales or
+ * return resource bundles in other formats such as XML.
+ *
+ * The module declaration of this provider module specifies the following
+ * directive:
+ *
+ *
+ * otherwise, this is equivalent to calling:
+ *
+ * getBundle(baseName, targetLocale, callerModule)
+ *
+ * where {@code control} is the default instance of {@link Control} unless
+ * a {@code Control} instance is provided by
+ * {@link ResourceBundleControlProvider} SPI. Refer to the
* description of modifying the default
- * behavior.
- *
- *
+ * getBundle(baseName, targetLocale, loader, control)
+ *
getBundle
uses the base name, the specified locale, and
* the default locale (obtained from {@link java.util.Locale#getDefault()
@@ -1201,7 +1208,7 @@
*
* baseName
argument should be a fully
* qualified class name. However, for compatibility with earlier versions,
- * Sun's Java SE Runtime Environments do not verify this, and so it is
+ * Java SE Runtime Environments do not verify this, and so it is
* possible to access PropertyResourceBundle
s by specifying a
* path name (using "/") instead of a fully qualified class name (using
* ".").
@@ -1248,7 +1255,7 @@
*
* @apiNote If the caller module is a named module and the given
* {@code loader} is the caller module's class loader, this method is
- * equivalent to {@code getBundle(baseName, locale)}; otherwise, it will not
+ * equivalent to {@code getBundle(baseName, locale)}; otherwise, it may not
* find resource bundles from named modules.
* Use {@link #getBundle(String, Locale, Module)} to load resource bundles
* on behalf on a specific module instead.
@@ -1264,6 +1271,7 @@
* @since 1.2
* @revised 9
* @spec JPMS
+ * @see Resource Bundles and Named Modules
*/
@CallerSensitive
public static ResourceBundle getBundle(String baseName, Locale locale,
@@ -1278,9 +1286,9 @@
/**
* Returns a resource bundle using the specified base name, target
- * locale, class loader and control. Unlike the {@linkplain
- * #getBundle(String, Locale, ClassLoader) getBundle
- * factory methods with no control
argument}, the given
+ * locale, class loader and control. Unlike the {@link
+ * #getBundle(String, Locale, ClassLoader) getBundle}
+ * factory methods with no {@code control} argument, the given
* control
specifies how to locate and instantiate resource
* bundles. Conceptually, the bundle loading process with the given
* control
is performed in the following steps.
@@ -2365,7 +2373,14 @@
* the callback methods provides the information necessary for the
* factory methods to perform the default behavior.
- * Note that this class is not supported in named modules.
+ *
+ *
+ * }}
*
- * @see
- * Resource Bundles in Named Modules
- * @see
- * ResourceBundleProvider Service Providers
+ * Refer to {@link ResourceBundleProvider} for details.
*
+ * @see
+ * Resource Bundles and Named Modules
* @since 9
* @spec JPMS
+
*/
public abstract class AbstractResourceBundleProvider implements ResourceBundleProvider {
private static final JavaUtilResourceBundleAccess RB_ACCESS =
diff -r b95b08f3e1a8 -r b6fc9a193661 src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java
--- a/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java Sat Jan 13 16:47:11 2018 +0000
+++ b/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java Thu Dec 21 15:18:49 2017 -0800
@@ -29,33 +29,117 @@
import java.util.ResourceBundle;
/**
- * {@code ResourceBundleProvider} is a provider interface that is used for
- * loading resource bundles for named modules. Implementation classes of
- * this interface are loaded with {@link java.util.ServiceLoader ServiceLoader}
- * during a call to the
- * {@link ResourceBundle#getBundle(String, Locale, ClassLoader)
- * ResourceBundle.getBundle} method. The provider service type is determined by
- * {@code
- * import com.example.app.MyResourcesProvider;
+ *
+ * {@code import com.example.app.spi.MyResourcesProvider;
* class MyResourcesProviderImpl extends AbstractResourceBundleProvider
* implements MyResourcesProvider
* {
+ * public MyResourcesProviderImpl() {
+ * super("java.properties");
+ * }
+ * // this provider maps the resource bundle to per-language package
* protected String toBundleName(String baseName, Locale locale) {
- * // return the bundle name per the naming of the resource bundle
- * :
+ * return "p." + locale.getLanguage() + "." + baseName;
* }
*
* public ResourceBundle getBundle(String baseName, Locale locale) {
- * // this module only provides bundles in french
+ * // this module only provides bundles in French
* if (locale.equals(Locale.FRENCH)) {
* return super.getBundle(baseName, locale);
* }
+ * // otherwise return null
* return null;
* }
- * }
Developing resource bundle services
*
- * {@code
+ * A service for a resource bundle of a given {@code baseName} must have
+ * a fully-qualified class name of the form:
+ *
+ *
+ *
+ * {@code
+ *
+ * The service type is in a {@code spi} subpackage as it may be packaged in
+ * a module separate from the resource bundle providers.
+ * For example, the service for a resource bundle named
+ * {@code com.example.app.MyResources} must be
+ * {@code com.example.app.spi.MyResourcesProvider}:
+ *
+ *
+ * {@code package com.example.app.spi;
* public interface MyResourcesProvider extends ResourceBundleProvider {
* }
- * }
+ * }Deploying resource bundle service providers
+ *
+ * Resource bundles can be deployed in one or more service providers
+ * in modules. For example, a provider for a service
+ * named "{@code com.example.app.spi.MyResourcesProvider}"
+ * has the following implementation class:
+ *
+ *
+ *
+ * This example provides "{@code com.example.app.MyResources}"
+ * resource bundle of the French locale. Traditionally resource bundles of
+ * all locales are packaged in the same package as the resource bundle base name.
+ * When deploying resource bundles in more than one modules and two modules
+ * containing a package of the same name, split package,
+ * is not supported, resource bundles in each module can be packaged in
+ * a different package as shown in this example where this provider packages
+ * the resource bundles in per-language package, i.e. {@code com.example.app.fr}
+ * for French locale.
*
- *
+ * {@code import com.example.app.spi.MyResourcesProvider;
+ * class MyResourcesProviderImpl extends AbstractResourceBundleProvider
+ * implements MyResourcesProvider
+ * {
+ * public MyResourcesProviderImpl() {
+ * super("java.properties");
+ * }
+ * // this provider maps the resource bundle to per-language package
+ * protected String toBundleName(String baseName, Locale locale) {
+ * return "p." + locale.getLanguage() + "." + baseName;
+ * }
+ *
+ * public ResourceBundle getBundle(String baseName, Locale locale) {
+ * // this module only provides bundles in French
+ * if (locale.equals(Locale.FRENCH)) {
+ * return super.getBundle(baseName, locale);
+ * }
+ * // otherwise return null
+ * return null;
+ * }
+ * }}
+ * provides com.example.app.spi.MyResourcesProvider with com.example.impl.MyResourcesProviderImpl;
+ *
+ *
+ * Obtaining resource bundles from providers
*
- * @see
- * Resource Bundles in Named Modules
- * @see
- * ResourceBundleProvider Service Providers
+ * The module declaration of the consumer module that calls one of the
+ * {@code ResourceBundle.getBundle} factory methods to obtain a resource
+ * bundle from service providers must specify the following directive:
+ *
+ * uses com.example.app.spi.MyResourcesProvider;
+ *
+ *
+ * {@link ResourceBundle#getBundle(String, Locale)
+ * ResourceBundle.getBundle("com.example.app.MyResource", locale)}
+ * locates and loads the providers for {@code com.example.app.spi.MyResourcesProvider}
+ * service and then invokes {@link #getBundle(String, Locale)
+ * ResourceBundleProvider.getBundle("com.example.app.MyResource", locale)} to
+ * find the resource bundle of the given base name and locale.
+ * If the consumer module is a resource bundle service provider for
+ * {@code com.example.app.spi.MyResourcesProvider}, {@code ResourceBundle.getBundle}
+ * will locate resource bundles only from service providers.
+ * Otherwise, {@code ResourceBundle.getBundle} may continue the search of
+ * the resource bundle in other modules and class path per the specification
+ * of the {@code ResourceBundle.getBundle} method being called.
+ *
+ * @see AbstractResourceBundleProvider
+ * @see
+ * Resource Bundles and Named Modules
+ * @see java.util.ServiceLoader
* @since 9
* @spec JPMS
*/