Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #803 PatternLayoutBase custom converter classloading in OSGi #804

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions logback-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit-jupiter-params.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
*/
package ch.qos.logback.core.pattern;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

import ch.qos.logback.core.Context;
import ch.qos.logback.core.CoreConstants;
Expand All @@ -32,7 +34,10 @@ abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
String pattern;
protected PostCompileProcessor<E> postCompileProcessor;

// instance converters whose value is a class name
Map<String, String> instanceConverterMap = new HashMap<String, String>();
// instance converters whose value is a supplier function
Map<String, Supplier<Converter<E>>> instanceConverterSupplierMap = new HashMap<String, Supplier<Converter<E>>>();
protected boolean outputPatternAsHeader = false;

/**
Expand All @@ -43,6 +48,16 @@ abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
*/
abstract public Map<String, String> getDefaultConverterMap();

/**
* Concrete implementations of this class may override this for elaborating the
* mapping between pattern words and converters.
*
* @return A map associating pattern words to the supplier of converter instances
*/
public Map<String, Supplier<Converter<E>>> getDefaultConverterSupplierMap() {
return Collections.emptyMap();
}

/**
* Returns a map where the default converter map is merged with the map
* contained in the context.
Expand Down Expand Up @@ -71,6 +86,24 @@ public Map<String, String> getEffectiveConverterMap() {
return effectiveMap;
}

/**
* Returns a map where the default converter supplier map is merged with the
* instance converter supplier map
*/
public Map<String, Supplier<Converter<E>>> getEffectiveConverterSupplierMap() {
Map<String, Supplier<Converter<E>>> effectiveMap = new HashMap<String, Supplier<Converter<E>>>();

// add the least specific map fist
Map<String, Supplier<Converter<E>>> defaultMap = getDefaultConverterSupplierMap();
if (defaultMap != null) {
effectiveMap.putAll(defaultMap);
}

// set the most specific map last
effectiveMap.putAll(getInstanceConverterSupplierMap());
return effectiveMap;
}

