io.gravitee.gateway.resource.internal.ResourceFactory Maven / Gradle / Ivy
/**
* 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.resource.internal;
import com.google.common.base.Predicate;
import io.gravitee.resource.api.Resource;
import io.gravitee.resource.api.ResourceConfiguration;
import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.lang.reflect.*;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.reflections.ReflectionUtils.*;
/**
* @author David BRASSELY (david at gravitee.io)
* @author GraviteeSource Team
*/
public class ResourceFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceFactory.class);
public Resource create(Class extends Resource> resourceClass, Map, Object> injectables) throws Exception {
LOGGER.debug("Create a new resource instance for {}", resourceClass.getName());
return createResource(resourceClass, injectables);
}
private Resource createResource(Class extends Resource> resourceClass, Map, Object> injectables) {
Resource resourceInst = null;
Constructor extends Resource> constr = lookingForConstructor(resourceClass);
if (constr != null) {
try {
// if (constr.getParameterCount() > 0) {
// resourceInst = constr.newInstance(injectables.get(policyMetadata.configuration()));
// } else {
resourceInst = constr.newInstance();
// }
} catch (IllegalAccessException | InstantiationException | InvocationTargetException ex) {
LOGGER.error("Unable to instantiate resource {}", resourceClass, ex);
}
}
if (resourceInst != null) {
Set fields = lookingForInjectableFields(resourceClass);
if (fields != null) {
for (Field field : fields) {
boolean accessible = field.isAccessible();
Class> type = field.getType();
Optional> value = injectables.values().stream()
.filter(o -> type.isAssignableFrom(o.getClass()))
.findFirst();
if (value.isPresent()) {
LOGGER.debug("Inject value into field {} [{}] in {}", field.getName(), type.getName(), resourceClass);
try {
field.setAccessible(true);
field.set(resourceInst, value.get());
} catch (IllegalAccessException iae) {
LOGGER.error("Unable to set field value for {} in {}", field.getName(), resourceClass, iae);
} finally {
field.setAccessible(accessible);
}
}
}
}
}
return resourceInst;
}
private Constructor extends Resource> lookingForConstructor(Class extends Resource> resourceClass) {
LOGGER.debug("Looking for a constructor to inject resource configuration");
Constructor extends Resource> constructor = null;
Set resourceConstructors =
ReflectionUtils.getConstructors(resourceClass,
withModifier(Modifier.PUBLIC),
withParametersAssignableFrom(ResourceConfiguration.class),
withParametersCount(1));
if (resourceConstructors.isEmpty()) {
LOGGER.debug("No configuration can be injected for {} because there is no valid constructor. " +
"Using default empty constructor.", resourceClass.getName());
try {
constructor = resourceClass.getConstructor();
} catch (NoSuchMethodException nsme) {
LOGGER.error("Unable to find default empty constructor for {}", resourceClass.getName(), nsme);
}
} else if (resourceConstructors.size() == 1) {
constructor = resourceConstructors.iterator().next();
} else {
LOGGER.info("Too much constructors to instantiate resource {}", resourceClass.getName());
}
return constructor;
}
private Set lookingForInjectableFields(Class> resourceClass) {
return ReflectionUtils.getAllFields(resourceClass, withAnnotation(Inject.class));
}
public 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