blob: ca3440db468498d4676cdb0482fa1626668474dc [file] [log] [blame]
/*
* 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.resolver;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.PluginUtil;
import org.apache.logging.log4j.status.StatusLogger;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Utility class for {@link TemplateResolverInterceptor}.
*/
public class TemplateResolverInterceptors {
private static final Logger LOGGER = StatusLogger.getLogger();
private TemplateResolverInterceptors() {}
/**
* Populates plugins implementing
* {@link TemplateResolverInterceptor TemplateResolverInterceptor<V, C>},
* where {@code V} and {@code C} denote the value and context class types,
* respectively.
*/
public static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> List<I> populateInterceptors(
final List<String> pluginPackages,
final Class<V> valueClass,
final Class<C> contextClass) {
// Populate interceptors.
final Map<String, PluginType<?>> pluginTypeByName =
PluginUtil.collectPluginsByCategoryAndPackage(
TemplateResolverInterceptor.CATEGORY,
pluginPackages);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"found {} plugins of category \"{}\": {}",
pluginTypeByName.size(),
TemplateResolverFactory.CATEGORY,
pluginTypeByName.keySet());
}
// Filter matching interceptors.
final List<I> interceptors =
populateInterceptors(pluginTypeByName, valueClass, contextClass);
LOGGER.debug(
"{} interceptors matched out of {} for value class {} and context class {}",
interceptors.size(),
pluginTypeByName.size(),
valueClass,
contextClass);
return interceptors;
}
private static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> List<I> populateInterceptors(
final Map<String, PluginType<?>> pluginTypeByName,
final Class<V> valueClass,
final Class<C> contextClass) {
final List<I> interceptors = new LinkedList<>();
final Set<String> pluginNames = pluginTypeByName.keySet();
for (final String pluginName : pluginNames) {
final PluginType<?> pluginType = pluginTypeByName.get(pluginName);
final Class<?> pluginClass = pluginType.getPluginClass();
final boolean pluginClassMatched =
TemplateResolverInterceptor.class.isAssignableFrom(pluginClass);
if (pluginClassMatched) {
final TemplateResolverInterceptor<?, ?> rawInterceptor =
instantiateInterceptor(pluginName, pluginClass);
final I interceptor =
castInterceptor(valueClass, contextClass, rawInterceptor);
if (interceptor != null) {
interceptors.add(interceptor);
}
}
}
return interceptors;
}
private static TemplateResolverInterceptor<?, ?> instantiateInterceptor(
final String pluginName,
final Class<?> pluginClass) {
try {
return (TemplateResolverInterceptor<?, ?>)
PluginUtil.instantiatePlugin(pluginClass);
} catch (final Exception error) {
final String message = String.format(
"failed instantiating resolver interceptor plugin %s of name %s",
pluginClass, pluginName);
throw new RuntimeException(message, error);
}
}
private static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> I castInterceptor(
final Class<V> valueClass,
final Class<C> contextClass,
final TemplateResolverInterceptor<?, ?> interceptor) {
final Class<?> interceptorValueClass = interceptor.getValueClass();
final Class<?> interceptorContextClass = interceptor.getContextClass();
final boolean interceptorValueClassMatched =
valueClass.isAssignableFrom(interceptorValueClass);
final boolean interceptorContextClassMatched =
contextClass.isAssignableFrom(interceptorContextClass);
if (interceptorValueClassMatched && interceptorContextClassMatched) {
@SuppressWarnings({"unchecked"})
final I typedInterceptor = (I) interceptor;
return typedInterceptor;
}
return null;
}
}