public void start() {
if (pattern == null || pattern.length() == 0) {
addError("Empty or null pattern.");
Expand All @@ -82,7 +115,7 @@ public void start() {
p.setContext(getContext());
}
Node t = p.parse();
this.head = p.compile(t, getEffectiveConverterMap());
this.head = p.compile(t, getEffectiveConverterMap(), getEffectiveConverterSupplierMap());
if (postCompileProcessor != null) {
postCompileProcessor.process(context, head);
}
Expand Down Expand Up @@ -135,6 +168,10 @@ public Map<String, String> getInstanceConverterMap() {
return instanceConverterMap;
}

public Map<String, Supplier<Converter<E>>> getInstanceConverterSupplierMap() {
return instanceConverterSupplierMap;
}

protected String getPresentationHeaderPrefix() {
return CoreConstants.EMPTY_STRING;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package ch.qos.logback.core.pattern.parser;

import java.util.Map;
import java.util.function.Supplier;

import ch.qos.logback.core.pattern.CompositeConverter;
import ch.qos.logback.core.pattern.Converter;
Expand All @@ -28,11 +29,15 @@ class Compiler<E> extends ContextAwareBase {
Converter<E> head;
Converter<E> tail;
final Node top;
// converters whose value is a class name
final Map<String, String> converterMap;
// converters whose value is a supplier function
final Map<String, Supplier<Converter<E>>> converterSupplierMap;

Compiler(final Node top, final Map<String, String> converterMap) {
Compiler(final Node top, final Map<String, String> converterMap, Map<String, Supplier<Converter<E>>> converterSupplierMap) {
this.top = top;
this.converterMap = converterMap;
this.converterSupplierMap = converterSupplierMap;
}

Converter<E> compile() {
Expand All @@ -52,7 +57,7 @@ Converter<E> compile() {
}
compositeConverter.setFormattingInfo(cn.getFormatInfo());
compositeConverter.setOptionList(cn.getOptions());
Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(), converterMap);
Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(), converterMap, converterSupplierMap);
childCompiler.setContext(context);
Converter<E> childConverter = childCompiler.compile();
compositeConverter.setChildConverter(childConverter);
Expand Down Expand Up @@ -95,22 +100,33 @@ private void addToList(Converter<E> c) {
*/
@SuppressWarnings("unchecked")
DynamicConverter<E> createConverter(SimpleKeywordNode kn) {
DynamicConverter<E> converter = null;
String keyword = (String) kn.getValue();
String converterClassStr = (String) converterMap.get(keyword);

if (converterClassStr != null) {
try {
return (DynamicConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
DynamicConverter.class, context);
} catch (Exception e) {
addError("Failed to instantiate converter class [" + converterClassStr + "] for keyword [" + keyword
+ "]", e);
return null;
Supplier<Converter<E>> supplier = converterSupplierMap.get(keyword);
if (supplier != null) {
// get the value from the supplier
Converter<E> suppliedValue = supplier.get();
if (suppliedValue instanceof DynamicConverter) {
converter = (DynamicConverter<E>)suppliedValue;
} else {
addError("Failed to supply converter for keyword [" + keyword + "]");
}
} else {
addError("There is no conversion class registered for conversion word [" + keyword + "]");
return null;
// create the value from the className
String converterClassStr = converterMap.get(keyword);
if (converterClassStr != null) {
try {
converter = (DynamicConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
DynamicConverter.class, context);
} catch (Exception e) {
addError("Failed to instantiate converter class [" + converterClassStr + "] for keyword [" + keyword
+ "]", e);
}
} else {
addError("There is no conversion registered for conversion word [" + keyword + "]");
}
}
return converter;
}

/**
Expand All @@ -122,22 +138,33 @@ DynamicConverter<E> createConverter(SimpleKeywordNode kn) {
*/
@SuppressWarnings("unchecked")
CompositeConverter<E> createCompositeConverter(CompositeNode cn) {
CompositeConverter<E> converter = null;
String keyword = (String) cn.getValue();
String converterClassStr = (String) converterMap.get(keyword);

if (converterClassStr != null) {
try {
return (CompositeConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
CompositeConverter.class, context);
} catch (Exception e) {
addError("Failed to instantiate converter class [" + converterClassStr
+ "] as a composite converter for keyword [" + keyword + "]", e);
return null;
Supplier<Converter<E>> supplier = converterSupplierMap.get(keyword);
if (supplier != null) {
// get the value from the supplier
Converter<E> suppliedValue = supplier.get();
if (suppliedValue instanceof CompositeConverter) {
converter = (CompositeConverter<E>)suppliedValue;
} else {
addError("Failed to supply composite converter for keyword [" + keyword + "]");
}
} else {
addError("There is no conversion class registered for composite conversion word [" + keyword + "]");
return null;
// create the value from the className
String converterClassStr = converterMap.get(keyword);
if (converterClassStr != null) {
try {
converter = (CompositeConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
CompositeConverter.class, context);
} catch (Exception e) {
addError("Failed to instantiate converter class [" + converterClassStr
+ "] as a composite converter for keyword [" + keyword + "]", e);
}
} else {
addError("There is no conversion registered for composite conversion word [" + keyword + "]");
}
}
return converter;
}

// public void setStatusManager(StatusManager statusManager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
*/
package ch.qos.logback.core.pattern.parser;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.pattern.Converter;
Expand Down Expand Up @@ -81,7 +83,21 @@ public Parser(String pattern, IEscapeUtil escapeUtil) throws ScanException {
* @return
*/
public Converter<E> compile(final Node top, Map<String, String> converterMap) {
Compiler<E> compiler = new Compiler<E>(top, converterMap);
return compile(top, converterMap, Collections.emptyMap());
}

/**
* When the parsing step is done, the Node list can be transformed into a
* converter chain.
*
* @param top
* @param converterMap
* @param converterSupplierMap
* @return
*/
public Converter<E> compile(final Node top, Map<String, String> converterMap,
Map<String, Supplier<Converter<E>>> converterSupplierMap) {
Compiler<E> compiler = new Compiler<E>(top, converterMap, converterSupplierMap);
compiler.setContext(context);
// compiler.setStatusManager(statusManager);
return compiler.compile();
Expand Down
Loading