Package org.springmodules.javaspaces

Source Code of org.springmodules.javaspaces.JavaSpaceTemplate

package org.springmodules.javaspaces;

import java.rmi.MarshalledObject;
import java.rmi.RemoteException;

import net.jini.core.entry.Entry;
import net.jini.core.entry.UnusableEntryException;
import net.jini.core.event.EventRegistration;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.lease.Lease;
import net.jini.core.transaction.Transaction;
import net.jini.core.transaction.TransactionException;
import net.jini.space.JavaSpace;

import org.springframework.beans.factory.InitializingBean;
import org.springmodules.jini.JiniUtils;

// TODO properly fix exception handling

/**
* Implementation of the Spring "template" concept for JavaSpaces. Translates
* exceptions into Spring exception hierarchy. Simplifies the performance of
* several operations in a single method.
*
* @author Rod Johnson
* @author Costin Leau
* @see org.springmodules.javaspaces.JavaSpaceCallback
*/
public class JavaSpaceTemplate implements InitializingBean {

  private JavaSpace space;

  /**
   * Required if operations with the space should be ran without a transaction
   * while there is a transaction already taken place.
   *
   */
  private boolean useTransaction = true;

  public JavaSpaceTemplate() {
  }

  /**
   * constructor
   * @param space the space
   */
  public JavaSpaceTemplate(JavaSpace space) {
    this.space = space;
    afterPropertiesSet();
  }

  /**
   * @see org.springmodules.beans.factory.InitializingBean#afterPropertiesSet()
   * @throws IllegalArgumentException in case the JavaSpaces instance is null
   */
  public void afterPropertiesSet() {
    if (space == null)
      throw new IllegalArgumentException("space property is required");
  }

