Skip to content

Commit f5c6d73

Browse files
authored
Fix loading of the effective RecyclerFactoryConverter in JSON Template Layout (#3398)
1 parent dde2652 commit f5c6d73

File tree

6 files changed

+141
-3
lines changed

6 files changed

+141
-3
lines changed

log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ void test_MultiformatMessage() {
228228

229229
private static final class TestMultiformatMessage implements MultiformatMessage {
230230

231+
private static final long serialVersionUID = 1L;
232+
231233
@Override
232234
public String getFormattedMessage() {
233235
return "{\"foo\": \"bar\"}";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.layout.template.json.util;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
22+
import org.junit.jupiter.api.Test;
23+
import org.junitpioneer.jupiter.SetSystemProperty;
24+
25+
class RecyclerFactoryConverterTest {
26+
27+
@Test
28+
@SetSystemProperty(key = "log4j.layout.jsonTemplate.recyclerFactory", value = RecyclerFactoryCustomConverter.NAME)
29+
void custom_converter_should_be_effective() {
30+
assertThat(JsonTemplateLayoutDefaults.getRecyclerFactory())
31+
.isSameAs(RecyclerFactoryCustomConverter.RECYCLER_FACTORY);
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.layout.template.json.util;
18+
19+
import java.util.function.Consumer;
20+
import java.util.function.Supplier;
21+
import org.apache.logging.log4j.core.config.plugins.Plugin;
22+
import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter;
23+
import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters;
24+
25+
/**
26+
* 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}.
27+
*/
28+
@SuppressWarnings("ComparableType")
29+
@Plugin(name = "RecyclerFactoryCustomConverter", category = TypeConverters.CATEGORY)
30+
public final class RecyclerFactoryCustomConverter
31+
implements TypeConverter<RecyclerFactory>, Comparable<TypeConverter<RecyclerFactory>> {
32+
33+
static final String NAME = "魔法";
34+
35+
static final RecyclerFactory RECYCLER_FACTORY = new RecyclerFactory() {
36+
37+
@Override
38+
public <V> Recycler<V> create(final Supplier<V> supplier, final Consumer<V> cleaner) {
39+
return new Recycler<V>() {
40+
41+
@Override
42+
public V acquire() {
43+
return supplier.get();
44+
}
45+
46+
@Override
47+
public void release(V value) {
48+
// Do nothing;
49+
}
50+
};
51+
}
52+
};
53+
54+
@Override
55+
public int compareTo(TypeConverter<RecyclerFactory> typeConverter) {
56+
return -1;
57+
}
58+
59+
@Override
60+
public RecyclerFactory convert(final String recyclerFactorySpec) {
61+
return NAME.equals(recyclerFactorySpec) ? RECYCLER_FACTORY : RecyclerFactories.ofSpec(recyclerFactorySpec);
62+
}
63+
}

log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java

+31-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
import java.nio.charset.StandardCharsets;
2323
import java.util.Locale;
2424
import java.util.TimeZone;
25-
import org.apache.logging.log4j.layout.template.json.util.RecyclerFactories;
25+
import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter;
26+
import org.apache.logging.log4j.core.config.plugins.convert.TypeConverterRegistry;
2627
import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
2728
import org.apache.logging.log4j.util.PropertiesUtil;
2829

@@ -116,7 +117,34 @@ public static String getTruncatedStringSuffix() {
116117
}
117118

118119
public static RecyclerFactory getRecyclerFactory() {
119-
final String recyclerFactorySpec = PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.recyclerFactory");
120-
return RecyclerFactories.ofSpec(recyclerFactorySpec);
120+
121+
// Get the recycler factory specification
122+
final String propertyName = "log4j.layout.jsonTemplate.recyclerFactory";
123+
final String recyclerFactorySpec = PROPERTIES.getStringProperty(propertyName);
124+
125+
// Read the specification
126+
@SuppressWarnings("unchecked")
127+
final TypeConverter<RecyclerFactory> typeConverter = (TypeConverter<RecyclerFactory>)
128+
TypeConverterRegistry.getInstance().findCompatibleConverter(RecyclerFactory.class);
129+
final RecyclerFactory recyclerFactory;
130+
try {
131+
// Using `TypeConverter#convert()` instead of `TypeConverters.convert`.
132+
// The latter doesn't pass the converter a null value, which is a valid input.
133+
recyclerFactory = typeConverter.convert(recyclerFactorySpec);
134+
} catch (final Exception error) {
135+
final String message = String.format(
136+
"failed converting the recycler factory specified by the `%s` property: %s",
137+
propertyName, recyclerFactorySpec == null ? null : '`' + recyclerFactorySpec + '`');
138+
throw new RuntimeException(message, error);
139+
}
140+
141+
// Verify and return loaded recycler factory
142+
if (recyclerFactory == null) {
143+
final String message = String.format(
144+
"could not determine the recycler factory specified by the `%s` property: %s",
145+
propertyName, recyclerFactorySpec == null ? null : '`' + recyclerFactorySpec + '`');
146+
throw new IllegalArgumentException(message);
147+
}
148+
return recyclerFactory;
121149
}
122150
}

log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
import org.apache.logging.log4j.util.LoaderUtil;
3030
import org.jctools.queues.MpmcArrayQueue;
3131

32+
/**
33+
* @deprecated As of version {@code 2.25.0}, planned to be removed!
34+
*/
35+
@Deprecated
3236
public final class RecyclerFactories {
3337

3438
private RecyclerFactories() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="https://logging.apache.org/xml/ns"
4+
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
5+
type="fixed">
6+
<issue id="3398" link="https://github.com/apache/logging-log4j2/pull/3398"/>
7+
<description format="asciidoc">Fix loading of the effective `RecyclerFactoryConverter` in JSON Template Layout</description>
8+
</entry>

0 commit comments

Comments
 (0)