package com.github.rmannibucau.cdi.configuration; import com.github.rmannibucau.cdi.configuration.factory.ContextualFactory; import com.github.rmannibucau.cdi.configuration.model.ConfigBean; import com.github.rmannibucau.cdi.configuration.reflect.ParameterizedTypeImpl; import com.github.rmannibucau.cdi.configuration.xml.ConfigParser; import org.apache.deltaspike.core.api.config.ConfigResolver; import org.apache.deltaspike.core.spi.activation.Deactivatable; import org.apache.deltaspike.core.util.ClassDeactivationUtils; import org.apache.deltaspike.core.util.bean.BeanBuilder; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.BeforeBeanDiscovery; import javax.enterprise.inject.spi.Extension; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.net.URL; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import static com.github.rmannibucau.cdi.configuration.loader.ClassLoaders.tccl; import static com.github.rmannibucau.cdi.configuration.qualifier.Qualifiers.toQualifier; import static com.github.rmannibucau.cdi.configuration.scope.Scopes.toScope; public class LightConfigurationExtension implements Extension, Deactivatable { private static final Logger LOGGER = Logger.getLogger(LightConfigurationExtension.class.getName()); private final Map<String, ConfigBean> beans = new HashMap<String, ConfigBean>(); private boolean activated; void readAllConfigurations(final @Observes BeforeBeanDiscovery bdd) { activated = ClassDeactivationUtils.isActivated(LightConfigurationExtension.class); if (!activated) { return; } final String configurationName = ConfigResolver.getPropertyValue(LightConfigurationExtension.class.getName() + ".path", "cdi-configuration.xml"); try { final Enumeration<URL> resources = tccl().getResources(configurationName); while (resources.hasMoreElements()) { addBeansForUrl(resources.nextElement()); } } catch (final Exception e) { throw new ConfigurationException(e); } } void addCdiBeans(final @Observes AfterBeanDiscovery abd, final BeanManager bm) { if (!activated) { return; } for (final ConfigBean bean : beans.values()) { try { final Bean<Object> cdiBean = createBean(bm, bean); abd.addBean(cdiBean); LOGGER.fine("Added bean " + cdiBean.getName()); } catch (final Exception e) { throw new ConfigurationException(e); } } } private void addBeansForUrl(final URL url) throws Exception { final InputStream is = url.openStream(); try { for (final ConfigBean bean : ConfigParser.parse(is)) { final String name = bean.getName(); if (name != null) { beans.put(name, bean); } else { beans.put("_no_name_" + bean.hashCode(), bean); } } LOGGER.info("Read: " + url.toExternalForm()); } finally { try { is.close(); } catch (final IOException ioe) { // no-op } } } private static Bean<Object> createBean(final BeanManager bm, final ConfigBean bean) throws Exception { final ClassLoader classLoader = tccl(); final Class<?> clazz = classLoader.loadClass(bean.getClassname()); final String name = bean.getName(); final Type type = findType(classLoader, clazz, bean.getTypeParameters()); final BeanBuilder<Object> beanBuilder = new BeanBuilder<Object>(bm) .passivationCapable(true) .beanClass(clazz) .name(name) .types(type, Object.class) .scope(toScope(bean.getScope())) .beanLifecycle(new ContextualFactory<Object>(bean)); final Annotation qualifier = toQualifier(bean.getQualifier(), name); if (qualifier != null) { beanBuilder.qualifiers(qualifier); } return beanBuilder.create(); } private static Type findType(final ClassLoader classLoader, final Class<?> base, final Collection<String> typeParameters) throws Exception { if (typeParameters == null) { return base; } final Type[] params = new Type[typeParameters.size()]; int i = 0; for (final String type : typeParameters) { params[i++] = classLoader.loadClass(type); } return new ParameterizedTypeImpl(base, params); } }