From 59727ef5d48ee831e6886433e147dceb82a7de69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volkan=20Yaz=C4=B1c=C4=B1?= Date: Wed, 15 Jan 2025 15:39:33 +0100 Subject: [PATCH 1/2] Fix loading of the effective `RecyclerFactoryConverter` in JSON Template Layout --- .../json/resolver/MessageResolverTest.java | 2 + .../util/RecyclerFactoryConverterTest.java | 33 ++++++++++ .../util/RecyclerFactoryCustomConverter.java | 63 +++++++++++++++++++ .../json/JsonTemplateLayoutDefaults.java | 34 +++++++++- .../3398_fix_JTL_RecyclerFactoryConverter.xml | 8 +++ 5 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverterTest.java create mode 100644 log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryCustomConverter.java create mode 100644 src/changelog/.2.x.x/3398_fix_JTL_RecyclerFactoryConverter.xml diff --git a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java index dab3bab00fc..ba0d4f65a10 100644 --- a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java +++ b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java @@ -228,6 +228,8 @@ void test_MultiformatMessage() { private static final class TestMultiformatMessage implements MultiformatMessage { + private static final long serialVersionUID = 1L; + @Override public String getFormattedMessage() { return "{\"foo\": \"bar\"}"; diff --git a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverterTest.java b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverterTest.java new file mode 100644 index 00000000000..7753caf45ac --- /dev/null +++ b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverterTest.java @@ -0,0 +1,33 @@ +/* + * 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.logging.log4j.layout.template.json.util; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetSystemProperty; + +class RecyclerFactoryConverterTest { + + @Test + @SetSystemProperty(key = "log4j.layout.jsonTemplate.recyclerFactory", value = RecyclerFactoryCustomConverter.NAME) + void custom_converter_should_be_effective() { + assertThat(JsonTemplateLayoutDefaults.getRecyclerFactory()) + .isSameAs(RecyclerFactoryCustomConverter.RECYCLER_FACTORY); + } +} diff --git a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryCustomConverter.java b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryCustomConverter.java new file mode 100644 index 00000000000..3675b58206c --- /dev/null +++ b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryCustomConverter.java @@ -0,0 +1,63 @@ +/* + * 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.logging.log4j.layout.template.json.util; + +import java.util.function.Consumer; +import java.util.function.Supplier; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter; +import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters; + +/** + * A custom {@link RecyclerFactory} type converter that always returns the same instance if the specification is {@value RecyclerFactoryCustomConverter#NAME}; otherwise, falls back to {@link RecyclerFactories#ofSpec(String) the default}. + */ +@SuppressWarnings("ComparableType") +@Plugin(name = "RecyclerFactoryCustomConverter", category = TypeConverters.CATEGORY) +public final class RecyclerFactoryCustomConverter + implements TypeConverter, Comparable> { + + static final String NAME = "魔法"; + + static final RecyclerFactory RECYCLER_FACTORY = new RecyclerFactory() { + + @Override + public Recycler create(final Supplier supplier, final Consumer cleaner) { + return new Recycler() { + + @Override + public V acquire() { + return supplier.get(); + } + + @Override + public void release(V value) { + // Do nothing; + } + }; + } + }; + + @Override + public int compareTo(TypeConverter typeConverter) { + return -1; + } + + @Override + public RecyclerFactory convert(final String recyclerFactorySpec) { + return NAME.equals(recyclerFactorySpec) ? RECYCLER_FACTORY : RecyclerFactories.ofSpec(recyclerFactorySpec); + } +} diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java index 316517b3a53..3afc7927fae 100644 --- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java +++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java @@ -22,7 +22,8 @@ import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.TimeZone; -import org.apache.logging.log4j.layout.template.json.util.RecyclerFactories; +import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter; +import org.apache.logging.log4j.core.config.plugins.convert.TypeConverterRegistry; import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory; import org.apache.logging.log4j.util.PropertiesUtil; @@ -116,7 +117,34 @@ public static String getTruncatedStringSuffix() { } public static RecyclerFactory getRecyclerFactory() { - final String recyclerFactorySpec = PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.recyclerFactory"); - return RecyclerFactories.ofSpec(recyclerFactorySpec); + + // Get the recycler factory specification + final String propertyName = "log4j.layout.jsonTemplate.recyclerFactory"; + final String recyclerFactorySpec = PROPERTIES.getStringProperty(propertyName); + + // Read the specification + @SuppressWarnings("unchecked") + final TypeConverter typeConverter = (TypeConverter) + TypeConverterRegistry.getInstance().findCompatibleConverter(RecyclerFactory.class); + final RecyclerFactory recyclerFactory; + try { + // Using `TypeConverter#convert()` instead of `TypeConverters.convert`. + // The latter doesn't pass the converter a null value, which is a valid input. + recyclerFactory = typeConverter.convert(recyclerFactorySpec); + } catch (final Exception error) { + final String message = String.format( + "failed converting the recycler factory specified by the `%s` property: %s", + propertyName, recyclerFactorySpec == null ? null : '`' + recyclerFactorySpec + '`'); + throw new RuntimeException(message, error); + } + + // Verify and return loaded recycler factory + if (recyclerFactory == null) { + final String message = String.format( + "could not determine the recycler factory specified by the `%s` property: %s", + propertyName, recyclerFactorySpec == null ? null : '`' + recyclerFactorySpec + '`'); + throw new IllegalArgumentException(message); + } + return recyclerFactory; } } diff --git a/src/changelog/.2.x.x/3398_fix_JTL_RecyclerFactoryConverter.xml b/src/changelog/.2.x.x/3398_fix_JTL_RecyclerFactoryConverter.xml new file mode 100644 index 00000000000..7678cd7fb7e --- /dev/null +++ b/src/changelog/.2.x.x/3398_fix_JTL_RecyclerFactoryConverter.xml @@ -0,0 +1,8 @@ + + + + Fix loading of the effective `RecyclerFactoryConverter` in JSON Template Layout + From 6f216f91cc1ad0c27fbb993e93feeb2ca6c043d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volkan=20Yaz=C4=B1c=C4=B1?= Date: Fri, 24 Jan 2025 11:49:13 +0100 Subject: [PATCH 2/2] Mark `RecyclerFactories` deprecated --- .../log4j/layout/template/json/util/RecyclerFactories.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java index 7f4ed7a1cf8..573b55327cc 100644 --- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java +++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java @@ -29,6 +29,10 @@ import org.apache.logging.log4j.util.LoaderUtil; import org.jctools.queues.MpmcArrayQueue; +/** + * @deprecated As of version {@code 2.25.0}, planned to be removed! + */ +@Deprecated public final class RecyclerFactories { private RecyclerFactories() {}