Package com.lightcrafts.media.jai.rmi

Source Code of com.lightcrafts.media.jai.rmi.JAIRMICRIF

/*
* $RCSfile: JAIRMICRIF.java,v $
*
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* Use is subject to license terms.
*
* $Revision: 1.1 $
* $Date: 2005/02/11 04:56:51 $
* $State: Exp $
*/package com.lightcrafts.media.jai.rmi;

import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderContext;
import java.awt.image.renderable.RenderableImage;
import java.rmi.RemoteException;
import java.rmi.Naming;
import java.net.InetAddress;
import java.util.Iterator;
import java.util.Vector;
import com.lightcrafts.mediax.jai.JAI;
import com.lightcrafts.mediax.jai.OperationRegistry;
import com.lightcrafts.mediax.jai.OperationNode;
import com.lightcrafts.mediax.jai.PropertyChangeEventJAI;
import com.lightcrafts.mediax.jai.RenderedOp;
import com.lightcrafts.mediax.jai.remote.RemoteCRIF;
import com.lightcrafts.mediax.jai.remote.JAIRMIDescriptor;
import com.lightcrafts.mediax.jai.remote.NegotiableCapabilitySet;
import com.lightcrafts.mediax.jai.remote.PlanarImageServerProxy;
import com.lightcrafts.mediax.jai.remote.RemoteImagingException;
import com.lightcrafts.mediax.jai.remote.RemoteRenderableOp;
import com.lightcrafts.mediax.jai.remote.RemoteRenderedImage;
import com.lightcrafts.mediax.jai.remote.RemoteRenderedOp;
import com.lightcrafts.mediax.jai.remote.SerializableState;
import com.lightcrafts.mediax.jai.remote.SerializerFactory;
import com.lightcrafts.mediax.jai.remote.SerializableRenderedImage;
import com.lightcrafts.mediax.jai.tilecodec.TileDecoderFactory;
import com.lightcrafts.mediax.jai.util.ImagingListener;
import com.lightcrafts.media.jai.util.ImageUtil;

/**
* An implementation of the <code>RemoteRIF</code> interface for the
* "jairmi" remote imaging protocol.
*/
public class JAIRMICRIF implements RemoteCRIF {

    /**
     * No arg constructor.
     */
    public JAIRMICRIF() {
    }

    /**
     * Maps the operation's output <code>RenderContext</code> into a
     * <code>RenderContext</code> for each of the operation's sources.
     * This is useful for operations that can be expressed in whole or in
     * part simply as alterations in the <code>RenderContext</code>, such as
     * an affine mapping, or operations that wish to obtain lower quality
     * renderings of their sources in order to save processing effort or
     * transmission bandwith.  Some operations, such as blur, can also
     * use this mechanism to avoid obtaining sources of higher quality
     * than necessary.
     *
     * @param serverName    A <code>String</code> specifying the name of the
     *                      server to perform the remote operation on.
     * @param operationName The <code>String</code> specifying the name of the
     *                      operation to be performed remotely.
     * @param i             The index of the source image.
     * @param renderContext The <code>RenderContext</code> being applied to the
     *                      operation.
     * @param paramBlock    A <code>ParameterBlock</code> containing the
     *                      operation's sources and parameters.
     * @param image the <code>RenderableImage</code> being rendered.
     */
    public RenderContext mapRenderContext(String serverName,
            String operationName,
            int i,
            RenderContext renderContext,
            ParameterBlock paramBlock,
            RenderableImage image)
  throws RemoteImagingException {

  // Create the RenderableOp on the server and it's sources on the
  // appropriate machines.
  RemoteRenderableOp rrop = (RemoteRenderableOp)image;
  RenderableRMIServerProxy rmisp = createProxy(rrop);

  SerializableState rcs =
      SerializerFactory.getState(renderContext, null);

  // Perform the mapRenderContext on the server.
  try {
      SerializableState rcpOut =
    rmisp.getImageServer(serverName).mapRenderContext(
                    i,
                    rmisp.getRMIID(),
                    operationName,
                    rcs);
  } catch (RemoteException re) {
            String message = JaiI18N.getString("JAIRMICRIF5");
            sendExceptionToListener(renderContext, message, re);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
  }

  return (RenderContext)rcs.getObject();
    }

