/** * 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.ArrayList; import java.util.Collection; import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionPoint; import org.apache.aries.cdi.container.internal.bean.ConfigurationBean; import org.apache.aries.cdi.container.internal.bean.ReferenceBean; import org.apache.aries.cdi.container.internal.literal.AnyLiteral; import org.apache.aries.cdi.container.internal.literal.ServiceLiteral; import org.apache.aries.cdi.container.internal.model.ServiceModel; import org.jboss.weld.bootstrap.WeldBootstrap; import org.jboss.weld.manager.BeanManagerImpl; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cdi.CdiEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Phase_Publish implements Phase { public Phase_Publish(BootstrapContainer bc) { _bc = bc; } @Override public void close() { for (ServiceRegistration<?> registration : _registrations) { try { registration.unregister(); } catch (IllegalStateException ise) { if (_log.isTraceEnabled()) { _log.trace("Service already unregistered {}", registration); } } } _registrations.clear(); if (_beanManagerRegistration != null) { try { _beanManagerRegistration.unregister(); } catch (Exception e) { if (_log.isTraceEnabled()) { _log.trace( "Service already unregistered {}", _beanManagerRegistration); } } } _bc.shutdown(); } @Override public void open() { _bc.fire(CdiEvent.Type.SATISFIED); BeanManagerImpl beanManagerImpl = _bc.getBeanManagerImpl(); processConfigurationDependencies(beanManagerImpl); processReferenceDependencies(beanManagerImpl); WeldBootstrap bootstrap = _bc.getBootstrap(); bootstrap.validateBeans(); bootstrap.endInitialization(); processRequirementDefinedServices(beanManagerImpl); processServiceDeclarations(); _beanManagerRegistration = _bc.getBundleContext().registerService( BeanManager.class, beanManagerImpl, null); _bc.fire(CdiEvent.Type.CREATED); } private void processConfigurationDependencies(BeanManagerImpl beanManagerImpl) { for (ConfigurationDependency configurationDependency : _bc.getConfigurations()) { InjectionPoint injectionPoint = configurationDependency.getInjectionPoint(); ConfigurationBean bean = new ConfigurationBean( configurationDependency, beanManagerImpl, injectionPoint.getType(), injectionPoint.getQualifiers()); beanManagerImpl.addBean(bean); } } private void processReferenceDependencies(BeanManagerImpl beanManagerImpl) { Map<ServiceReference<?>, Set<ReferenceBean>> beans = new HashMap<>(); for (ReferenceDependency referenceDependency : _bc.getReferences()) { for (ServiceReference<?> matchingReference : referenceDependency.getMatchingReferences()) { Set<ReferenceBean> set = beans.get(matchingReference); if (set == null) { set = new HashSet<>(); beans.put(matchingReference, set); } ReferenceBean existingBean = null; for (ReferenceBean bean : set) { if (bean.getBindType() == referenceDependency.getBindType() && bean.getBeanClass().equals(referenceDependency.getBeanClass()) && bean.getTypes().contains(referenceDependency.getInjectionPointType())) { existingBean = bean; } } if (existingBean != null) { existingBean.addQualifier(referenceDependency.getReference()); existingBean.addQualifiers(referenceDependency.getInjectionPoint().getQualifiers()); } else { ReferenceBean bean = new ReferenceBean( beanManagerImpl, _bc.getBundleContext(), referenceDependency.getInjectionPointType(), referenceDependency.getBeanClass(), referenceDependency.getBindType(), matchingReference); bean.addQualifier(referenceDependency.getReference()); bean.addQualifiers(referenceDependency.getInjectionPoint().getQualifiers()); set.add(bean); beanManagerImpl.addBean(bean); } } } } private void processRequirementDefinedServices(BeanManagerImpl beanManagerImpl) { Collection<ServiceModel> serviceModels = _bc.getServiceModels(); for (ServiceModel serviceModel : serviceModels) { try { Class<?> beanClass = _bc.loadClass(serviceModel.getBeanClass()); Set<Bean<?>> beans = beanManagerImpl.getBeans(beanClass, AnyLiteral.INSTANCE); if (beans.isEmpty()) { _log.error( "CDIe - MANIFEST service processing cannot find bean for class {}", serviceModel.getBeanClass()); continue; } Bean<?> bean = beanManagerImpl.resolve(beans); CreationalContext<?> creationalContext = beanManagerImpl.createCreationalContext(bean); List<String> provides = serviceModel.getProvides(); List<Class<?>> interfaces = new ArrayList<>(); for (String provide : provides) { try { interfaces.add(_bc.loadClass(provide)); } catch (Exception e) { _log.error("CDIe - Failure loading provided interface for service {}", provide); } } ServiceDeclaration serviceDeclaration = new ServiceDeclaration( ServiceLiteral.from(interfaces.toArray(new Class<?>[interfaces.size()]), serviceModel.getProperties()), bean, creationalContext); processServiceDeclaration(serviceDeclaration); } catch (ClassNotFoundException cnfe) { _log.error( "CDIe - MANIFEST service processing cannot load class {}", serviceModel.getBeanClass(), cnfe); } } } private void processServiceDeclarations() { for (ServiceDeclaration serviceDeclaration : _bc.getServices()) { processServiceDeclaration(serviceDeclaration); } } private void processServiceDeclaration(ServiceDeclaration serviceDeclaration) { if (_log.isDebugEnabled()) { _log.debug("CDIe - Publishing bean {} as service.", serviceDeclaration.getBean()); } String[] classNames = serviceDeclaration.getClassNames(); Object serviceInstance = serviceDeclaration.getServiceInstance(); Dictionary<String,Object> properties = serviceDeclaration.getProperties(); _registrations.add( _bc.getBundleContext().registerService(classNames, serviceInstance, properties)); } private static final Logger _log = LoggerFactory.getLogger(Phase_Publish.class); private final BootstrapContainer _bc; private final List<ServiceRegistration<?>> _registrations = new CopyOnWriteArrayList<>(); private ServiceRegistration<BeanManager> _beanManagerRegistration; }