in log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java [511:595]
private PatternConverter createConverter(final String converterId, final StringBuilder currentLiteral,
final Map<String, Class<PatternConverter>> rules, final List<String> options, final boolean disableAnsi,
final boolean noConsoleNoAnsi) {
String converterName = converterId;
Class<PatternConverter> converterClass = null;
if (rules == null) {
LOGGER.error("Null rules for [" + converterId + ']');
return null;
}
for (int i = converterId.length(); i > 0 && converterClass == null; i--) {
converterName = converterName.substring(0, i);
converterClass = rules.get(converterName);
}
if (converterClass == null) {
LOGGER.error("Unrecognized format specifier [" + converterId + ']');
return null;
}
if (AnsiConverter.class.isAssignableFrom(converterClass)) {
options.add(DISABLE_ANSI + '=' + disableAnsi);
options.add(NO_CONSOLE_NO_ANSI + '=' + noConsoleNoAnsi);
}
// Work around the regression bug in Class.getDeclaredMethods() in Oracle Java in version > 1.6.0_17:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6815786
final Method[] methods = converterClass.getDeclaredMethods();
Method newInstanceMethod = null;
for (final Method method : methods) {
if (Modifier.isStatic(method.getModifiers())
&& method.getDeclaringClass().equals(converterClass)
&& method.getName().equals("newInstance")
&& areValidNewInstanceParameters(method.getParameterTypes())) {
if (newInstanceMethod == null) {
newInstanceMethod = method;
} else if (method.getReturnType().equals(newInstanceMethod.getReturnType())) {
LOGGER.error("Class " + converterClass + " cannot contain multiple static newInstance methods");
return null;
}
}
}
if (newInstanceMethod == null) {
LOGGER.error("Class " + converterClass + " does not contain a static newInstance method");
return null;
}
final Class<?>[] parmTypes = newInstanceMethod.getParameterTypes();
final Object[] parms = parmTypes.length > 0 ? new Object[parmTypes.length] : null;
if (parms != null) {
int i = 0;
boolean errors = false;
for (final Class<?> clazz : parmTypes) {
if (clazz.isArray() && clazz.getName().equals("[Ljava.lang.String;")) {
final String[] optionsArray = options.toArray(Strings.EMPTY_ARRAY);
parms[i] = optionsArray;
} else if (clazz.isAssignableFrom(Configuration.class)) {
parms[i] = config;
} else {
LOGGER.error("Unknown parameter type " + clazz.getName() + " for static newInstance method of "
+ converterClass.getName());
errors = true;
}
++i;
}
if (errors) {
return null;
}
}
try {
final Object newObj = newInstanceMethod.invoke(null, parms);
if (newObj instanceof PatternConverter) {
currentLiteral.delete(0, currentLiteral.length() - (converterId.length() - converterName.length()));
return (PatternConverter) newObj;
}
LOGGER.warn("Class {} does not extend PatternConverter.", converterClass.getName());
} catch (final Exception ex) {
LOGGER.error("Error creating converter for " + converterId, ex);
}
return null;
}