This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
The following commit(s) were added to refs/heads/master by this push: new 05b1d84 [OWB-1370] ensure CdiSeInitializer can be forced to one of the impls 05b1d84 is described below commit 05b1d845ed5200dcecdc1b6052ca364bd58cb435 Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Sat Feb 20 18:27:59 2021 +0100 [OWB-1370] ensure CdiSeInitializer can be forced to one of the impls --- .../openwebbeans/se/SeInitializerFacade.java | 184 ++++++++++++++++----- 1 file changed, 143 insertions(+), 41 deletions(-) diff --git a/webbeans-se/src/main/java/org/apache/openwebbeans/se/SeInitializerFacade.java b/webbeans-se/src/main/java/org/apache/openwebbeans/se/SeInitializerFacade.java index 0d44726..59ec6a3 100644 --- a/webbeans-se/src/main/java/org/apache/openwebbeans/se/SeInitializerFacade.java +++ b/webbeans-se/src/main/java/org/apache/openwebbeans/se/SeInitializerFacade.java @@ -18,122 +18,224 @@ */ package org.apache.openwebbeans.se; +import org.apache.webbeans.conversation.DefaultConversationService; +import org.apache.webbeans.corespi.se.StandaloneContextsService; +import org.apache.webbeans.lifecycle.StandaloneLifeCycle; +import org.apache.webbeans.spi.ContainerLifecycle; +import org.apache.webbeans.spi.ContextsService; +import org.apache.webbeans.spi.ConversationService; + +import javax.annotation.Priority; import javax.enterprise.inject.se.SeContainer; import javax.enterprise.inject.se.SeContainerInitializer; import javax.enterprise.inject.spi.Extension; import java.lang.annotation.Annotation; -import java.util.Iterator; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; import java.util.Map; -import java.util.Optional; import java.util.ServiceLoader; +import java.util.function.Consumer; +import java.util.stream.StreamSupport; + +import static java.util.Comparator.comparing; +import static java.util.Optional.ofNullable; // will allow to plug other impl but reusing most of our logic public class SeInitializerFacade extends SeContainerInitializer { - private final SeContainerInitializer delegate; + public final static String PROVIDER = SeContainerInitializer.class.getName() + ".provider"; - public SeInitializerFacade() - { - delegate = Optional.of(ServiceLoader.load(SeContainerSelector.class).iterator()) - .filter(Iterator::hasNext) - .map(Iterator::next) - .map(SeContainerSelector::find) - .orElseGet(OWBInitializer::new); - } + private final Collection<Consumer<SeContainerInitializer>> initializers = new ArrayList<>(); + private SeContainerInitializer delegate; @Override - public SeContainerInitializer addBeanClasses(Class<?>... classes) + public SeContainerInitializer addBeanClasses(final Class<?>... classes) { - return delegate.addBeanClasses(classes); + initializers.add(i -> i.addBeanClasses(classes)); + return this; } @Override - public SeContainerInitializer addPackages(Class<?>... packageClasses) + public SeContainerInitializer addPackages(final Class<?>... packageClasses) { - return delegate.addPackages(packageClasses); + initializers.add(i -> i.addPackages(packageClasses)); + return this; } @Override - public SeContainerInitializer addPackages(boolean scanRecursively, Class<?>... packageClasses) + public SeContainerInitializer addPackages(final boolean scanRecursively, final Class<?>... packageClasses) { - return delegate.addPackages(scanRecursively, packageClasses); + initializers.add(i -> i.addPackages(scanRecursively, packageClasses)); + return this; } @Override - public SeContainerInitializer addPackages(Package... packages) + public SeContainerInitializer addPackages(final Package... packages) { - return delegate.addPackages(packages); + initializers.add(i -> i.addPackages(packages)); + return this; } @Override - public SeContainerInitializer addPackages(boolean scanRecursively, Package... packages) + public SeContainerInitializer addPackages(final boolean scanRecursively, final Package... packages) { - return delegate.addPackages(scanRecursively, packages); + initializers.add(i -> i.addPackages(scanRecursively, packages)); + return this; } @Override - public SeContainerInitializer addExtensions(Extension... extensions) + public SeContainerInitializer addExtensions(final Extension... extensions) { - return delegate.addExtensions(extensions); + initializers.add(i -> i.addExtensions(extensions)); + return this; } @Override - public SeContainerInitializer addExtensions(Class<? extends Extension>... extensions) + public SeContainerInitializer addExtensions(final Class<? extends Extension>... extensions) { - return delegate.addExtensions(extensions); + initializers.add(i -> i.addExtensions(extensions)); + return this; } @Override - public SeContainerInitializer enableInterceptors(Class<?>... interceptorClasses) + public SeContainerInitializer enableInterceptors(final Class<?>... interceptorClasses) { - return delegate.enableInterceptors(interceptorClasses); + initializers.add(i -> i.enableInterceptors(interceptorClasses)); + return this; } @Override - public SeContainerInitializer enableDecorators(Class<?>... decoratorClasses) + public SeContainerInitializer enableDecorators(final Class<?>... decoratorClasses) { - return delegate.enableDecorators(decoratorClasses); + initializers.add(i -> i.enableDecorators(decoratorClasses)); + return this; } @Override - public SeContainerInitializer selectAlternatives(Class<?>... alternativeClasses) + public SeContainerInitializer selectAlternatives(final Class<?>... alternativeClasses) { - return delegate.selectAlternatives(alternativeClasses); + initializers.add(i -> i.selectAlternatives(alternativeClasses)); + return this; } @Override - public SeContainerInitializer selectAlternativeStereotypes(Class<? extends Annotation>... alternativeStereotypeClasses) + public SeContainerInitializer selectAlternativeStereotypes(final Class<? extends Annotation>... alternativeStereotypeClasses) { - return delegate.selectAlternativeStereotypes(alternativeStereotypeClasses); + initializers.add(i -> i.selectAlternativeStereotypes(alternativeStereotypeClasses)); + return this; } @Override - public SeContainerInitializer addProperty(String key, Object value) + public SeContainerInitializer addProperty(final String key, final Object value) { - return delegate.addProperty(key, value); + if (PROVIDER.endsWith(key)) + { + delegate = loadProvider(value); + } + initializers.add(i -> i.addProperty(key, value)); + return this; } @Override - public SeContainerInitializer setProperties(Map<String, Object> properties) + public SeContainerInitializer setProperties(final Map<String, Object> properties) { - return delegate.setProperties(properties); + if (properties != null && properties.containsKey(PROVIDER)) + { + addProperty(PROVIDER, properties.get(PROVIDER)); + } + initializers.add(i -> i.setProperties(properties)); + return this; } @Override public SeContainerInitializer disableDiscovery() { - return delegate.disableDiscovery(); + initializers.add(SeContainerInitializer::disableDiscovery); + return this; } @Override - public SeContainerInitializer setClassLoader(ClassLoader classLoader) + public SeContainerInitializer setClassLoader(final ClassLoader classLoader) { - return delegate.setClassLoader(classLoader); + initializers.add(i -> i.setClassLoader(classLoader)); + return this; } @Override public SeContainer initialize() { - return delegate.initialize(); + final SeContainerInitializer initializer = delegate != null ? + delegate : + StreamSupport.stream(ServiceLoader.load(SeContainerSelector.class).spliterator(), false) + .min(comparing(it -> ofNullable(it.getClass().getAnnotation(Priority.class)) + .map(Priority::value) + .orElse(0))) + .map(SeContainerSelector::find) + .orElseGet(OWBInitializer::new); + initializers.forEach(i -> i.accept(initializer)); + return initializer.initialize(); + } + + private SeContainerInitializer loadProvider(final Object value) + { + if (SeContainerInitializer.class.isInstance(value)) + { + return SeContainerInitializer.class.cast(value); + } + if (Class.class.isInstance(value)) + { + return newInitializerInstance(Class.class.cast(value).asSubclass(SeContainerInitializer.class)); + } + return newInitializerInstance(findClass(String.valueOf(value))); + } + + private Class<? extends SeContainerInitializer> findClass(final String name) + { + switch (name) + { + case "owb": + case "openwebbeans": + case "org.apache.openwebbeans.se.OWBInitializer": + return OWBInitializer.class; + default: + try + { + return ofNullable(SeInitializerFacade.class.getClassLoader()) + .orElseGet(ClassLoader::getSystemClassLoader) + .loadClass(name.trim()) + .asSubclass(SeContainerInitializer.class); + } + catch (final ClassNotFoundException e) + { + throw new IllegalArgumentException(e); + } + } + } + + private SeContainerInitializer newInitializerInstance(final Class<? extends SeContainerInitializer> type) + { + if (type == OWBInitializer.class) + { + final OWBInitializer initializer = new OWBInitializer(); + // in this mode force some SPI impl since when you force a provider you want to fix some ambiguity + // and these services can easily conflict with meecrowave for example + initializer.addProperty(ContainerLifecycle.class.getName(), StandaloneLifeCycle.class.getName()); + initializer.addProperty(ContextsService.class.getName(), StandaloneContextsService.class.getName()); + initializer.addProperty(ConversationService.class.getName(), DefaultConversationService.class.getName()); + return initializer; + } + try + { + return type.getDeclaredConstructor().newInstance(); + } + catch (final NoSuchMethodException | InstantiationException | IllegalAccessException e) + { + throw new IllegalArgumentException(e); + } + catch (final InvocationTargetException e) + { + throw new IllegalArgumentException(e.getTargetException()); + } } }