/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.config;
import java.lang.reflect.Field;
import java.util.Deque;
import java.util.LinkedList;
import javax.inject.Inject;
import org.diqube.context.AutoInstatiate;
import org.diqube.context.Profiles;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Profile;
import org.springframework.util.ReflectionUtils;
/**
* A {@link BeanPostProcessor} that will fill the fields annotated with {@link Config} correctly.
*
* @author Bastian Gloeckle
*/
@AutoInstatiate
@Profile(Profiles.CONFIG)
public class ConfigurationPostProcessor implements BeanPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(ConfigurationPostProcessor.class);
@Inject
private ConfigurationManager configManager;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Deque<Class<?>> classes = new LinkedList<>();
classes.add(bean.getClass());
while (!classes.isEmpty()) {
Class<?> clazz = classes.poll();
if (clazz.equals(Object.class))
break;
for (Field f : clazz.getDeclaredFields()) {
Config[] c = f.getAnnotationsByType(Config.class);
if (c.length > 0) {
String configKey = c[0].value();
if (configManager.getValue(configKey) != null) {
String valueString = configManager.getValue(configKey);
Object value;
if (f.getType().equals(Long.class) || f.getType().equals(Long.TYPE))
value = Long.valueOf(valueString);
else if (f.getType().equals(Double.class) || f.getType().equals(Double.TYPE))
value = Double.valueOf(valueString);
else if (f.getType().equals(Integer.class) || f.getType().equals(Integer.TYPE))
value = Integer.valueOf(valueString);
else if (f.getType().equals(String.class))
value = valueString;
else
throw new FatalBeanException("Cannot wire config value for '" + bean.getClass().getName() + "."
+ f.getName() + " as the datatype is not supported.");
ReflectionUtils.makeAccessible(f);
try {
logger.debug("Wiring config value of '{}' to '{}.{}'", configKey, bean.getClass().getName(), f.getName());
f.set(bean, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new FatalBeanException("Could not wire configManager value to " + f);
}
} else
throw new FatalBeanException(bean.getClass().getName() + "." + f.getName()
+ " requires configKey of which no value is available: " + configKey);
}
}
classes.add(clazz.getSuperclass());
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}