  /**
   * Write using the current transaction.
   *
   * @param entry
   * @param millis
   */
  public Lease write(final Entry entry, final long millis) {
    return (Lease) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException {
        return js.write(entry, tx, millis);
      }
    });
  }

  /**
   * The process of serializing an entry for transmission to a JavaSpaces
   * service will be identical if the same entry is used twice. This is most
   * likely to be an issue with templates that are used repeatedly to search
   * for entries with read or take. The client-side implementations of read
   * and take cannot reasonably avoid this duplicated effort, since they have
   * no efficient way of checking whether the same template is being used
   * without intervening modification. The snapshot method gives the
   * JavaSpaces service implementor a way to reduce the impact of repeated use
   * of the same entry. Invoking snapshot with an Entry will return another
   * Entry object that contains a snapshot of the original entry. Using the
   * returned snapshot entry is equivalent to using the unmodified original
   * entry in all operations on the same JavaSpaces service. Modifications to
   * the original entry will not affect the snapshot. You can snapshot a null
   * template; snapshot may or may not return null given a null template. The
   * entry returned from snapshot will be guaranteed equivalent to the
   * original unmodified object only when used with the space. Using the
   * snapshot with any other JavaSpaces service will generate an
   * IllegalArgumentException unless the other space can use it because of
   * knowledge about the JavaSpaces service that generated the snapshot. The
   * snapshot will be a different object from the original, may or may not
   * have the same hash code, and equals may or may not return true when
   * invoked with the original object, even if the original object is
   * unmodified. A snapshot is guaranteed to work only within the virtual
   * machine in which it was generated. If a snapshot is passed to another
   * virtual machine (for example, in a parameter of an RMI call), using
   * it--even with the same JavaSpaces service--may generate an
   * IllegalArgumentException.
   *
   * @param entry the entry to take a snapshot of.
   * @return a snapshot of the entry.
   */
  public Entry snapshot(final Entry entry) {
    return (Entry) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException {
        return js.snapshot(entry);
      }
    });
  }

  /**
   * Take a matching entry from the space, waiting until one exists. Matching
   * is and timeout done as for read.
   *
   * @param template The template used for matching. Matching is done against
   *            tmpl with null fields being wildcards ("match anything") other
   *            fields being values ("match exactly on the serialized form").
   * @param millis How long the client is willing to wait for a
   *            transactionally proper matching entry. A timeout of NO_WAIT
   *            means to wait no time at all; this is equivalent to a wait of
   *            zero.
   * @return the entry taken from the space
   */
  public Entry take(final Entry template, final long millis) {
    return (Entry) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException, InterruptedException {
        return js.take(template, tx, millis);
      }
    });
  }

  /**
   * Take a matching entry from the space, returning null if there is
   * currently is none. Matching is and timeout done as for read, except that
   * blocking in this call is done only if necessary to wait for transactional
   * state to settle.
   *
   * @param template The template used for matching. Matching is done against
   *            tmpl with null fields being wildcards ("match anything") other
   *            fields being values ("match exactly on the serialized form").
   * @param millis How long the client is willing to wait for a
   *            transactionally proper matching entry. A timeout of NO_WAIT
   *            means to wait no time at all; this is equivalent to a wait of
   *            zero.
   * @return the entry taken from the space
   */
  public Entry takeIfExists(final Entry template, final long millis) {
    return (Entry) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException, InterruptedException {
        return js.takeIfExists(template, tx, millis);
      }
    });
  }

  /**
   * Read any matching entry from the space, returning null if there is
   * currently is none. Matching and timeouts are done as in read, except that
   * blocking in this call is done only if necessary to wait for transactional
   * state to settle.
   *
   * @param template The template used for matching. Matching is done against
   *            tmpl with null fields being wildcards ("match anything") other
   *            fields being values ("match exactly on the serialized form").
   * @param millis How long the client is willing to wait for a
   *            transactionally proper matching entry. A timeout of NO_WAIT
   *            means to wait no time at all; this is equivalent to a wait of
   *            zero.
   * @return a copy of the entry read from the space
   */
  public Entry readIfExists(final Entry template, final long millis) {
    return (Entry) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException, InterruptedException {
        return js.readIfExists(template, tx, millis);
      }
    });
  }

  /**
   * Read any matching entry from the space, blocking until one exists. Return
   * null if the timeout expires.
   *
   * @param template The template used for matching. Matching is done against
   *            tmpl with null fields being wildcards ("match anything") other
   *            fields being values ("match exactly on the serialized form").
   * @param millis How long the client is willing to wait for a
   *            transactionally proper matching entry. A timeout of NO_WAIT
   *            means to wait no time at all; this is equivalent to a wait of
   *            zero.
   * @return a copy of the entry read from the space
   */
  public Entry read(final Entry template, final long millis) {
    return (Entry) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException, InterruptedException {
        return js.read(template, tx, millis);
      }
    });
  }

  /**
   * When entries are written that match this template notify the given
   * listener with a RemoteEvent that includes the handback object. Matching
   * is done as for read.
   *
   * @param template tmpl - The template used for matching. Matching is done
   *            against tmpl with null fields being wildcards ("match
   *            anything") other fields being values ("match exactly on the
   *            serialized form").
   * @param listener The remote event listener to notify.
   * @param millis the requested lease time, in milliseconds
   * @param handback
   * @return An object to send to the listener as part of the event
   *         notification.
   */
  public EventRegistration notify(final Entry template, final RemoteEventListener listener, final long millis,
      final MarshalledObject handback) {

    return (EventRegistration) execute(new JavaSpaceCallback() {
      public Object doInSpace(JavaSpace js, Transaction tx) throws RemoteException, TransactionException,
          UnusableEntryException, InterruptedException {
        return js.notify(template, tx, listener, millis, handback);
      }
    });
  }

  // TODO transaction nesting

  protected Transaction getCurrentTransaction() {
    return JiniUtils.getTransaction(getSpace());
  }

  /**
   * Perform multiple JavaSpaces tasks in a single transaction.
   * @param jsc The javaspace callback
   * @return the result of the execution.
   */
  public Object execute(JavaSpaceCallback jsc) {
    try {
      Transaction tx = (useTransaction ? getCurrentTransaction() : null);
      Object retval = jsc.doInSpace(this.space, tx);
      return retval;
    }
    catch (Exception ex) {
      throw convertSpaceException(ex);
    }
    finally {
    }
  }

  protected RuntimeException convertSpaceException(Exception e) {
    return JiniUtils.convertJiniException(e);
  }

  /**
   * @param space
   */
  public void setSpace(JavaSpace space) {
    this.space = space;
  }

  /**
   *
   * @return the Javaspace this template operates on
   */
  public JavaSpace getSpace() {
    return this.space;
  }

  /**
   * @return Returns the useTransaction.
   */
  public boolean isUseTransaction() {
    return useTransaction;
  }

  /**
   * @param useTransaction
   *            The useTransaction to set.
   */
  public void setUseTransaction(boolean useTransaction) {
    this.useTransaction = useTransaction;
  }

}
TOP

Related Classes of org.springmodules.javaspaces.JavaSpaceTemplate

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.