io.gravitee.gateway.policy.impl.PolicyPluginFactoryImpl Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed 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 io.gravitee.gateway.policy.impl;
import static org.reflections.ReflectionUtils.withModifier;
import static org.reflections.ReflectionUtils.withParametersCount;
import com.google.common.base.Predicate;
import io.gravitee.gateway.policy.PolicyPluginFactory;
import io.gravitee.policy.api.PolicyConfiguration;
import java.lang.reflect.*;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author GraviteeSource Team
*/
public class PolicyPluginFactoryImpl implements PolicyPluginFactory {
private final Logger LOGGER = LoggerFactory.getLogger(PolicyPluginFactoryImpl.class);
/**
* Cache of constructor by policy
*/
private final ConcurrentMap, Constructor>> constructors = new ConcurrentHashMap<>();
@Override
public T create(Class policyClass, PolicyConfiguration policyConfiguration) {
LOGGER.debug("Create a new policy instance for {}", policyClass.getName());
//TODO: could we reuse policy instance ?
return createInstance(policyClass, policyConfiguration);
}
@Override
public void clearCache() {
constructors.clear();
}
private T createInstance(Class policyClass, PolicyConfiguration policyConfiguration) {
T policyInst = null;
Constructor constr = lookingForConstructor(policyClass);
if (constr != null) {
try {
if (constr.getParameterCount() > 0) {
policyInst = constr.newInstance(policyConfiguration);
} else {
policyInst = constr.newInstance();
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException ex) {
LOGGER.error("Unable to instantiate policy {}", policyClass.getName(), ex);
}
}
return policyInst;
}
private Constructor lookingForConstructor(Class policyClass) {
return (Constructor) constructors.computeIfAbsent(
policyClass,
aClass -> {
LOGGER.debug("Looking for a constructor to inject policy configuration");
Set policyConstructors = ReflectionUtils.getConstructors(
policyClass,
withModifier(Modifier.PUBLIC),
withParametersAssignableFrom(PolicyConfiguration.class),
withParametersCount(1)
);
if (policyConstructors.isEmpty()) {
LOGGER.debug(
"No configuration can be injected for {} because there is no valid constructor. " +
"Using default empty constructor.",
policyClass.getName()
);
try {
return policyClass.getConstructor();
} catch (NoSuchMethodException nsme) {
LOGGER.error("Unable to find default empty constructor for {}", policyClass.getName(), nsme);
}
} else if (policyConstructors.size() == 1) {
return policyConstructors.iterator().next();
} else {
LOGGER.info("Too much constructors to instantiate policy {}", policyClass.getName());
}
return null;
}
);
}
private static Predicate withParametersAssignableFrom(final Class... types) {
return input -> {
if (input != null) {
Class>[] parameterTypes = parameterTypes(input);
if (parameterTypes.length == types.length) {
for (int i = 0; i < parameterTypes.length; i++) {
if (
!types[i].isAssignableFrom(parameterTypes[i]) || (parameterTypes[i] == Object.class && types[i] != Object.class)
) {
return false;
}
}
return true;
}
}
return false;
};
}
private static Class[] parameterTypes(Member member) {
return member != null
? member.getClass() == Method.class
? ((Method) member).getParameterTypes()
: member.getClass() == Constructor.class ? ((Constructor) member).getParameterTypes() : null
: null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy