/****************************************************************************** * Copyright (c) 2006, 2010 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 * is available at http://www.opensource.org/licenses/apache2.0.php. * You may elect to redistribute this code under either of these licenses. * * Contributors: * VMware Inc. *****************************************************************************/ package org.eclipse.gemini.blueprint.service.exporter.support.internal.support; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.gemini.blueprint.util.OsgiServiceReferenceUtils; import org.springframework.beans.factory.BeanFactory; /** * Class encapsulating the lazy dependency lookup of the target bean. Handles caching as well as the lazy listener * notifications. * * @author Costin Leau */ public class LazyTargetResolver implements UnregistrationNotifier { private final BeanFactory beanFactory; private final String beanName; private final boolean cacheService; private volatile Object target; private final Object lock = new Object(); private final AtomicBoolean activated; private final ListenerNotifier notifier; private volatile ServiceRegistrationDecorator decorator; public LazyTargetResolver(Object target, BeanFactory beanFactory, String beanName, boolean cacheService, ListenerNotifier notifier, boolean lazyListeners) { this.target = target; this.beanFactory = beanFactory; this.beanName = beanName; this.cacheService = cacheService; this.notifier = notifier; this.activated = new AtomicBoolean(!lazyListeners); } public void activate() { if (activated.compareAndSet(false, true)) { // no service registered if (decorator == null) { notifier.callUnregister(null, null); } else { Object target = getBeanIfPossible(); Map properties = (Map) OsgiServiceReferenceUtils.getServicePropertiesSnapshot(decorator.getReference()); notifier.callRegister(target, properties); } } } private Object getBeanIfPossible() { if (target == null) { if (cacheService || beanFactory.isSingleton(beanName)) { getBean(); } } return target; } public Object getBean() { if (target == null) { if (cacheService) { synchronized (lock) { if (target == null) { target = beanFactory.getBean(beanName); } } } else { return beanFactory.getBean(beanName); } } return target; } public Class<?> getType() { return (target == null ? (beanFactory.isSingleton(beanName) ? beanFactory.getBean(beanName).getClass() : beanFactory.getType(beanName)) : target.getClass()); } public void unregister(Map properties) { if (activated.get()) { Object target = getBeanIfPossible(); notifier.callUnregister(target, properties); } } public void setDecorator(ServiceRegistrationDecorator decorator) { this.decorator = decorator; if (decorator != null) { decorator.setNotifier(this); } } public void notifyIfPossible() { if (activated.get() && notifier != null) { Object target = getBeanIfPossible(); Map properties = (Map) OsgiServiceReferenceUtils.getServicePropertiesSnapshot(decorator.getReference()); notifier.callRegister(target, properties); } } // called when the exporter is activated but no service is published public void startupUnregisterIfPossible() { if (activated.get() && notifier != null) { notifier.callUnregister(null, null); } } }