    /**
     * Returns the bounding box for the output of the operation,
     * performed on a given set of sources, in rendering-independent
     * space.  The bounds are returned as a <code>Rectangle2D</code>,
     * that is, an axis-aligned rectangle with floating-point corner
     * coordinates.
     *
     * @param serverName    A <code>String</code> specifying the name of the
     *                      server to perform the remote operation on.
     * @param operationName The <code>String</code> specifying the name of the
     *                      operation to be performed remotely.
     * @param paramBlock    A <code>ParameterBlock</code> containing the
     *                      operation's sources and parameters.
     * @return a <code>Rectangle2D</code> specifying the rendering-independent
     * bounding box of the output.
     */
    public Rectangle2D getBounds2D(String serverName,
           String operationName,
           ParameterBlock paramBlock)
  throws RemoteImagingException {

  SerializableState bounds = null;

  // Create a RemoteRenderableOp that represents the operation.
  RemoteRenderableOp original = new RemoteRenderableOp("jairmi",
                   serverName,
                   operationName,
                   paramBlock);

  // Create the RenderableOp on the server alongwith creating the
  // sources on appropriate machines.
  RenderableRMIServerProxy rmisp = createProxy(original);

  try {
      bounds =
    rmisp.getImageServer(serverName).getBounds2D(rmisp.getRMIID(),
                   operationName);
  } catch (RemoteException e) {
            String message = JaiI18N.getString("JAIRMICRIF6");
            sendExceptionToListener(null, message, e);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  }

  return (Rectangle2D.Float)bounds.getObject();
    }

    /**
     * Gets the appropriate instance of the property specified by the name
     * parameter.  This method must determine which instance of a property to
     * return when there are multiple sources that each specify the property.
     *
     * @param paramBlock a ParameterBlock containing the operation's
     *        sources and parameters.
     * @param name a String naming the desired property.
     * @return an object reference to the value of the property requested.
     */
    public Object getProperty(String serverName,
            String operationName,
            ParameterBlock paramBlock,
            String name) throws RemoteImagingException {

  ParameterBlock pb = null;
  if(paramBlock == null){
      pb = new ParameterBlock();
  } else {
      pb = (ParameterBlock)paramBlock.clone();
  }

  // Create a RemoteRenderableOp that represents the operation.
  RemoteRenderableOp original = new RemoteRenderableOp("jairmi",
                   serverName,
                   operationName,
                   paramBlock);

  // Create the RenderableOp on the server alongwith creating the
  // sources on appropriate machines.
  RenderableRMIServerProxy rmisp = createProxy(original);

   try {
      return rmisp.getProperty(name);
  } catch(Exception e) {
            String message = JaiI18N.getString("JAIRMICRIF7");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  }
        return null;
    }

    /**
     * Returns a list of names recognized by getProperty.
     */
    public String[] getPropertyNames(String serverName,
             String operationName)
  throws RemoteImagingException {

  ImageServer remoteImage = getImageServer(serverName);
  try {
      return remoteImage.getPropertyNames(operationName);
  } catch (RemoteException e){
      // Should we be catching Exception or RemoteException
            String message = JaiI18N.getString("JAIRMICRIF8");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  }
        return null;
    }

    private ImageServer getImageServer(String serverName){

  if (serverName == null) {
      try {
    serverName = InetAddress.getLocalHost().getHostAddress();
      } catch(java.net.UnknownHostException e) {
                String message = JaiI18N.getString("RMIServerProxy11");
                sendExceptionToListener(null, message,
                                        new RemoteImagingException(message, e));
//    throw new RuntimeException(e.getMessage());
      }
  }

  // Derive the service name.
  String serviceName =
      new String("rmi://"+serverName+"/"+
           JAIRMIDescriptor.IMAGE_SERVER_BIND_NAME);

  // Look up the remote object.
  try {
      return (ImageServer)Naming.lookup(serviceName);
  } catch(java.rmi.NotBoundException e) {
            String message = JaiI18N.getString("RMIServerProxy12");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  } catch (java.net.MalformedURLException e) {
            String message = JaiI18N.getString("RMIServerProxy12");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
        } catch (java.rmi.RemoteException e) {
            String message = JaiI18N.getString("RMIServerProxy12");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
        }

        return null;
    }

    /**
     * Returns true if successive renderings (that is, calls to
     * create(RenderContext, ParameterBlock)) with the same arguments
     * may produce different results.  This method may be used to
     * determine whether an existing rendering may be cached and
     * reused.  It is always safe to return true.
     */
    public boolean isDynamic(String serverName,
           String operationName)
  throws RemoteImagingException {

  ImageServer remoteImage = getImageServer(serverName);
  try {
      return remoteImage.isDynamic(operationName);
  } catch (RemoteException e){
            String message = JaiI18N.getString("JAIRMICRIF9");
            sendExceptionToListener(null, message,
                                    new RemoteImagingException(message, e));
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  }
        return true;
    }

