Package org.springmodules.jini

Source Code of org.springmodules.jini.JiniServiceFactoryBean

/**
* Created on Mar 13, 2006
*
* $Id$
* $Revision$
*/
package org.springmodules.jini;

import java.io.IOException;
import java.rmi.RemoteException;

import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.LookupDiscovery;
import net.jini.lookup.entry.Name;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.NestedRuntimeException;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteLookupFailureException;

/**
* JiniServiceFactoryBean for JINI environments. The class is made up from various samples found on jini.org
* customized in a Spring specific way. The search will be executed using the provided ServiceTemplate
* or, if it is null, one will be created using the serviceClass and serviceName. If the lookup operation
* times out (30 seconds by default), a null service will be returned.
* For most cases the serviceClass and serviceNames are enought and hide the jini details from the client.
* <p/>
* The factoryBean can be configured to do a lookup each time before returning the object type by setting
* the "singleton" property to false.
*  
* @author Costin Leau
*
*/
public class JiniServiceFactoryBean extends AbstractFactoryBean {
  private static final Log log = LogFactory.getLog(JiniServiceFactoryBean.class);

  private ServiceTemplate template;
  // utility properties
  private Class serviceClass;
  private String serviceName;

  private String[] groups = LookupDiscovery.ALL_GROUPS;
  // 30 secs
  private long timeout = 30 * 1000;
  // used to pass out information from inner classes
  private Object proxy;

  /**
   * @see org.springmodules.beans.factory.FactoryBean#getObjectType()
   */
  public Class getObjectType() {
    // try to discover the class type if possible to make it work with autowiring
    if (proxy == null) {
      // no template - look at serviceClass
      if (template == null) {
        return (serviceClass == null ? null : serviceClass);
      }

      // look at the template and
      // return the first class from the template (if there is one)
      if (template.serviceTypes != null && template.serviceTypes.length > 0)
        return template.serviceTypes[0];

    }
    return proxy.getClass();
  }

  /**
   * @see org.springmodules.beans.factory.config.AbstractFactoryBean#createInstance()
   */
  protected Object createInstance() throws Exception {
    ServiceTemplate templ;

    if (template == null) {
      Class[] types = (serviceClass == null ? null : new Class[] { serviceClass });
      Entry[] entry = (serviceName == null ? null : new Entry[] { new Name(serviceName) });

      templ = new ServiceTemplate(null, types, entry);
    }
    else
      templ = template;

    final ServiceTemplate finalTemplate = templ;

    LookupDiscovery lookupDiscovery = null;

    try {
      lookupDiscovery = new LookupDiscovery(groups);

      // hook listener for finding the service
      lookupDiscovery.addDiscoveryListener(new DiscoveryListener() {
        public void discovered(DiscoveryEvent ev) {
          log.debug("received discovery event " + ev);
          ServiceRegistrar[] reg = ev.getRegistrars();
          // once the proxy if found, bail out
          for (int i = 0; i < reg.length && proxy == null; i++) {
            findService(finalTemplate, reg[i]);
          }
        }

        public void discarded(DiscoveryEvent ev) {
        }
      });

      if (log.isDebugEnabled())
        log.debug("Awaiting discovery event...");

      if (proxy == null) {
        synchronized (this) {
          this.wait(timeout);
        }
      }

      if (log.isDebugEnabled())
        log.debug("Terminating discovery service");

    }
    catch (IOException e) {
      throw new RemoteLookupFailureException("cannot create lookup discovery", e);
    }
    catch (InterruptedException e) {
      throw new NestedRuntimeException("lookup interrupted", e) {
      };
    }
    finally {
      // make sure to close the lookup threads
      if (lookupDiscovery != null)
        lookupDiscovery.terminate();
    }

    return proxy;
  }

  /**
   * Find the service and notify once it is found.
   *
   * @param templ
   * @param lus
   */
  private void findService(ServiceTemplate templ, ServiceRegistrar lus) {
    try {
      synchronized (this) {

        proxy = lus.lookup(templ);

        //System.out.println(lus.lookup(new ServiceTemplate(null,
        //    new Class[] { TransactionManager.class }, null)));

        if (proxy != null) {
          if (log.isDebugEnabled())
            log.debug("Discovered proxy " + proxy.getClass());
          this.notify();
        }
        else {
          if (log.isDebugEnabled())
            log.debug("template " + templ + " not found in registrar " + lus);
        }
      }
    }
    catch (RemoteException re) {
      throw new RemoteAccessException("can not find service", re);
    }
  }

  /**
   * @return Returns the groups.
   */
  public String[] getGroups() {
    return groups;
  }

  /**
   * @param groups The groups to set.
   */
  public void setGroups(String[] groups) {
    this.groups = groups;
  }

  /**
   * @return Returns the serviceClass.
   */
  public Class getServiceClass() {
    return serviceClass;
  }

  /**
   * @param serviceClass The serviceClass to set.
   */
  public void setServiceClass(Class serviceClass) {
    this.serviceClass = serviceClass;
  }

  /**
   * @return Returns the serviceName.
   */
  public String getServiceName() {
    return serviceName;
  }

  /**
   * @param serviceName The serviceName to set.
   */
  public void setServiceName(String serviceName) {
    this.serviceName = serviceName;
  }

  /**
   * @return Returns the template.
   */
  public ServiceTemplate getTemplate() {
    return template;
  }

  /**
   * @param template The template to set.
   */
  public void setTemplate(ServiceTemplate template) {
    this.template = template;
  }

  /**
   * @return Returns the timeout.
   */
  public long getTimeout() {
    return timeout;
  }

  /**
   * @param timeout The timeout to set.
   */
  public void setTimeout(long timeout) {
    this.timeout = timeout;
  }

}
TOP

Related Classes of org.springmodules.jini.JiniServiceFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.