Skip to content

Commit

Permalink
Fix loading of the effective RecyclerFactoryConverter in JSON Templ…
Browse files Browse the repository at this point in the history
…ate Layout (#3398)
  • Loading branch information
vy authored Jan 27, 2025
1 parent dde2652 commit f5c6d73
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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\"}";
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<RecyclerFactory>, Comparable<TypeConverter<RecyclerFactory>> {

static final String NAME = "魔法";

static final RecyclerFactory RECYCLER_FACTORY = new RecyclerFactory() {

@Override
public <V> Recycler<V> create(final Supplier<V> supplier, final Consumer<V> cleaner) {
return new Recycler<V>() {

@Override
public V acquire() {
return supplier.get();
}

@Override
public void release(V value) {
// Do nothing;
}
};
}
};

@Override
public int compareTo(TypeConverter<RecyclerFactory> typeConverter) {
return -1;
}

@Override
public RecyclerFactory convert(final String recyclerFactorySpec) {
return NAME.equals(recyclerFactorySpec) ? RECYCLER_FACTORY : RecyclerFactories.ofSpec(recyclerFactorySpec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<RecyclerFactory> typeConverter = (TypeConverter<RecyclerFactory>)
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://logging.apache.org/xml/ns"
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
type="fixed">
<issue id="3398" link="https://github.com/apache/logging-log4j2/pull/3398"/>
<description format="asciidoc">Fix loading of the effective `RecyclerFactoryConverter` in JSON Template Layout</description>
</entry>

0 comments on commit f5c6d73

Please sign in to comment.