diff --git a/src/main/java/org/apache/commons/beanutils2/BeanPredicate.java b/src/main/java/org/apache/commons/beanutils2/BeanPredicate.java index 6bf1a62ad..ad747cac7 100644 --- a/src/main/java/org/apache/commons/beanutils2/BeanPredicate.java +++ b/src/main/java/org/apache/commons/beanutils2/BeanPredicate.java @@ -21,7 +21,6 @@ import java.util.function.Predicate; import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** *
Predicate implementation that applies the given {@code Predicate}
@@ -32,7 +31,7 @@
*/
public class BeanPredicate {@code Closure} that sets a property. {@code Predicate} that evaluates a property value against a specified value. {@code Transformer} that outputs a property value. JavaBean property population methods. Utility methods for converting String scalar values to objects of the
@@ -196,7 +195,7 @@ public class ConvertUtilsBean {
/**
* The {@code Log} instance for this class.
*/
- private static final Log LOG = LogFactory.getLog(ConvertUtilsBean.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(ConvertUtilsBean.class);
/**
* Gets singleton instance
diff --git a/src/main/java/org/apache/commons/beanutils2/DefaultBeanIntrospector.java b/src/main/java/org/apache/commons/beanutils2/DefaultBeanIntrospector.java
index c05125032..5cb6dc530 100644
--- a/src/main/java/org/apache/commons/beanutils2/DefaultBeanIntrospector.java
+++ b/src/main/java/org/apache/commons/beanutils2/DefaultBeanIntrospector.java
@@ -25,7 +25,6 @@
import java.util.List;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
*
@@ -54,7 +53,7 @@ public class DefaultBeanIntrospector implements BeanIntrospector {
private static final Class>[] LIST_CLASS_PARAMETER = new Class[] { java.util.List.class };
/** For logging. Each subclass gets its own log instance. */
- private final Log log = LogFactory.getLog(getClass());
+ private final Log log = LoggerUtil.createLoggerWithContextClassLoader(getClass());
/**
* Private constructor so that no instances can be created.
diff --git a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
index c27a7f431..d2134fb60 100644
--- a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
+++ b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
@@ -24,7 +24,6 @@
import java.util.Objects;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
*
@@ -81,7 +80,7 @@ public class FluentPropertyBeanIntrospector implements BeanIntrospector {
public static final String DEFAULT_WRITE_METHOD_PREFIX = "set";
/** The logger. */
- private final Log log = LogFactory.getLog(getClass());
+ private final Log log = LoggerUtil.createLoggerWithContextClassLoader(getClass());
/** The prefix of write methods to search for. */
private final String writeMethodPrefix;
diff --git a/src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java b/src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java
index 136a432b3..742bbea19 100644
--- a/src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java
+++ b/src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java
@@ -28,8 +28,6 @@
import java.util.Objects;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
/**
* DynaBean which automatically adds properties to the {@code DynaClass}
* and provides Lazy List and Lazy Map features. Utility reflection methods focused on methods in general rather than properties in particular. Utility methods for populating JavaBeans properties
@@ -56,7 +56,7 @@ protected LocaleBeanUtilsBean initialValue() {
};
/** All logging goes through this logger */
- private static final Log LOG = LogFactory.getLog(LocaleBeanUtilsBean.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(LocaleBeanUtilsBean.class);
/**
* Gets singleton instance
diff --git a/src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java b/src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java
index c08b1afaf..057d72397 100644
--- a/src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java
+++ b/src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java
@@ -24,6 +24,7 @@
import java.util.Map;
import org.apache.commons.beanutils2.ConversionException;
+import org.apache.commons.beanutils2.LoggerUtil;
import org.apache.commons.beanutils2.WeakFastHashMap;
import org.apache.commons.beanutils2.locale.converters.BigDecimalLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.BigIntegerLocaleConverter;
@@ -38,7 +39,6 @@
import org.apache.commons.beanutils2.sql.converters.locale.SqlTimeLocaleConverter;
import org.apache.commons.beanutils2.sql.converters.locale.SqlTimestampLocaleConverter;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
* Utility methods for converting locale-sensitive String scalar values to objects of the
@@ -82,7 +82,7 @@
public class LocaleConvertUtilsBean {
/** The {@code Log} instance for this class. */
- private static final Log LOG = LogFactory.getLog(LocaleConvertUtilsBean.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(LocaleConvertUtilsBean.class);
/**
* Gets singleton instance.
diff --git a/src/main/java/org/apache/commons/beanutils2/locale/converters/DateLocaleConverter.java b/src/main/java/org/apache/commons/beanutils2/locale/converters/DateLocaleConverter.java
index 30714bf22..0bfc3fb81 100644
--- a/src/main/java/org/apache/commons/beanutils2/locale/converters/DateLocaleConverter.java
+++ b/src/main/java/org/apache/commons/beanutils2/locale/converters/DateLocaleConverter.java
@@ -26,10 +26,10 @@
import java.util.Locale;
import org.apache.commons.beanutils2.ConversionException;
+import org.apache.commons.beanutils2.LoggerUtil;
import org.apache.commons.beanutils2.locale.BaseLocaleConverter;
import org.apache.commons.beanutils2.locale.LocaleConverter;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
* Standard {@link org.apache.commons.beanutils2.locale.LocaleConverter} implementation that converts an incoming locale-sensitive String into a
@@ -94,7 +94,7 @@ public B setLenient(final boolean lenient) {
private static final String DEFAULT_PATTERN_CHARS = DateLocaleConverter.initDefaultChars();
/** All logging goes through this logger */
- private static final Log LOG = LogFactory.getLog(DateLocaleConverter.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(DateLocaleConverter.class);
/**
* Constructs a new builder.
diff --git a/src/main/java/org/apache/commons/beanutils2/locale/converters/DecimalLocaleConverter.java b/src/main/java/org/apache/commons/beanutils2/locale/converters/DecimalLocaleConverter.java
index 679b85b2e..66e8ede22 100644
--- a/src/main/java/org/apache/commons/beanutils2/locale/converters/DecimalLocaleConverter.java
+++ b/src/main/java/org/apache/commons/beanutils2/locale/converters/DecimalLocaleConverter.java
@@ -23,10 +23,10 @@
import java.util.Locale;
import org.apache.commons.beanutils2.ConversionException;
+import org.apache.commons.beanutils2.LoggerUtil;
import org.apache.commons.beanutils2.locale.BaseLocaleConverter;
import org.apache.commons.beanutils2.locale.LocaleConverter;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
* Standard {@link LocaleConverter} implementation that converts an incoming locale-sensitive String into a {@link Number} object, optionally using a
@@ -62,7 +62,7 @@ public DecimalLocaleConverter> get() {
}
/** All logging goes through this logger */
- private static final Log LOG = LogFactory.getLog(DecimalLocaleConverter.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(DecimalLocaleConverter.class);
/**
* Constructs a new builder.
diff --git a/src/main/java/org/apache/commons/beanutils2/locale/converters/StringLocaleConverter.java b/src/main/java/org/apache/commons/beanutils2/locale/converters/StringLocaleConverter.java
index a129eb9fb..64520a625 100644
--- a/src/main/java/org/apache/commons/beanutils2/locale/converters/StringLocaleConverter.java
+++ b/src/main/java/org/apache/commons/beanutils2/locale/converters/StringLocaleConverter.java
@@ -27,10 +27,10 @@
import java.util.Locale;
import org.apache.commons.beanutils2.ConversionException;
+import org.apache.commons.beanutils2.LoggerUtil;
import org.apache.commons.beanutils2.locale.BaseLocaleConverter;
import org.apache.commons.beanutils2.locale.LocaleConverter;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
* Standard {@link org.apache.commons.beanutils2.locale.LocaleConverter} implementation that converts an incoming locale-sensitive object into a {@link String}
@@ -60,7 +60,7 @@ public StringLocaleConverter get() {
}
/** All logging goes through this logger */
- private static final Log LOG = LogFactory.getLog(StringLocaleConverter.class);
+ private static final Log LOG = LoggerUtil.createLoggerWithContextClassLoader(StringLocaleConverter.class);
/**
* Constructs a new builder.
diff --git a/src/test/java/org/apache/commons/beanutils2/bugs/Jira566TestCase.java b/src/test/java/org/apache/commons/beanutils2/bugs/Jira566TestCase.java
new file mode 100644
index 000000000..b38a5f0e2
--- /dev/null
+++ b/src/test/java/org/apache/commons/beanutils2/bugs/Jira566TestCase.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils2.bugs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.commons.beanutils2.LoggerUtil;
+import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test class for {@code LoggerUtil}
+ * https://issues.apache.org/jira/browse/BEANUTILS-566
+ */
+public class Jira566TestCase {
+
+ private static CustomURLClassLoader CUSTOM_CLASSLOADER;
+
+ private static Boolean IS_CUSTOM_CLASSLOADER_INVOKED = false;
+
+ private static class CustomURLClassLoader extends URLClassLoader {
+
+ public CustomURLClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ /*
+ * Given the following default loadClass implementation steps (in order, per the JavaDoc):
+ * 1) Invoke findLoadedClass(String) to check if the class has already been loaded.
+ * 2) Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
+ * 3) Invoke the findClass(String) method to find the class.
+ *
+ * If the name matches Jira566TestCase, then we find that class with this classloader instead via findClass.
+ * Calling newInstance().getClass().getClassLoader() on the returned class object would an instance of CustomURLClassLoader.
+ * Otherwise, if findLoadedClass or loadClass are used instead, then the original classloader is used (i.e jdk.internal.loader.ClassLoaders$AppClassLoader)
+ *
+ */
+ @Override
+ public Class> loadClass(String name) throws ClassNotFoundException {
+ if (name.equals("org.apache.commons.beanutils2.bugs.Jira566TestCase")) {
+ // System.out.println("match: " + name); // debug
+ return findClass(name);
+ } else {
+ // System.out.println("super: " + name); // debug
+ IS_CUSTOM_CLASSLOADER_INVOKED = true;
+ return super.loadClass(name);
+ }
+ }
+
+ }
+
+
+ public static void setup() throws Exception {
+ Path targetPath = Paths.get(Jira566TestCase.class.getResource("/").toURI()).getParent();
+ ClassLoader parent = Jira566TestCase.class.getClassLoader();
+ CUSTOM_CLASSLOADER = new CustomURLClassLoader(new URL[] {new File(targetPath.toString(), "test-classes").toURI().toURL()}, parent);
+ }
+
+ /*
+ * Tests that context classloader is used
+ */
+ @Test
+ public void testContextClassLoaderUsed() throws Exception {
+
+ setup();
+
+ /*
+ * Create an instance of this class (Jira566TestCase) so that it's classloader is CustomURLClassLoader
+ */
+ Class> loadedClass = CUSTOM_CLASSLOADER.loadClass("org.apache.commons.beanutils2.bugs.Jira566TestCase");
+ Class> instance = loadedClass.newInstance().getClass();
+
+ IS_CUSTOM_CLASSLOADER_INVOKED = false; // reset to false
+
+ /*
+ * When the logger is created, the creation will go through CustomURLClassLoader#loadClass
+ */
+ LoggerUtil.createLoggerWithContextClassLoader(instance);
+
+ assertTrue("Context ClassLoader was not invoked", IS_CUSTOM_CLASSLOADER_INVOKED);
+ }
+
+ /*
+ * Tests that original classloader is used
+ */
+ @Test
+ public void testOriginalClassLoaderUsed() throws Exception {
+
+ setup();
+
+ IS_CUSTOM_CLASSLOADER_INVOKED = false; // reset to false
+ LogFactory.getLog(Jira566TestCase.class);
+
+ assertFalse("Context ClassLoader was invoked when it should not have been", IS_CUSTOM_CLASSLOADER_INVOKED);
+ }
+
+ /*
+ * The LoggerUtil.createLoggerWithContextClassLoader method swaps out the classloaders,
+ * so this test checks to make it the original is set back.
+ */
+ @Test
+ public void testClassLoaderIsSetBackToOriginalInLoggerUtil() throws Exception {
+
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(CUSTOM_CLASSLOADER);
+ LoggerUtil.createLoggerWithContextClassLoader(Jira566TestCase.class);
+
+ assertEquals("Classloader do not match!",Thread.currentThread().getContextClassLoader(), CUSTOM_CLASSLOADER);
+ } finally {
+ // set it back to avoid any problems in the other tests
+ Thread.currentThread().setContextClassLoader(original);
+ }
+
+ }
+}