Source Code Cross Referenced for RemoteRenderedOp.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » javax » media » jai » remote » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » javax.media.jai.remote 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: RemoteRenderedOp.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.2 $
0009:         * $Date: 2006/06/16 22:52:05 $
0010:         * $State: Exp $
0011:         */package javax.media.jai.remote;
0012:
0013:        import java.awt.Point;
0014:        import java.awt.Rectangle;
0015:        import java.awt.RenderingHints;
0016:        import java.awt.Shape;
0017:        import java.awt.geom.Area;
0018:        import java.awt.geom.GeneralPath;
0019:        import java.awt.image.Raster;
0020:        import java.awt.image.RenderedImage;
0021:        import java.awt.image.renderable.ParameterBlock;
0022:        import java.beans.PropertyChangeEvent;
0023:        import java.beans.PropertyChangeListener;
0024:        import java.util.ArrayList;
0025:        import java.util.Collection;
0026:        import java.util.HashSet;
0027:        import java.util.Locale;
0028:        import java.util.Set;
0029:        import java.util.Vector;
0030:        import java.text.MessageFormat;
0031:        import javax.media.jai.CollectionChangeEvent;
0032:        import javax.media.jai.CollectionOp;
0033:        import javax.media.jai.JAI;
0034:        import javax.media.jai.OperationRegistry;
0035:        import javax.media.jai.PlanarImage;
0036:        import javax.media.jai.PropertyChangeEventJAI;
0037:        import javax.media.jai.PropertySourceChangeEvent;
0038:        import javax.media.jai.RegistryMode;
0039:        import javax.media.jai.RenderedOp;
0040:        import javax.media.jai.RenderingChangeEvent;
0041:        import javax.media.jai.TileCache;
0042:        import javax.media.jai.registry.RemoteRIFRegistry;
0043:        import javax.media.jai.util.ImagingException;
0044:        import javax.media.jai.util.ImagingListener;
0045:        import com.sun.media.jai.util.ImageUtil;
0046:
0047:        /**
0048:         * A node in a remote rendered imaging chain.  This class is a concrete
0049:         * implementation of the <code>RemoteRenderedImage</code> interface. A
0050:         * <code>RemoteRenderedOp</code> stores a protocol name (as a
0051:         * <code>String</code>), a server name (as a <code>String</code>), an
0052:         * operation name (as a <code>String</code>), a
0053:         * <code>ParameterBlock</code> containing sources and miscellaneous
0054:         * parameters, and a <code>RenderingHints</code> containing rendering
0055:         * hints.  A set of nodes may be joined together via the source
0056:         * <code>Vector</code>s within their <code>ParameterBlock</code>s to
0057:         * form a <u>d</u>irected <u>a</u>cyclic <u>g</u>raph (DAG). The topology
0058:         * i.e., connectivity of the graph may be altered by changing the
0059:         * <code>ParameterBlock</code>s; the operation name, parameters, and
0060:         * rendering hints may also be changed.
0061:         *
0062:         * <p> Such chains represent and handle operations that are being
0063:         * performed remotely. They convey the structure of an imaging
0064:         * chain in a compact representation and can be used to influence the
0065:         * remote imaging process (through the use of retry interval, retries and
0066:         * negotiation preferences).
0067:         *
0068:         * <p> <code>RemoteRenderedOp</code>s are a client side representation of
0069:         * the chain of operations taking place on the server.
0070:         *
0071:         * <p> The translation between <code>RemoteRenderedOp</code> chains and
0072:         * <code>RemoteRenderedImage</code> (usually
0073:         * <code>PlanarImageServerProxy</code>) chains makes use of two levels of
0074:         * indirection provided by the <code>OperationRegistry</code> and
0075:         * <code>RemoteRIF</code> facilities.  First, the
0076:         * local <code>OperationRegistry</code> is used to map the protocol
0077:         * name into a <code>RemoteRIF</code>.  This <code>RemoteRIF</code> then
0078:         * constructs one or more <code>RemoteRenderedImage</code>s (usually
0079:         * <code>PlanarImageServerProxy</code>s) to do the actual work (or
0080:         * returns a <code>RemoteRenderedImage</code> by other means. The
0081:         * <code>OperationRegistry</code> maps a protocol name into a
0082:         * <code>RemoteRIF</code>, since there is one to one correspondence
0083:         * between a protocol name and a <code>RemoteRIF</code>. This differs from
0084:         * the case of <code>RenderedOp</code>s, where the
0085:         * <code>OperationRegistry</code> maps each operation name to a
0086:         * <code>RenderedImageFactory</code> (RIF), since there is a one to one
0087:         * correspondence between an operation name and a RIF. The
0088:         * <code>RemoteRIF</code>s are therefore protocol-specific and not operation
0089:         * specific, while a RIF is operation specific.
0090:         *
0091:         * <p> Once a protocol name has been mapped into a <code>RemoteRIF</code>,
0092:         * the <code>RemoteRIF.create()</code> method is used to create a rendering.
0093:         * This rendering is responsible for communicating with the server to
0094:         * perform the specified operation remotely.
0095:         *
0096:         * <p> By virtue of being a subclass of <code>RenderedOp</code>, this class
0097:         * participates in Java Bean-style events as specified by
0098:         * <code>RenderedOp</code>. This means that <code>PropertyChangeEmitter</code>
0099:         * methods may be used to register and unregister
0100:         * <code>PropertyChangeListener</code>s. <code>RemoteRenderedOp</code>s
0101:         * are also <code>PropertyChangeListener</code>s so that they may be
0102:         * registered as listeners of other <code>PropertyChangeEmitter</code>s
0103:         * or the equivalent. Each <code>RemoteRenderedOp</code> also automatically
0104:         * receives any <code>RenderingChangeEvent</code>s emitted by any of its
0105:         * sources which are <code>RenderedOp</code>s.
0106:         *
0107:         * <p> <code>RemoteRenderedOp</code>s add the server name and the protocol
0108:         * name to the critical attributes, the editing (changing) of which,
0109:         * coupled with a difference in the old and new rendering over some
0110:         * non-empty region, may cause a <code>RenderingChangeEvent</code> to
0111:         * be emitted. As with <code>RenderedOp</code>, editing of a critical
0112:         * attribute of a <code>RemoteRenderedOp</code> will cause a
0113:         * <code>PropertyChangeEventJAI</code> detailing the change to be fired
0114:         * to all registered <code>PropertyChangeListener</code>s.
0115:         * <code>RemoteRenderedOp</code> registers itself as a
0116:         * <code>PropertyChangeListener</code> for all critical attributes, and
0117:         * thus receives all <code>PropertyChangeEventJAI</code> events generated
0118:         * by itself. This is done in order to allow the event handling code
0119:         * to generate a new rendering and reuse any tiles that might be valid
0120:         * after the critical argument change.
0121:         *
0122:         * <p> When a <code>RemoteRenderedOp</code> node receives a
0123:         * <code>PropertyChangeEventJAI</code> from itself, the region of
0124:         * the current rendering which is invalidated is computed using
0125:         * <code>RemoteDescriptor.getInvalidRegion()</code>. When a
0126:         * <code>RemoteRenderedOp</code> node receives a
0127:         * <code>RenderingChangeEvent</code> from one of its sources, the region of
0128:         * the current rendering which is invalidated is computed using
0129:         * the <code>mapSourceRect()</code> method of the current rendering and
0130:         * the invalid region of the source (retrieved using
0131:         * <code>RenderingChangeEvent.getInvalidRegion()</code>)
0132:         * If the complement of the invalid region contains any tiles of the
0133:         * current rendering, a new rendering of the node will be generated using
0134:         * the new source node and its rendering generated using that version of
0135:         * <code>RemoteRIF.create</code>() that updates the rendering of the node
0136:         * according to the specified <code>PropertyChangeEventJAI</code>. The
0137:         * identified tiles will be retained from the old rendering insofar as
0138:         * possible.  This might involve for example adding tiles to a
0139:         * <code>TileCache</code> under the ownership of the new rendering.
0140:         * A <code>RenderingChangeEvent</code> will then be fired to all
0141:         * <code>PropertyChangeListener</code>s of the node, and to any node sinks
0142:         * that are <code>PropertyChangeListener</code>s. The
0143:         * <code>newRendering</code> parameter of the event constructor
0144:         * (which may be retrieved via the <code>getNewValue()</code> method of
0145:         * the event) will be set to either the new rendering of the node or to
0146:         * <code>null</code> if it was not possible to retain any tiles of the
0147:         * previous rendering.
0148:         *
0149:         * @see RenderedOp
0150:         * @see RemoteRenderedImage
0151:         *
0152:         * @since JAI 1.1
0153:         */
0154:        public class RemoteRenderedOp extends RenderedOp implements 
0155:                RemoteRenderedImage {
0156:
0157:            /** The name of the protocol this class provides an implementation for. */
0158:            protected String protocolName;
0159:
0160:            /** The name of the server. */
0161:            protected String serverName;
0162:
0163:            // The NegotiableCapabilitySet representing the negotiated values.
0164:            private NegotiableCapabilitySet negotiated;
0165:
0166:            /**
0167:             * The RenderingHints when the node was last rendered, i.e., when
0168:             * "theImage" was set to its current value.
0169:             */
0170:            private transient RenderingHints oldHints;
0171:
0172:            /** Node event names. */
0173:            private static Set nodeEventNames = null;
0174:
0175:            static {
0176:                nodeEventNames = new HashSet();
0177:                nodeEventNames.add("protocolname");
0178:                nodeEventNames.add("servername");
0179:                nodeEventNames.add("protocolandservername");
0180:                nodeEventNames.add("operationname");
0181:                nodeEventNames.add("operationregistry");
0182:                nodeEventNames.add("parameterblock");
0183:                nodeEventNames.add("sources");
0184:                nodeEventNames.add("parameters");
0185:                nodeEventNames.add("renderinghints");
0186:            }
0187:
0188:            /**
0189:             * Constructs a <code>RemoteRenderedOp</code> that will be used to
0190:             * instantiate a particular rendered operation to be performed remotely
0191:             * using the default operation registry, the name of the remote imaging
0192:             * protocol, the name of the server to perform the operation on, an
0193:             * operation name, a <code>ParameterBlock</code>, and a set of
0194:             * rendering hints.  All input parameters are saved by reference.
0195:             *
0196:             * <p> An <code>IllegalArgumentException</code> may
0197:             * be thrown by the protocol specific classes at a later point, if
0198:             * null is provided as the serverName argument and null is not
0199:             * considered a valid server name by the specified protocol.
0200:             *
0201:             * <p> The <code>RenderingHints</code> may contain negotiation
0202:             * preferences specified under the <code>KEY_NEGOTIATION_PREFERENCES</code>
0203:             * key.
0204:             *
0205:             * @param protocolName The protocol name as a String.
0206:             * @param serverName   The server name as a String.
0207:             * @param opName       The operation name.
0208:             * @param pb           The sources and parameters. If <code>null</code>,
0209:             *                     it is assumed that this node has no sources and
0210:             *                     parameters.
0211:             * @param hints        The rendering hints.  If <code>null</code>, it is
0212:             *                     assumed that no hints are associated with the
0213:             *                     rendering.
0214:             *
0215:             * @throws IllegalArgumentException if <code>protocolName</code> is
0216:             * <code>null</code>.
0217:             * @throws IllegalArgumentException if <code>opName</code> is
0218:             * <code>null</code>.
0219:             */
0220:            public RemoteRenderedOp(String protocolName, String serverName,
0221:                    String opName, ParameterBlock pb, RenderingHints hints) {
0222:                this (null, protocolName, serverName, opName, pb, hints);
0223:            }
0224:
0225:            /**
0226:             * Constructs a <code>RemoteRenderedOp</code> that will be used to
0227:             * instantiate a particular rendered operation to be performed remotely
0228:             * using the specified operation registry, the name of the remote imaging
0229:             * protocol, the name of the server to perform the operation on, an
0230:             * operation name, a <code>ParameterBlock</code>, and a set of
0231:             * rendering hints.  All input parameters are saved by reference.
0232:             *
0233:             * <p> An <code>IllegalArgumentException</code> may
0234:             * be thrown by the protocol specific classes at a later point, if
0235:             * null is provided as the serverName argument and null is not
0236:             * considered a valid server name by the specified protocol.
0237:             *
0238:             * <p> The <code>RenderingHints</code> may contain negotiation
0239:             * preferences specified under the <code>KEY_NEGOTIATION_PREFERENCES</code>
0240:             * key.
0241:             *
0242:             * @param registry     The <code>OperationRegistry</code> to be used for
0243:             *                     instantiation.  if <code>null</code>, the default
0244:             *                     registry is used.
0245:             * @param protocolName The protocol name as a String.
0246:             * @param serverName   The server name as a String.
0247:             * @param opName       The operation name.
0248:             * @param pb           The sources and parameters. If <code>null</code>,
0249:             *                     it is assumed that this node has no sources and
0250:             *                     parameters.
0251:             * @param hints        The rendering hints.  If <code>null</code>, it is
0252:             *                     assumed that no hints are associated with the
0253:             *                     rendering.
0254:             *
0255:             * @throws IllegalArgumentException if <code>protocolName</code> is
0256:             * <code>null</code>.
0257:             * @throws IllegalArgumentException if <code>opName</code> is
0258:             * <code>null</code>.
0259:             */
0260:            public RemoteRenderedOp(OperationRegistry registry,
0261:                    String protocolName, String serverName, String opName,
0262:                    ParameterBlock pb, RenderingHints hints) {
0263:
0264:                // This will throw IAE for opName if null
0265:                super (registry, opName, pb, hints);
0266:
0267:                if (protocolName == null)
0268:                    throw new IllegalArgumentException(JaiI18N
0269:                            .getString("Generic1"));
0270:
0271:                this .protocolName = protocolName;
0272:                this .serverName = serverName;
0273:
0274:                // Add the node as a PropertyChangeListener of itself for
0275:                // the critical attributes of the node. Superclass RenderedOp
0276:                // takes care of all critical attributes except the following.
0277:                // Case is ignored in the property names but infix caps are
0278:                // used here anyway.
0279:                addPropertyChangeListener("ServerName", this );
0280:                addPropertyChangeListener("ProtocolName", this );
0281:                addPropertyChangeListener("ProtocolAndServerName", this );
0282:            }
0283:
0284:            /**
0285:             * Returns the <code>String</code> that identifies the server.
0286:             */
0287:            public String getServerName() {
0288:                return serverName;
0289:            }
0290:
0291:            /**
0292:             * Sets a <code>String</code> identifying the server.
0293:             *
0294:             * <p> If the supplied name does not equal the current server name, a
0295:             * <code>PropertyChangeEventJAI</code> named "ServerName"
0296:             * will be fired and a <code>RenderingChangeEvent</code> may be
0297:             * fired if the node has already been rendered. The oldValue
0298:             * field in the <code>PropertyChangeEventJAI</code> will contain
0299:             * the old server name <code>String</code> and the newValue
0300:             * field will contain the new server name <code>String</code>.
0301:             *
0302:             * @param serverName A <code>String</code> identifying the server.
0303:             * @throws IllegalArgumentException if serverName is null.
0304:             */
0305:            public void setServerName(String serverName) {
0306:
0307:                if (serverName == null)
0308:                    throw new IllegalArgumentException(JaiI18N
0309:                            .getString("Generic2"));
0310:
0311:                if (serverName.equalsIgnoreCase(this .serverName))
0312:                    return;
0313:
0314:                String oldServerName = this .serverName;
0315:                this .serverName = serverName;
0316:                fireEvent("ServerName", oldServerName, serverName);
0317:                nodeSupport.resetPropertyEnvironment(false);
0318:            }
0319:
0320:            /**
0321:             * Returns the <code>String</code> that identifies the remote imaging
0322:             * protocol.
0323:             */
0324:            public String getProtocolName() {
0325:                return protocolName;
0326:            }
0327:
0328:            /**
0329:             * Sets a <code>String</code> identifying the remote imaging protocol.
0330:             * This method causes this <code>RemoteRenderedOp</code> to use
0331:             * the new protocol name with the server name set on this node
0332:             * previously. If the server is not compliant with the new
0333:             * protocol name, the <code>setProtocolAndServerNames()</code>
0334:             * method should be used to set a new protocol name and a compliant
0335:             * new server name at the same time.
0336:             *
0337:             * <p> If the supplied name does not equal the current protocol name, a
0338:             * <code>PropertyChangeEventJAI</code> named "ProtocolName"
0339:             * will be fired and a <code>RenderingChangeEvent</code> may be
0340:             * fired if the node has already been rendered. The oldValue
0341:             * field in the <code>PropertyChangeEventJAI</code> will contain
0342:             * the old protocol name <code>String</code> and the newValue
0343:             * field will contain the new protocol name <code>String</code>.
0344:             *
0345:             * @param protocolName A <code>String</code> identifying the server.
0346:             * @throws IllegalArgumentException if protocolName is null.
0347:             */
0348:            public void setProtocolName(String protocolName) {
0349:
0350:                if (protocolName == null)
0351:                    throw new IllegalArgumentException(JaiI18N
0352:                            .getString("Generic1"));
0353:
0354:                if (protocolName.equalsIgnoreCase(this .protocolName))
0355:                    return;
0356:
0357:                String oldProtocolName = this .protocolName;
0358:                this .protocolName = protocolName;
0359:                fireEvent("ProtocolName", oldProtocolName, protocolName);
0360:                nodeSupport.resetPropertyEnvironment(false);
0361:            }
0362:
0363:            /**
0364:             * Sets the protocol name and the server name of this
0365:             * <code>RemoteRenderedOp</code> to the specified arguments..
0366:             *
0367:             * <p> If both the supplied protocol name and the supplied server
0368:             * name values do not equal the current values, a
0369:             * <code>PropertyChangeEventJAI</code> named "ProtocolAndServerName"
0370:             * will be fired. The oldValue field in the
0371:             * <code>PropertyChangeEventJAI</code> will contain a two element
0372:             * array of <code>String</code>s, the old protocol name being the
0373:             * first element and the old server name being the second. Similarly
0374:             * the newValue field of the <code>PropertyChangeEventJAI</code> will
0375:             * contain a two element array of <code>String</code>s, the new protocol
0376:             * name being the first element and the new server name being the
0377:             * second. If only the supplied protocol name does not equal
0378:             * the current protocol name, a <code>PropertyChangeEventJAI</code>
0379:             * named "ProtocolName" will be fired. If only the supplied server
0380:             * name does not equal the current server name, a
0381:             * <code>PropertyChangeEventJAI</code> named "ServerName"
0382:             * will be fired.
0383:             *
0384:             * @param protocolName A <code>String</code> identifying the protocol.
0385:             * @param serverName A <code>String</code> identifying the server.
0386:             * @throws IllegalArgumentException if protocolName is null.
0387:             * @throws IllegalArgumentException if serverName is null.
0388:             */
0389:            public void setProtocolAndServerNames(String protocolName,
0390:                    String serverName) {
0391:
0392:                if (serverName == null)
0393:                    throw new IllegalArgumentException(JaiI18N
0394:                            .getString("Generic2"));
0395:
0396:                if (protocolName == null)
0397:                    throw new IllegalArgumentException(JaiI18N
0398:                            .getString("Generic1"));
0399:
0400:                boolean protocolNotChanged = protocolName
0401:                        .equalsIgnoreCase(this .protocolName);
0402:                boolean serverNotChanged = serverName
0403:                        .equalsIgnoreCase(this .serverName);
0404:
0405:                if (protocolNotChanged) {
0406:                    if (serverNotChanged)
0407:                        // Neither changed
0408:                        return;
0409:                    else {
0410:                        // Only serverName changed
0411:                        setServerName(serverName);
0412:                        return;
0413:                    }
0414:                } else {
0415:                    if (serverNotChanged) {
0416:                        // Only protocolName changed
0417:                        setProtocolName(protocolName);
0418:                        return;
0419:                    }
0420:                }
0421:
0422:                String oldProtocolName = this .protocolName;
0423:                String oldServerName = this .serverName;
0424:                this .protocolName = protocolName;
0425:                this .serverName = serverName;
0426:
0427:                // Both changed
0428:                fireEvent("ProtocolAndServerName", new String[] {
0429:                        oldProtocolName, oldServerName }, new String[] {
0430:                        protocolName, serverName });
0431:                nodeSupport.resetPropertyEnvironment(false);
0432:            }
0433:
0434:            /**
0435:             * Returns the name of the <code>RegistryMode</code> corresponding to
0436:             * this <code>RemoteRenderedOp</code>.  This method overrides the
0437:             * implementation in <code>RenderedOp</code> to always returns the
0438:             * <code>String</code> "remoteRendered".
0439:             */
0440:            public String getRegistryModeName() {
0441:                return RegistryMode.getMode("remoteRendered").getName();
0442:            }
0443:
0444:            /**
0445:             * Overrides the <code>RenderedOp</code> method to allow the operation
0446:             * to be performed remotely.
0447:             */
0448:            protected synchronized PlanarImage createInstance(
0449:                    boolean isNodeRendered) {
0450:
0451:                ParameterBlock pb = new ParameterBlock();
0452:                pb.setParameters(getParameters());
0453:
0454:                int numSources = getNumSources();
0455:
0456:                for (int i = 0; i < numSources; i++) {
0457:
0458:                    Object source = getNodeSource(i);
0459:                    Object ai = null;
0460:                    if (source instanceof  RenderedOp) {
0461:
0462:                        RenderedOp src = (RenderedOp) source;
0463:                        ai = isNodeRendered ? src.getRendering() : src
0464:                                .createInstance();
0465:
0466:                    } else if ((source instanceof  RenderedImage)
0467:                            || (source instanceof  Collection)) {
0468:
0469:                        ai = source;
0470:                    } else if (source instanceof  CollectionOp) {
0471:                        ai = ((CollectionOp) source).getCollection();
0472:                    } else {
0473:                        /* Source is some other type. Pass on (for now). */
0474:                        ai = source;
0475:                    }
0476:                    pb.addSource(ai);
0477:                }
0478:
0479:                RemoteRenderedImage instance = RemoteRIFRegistry.create(
0480:                        nodeSupport.getRegistry(), protocolName, serverName,
0481:                        nodeSupport.getOperationName(), pb, nodeSupport
0482:                                .getRenderingHints());
0483:
0484:                // Throw an exception if the rendering is null.
0485:                if (instance == null) {
0486:                    throw new ImagingException(JaiI18N
0487:                            .getString("RemoteRenderedOp2"));
0488:                }
0489:
0490:                // Save the state of the node.
0491:                RenderingHints rh = nodeSupport.getRenderingHints();
0492:                oldHints = rh == null ? null : (RenderingHints) rh.clone();
0493:
0494:                // Ensure that the rendering is a PlanarImage.
0495:                return PlanarImage.wrapRenderedImage(instance);
0496:            }
0497:
0498:            /* ----- PropertyChangeListener method. ----- */
0499:
0500:            /**
0501:             * Implementation of <code>PropertyChangeListener</code>.
0502:             *
0503:             * <p> When invoked with an event which is an instance of
0504:             * <code>RenderingChangeEvent</code> the node will respond by
0505:             * re-rendering itself while retaining any tiles possible.
0506:             */
0507:            // XXX Update javadoc both here and at class level.
0508:            public synchronized void propertyChange(PropertyChangeEvent evt) {
0509:
0510:                //
0511:                // React if and only if the node has been rendered and
0512:                // A: a non-PropertySourceChangeEvent PropertyChangeEventJAI
0513:                //    was received from this node, or
0514:                // B: a RenderingChangeEvent was received from a source node.
0515:                //
0516:
0517:                // Cache event and node sources.
0518:                Object evtSrc = evt.getSource();
0519:                Vector nodeSources = nodeSupport.getParameterBlock()
0520:                        .getSources();
0521:
0522:                // Get the name of the bean property and convert it to lower
0523:                // case now for efficiency later.
0524:                String propName = evt.getPropertyName().toLowerCase(
0525:                        Locale.ENGLISH);
0526:
0527:                if (theImage != null
0528:                        && ((evt instanceof  PropertyChangeEventJAI
0529:                                && evtSrc == this 
0530:                                && !(evt instanceof  PropertySourceChangeEvent) && nodeEventNames
0531:                                .contains(propName)) || ((evt instanceof  RenderingChangeEvent
0532:                                || evt instanceof  CollectionChangeEvent || (evt instanceof  PropertyChangeEventJAI
0533:                                && evtSrc instanceof  RenderedImage && propName
0534:                                .equals("invalidregion"))) && nodeSources
0535:                                .contains(evtSrc)))) {
0536:
0537:                    // Save the previous rendering.
0538:                    PlanarImage theOldImage = theImage;
0539:
0540:                    // Initialize the event flag.
0541:                    boolean shouldFireEvent = false;
0542:
0543:                    // Set default invalid region to null (the entire image).
0544:                    Shape invalidRegion = null;
0545:
0546:                    if (evtSrc == this 
0547:                            && (propName.equals("operationregistry")
0548:                                    || propName.equals("protocolname") || propName
0549:                                    .equals("protocolandservername"))) {
0550:
0551:                        // invalidate the entire rendering.
0552:                        shouldFireEvent = true;
0553:                        theImage = null;
0554:
0555:                    } else if (evt instanceof  RenderingChangeEvent
0556:                            || (evtSrc instanceof  RenderedImage && propName
0557:                                    .equals("invalidregion"))) {
0558:
0559:                        // Set the event flag.
0560:                        shouldFireEvent = true;
0561:                        Shape srcInvalidRegion = null;
0562:
0563:                        if (evt instanceof  RenderingChangeEvent) {
0564:
0565:                            // RenderingChangeEvent presumably from a source
0566:                            // RenderedOp.
0567:                            RenderingChangeEvent rcEvent = (RenderingChangeEvent) evt;
0568:
0569:                            // Get the invalidated region of the source.
0570:                            srcInvalidRegion = rcEvent.getInvalidRegion();
0571:
0572:                            // If entire source is invalid replace with source bounds.
0573:                            if (srcInvalidRegion == null) {
0574:                                srcInvalidRegion = ((PlanarImage) rcEvent
0575:                                        .getOldValue()).getBounds();
0576:                            }
0577:                        } else {
0578:
0579:                            // Get the invalidated region of the source.
0580:                            srcInvalidRegion = (Shape) evt.getNewValue();
0581:
0582:                            // If entire source is invalid replace with source bounds.
0583:                            if (srcInvalidRegion == null) {
0584:                                RenderedImage rSrc = (RenderedImage) evtSrc;
0585:                                srcInvalidRegion = new Rectangle(
0586:                                        rSrc.getMinX(), rSrc.getMinY(), rSrc
0587:                                                .getWidth(), rSrc.getHeight());
0588:                            }
0589:                        }
0590:
0591:                        // Only process further if the rendering is a
0592:                        // PlanarImageServerProxy.
0593:                        if (!(theImage instanceof  PlanarImageServerProxy)) {
0594:
0595:                            // Clear the current rendering.
0596:                            theImage = null;
0597:
0598:                        } else {
0599:
0600:                            // Save the previous rendering as a PlanarImageServerProxy.
0601:                            PlanarImageServerProxy oldPISP = (PlanarImageServerProxy) theImage;
0602:
0603:                            // Cache source invalid bounds.
0604:                            Rectangle srcInvalidBounds = srcInvalidRegion
0605:                                    .getBounds();
0606:
0607:                            // If bounds are empty, replace srcInvalidRegion with
0608:                            // the complement of the image bounds within the
0609:                            // bounds of all tiles.
0610:                            if (srcInvalidBounds.isEmpty()) {
0611:                                int x = oldPISP.tileXToX(oldPISP.getMinTileX());
0612:                                int y = oldPISP.tileYToY(oldPISP.getMinTileY());
0613:                                int w = oldPISP.getNumXTiles()
0614:                                        * oldPISP.getTileWidth();
0615:                                int h = oldPISP.getNumYTiles()
0616:                                        * oldPISP.getTileHeight();
0617:                                Rectangle tileBounds = new Rectangle(x, y, w, h);
0618:                                Rectangle imageBounds = oldPISP.getBounds();
0619:                                if (!tileBounds.equals(imageBounds)) {
0620:                                    Area tmpArea = new Area(tileBounds);
0621:                                    tmpArea.subtract(new Area(imageBounds));
0622:                                    srcInvalidRegion = tmpArea;
0623:                                    srcInvalidBounds = srcInvalidRegion
0624:                                            .getBounds();
0625:                                }
0626:                            }
0627:
0628:                            // ----- Determine invalid destination region. -----
0629:
0630:                            boolean saveAllTiles = false;
0631:                            ArrayList validTiles = null;
0632:                            if (srcInvalidBounds.isEmpty()) {
0633:                                invalidRegion = srcInvalidRegion;
0634:                                saveAllTiles = true;
0635:
0636:                            } else {
0637:
0638:                                // Get index of source which changed.
0639:                                int idx = nodeSources.indexOf(evtSrc);
0640:
0641:                                // Determine bounds of invalid destination region.
0642:                                Rectangle dstRegionBounds = oldPISP
0643:                                        .mapSourceRect(srcInvalidBounds, idx);
0644:
0645:                                if (dstRegionBounds == null) {
0646:                                    dstRegionBounds = oldPISP.getBounds();
0647:                                }
0648:
0649:                                // Determine invalid destination region.
0650:                                Point[] indices = getTileIndices(dstRegionBounds);
0651:                                int numIndices = indices != null ? indices.length
0652:                                        : 0;
0653:                                GeneralPath gp = null;
0654:
0655:                                for (int i = 0; i < numIndices; i++) {
0656:                                    if (i % 1000 == 0 && gp != null)
0657:                                        gp = new GeneralPath(new Area(gp));
0658:
0659:                                    Rectangle dstRect = getTileRect(
0660:                                            indices[i].x, indices[i].y);
0661:                                    Rectangle srcRect = oldPISP.mapDestRect(
0662:                                            dstRect, idx);
0663:                                    if (srcRect == null) {
0664:                                        gp = null;
0665:                                        break;
0666:                                    }
0667:                                    if (srcInvalidRegion.intersects(srcRect)) {
0668:                                        if (gp == null) {
0669:                                            gp = new GeneralPath(dstRect);
0670:                                        } else {
0671:                                            gp.append(dstRect, false);
0672:                                        }
0673:                                    } else {
0674:                                        if (validTiles == null) {
0675:                                            validTiles = new ArrayList();
0676:                                        }
0677:                                        validTiles.add(indices[i]);
0678:                                    }
0679:                                }
0680:
0681:                                invalidRegion = (gp == null) ? null : new Area(
0682:                                        gp);
0683:                            }
0684:
0685:                            // Retrieve the old TileCache.
0686:                            TileCache oldCache = oldPISP.getTileCache();
0687:                            theImage = null;
0688:
0689:                            // Only perform further processing if there is a cache
0690:                            // and there are tiles to save.
0691:                            if (oldCache != null
0692:                                    && (saveAllTiles || validTiles != null)) {
0693:
0694:                                // Create new rendering
0695:                                newEventRendering(protocolName, oldPISP,
0696:                                        (PropertyChangeEventJAI) evt);
0697:
0698:                                // Only perform further processing if the new
0699:                                // rendering is an OpImage with a non-null TileCache.
0700:                                if (theImage instanceof  PlanarImageServerProxy
0701:                                        && ((PlanarImageServerProxy) theImage)
0702:                                                .getTileCache() != null) {
0703:                                    PlanarImageServerProxy newPISP = (PlanarImageServerProxy) theImage;
0704:                                    TileCache newCache = newPISP.getTileCache();
0705:
0706:                                    Object tileCacheMetric = newPISP
0707:                                            .getTileCacheMetric();
0708:
0709:                                    if (saveAllTiles) {
0710:                                        Raster[] tiles = oldCache
0711:                                                .getTiles(oldPISP);
0712:                                        int numTiles = tiles == null ? 0
0713:                                                : tiles.length;
0714:                                        for (int i = 0; i < numTiles; i++) {
0715:                                            Raster tile = tiles[i];
0716:                                            int tx = newPISP.XToTileX(tile
0717:                                                    .getMinX());
0718:                                            int ty = newPISP.YToTileY(tile
0719:                                                    .getMinY());
0720:                                            newCache.add(newPISP, tx, ty, tile,
0721:                                                    tileCacheMetric);
0722:                                        }
0723:                                    } else { // save some, but not all, tiles
0724:                                        int numValidTiles = validTiles.size();
0725:                                        for (int i = 0; i < numValidTiles; i++) {
0726:                                            Point tileIndex = (Point) validTiles
0727:                                                    .get(i);
0728:                                            Raster tile = oldCache.getTile(
0729:                                                    oldPISP, tileIndex.x,
0730:                                                    tileIndex.y);
0731:                                            if (tile != null) {
0732:                                                newCache.add(newPISP,
0733:                                                        tileIndex.x,
0734:                                                        tileIndex.y, tile,
0735:                                                        tileCacheMetric);
0736:                                            }
0737:                                        }
0738:                                    }
0739:                                }
0740:                            }
0741:                        }
0742:                    } else { // not op name or registry change nor RenderingChangeEvent
0743:                        ParameterBlock oldPB = null;
0744:                        ParameterBlock newPB = null;
0745:                        String oldServerName = serverName;
0746:                        String newServerName = serverName;
0747:
0748:                        boolean checkInvalidRegion = false;
0749:
0750:                        if (propName.equals("operationname")) {
0751:
0752:                            if (theImage instanceof  PlanarImageServerProxy) {
0753:                                newEventRendering(protocolName,
0754:                                        (PlanarImageServerProxy) theImage,
0755:                                        (PropertyChangeEventJAI) evt);
0756:                            } else {
0757:                                theImage = null;
0758:                                createRendering();
0759:                            }
0760:
0761:                            // Do not set checkInvalidRegion to true, since there
0762:                            // are no tiles to save for this case.
0763:
0764:                            shouldFireEvent = true;
0765:
0766:                            // XXX Do we need to do any evaluation of any
0767:                            // DeferredData parameters.
0768:
0769:                        } else if (propName.equals("parameterblock")) {
0770:                            oldPB = (ParameterBlock) evt.getOldValue();
0771:                            newPB = (ParameterBlock) evt.getNewValue();
0772:                            checkInvalidRegion = true;
0773:                        } else if (propName.equals("sources")) {
0774:                            // Replace source(s)
0775:                            Vector params = nodeSupport.getParameterBlock()
0776:                                    .getParameters();
0777:                            oldPB = new ParameterBlock((Vector) evt
0778:                                    .getOldValue(), params);
0779:                            newPB = new ParameterBlock((Vector) evt
0780:                                    .getNewValue(), params);
0781:                            checkInvalidRegion = true;
0782:                        } else if (propName.equals("parameters")) {
0783:                            // Replace parameter(s)
0784:                            oldPB = new ParameterBlock(nodeSources,
0785:                                    (Vector) evt.getOldValue());
0786:                            newPB = new ParameterBlock(nodeSources,
0787:                                    (Vector) evt.getNewValue());
0788:                            checkInvalidRegion = true;
0789:                        } else if (propName.equals("renderinghints")) {
0790:                            oldPB = newPB = nodeSupport.getParameterBlock();
0791:                            checkInvalidRegion = true;
0792:                        } else if (propName.equals("servername")) {
0793:                            oldPB = newPB = nodeSupport.getParameterBlock();
0794:                            oldServerName = (String) evt.getOldValue();
0795:                            newServerName = (String) evt.getNewValue();
0796:                            checkInvalidRegion = true;
0797:                        } else if (evt instanceof  CollectionChangeEvent) {
0798:                            // Event from a CollectionOp source.
0799:                            // Replace appropriate source.
0800:                            int collectionIndex = nodeSources.indexOf(evtSrc);
0801:                            Vector oldSources = (Vector) nodeSources.clone();
0802:                            Vector newSources = (Vector) nodeSources.clone();
0803:                            oldSources.set(collectionIndex, evt.getOldValue());
0804:                            newSources.set(collectionIndex, evt.getNewValue());
0805:
0806:                            Vector params = nodeSupport.getParameterBlock()
0807:                                    .getParameters();
0808:
0809:                            oldPB = new ParameterBlock(oldSources, params);
0810:                            newPB = new ParameterBlock(newSources, params);
0811:
0812:                            checkInvalidRegion = true;
0813:                        }
0814:
0815:                        if (checkInvalidRegion) {
0816:                            // Set event flag.
0817:                            shouldFireEvent = true;
0818:
0819:                            // Get the associated RemoteDescriptor.
0820:                            OperationRegistry registry = nodeSupport
0821:                                    .getRegistry();
0822:                            RemoteDescriptor odesc = (RemoteDescriptor) registry
0823:                                    .getDescriptor(RemoteDescriptor.class,
0824:                                            protocolName);
0825:
0826:                            // XXX
0827:                            // Evaluate any DeferredData parameters.
0828:                            oldPB = ImageUtil.evaluateParameters(oldPB);
0829:                            newPB = ImageUtil.evaluateParameters(newPB);
0830:
0831:                            // Determine the invalid region.
0832:                            invalidRegion = (Shape) odesc.getInvalidRegion(
0833:                                    "rendered", oldServerName, oldPB, oldHints,
0834:                                    newServerName, newPB, nodeSupport
0835:                                            .getRenderingHints(), this );
0836:
0837:                            if (invalidRegion == null
0838:                                    || !(theImage instanceof  PlanarImageServerProxy)) {
0839:                                // Can't save any tiles; clear the rendering.
0840:                                theImage = null;
0841:
0842:                            } else {
0843:
0844:                                // Create a new rendering.
0845:                                PlanarImageServerProxy oldRendering = (PlanarImageServerProxy) theImage;
0846:
0847:                                newEventRendering(protocolName, oldRendering,
0848:                                        (PropertyChangeEventJAI) evt);
0849:
0850:                                // If the new rendering is also a
0851:                                // PlanarImageServerProxy, save some tiles.
0852:                                if (theImage instanceof  PlanarImageServerProxy
0853:                                        && oldRendering.getTileCache() != null
0854:                                        && ((PlanarImageServerProxy) theImage)
0855:                                                .getTileCache() != null) {
0856:                                    PlanarImageServerProxy newRendering = (PlanarImageServerProxy) theImage;
0857:
0858:                                    TileCache oldCache = oldRendering
0859:                                            .getTileCache();
0860:                                    TileCache newCache = newRendering
0861:                                            .getTileCache();
0862:
0863:                                    Object tileCacheMetric = newRendering
0864:                                            .getTileCacheMetric();
0865:
0866:                                    // If bounds are empty, replace invalidRegion with
0867:                                    // the complement of the image bounds within the
0868:                                    // bounds of all tiles.
0869:                                    if (invalidRegion.getBounds().isEmpty()) {
0870:                                        int x = oldRendering
0871:                                                .tileXToX(oldRendering
0872:                                                        .getMinTileX());
0873:                                        int y = oldRendering
0874:                                                .tileYToY(oldRendering
0875:                                                        .getMinTileY());
0876:                                        int w = oldRendering.getNumXTiles()
0877:                                                * oldRendering.getTileWidth();
0878:                                        int h = oldRendering.getNumYTiles()
0879:                                                * oldRendering.getTileHeight();
0880:                                        Rectangle tileBounds = new Rectangle(x,
0881:                                                y, w, h);
0882:                                        Rectangle imageBounds = oldRendering
0883:                                                .getBounds();
0884:                                        if (!tileBounds.equals(imageBounds)) {
0885:                                            Area tmpArea = new Area(tileBounds);
0886:                                            tmpArea.subtract(new Area(
0887:                                                    imageBounds));
0888:                                            invalidRegion = tmpArea;
0889:                                        }
0890:                                    }
0891:
0892:                                    if (invalidRegion.getBounds().isEmpty()) {
0893:
0894:                                        // Save all tiles.
0895:                                        Raster[] tiles = oldCache
0896:                                                .getTiles(oldRendering);
0897:                                        int numTiles = tiles == null ? 0
0898:                                                : tiles.length;
0899:                                        for (int i = 0; i < numTiles; i++) {
0900:                                            Raster tile = tiles[i];
0901:                                            int tx = newRendering.XToTileX(tile
0902:                                                    .getMinX());
0903:                                            int ty = newRendering.YToTileY(tile
0904:                                                    .getMinY());
0905:                                            newCache.add(newRendering, tx, ty,
0906:                                                    tile, tileCacheMetric);
0907:                                        }
0908:                                    } else {
0909:                                        // Copy tiles not in invalid region from old
0910:                                        // TileCache to new TileCache.
0911:                                        Raster[] tiles = oldCache
0912:                                                .getTiles(oldRendering);
0913:                                        int numTiles = tiles == null ? 0
0914:                                                : tiles.length;
0915:                                        for (int i = 0; i < numTiles; i++) {
0916:                                            Raster tile = tiles[i];
0917:                                            Rectangle bounds = tile.getBounds();
0918:                                            if (!invalidRegion
0919:                                                    .intersects(bounds)) {
0920:                                                newCache
0921:                                                        .add(
0922:                                                                newRendering,
0923:                                                                newRendering
0924:                                                                        .XToTileX(bounds.x),
0925:                                                                newRendering
0926:                                                                        .YToTileY(bounds.y),
0927:                                                                tile,
0928:                                                                tileCacheMetric);
0929:                                            }
0930:                                        }
0931:                                    }
0932:                                }
0933:                            }
0934:                        }
0935:                    }
0936:
0937:                    // Re-render the node. This will only occur if theImage
0938:                    // has been set to null above.
0939:                    if (theOldImage instanceof  PlanarImageServerProxy
0940:                            && theImage == null) {
0941:                        newEventRendering(protocolName,
0942:                                (PlanarImageServerProxy) theOldImage,
0943:                                (PropertyChangeEventJAI) evt);
0944:                    } else {
0945:                        createRendering();
0946:                    }
0947:
0948:                    // Fire an event if the flag was set.
0949:                    if (shouldFireEvent) {
0950:
0951:                        // Clear the synthetic and cached properties and reset the
0952:                        // property source.
0953:                        resetProperties(true);
0954:
0955:                        // Create the event object.
0956:                        RenderingChangeEvent rcEvent = new RenderingChangeEvent(
0957:                                this , theOldImage, theImage, invalidRegion);
0958:
0959:                        // Fire to all registered listeners.
0960:                        eventManager.firePropertyChange(rcEvent);
0961:
0962:                        // Fire an event to all PropertyChangeListener sinks.
0963:                        Vector sinks = getSinks();
0964:                        if (sinks != null) {
0965:                            int numSinks = sinks.size();
0966:                            for (int i = 0; i < numSinks; i++) {
0967:                                Object sink = sinks.get(i);
0968:                                if (sink instanceof  PropertyChangeListener) {
0969:                                    ((PropertyChangeListener) sink)
0970:                                            .propertyChange(rcEvent);
0971:                                }
0972:                            }
0973:                        }
0974:                    }
0975:                }
0976:            }
0977:
0978:            /**
0979:             * Creates a new rendering in response to the provided event, and
0980:             * assigns the new rendering to "theImage" variable.
0981:             */
0982:            private void newEventRendering(String protocolName,
0983:                    PlanarImageServerProxy oldPISP, PropertyChangeEventJAI event) {
0984:                RemoteRIF rrif = (RemoteRIF) nodeSupport.getRegistry()
0985:                        .getFactory("remoterendered", protocolName);
0986:                theImage = (PlanarImage) rrif.create(oldPISP, this , event);
0987:            }
0988:
0989:            /**
0990:             * Fire an events to all registered listeners.
0991:             */
0992:            private void fireEvent(String propName, Object oldVal, Object newVal) {
0993:                if (eventManager != null) {
0994:                    Object eventSource = eventManager
0995:                            .getPropertyChangeEventSource();
0996:                    PropertyChangeEventJAI evt = new PropertyChangeEventJAI(
0997:                            eventSource, propName, oldVal, newVal);
0998:                    eventManager.firePropertyChange(evt);
0999:                }
1000:            }
1001:
1002:            /**
1003:             * Returns the amount of time between retries in milliseconds.
1004:             *
1005:             * <p> If this <code>RemoteRenderedOp</code> has been rendered, then its
1006:             * <code>getRetryInterval()</code> method will be called to return
1007:             * the current retry interval. If no rendering has been created, and
1008:             * a value was set using the <code>setRetryInterval()</code> method), that
1009:             * value will be returned, else the default retry interval as defined by
1010:             * <code>RemoteJAI.DEFAULT_RETRY_INTERVAL</code> is returned.
1011:             */
1012:            public int getRetryInterval() {
1013:                if (theImage != null) {
1014:                    return ((RemoteRenderedImage) theImage).getRetryInterval();
1015:                } else {
1016:                    RenderingHints rh = nodeSupport.getRenderingHints();
1017:                    if (rh == null) {
1018:                        return RemoteJAI.DEFAULT_RETRY_INTERVAL;
1019:                    } else {
1020:                        Integer i = (Integer) rh.get(JAI.KEY_RETRY_INTERVAL);
1021:                        if (i == null)
1022:                            return RemoteJAI.DEFAULT_RETRY_INTERVAL;
1023:                        else
1024:                            return i.intValue();
1025:                    }
1026:                }
1027:            }
1028:
1029:            /**
1030:             * Sets the amount of time between retries in milliseconds. If this
1031:             * <code>RemoteRenderedOp</code> has already been rendered, the
1032:             * <code>setRetryInterval()</code> method is called on the rendering
1033:             * to inform it of the new retry interval. The rendering can choose to
1034:             * ignore this new setting, in which case <code>getRetryInterval()</code>
1035:             * will still return the old value, or the rendering can honor these
1036:             * settings, in which case <code>getRetryInterval()</code> will return
1037:             * the new settings. If this <code>RemoteRenderedOp</code> has not been
1038:             * rendered, the new retry interval specified will be stored.
1039:             * These new stored retry interval will be passed as
1040:             * part of the <code>RenderingHints</code> using the
1041:             * <code>KEY_RETRY_INTERVAL</code> key, to the new rendering
1042:             * when it is created.
1043:             *
1044:             * @param retryInterval The amount of time (in milliseconds) to wait
1045:             *                      between retries.
1046:             * @throws IllegalArgumentException if retryInterval is negative.
1047:             */
1048:            public void setRetryInterval(int retryInterval) {
1049:
1050:                if (retryInterval < 0)
1051:                    throw new IllegalArgumentException(JaiI18N
1052:                            .getString("Generic3"));
1053:
1054:                if (theImage != null) {
1055:                    ((RemoteRenderedImage) theImage)
1056:                            .setRetryInterval(retryInterval);
1057:                }
1058:
1059:                RenderingHints rh = nodeSupport.getRenderingHints();
1060:                if (rh == null) {
1061:                    nodeSupport.setRenderingHints(new RenderingHints(null));
1062:                    rh = nodeSupport.getRenderingHints();
1063:                }
1064:
1065:                rh.put(JAI.KEY_RETRY_INTERVAL, new Integer(retryInterval));
1066:            }
1067:
1068:            /**
1069:             * Returns the number of retries.
1070:             *
1071:             * <p> If this <code>RemoteRenderedOp</code> has been rendered, then its
1072:             * <code>getNumRetries()</code> method will be called to return
1073:             * the current number of retries. If no rendering has been created, and
1074:             * a value was set using the <code>setNumRetries()</code> method), that
1075:             * value will be returned, else the default retry interval as defined by
1076:             * <code>RemoteJAI.DEFAULT_NUM_RETRIES</code> is returned.
1077:             */
1078:            public int getNumRetries() {
1079:                if (theImage != null) {
1080:                    return ((RemoteRenderedImage) theImage).getNumRetries();
1081:                } else {
1082:                    RenderingHints rh = nodeSupport.getRenderingHints();
1083:                    if (rh == null) {
1084:                        return RemoteJAI.DEFAULT_NUM_RETRIES;
1085:                    } else {
1086:                        Integer i = (Integer) rh.get(JAI.KEY_NUM_RETRIES);
1087:                        if (i == null)
1088:                            return RemoteJAI.DEFAULT_NUM_RETRIES;
1089:                        else
1090:                            return i.intValue();
1091:                    }
1092:                }
1093:            }
1094:
1095:            /**
1096:             * Sets the number of retries. If this <code>RemoteRenderedOp</code>
1097:             * has already been rendered, the <code>setNumRetries()</code> method
1098:             * is called on the rendering to inform it of the new number of retries.
1099:             * The rendering can choose to ignore these new settings, in which case
1100:             * <code>getNunRetries()</code> will still return the old values, or
1101:             * the rendering can honor these new settings in which
1102:             * case <code>getNumRetries()</code> will return the new value.
1103:             * If this <code>RemoteRenderedOp</code> has not been rendered,
1104:             * the new setting specified will be stored.
1105:             * These new settings which have been stored will be passed as
1106:             * part of the <code>RenderingHints</code> using the
1107:             * <code>KEY_NUM_RETRIES</code> key, to the new rendering
1108:             * when it is created.
1109:             *
1110:             * @param numRetries The number of times an operation should be retried
1111:             *                   in case of a network error.
1112:             * @throws IllegalArgumentException if numRetries is negative.
1113:             */
1114:            public void setNumRetries(int numRetries) {
1115:
1116:                if (numRetries < 0)
1117:                    throw new IllegalArgumentException(JaiI18N
1118:                            .getString("Generic4"));
1119:
1120:                if (theImage != null) {
1121:                    ((RemoteRenderedImage) theImage).setNumRetries(numRetries);
1122:                }
1123:
1124:                RenderingHints rh = nodeSupport.getRenderingHints();
1125:                if (rh == null) {
1126:                    nodeSupport.setRenderingHints(new RenderingHints(null));
1127:                    rh = nodeSupport.getRenderingHints();
1128:                }
1129:
1130:                rh.put(JAI.KEY_NUM_RETRIES, new Integer(numRetries));
1131:            }
1132:
1133:            /**
1134:             * Sets the preferences to be used in the client-server
1135:             * communication. These preferences are utilized in the negotiation
1136:             * process. Note that preferences for more than one category can be
1137:             * specified using this method. Also each preference can be a list
1138:             * of values in decreasing order of preference, each value specified
1139:             * as a <code>NegotiableCapability</code>. The
1140:             * <code>NegotiableCapability</code> first (for a particular category)
1141:             * in this list is given highest priority in the negotiation process
1142:             * (for that category).
1143:             *
1144:             * <p> It may be noted that this method allows for multiple negotiation
1145:             * cycles by allowing negotiation preferences to be set
1146:             * multiple times. If this <code>RemoteRenderedOp</code> has already
1147:             * been rendered, the <code>setNegotiationPreferences()</code> method
1148:             * is called on the rendering to inform it of the new preferences. The
1149:             * rendering can choose to ignore these new preferences, in which case
1150:             * <code>getNegotiatedValues()</code> will still return the results of
1151:             * the old negotiation, or the rendering can re-perform the negotiation,
1152:             * (using the <code>RemoteJAI.negotiate</code>, for example) in which
1153:             * case <code>getNegotiatedValues()</code> will return the new
1154:             * negotiated values. If this <code>RemoteRenderedOp</code> has not been
1155:             * rendered, the new preferences specified will be stored, a negotiation
1156:             * with these new preferences will be initiated and the results stored.
1157:             * These new preferences which have been stored will be passed as
1158:             * part of the <code>RenderingHints</code> using the
1159:             * <code>KEY_NEGOTIATION_PREFERENCES</code> key, to the new rendering
1160:             * when it is created.
1161:             *
1162:             * @param preferences The preferences to be used in the negotiation
1163:             * process.
1164:             */
1165:            public void setNegotiationPreferences(
1166:                    NegotiableCapabilitySet preferences) {
1167:                if (theImage != null) {
1168:                    ((RemoteRenderedImage) theImage)
1169:                            .setNegotiationPreferences(preferences);
1170:                }
1171:
1172:                RenderingHints rh = nodeSupport.getRenderingHints();
1173:
1174:                if (preferences != null) {
1175:                    if (rh == null) {
1176:                        nodeSupport.setRenderingHints(new RenderingHints(null));
1177:                        rh = nodeSupport.getRenderingHints();
1178:                    }
1179:
1180:                    rh.put(JAI.KEY_NEGOTIATION_PREFERENCES, preferences);
1181:                } else {
1182:                    // Remove any previous values set for negotiation preferences
1183:                    if (rh != null) {
1184:                        rh.remove(JAI.KEY_NEGOTIATION_PREFERENCES);
1185:                    }
1186:                }
1187:
1188:                negotiated = negotiate(preferences);
1189:            }
1190:
1191:            /**
1192:             * Returns the current negotiation preferences or null, if none were
1193:             * set previously.
1194:             */
1195:            public NegotiableCapabilitySet getNegotiationPreferences() {
1196:
1197:                RenderingHints rh = nodeSupport.getRenderingHints();
1198:                return rh == null ? null : (NegotiableCapabilitySet) rh
1199:                        .get(JAI.KEY_NEGOTIATION_PREFERENCES);
1200:            }
1201:
1202:            // do the negotiation
1203:            private NegotiableCapabilitySet negotiate(
1204:                    NegotiableCapabilitySet prefs) {
1205:
1206:                OperationRegistry registry = nodeSupport.getRegistry();
1207:
1208:                NegotiableCapabilitySet serverCap = null;
1209:
1210:                // Get the RemoteDescriptor for protocolName
1211:                RemoteDescriptor descriptor = (RemoteDescriptor) registry
1212:                        .getDescriptor(RemoteDescriptor.class, protocolName);
1213:
1214:                if (descriptor == null) {
1215:                    Object[] msgArg0 = { new String(protocolName) };
1216:                    MessageFormat formatter = new MessageFormat("");
1217:                    formatter.setLocale(Locale.getDefault());
1218:                    formatter.applyPattern(JaiI18N.getString("RemoteJAI16"));
1219:                    throw new ImagingException(formatter.format(msgArg0));
1220:                }
1221:
1222:                int count = 0;
1223:                int numRetries = getNumRetries();
1224:                int retryInterval = getRetryInterval();
1225:
1226:                Exception rieSave = null;
1227:                while (count++ < numRetries) {
1228:                    try {
1229:                        serverCap = descriptor
1230:                                .getServerCapabilities(serverName);
1231:                        break;
1232:                    } catch (RemoteImagingException rie) {
1233:                        // Print that an Exception occured
1234:                        System.err.println(JaiI18N.getString("RemoteJAI24"));
1235:                        rieSave = rie;
1236:                        // Sleep for retryInterval milliseconds
1237:                        try {
1238:                            Thread.sleep(retryInterval);
1239:                        } catch (InterruptedException ie) {
1240:                            //		    throw new RuntimeException(ie.toString());
1241:                            sendExceptionToListener(JaiI18N
1242:                                    .getString("Generic5"),
1243:                                    new ImagingException(JaiI18N
1244:                                            .getString("Generic5"), ie));
1245:                        }
1246:                    }
1247:                }
1248:
1249:                if (serverCap == null && count > numRetries) {
1250:                    sendExceptionToListener(JaiI18N.getString("RemoteJAI18"),
1251:                            rieSave);
1252:                    //	    throw new RemoteImagingException(JaiI18N.getString("RemoteJAI18")+"\n"+rieSave.getMessage());
1253:                }
1254:
1255:                RemoteRIF rrif = (RemoteRIF) registry.getFactory(
1256:                        "remoteRendered", protocolName);
1257:
1258:                return RemoteJAI.negotiate(prefs, serverCap, rrif
1259:                        .getClientCapabilities());
1260:            }
1261:
1262:            /**
1263:             * Returns the results of the negotiation between the client and server
1264:             * capabilities according to the preferences set via the
1265:             * <code>setNegotiationPreferences()</code> method. This will return
1266:             * null if no negotiation preferences were set, and no negotiation
1267:             * was performed, or if the negotiation failed.
1268:             *
1269:             * <p> If this <code>RemoteRenderedOp</code> has been rendered, then its
1270:             * <code>getNegotiatedValues()</code> method will be called to return
1271:             * the current negotiated values. If no rendering has been created, then
1272:             * the internally stored negotiated value (calculated when the new
1273:             * preferences were set using the <code>setNegotiationPreferences()</code>
1274:             * method) will be returned.
1275:             */
1276:            public NegotiableCapabilitySet getNegotiatedValues()
1277:                    throws RemoteImagingException {
1278:                if (theImage != null) {
1279:                    return ((RemoteRenderedImage) theImage)
1280:                            .getNegotiatedValues();
1281:                } else {
1282:                    return negotiated;
1283:                }
1284:            }
1285:
1286:            /**
1287:             * Returns the results of the negotiation between the client and server
1288:             * capabilities for the given category according to the preferences
1289:             * set via the <code>setNegotiationPreferences()</code> method. This
1290:             * will return null if no negotiation preferences were set, and no
1291:             * negotiation was performed, or if the negotiation failed.
1292:             *
1293:             * <p> If this <code>RemoteRenderedOp</code> has been rendered, then its
1294:             * <code>getNegotiatedValues()</code> method will be called to return
1295:             * the current negotiated values. If no rendering has been created, then
1296:             * the internally stored negotiated value (calculated when the new
1297:             * preferences were set using the <code>setNegotiationPreferences()</code>
1298:             * method) will be returned.
1299:             *
1300:             * @param category The category to return the negotiated results for.
1301:             */
1302:            public NegotiableCapability getNegotiatedValue(String category)
1303:                    throws RemoteImagingException {
1304:                if (theImage != null) {
1305:                    return ((RemoteRenderedImage) theImage)
1306:                            .getNegotiatedValue(category);
1307:                } else {
1308:                    return negotiated == null ? null : negotiated
1309:                            .getNegotiatedValue(category);
1310:                }
1311:            }
1312:
1313:            /**
1314:             * Informs the server of the negotiated values that are the result of
1315:             * a successful negotiation. If this <code>RemoteRenderedOp</code> has
1316:             * been rendered, then the rendering's
1317:             * <code>setServerNegotiatedValues</code> method will be called to
1318:             * inform the server of the negotiated results. If no rendering has
1319:             * been created, this method will do nothing.
1320:             *
1321:             * @param negotiatedValues    The result of the negotiation.
1322:             */
1323:            public void setServerNegotiatedValues(
1324:                    NegotiableCapabilitySet negotiatedValues)
1325:                    throws RemoteImagingException {
1326:
1327:                if (theImage != null) {
1328:                    ((RemoteRenderedImage) theImage)
1329:                            .setServerNegotiatedValues(negotiatedValues);
1330:                }
1331:            }
1332:
1333:            void sendExceptionToListener(String message, Exception e) {
1334:                ImagingListener listener = (ImagingListener) getRenderingHints()
1335:                        .get(JAI.KEY_IMAGING_LISTENER);
1336:
1337:                listener.errorOccurred(message, e, this , false);
1338:            }
1339:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.