0001: /*
0002: * $RCSfile: RMIServerProxy.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.1 $
0009: * $Date: 2005/02/11 04:56:52 $
0010: * $State: Exp $
0011: */package com.sun.media.jai.rmi;
0012:
0013: import java.awt.Image;
0014: import java.awt.Rectangle;
0015: import java.awt.RenderingHints;
0016: import java.awt.Shape;
0017: import java.awt.image.ColorModel;
0018: import java.awt.image.Raster;
0019: import java.awt.image.RenderedImage;
0020: import java.awt.image.SampleModel;
0021: import java.awt.image.renderable.RenderContext;
0022: import java.awt.image.renderable.ParameterBlock;
0023: import java.io.ByteArrayInputStream;
0024: import java.io.Serializable;
0025: import java.net.InetAddress;
0026: import java.rmi.Naming;
0027: import java.rmi.RemoteException;
0028: import java.util.Collection;
0029: import java.util.List;
0030: import java.util.Iterator;
0031: import java.util.Vector;
0032: import javax.media.jai.ImageLayout;
0033: import javax.media.jai.JAI;
0034: import javax.media.jai.remote.NegotiableCapability;
0035: import javax.media.jai.OperationRegistry;
0036: import javax.media.jai.OperationDescriptor;
0037: import javax.media.jai.OperationNode;
0038: import javax.media.jai.ParameterListDescriptor;
0039: import javax.media.jai.PlanarImage;
0040: import javax.media.jai.PropertyChangeEventJAI;
0041: import javax.media.jai.PropertySourceChangeEvent;
0042: import javax.media.jai.RenderingChangeEvent;
0043: import javax.media.jai.RenderedOp;
0044: import javax.media.jai.RenderableOp;
0045: import javax.media.jai.TileCache;
0046: import javax.media.jai.remote.JAIRMIDescriptor;
0047: import javax.media.jai.remote.NegotiableCapabilitySet;
0048: import javax.media.jai.remote.RemoteImagingException;
0049: import javax.media.jai.remote.RemoteRenderedOp;
0050: import javax.media.jai.remote.PlanarImageServerProxy;
0051: import javax.media.jai.remote.SerializerFactory;
0052: import javax.media.jai.remote.SerializableState;
0053: import javax.media.jai.remote.SerializableRenderedImage;
0054: import javax.media.jai.tilecodec.TileCodecDescriptor;
0055: import javax.media.jai.tilecodec.TileCodecParameterList;
0056: import javax.media.jai.tilecodec.TileDecoder;
0057: import javax.media.jai.tilecodec.TileDecoderFactory;
0058: import javax.media.jai.tilecodec.TileEncoderFactory;
0059: import javax.media.jai.util.ImagingException;
0060: import javax.media.jai.util.ImagingListener;
0061: import com.sun.media.jai.util.ImageUtil;
0062:
0063: public class RMIServerProxy extends PlanarImageServerProxy {
0064:
0065: /** The server object our data will come from. */
0066: private ImageServer remoteImage = null;
0067:
0068: /** The RMI ID of this object. */
0069: private Long id;
0070:
0071: /**
0072: * The ID associated with the Rendering of the corresponding
0073: * RenderableOp.
0074: */
0075: private Long renderingID = null;
0076:
0077: // Boolean to indicate whether PlanarImageServerProxy set the
0078: // negotiation preferences when super(...) was called.
0079: private boolean preferencesSet;
0080:
0081: // NegotiableCapabilitySet that stores the negotiation preferences
0082: // that were set by PlanarImageServerProxy when super(...) was called.
0083: private NegotiableCapabilitySet negPref;
0084:
0085: // The class of the serializable representation of a NULL property.
0086: private static final Class NULL_PROPERTY_CLASS = com.sun.media.jai.rmi.JAIRMIImageServer.NULL_PROPERTY
0087: .getClass();
0088:
0089: // Cache the listener
0090: private ImagingListener listener;
0091:
0092: /**
0093: * Construct an RMIServerProxy. This constructor should only be used
0094: * when the source is a RenderedOp on a different server.
0095: */
0096: public RMIServerProxy(String serverName, String opName,
0097: RenderingHints hints) {
0098:
0099: super (serverName, "jairmi", opName, null, hints);
0100:
0101: // Look for a separator indicating the remote image chaining hack
0102: // in which case the serverName argument contains host[:port]::id
0103: // where id is the RMI ID of the image on the indicated server.
0104: int index = serverName.indexOf("::");
0105: boolean remoteChaining = index != -1;
0106:
0107: if (!remoteChaining) {
0108: // Don't throw the IllegalArgumentException if it's the hack.
0109: throw new IllegalArgumentException(JaiI18N
0110: .getString("RemoteImage1"));
0111: }
0112:
0113: if (remoteChaining) {
0114: // Extract the RMI ID from the servername string and replace
0115: // the original serverName string with one of the usual type.
0116: id = Long.valueOf(serverName.substring(index + 2));
0117: serverName = serverName.substring(0, index);
0118: super .serverName = serverName;
0119: }
0120:
0121: listener = ImageUtil.getImagingListener(hints);
0122:
0123: remoteImage = getImageServer(serverName);
0124:
0125: if (preferencesSet) {
0126: super .setNegotiationPreferences(negPref);
0127: }
0128:
0129: try {
0130: // Increment the reference count for this id on the server
0131: remoteImage.incrementRefCount(id);
0132: } catch (RemoteException re) {
0133: System.err.println(JaiI18N.getString("RMIServerProxy2"));
0134: }
0135: }
0136:
0137: /**
0138: * Construct an RMIServerProxy. This constructor should only be used
0139: * when the source is a RenderedOp on a different server and the
0140: * ParameterBlock for the source itself is available.
0141: */
0142: public RMIServerProxy(String serverName, ParameterBlock pb,
0143: String opName, RenderingHints hints) {
0144:
0145: super (serverName, "jairmi", opName, pb, hints);
0146:
0147: // Look for a separator indicating the remote image chaining hack
0148: // in which case the serverName argument contains host[:port]::id
0149: // where id is the RMI ID of the image on the indicated server.
0150: int index = serverName.indexOf("::");
0151: boolean remoteChaining = index != -1;
0152:
0153: if (!remoteChaining) {
0154: // Don't throw the IllegalArgumentException if it's the hack.
0155: throw new IllegalArgumentException(JaiI18N
0156: .getString("RemoteImage1"));
0157: }
0158:
0159: if (remoteChaining) {
0160: // Extract the RMI ID from the servername string and replace
0161: // the original serverName string with one of the usual type.
0162: id = Long.valueOf(serverName.substring(index + 2));
0163: serverName = serverName.substring(0, index);
0164: super .serverName = serverName;
0165: }
0166:
0167: listener = ImageUtil.getImagingListener(hints);
0168:
0169: remoteImage = getImageServer(serverName);
0170:
0171: if (preferencesSet) {
0172: super .setNegotiationPreferences(negPref);
0173: }
0174:
0175: try {
0176: // Increment the reference count for this id on the server
0177: remoteImage.incrementRefCount(id);
0178: } catch (RemoteException re) {
0179: System.err.println(JaiI18N.getString("RMIServerProxy2"));
0180: }
0181: }
0182:
0183: /**
0184: * Constructs an RMIServerProxy. This constructor creates nodes on
0185: * the server corresponding to a RemoteRenderedOp on the client.
0186: */
0187: public RMIServerProxy(String serverName, String operationName,
0188: ParameterBlock paramBlock, RenderingHints hints) {
0189:
0190: super (serverName, "jairmi", operationName, paramBlock, hints);
0191:
0192: listener = ImageUtil.getImagingListener(hints);
0193:
0194: // Construct the remote RMI image.
0195: remoteImage = getImageServer(serverName);
0196:
0197: // Get the RMI ID for this object.
0198: getRMIID();
0199:
0200: // If PlanarImageServerProxy had set the preferences during the
0201: // call to the super constructor, then honor that now.
0202: if (preferencesSet)
0203: super .setNegotiationPreferences(negPref);
0204:
0205: // Create a RenderedOp on the server for this operation.
0206: ParameterBlock newPB = (ParameterBlock) paramBlock.clone();
0207: newPB.removeSources();
0208:
0209: // Check to see whether any of the parameters are images
0210: JAIRMIUtil.checkClientParameters(newPB, serverName);
0211:
0212: try {
0213: SerializableState rhs = SerializerFactory.getState(hints,
0214: null);
0215: remoteImage.createRenderedOp(id, operationName, newPB, rhs);
0216: } catch (RemoteException e) {
0217: String message = JaiI18N.getString("RMIServerProxy5");
0218: listener.errorOccurred(message, new RemoteImagingException(
0219: message, e), this , false);
0220: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0221: }
0222:
0223: RenderedImage source;
0224:
0225: int size = getNumSources();
0226: for (int i = 0; i < size; i++) {
0227:
0228: source = getSource(i);
0229:
0230: if (source instanceof RMIServerProxy) {
0231: try {
0232: RMIServerProxy rop = (RMIServerProxy) source;
0233: if (rop.serverName
0234: .equalsIgnoreCase(this .serverName)) {
0235: // Send the id of the source
0236: remoteImage.setRenderedSource(id, rop
0237: .getRMIID(), i);
0238: } else {
0239: remoteImage.setRenderedSource(id, rop
0240: .getRMIID(), rop.serverName,
0241: rop.operationName, i);
0242: }
0243: } catch (RemoteException e) {
0244: String message = JaiI18N
0245: .getString("RMIServerProxy6");
0246: listener.errorOccurred(message,
0247: new RemoteImagingException(e), this , false);
0248: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0249: }
0250:
0251: } else if (source instanceof RenderedOp) {
0252: /// XXX This should not happen, since by the time a
0253: // RMIServerProxy is created, all its sources should already
0254: // have been rendered. In any case, the following deals
0255: // correctly with the situation if it should arise.
0256:
0257: RenderedOp rop = (RenderedOp) source;
0258: RenderedImage rendering = rop.getRendering();
0259: if (!(rendering instanceof Serializable))
0260: rendering = new SerializableRenderedImage(rendering);
0261:
0262: try {
0263: remoteImage.setRenderedSource(id, rendering, i);
0264: } catch (RemoteException e) {
0265: String message = JaiI18N
0266: .getString("RMIServerProxy6");
0267: listener.errorOccurred(message,
0268: new RemoteImagingException(message, e),
0269: this , false);
0270:
0271: /*
0272: throw new RemoteImagingException(
0273: ImageUtil.getStackTraceString(e));
0274: */
0275: }
0276: } else if (source instanceof RenderedImage) {
0277: try {
0278: if (source instanceof Serializable) {
0279: remoteImage.setRenderedSource(id, source, i);
0280: } else {
0281: remoteImage.setRenderedSource(id,
0282: new SerializableRenderedImage(source),
0283: i);
0284: }
0285:
0286: } catch (RemoteException e) {
0287: String message = JaiI18N
0288: .getString("RMIServerProxy6");
0289: listener.errorOccurred(message,
0290: new RemoteImagingException(message, e),
0291: this , false);
0292: /*
0293: throw new RemoteImagingException(
0294: ImageUtil.getStackTraceString(e));
0295: */
0296: }
0297: }
0298: }
0299:
0300: try {
0301: // Increment the reference count for this id on the server
0302: remoteImage.incrementRefCount(id);
0303: } catch (RemoteException re) {
0304: System.err.println(JaiI18N.getString("RMIServerProxy2"));
0305: }
0306: }
0307:
0308: /**
0309: * Creates a <code>RMIServerProxy</code> which is the new rendering
0310: * produced when the serverName is updated.
0311: */
0312: public RMIServerProxy(PlanarImageServerProxy oldRendering,
0313: OperationNode node, String newServerName) {
0314:
0315: // Simply create a new RMIServerProxy that creates a new node
0316: // on the new server.
0317: this (newServerName, node.getOperationName(), node
0318: .getParameterBlock(), node.getRenderingHints());
0319: }
0320:
0321: /**
0322: * Creates a <code>RMIServerProxy</code> which is the new rendering
0323: * produced by updating the given old rendering by the changes
0324: * specified by the given <code>PropertyChangeEventJAI</code>.
0325: */
0326: public RMIServerProxy(PlanarImageServerProxy oldRendering,
0327: OperationNode node, PropertyChangeEventJAI event) {
0328:
0329: super (((RemoteRenderedOp) node).getServerName(), "jairmi", node
0330: .getOperationName(), node.getParameterBlock(), node
0331: .getRenderingHints());
0332:
0333: listener = ImageUtil.getImagingListener(node
0334: .getRenderingHints());
0335:
0336: remoteImage = getImageServer(serverName);
0337:
0338: RMIServerProxy oldRMISP = null;
0339: if (oldRendering instanceof RMIServerProxy) {
0340: oldRMISP = (RMIServerProxy) oldRendering;
0341: } else {
0342: System.err.println(JaiI18N.getString("RMIServerProxy3"));
0343: }
0344:
0345: Long opID = oldRMISP.getRMIID();
0346:
0347: String propName = event.getPropertyName();
0348: if (event instanceof RenderingChangeEvent) {
0349: // Event is a RenderingChangeEvent
0350: RenderingChangeEvent rce = (RenderingChangeEvent) event;
0351:
0352: // Get index of source which changed.
0353: int idx = ((RenderedOp) node).getSources().indexOf(
0354: rce.getSource());
0355:
0356: PlanarImage oldSrcRendering = (PlanarImage) event
0357: .getOldValue();
0358:
0359: Object oldSrc = null;
0360: String serverNodeDesc = null;
0361: if (oldSrcRendering instanceof RMIServerProxy) {
0362:
0363: RMIServerProxy oldSrcRMISP = (RMIServerProxy) oldSrcRendering;
0364:
0365: if (oldSrcRMISP.getServerName().equalsIgnoreCase(
0366: this .serverName) == false) {
0367: serverNodeDesc = oldSrcRMISP.getServerName() + "::"
0368: + oldSrcRMISP.getRMIID();
0369: } else {
0370: serverNodeDesc = oldSrcRMISP.getRMIID().toString();
0371: }
0372: oldSrc = serverNodeDesc;
0373: } else if (oldSrcRendering instanceof Serializable) {
0374: oldSrc = oldSrcRendering;
0375: } else {
0376: oldSrc = new SerializableRenderedImage(oldSrcRendering);
0377: }
0378:
0379: Object srcInvalidRegion = rce.getInvalidRegion();
0380: SerializableState shapeState = SerializerFactory.getState(
0381: (Shape) srcInvalidRegion, null);
0382:
0383: Long oldRenderingID = null;
0384: try {
0385: oldRenderingID = remoteImage.handleEvent(opID, idx,
0386: shapeState, oldSrc);
0387: } catch (RemoteException re) {
0388: String message = JaiI18N.getString("RMIServerProxy7");
0389: listener.errorOccurred(message,
0390: new RemoteImagingException(message, re), this ,
0391: false);
0392:
0393: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0394: }
0395:
0396: oldRMISP.id = oldRenderingID;
0397: this .id = opID;
0398:
0399: } else {
0400:
0401: // Changes to operationName, operationRegistry, protocolName
0402: // and protocolAndServerName should never be sent to this
0403: // constructor and thus don't need to be handled here.
0404:
0405: // Changes to serverName should be sent only to the previous
0406: // constructor and thus do not need to be handled here.
0407:
0408: Object oldValue = null, newValue = null;
0409:
0410: if (propName.equals("operationname")) {
0411:
0412: oldValue = event.getOldValue();
0413: newValue = event.getNewValue();
0414:
0415: } else if (propName.equals("parameterblock")) {
0416:
0417: ParameterBlock oldPB = (ParameterBlock) event
0418: .getOldValue();
0419: Vector oldSrcs = oldPB.getSources();
0420: oldPB.removeSources();
0421:
0422: ParameterBlock newPB = (ParameterBlock) event
0423: .getNewValue();
0424: Vector newSrcs = newPB.getSources();
0425: newPB.removeSources();
0426:
0427: // XXX Check serverName is correct thing to pass
0428: JAIRMIUtil.checkClientParameters(oldPB, serverName);
0429: JAIRMIUtil.checkClientParameters(newPB, serverName);
0430:
0431: oldPB.setSources(JAIRMIUtil.replaceSourcesWithId(
0432: oldSrcs, serverName));
0433: newPB.setSources(JAIRMIUtil.replaceSourcesWithId(
0434: newSrcs, serverName));
0435:
0436: oldValue = oldPB;
0437: newValue = newPB;
0438:
0439: } else if (propName.equals("sources")) {
0440:
0441: Vector oldSrcs = (Vector) event.getOldValue();
0442: Vector newSrcs = (Vector) event.getNewValue();
0443:
0444: oldValue = JAIRMIUtil.replaceSourcesWithId(oldSrcs,
0445: serverName);
0446: newValue = JAIRMIUtil.replaceSourcesWithId(newSrcs,
0447: serverName);
0448:
0449: } else if (propName.equals("parameters")) {
0450:
0451: Vector oldParameters = (Vector) event.getOldValue();
0452: Vector newParameters = (Vector) event.getNewValue();
0453:
0454: // XXX Check serverName is correct thing to pass
0455: JAIRMIUtil.checkClientParameters(oldParameters,
0456: serverName);
0457: JAIRMIUtil.checkClientParameters(newParameters,
0458: serverName);
0459:
0460: oldValue = oldParameters;
0461: newValue = newParameters;
0462:
0463: } else if (propName.equals("renderinghints")) {
0464:
0465: RenderingHints oldRH = (RenderingHints) event
0466: .getOldValue();
0467: RenderingHints newRH = (RenderingHints) event
0468: .getNewValue();
0469:
0470: oldValue = SerializerFactory.getState(oldRH, null);
0471: newValue = SerializerFactory.getState(newRH, null);
0472: } else {
0473: throw new RemoteImagingException(JaiI18N
0474: .getString("RMIServerProxy4"));
0475: }
0476:
0477: Long oldRenderingID = null;
0478:
0479: try {
0480: oldRenderingID = remoteImage.handleEvent(opID,
0481: propName, oldValue, newValue);
0482: // Increment the reference count for this id on the server
0483: remoteImage.incrementRefCount(oldRenderingID);
0484: } catch (RemoteException re) {
0485: String message = JaiI18N.getString("RMIServerProxy7");
0486: listener.errorOccurred(message,
0487: new RemoteImagingException(message, re), this ,
0488: false);
0489: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0490: }
0491:
0492: oldRMISP.id = oldRenderingID;
0493: this .id = opID;
0494: }
0495:
0496: // If PlanarImageServerProxy had set the preferences during the
0497: // call to the super constructor, then honor that now.
0498: if (preferencesSet)
0499: super .setNegotiationPreferences(negPref);
0500: }
0501:
0502: /**
0503: * Create an RMIServerProxy to access an already created operation
0504: * (as specified by the supplied id) on the server.
0505: */
0506: public RMIServerProxy(String serverName, String operationName,
0507: ParameterBlock pb, RenderingHints hints, Long id) {
0508:
0509: super (serverName, "jairmi", operationName, pb, hints);
0510:
0511: listener = ImageUtil.getImagingListener(hints);
0512:
0513: //Construct the the remote ImageServer
0514: remoteImage = getImageServer(serverName);
0515:
0516: this .id = id;
0517: }
0518:
0519: /**
0520: * the RMIServerProxy for the Renderable Layer
0521: */
0522: public RMIServerProxy(String serverName, String operationName,
0523: ParameterBlock paramBlock, RenderContext rc,
0524: boolean isRender) {
0525:
0526: super (serverName, "jairmi", operationName, paramBlock, null);
0527:
0528: listener = ImageUtil.getImagingListener(rc.getRenderingHints());
0529:
0530: //Construct the the remote ImageServer
0531: remoteImage = getImageServer(serverName);
0532:
0533: // get the Remote ID
0534: getRMIID();
0535:
0536: if (preferencesSet)
0537: super .setNegotiationPreferences(negPref);
0538:
0539: // Create a RenderableOp on the server for this operation.
0540:
0541: ParameterBlock newPB = (ParameterBlock) paramBlock.clone();
0542: newPB.removeSources();
0543:
0544: // XXX Since checking to see whether any of the parameters are images
0545: // causes problems with the "renderable" operator (the RenderedOp
0546: // downsampler chain needs to be sent to the server as a RenderedOp,
0547: // and checkClientParameters would make it a RenderedImage), we do
0548: // not do checkClientParameters here (in renderable). This currently
0549: // works because there are no renderable operations which have images
0550: // as parameters. aastha 09/26/01
0551:
0552: try {
0553: remoteImage.createRenderableOp(id, operationName, newPB);
0554: } catch (RemoteException e) {
0555: String message = JaiI18N.getString("RMIServerProxy8");
0556: listener.errorOccurred(message, new RemoteImagingException(
0557: message, e), this , false);
0558: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0559: }
0560:
0561: Object source;
0562: int size = getNumSources();
0563:
0564: for (int i = 0; i < size; i++) {
0565:
0566: Vector sources = paramBlock.getSources();
0567: source = sources.elementAt(i);
0568:
0569: if (source instanceof RMIServerProxy) {
0570: try {
0571: RMIServerProxy rop = (RMIServerProxy) source;
0572: // Send the id of the source
0573: if ((rop.serverName).equals(this .serverName)) {
0574: remoteImage.setRenderableSource(id, rop
0575: .getRMIID(), i);
0576: } else {
0577: remoteImage.setRenderableSource(id, rop
0578: .getRMIID(), rop.serverName,
0579: rop.operationName, i);
0580: }
0581: } catch (RemoteException e) {
0582: String message = JaiI18N
0583: .getString("RMIServerProxy6");
0584: listener.errorOccurred(message,
0585: new RemoteImagingException(message, e),
0586: this , false);
0587: /*
0588: throw new RemoteImagingException(
0589: ImageUtil.getStackTraceString(e));
0590: */
0591: }
0592: } else if (source instanceof RenderableOp) {
0593: try {
0594: remoteImage.setRenderableSource(id,
0595: (RenderableOp) source, i);
0596: } catch (RemoteException e) {
0597: String message = JaiI18N
0598: .getString("RMIServerProxy6");
0599: listener.errorOccurred(message,
0600: new RemoteImagingException(message, e),
0601: this , false);
0602: /*
0603: throw new RemoteImagingException(
0604: ImageUtil.getStackTraceString(e));
0605: */
0606: }
0607: } else if (source instanceof RenderedImage) {
0608: try {
0609: remoteImage.setRenderableSource(id,
0610: new SerializableRenderedImage(
0611: (RenderedImage) source), i);
0612:
0613: } catch (RemoteException e) {
0614: String message = JaiI18N
0615: .getString("RMIServerProxy6");
0616: listener.errorOccurred(message,
0617: new RemoteImagingException(message, e),
0618: this , false);
0619: /*
0620: throw new RemoteImagingException(
0621: ImageUtil.getStackTraceString(e));
0622: */
0623: }
0624: }
0625: }
0626:
0627: try {
0628: // Increment the reference count for this id on the server
0629: remoteImage.incrementRefCount(id);
0630: } catch (RemoteException e) {
0631: String message = JaiI18N.getString("RMIServerProxy9");
0632: listener.errorOccurred(message, new RemoteImagingException(
0633: message, e), this , false);
0634: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0635: }
0636:
0637: // If this was a call for Rendering of this RenderableOp
0638: // then render it and store the associated id in
0639: // renderingID and then RMICRIF will return a new RMISP with reference
0640: // to that rendering ID
0641: // This will not be executed at the time of calls to getBounds2D and
0642: // mapRenderContext
0643:
0644: if (isRender) {
0645: try {
0646: renderingID = remoteImage.getRendering(id,
0647: SerializerFactory.getState(rc, null));
0648: // Increment the reference count for this id on the server
0649: remoteImage.incrementRefCount(renderingID);
0650: } catch (RemoteException e) {
0651: String message = JaiI18N.getString("RMIServerProxy10");
0652: listener.errorOccurred(message,
0653: new RemoteImagingException(message, e), this ,
0654: false);
0655: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0656: }
0657: }
0658: }
0659:
0660: /**
0661: * Construct an ImageServer on the indicated server.
0662: *
0663: * <p> The name of the server must be supplied in the form
0664: * <pre>
0665: * host:port
0666: * </pre>
0667: * where the port number is optional and may be supplied only if
0668: * the host name is supplied. If this parameter is null the default
0669: * is to search for the ImageServer service on the local host at the
0670: * default <i>rmiregistry</i> port (1099).
0671: *
0672: * <p> The result is cached in the instance variable "remoteImage".
0673: *
0674: * @param serverName The name of the server in the format described.
0675: */
0676: protected synchronized ImageServer getImageServer(String serverName) {
0677:
0678: if (remoteImage == null) {
0679:
0680: if (serverName == null) {
0681: try {
0682: serverName = InetAddress.getLocalHost()
0683: .getHostAddress();
0684: } catch (Exception e) {
0685: String message = JaiI18N
0686: .getString("RMIServerProxy11");
0687: listener.errorOccurred(message,
0688: new RemoteImagingException(message, e),
0689: this , false);
0690: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0691: }
0692: }
0693:
0694: // Derive the service name.
0695: String serviceName = new String("rmi://" + serverName + "/"
0696: + JAIRMIDescriptor.IMAGE_SERVER_BIND_NAME);
0697:
0698: // Look up the remote object.
0699: remoteImage = null;
0700: try {
0701: remoteImage = (ImageServer) Naming.lookup(serviceName);
0702: } catch (Exception e) {
0703: String message = JaiI18N.getString("RMIServerProxy12");
0704: listener.errorOccurred(message,
0705: new RemoteImagingException(message, e), this ,
0706: false);
0707: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0708: }
0709: }
0710:
0711: return remoteImage;
0712: }
0713:
0714: /**
0715: * Get the unique ID to be used to refer to this object on the server.
0716: * The result is cached in the instance variable "id".
0717: */
0718: public synchronized Long getRMIID() {
0719:
0720: if (id != null) {
0721: return id;
0722: }
0723:
0724: try {
0725: id = remoteImage.getRemoteID();
0726: return id;
0727: } catch (Exception e) {
0728: String message = JaiI18N.getString("RMIServerProxy13");
0729: listener.errorOccurred(message, new RemoteImagingException(
0730: message, e), this , false);
0731: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0732: }
0733:
0734: return id;
0735: }
0736:
0737: public Long getRenderingID() {
0738: return renderingID;
0739: }
0740:
0741: public boolean canBeRendered() {
0742:
0743: boolean cbr = true; //XXX: please verify
0744: getImageServer(serverName);
0745: try {
0746: cbr = remoteImage.getRendering(getRMIID());
0747: } catch (RemoteException re) {
0748: String message = JaiI18N.getString("RMIServerProxy10");
0749: listener.errorOccurred(message, new RemoteImagingException(
0750: message, re), this , false);
0751: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0752: }
0753:
0754: return cbr;
0755: }
0756:
0757: /*
0758: * Disposes of any resources allocated for remote operation.
0759: */
0760: protected void finalize() {
0761:
0762: try {
0763: remoteImage.dispose(id);
0764: } catch (Exception e) {
0765: // Ignore the Exception.
0766: }
0767:
0768: super .dispose();
0769: }
0770:
0771: /**
0772: * Gets the image layout variables from the server and creates
0773: * an ImageLayout object initialized with these values.
0774: *
0775: * @throws RemoteImagingException if a RemoteException is thrown
0776: * during the RMI communication.
0777: */
0778: public ImageLayout getImageLayout() throws RemoteImagingException {
0779:
0780: ImageLayout layout = new ImageLayout();
0781: try {
0782: layout.setMinX(remoteImage.getMinX(id));
0783: layout.setMinY(remoteImage.getMinY(id));
0784: layout.setWidth(remoteImage.getWidth(id));
0785: layout.setHeight(remoteImage.getHeight(id));
0786: layout.setTileWidth(remoteImage.getTileWidth(id));
0787: layout.setTileHeight(remoteImage.getTileHeight(id));
0788: layout.setTileGridXOffset(remoteImage
0789: .getTileGridXOffset(id));
0790: layout.setTileGridYOffset(remoteImage
0791: .getTileGridYOffset(id));
0792:
0793: SerializableState smState = remoteImage.getSampleModel(id);
0794: layout.setSampleModel((SampleModel) (smState.getObject()));
0795: SerializableState cmState = remoteImage.getColorModel(id);
0796: layout.setColorModel((ColorModel) (cmState.getObject()));
0797: return layout;
0798: } catch (RemoteException re) {
0799: String message = JaiI18N.getString("RMIServerProxy14");
0800: listener.errorOccurred(message, new RemoteImagingException(
0801: message, re), this , false);
0802: return null;
0803: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0804: }
0805: }
0806:
0807: /**
0808: * Gets the requested tile from the server, which does the processing
0809: * to produce the desired tile.
0810: *
0811: * @throws a RemoteImagingException if a RemoteException is thrown
0812: * during the RMI communication.
0813: */
0814: public Raster computeTile(int tileX, int tileY)
0815: throws RemoteImagingException {
0816:
0817: // Return null if the requested tile is outside this image's boundary.
0818: if (tileX < getMinTileX() || tileX > getMaxTileX()
0819: || tileY < getMinTileY() || tileY > getMaxTileY()) {
0820: return null;
0821: }
0822:
0823: // Since "tileCodec" is the only category that we care about or honor
0824: // currently in the remote communication.
0825: NegotiableCapability codecCap = getNegotiatedValue("tileCodec");
0826:
0827: TileDecoderFactory tdf = null;
0828: TileCodecParameterList tcpl = null;
0829:
0830: if (codecCap != null) {
0831:
0832: String category = codecCap.getCategory();
0833: String capabilityName = codecCap.getCapabilityName();
0834: List generators = codecCap.getGenerators();
0835:
0836: Class factory;
0837: for (Iterator i = generators.iterator(); i.hasNext();) {
0838: factory = (Class) i.next();
0839: if (tdf == null
0840: && TileDecoderFactory.class
0841: .isAssignableFrom(factory)) {
0842:
0843: try {
0844: tdf = (TileDecoderFactory) factory
0845: .newInstance();
0846: } catch (InstantiationException ie) {
0847: throw new RemoteImagingException(ImageUtil
0848: .getStackTraceString(ie));
0849: } catch (IllegalAccessException iae) {
0850: throw new RemoteImagingException(ImageUtil
0851: .getStackTraceString(iae));
0852: }
0853: }
0854: }
0855:
0856: if (tdf == null) {
0857: throw new RemoteImagingException(JaiI18N
0858: .getString("RMIServerProxy0"));
0859: }
0860:
0861: TileCodecDescriptor tcd = (TileCodecDescriptor) registry
0862: .getDescriptor("tileDecoder", capabilityName);
0863:
0864: if (tcd.includesSampleModelInfo() == false
0865: || tcd.includesLocationInfo() == false) {
0866: throw new RemoteImagingException(JaiI18N
0867: .getString("RMIServerProxy1"));
0868: }
0869:
0870: ParameterListDescriptor pld = tcd
0871: .getParameterListDescriptor("tileDecoder");
0872:
0873: tcpl = new TileCodecParameterList(capabilityName,
0874: new String[] { "tileDecoder" }, pld);
0875:
0876: // Set parameters on TileCodecParameterList only if there are any
0877: // parameters defined.
0878: if (pld != null) {
0879:
0880: String paramNames[] = pld.getParamNames();
0881: String currParam;
0882: Object currValue;
0883: if (paramNames != null) {
0884: for (int i = 0; i < paramNames.length; i++) {
0885: currParam = paramNames[i];
0886: try {
0887: currValue = codecCap
0888: .getNegotiatedValue(currParam);
0889: } catch (IllegalArgumentException iae) {
0890: // If this parameter is not defined on the
0891: // NegotiableCapability, then move onto the next
0892: continue;
0893: }
0894:
0895: tcpl.setParameter(currParam, currValue);
0896: }
0897: }
0898: }
0899: }
0900:
0901: try {
0902: // If a compression hint was set, use it
0903: if (codecCap != null) {
0904: byte ctile[] = remoteImage.getCompressedTile(id, tileX,
0905: tileY);
0906: ByteArrayInputStream stream = new ByteArrayInputStream(
0907: ctile);
0908: TileDecoder decoder = tdf.createDecoder(stream, tcpl);
0909: try {
0910: return decoder.decode();
0911: } catch (java.io.IOException ioe) {
0912: throw new RemoteImagingException(ImageUtil
0913: .getStackTraceString(ioe));
0914: }
0915: } else {
0916: // Ask for uncompressed tiles.
0917: SerializableState rp = remoteImage.getTile(id, tileX,
0918: tileY);
0919: return (Raster) (rp.getObject());
0920: }
0921: } catch (RemoteException e) {
0922: String message = JaiI18N.getString("RMIServerProxy15");
0923: listener.errorOccurred(message, new RemoteImagingException(
0924: message, e), this , false);
0925: // throw new RemoteImagingException(ImageUtil.getStackTraceString(e));
0926: }
0927:
0928: return null;
0929: }
0930:
0931: public Object getRemoteProperty(String name)
0932: throws RemoteImagingException {
0933: try {
0934: Object property = remoteImage.getProperty(id, name);
0935: if (NULL_PROPERTY_CLASS.isInstance(property)) {
0936: property = Image.UndefinedProperty;
0937: }
0938: return property;
0939: } catch (RemoteException re) {
0940: String message = JaiI18N.getString("RMIServerProxy16");
0941: listener.errorOccurred(message, new RemoteImagingException(
0942: message, re), this , false);
0943: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0944: }
0945:
0946: return Image.UndefinedProperty;
0947: }
0948:
0949: /**
0950: * Returns a list of names recognized by the <code>getRemoteProperty</code>
0951: * method. Network errors encountered should be signalled by
0952: * throwing a RemoteImagingException.
0953: *
0954: * @throws RemoteImagingException if an error condition during remote
0955: * image processing occurs
0956: */
0957: public String[] getRemotePropertyNames()
0958: throws RemoteImagingException {
0959: try {
0960: return remoteImage.getPropertyNames(id);
0961: } catch (RemoteException re) {
0962: String message = JaiI18N.getString("RMIServerProxy17");
0963: listener.errorOccurred(message, new RemoteImagingException(
0964: message, re), this , false);
0965: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
0966: }
0967:
0968: return null;
0969: }
0970:
0971: /**
0972: * Returns a conservative estimate of the destination region that
0973: * can potentially be affected by the pixels of a rectangle of a
0974: * given source. This can be implemented by either asking the server
0975: * to compute the destination region, or by having the client compute
0976: * the destination region. Network errors encountered should be
0977: * signalled by throwing a <code>RemoteImagingException</code>.
0978: *
0979: * @param sourceRect The <code>Rectangle</code> in source coordinates.
0980: * @param sourceIndex The index of the source image.
0981: *
0982: * @return A <code>Rectangle</code> indicating the potentially
0983: * affected destination region, or <code>null</code> if
0984: * the region is unknown.
0985: *
0986: * @throws IllegalArgumentException If the source index is
0987: * negative or greater than that of the last source.
0988: * @throws IllegalArgumentException If <code>sourceRect</code> is
0989: * <code>null</code>.
0990: */
0991: public Rectangle mapSourceRect(Rectangle sourceRect, int sourceIndex)
0992: throws RemoteImagingException {
0993:
0994: Rectangle dstRect = null;
0995:
0996: try {
0997: dstRect = remoteImage.mapSourceRect(id, sourceRect,
0998: sourceIndex);
0999: } catch (RemoteException re) {
1000: String message = JaiI18N.getString("RMIServerProxy18");
1001: listener.errorOccurred(message, new RemoteImagingException(
1002: message, re), this , false);
1003: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
1004: }
1005:
1006: return dstRect;
1007: }
1008:
1009: /**
1010: * Returns a conservative estimate of the region of a specified
1011: * source that is required in order to compute the pixels of a
1012: * given destination rectangle. Either the server or the client can
1013: * compute the source region to implement this method. Network errors
1014: * encountered should be signalled by throwing a
1015: * <code>RemoteImagingException</code>.
1016: *
1017: * @param destRect The <code>Rectangle</code> in destination coordinates.
1018: * @param sourceIndex The index of the source image.
1019: *
1020: * @return A <code>Rectangle</code> indicating the required source region.
1021: *
1022: * @throws IllegalArgumentException If the source index is
1023: * negative or greater than that of the last source.
1024: * @throws IllegalArgumentException If <code>destRect</code> is
1025: * <code>null</code>.
1026: */
1027: public Rectangle mapDestRect(Rectangle destRect, int sourceIndex)
1028: throws RemoteImagingException {
1029:
1030: Rectangle srcRect = null;
1031:
1032: try {
1033: srcRect = remoteImage
1034: .mapDestRect(id, destRect, sourceIndex);
1035: } catch (RemoteException re) {
1036: String message = JaiI18N.getString("RMIServerProxy18");
1037: listener.errorOccurred(message, new RemoteImagingException(
1038: message, re), this , false);
1039: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
1040: }
1041:
1042: return srcRect;
1043: }
1044:
1045: public void setNegotiationPreferences(
1046: NegotiableCapabilitySet preferences) {
1047: if (remoteImage == null) {
1048: this .negPref = preferences;
1049: preferencesSet = true;
1050: } else {
1051: super .setNegotiationPreferences(preferences);
1052: }
1053: }
1054:
1055: /**
1056: * Informs the server of the negotiated values that are the result of
1057: * a successful negotiation.
1058: *
1059: * @param negotiatedValues The result of the negotiation.
1060: */
1061: public synchronized void setServerNegotiatedValues(
1062: NegotiableCapabilitySet negotiatedValues)
1063: throws RemoteImagingException {
1064: try {
1065: remoteImage.setServerNegotiatedValues(id, negotiatedValues);
1066: } catch (RemoteException re) {
1067: String message = JaiI18N.getString("RMIServerProxy19");
1068: listener.errorOccurred(message, new RemoteImagingException(
1069: message, re), this , false);
1070: // throw new RemoteImagingException(ImageUtil.getStackTraceString(re));
1071: }
1072: }
1073: }
|