    /**
     * Creates a <code>RemoteRenderedImage</code> representing the results
     * of an imaging operation (or chain of operations) for a given
     * <code>ParameterBlock</code> and <code>RenderingHints</code>. The
     * <code>RemoteRIF</code> may also query any source images
     * referenced by the <code>ParameterBlock</code> for their dimensions,
     * <code>SampleModel</code>s, properties, etc., as necessary.
     *
     * <p> The <code>create()</code> method can return null if the
     * <code>RemoteRIF</code> (representing the server) is not capable of
     * producing output for the given set of source images and parameters.
     * For example, if a server (represented by a <code>RemoteRIF</code>) is
     * only capable of performing a 3x3 convolution on single-banded image
     * data, and the source image has multiple bands or the convolution
     * Kernel is 5x5, null should be returned.
     *
     * <p> Hints should be taken into account, but can be ignored.
     * The created <code>RemoteRenderedImage</code> may have a property
     * identified by the String HINTS_OBSERVED to indicate which
     * <code>RenderingHints</code> were used to create the image. In addition
     * any <code>RenderedImage</code>s that are obtained via the getSources()
     * method on the created <code>RemoteRenderedImage</code> may have such
     * a property.
     *
     * @param serverName    A <code>String</code> specifying the name of the
     *                      server to perform the remote operation on.
     * @param operationName The <code>String</code> specifying the name of the
     *                      operation to be performed remotely.
     * @param paramBlock    A <code>ParameterBlock</code> containing sources
     *                      and parameters for the
     *                      <code>RemoteRenderedImage</code> to be created.
     * @param hints         A <code>RenderingHints</code> object containing
     *                      hints.
     * @return A <code>RemoteRenderedImage</code> containing the desired
     * output.
     */
    public RemoteRenderedImage create(String serverName,
              String operationName,
              ParameterBlock paramBlock,
              RenderingHints hints)
  throws RemoteImagingException {

  // Create the RenderedOp on the server
  RMIServerProxy rmisp = new RMIServerProxy(serverName,
              operationName,
              paramBlock,
              hints);

  // Check whether there is a RIF on the server that can satisfy this
  // rendering request.
  boolean cbr = rmisp.canBeRendered();

  if (!cbr){
      return null;
  } else {
      return rmisp;
  }
    }

    /**
     * Creates a <code>RemoteRenderedImage</code> representing the results
     * of an imaging operation, whose given old rendering is updated
     * according to the given <code>PropertyChangeEventJAI</code>. This
     * factory method should be used to create a new rendering updated
     * according to the changes reported by the given
     * <code>PropertyChangeEventJAI</code>. The <code>RemoteRIF</code>
     * can query the supplied <code>PlanarImageServerProxy</code> for
     * references to the server name, operation name, parameter block,
     * and rendering hints. The <code>RemoteRIF</code> may also query
     * any source images referenced by the <code>ParameterBlock</code>
     * for their dimensions, <code>SampleModel</code>s, properties, etc.,
     * as necessary.
     *
     * <p> The <code>create()</code> method can return null if the
     * <code>RemoteRIF</code> (representing the server) is not capable of
     * producing output for the given set of source images and parameters.
     * For example, if a server (represented by a <code>RemoteRIF</code>) is
     * only capable of performing a 3x3 convolution on single-banded image
     * data, and the source image has multiple bands or the convolution
     * Kernel is 5x5, null should be returned.
     *
     * <p> Hints should be taken into account, but can be ignored.
     * The created <code>RemoteRenderedImage</code> may have a property
     * identified by the String HINTS_OBSERVED to indicate which
     * <code>RenderingHints</code> were used to create the image. In addition
     * any <code>RenderedImage</code>s that are obtained via the getSources()
     * method on the created <code>RemoteRenderedImage</code> may have such
     * a property.
     *
     * @param oldRendering The old rendering of the imaging operation.
     * @param event        An event that specifies the changes made to the
     *                     imaging operation.
     * @return A <code>RemoteRenderedImage</code> containing the desired
     * output.
     */
    public RemoteRenderedImage create(PlanarImageServerProxy oldRendering,
              OperationNode node,
                     PropertyChangeEventJAI event)
  throws RemoteImagingException {

  if (!(node instanceof RemoteRenderedOp))
      return null;

  String propName = event.getPropertyName();
  RMIServerProxy rmisp;
  if (propName.equals("servername")) {
      rmisp = new RMIServerProxy(oldRendering,
               node,
               (String)event.getNewValue());
  } else if (propName.equals("operationregistry") ||
       propName.equals("protocolname") ||
       propName.equals("protocolandservername")) {

      return create(((RemoteRenderedOp)node).getServerName(),
        node.getOperationName(),
        node.getParameterBlock(),
        node.getRenderingHints());

  } else {
      rmisp = new RMIServerProxy(oldRendering, node, event);
  }

  return rmisp;
    }

