/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.config.inject; import java.io.Serializable; import java.lang.reflect.Type; import java.lang.annotation.Annotation; import java.util.Iterator; import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.*; import javax.enterprise.inject.spi.*; import javax.enterprise.util.TypeLiteral; import com.caucho.config.inject.InjectManager.ReferenceFactory; import com.caucho.inject.Module; /** * Factory to create instances of a bean. */ @Module public final class InstanceImpl<T> implements Instance<T>, Serializable { private transient InjectManager _cdiManager; private Type _type; private Annotation []_qualifiers; private transient long _version; private transient Set<Bean<?>> _beanSet; private transient ReferenceFactory<T> _factory; private transient InjectionPoint _injectionPoint; InstanceImpl(InjectManager beanManager, Type type, Annotation []bindings, InjectionPoint injectionPoint) { _cdiManager = beanManager; _type = type; _qualifiers = bindings; _beanSet = beanManager.getBeans(type, bindings); _version = beanManager.getVersion(); _injectionPoint = injectionPoint; } /** * Returns an instance of the selected bean */ @Override public T get() { if (_factory == null) { Bean<?> bean = _cdiManager.resolve(_beanSet); if (bean != null) _factory = (ReferenceFactory<T>) _cdiManager.getReferenceFactory(bean); else throw _cdiManager.unsatisfiedException(_type, _qualifiers); } if (_factory != null) { return (T) _factory.create(null, null, _injectionPoint); } else return null; } /** * Restricts the instance given a set of bindings */ @Override public Instance<T> select(Annotation ... bindings) { return new InstanceImpl<T>(_cdiManager, _type, bindings, _injectionPoint); } /** * Restricts the instance to a subtype and bindings. */ @Override public <U extends T> Instance<U> select(Class<U> subtype, Annotation... bindings) { if (bindings == null || bindings.length == 0) bindings = _qualifiers; return new InstanceImpl<U>(_cdiManager, subtype, bindings, _injectionPoint); } /** * Restricts the instance to a subtype and bindings. */ @Override public <U extends T> Instance<U> select(TypeLiteral<U> subtype, Annotation... bindings) { return new InstanceImpl<U>(_cdiManager, subtype.getType(), bindings, _injectionPoint); } @Override public Iterator<T> iterator() { return new InstanceIterator(_cdiManager, getBeanSet().iterator()); } @Override public boolean isAmbiguous() { return getBeanSet().size() > 1; } @Override public boolean isUnsatisfied() { return getBeanSet().size() == 0; } private Set<Bean<?>> getBeanSet() { if (_version != _cdiManager.getVersion()) { _beanSet = _cdiManager.getBeans(_type, _qualifiers); _version = _cdiManager.getVersion(); } return _beanSet; } private Object readResolve() { return new InstanceImpl(InjectManager.create(), _type, _qualifiers, _injectionPoint); } @Override public String toString() { return getClass().getSimpleName() + "[" + _type + "]"; } static class InstanceIterator<T> implements Iterator<T> { private final BeanManager _manager; private final Iterator<Bean<T>> _beanIter; InstanceIterator(BeanManager manager, Iterator<Bean<T>> beanIter) { _manager = manager; _beanIter = beanIter; } public boolean hasNext() { return _beanIter.hasNext(); } public T next() { Bean<T> bean = _beanIter.next(); CreationalContext<?> env = _manager.createCreationalContext(bean); return (T) _manager.getReference(bean, bean.getBeanClass(), env); } public void remove() { throw new UnsupportedOperationException(); } } }