blob: 75636584b8f32362dd1ba0eb9704ce8badc87c15 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.openwebbeans.se;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.config.WebBeansFinder;
import org.apache.webbeans.corespi.DefaultSingletonService;
import org.apache.webbeans.spi.BeanArchiveService;
import org.apache.webbeans.spi.ContainerLifecycle;
import org.apache.webbeans.spi.LoaderService;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.spi.SingletonService;
import org.apache.webbeans.xml.DefaultBeanArchiveInformation;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import javax.enterprise.inject.spi.Extension;
import java.io.IOException;
import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
public class OWBInitializer extends SeContainerInitializer
{
protected final CDISeScannerService scannerService = new CDISeScannerService();
protected final Properties properties = new Properties();
protected final Map<String, Object> services = new HashMap<>();
protected final Collection<Extension> extensions = new ArrayList<>();
protected final DefaultBeanArchiveInformation bai = new DefaultBeanArchiveInformation(CDISeBeanArchiveService.EMBEDDED_URL);
protected ClassLoader loader = Thread.currentThread().getContextClassLoader();
public OWBInitializer()
{
scannerService.loader(loader);
}
@Override
public SeContainer initialize()
{
Thread thread = Thread.currentThread();
ClassLoader old = thread.getContextClassLoader();
thread.setContextClassLoader(loader);
try
{
services.putIfAbsent(ScannerService.class.getName(), getScannerService());
services.putIfAbsent(LoaderService.class.getName(), new CDISeLoaderService(extensions, loader));
services.putIfAbsent(BeanArchiveService.class.getName(), new CDISeBeanArchiveService(bai));
addCustomServices(services);
Map<Class<?>, Object> preparedServices = services.entrySet().stream()
.collect(toMap(e ->
{
try
{
return loader.loadClass(e.getKey());
}
catch (ClassNotFoundException e1)
{
throw new IllegalArgumentException(e1);
}
}, Map.Entry::getValue));
WebBeansContext context = new WebBeansContext(preparedServices, properties);
SingletonService<WebBeansContext> singletonInstance = WebBeansFinder.getSingletonService();
DefaultSingletonService.class.cast(singletonInstance).register(loader, context);
return newContainer(context);
}
finally
{
thread.setContextClassLoader(old);
}
}
protected void addCustomServices(final Map<String, Object> services)
{
// for children classes
}
protected SeContainer newContainer(final WebBeansContext context)
{
Object startObj = new Object();
context.getService(ContainerLifecycle.class).startApplication(startObj);
return new OWBContainer(context, startObj);
}
protected ScannerService getScannerService()
{
return scannerService;
}
@Override
public SeContainerInitializer addBeanClasses(Class<?>... classes)
{
scannerService.classes(classes);
return this;
}
@Override
public SeContainerInitializer addPackages(Package... packages)
{
return addPackages(false, packages);
}
@Override
public SeContainerInitializer addPackages(boolean scanRecursively, Package... packages)
{
scannerService.packages(scanRecursively, packages);
return this;
}
@Override
public SeContainerInitializer addPackages(Class<?>... packageClasses)
{
return addPackages(false, packageClasses);
}
@Override
public SeContainerInitializer addPackages(boolean scanRecursively, Class<?>... packageClasses)
{
scannerService.packages(scanRecursively, packageClasses);
return this;
}
@Override
public SeContainerInitializer enableInterceptors(Class<?>... interceptorClasses)
{
bai.getInterceptors().addAll(Stream.of(interceptorClasses).map(Class::getName).collect(toList()));
return this;
}
@Override
public SeContainerInitializer enableDecorators(Class<?>... decoratorClasses)
{
bai.getDecorators().addAll(Stream.of(decoratorClasses).map(Class::getName).collect(toList()));
return this;
}
@Override
public SeContainerInitializer selectAlternatives(Class<?>... alternativeClasses)
{
bai.getAlternativeClasses().addAll(Stream.of(alternativeClasses).map(Class::getName).collect(toList()));
return this;
}
@Override
public SeContainerInitializer selectAlternativeStereotypes(Class<? extends Annotation>... alternativeStereotypeClasses)
{
bai.getAlternativeStereotypes().addAll(Stream.of(alternativeStereotypeClasses).map(Class::getName).collect(toList()));
return this;
}
@Override
public SeContainerInitializer addExtensions(Extension... extensions)
{
this.extensions.addAll(asList(extensions));
return this;
}
@Override
public SeContainerInitializer addExtensions(Class<? extends Extension>... extensions)
{
this.extensions.addAll(Stream.of(extensions).map(e ->
{
try
{
return e.getConstructor().newInstance();
}
catch (InstantiationException | IllegalAccessException | NoSuchMethodException e1)
{
throw new IllegalArgumentException(e1);
}
catch (InvocationTargetException e1)
{
throw new IllegalArgumentException(e1.getCause());
}
}).collect(toList()));
return this;
}
@Override
public SeContainerInitializer addProperty(final String key, final Object value)
{
switch (key)
{
case "openwebbeans.disableDiscovery":
if ("true".equalsIgnoreCase(String.valueOf(value)))
{
disableDiscovery();
}
break;
case "openwebbeans.classes":
addBeanClasses(list(value, this::loadClass).toArray(Class[]::new));
break;
case "openwebbeans.interceptors":
enableInterceptors(list(value, this::loadClass).toArray(Class[]::new));
break;
case "openwebbeans.decorators":
enableDecorators(list(value, this::loadClass).toArray(Class[]::new));
break;
case "openwebbeans.alternatives":
selectAlternatives(list(value, this::loadClass).toArray(Class[]::new));
break;
case "openwebbeans.stereotypes":
selectAlternativeStereotypes(list(value, this::loadClass).toArray(Class[]::new));
break;
case "openwebbeans.extensions":
addExtensions((Class<? extends Extension>[]) list(value, this::loadClass)
.toArray(Class[]::new));
break;
case "openwebbeans.packages":
addPackages(list(value, this::loadPackage).toArray(Package[]::new));
break;
case "openwebbeans.packages.recursive":
addPackages(true, list(value, this::loadPackage).toArray(Package[]::new));
break;
case "openwebbeans.properties":
{
final Properties properties = new Properties();
try (final StringReader reader = new StringReader(String.valueOf(value)))
{
properties.load(reader);
}
catch (final IOException e)
{
throw new IllegalArgumentException(e);
}
properties.stringPropertyNames().forEach(k -> addProperty(k, properties.getProperty(k)));
break;
}
case "openwebbeans.property.":
{
addProperty(key.substring("openwebbeans.property.".length()), value);
break;
}
default:
if (String.class.isInstance(value))
{
properties.put(key, value);
}
else
{
services.put(key, value);
}
}
return this;
}
@Override
public SeContainerInitializer setProperties(Map<String, Object> properties)
{
properties.forEach(this::addProperty);
return this;
}
@Override
public SeContainerInitializer disableDiscovery()
{
scannerService.disableAutoScanning();
return this;
}
@Override
public SeContainerInitializer setClassLoader(ClassLoader classLoader)
{
loader = classLoader;
scannerService.loader(loader);
return this;
}
private <T> Stream<T> list(final Object list, final Function<Object, T> mapper)
{
if (Collection.class.isInstance(list))
{
return Collection.class.cast(list).stream().map(mapper);
}
return Stream.of(String.valueOf(list).split(","))
.map(String::trim)
.filter(it -> !it.isEmpty())
.map(mapper);
}
private Package loadPackage(final Object obj)
{
if (Package.class.isInstance(obj))
{
return Package.class.cast(obj);
}
final String name = String.valueOf(obj);
try
{
return loader.loadClass(name + ".package-info").getPackage();
}
catch (final ClassNotFoundException e)
{
try
{
return loader.loadClass(name).getPackage();
}
catch (final ClassNotFoundException e1)
{
throw new IllegalArgumentException(e);
}
}
}
private Class loadClass(final Object it)
{
if (Class.class.isInstance(it))
{
return Class.class.cast(it);
}
try
{
return loader.loadClass(String.valueOf(it));
}
catch (final ClassNotFoundException e)
{
throw new IllegalArgumentException(e);
}
}
}