    /**
     * Creates a rendering, given a <code>RenderContext</code> and a
     * <code>ParameterBlock</code> containing the operation's sources
     * and parameters.  The output is a <code>RemoteRenderedImage</code>
     * that takes the <code>RenderContext</code> into account to
     * determine its dimensions and placement on the image plane.
     * This method houses the "intelligence" that allows a
     * rendering-independent operation to adapt to a specific
     * <code>RenderContext</code>.
     *
     * @param serverName    A <code>String</code> specifying the name of the
     *                      server to perform the remote operation on.
     * @param operationName The <code>String</code> specifying the name of the
     *                      operation to be performed remotely.
     * @param renderContext The <code>RenderContext</code> specifying the
     *                      rendering context.
     * @param paramBlock    A <code>ParameterBlock</code> containing the
     *                      operation's sources and parameters.
     */
    public RemoteRenderedImage create(String serverName,
              String operationName,
              RenderContext renderContext,
              ParameterBlock paramBlock)
  throws RemoteImagingException {

  // Create the RenderableOp on the server.
  RMIServerProxy rmisp = new RMIServerProxy(serverName,
              operationName,
              paramBlock,
              renderContext,
              true);

  // Cause a rendering to take place, so we can return a RenderedImage
  // since we can't return a RenderableOp.
  Long renderingID = rmisp.getRenderingID();

  // Return an RMIServerProxy that is a link to the rendering on the
  // server.
  return new RMIServerProxy((serverName+"::"+renderingID),
          paramBlock,
          operationName,
          renderContext.getRenderingHints());
    }

    /**
     * Returns the set of capabilities supported by the client object.
     */
    public  NegotiableCapabilitySet getClientCapabilities() {

       OperationRegistry registry =
           JAI.getDefaultInstance().getOperationRegistry();
       String modeName = "tileDecoder";
       String[] descriptorNames = registry.getDescriptorNames(modeName);
       TileDecoderFactory tdf = null;

       // Only non-preference NegotiableCapability objects can be added
       // to this NCS, which is ok, since these represent the capabilities
       // of the client and thus are not preferences as much as they are
       // hard capabilities (i.e. non-preferences)
       NegotiableCapabilitySet capabilities =
           new NegotiableCapabilitySet(false);

       // Note that tileEncoder capabilities cannot be added since there is
       // no way to differentiate between a encoding and a decoding capability
       // within an NCS, and since the client should only be expected to
       // decode, this should be ok.

       Iterator it;
       for (int i=0; i<descriptorNames.length; i++) {

     it = registry.getFactoryIterator(modeName, descriptorNames[i]);
     for (; it.hasNext(); ) {
         tdf = (TileDecoderFactory)it.next();
         capabilities.add(tdf.getDecodeCapability());
     }
       }

       return capabilities;
    }

    // Recursive evaluation of sources.

