Project: Gemini-Blueprint
/******************************************************************************
 * 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(falsetrue)) { 
   // no service registered 
   if (decorator == null) { 
    notifier.callUnregister(nullnull); 
   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(nullnull); 
  
 
}