8013839: Enhance Logger API for handling of resource bundles
4814565: (rb) add method to get basename from a ResourceBundle
Summary: adds Logger.setResourceBundle(ResourceBundle) and ResourceBundle.getBaseBundleName()
Reviewed-by: mchung, naoto
--- a/jdk/src/share/classes/java/util/ResourceBundle.java Wed Oct 16 17:19:09 2013 +0200
+++ b/jdk/src/share/classes/java/util/ResourceBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -311,6 +311,24 @@
private static final ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
/**
+ * Returns the base name of this bundle, if known, or {@code null} if unknown.
+ *
+ * If not null, then this is the value of the {@code baseName} parameter
+ * that was passed to the {@code ResourceBundle.getBundle(...)} method
+ * when the resource bundle was loaded.
+ *
+ * @return The base name of the resource bundle, as provided to and expected
+ * by the {@code ResourceBundle.getBundle(...)} methods.
+ *
+ * @see #getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+ *
+ * @since 1.8
+ */
+ public String getBaseBundleName() {
+ return name;
+ }
+
+ /**
* The parent bundle of this bundle.
* The parent bundle is searched by {@link #getObject getObject}
* when this bundle does not contain a particular resource.
--- a/jdk/src/share/classes/java/util/logging/Logger.java Wed Oct 16 17:19:09 2013 +0200
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Oct 16 20:47:30 2013 +0200
@@ -88,17 +88,21 @@
* the LogRecord to its output Handlers. By default, loggers also
* publish to their parent's Handlers, recursively up the tree.
* <p>
- * Each Logger may have a ResourceBundle name associated with it.
- * The named bundle will be used for localizing logging messages.
- * If a Logger does not have its own ResourceBundle name, then
- * it will inherit the ResourceBundle name from its parent,
- * recursively up the tree.
+ * Each Logger may have a {@code ResourceBundle} associated with it.
+ * The {@code ResourceBundle} may be specified by name, using the
+ * {@link #getLogger(java.lang.String, java.lang.String)} factory
+ * method, or by value - using the {@link
+ * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method.
+ * This bundle will be used for localizing logging messages.
+ * If a Logger does not have its own {@code ResourceBundle} or resource bundle
+ * name, then it will inherit the {@code ResourceBundle} or resource bundle name
+ * from its parent, recursively up the tree.
* <p>
* Most of the logger output methods take a "msg" argument. This
* msg argument may be either a raw value or a localization key.
* During formatting, if the logger has (or inherits) a localization
- * ResourceBundle and if the ResourceBundle has a mapping for the msg
- * string, then the msg string is replaced by the localized value.
+ * {@code ResourceBundle} and if the {@code ResourceBundle} has a mapping for
+ * the msg string, then the msg string is replaced by the localized value.
* Otherwise the original msg string is used. Typically, formatters use
* java.text.MessageFormat style formatting to format parameters, so
* for example a format string "{0} {1}" would format two parameters
@@ -131,10 +135,30 @@
logger.log(Level.FINER, DiagnosisMessages::systemHealthStatus);
</code></pre>
* <p>
- * When mapping ResourceBundle names to ResourceBundles, the Logger
- * will first try to use the Thread's ContextClassLoader. If that
- * is null it will try the
- * {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader} instead.
+ * When looking for a {@code ResourceBundle}, the logger will first look at
+ * whether a bundle was specified using {@link
+ * #setResourceBundle(java.util.ResourceBundle) setResourceBundle}, and then
+ * only whether a resource bundle name was specified through the {@link
+ * #getLogger(java.lang.String, java.lang.String) getLogger} factory method.
+ * If no {@code ResourceBundle} or no resource bundle name is found,
+ * then it will use the nearest {@code ResourceBundle} or resource bundle
+ * name inherited from its parent tree.<br>
+ * When a {@code ResourceBundle} was inherited or specified through the
+ * {@link
+ * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method, then
+ * that {@code ResourceBundle} will be used. Otherwise if the logger only
+ * has or inherited a resource bundle name, then that resource bundle name
+ * will be mapped to a {@code ResourceBundle} object, using the default Locale
+ * at the time of logging.
+ * <br><a name="ResourceBundleMapping"/>When mapping resource bundle names to
+ * {@code ResourceBundle} objects, the logger will first try to use the
+ * Thread's {@linkplain java.lang.Thread#getContextClassLoader() context class
+ * loader} to map the given resource bundle name to a {@code ResourceBundle}.
+ * If the thread context class loader is {@code null}, it will try the
+ * {@linkplain java.lang.ClassLoader#getSystemClassLoader() system class loader}
+ * instead. If the {@code ResourceBundle} is still not found, it will use the
+ * class loader of the first caller of the {@link
+ * #getLogger(java.lang.String, java.lang.String) getLogger} factory method.
* <p>
* Formatting (including localization) is the responsibility of
* the output Handler, which will typically call a Formatter.
@@ -154,7 +178,7 @@
* <li><p>
* There are a set of "logrb" method (for "log with resource bundle")
* that are like the "logp" method, but also take an explicit resource
- * bundle name for use in localizing the log message.
+ * bundle object for use in localizing the log message.
* <li><p>
* There are convenience methods for tracing method entries (the
* "entering" methods), method returns (the "exiting" methods) and
@@ -198,18 +222,20 @@
private String name;
private final CopyOnWriteArrayList<Handler> handlers =
new CopyOnWriteArrayList<>();
- private String resourceBundleName;
+ private String resourceBundleName; // Base name of the bundle.
+ private ResourceBundle userBundle; // Bundle set through setResourceBundle.
private volatile boolean useParentHandlers = true;
private volatile Filter filter;
private boolean anonymous;
+ // Cache to speed up behavior of findResourceBundle:
private ResourceBundle catalog; // Cached resource bundle
private String catalogName; // name associated with catalog
private Locale catalogLocale; // locale associated with catalog
// The fields relating to parent-child relationships and levels
// are managed under a separate lock, the treeLock.
- private static Object treeLock = new Object();
+ private static final Object treeLock = new Object();
// We keep weak references from parents to children, but strong
// references from children to parents.
private volatile Logger parent; // our nearest parent.
@@ -372,6 +398,7 @@
static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck");
private static boolean getBooleanProperty(final String key) {
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ @Override
public String run() {
return System.getProperty(key);
}
@@ -579,11 +606,18 @@
/**
* Retrieve the localization resource bundle for this
- * logger for the current default locale. Note that if
- * the result is null, then the Logger will use a resource
- * bundle inherited from its parent.
+ * logger.
+ * This method will return a {@code ResourceBundle} that was either
+ * set by the {@link
+ * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method or
+ * <a href="#ResourceBundleMapping">mapped from the
+ * the resource bundle name</a> set via the {@link
+ * Logger#getLogger(java.lang.String, java.lang.String) getLogger} factory
+ * method for the current default locale.
+ * <br>Note that if the result is {@code null}, then the Logger will use a resource
+ * bundle or resource bundle name inherited from its parent.
*
- * @return localization bundle (may be null)
+ * @return localization bundle (may be {@code null})
*/
public ResourceBundle getResourceBundle() {
return findResourceBundle(getResourceBundleName(), true);
@@ -591,10 +625,16 @@
/**
* Retrieve the localization resource bundle name for this
- * logger. Note that if the result is null, then the Logger
- * will use a resource bundle name inherited from its parent.
+ * logger.
+ * This is either the name specified through the {@link
+ * #getLogger(java.lang.String, java.lang.String) getLogger} factory method,
+ * or the {@linkplain ResourceBundle#getBaseBundleName() base name} of the
+ * ResourceBundle set through {@link
+ * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method.
+ * <br>Note that if the result is {@code null}, then the Logger will use a resource
+ * bundle or resource bundle name inherited from its parent.
*
- * @return localization bundle name (may be null)
+ * @return localization bundle name (may be {@code null})
*/
public String getResourceBundleName() {
return resourceBundleName;
@@ -665,10 +705,11 @@
// resource bundle and then call "void log(LogRecord)".
private void doLog(LogRecord lr) {
lr.setLoggerName(name);
- String ebname = getEffectiveResourceBundleName();
- if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
+ final ResourceBundle bundle = getEffectiveResourceBundle();
+ final String ebname = getEffectiveResourceBundleName();
+ if (ebname != null && bundle != null) {
lr.setResourceBundleName(ebname);
- lr.setResourceBundle(findResourceBundle(ebname, true));
+ lr.setResourceBundle(bundle);
}
log(lr);
}
@@ -1000,6 +1041,16 @@
log(lr);
}
+ // Private support method for logging for "logrb" methods.
+ private void doLog(LogRecord lr, ResourceBundle rb) {
+ lr.setLoggerName(name);
+ if (rb != null) {
+ lr.setResourceBundleName(rb.getBaseBundleName());
+ lr.setResourceBundle(rb);
+ }
+ log(lr);
+ }
+
/**
* Log a message, specifying source class, method, and resource bundle name
* with no arguments.
@@ -1018,7 +1069,11 @@
* @param bundleName name of resource bundle to localize msg,
* can be null
* @param msg The string message (or a key in the message catalog)
+ * @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
+ * java.lang.String, java.util.ResourceBundle, java.lang.String,
+ * java.lang.Object...)} instead.
*/
+ @Deprecated
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg) {
if (!isLoggable(level)) {
@@ -1049,7 +1104,11 @@
* can be null
* @param msg The string message (or a key in the message catalog)
* @param param1 Parameter to the log message.
+ * @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
+ * java.lang.String, java.util.ResourceBundle, java.lang.String,
+ * java.lang.Object...)} instead
*/
+ @Deprecated
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Object param1) {
if (!isLoggable(level)) {
@@ -1082,7 +1141,11 @@
* can be null.
* @param msg The string message (or a key in the message catalog)
* @param params Array of parameters to the message
+ * @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
+ * java.lang.String, java.util.ResourceBundle, java.lang.String,
+ * java.lang.Object...)} instead.
*/
+ @Deprecated
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Object params[]) {
if (!isLoggable(level)) {
@@ -1096,6 +1159,41 @@
}
/**
+ * Log a message, specifying source class, method, and resource bundle,
+ * with an optional list of message parameters.
+ * <p>
+ * If the logger is currently enabled for the given message
+ * level then a corresponding LogRecord is created and forwarded
+ * to all the registered output Handler objects.
+ * <p>
+ * The {@code msg} string is localized using the given resource bundle.
+ * If the resource bundle is {@code null}, then the {@code msg} string is not
+ * localized.
+ * <p>
+ * @param level One of the message level identifiers, e.g., SEVERE
+ * @param sourceClass Name of the class that issued the logging request
+ * @param sourceMethod Name of the method that issued the logging request
+ * @param bundle Resource bundle to localize {@code msg},
+ * can be {@code null}.
+ * @param msg The string message (or a key in the message catalog)
+ * @param params Parameters to the message (optional, may be none).
+ * @since 1.8
+ */
+ public void logrb(Level level, String sourceClass, String sourceMethod,
+ ResourceBundle bundle, String msg, Object... params) {
+ if (!isLoggable(level)) {
+ return;
+ }
+ LogRecord lr = new LogRecord(level, msg);
+ lr.setSourceClassName(sourceClass);
+ lr.setSourceMethodName(sourceMethod);
+ if (params != null && params.length != 0) {
+ lr.setParameters(params);
+ }
+ doLog(lr, bundle);
+ }
+
+ /**
* Log a message, specifying source class, method, and resource bundle name,
* with associated Throwable information.
* <p>
@@ -1119,7 +1217,11 @@
* can be null
* @param msg The string message (or a key in the message catalog)
* @param thrown Throwable associated with log message.
+ * @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
+ * java.lang.String, java.util.ResourceBundle, java.lang.String,
+ * java.lang.Throwable)} instead.
*/
+ @Deprecated
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Throwable thrown) {
if (!isLoggable(level)) {
@@ -1132,6 +1234,43 @@
doLog(lr, bundleName);
}
+ /**
+ * Log a message, specifying source class, method, and resource bundle,
+ * with associated Throwable information.
+ * <p>
+ * If the logger is currently enabled for the given message
+ * level then the given arguments are stored in a LogRecord
+ * which is forwarded to all registered output handlers.
+ * <p>
+ * The {@code msg} string is localized using the given resource bundle.
+ * If the resource bundle is {@code null}, then the {@code msg} string is not
+ * localized.
+ * <p>
+ * Note that the thrown argument is stored in the LogRecord thrown
+ * property, rather than the LogRecord parameters property. Thus it is
+ * processed specially by output Formatters and is not treated
+ * as a formatting parameter to the LogRecord message property.
+ * <p>
+ * @param level One of the message level identifiers, e.g., SEVERE
+ * @param sourceClass Name of the class that issued the logging request
+ * @param sourceMethod Name of the method that issued the logging request
+ * @param bundle Resource bundle to localize {@code msg},
+ * can be {@code null}
+ * @param msg The string message (or a key in the message catalog)
+ * @param thrown Throwable associated with the log message.
+ * @since 1.8
+ */
+ public void logrb(Level level, String sourceClass, String sourceMethod,
+ ResourceBundle bundle, String msg, Throwable thrown) {
+ if (!isLoggable(level)) {
+ return;
+ }
+ LogRecord lr = new LogRecord(level, msg);
+ lr.setSourceClassName(sourceClass);
+ lr.setSourceMethodName(sourceMethod);
+ lr.setThrown(thrown);
+ doLog(lr, bundle);
+ }
//======================================================================
// Start of convenience methods for logging method entries and returns.
@@ -1610,6 +1749,7 @@
private static ResourceBundle findSystemResourceBundle(final Locale locale) {
// the resource bundle is in a restricted package
return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
+ @Override
public ResourceBundle run() {
try {
return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
@@ -1650,7 +1790,10 @@
Locale currentLocale = Locale.getDefault();
// Normally we should hit on our simple one entry cache.
- if (catalog != null && currentLocale.equals(catalogLocale)
+ if (userBundle != null &&
+ name.equals(resourceBundleName)) {
+ return userBundle;
+ } else if (catalog != null && currentLocale.equals(catalogLocale)
&& name.equals(catalogName)) {
return catalog;
}
@@ -1738,6 +1881,45 @@
}
/**
+ * Sets a resource bundle on this logger.
+ * All messages will be logged using the given resource bundle for its
+ * specific {@linkplain ResourceBundle#getLocale locale}.
+ * @param bundle The resource bundle that this logger shall use.
+ * @throws NullPointerException if the given bundle is {@code null}.
+ * @throws IllegalArgumentException if the given bundle doesn't have a
+ * {@linkplain ResourceBundle#getBaseBundleName base name},
+ * or if this logger already has a resource bundle set but
+ * the given bundle has a different base name.
+ * @throws SecurityException if a security manager exists and if
+ * the caller does not have LoggingPermission("control").
+ * @since 1.8
+ */
+ public void setResourceBundle(ResourceBundle bundle) {
+ checkPermission();
+
+ // Will throw NPE if bundle is null.
+ final String baseName = bundle.getBaseBundleName();
+
+ // bundle must have a name
+ if (baseName == null || baseName.isEmpty()) {
+ throw new IllegalArgumentException("resource bundle must have a name");
+ }
+
+ synchronized (this) {
+ final boolean canReplaceResourceBundle = resourceBundleName == null
+ || resourceBundleName.equals(baseName);
+
+ if (!canReplaceResourceBundle) {
+ throw new IllegalArgumentException("can't replace resource bundle");
+ }
+
+
+ userBundle = bundle;
+ resourceBundleName = baseName;
+ }
+ }
+
+ /**
* Return the parent for this Logger.
* <p>
* This method returns the nearest extant parent in the namespace.
@@ -1813,7 +1995,7 @@
// we didn't have a previous parent
ref = manager.new LoggerWeakRef(this);
}
- ref.setParentRef(new WeakReference<Logger>(parent));
+ ref.setParentRef(new WeakReference<>(parent));
parent.kids.add(ref);
// As a result of the reparenting, the effective level
@@ -1895,4 +2077,30 @@
}
+ private ResourceBundle getEffectiveResourceBundle() {
+ Logger target = this;
+ if (SYSTEM_LOGGER_RB_NAME.equals(resourceBundleName)) return null;
+ ResourceBundle localRB = getResourceBundle();
+ if (localRB != null) {
+ return localRB;
+ }
+
+ while (target != null) {
+ final ResourceBundle rb = target.userBundle;
+ if (rb != null) {
+ return rb;
+ }
+ final String rbn = target.getResourceBundleName();
+ if (rbn != null) {
+ if (!SYSTEM_LOGGER_RB_NAME.equals(rbn)) {
+ return findResourceBundle(rbn, true);
+ } else {
+ return null;
+ }
+ }
+ target = target.getParent();
+ }
+ return null;
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/getBaseBundleName/TestGetBaseBundleName.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.util.Collections;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+/**
+ * @test
+ * @bug 4814565
+ * @summary tests ResourceBundle.getBaseBundleName();
+ * @build TestGetBaseBundleName resources.ListBundle resources.ListBundle_fr
+ * @run main TestGetBaseBundleName
+ * @author danielfuchs
+ */
+public class TestGetBaseBundleName {
+
+ final static String PROPERTY_BUNDLE_NAME = "resources/PropertyBundle";
+ final static String LIST_BUNDLE_NAME = "resources.ListBundle";
+
+ public static String getBaseName(ResourceBundle bundle) {
+ return bundle == null ? null : bundle.getBaseBundleName();
+ }
+
+ public static void main(String... args) throws Exception {
+
+ Locale defaultLocale = Locale.getDefault();
+ System.out.println("Default locale is: " + defaultLocale);
+ for (String baseName : new String[] {
+ PROPERTY_BUNDLE_NAME,
+ LIST_BUNDLE_NAME
+ }) {
+ ResourceBundle bundle = ResourceBundle.getBundle(baseName);
+ System.out.println(getBaseName(bundle));
+ if (!Locale.ROOT.equals(bundle.getLocale())) {
+ throw new RuntimeException("Unexpected locale: "
+ + bundle.getLocale());
+ }
+ if (!baseName.equals(getBaseName(bundle))) {
+ throw new RuntimeException("Unexpected base name: "
+ + getBaseName(bundle));
+ }
+ Locale.setDefault(Locale.FRENCH);
+ try {
+ ResourceBundle bundle_fr = ResourceBundle.getBundle(baseName);
+ if (!Locale.FRENCH.equals(bundle_fr.getLocale())) {
+ throw new RuntimeException("Unexpected locale: "
+ + bundle_fr.getLocale());
+ }
+ if (!baseName.equals(getBaseName(bundle_fr))) {
+ throw new RuntimeException("Unexpected base name: "
+ + getBaseName(bundle_fr));
+ }
+ } finally {
+ Locale.setDefault(defaultLocale);
+ }
+ }
+
+ final ResourceBundle bundle = new ResourceBundle() {
+ @Override
+ protected Object handleGetObject(String key) {
+ if ("dummy".equals(key)) return "foo";
+ throw new MissingResourceException("Missing key",
+ this.getClass().getName(), key);
+ }
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(java.util.Arrays.asList(
+ new String[] {"dummy"}));
+ }
+ };
+
+ if (getBaseName(bundle) != null) {
+ throw new RuntimeException("Expected null baseName, got "
+ + getBaseName(bundle));
+ }
+
+ final ResourceBundle bundle2 = new ResourceBundle() {
+ @Override
+ protected Object handleGetObject(String key) {
+ if ("dummy".equals(key)) return "foo";
+ throw new MissingResourceException("Missing key",
+ this.getClass().getName(), key);
+ }
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(java.util.Arrays.asList(
+ new String[] {"dummy"}));
+ }
+
+ @Override
+ public String getBaseBundleName() {
+ return this.getClass().getName();
+ }
+
+
+ };
+
+ if (!bundle2.getClass().getName().equals(getBaseName(bundle2))) {
+ throw new RuntimeException("Expected "
+ + bundle2.getClass().getName() + ", got "
+ + getBaseName(bundle2));
+ }
+
+ ResourceBundle propertyBundle = new PropertyResourceBundle(
+ TestGetBaseBundleName.class.getResourceAsStream(
+ PROPERTY_BUNDLE_NAME+".properties"));
+
+ if (getBaseName(propertyBundle) != null) {
+ throw new RuntimeException("Expected null baseName, got "
+ + getBaseName(propertyBundle));
+ }
+
+ ResourceBundle listBundle = new resources.ListBundle_fr();
+ if (getBaseName(listBundle) != null) {
+ throw new RuntimeException("Expected null baseName, got "
+ + getBaseName(listBundle));
+ }
+
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/getBaseBundleName/resources/ListBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "foo" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/getBaseBundleName/resources/ListBundle_fr.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle_fr extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "toto" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/getBaseBundleName/resources/PropertyBundle.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 20013, 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.
+#
+dummy=foo
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/getBaseBundleName/resources/PropertyBundle_fr.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+dummy=toto
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/logrb/TestLogrbResourceBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.util.Arrays;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.ResourceBundle;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import resources.ListBundle;
+
+/**
+ * @test
+ * @bug 8013839
+ * @summary tests Logger.logrb(..., ResourceBundle);
+ * @build TestLogrbResourceBundle resources.ListBundle resources.ListBundle_fr
+ * @run main TestLogrbResourceBundle
+ * @author danielfuchs
+ */
+public class TestLogrbResourceBundle {
+
+ final static String LIST_BUNDLE_NAME = "resources.ListBundle";
+ final static String PROPERTY_BUNDLE_NAME = "resources.PropertyBundle";
+
+ /**
+ * A dummy handler class that we can use to check the bundle/bundle name
+ * that was present in the last LogRecord instance published.
+ */
+ static final class TestHandler extends Handler {
+ ResourceBundle lastBundle = null;
+ String lastBundleName = null;
+ Object[] lastParams = null;
+ Throwable lastThrown = null;
+ String lastMessage = null;
+ @Override
+ public void publish(LogRecord record) {
+ lastBundle = record.getResourceBundle();
+ lastBundleName = record.getResourceBundleName();
+ lastParams = record.getParameters();
+ lastThrown = record.getThrown();
+ lastMessage = record.getMessage();
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+ }
+
+ /**
+ * We're going to do the same test with each of the different new logrb
+ * forms.
+ * <ul>
+ * <li> LOGRB_NO_ARGS: calling logrb with no message argument.
+ * <li> LOGRB_SINGLE_ARG: calling logrb with a single message argument.
+ * <li> LOGRB_ARG_ARRAY: calling logrb with an array of message arguments.
+ * <li> LOGRB_VARARGS: calling logrb with a variable list of message arguments.
+ * <li> LOGRB_THROWABLE: calling logrb with an exception.
+ * </ul>
+ */
+ private static enum TestCase {
+ LOGRB_NO_ARGS, LOGRB_SINGLE_ARG, LOGRB_ARG_ARRAY, LOGRB_VARARGS, LOGRB_THROWABLE;
+
+ public void logrb(Logger logger, ResourceBundle bundle) {
+ switch(this) {
+ case LOGRB_NO_ARGS:
+ logger.logrb(Level.CONFIG,
+ TestLogrbResourceBundle.class.getName(),
+ "main", bundle, "dummy");
+ break;
+ case LOGRB_SINGLE_ARG:
+ logger.logrb(Level.CONFIG,
+ TestLogrbResourceBundle.class.getName(),
+ "main", bundle, "dummy", "bar");
+ break;
+ case LOGRB_ARG_ARRAY:
+ logger.logrb(Level.CONFIG,
+ TestLogrbResourceBundle.class.getName(),
+ "main", bundle, "dummy",
+ new Object[] { "bar", "baz"} );
+ break;
+ case LOGRB_VARARGS:
+ logger.logrb(Level.CONFIG,
+ TestLogrbResourceBundle.class.getName(),
+ "main", bundle, "dummy",
+ "bar", "baz" );
+ break;
+ case LOGRB_THROWABLE:
+ logger.logrb(Level.CONFIG,
+ TestLogrbResourceBundle.class.getName(),
+ "main", bundle, "dummy",
+ new Exception("dummy exception") );
+ break;
+ default:
+ }
+ }
+
+ /**
+ * Checks that the last published logged record had the expected data.
+ * @param handler the TestHandler through which the record was published.
+ */
+ public void checkLogged(TestHandler handler) {
+ checkLogged(handler.lastMessage, handler.lastParams, handler.lastThrown);
+ }
+
+ private void checkLogged(String message, Object[] parameters, Throwable thrown) {
+ switch(this) {
+ case LOGRB_NO_ARGS:
+ if ("dummy".equals(message) && thrown == null
+ && (parameters == null || parameters.length == 0)) {
+ return; // OK: all was as expected.
+ }
+ break;
+ case LOGRB_SINGLE_ARG:
+ if ("dummy".equals(message) && thrown == null
+ && parameters != null
+ && parameters.length == 1
+ && "bar".equals(parameters[0])) {
+ return; // OK: all was as expected.
+ }
+ break;
+ case LOGRB_VARARGS:
+ case LOGRB_ARG_ARRAY:
+ if ("dummy".equals(message) && thrown == null
+ && parameters != null
+ && parameters.length > 1
+ && Arrays.deepEquals(new Object[] { "bar", "baz"},
+ parameters)) {
+ return; // OK: all was as expected.
+ }
+ break;
+ case LOGRB_THROWABLE:
+ if ("dummy".equals(message) && thrown != null
+ && thrown.getClass() == Exception.class
+ && "dummy exception".equals(thrown.getMessage())) {
+ return; // OK: all was as expected.
+ }
+ break;
+ default:
+ }
+
+ // We had some unexpected stuff: throw exception.
+ throw new RuntimeException(this + ": "
+ + "Unexpected content in last published log record: "
+ + "\n\tmessage=\"" + message + "\""
+ + "\n\tparameters=" + Arrays.toString(parameters)
+ + "\n\tthrown=" + thrown);
+ }
+ }
+
+ static String getBaseName(ResourceBundle bundle) {
+ return bundle == null ? null : bundle.getBaseBundleName();
+ }
+
+ public static void main(String... args) throws Exception {
+
+ Locale defaultLocale = Locale.getDefault();
+
+ final ResourceBundle bundle = ResourceBundle.getBundle(LIST_BUNDLE_NAME);
+ final ResourceBundle bundle_fr =
+ ResourceBundle.getBundle(LIST_BUNDLE_NAME, Locale.FRENCH);
+ final ResourceBundle propertyBundle = ResourceBundle.getBundle(PROPERTY_BUNDLE_NAME);
+ final ResourceBundle propertyBundle_fr =
+ ResourceBundle.getBundle(PROPERTY_BUNDLE_NAME, Locale.FRENCH);
+ Logger foobar = Logger.getLogger("foo.bar");
+ final TestHandler handler = new TestHandler();
+ foobar.addHandler(handler);
+ foobar.setLevel(Level.CONFIG);
+
+ final ResourceBundle anonBundle = new ListBundle();
+ try {
+ // First we're going to call logrb on a logger that
+ // has no bundle set...
+
+ // For each possible logrb form...
+ for (TestCase test : TestCase.values()) {
+ // For various resource bundles
+ for (ResourceBundle b : new ResourceBundle[] {
+ anonBundle, bundle, bundle_fr, propertyBundle,
+ anonBundle, null, propertyBundle_fr,
+ }) {
+ // Prints the resource bundle base name (can be null,
+ // we don't enforce non-null names in logrb.
+ final String baseName = getBaseName(b);
+ System.out.println("Testing " + test + " with " + baseName);
+
+ // log in the 'foobar' logger using bundle 'b'
+ test.logrb(foobar, b);
+
+ // check that the correct bundle was set in the published
+ // LogRecord
+ if (handler.lastBundle != b) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler.lastBundle);
+ }
+
+ // check that the correct bundle name was set in the published
+ // LogRecord
+ if (!Objects.equals(handler.lastBundleName, baseName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler.lastBundleName);
+ }
+
+ // check that calling foobar.logrb() had no side effect on
+ // the bundle used by foobar. foobar should still have no
+ // bundle set.
+ if (foobar.getResourceBundle() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (foobar.getResourceBundleName() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundleName());
+ }
+
+ // Test that the last published log record had all the
+ // data that this test case had logged (message, parameters,
+ // thrown...
+ test.checkLogged(handler);
+ }
+ }
+
+ // No we're going to set a resource bundle on the foobar logger
+ // and do it all again...
+
+ // For the same bundle in two different locales
+ for (ResourceBundle propBundle : new ResourceBundle[] {
+ propertyBundle, propertyBundle_fr,
+ }) {
+
+ // set the bundle on foobar...
+ foobar.setResourceBundle(propBundle);
+
+ // check the bundle was correctly set...
+ if (!propBundle.equals(foobar.getResourceBundle())) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (!Objects.equals(getBaseName(propBundle), foobar.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobar.getResourceBundleName());
+ }
+
+ System.out.println("Configuring " + foobar.getName() + " with "
+ + propBundle);
+
+ // for each possible logrb form...
+ for (TestCase test : TestCase.values()) {
+
+ // for various resource bundles
+ for (ResourceBundle b : new ResourceBundle[] {
+ anonBundle, bundle, null, bundle_fr, propertyBundle,
+ anonBundle, propertyBundle_fr,
+ }) {
+
+ final String baseName = getBaseName(b);
+ System.out.println("Testing " + test + " with " + baseName);
+
+ // call foobar.logrb
+ test.logrb(foobar, b);
+
+ // check which resource bundle was used (should be
+ // the one passed to logrb)
+ if (handler.lastBundle != b) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler.lastBundle);
+ }
+ if (!Objects.equals(handler.lastBundleName, baseName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler.lastBundleName);
+ }
+
+ // Verify there was no side effect on the bundle that
+ // had been previously set on the logger...
+ if (foobar.getResourceBundle() != propBundle) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (!Objects.equals(getBaseName(propBundle),
+ foobar.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobar.getResourceBundleName());
+ }
+
+ // Checked that the published LogRecord had the
+ // expected content logged by this test case.
+ test.checkLogged(handler);
+ }
+ }
+ }
+
+ // Now we're going to the same thing, but with a logger which
+ // has an inherited resource bundle.
+ Logger foobaz = Logger.getLogger("foo.bar.baz");
+
+ // check that foobaz has no bundle set locally.
+ if (foobaz.getResourceBundle() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobaz.getResourceBundle());
+ }
+ if (foobaz.getResourceBundleName() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobaz.getResourceBundle());
+ }
+
+ // The current locale should have no effect on logrb.
+ Locale.setDefault(Locale.GERMAN); // shouldn't change anything...
+
+ // for each possible logrb form
+ for (TestCase test : TestCase.values()) {
+
+ // for various resource bundle
+ for (ResourceBundle b : new ResourceBundle[] {
+ anonBundle, bundle, bundle_fr, propertyBundle, null,
+ anonBundle, propertyBundle_fr,
+ }) {
+ final String baseName = getBaseName(b);
+ System.out.println("Testing " + test + " with "
+ + foobaz.getName() + " and "
+ + baseName);
+
+ // call foobaz.logrb with the bundle
+ test.logrb(foobaz, b);
+
+ // check that the bundle passed to logrb was used.
+ if (handler.lastBundle != b) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler.lastBundle);
+ }
+ if (!Objects.equals(handler.lastBundleName, baseName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler.lastBundleName);
+ }
+
+ // check that there was no effect on the bundle set
+ // on foobaz: it should still be null.
+ if (foobaz.getResourceBundle() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobaz.getResourceBundle());
+ }
+ if (foobaz.getResourceBundleName() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobaz.getResourceBundleName());
+ }
+
+ // check that the last published log record had all the
+ // data that was logged by this testcase.
+ test.checkLogged(handler);
+ }
+ }
+
+ } finally {
+ Locale.setDefault(defaultLocale);
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/logrb/resources/ListBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "foo" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/logrb/resources/ListBundle_fr.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle_fr extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "toto" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/logrb/resources/PropertyBundle.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 20013, 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.
+#
+dummy=foo
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/logrb/resources/PropertyBundle_fr.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+dummy=toto
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/setResourceBundle/TestSetResourceBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.security.AccessControlException;
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.PropertyPermission;
+import java.util.ResourceBundle;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+import resources.ListBundle;
+
+/**
+ * @test
+ * @bug 8013839
+ * @summary tests Logger.setResourceBundle;
+ * @build TestSetResourceBundle resources.ListBundle resources.ListBundle_fr
+ * @run main/othervm TestSetResourceBundle UNSECURE
+ * @run main/othervm TestSetResourceBundle PERMISSION
+ * @run main/othervm TestSetResourceBundle SECURE
+ * @author danielfuchs
+ */
+public class TestSetResourceBundle {
+
+ final static String LIST_BUNDLE_NAME = "resources.ListBundle";
+ final static String PROPERTY_BUNDLE_NAME = "resources.PropertyBundle";
+
+ /**
+ * A dummy handler class that we can use to check the bundle/bundle name
+ * that was present in the last LogRecord instance published.
+ */
+ static final class TestHandler extends Handler {
+ ResourceBundle lastBundle = null;
+ String lastBundleName = null;
+ @Override
+ public void publish(LogRecord record) {
+ lastBundle = record.getResourceBundle();
+ lastBundleName = record.getResourceBundleName();
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+ }
+
+ /**
+ * We will test setResourceBundle() in 3 configurations.
+ * UNSECURE: No security manager.
+ * SECURE: With the security manager present - and the required
+ * LoggingPermission("control") granted.
+ * PERMISSION: With the security manager present - and the required
+ * LoggingPermission("control") *not* granted. Here we will
+ * test that the expected security permission is thrown.
+ */
+ public static enum TestCase {
+ UNSECURE, SECURE, PERMISSION;
+ public void run(String name) throws Exception {
+ System.out.println("Running test case: " + name());
+ switch (this) {
+ case UNSECURE:
+ testUnsecure(name);
+ break;
+ case SECURE:
+ testSecure(name);
+ break;
+ case PERMISSION:
+ testPermission(name);
+ break;
+ default:
+ throw new Error("Unknown test case: "+this);
+ }
+ }
+ public String loggerName(String name) {
+ return name().toLowerCase(Locale.ROOT) + "." + name;
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+
+ Locale defaultLocale = Locale.getDefault();
+
+ if (args == null || args.length == 0) {
+ args = new String[] {
+ TestCase.UNSECURE.name(),
+ TestCase.SECURE.name()
+ };
+ }
+
+ for (String testName : args) {
+ TestCase test = TestCase.valueOf(testName);
+ try {
+ test.run(test.loggerName("foo.bar"));
+ } finally {
+ Locale.setDefault(defaultLocale);
+ }
+ }
+ }
+
+ /**
+ * Test without security manager.
+ * @param loggerName The logger to use.
+ * @throws Exception if the test fails.
+ */
+ public static void testUnsecure(String loggerName) throws Exception {
+ if (System.getSecurityManager() != null) {
+ throw new Error("Security manager is set");
+ }
+ test(loggerName);
+ }
+
+ /**
+ * Test with security manager.
+ * @param loggerName The logger to use.
+ * @throws Exception if the test fails.
+ */
+ public static void testSecure(String loggerName) throws Exception {
+ if (System.getSecurityManager() != null) {
+ throw new Error("Security manager is already set");
+ }
+ Policy.setPolicy(new SimplePolicy(TestCase.SECURE));
+ System.setSecurityManager(new SecurityManager());
+ test(loggerName);
+ }
+
+ /**
+ * Test the LoggingPermission("control") is required.
+ * @param loggerName The logger to use.
+ */
+ public static void testPermission(String loggerName) {
+ if (System.getSecurityManager() != null) {
+ throw new Error("Security manager is already set");
+ }
+ Policy.setPolicy(new SimplePolicy(TestCase.PERMISSION));
+ System.setSecurityManager(new SecurityManager());
+ final ResourceBundle bundle = ResourceBundle.getBundle(LIST_BUNDLE_NAME);
+ Logger foobar = Logger.getLogger(loggerName);
+ try {
+ foobar.setResourceBundle(bundle);
+ throw new RuntimeException("Permission not checked!");
+ } catch (AccessControlException x) {
+ if (x.getPermission() instanceof LoggingPermission) {
+ if ("control".equals(x.getPermission().getName())) {
+ System.out.println("Got expected exception: " + x);
+ return;
+ }
+ }
+ throw new RuntimeException("Unexpected exception: "+x, x);
+ }
+
+ }
+
+ static String getBaseName(ResourceBundle bundle) {
+ return bundle == null ? null : bundle.getBaseBundleName();
+ }
+
+ public static void test(String loggerName) throws Exception {
+
+ final ResourceBundle bundle = ResourceBundle.getBundle(LIST_BUNDLE_NAME);
+ Logger foobar = Logger.getLogger(loggerName);
+
+ // Checks that IAE is thrown if the bundle has a null base name.
+ try {
+ foobar.setResourceBundle(new ListBundle());
+ throw new RuntimeException("Expected exception not raised!");
+ } catch (IllegalArgumentException x) {
+ System.out.println("Got expected exception: " + x);
+ }
+
+ // Verify that resource bundle was not set.
+ if (foobar.getResourceBundle() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (foobar.getResourceBundleName() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundleName());
+ }
+
+ // Set acceptable resource bundle on logger.
+ foobar.setResourceBundle(bundle);
+
+ // check that the bundle has been set correctly
+ if (bundle != foobar.getResourceBundle()) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (!Objects.equals(getBaseName(bundle), foobar.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobar.getResourceBundleName());
+ }
+
+ // Check that we can replace the bundle with a bundle of the same name.
+ final ResourceBundle bundle_fr =
+ ResourceBundle.getBundle(LIST_BUNDLE_NAME, Locale.FRENCH);
+ foobar.setResourceBundle(bundle_fr);
+
+ if (bundle_fr != foobar.getResourceBundle()) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (!Objects.equals(getBaseName(bundle_fr), foobar.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobar.getResourceBundleName());
+ }
+
+ // Create a child logger
+ Logger foobaz = Logger.getLogger(loggerName + ".baz");
+
+ // Check that the child logger does not have a bundle set locally
+ if (foobaz.getResourceBundle() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundle());
+ }
+ if (foobaz.getResourceBundleName() != null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + foobar.getResourceBundleName());
+ }
+
+
+ // Add a handler on the child logger.
+ final TestHandler handler = new TestHandler();
+ foobaz.addHandler(handler);
+
+ // log a message on the child logger
+ foobaz.severe("dummy");
+
+ // checks that the message has been logged with the bundle
+ // inherited from the parent logger
+ if (!LIST_BUNDLE_NAME.equals(handler.lastBundleName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler.lastBundleName);
+ }
+ if (!bundle_fr.equals(handler.lastBundle)) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler.lastBundle);
+ }
+
+ // Check that we can get set a bundle on the child logger
+ // using Logger.getLogger.
+ foobaz = Logger.getLogger(loggerName + ".baz", PROPERTY_BUNDLE_NAME);
+
+ // check that the child logger has the correct bundle.
+ // it should no longer inherit it from its parent.
+ if (!PROPERTY_BUNDLE_NAME.equals(foobaz.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobaz.getResourceBundleName());
+ }
+ if (!PROPERTY_BUNDLE_NAME.equals(foobaz.getResourceBundle().getBaseBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + foobaz.getResourceBundle().getBaseBundleName());
+ }
+
+ // log a message on the child logger
+ foobaz.severe("dummy");
+
+ // check that the last published log record has the appropriate
+ // bundle.
+ if (!PROPERTY_BUNDLE_NAME.equals(handler.lastBundleName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler.lastBundleName);
+ }
+ if (foobaz.getResourceBundle() != handler.lastBundle) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler.lastBundle);
+ }
+
+ // try to set a bundle that has a different name, and checks that
+ // it fails in IAE.
+ try {
+ foobaz.setResourceBundle(bundle_fr);
+ throw new RuntimeException("Expected exception not raised!");
+ } catch (IllegalArgumentException x) {
+ System.out.println("Got expected exception: " + x);
+ }
+
+ // Test with a subclass of logger which overrides
+ // getResourceBundle() and getResourceBundleName()
+ Logger customLogger = new Logger(foobar.getName()+".bie", null) {
+ @Override
+ public ResourceBundle getResourceBundle() {
+ return bundle_fr;
+ }
+
+ @Override
+ public String getResourceBundleName() {
+ return PROPERTY_BUNDLE_NAME;
+ }
+ };
+
+ final TestHandler handler2 = new TestHandler();
+ customLogger.addHandler(handler2);
+ customLogger.setLevel(Level.FINE);
+ LogManager.getLogManager().addLogger(customLogger);
+
+ Logger l = Logger.getLogger(customLogger.getName());
+ if (l != customLogger) {
+ throw new RuntimeException("Wrong logger: " + l);
+ }
+
+ // log on the custom logger.
+ customLogger.fine("dummy");
+
+ // check that the log record had the correct bundle.
+ if (! PROPERTY_BUNDLE_NAME.equals(handler2.lastBundleName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler2.lastBundleName);
+ }
+ if (! PROPERTY_BUNDLE_NAME.equals(customLogger.getResourceBundleName())) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + customLogger.getResourceBundleName());
+ }
+ if (bundle_fr != handler2.lastBundle) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler2.lastBundle);
+ }
+ if (bundle_fr != customLogger.getResourceBundle()) {
+ throw new RuntimeException("Unexpected bundle: "
+ + customLogger.getResourceBundle());
+ }
+
+ // Do the same thing again with a child of the custom logger.
+ Logger biebar = Logger.getLogger(customLogger.getName() + ".bar");
+ biebar.fine("dummy");
+
+ // because getResourceBundleName() is called on parent logger
+ // we will have handler2.lastBundleName = PROPERTY_BUNDLE_NAME
+ if (!PROPERTY_BUNDLE_NAME.equals(handler2.lastBundleName)) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + handler2.lastBundleName);
+ }
+ // because getResourceBundle() is not called on parent logger
+ // we will have getBaseName(handler2.lastBundle) = PROPERTY_BUNDLE_NAME
+ // and not handler2.lastBundle = bundle_fr
+ if (handler2.lastBundle == null) {
+ throw new RuntimeException("Unexpected bundle: "
+ + handler2.lastBundle);
+ }
+ if (!PROPERTY_BUNDLE_NAME.equals(getBaseName(handler2.lastBundle))) {
+ throw new RuntimeException("Unexpected bundle name: "
+ + getBaseName(handler2.lastBundle));
+ }
+ }
+
+ public static class SimplePolicy extends Policy {
+
+ final Permissions permissions;
+ public SimplePolicy(TestCase test) {
+ permissions = new Permissions();
+ if (test != TestCase.PERMISSION) {
+ permissions.add(new LoggingPermission("control", null));
+ }
+ // required for calling Locale.setDefault in the test.
+ permissions.add(new PropertyPermission("user.language", "write"));
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ return permissions.implies(permission);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/setResourceBundle/resources/ListBundle.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "foo" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/setResourceBundle/resources/ListBundle_fr.java Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ *
+ * @author danielfuchs
+ */
+public class ListBundle_fr extends ListResourceBundle {
+
+ @Override
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "dummy", "toto" },
+ };
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/setResourceBundle/resources/PropertyBundle.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 20013, 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.
+#
+dummy=foo
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/setResourceBundle/resources/PropertyBundle_fr.properties Wed Oct 16 20:47:30 2013 +0200
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+dummy=toto
+