    /**
     * Create a <code>RenderableRMIServerProxy</code> that represents
     * a remote Renderable operation. This method examines the operation's
     * sources recursively and creates them as needed.
     */
    private RenderableRMIServerProxy createProxy(RemoteRenderableOp rop) {

  ParameterBlock oldPB = rop.getParameterBlock();
  ParameterBlock newPB = (ParameterBlock)oldPB.clone();
  Vector sources = oldPB.getSources();
  newPB.removeSources();

  // Create a new RenderableOp on the server
  ImageServer remoteImage = getImageServer(rop.getServerName());
        ImagingListener listener =
                ImageUtil.getImagingListener(rop.getRenderingHints());
  Long opID = new Long(0L);
  try {
      opID = remoteImage.getRemoteID();
      remoteImage.createRenderableOp(opID,
             rop.getOperationName(),
             newPB);
  } catch (RemoteException e){
            String message = JaiI18N.getString("RMIServerProxy8");
            listener.errorOccurred(message,
                                   new RemoteImagingException(message, e),
                                   this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
  }

  // Now look at the sources of the RenderableOp
  if (sources != null) {

      for (int i = 0; i < sources.size(); i++) {

    Object source = sources.elementAt(i);

    if (source instanceof RemoteRenderedOp) {

        // If source is a RenderedOp on a remote machine, create
        // it on the remote machine.
        RMIServerProxy rmisp =
    (RMIServerProxy)(((RemoteRenderedOp)source).getRendering());

        try {
      if (rmisp.getServerName().equalsIgnoreCase(
              rop.getServerName())) {

          // Both the RenderableOp and this source are on
          // the same server.
          remoteImage.setRenderedSource(opID,
                rmisp.getRMIID(),
                i);
          newPB.setSource(rmisp, i);
      } else {

          // The RenderableOp and this source are on
          // different servers.
          remoteImage.setRenderedSource(
               opID,
               rmisp.getRMIID(),
               rmisp.getServerName(),
               rmisp.getOperationName(),
               i);
          newPB.setSource(rmisp, i);
      }
        } catch (RemoteException e) {
                        String message = JaiI18N.getString("RMIServerProxy6");
                        listener.errorOccurred(message,
                                               new RemoteImagingException(message, e),
                                               this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
        }

    } else if (source instanceof RenderedOp) {

        // If the source is a local RenderedOp, then the only way
        // to access it from a remote machine is to render it and
        // create a SerializableRenderedImage wrapping the
        // rendering, which is set as the source of the remote op.
        RenderedImage ri = ((RenderedOp)source).getRendering();
        try {
      SerializableRenderedImage sri =
          new SerializableRenderedImage(ri);
      remoteImage.setRenderedSource(opID, sri, i);
      newPB.setSource(sri, i);
        } catch (RemoteException e) {
                        String message = JaiI18N.getString("RMIServerProxy6");
                        listener.errorOccurred(message,
                                               new RemoteImagingException(message, e),
                                               this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
        }

    } else if (source instanceof RenderedImage) {

        // If the source is a local RenderedImage, then the only
        // way to access it from a remote machine is by wrapping
        // it in SerializableRenderedImage and then setting the
        // SRI as the source.
        RenderedImage ri = (RenderedImage)source;
        try {
      SerializableRenderedImage sri =
          new SerializableRenderedImage(ri);
      remoteImage.setRenderedSource(opID, sri, i);
      newPB.setSource(sri, i);
        } catch (RemoteException e) {
                        String message = JaiI18N.getString("RMIServerProxy6");
                        listener.errorOccurred(message,
                                               new RemoteImagingException(message, e),
                                               this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
        }

    } else if (source instanceof RemoteRenderableOp) {

        // If the source is a RenderableOp on a remote machine,
        // cause the RenderableOp to be created on the remote
        // machine.
        RenderableRMIServerProxy rrmisp =
      createProxy((RemoteRenderableOp)source);

        try {

      // If the source RenderableOp is on the same server
      // as the RenderableOp that represents the operation
      if (rrmisp.getServerName().equalsIgnoreCase(
              rop.getServerName())) {
          remoteImage.setRenderableSource(opID,
                  rrmisp.getRMIID(),
                  i);
          newPB.setSource(rrmisp, i);
      } else {
          // If the source RenderableOp is on a different
          // server than the RenderableOp that represents
          // the operation
          remoteImage.setRenderableRMIServerProxyAsSource(
                opID,
                rrmisp.getRMIID(),
                rrmisp.getServerName(),
                rrmisp.getOperationName(),
                i);
          newPB.setSource(rrmisp, i);
      }
        } catch (RemoteException e) {
                        String message = JaiI18N.getString("RMIServerProxy6");
                        listener.errorOccurred(message,
                                               new RemoteImagingException(message, e),
                                               this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
        }

    } else if (source instanceof RenderableImage) {

        // If the source is a local RenderableImage, the only way
        // to access it from a remote machine is to wrap it in
        // a SerializableRenderableImage and then set the SRI as
        // the source on the remote operation.
        RenderableImage ri = (RenderableImage)source;
        try {
      SerializableRenderableImage sri =
          new SerializableRenderableImage(ri);
      remoteImage.setRenderableSource(opID, sri, i);
      newPB.setSource(sri, i);
        } catch (RemoteException e) {
                        String message = JaiI18N.getString("RMIServerProxy6");
                        listener.errorOccurred(message,
                                               new RemoteImagingException(message, e),
                                               this, false);
//      throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
        }
    }

      }
  }

  // Create a new RMIServerProxy to access the RenderableOp
  // created at the beginning of this method.
  RenderableRMIServerProxy finalRmisp =
      new RenderableRMIServerProxy(rop.getServerName(),
           rop.getOperationName(),
           newPB,
           opID);
  return finalRmisp;
    }

    private void sendExceptionToListener(RenderContext renderContext,
                                         String message,
                                         Exception e) {
        ImagingListener listener =
            ImageUtil.getImagingListener(renderContext);
        listener.errorOccurred(message,
                               new RemoteImagingException(message, e),
                               this, false);
    }
}
TOP

Related Classes of com.lightcrafts.media.jai.rmi.JAIRMICRIF

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.