/**
* Licensed 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.aries.cdi.container.internal.container;
import java.util.Collection;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.enterprise.inject.spi.Extension;
import org.apache.aries.cdi.container.internal.literal.ReferenceLiteral;
import org.apache.aries.cdi.container.internal.model.BeansModel;
import org.apache.aries.cdi.container.internal.model.ConfigurationInjectionPoint;
import org.apache.aries.cdi.container.internal.model.ConfigurationModel;
import org.apache.aries.cdi.container.internal.model.ReferenceInjectionPoint;
import org.apache.aries.cdi.container.internal.model.ReferenceModel;
import org.apache.aries.cdi.container.internal.model.ServiceModel;
import org.jboss.weld.bootstrap.WeldBootstrap;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.Deployment;
import org.jboss.weld.bootstrap.spi.Metadata;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.ServiceLoader;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.cdi.CdiEvent.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BootstrapContainer {
public BootstrapContainer(
BundleWiring bundleWiring, Map<ServiceReference<Extension>, Metadata<Extension>> extensions,
CdiContainerState cdiContainerState) {
_bundleWiring = bundleWiring;
_externalExtensions = extensions;
_cdiContainerState = cdiContainerState;
_bundle = _bundleWiring.getBundle();
// Add the internal extensions
_extensions.add(
new ExtensionMetadata(
new ConfigurationExtension(_configurations, _bundle.getBundleContext()), _bundle.toString()));
_extensions.add(
new ExtensionMetadata(
new ReferenceExtension(_references, _bundle.getBundleContext()), _bundle.toString()));
_extensions.add(new ExtensionMetadata(new ServiceExtension(_services), _bundle.toString()));
// Add extensions found from the bundle's classloader, such as those in the Bundle-ClassPath
for (Metadata<Extension> meta : ServiceLoader.load(Extension.class, _bundleWiring.getClassLoader())) {
_extensions.add(meta);
}
// Add external extensions
for (Metadata<Extension> meta : _externalExtensions.values()) {
_extensions.add(meta);
}
BeansModel beansModel = _cdiContainerState.getBeansModel();
BeanDeploymentArchive beanDeploymentArchive = new BundleDeploymentArchive(
bundleWiring, _cdiContainerState.getId(), beansModel.getBeanClassNames(), beansModel.getBeansXml(),
_cdiContainerState.getExtenderBundle());
Deployment deployment = new BundleDeployment(_extensions, beanDeploymentArchive);
_bootstrap = new WeldBootstrap();
_bootstrap.startContainer(_cdiContainerState.getId(), new SimpleEnvironment(), deployment);
_beanManagerImpl = _bootstrap.getManager(beanDeploymentArchive);
_cdiContainerState.setBeanManager(_beanManagerImpl);
_cdiContainerState.setConfigurationDependencies(_configurations);
_cdiContainerState.setReferenceDependencies(_references);
_bootstrap.startInitialization();
_bootstrap.deployBeans();
processDescriptorConfigurations();
processDescriptorReferences();
}
@Override
protected BootstrapContainer clone() {
BootstrapContainer bootstrapContainer = new BootstrapContainer(
_bundleWiring, _externalExtensions, _cdiContainerState);
bootstrapContainer._configurations.clear();
bootstrapContainer._configurations.addAll(_configurations);
return bootstrapContainer;
}
public void fire(Type state) {
_cdiContainerState.fire(state);
}
public void fire(Type state, String payload) {
_cdiContainerState.fire(state, payload);
}
public void fire(Type state, Throwable cause) {
_cdiContainerState.fire(state, cause);
}
public BeanManagerImpl getBeanManagerImpl() {
return _beanManagerImpl;
}
public WeldBootstrap getBootstrap() {
return _bootstrap;
}
public Bundle getBundle() {
return _bundle;
}
public BundleContext getBundleContext() {
return _bundle.getBundleContext();
}
public CdiContainerState getCdiContainerState() {
return _cdiContainerState;
}
public List<ConfigurationDependency> getConfigurations() {
return _configurations;
}
public Collection<ReferenceModel> getReferenceModels() {
return _cdiContainerState.getBeansModel().getReferenceModels();
}
public List<ReferenceDependency> getReferences() {
return _references;
}
public Collection<ServiceModel> getServiceModels() {
return _cdiContainerState.getBeansModel().getServiceModels();
}
public List<ServiceDeclaration> getServices() {
return _services;
}
public boolean hasConfigurations() {
return !_configurations.isEmpty();
}
public boolean hasReferences() {
return !_references.isEmpty();
}
public Class<?> loadClass(String clazz) throws ClassNotFoundException {
return _bundle.loadClass(clazz);
}
public ServiceRegistration<?> registerService(
String[] classNames, Object serviceInstance, Dictionary<String, Object> properties) {
return getBundleContext().registerService(classNames, serviceInstance, properties);
}
public void shutdown() {
_bootstrap.shutdown();
}
private void processConfigurationModel(ConfigurationModel configurationModel) {
try {
Class<?> beanClass = _bundle.loadClass(configurationModel.beanClass());
String[] pids = configurationModel.pids();
ConfigurationDependency configurationDependency = new ConfigurationDependency(
_bundle.getBundleContext(), pids, configurationModel.required(), beanClass.getName(),
new ConfigurationInjectionPoint(beanClass, pids));
_configurations.add(configurationDependency);
}
catch (ClassNotFoundException cnfe) {
_log.error(
"CDIe - osgi bean descriptor configuration processing cannot load class {}",
configurationModel.beanClass(), cnfe);
}
}
private void processDescriptorConfigurations() {
Collection<ConfigurationModel> configurationModels =
_cdiContainerState.getBeansModel().getConfigurationModels();
for (ConfigurationModel configurationModel : configurationModels) {
processConfigurationModel(configurationModel);
}
}
private void processDescriptorReferences() {
Collection<ReferenceModel> referenceModels = _cdiContainerState.getBeansModel().getReferenceModels();
for (ReferenceModel referenceModel : referenceModels) {
processReferenceModel(referenceModel);
}
}
private void processReferenceModel(ReferenceModel referenceModel) {
try {
Class<?> beanClass = _bundle.loadClass(referenceModel.getBeanClass());
ReferenceDependency referenceDependency = new ReferenceDependency(
_beanManagerImpl, ReferenceLiteral.from(referenceModel.getTarget()),
new ReferenceInjectionPoint(beanClass, referenceModel.getTarget()));
_references.add(referenceDependency);
}
catch (ClassNotFoundException cnfe) {
_log.error(
"CDIe - osgi bean descriptor reference processing cannot load class {}",
referenceModel.getBeanClass(), cnfe);
}
catch (InvalidSyntaxException ise) {
_log.error("CDIe - osgi bean descriptor reference processing error", ise);
}
}
private static final Logger _log = LoggerFactory.getLogger(BootstrapContainer.class);
private final BeanManagerImpl _beanManagerImpl;
private final WeldBootstrap _bootstrap;
private final Bundle _bundle;
private final BundleWiring _bundleWiring;
private final CdiContainerState _cdiContainerState;
private final List<ConfigurationDependency> _configurations = new CopyOnWriteArrayList<>();
private final List<Metadata<Extension>> _extensions = new CopyOnWriteArrayList<>();
private final Map<ServiceReference<Extension>, Metadata<Extension>> _externalExtensions;
private final List<ReferenceDependency> _references = new CopyOnWriteArrayList<>();
private final List<ServiceDeclaration> _services = new CopyOnWriteArrayList<>();
}