/** * 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 javax.inject.Named; 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); for (Annotation qualifier : _qualifiers) { if (qualifier.annotationType().equals(Named.class)) { _name = ((Named)qualifier).value(); } } } 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 _name; } @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) { T instance = cast(getServiceImpl()); InjectionPoint ip = getInjectionPoint(_currentInjectionPoint); if (ip == null) { return instance; } List<Decorator<?>> decorators = getDecorators(ip); 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 BeanManagerImpl _beanManagerImpl; private final BindType _bindType; private final BundleContext _bundleContext; private final CurrentInjectionPoint _currentInjectionPoint; private String _name; private final Set<Annotation> _qualifiers; @SuppressWarnings("rawtypes") private volatile ServiceObjects _serviceObjects; private final ServiceReference<?> _serviceReference; private final Set<Type> _typesForMatchingBeansToInjectionPoints; }