package com.softwaremill.common.cdi.config; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; import javax.enterprise.inject.InjectionException; import javax.enterprise.inject.spi.*; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; /** * @author Gavin King * @author Adam Warski (adam at warski dot org) * @link http://in.relation.to/13053.lace */ public class ConfigExtension implements Extension { public <X> void processInjectionTarget(@Observes ProcessInjectionTarget<X> pit) { final InjectionTarget<X> it = pit.getInjectionTarget(); final Map<Field, Object> configuredValues = new HashMap<Field, Object>(); AnnotatedType<X> at = pit.getAnnotatedType(); Annotation annotation = at.getAnnotation(Configuration.class); if(annotation == null){ //don't process classes not marked with @Configuration annotation return; } String propsFileName = at.getJavaClass().getSimpleName() + ".properties"; InputStream stream = at.getJavaClass().getResourceAsStream(propsFileName); if (stream!=null) { try { Properties props = new Properties(); props.load(stream); for (Map.Entry<Object, Object> property : props.entrySet()) { String fieldName = property.getKey().toString(); Object value = property.getValue(); try { Field field = at.getJavaClass().getDeclaredField(fieldName); field.setAccessible(true); if ( field.getType().isAssignableFrom( value.getClass() ) ) { configuredValues.put(field, value); } else { //TODO: do type conversion automatically pit.addDefinitionError( new InjectionException("field is not of type String: " + field ) ); } } catch (NoSuchFieldException nsfe) { pit.addDefinitionError(nsfe); } } } catch (IOException ioe) { pit.addDefinitionError(ioe); } finally { try { stream.close(); } catch (IOException e) { pit.addDefinitionError(e); } } InjectionTarget<X> wrapped = new InjectionTarget<X>() { @Override public void inject(X instance, CreationalContext<X> ctx) { it.inject(instance, ctx); for (Map.Entry<Field, Object> configuredValue: configuredValues.entrySet()) { try { configuredValue.getKey().set(instance, configuredValue.getValue()); } catch (Exception e) { throw new InjectionException(e); } } } @Override public void postConstruct(X instance) { it.postConstruct(instance); } @Override public void preDestroy(X instance) { it.dispose(instance); } @Override public void dispose(X instance) { it.dispose(instance); } @Override public Set<InjectionPoint> getInjectionPoints() { return it.getInjectionPoints(); } @Override public X produce(CreationalContext<X> ctx) { return it.produce(ctx); } }; pit.setInjectionTarget(wrapped); } } }