Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/BundleContextBean.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/BundleContextBean.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/BundleContextBean.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/BundleContextBean.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,98 @@ +/** + * 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.bean; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.Set; + +import javax.enterprise.context.Dependent; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.InjectionPoint; + +import org.apache.aries.cdi.container.internal.literal.AnyLiteral; +import org.apache.aries.cdi.container.internal.literal.DefaultLiteral; +import org.apache.aries.cdi.container.internal.util.Sets; +import org.osgi.framework.BundleContext; + +public class BundleContextBean implements Bean<BundleContext> { + + public BundleContextBean(BundleContext bundleContext) { + _bundleContext = bundleContext; + } + + @Override + public BundleContext create(CreationalContext<BundleContext> creationalContext) { + return _bundleContext; + } + + @Override + public void destroy(BundleContext instance, CreationalContext<BundleContext> creationalContext) { + } + + @Override + public Class<?> getBeanClass() { + return BundleContext.class; + } + + @Override + public Set<InjectionPoint> getInjectionPoints() { + return Collections.emptySet(); + } + + @Override + public String getName() { + return "BundleContext"; + } + + @Override + public Set<Annotation> getQualifiers() { + return DEFAULT_QUALIFIERS; + } + + @Override + public Class<? extends Annotation> getScope() { + return Dependent.class; + } + + @Override + public Set<Class<? extends Annotation>> getStereotypes() { + return Collections.emptySet(); + } + + @Override + public Set<Type> getTypes() { + return TYPES; + } + + @Override + public boolean isAlternative() { + return false; + } + + @Override + public boolean isNullable() { + return false; + } + + private static final Set<Annotation> DEFAULT_QUALIFIERS = Sets.hashSet( + DefaultLiteral.INSTANCE, AnyLiteral.INSTANCE); + private static final Set<Type> TYPES = Sets.immutableHashSet(BundleContext.class, Object.class); + + private final BundleContext _bundleContext; + +} \ No newline at end of file
Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ReferenceBean.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ReferenceBean.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ReferenceBean.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ReferenceBean.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,203 @@ +/** + * 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.bean; + +import static org.apache.aries.cdi.container.internal.util.Reflection.cast; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.enterprise.context.Dependent; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.Decorator; +import javax.enterprise.inject.spi.InjectionPoint; + +import org.apache.aries.cdi.container.internal.container.BindType; +import org.apache.aries.cdi.container.internal.literal.AnyLiteral; +import org.apache.aries.cdi.container.internal.literal.DefaultLiteral; +import org.apache.aries.cdi.container.internal.util.Sets; +import org.jboss.weld.injection.CurrentInjectionPoint; +import org.jboss.weld.injection.EmptyInjectionPoint; +import org.jboss.weld.manager.BeanManagerImpl; +import org.jboss.weld.util.Decorators; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReferenceBean implements Bean<Object> { + + public ReferenceBean( + BeanManagerImpl beanManagerImpl, BundleContext bundleContext, Type injectionPointType, Class<?> beanClass, + BindType bindType, ServiceReference<?> serviceReference) { + + _beanManagerImpl = beanManagerImpl; + _bundleContext = bundleContext; + + _typesForMatchingBeansToInjectionPoints = Sets.immutableHashSet(injectionPointType, Object.class); + _beanClass = beanClass; + _bindType = bindType; + _serviceReference = serviceReference; + + _currentInjectionPoint = _beanManagerImpl.getServices().get(CurrentInjectionPoint.class); + _qualifiers = Sets.hashSet(DefaultLiteral.INSTANCE, AnyLiteral.INSTANCE); + } + + public void addQualifier(Annotation annotation) { + _qualifiers.add(annotation); + } + + public void addQualifiers(Set<Annotation> qualifiers) { + _qualifiers.addAll(qualifiers); + } + + @Override + public Object create(CreationalContext<Object> creationalContext) { + return create0(creationalContext); + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void destroy(Object instance, CreationalContext creationalContext) { + if (_serviceObjects == null) { + return; + } + + try { + _serviceObjects.ungetService(instance); + } + catch (Throwable t) { + if (_log.isWarnEnabled()) { + _log.warn("CDIe - UngetService resulted in error", t); + } + } + } + + @Override + public Class<?> getBeanClass() { + return _beanClass; + } + + public BindType getBindType() { + return _bindType; + } + + @Override + public Set<InjectionPoint> getInjectionPoints() { + return Collections.emptySet(); + } + + @Override + public String getName() { + return toString() + "#" + System.identityHashCode(this); + } + + @Override + public Set<Annotation> getQualifiers() { + return _qualifiers; + } + + @Override + public Class<? extends Annotation> getScope() { + return Dependent.class; + } + + @Override + public Set<Class<? extends Annotation>> getStereotypes() { + return Collections.emptySet(); + } + + @Override + public Set<Type> getTypes() { + return _typesForMatchingBeansToInjectionPoints; + } + + @Override + public boolean isAlternative() { + return false; + } + + @Override + public boolean isNullable() { + return false; + } + + @Override + public String toString() { + return "ReferenceBean(" + _serviceReference + ")"; + } + + protected <T> T create0(CreationalContext<T> creationalContext) { + InjectionPoint ip = getInjectionPoint(_currentInjectionPoint); + List<Decorator<?>> decorators = getDecorators(ip); + T instance = cast(getServiceImpl()); + if (decorators.isEmpty()) { + return instance; + } + return Decorators.getOuterDelegate( + cast(this), instance, creationalContext, cast(getBeanClass()), ip, _beanManagerImpl, decorators); + } + + protected List<Decorator<?>> getDecorators(InjectionPoint ip) { + return _beanManagerImpl.resolveDecorators(Collections.singleton(ip.getType()), getQualifiers()); + } + + protected InjectionPoint getInjectionPoint(CurrentInjectionPoint currentInjectionPoint) { + InjectionPoint ip = currentInjectionPoint.peek(); + return EmptyInjectionPoint.INSTANCE.equals(ip) ? null : ip; + } + + protected Object getServiceImpl() { + if (ServiceReference.class.equals(_beanClass)) { + return _serviceReference; + } + else if (Map.class.equals(_beanClass)) { + Map<String, Object> properties = new HashMap<>(); + + for (String key : _serviceReference.getPropertyKeys()) { + properties.put(key, _serviceReference.getProperty(key)); + } + + return properties; + } + + if (_serviceObjects == null) { + _serviceObjects = _bundleContext.getServiceObjects(_serviceReference); + } + + return _serviceObjects.getService(); + } + + private static final Logger _log = LoggerFactory.getLogger(ReferenceBean.class); + + private final Class<?> _beanClass; + private final BindType _bindType; + private final BundleContext _bundleContext; + private final CurrentInjectionPoint _currentInjectionPoint; + private final BeanManagerImpl _beanManagerImpl; + private final Set<Annotation> _qualifiers; + @SuppressWarnings("rawtypes") + private volatile ServiceObjects _serviceObjects; + private final ServiceReference<?> _serviceReference; + private final Set<Type> _typesForMatchingBeansToInjectionPoints; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/command/CdiCommand.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/command/CdiCommand.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/command/CdiCommand.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/command/CdiCommand.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,77 @@ +/** + * 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.command; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.aries.cdi.container.internal.container.CdiContainerState; +import org.apache.aries.cdi.container.internal.container.ExtensionDependency; +import org.apache.aries.cdi.container.internal.container.ReferenceDependency; + +public class CdiCommand { + + public CdiCommand() { + + } + + public void list() { + for (CdiContainerState cdiContainerState : _states.values()) { + System.out.printf("[%s] %s\n", cdiContainerState.getId(), cdiContainerState.getLastState()); + } + } + + public void info(long bundleId) { + CdiContainerState cdiContainerState = _states.get(bundleId); + + if (cdiContainerState == null) { + System.out.println("No matching CDI bundle found."); + + return; + } + + System.out.printf("[%s] %s\n", cdiContainerState.getId(), cdiContainerState.getLastState()); + List<ExtensionDependency> extensionDependencies = cdiContainerState.getExtensionDependencies(); + if (!extensionDependencies.isEmpty()) { + System.out.println(" [EXTENSIONS]"); + for (ExtensionDependency extensionDependency : extensionDependencies) { + System.out.printf(" %s%s\n", extensionDependency.toString(), " ???is this resolved???"); + } + } + List<ReferenceDependency> referenceDependencies = cdiContainerState.getReferenceDependencies(); + if (!referenceDependencies.isEmpty()) { + System.out.println(" [REFERENCES]"); + for (ReferenceDependency referenceDependency : referenceDependencies) { + System.out.printf( + " %s\n Status: %s\n Min Cardinality: %s\n", + referenceDependency.toString(), + !referenceDependency.isResolved() ? " UNRESOLVED" : "resolved", + referenceDependency.getMinCardinality()); + } + } + } + + public void add(Long bundleId, CdiContainerState cdiContainerState) { + _states.put(bundleId, cdiContainerState); + } + + public void remove(Long bundleId) { + _states.remove(bundleId); + } + + private final Map<Long, CdiContainerState> _states = new ConcurrentHashMap<>(); + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,5 @@ +package org.apache.aries.cdi.container.internal.container; + +public enum BindType { + SERVICE, SERVICE_PROPERTIES, SERVICE_REFERENCE +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeployment.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeployment.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeployment.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeployment.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,66 @@ +/** + * 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 javax.enterprise.inject.spi.Extension; + +import org.jboss.weld.bootstrap.api.ServiceRegistry; +import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive; +import org.jboss.weld.bootstrap.spi.CDI11Deployment; +import org.jboss.weld.bootstrap.spi.Metadata; + +public class BundleDeployment implements CDI11Deployment { + + public BundleDeployment(Iterable<Metadata<Extension>> extensions, BeanDeploymentArchive beanDeploymentArchive) { + _extensions = extensions; + _beanDeploymentArchive = beanDeploymentArchive; + + _beanDeploymentArchives = new ArrayList<BeanDeploymentArchive>(); + _beanDeploymentArchives.add(beanDeploymentArchive); + } + + @Override + public BeanDeploymentArchive getBeanDeploymentArchive(Class<?> beanClass) { + return _beanDeploymentArchive; + } + + @Override + public Collection<BeanDeploymentArchive> getBeanDeploymentArchives() { + return _beanDeploymentArchives; + } + + @Override + public Iterable<Metadata<Extension>> getExtensions() { + return _extensions; + } + + @Override + public ServiceRegistry getServices() { + return _beanDeploymentArchive.getServices(); + } + + @Override + public BeanDeploymentArchive loadBeanDeploymentArchive(Class<?> aClass) { + return _beanDeploymentArchive; + } + + private final BeanDeploymentArchive _beanDeploymentArchive; + private final Collection<BeanDeploymentArchive> _beanDeploymentArchives; + private final Iterable<Metadata<Extension>> _extensions; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeploymentArchive.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeploymentArchive.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeploymentArchive.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BundleDeploymentArchive.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,87 @@ +/** + * 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.Collections; + +import org.apache.aries.cdi.container.internal.loader.BundleResourcesLoader; +import org.jboss.weld.bootstrap.api.ServiceRegistry; +import org.jboss.weld.bootstrap.api.helpers.SimpleServiceRegistry; +import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive; +import org.jboss.weld.bootstrap.spi.BeansXml; +import org.jboss.weld.ejb.spi.EjbDescriptor; +import org.jboss.weld.resources.spi.ResourceLoader; +import org.jboss.weld.serialization.spi.ProxyServices; +import org.osgi.framework.Bundle; +import org.osgi.framework.wiring.BundleWiring; + +public class BundleDeploymentArchive implements BeanDeploymentArchive { + + public BundleDeploymentArchive( + BundleWiring bundleWiring, String id, Collection<String> beanClassNames, BeansXml beansXml, + Bundle extenderBundle) { + + _id = id; + _beanClassNames = beanClassNames; + _beanDeploymentArchives = Collections.emptyList(); + _beansXml = beansXml; + _ejbs = Collections.emptyList(); + _services = new SimpleServiceRegistry(); + + BundleResourcesLoader loader = new BundleResourcesLoader(bundleWiring, extenderBundle); + + _services.add(ResourceLoader.class, loader); + _services.add(ProxyServices.class, loader); + } + + @Override + public Collection<String> getBeanClasses() { + return _beanClassNames; + } + + @Override + public Collection<BeanDeploymentArchive> getBeanDeploymentArchives() { + return _beanDeploymentArchives; + } + + @Override + public BeansXml getBeansXml() { + return _beansXml; + } + + @Override + public Collection<EjbDescriptor<?>> getEjbs() { + return _ejbs; + } + + @Override + public String getId() { + return _id; + } + + @Override + public ServiceRegistry getServices() { + return _services; + } + + private final Collection<String> _beanClassNames; + private final Collection<BeanDeploymentArchive> _beanDeploymentArchives; + private final BeansXml _beansXml; + private final Collection<EjbDescriptor<?>> _ejbs; + private final String _id; + private final ServiceRegistry _services; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerService.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerService.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerService.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerService.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,20 @@ +package org.apache.aries.cdi.container.internal.container; + +import javax.enterprise.inject.spi.BeanManager; + +import org.osgi.service.cdi.CdiContainer; + +public class CdiContainerService implements CdiContainer { + + @Override + public BeanManager getBeanManager() { + return _beanManager; + } + + public void setBeanManager(BeanManager beanManager) { + _beanManager = beanManager; + } + + private volatile BeanManager _beanManager; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerState.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerState.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerState.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/CdiContainerState.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,206 @@ +/** + * 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.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; + +import javax.enterprise.inject.Any; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.util.AnnotationLiteral; + +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.cdi.CdiContainer; +import org.osgi.service.cdi.CdiEvent; +import org.osgi.service.cdi.CdiExtenderConstants; +import org.osgi.service.cdi.CdiListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CdiContainerState { + + public static final AnnotationLiteral<Any> ANY = new AnnotationLiteral<Any>() { + private static final long serialVersionUID = 1L; + }; + + public CdiContainerState( + Bundle bundle, Bundle extenderBundle, Map<ServiceReference<CdiListener>, CdiListener> listeners) { + + _bundle = bundle; + _extenderBundle = extenderBundle; + _listeners = listeners; + + _cdiContainerService = new CdiContainerService(); + + Hashtable<String, Object> properties = new Hashtable<>(); + + properties.put(CdiExtenderConstants.CDI_EXTENDER_CONTAINER_STATE, CdiEvent.State.CREATING); + + _cdiContainerRegistration = _bundle.getBundleContext().registerService( + CdiContainer.class, _cdiContainerService, properties); + } + + public void close() { + try { + _lock.lock(); + + _cdiContainerRegistration.unregister(); + } + catch (Exception e) { + if (_log.isTraceEnabled()) { + _log.trace("Service already unregistered {}", _cdiContainerRegistration); + } + } + finally { + _lock.unlock(); + } + } + + public BeanManager getBeanManager() { + return _beanManager; + } + + public Bundle getBundle() { + return _bundle; + } + + public Bundle getExtenderBundle() { + return _extenderBundle; + } + + public List<ExtensionDependency> getExtensionDependencies() { + return _extensionDependencies; + } + + public String getId() { + return _bundle.getSymbolicName() + ":" + _bundle.getBundleId(); + } + + public CdiEvent.State getLastState() { + return _lastState.get(); + } + + public List<ReferenceDependency> getReferenceDependencies() { + return _referenceDependencies; + } + + public void fire(CdiEvent event) { + try { + _lock.lock(); + + if ((_lastState.get() == CdiEvent.State.DESTROYING) && + ((event.getState() == CdiEvent.State.WAITING_FOR_EXTENSIONS) || + (event.getState() == CdiEvent.State.WAITING_FOR_SERVICES))) { + + return; + } + + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Event {}", event, event.getCause()); + } + + updateState(event); + + if (_beanManager != null) { + _beanManager.fireEvent(event); + } + + for (CdiListener listener : _listeners.values()) { + try { + listener.cdiEvent(event); + } + catch (Throwable t) { + if (_log.isErrorEnabled()) { + _log.error("CDIe - CdiListener failed", t); + } + } + } + } + finally { + _lock.unlock(); + } + } + + public void fire(CdiEvent.State state) { + fire(new CdiEvent(state, _bundle, _extenderBundle)); + } + + public void fire(CdiEvent.State state, String payload) { + fire(new CdiEvent(state, _bundle, _extenderBundle, payload, null)); + } + + public void fire(CdiEvent.State state, Throwable cause) { + fire(new CdiEvent(state, _bundle, _extenderBundle, null, cause)); + } + + public void setBeanManager(BeanManager beanManager) { + _beanManager = beanManager; + _cdiContainerService.setBeanManager(beanManager); + } + + public void setExtensionDependencies(List<ExtensionDependency> extensionDependencies) { + _extensionDependencies = extensionDependencies; + } + + public void setReferenceDependency(List<ReferenceDependency> referenceDependencies) { + _referenceDependencies = referenceDependencies; + } + + private void updateState(CdiEvent event) { + try { + _lock.lock(); + + ServiceReference<CdiContainer> reference = _cdiContainerRegistration.getReference(); + + if (event.getState() == reference.getProperty(CdiExtenderConstants.CDI_EXTENDER_CONTAINER_STATE)) { + return; + } + + _lastState.set(event.getState()); + + Hashtable<String, Object> properties = new Hashtable<>(); + + for (String key : reference.getPropertyKeys()) { + properties.put(key, reference.getProperty(key)); + } + + properties.put(CdiExtenderConstants.CDI_EXTENDER_CONTAINER_STATE, event.getState()); + + _cdiContainerRegistration.setProperties(properties); + } + finally { + _lock.unlock(); + } + } + + private static final Logger _log = LoggerFactory.getLogger(CdiContainerState.class); + + private volatile BeanManager _beanManager; + private final Bundle _bundle; + private final ServiceRegistration<CdiContainer> _cdiContainerRegistration; + private final CdiContainerService _cdiContainerService; + private final Bundle _extenderBundle; + private List<ExtensionDependency> _extensionDependencies; + private AtomicReference<CdiEvent.State> _lastState = new AtomicReference<CdiEvent.State>(CdiEvent.State.CREATING); + private final Map<ServiceReference<CdiListener>, CdiListener> _listeners; + private final ReentrantLock _lock = new ReentrantLock(); + private List<ReferenceDependency> _referenceDependencies; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionDependency.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionDependency.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionDependency.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionDependency.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,51 @@ +/** + * 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 javax.enterprise.inject.spi.Extension; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cdi.CdiExtenderConstants; + +public class ExtensionDependency { + + public ExtensionDependency(BundleContext bundleContext, Long bundleId, String name) { + _string = "(&(" + org.osgi.framework.Constants.SERVICE_BUNDLEID + "=" + bundleId + ")(" + + CdiExtenderConstants.CDI_EXTENSION + "=" + name + "))"; + + try { + _filter = bundleContext.createFilter(_string); + } + catch (InvalidSyntaxException ise) { + throw new RuntimeException(ise); + } + } + + public boolean matches(ServiceReference<Extension> reference) { + return _filter.match(reference); + } + + @Override + public String toString() { + return _string; + } + + private final Filter _filter; + private final String _string; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionMetadata.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionMetadata.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionMetadata.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ExtensionMetadata.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,41 @@ +/** + * 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 javax.enterprise.inject.spi.Extension; + +import org.jboss.weld.bootstrap.spi.Metadata; + +public class ExtensionMetadata implements Metadata<Extension> { + + public ExtensionMetadata(Extension extension, String location) { + _extension = extension; + _location = location; + } + + @Override + public Extension getValue() { + return _extension; + } + + @Override + public String getLocation() { + return _location; + } + + private final Extension _extension; + private final String _location; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/FilterBuilder.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/FilterBuilder.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/FilterBuilder.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/FilterBuilder.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,67 @@ +/** + * 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.List; + +import javax.enterprise.inject.spi.Extension; + +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; + +public class FilterBuilder { + + public static Filter createExtensionFilter(List<ExtensionDependency> extentionDependencies) { + try { + StringBuilder sb = new StringBuilder("(&(objectClass=" + Extension.class.getName() + ")"); + + if (extentionDependencies.size() > 1) sb.append("(|"); + + for (ExtensionDependency dependency : extentionDependencies) { + sb.append(dependency.toString()); + } + + if (extentionDependencies.size() > 1) sb.append(")"); + + sb.append(")"); + + return FrameworkUtil.createFilter(sb.toString()); + } + catch (InvalidSyntaxException ise) { + throw new RuntimeException(ise); + } + } + + public static Filter createReferenceFilter(List<ReferenceDependency> referenceDependencies) { + try { + StringBuilder sb = new StringBuilder(); + + if (referenceDependencies.size() > 1) sb.append("(|"); + + for (ReferenceDependency dependency : referenceDependencies) { + sb.append(dependency.toString()); + } + + if (referenceDependencies.size() > 1) sb.append(")"); + + return FrameworkUtil.createFilter(sb.toString()); + } + catch (InvalidSyntaxException ise) { + throw new RuntimeException(ise); + } + } + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_1_Init.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_1_Init.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_1_Init.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_1_Init.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,49 @@ +/** + * 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 org.apache.aries.cdi.container.internal.locate.ClassLocater; +import org.apache.aries.cdi.container.internal.locate.ClassLocaterResult; +import org.jboss.weld.bootstrap.spi.BeansXml; +import org.jboss.weld.xml.BeansXmlParser; +import org.osgi.framework.Bundle; +import org.osgi.framework.wiring.BundleWiring; + +public class Phase_1_Init { + + public Phase_1_Init(Bundle bundle, CdiContainerState cdiContainerState) { + BundleWiring bundleWiring = bundle.adapt(BundleWiring.class); + + ClassLocaterResult locatorResult = ClassLocater.locate(bundleWiring); + Collection<String> beanClassNames = locatorResult.getBeanClassNames(); + BeansXmlParser beansXmlParser = new BeansXmlParser(); + BeansXml beansXml = beansXmlParser.parse(locatorResult.getBeanDescriptorURLs()); + + _extensionPhase = new Phase_2_Extension(bundle, cdiContainerState, beanClassNames, beansXml); + } + + public void close() { + _extensionPhase.close(); + } + + public void open() { + _extensionPhase.open(); + } + + private final Phase_2_Extension _extensionPhase; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_2_Extension.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_2_Extension.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_2_Extension.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_2_Extension.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,188 @@ +/** + * 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.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.enterprise.inject.spi.Extension; + +import org.jboss.weld.bootstrap.spi.BeansXml; +import org.jboss.weld.bootstrap.spi.Metadata; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.wiring.BundleWire; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.cdi.CdiEvent; +import org.osgi.service.cdi.CdiExtenderConstants; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Phase_2_Extension { + + public Phase_2_Extension( + Bundle bundle, CdiContainerState cdiContainerState, Collection<String> beanClassNames, BeansXml beansXml) { + + _bundle = bundle; + _cdiContainerState = cdiContainerState; + _bundleContext = bundle.getBundleContext(); + _extensionDependencies = findExtensionDependencies(bundle.adapt(BundleWiring.class)); + _extensions = new ConcurrentSkipListMap<>(Comparator.reverseOrder()); + _beanClassNames = beanClassNames; + _beansXml = beansXml; + + _cdiContainerState.setExtensionDependencies(_extensionDependencies); + } + + public void close() { + _cdiContainerState.fire(CdiEvent.State.DESTROYING); + + if (_extensionTracker != null) { + _extensionTracker.close(); + + _extensionTracker = null; + } + else { + _referencePhase.close(); + + _referencePhase = null; + } + + _cdiContainerState.fire(CdiEvent.State.DESTROYED); + + _cdiContainerState.close(); + } + + public void open() { + _cdiContainerState.fire(CdiEvent.State.CREATING); + + if (!_extensionDependencies.isEmpty()) { + Filter filter = FilterBuilder.createExtensionFilter(_extensionDependencies); + + _cdiContainerState.fire(CdiEvent.State.WAITING_FOR_EXTENSIONS, filter.toString()); + + _extensionTracker = new ServiceTracker<>(_bundleContext, filter, new ExtensionPhaseCustomizer()); + + _extensionTracker.open(); + } + else { + _referencePhase = new Phase_3_Reference(_bundle, _cdiContainerState, _extensions, _beanClassNames, _beansXml); + + _referencePhase.open(); + } + } + + List<ExtensionDependency> findExtensionDependencies(BundleWiring bundleWiring) { + List<ExtensionDependency> extensionDependencies = new CopyOnWriteArrayList<>(); + List<BundleWire> requiredWires = bundleWiring.getRequiredWires(CdiExtenderConstants.CDI_EXTENSION); + + for (BundleWire wire : requiredWires) { + Map<String, Object> attributes = wire.getCapability().getAttributes(); + + String extension = (String)attributes.get(CdiExtenderConstants.CDI_EXTENSION); + + if (extension != null) { + ExtensionDependency extensionDependency = new ExtensionDependency( + _bundleContext, wire.getProvider().getBundle().getBundleId(), extension); + + extensionDependencies.add(extensionDependency); + } + } + + return extensionDependencies; + } + + private static final Logger _log = LoggerFactory.getLogger(Phase_2_Extension.class); + + private final Collection<String> _beanClassNames; + private final BeansXml _beansXml; + private final Bundle _bundle; + private final BundleContext _bundleContext; + private final CdiContainerState _cdiContainerState; + private final Map<ServiceReference<Extension>, Metadata<Extension>> _extensions; + private final List<ExtensionDependency> _extensionDependencies; + private Phase_3_Reference _referencePhase; + + private ServiceTracker<Extension, ExtensionDependency> _extensionTracker; + + private class ExtensionPhaseCustomizer implements ServiceTrackerCustomizer<Extension, ExtensionDependency> { + + @Override + public ExtensionDependency addingService(ServiceReference<Extension> reference) { + ExtensionDependency trackedDependency = null; + + for (ExtensionDependency extensionDependency : _extensionDependencies) { + if (extensionDependency.matches(reference)) { + _extensionDependencies.remove(extensionDependency); + trackedDependency = extensionDependency; + + Extension extension = _bundleContext.getService(reference); + + _extensions.put(reference, new ExtensionMetadata(extension, reference.getBundle().toString())); + + break; + } + } + + if ((trackedDependency != null) && _extensionDependencies.isEmpty()) { + _referencePhase = new Phase_3_Reference(_bundle, _cdiContainerState, _extensions, _beanClassNames, _beansXml); + + _referencePhase.open(); + } + else if (_log.isDebugEnabled()) { + _log.debug("CDIe - Still waiting for extensions {}", _extensionDependencies); + } + + return trackedDependency; + } + + @Override + public void modifiedService(ServiceReference<Extension> reference, ExtensionDependency extentionDependency) { + } + + @Override + public void removedService(ServiceReference<Extension> reference, ExtensionDependency extentionDependency) { + if (_extensionDependencies.isEmpty()) { + _referencePhase.close(); + + _referencePhase = null; + + _cdiContainerState.fire(CdiEvent.State.WAITING_FOR_EXTENSIONS); + } + _extensions.remove(reference); + + try { + _bundleContext.ungetService(reference); + } + catch (IllegalStateException ise) { + if (_log.isWarnEnabled()) { + _log.warn("CDIe - UngetService resulted in error", ise); + } + } + + _extensionDependencies.add(extentionDependency); + } + + } + +} Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_3_Reference.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_3_Reference.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_3_Reference.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_3_Reference.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,337 @@ +/** + * 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 static org.osgi.namespace.extender.ExtenderNamespace.EXTENDER_NAMESPACE; +import static org.osgi.service.cdi.CdiExtenderConstants.CDI_EXTENDER; +import static org.osgi.service.cdi.CdiExtenderConstants.REQUIREMENT_REFERENCES_DIRECTIVE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.InjectionPoint; + +import org.apache.aries.cdi.container.internal.literal.AnyLiteral; +import org.apache.aries.cdi.container.internal.literal.ReferenceLiteral; +import org.jboss.weld.bootstrap.WeldBootstrap; +import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive; +import org.jboss.weld.bootstrap.spi.BeansXml; +import org.jboss.weld.bootstrap.spi.Deployment; +import org.jboss.weld.bootstrap.spi.Metadata; +import org.jboss.weld.manager.BeanManagerImpl; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.wiring.BundleRequirement; +import org.osgi.framework.wiring.BundleWire; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.cdi.CdiEvent; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Phase_3_Reference { + + public Phase_3_Reference( + Bundle bundle, CdiContainerState cdiContainerState, Map<ServiceReference<Extension>, + Metadata<Extension>> extensions, Collection<String> beanClassNames, BeansXml beansXml) { + + _bundle = bundle; + _cdiContainerState = cdiContainerState; + _extensions = extensions; + _bundleContext = _bundle.getBundleContext(); + _bundleWiring = _bundle.adapt(BundleWiring.class); + _beanClassNames = beanClassNames; + _beansXml = beansXml; + + _cdiContainerState.setReferenceDependency(_referenceDependencies); + } + + public void close() { + if (_serviceTracker != null) { + _serviceTracker.close(); + + _serviceTracker = null; + } + else { + _lock.lock(); + + try { + if (_publishPhase != null) { + _publishPhase.close(); + + _publishPhase = null; + } + } + finally { + _lock.unlock(); + } + } + } + + public void open() { + BeanDeploymentArchive beanDeploymentArchive = new BundleDeploymentArchive( + _bundleWiring, _cdiContainerState.getId(), _beanClassNames, _beansXml, + _cdiContainerState.getExtenderBundle()); + + WeldBootstrap bootstrap = new WeldBootstrap(); + + List<Metadata<Extension>> extensions = new ArrayList<>(); + + // Add the internal extensions + extensions.add( + new ExtensionMetadata(new ReferenceExtension(_referenceDependencies, _bundleContext), _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 : bootstrap.loadExtensions(_bundleWiring.getClassLoader())) { + extensions.add(meta); + } + + // Add external extensions + for (Metadata<Extension> meta : _extensions.values()) { + extensions.add(meta); + } + + Deployment deployment = new BundleDeployment(extensions, beanDeploymentArchive); + + bootstrap.startContainer(_cdiContainerState.getId(), new SimpleEnvironment(), deployment); + + BeanManager beanManager = bootstrap.getManager(beanDeploymentArchive); + + _cdiContainerState.setBeanManager(beanManager); + + bootstrap.startInitialization(); + bootstrap.deployBeans(); + + processRequirementDefinedReferences((BeanManagerImpl)beanManager); + + if (!_referenceDependencies.isEmpty()) { + Filter filter = FilterBuilder.createReferenceFilter(_referenceDependencies); + + _cdiContainerState.fire(CdiEvent.State.WAITING_FOR_SERVICES, filter.toString()); + + _serviceTracker = new ServiceTracker<>(_bundleContext, filter, new ReferencePhaseCustomizer(bootstrap)); + + _serviceTracker.open(); + } + + _lock.lock(); + + try { + if ((_publishPhase == null) && dependenciesAreEmptyOrAllOptional()) { + _publishPhase = new Phase_4_Publish(this, bootstrap); + + _publishPhase.open(); + } + } + finally { + _lock.unlock(); + } + + } + + private boolean dependenciesAreEmptyOrAllOptional() { + if (_referenceDependencies.isEmpty()) { + return true; + } + + for (ReferenceDependency referenceDependency : _referenceDependencies) { + if (referenceDependency.getMinCardinality() > 0) { + return false; + } + } + + return true; + } + + private List<String> getReferenceClassNames() { + List<String> referenceClassNames = new ArrayList<>(); + + BundleWiring bundleWiring = _bundle.adapt(BundleWiring.class); + List<BundleWire> requiredBundleWires = bundleWiring.getRequiredWires(EXTENDER_NAMESPACE); + + for (BundleWire bundleWire : requiredBundleWires) { + Map<String, Object> attributes = bundleWire.getCapability().getAttributes(); + + if (attributes.containsKey(EXTENDER_NAMESPACE) && + attributes.get(EXTENDER_NAMESPACE).equals(CDI_EXTENDER)) { + + BundleRequirement requirement = bundleWire.getRequirement(); + + Map<String, String> directives = requirement.getDirectives(); + + if (directives.containsKey(REQUIREMENT_REFERENCES_DIRECTIVE)) { + String string = directives.get(REQUIREMENT_REFERENCES_DIRECTIVE); + + List<String> references = Arrays.asList(string.split("\\s*,\\s*")); + + if (!references.isEmpty()) { + referenceClassNames.addAll(references); + } + } + } + } + + return referenceClassNames; + } + + private void processReferenceClass(String referenceClassName, BeanManagerImpl beanManagerImpl) { + try { + Class<?> beanClass = _bundle.loadClass(referenceClassName); + + Set<Bean<?>> beans = beanManagerImpl.getBeans(beanClass, AnyLiteral.INSTANCE); + + if (beans.isEmpty()) { + _log.error( + "CDIe - MANIFEST reference processing cannot find bean for class {}", referenceClassName); + + return; + } + + Bean<?> bean = beanManagerImpl.resolve(beans); + + for (InjectionPoint injectionPoint : bean.getInjectionPoints()) { + try { + ReferenceDependency referenceDependency = new ReferenceDependency( + beanManagerImpl, ReferenceLiteral.INSTANCE, injectionPoint); + + _referenceDependencies.add(referenceDependency); + } + catch (InvalidSyntaxException ise) { + _log.error("CDIe - MANIFEST reference processing error", ise); + } + } + } + catch (ClassNotFoundException cnfe) { + _log.error("CDIe - MANIFEST reference processing cannot load class {}", referenceClassName, cnfe); + } + } + + private void processRequirementDefinedReferences(BeanManagerImpl beanManagerImpl) { + List<String> referenceClassNames = getReferenceClassNames(); + + for (String referenceClassName : referenceClassNames) { + processReferenceClass(referenceClassName, beanManagerImpl); + } + } + + private static final Logger _log = LoggerFactory.getLogger(Phase_3_Reference.class); + + private final Collection<String> _beanClassNames; + private final BeansXml _beansXml; + final Bundle _bundle; + private final BundleContext _bundleContext; + private final BundleWiring _bundleWiring; + final CdiContainerState _cdiContainerState; + private final Map<ServiceReference<Extension>, Metadata<Extension>> _extensions; + private final Lock _lock = new ReentrantLock(true); + private Phase_4_Publish _publishPhase; + final List<ReferenceDependency> _referenceDependencies = new CopyOnWriteArrayList<>(); + final List<ServiceDeclaration> _services = new CopyOnWriteArrayList<>(); + + ServiceTracker<?, ?> _serviceTracker; + + private class ReferencePhaseCustomizer implements ServiceTrackerCustomizer<Object, Object> { + + public ReferencePhaseCustomizer(WeldBootstrap bootstrap) { + _bootstrap = bootstrap; + } + + @Override + public Object addingService(ServiceReference<Object> reference) { + _lock.lock(); + + try { + if (_publishPhase != null) { + return null; + } + + boolean matches = false; + boolean resolved = true; + + for (ReferenceDependency referenceDependency : _referenceDependencies) { + if (referenceDependency.matches(reference)) { + referenceDependency.resolve(reference); + matches = true; + } + if (!referenceDependency.isResolved()) { + resolved = false; + } + } + + if (!matches) { + return null; + } + + if (resolved) { + _publishPhase = new Phase_4_Publish(Phase_3_Reference.this, _bootstrap); + + _publishPhase.open(); + } + + return new Object(); + } + finally { + _lock.unlock(); + } + } + + @Override + public void modifiedService(ServiceReference<Object> reference, Object object) { + } + + @Override + public void removedService(ServiceReference<Object> reference, Object object) { + _lock.lock(); + + try { + if (_publishPhase != null) { + _publishPhase.close(); + + _publishPhase = null; + + _cdiContainerState.fire(CdiEvent.State.WAITING_FOR_SERVICES); + } + + for (ReferenceDependency referenceDependency : _referenceDependencies) { + if (referenceDependency.matches(reference)) { + referenceDependency.unresolve(reference); + } + } + } + finally { + _lock.unlock(); + } + } + + private final WeldBootstrap _bootstrap; + + } + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_4_Publish.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_4_Publish.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_4_Publish.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_4_Publish.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,255 @@ +/** + * 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 static org.osgi.namespace.extender.ExtenderNamespace.EXTENDER_NAMESPACE; +import static org.osgi.service.cdi.CdiExtenderConstants.CDI_EXTENDER; +import static org.osgi.service.cdi.CdiExtenderConstants.REQUIREMENT_SERVICES_DIRECTIVE; + +import java.util.ArrayList; +import java.util.Arrays; +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.naming.spi.ObjectFactory; + +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.jboss.weld.bootstrap.api.Bootstrap; +import org.jboss.weld.manager.BeanManagerImpl; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.wiring.BundleRequirement; +import org.osgi.framework.wiring.BundleWire; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.cdi.CdiEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Phase_4_Publish { + + public Phase_4_Publish( + Phase_3_Reference referencePhase, Bootstrap bootstrap) { + + _referencePhase = referencePhase; + _bootstrap = bootstrap; + _bundle = _referencePhase._bundle; + _bundleContext = _referencePhase._bundle.getBundleContext(); + } + + 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); + } + } + } + + if (_objectFactoryRegistration != null) { + try { + _objectFactoryRegistration.unregister(); + } + catch (Exception e) { + if (_log.isTraceEnabled()) { + _log.trace("Service already unregistered {}", _objectFactoryRegistration); + } + } + } + + _bootstrap.shutdown(); + } + + public void open() { + _referencePhase._cdiContainerState.fire(CdiEvent.State.SATISFIED); + + BeanManager beanManager = _referencePhase._cdiContainerState.getBeanManager(); + + processReferenceDependencies((BeanManagerImpl)beanManager); + + _bootstrap.validateBeans(); + _bootstrap.endInitialization(); + + processRequirementDefinedServices((BeanManagerImpl)beanManager); + processServiceDeclarations(); + + _beanManagerRegistration = _bundleContext.registerService( + BeanManager.class, beanManager, null); + + _referencePhase._cdiContainerState.fire(CdiEvent.State.CREATED); + } + + private List<String> getServiceClassNames() { + List<String> serviceClassNames = new ArrayList<>(); + + BundleWiring bundleWiring = _bundle.adapt(BundleWiring.class); + List<BundleWire> requiredBundleWires = bundleWiring.getRequiredWires(EXTENDER_NAMESPACE); + + for (BundleWire bundleWire : requiredBundleWires) { + Map<String, Object> attributes = bundleWire.getCapability().getAttributes(); + + if (attributes.containsKey(EXTENDER_NAMESPACE) && + attributes.get(EXTENDER_NAMESPACE).equals(CDI_EXTENDER)) { + + BundleRequirement requirement = bundleWire.getRequirement(); + + Map<String, String> directives = requirement.getDirectives(); + + if (directives.containsKey(REQUIREMENT_SERVICES_DIRECTIVE)) { + String string = directives.get(REQUIREMENT_SERVICES_DIRECTIVE); + + List<String> services = Arrays.asList(string.split("\\s*,\\s*")); + + if (!services.isEmpty()) { + serviceClassNames.addAll(services); + } + } + } + } + + return serviceClassNames; + } + + private void processReferenceDependencies(BeanManagerImpl beanManagerImpl) { + Map<ServiceReference<?>, Set<ReferenceBean>> beans = new HashMap<>(); + + for (ReferenceDependency referenceDependency : _referencePhase._referenceDependencies) { + 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, _bundleContext, 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) { + List<String> serviceClassNames = getServiceClassNames(); + + for (String serviceClassName : serviceClassNames) { + try { + Class<?> beanClass = _bundle.loadClass(serviceClassName); + + Set<Bean<?>> beans = beanManagerImpl.getBeans(beanClass, AnyLiteral.INSTANCE); + + if (beans.isEmpty()) { + _log.error( + "CDIe - MANIFEST service processing cannot find bean for class {}", serviceClassName); + + continue; + } + + Bean<?> bean = beanManagerImpl.resolve(beans); + CreationalContext<?> creationalContext = beanManagerImpl.createCreationalContext(bean); + ServiceDeclaration serviceDeclaration = new ServiceDeclaration( + ServiceLiteral.INSTANCE, bean, creationalContext); + + processServiceDeclaration(serviceDeclaration); + } + catch (ClassNotFoundException cnfe) { + _log.error("CDIe - MANIFEST service processing cannot load class {}", serviceClassName, cnfe); + } + } + } + + private void processServiceDeclarations() { + for (ServiceDeclaration serviceDeclaration : _referencePhase._services) { + processServiceDeclaration(serviceDeclaration); + } + } + + private void processServiceDeclaration(ServiceDeclaration serviceDeclaration) { + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Publishing bean {} as service.", serviceDeclaration); + } + + String[] classNames = serviceDeclaration.getClassNames(); + Object serviceInstance = serviceDeclaration.getServiceInstance(); + Dictionary<String,Object> properties = serviceDeclaration.getProperties(); + + _registrations.add( + _bundleContext.registerService(classNames, serviceInstance, properties)); + } + + private static final Logger _log = LoggerFactory.getLogger(Phase_4_Publish.class); + + private final Bootstrap _bootstrap; + private final Bundle _bundle; + private final BundleContext _bundleContext; + private final Phase_3_Reference _referencePhase; + private final List<ServiceRegistration<?>> _registrations = new CopyOnWriteArrayList<>(); + + private ServiceRegistration<BeanManager> _beanManagerRegistration; + private ServiceRegistration<ObjectFactory> _objectFactoryRegistration; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceDependency.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceDependency.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceDependency.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceDependency.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,341 @@ +/** + * 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 static org.apache.aries.cdi.container.internal.util.Reflection.cast; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.Comparator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; + +import javax.enterprise.inject.Instance; +import javax.enterprise.inject.spi.InjectionPoint; + +import org.apache.aries.cdi.container.internal.util.Strings; +import org.jboss.weld.manager.BeanManagerImpl; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cdi.annotations.MinCardinality; +import org.osgi.service.cdi.annotations.Reference; +import org.osgi.service.cdi.annotations.ReferenceFilterQualifier; +import org.osgi.service.cdi.annotations.ReferenceScope; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReferenceDependency { + + public ReferenceDependency( + BeanManagerImpl beanManagerImpl, Reference reference, InjectionPoint injectionPoint) + throws InvalidSyntaxException { + + _beanManagerImpl = beanManagerImpl; + _reference = reference; + _injectionPoint = injectionPoint; + + _bindType = getBindType(_injectionPoint.getType()); + _minCardinality = getMinCardinality(_injectionPoint); + _serviceClass = getServiceType(); + + _string = buildFilter(_serviceClass, _injectionPoint.getQualifiers()); + _filter = FrameworkUtil.createFilter(_string); + } + + public Class<?> getBeanClass() { + if (_bindType == BindType.SERVICE_REFERENCE) { + return ServiceReference.class; + } + else if (_bindType == BindType.SERVICE_PROPERTIES) { + return Map.class; + } + + return _serviceClass; + } + + public BindType getBindType() { + return _bindType; + } + + public InjectionPoint getInjectionPoint() { + return _injectionPoint; + } + + public int getMinCardinality() { + return _minCardinality; + } + + public BeanManagerImpl getManager() { + return _beanManagerImpl; + } + + public Reference getReference() { + return _reference; + } + + public Set<ServiceReference<?>> getMatchingReferences() { + return _matchingReferences; + } + + public Type getInjectionPointType() { + Type type = _injectionPoint.getType(); + + if ((type instanceof ParameterizedType)) { + ParameterizedType pType = (ParameterizedType)type; + + if (Instance.class.isAssignableFrom(cast(pType.getRawType()))) { + type = pType.getActualTypeArguments()[0]; + } + } + + return type; + } + + public boolean isResolved() { + return (_matchingReferences.size() >= _minCardinality); + } + + public boolean matches(ServiceReference<?> reference) { + return _filter.match(reference); + } + + public void resolve(ServiceReference<?> reference) { + _matchingReferences.add(reference); + } + + public void unresolve(ServiceReference<?> reference) { + _matchingReferences.remove(reference); + } + + @Override + public String toString() { + return _string; + } + + private String buildFilter(Class<?> serviceType, Set<Annotation> qualifiers) throws InvalidSyntaxException { + String targetFilter = _reference.target(); + + int targetFilterLength = targetFilter.length(); + + if (targetFilterLength > 0) { + FrameworkUtil.createFilter(targetFilter); + } + + StringBuilder sb = new StringBuilder(); + + sb.append("(&("); + sb.append(Constants.OBJECTCLASS); + sb.append("="); + sb.append(serviceType.getName()); + sb.append(")"); + + // TODO add Bundle scope? + + if (_reference.scope() == ReferenceScope.PROTOTYPE) { + sb.append("("); + sb.append(Constants.SERVICE_SCOPE); + sb.append("="); + sb.append(Constants.SCOPE_PROTOTYPE); + sb.append(")"); + } + else if (_reference.scope() == ReferenceScope.SINGLETON) { + sb.append("("); + sb.append(Constants.SERVICE_SCOPE); + sb.append("="); + sb.append(Constants.SCOPE_SINGLETON); + sb.append(")"); + } + + if ((targetFilterLength > 0)) { + sb.append(targetFilter); + } + + for (Annotation qualifier : qualifiers) { + if (qualifier.annotationType().isAnnotationPresent(ReferenceFilterQualifier.class)) { + Class<?> clazz = qualifier.annotationType(); + try { + Method methodValue = clazz.getDeclaredMethod("value"); + String value = String.valueOf(methodValue.invoke(qualifier)); + append(sb, clazz.getSimpleName(), value); + } + catch (ReflectiveOperationException roe) { + Method[] methods = clazz.getDeclaredMethods(); + + for (Method method : methods) { + try { + String value = String.valueOf(method.invoke(qualifier)); + append(sb, method.getName(), value); + } catch (ReflectiveOperationException roe2) { + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Failure in reference filter qualifier processing", roe2); + } + } + } + } + } + } + + sb.append(")"); + + return sb.toString(); + } + + private void append(StringBuilder sb, String simpleName, String value) { + sb.append("("); + sb.append(Strings.camelCase(simpleName)); + sb.append("="); + sb.append(value); + sb.append(")"); + } + + private BindType getBindType(Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = cast(type); + + Type rawType = parameterizedType.getRawType(); + + if (Instance.class.isAssignableFrom(cast(rawType))) { + _instance = true; + + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + + return getBindType(actualTypeArguments[0]); + } + else if (Map.class.isAssignableFrom(cast(rawType))) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + + Type first = actualTypeArguments[0]; + Type second = actualTypeArguments[1]; + + if (!(first instanceof ParameterizedType) && + String.class.isAssignableFrom(cast(first))) { + + if ((!(second instanceof ParameterizedType) && (second == Object.class)) || + (second instanceof WildcardType)) { + + return BindType.SERVICE_PROPERTIES; + } + } + + return BindType.SERVICE; + } + else if (ServiceReference.class.isAssignableFrom(cast(rawType))) { + return BindType.SERVICE_REFERENCE; + } + + return BindType.SERVICE; + } + else if (ServiceReference.class.isAssignableFrom(cast(type))) { + return BindType.SERVICE_REFERENCE; + } + + return BindType.SERVICE; + } + + private int getMinCardinality(InjectionPoint injectionPoint) { + int value = 1; + + if (_instance) { + MinCardinality minCardinality = injectionPoint.getAnnotated().getAnnotation(MinCardinality.class); + + if ((minCardinality != null) && (minCardinality.value() >= 0)) { + value = minCardinality.value(); + } + } + + return value; + } + + private Class<?> getServiceType() { + if (_reference.service() != Object.class) { + return _reference.service(); + } + + Type type = _injectionPoint.getType(); + + if (_bindType == BindType.SERVICE_PROPERTIES) { + throw new IllegalArgumentException( + "A @Reference cannot bind service properties to a Map<String, Object> without " + + "specifying the @Reference.service property: " + _injectionPoint); + } + else if ((_bindType == BindType.SERVICE_REFERENCE) && !(type instanceof ParameterizedType)) { + throw new IllegalArgumentException( + "A @Reference cannot bind a ServiceReference without specifying either the " + + "@Reference.service property or a generic type argument (e.g. ServiceReference<Foo>: " + + _injectionPoint); + } + + if (!(type instanceof ParameterizedType)) { + return cast(type); + } + + ParameterizedType parameterizedType = cast(type); + + Type rawType = parameterizedType.getRawType(); + + if (Instance.class.isAssignableFrom(cast(rawType))) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + + type = actualTypeArguments[0]; + + if (type instanceof ParameterizedType) { + parameterizedType = (ParameterizedType)type; + + rawType = parameterizedType.getRawType(); + } + else { + rawType = type; + } + } + + if (!ServiceReference.class.isAssignableFrom(cast(rawType))) { + return cast(rawType); + } + + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + + Type first = actualTypeArguments[0]; + + if (first instanceof ParameterizedType) { + ParameterizedType parameterizedType1 = cast(first); + + return cast(parameterizedType1.getRawType()); + } + + return cast(first); + } + + private static final Logger _log = LoggerFactory.getLogger(ReferenceDependency.class); + + private final BeanManagerImpl _beanManagerImpl; + private final BindType _bindType; + private final int _minCardinality; + private final Filter _filter; + private final InjectionPoint _injectionPoint; + private final Reference _reference; + private final Set<ServiceReference<?>> _matchingReferences = new ConcurrentSkipListSet<>(Comparator.reverseOrder()); + private final Class<?> _serviceClass; + private final String _string; + + private boolean _instance = false; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceExtension.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceExtension.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceExtension.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ReferenceExtension.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,94 @@ +/** + * 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.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.Annotated; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.BeforeBeanDiscovery; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.ProcessInjectionPoint; + +import org.apache.aries.cdi.container.internal.bean.BundleContextBean; +import org.jboss.weld.bean.builtin.BeanManagerProxy; +import org.jboss.weld.manager.BeanManagerImpl; +import org.osgi.framework.BundleContext; +import org.osgi.service.cdi.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class ReferenceExtension implements Extension { + + public ReferenceExtension(List<ReferenceDependency> referenceDependencies, BundleContext bundleContext) { + _referenceDependencies = referenceDependencies; + _bundleContext = bundleContext; + } + + void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager manager) { + abd.addBean(new BundleContextBean(_bundleContext)); + + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Bean discovery complete"); + } + } + + void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) { + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Bean discovery started"); + } + } + + void processInjectionTarget( + @Observes @SuppressWarnings("rawtypes") ProcessInjectionPoint pip, BeanManager manager) { + + InjectionPoint injectionPoint = pip.getInjectionPoint(); + Annotated annotated = injectionPoint.getAnnotated(); + Reference reference = annotated.getAnnotation(Reference.class); + + if (reference == null) { + return; + } + + try { + BeanManagerImpl beanManagerImpl = ((BeanManagerProxy)manager).delegate(); + + ReferenceDependency referenceDependency = new ReferenceDependency( + beanManagerImpl, reference, injectionPoint); + + _referenceDependencies.add(referenceDependency); + + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Found OSGi service reference {}", referenceDependency); + } + } + catch (Exception e) { + if (_log.isErrorEnabled()) { + _log.error("CDIe - Error on reference {}", reference, e); + } + } + } + + private static final Logger _log = LoggerFactory.getLogger(ReferenceExtension.class); + + private final BundleContext _bundleContext; + private final List<ReferenceDependency> _referenceDependencies; + +} \ No newline at end of file Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceDeclaration.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceDeclaration.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceDeclaration.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceDeclaration.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,184 @@ +/** + * 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.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.inject.Singleton; + +import org.apache.aries.cdi.container.internal.util.Strings; +import org.osgi.framework.Bundle; +import org.osgi.framework.PrototypeServiceFactory; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.cdi.annotations.Service; +import org.osgi.service.cdi.annotations.ServiceProperty; +import org.osgi.service.cdi.annotations.ServicePropertyQualifier; +import org.osgi.util.converter.Converter; +import org.osgi.util.converter.StandardConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceDeclaration { + + @SuppressWarnings({ "rawtypes"}) + public ServiceDeclaration(Service service, Bean bean, CreationalContext creationalContext) { + _service = service; + _bean = bean; + _creationalContext = creationalContext; + + Dictionary<String, Object> properties = new Hashtable<>(); + + for (Object object : bean.getQualifiers()) { + Annotation qualifier = (Annotation)object; + if (qualifier.annotationType().isAnnotationPresent(ServicePropertyQualifier.class)) { + Class<?> clazz = qualifier.annotationType(); + try { + Method methodValue = clazz.getDeclaredMethod("value"); + put(properties, clazz.getSimpleName(), methodValue.invoke(qualifier)); + } + catch (ReflectiveOperationException roe) { + Method[] methods = clazz.getDeclaredMethods(); + + for (Method method : methods) { + try { + put(properties, method.getName(), method.invoke(qualifier)); + } catch (ReflectiveOperationException roe2) { + if (_log.isDebugEnabled()) { + _log.debug("CDIe - Failure in service property qualifier processing", roe2); + } + } + } + } + } + } + + for (ServiceProperty serviceProperty : _service.properties()) { + Type type = serviceProperty.type().getType(); + String[] value = serviceProperty.value().split("\\s*,\\s*"); + + @SuppressWarnings("deprecation") + Object object = _converter.convert(value).to(type); + + properties.put(serviceProperty.key(), object); + } + + _properties = properties; + } + + private void put(Dictionary<String, Object> properties, String simpleName, Object value) { + properties.put(Strings.camelCase(simpleName), value); + } + + @SuppressWarnings("rawtypes") + public Bean getBean() { + return _bean; + } + + public String[] getClassNames() { + List<String> classNames = new ArrayList<>(); + + Class<?>[] types = _service.type(); + + if (types.length > 0) { + for (Type type : types) { + classNames.add(type.getTypeName()); + } + } + else { + types = _bean.getBeanClass().getInterfaces(); + + if (types.length > 0) { + for (Type type : types) { + classNames.add(type.getTypeName()); + } + } + else { + classNames.add(_bean.getBeanClass().getName()); + } + } + + return classNames.toArray(new String[0]); + } + + public Dictionary<String, Object> getProperties() { + return _properties; + } + + @SuppressWarnings({ "unchecked" }) + public Object getServiceInstance() { + Class<?> scope = _bean.getScope(); + if (Singleton.class.isAssignableFrom(scope)) { + return _bean.create(_creationalContext); + } + else if (ApplicationScoped.class.isAssignableFrom(scope)) { + return new BundleScopeWrapper(); + } + + return new PrototypeScopeWrapper(); + } + + @SuppressWarnings("deprecation") + private static final Converter _converter = new StandardConverter(); + + private static final Logger _log = LoggerFactory.getLogger(ServiceDeclaration.class); + + @SuppressWarnings("rawtypes") + private final Bean _bean; + @SuppressWarnings("rawtypes") + private final CreationalContext _creationalContext; + private final Dictionary<String, Object> _properties; + private final Service _service; + + @SuppressWarnings({"rawtypes", "unchecked"}) + private class BundleScopeWrapper implements ServiceFactory { + + @Override + public Object getService(Bundle bundle, ServiceRegistration registration) { + return _bean.create(_creationalContext); + } + + @Override + public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { + _bean.destroy(service, _creationalContext); + } + + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private class PrototypeScopeWrapper implements PrototypeServiceFactory { + + @Override + public Object getService(Bundle bundle, ServiceRegistration registration) { + return _bean.create(_creationalContext); + } + + @Override + public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { + _bean.destroy(service, _creationalContext); + } + + } + +} Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceExtension.java URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceExtension.java?rev=1780127&view=auto ============================================================================== --- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceExtension.java (added) +++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ServiceExtension.java Wed Jan 25 00:08:04 2017 @@ -0,0 +1,51 @@ +/** + * 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.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.ProcessBean; + +import org.osgi.service.cdi.annotations.Service; + +@ApplicationScoped +public class ServiceExtension implements Extension { + + public ServiceExtension(List<ServiceDeclaration> services) { + _services = services; + } + + void processBean(@Observes ProcessBean<?> processBean, BeanManager beanManager) { + Service service = processBean.getAnnotated().getAnnotation(Service.class); + + if (service == null) { + return; + } + + Bean<?> bean = processBean.getBean(); + CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean); + + _services.add(new ServiceDeclaration(service, bean, creationalContext)); + } + + private final List<ServiceDeclaration> _services; + +}