Source Code Cross Referenced for SerializableRenderableImage.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » rmi » 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 » com.sun.media.jai.rmi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: SerializableRenderableImage.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:54 $
0010:         * $State: Exp $
0011:         */package com.sun.media.jai.rmi;
0012:
0013:        /*
0014:         XXX
0015:         See if the SerializableRenderedImage can be sent by requests instead of 
0016:         deep copy. 
0017:         */
0018:
0019:        import java.awt.Image;
0020:        import java.awt.RenderingHints;
0021:        import java.awt.image.RenderedImage;
0022:        import java.awt.image.renderable.RenderableImage;
0023:        import java.awt.image.renderable.RenderContext;
0024:        import java.io.InputStream;
0025:        import java.io.InterruptedIOException;
0026:        import java.io.IOException;
0027:        import java.io.NotSerializableException;
0028:        import java.io.OutputStream;
0029:        import java.io.ObjectInputStream;
0030:        import java.io.ObjectOutputStream;
0031:        import java.io.Serializable;
0032:        import java.net.InetAddress;
0033:        import java.net.Socket;
0034:        import java.net.SocketException;
0035:        import java.net.ServerSocket;
0036:        import java.net.UnknownHostException;
0037:        import java.util.Enumeration;
0038:        import java.util.Hashtable;
0039:        import java.util.Vector;
0040:        import javax.media.jai.OperationRegistry;
0041:        import javax.media.jai.remote.SerializableState;
0042:        import javax.media.jai.remote.SerializerFactory;
0043:        import javax.media.jai.remote.SerializableRenderedImage;
0044:        import javax.media.jai.tilecodec.TileCodecParameterList;
0045:        import javax.media.jai.tilecodec.TileDecoder;
0046:        import javax.media.jai.tilecodec.TileEncoder;
0047:        import javax.media.jai.tilecodec.TileDecoderFactory;
0048:        import javax.media.jai.tilecodec.TileEncoderFactory;
0049:        import javax.media.jai.util.CaselessStringKey;
0050:
0051:        /**
0052:         * A serializable wrapper class for classes which implement the
0053:         * <code>RenderableImage</code> interface.
0054:         *
0055:         * <p> A <code>SerializableRenderableImage</code> provides a means to
0056:         * serialize a <code>RenderableImage</code>.  Transient fields are handled
0057:         * using <code>Serializer</code>s registered with the
0058:         * <code>SerializerFactory</code>. Since no data is associated with a
0059:         * <code>RenderableImage</code>, <code>SerializableRenderableImage</code>
0060:         * does not provide any renderable image data. The only way to access image
0061:         * data from a <code>SerializableRenderableImage</code> is by calling any
0062:         * one of the <code>createDefaultRendering</code>, 
0063:         * <code>createRendering</code>, or <code>createScaledRendering</code>
0064:         * methods. The resultant <code>RenderedImage</code> is created on the remote
0065:         * host and provided via deep copy of the image data. If the request is
0066:         * made on the local host, the image data are provided by forwarding
0067:         * the request to the wrapped <code>RenderableImage</code>.  Note that a single
0068:         * <code>SerializableRenderableImage</code> object should be able to service
0069:         * multiple remote hosts.
0070:         *
0071:         * <p> An example of the usage of this class is as follows:
0072:         *
0073:         * <pre>
0074:         * import java.io.IOException;
0075:         * import java.io.ObjectInputStream;
0076:         * import java.io.ObjectOutputStream;
0077:         * import java.io.Serializable;
0078:         *
0079:         * public class SomeSerializableClass implements Serializable {
0080:         *     protected transient RenderableImage image;
0081:         *
0082:         *     // Fields omitted.
0083:         *
0084:         *     public SomeSerializableClass(RenderableImage image) {
0085:         *         this.image = image;
0086:         *     }
0087:         *
0088:         *     // Methods omitted.
0089:         *
0090:         *     // Serialization method.
0091:         *     private void writeObject(ObjectOutputStream out) throws IOException {
0092:         *         out.defaultWriteObject();
0093:         *         out.writeObject(new SerializableRenderableImage(image));
0094:         *     }
0095:         *
0096:         *     // Deserialization method.
0097:         *     private void readObject(ObjectInputStream in)
0098:         *         throws IOException, ClassNotFoundException {
0099:         *         in.defaultReadObject();
0100:         *         image = (RenderableImage)in.readObject();
0101:         *     }
0102:         * }
0103:         * </pre>
0104:         *
0105:         * @see java.awt.image.renderable.RenderableImage
0106:         * @see javax.media.jai.RenderableOp
0107:         */
0108:        public final class SerializableRenderableImage implements 
0109:                RenderableImage, Serializable {
0110:
0111:            /** Value to indicate the server socket timeout period (milliseconds). */
0112:            private static final int SERVER_TIMEOUT = 60000; // XXX 1 minute?
0113:
0114:            /** Message indicating that a client will not connect again. */
0115:            private static final String CLOSE_MESSAGE = "CLOSE";
0116:
0117:            /** Flag indicating whether this is a data server. */
0118:            private transient boolean isServer;
0119:
0120:            /** The RenderableImage source of this object (server only). */
0121:            private transient RenderableImage source;
0122:
0123:            /** The X coordinate of the image's upper-left pixel. */
0124:            private float minX;
0125:
0126:            /** The Y coordinate of the image's upper-left pixel. */
0127:            private float minY;
0128:
0129:            /** The image's width in pixels. */
0130:            private float width;
0131:
0132:            /** The image's height in pixels. */
0133:            private float height;
0134:
0135:            /** The image's sources, stored in a Vector. */
0136:            private transient Vector sources = null;
0137:
0138:            /** A Hashtable containing the image properties. */
0139:            private transient Hashtable properties = null;
0140:
0141:            /** */
0142:            private boolean isDynamic;
0143:
0144:            /** The Internet Protocol (IP) address of the instantiating host. */
0145:            private InetAddress host;
0146:
0147:            /** The port on which the data server is listening. */
0148:            private int port;
0149:
0150:            /** Flag indicating that the server is available for connections. */
0151:            private transient boolean serverOpen = false;
0152:
0153:            /** The server socket for image data transfer (server only). */
0154:            private transient ServerSocket serverSocket = null;
0155:
0156:            /** The thread in which the data server is running (server only). */
0157:            private transient Thread serverThread;
0158:
0159:            /**
0160:             * A table of counts of remote references to instances of this class
0161:             * (server only).
0162:             *
0163:             * <p> This table consists of entries with the keys being instances of
0164:             * <code>SerializableRenderableImage</code> and the values being
0165:             * <code>Integer</code>s the int value of which represents the number
0166:             * of remote <code>SerializableRenderableImage</code> objects which could
0167:             * potentially request a socket connection with the associated key. This
0168:             * table is necessary to prevent the garbage collector of the interpreter
0169:             * in which the server <code>SerializableRenderableImage</code> object is
0170:             * instantiated from finalizing the object - and thereby closing its
0171:             * server socket - when that object could still receive socket connection
0172:             * requests from its remote clients. The reference to the object in the
0173:             * static class variable ensures that the object will not be prematurely
0174:             * finalized.
0175:             */
0176:            private static transient Hashtable remoteReferenceCount;
0177:
0178:            /** Indicate that tilecodec is used in the transfering or not */
0179:            private boolean useTileCodec = false;
0180:
0181:            /** 
0182:             * The <code>OperationRegistry</code> to be used to find the 
0183:             * <code>TileEncoderFactory</code> and <code>TileDecoderFactory</code>
0184:             */
0185:            private OperationRegistry registry = null;
0186:
0187:            /** The name of the TileCodec format. */
0188:            private String formatName = null;
0189:
0190:            /** Cache the encoding/decoding parameters */
0191:            private TileCodecParameterList encodingParam = null;
0192:            private TileCodecParameterList decodingParam = null;
0193:
0194:            /**
0195:             * Increment the remote reference count of the argument.
0196:             *
0197:             * <p> If the argument is not already in the remote reference table,
0198:             * add it to the table with a count value of unity. If it exists in
0199:             * table, increment its count value.
0200:             *
0201:             * @parameter o The object the count value of which is to be incremented.
0202:             */
0203:            private static synchronized void incrementRemoteReferenceCount(
0204:                    Object o) {
0205:                if (remoteReferenceCount == null) {
0206:                    remoteReferenceCount = new Hashtable();
0207:                    remoteReferenceCount.put(o, new Integer(1));
0208:                } else {
0209:                    Integer count = (Integer) remoteReferenceCount.get(o);
0210:                    if (count == null) {
0211:                        remoteReferenceCount.put(o, new Integer(1));
0212:                    } else {
0213:                        remoteReferenceCount.put(o, new Integer(count
0214:                                .intValue() + 1));
0215:                    }
0216:                }
0217:            }
0218:
0219:            /**
0220:             * Decrement the remote reference count of the argument.
0221:             *
0222:             * <p> If the count value of the argument exists in the table its count
0223:             * value is decremented unless the count value is unity in which case the
0224:             * entry is removed from the table.
0225:             *
0226:             * @parameter o The object the count value of which is to be decremented.
0227:             */
0228:            private static synchronized void decrementRemoteReferenceCount(
0229:                    Object o) {
0230:                if (remoteReferenceCount != null) {
0231:                    Integer count = (Integer) remoteReferenceCount.get(o);
0232:                    if (count != null) {
0233:                        if (count.intValue() == 1) {
0234:                            remoteReferenceCount.remove(o);
0235:                        } else {
0236:                            remoteReferenceCount.put(o, new Integer(count
0237:                                    .intValue() - 1));
0238:                        }
0239:                    }
0240:                }
0241:            }
0242:
0243:            /**
0244:             * The default constructor.
0245:             */
0246:            SerializableRenderableImage() {
0247:            }
0248:
0249:            /**
0250:             * Constructs a <code>SerializableRenderableImage</code> wrapper for a
0251:             * <code>RenderableImage</code> source.  The image data of the rendering
0252:             * will be serialized via a single deep copy.  Tile encoding and
0253:             * decoding may be effected via a <code>TileEncoder</code> and
0254:             * <code>TileDecoder</code> specified by format name.
0255:             *
0256:             * @param source The <code>RenderableImage</code> source.
0257:             * @param registry The <code>OperationRegistry</code> to use in
0258:             *                 creating the <code>TileEncoder</code>.  The
0259:             *                 <code>TileDecoder</code> will of necessity be
0260:             *                 created using the default <code>OperationRegistry</code>
0261:             *                 as the specified <code>OperationRegistry</code> is not
0262:             *                 serialized.  If <code>null</code> the default registry
0263:             *                 will be used.
0264:             * @param formatName The name of the format used to encode the data.
0265:             *                   If <code>null</code> simple tile serialization will
0266:             *                   be performed either directly or by use of a "raw"
0267:             *                   <code>TileCodec</code>.
0268:             * @param encodingParam The parameters to be used for data encoding.  If
0269:             *                      <code>null</code> the default encoding
0270:             *                      <code>TileCodecParameterList</code> for this
0271:             *                      format will be used.  Ignored if
0272:             *                      <code>formatName</code> is <code>null</code>.
0273:             * @param decodingParam The parameters to be used for data decoding.  If
0274:             *                      <code>null</code> a complementary
0275:             *                      <code>TileCodecParameterList</code> will be
0276:             *                      derived from <code>encodingParam</code>.  Ignored
0277:             *                      if <code>formatName</code> is <code>null</code>.
0278:             *
0279:             * @exception IllegalArgumentException if <code>source</code>
0280:             *            or <code>formatName</code> is <code>null</code>.
0281:             * @exception IllegalArgumentException if <code>encodingParam</code> and
0282:             * <code>decodingParam</code> do not have the same format name as the
0283:             * supplied <code>formatName</code>. 
0284:             */
0285:            public SerializableRenderableImage(RenderableImage source,
0286:                    OperationRegistry registry, String formatName,
0287:                    TileCodecParameterList encodingParam,
0288:                    TileCodecParameterList decodingParam) {
0289:
0290:                this (source);
0291:
0292:                this .registry = registry;
0293:                this .formatName = formatName;
0294:                this .encodingParam = encodingParam;
0295:                this .decodingParam = decodingParam;
0296:
0297:                if (formatName == null) {
0298:                    throw new IllegalArgumentException(JaiI18N
0299:                            .getString("SerializableRenderableImage2"));
0300:                }
0301:
0302:                if (!formatName.equals(encodingParam.getFormatName())) {
0303:                    throw new IllegalArgumentException(JaiI18N
0304:                            .getString("UseTileCodec0"));
0305:                }
0306:
0307:                if (!formatName.equals(decodingParam.getFormatName())) {
0308:                    throw new IllegalArgumentException(JaiI18N
0309:                            .getString("UseTileCodec1"));
0310:                }
0311:
0312:                TileEncoderFactory tileEncoderFactory = (TileEncoderFactory) registry
0313:                        .getFactory("tileEncoder", formatName);
0314:                TileDecoderFactory tileDecoderFactory = (TileDecoderFactory) registry
0315:                        .getFactory("tileDecoder", formatName);
0316:                if (tileEncoderFactory == null || tileDecoderFactory == null)
0317:                    throw new RuntimeException(JaiI18N
0318:                            .getString("UseTileCodec2"));
0319:
0320:                useTileCodec = true;
0321:            }
0322:
0323:            /**
0324:             * Constructs a <code>SerializableRenderableImage</code> wrapper for a
0325:             * <code>RenderableImage</code> source.  Image data of the rendering of
0326:             * the <code>RenderableImage</code> will be serialized via a single deep
0327:             * copy.  No <code>TileCodec</code> will be used, i.e., data will be
0328:             * transmitted using the serialization protocol for <code>Raster</code>s.
0329:             *
0330:             * @param source The <code>RenderableImage</code> source.
0331:             * @exception IllegalArgumentException if <code>source</code>
0332:             *            or <code>formatName</code> is <code>null</code>.
0333:             */
0334:            public SerializableRenderableImage(RenderableImage source) {
0335:
0336:                if (source == null)
0337:                    throw new IllegalArgumentException(JaiI18N
0338:                            .getString("SerializableRenderableImage1"));
0339:
0340:                // Set server flag.
0341:                isServer = true;
0342:
0343:                // Cache the parameter.
0344:                this .source = source;
0345:
0346:                // Initialize RenderableImage fields.
0347:                minX = source.getMinX();
0348:                minY = source.getMinY();
0349:                width = source.getWidth();
0350:                height = source.getHeight();
0351:                isDynamic = source.isDynamic();
0352:
0353:                sources = new Vector();
0354:                sources.add(source);
0355:
0356:                properties = new Hashtable();
0357:                String[] propertyNames = source.getPropertyNames();
0358:                String propertyName;
0359:                if (propertyNames != null) {
0360:                    for (int i = 0; i < propertyNames.length; i++) {
0361:                        propertyName = propertyNames[i];
0362:                        properties.put(new CaselessStringKey(propertyName),
0363:                                source.getProperty(propertyName));
0364:                    }
0365:                }
0366:
0367:                // Initialize the host field.
0368:                try {
0369:                    host = InetAddress.getLocalHost();
0370:                } catch (UnknownHostException e) {
0371:                    throw new RuntimeException(e.getMessage());
0372:                }
0373:
0374:                // Unset the server availability flag.
0375:                serverOpen = false;
0376:            }
0377:
0378:            /**
0379:             * Private implementation of tile server.
0380:             */
0381:            private class RenderingServer implements  Runnable {
0382:
0383:                /**
0384:                 * Provide Rasters to clients on request.
0385:                 *
0386:                 * <p> This method is called by the data server thread when a deep copy
0387:                 * of the source image Raster is not being used. A socket connection is
0388:                 * set up at a well known address to which clients may connect. After a
0389:                 * client connects it transmits a Rectangle object which is read by
0390:                 * this method. The Raster corresponding to this Rectangle is then
0391:                 * retrieved from the source image and transmitted back over the
0392:                 * socket connection.
0393:                 *
0394:                 * <p> The server loop will continue until this object is garbage
0395:                 * collected.
0396:                 */
0397:                public void run() {
0398:                    // Loop while the server availability flag is set.
0399:                    while (serverOpen) {
0400:                        // Wait for a client connection request.
0401:                        Socket socket = null;
0402:                        try {
0403:                            socket = serverSocket.accept();
0404:                            socket.setSoLinger(true, 1);
0405:                        } catch (InterruptedIOException e) {
0406:                            // accept() timeout: restart loop to check
0407:                            // availability flag.
0408:                            continue;
0409:                        } catch (Exception e) {
0410:                            throw new RuntimeException(e.getMessage());
0411:                        }
0412:
0413:                        // Get the socket input and output streams and wrap object
0414:                        // input and output streams around them, respectively.
0415:                        InputStream in = null;
0416:                        OutputStream out = null;
0417:                        ObjectInputStream objectIn = null;
0418:                        ObjectOutputStream objectOut = null;
0419:                        try {
0420:                            in = socket.getInputStream();
0421:                            out = socket.getOutputStream();
0422:                            objectIn = new ObjectInputStream(in);
0423:                            objectOut = new ObjectOutputStream(out);
0424:                        } catch (Exception e) {
0425:                            throw new RuntimeException(e.getMessage());
0426:                        }
0427:
0428:                        // Read the Object from the object stream.
0429:                        Object obj = null;
0430:                        try {
0431:                            obj = objectIn.readObject();
0432:                        } catch (Exception e) {
0433:                            throw new RuntimeException(e.getMessage());
0434:                        }
0435:
0436:                        RenderedImage ri = null;
0437:                        SerializableRenderedImage sri;
0438:                        // Switch according to object class; ignore unsupported types.
0439:                        if (obj instanceof  String) {
0440:                            String str = (String) obj;
0441:
0442:                            if (str.equals(CLOSE_MESSAGE)) {
0443:                                // Decrement the remote reference count.
0444:                                decrementRemoteReferenceCount(this );
0445:
0446:                            } else {
0447:                                if (str.equals("createDefaultRendering")) {
0448:
0449:                                    ri = source.createDefaultRendering();
0450:
0451:                                } else if (str.equals("createRendering")) {
0452:
0453:                                    // Read the Object from the object stream.
0454:                                    obj = null;
0455:                                    try {
0456:                                        obj = objectIn.readObject();
0457:                                    } catch (Exception e) {
0458:                                        throw new RuntimeException(e
0459:                                                .getMessage());
0460:                                    }
0461:
0462:                                    SerializableState ss = (SerializableState) obj;
0463:                                    RenderContext rc = (RenderContext) ss
0464:                                            .getObject();
0465:
0466:                                    ri = source.createRendering(rc);
0467:
0468:                                } else if (str.equals("createScaledRendering")) {
0469:
0470:                                    // Read the Object from the object stream.
0471:                                    obj = null;
0472:                                    try {
0473:                                        obj = objectIn.readObject();
0474:                                    } catch (Exception e) {
0475:                                        throw new RuntimeException(e
0476:                                                .getMessage());
0477:                                    }
0478:
0479:                                    int w = ((Integer) obj).intValue();
0480:
0481:                                    try {
0482:                                        obj = objectIn.readObject();
0483:                                    } catch (Exception e) {
0484:                                        throw new RuntimeException(e
0485:                                                .getMessage());
0486:                                    }
0487:
0488:                                    int h = ((Integer) obj).intValue();
0489:
0490:                                    try {
0491:                                        obj = objectIn.readObject();
0492:                                    } catch (Exception e) {
0493:                                        throw new RuntimeException(e
0494:                                                .getMessage());
0495:                                    }
0496:
0497:                                    SerializableState ss = (SerializableState) obj;
0498:                                    RenderingHints rh = (RenderingHints) ss
0499:                                            .getObject();
0500:
0501:                                    ri = source.createScaledRendering(w, h, rh);
0502:                                }
0503:
0504:                                if (useTileCodec) {
0505:                                    try {
0506:                                        sri = new SerializableRenderedImage(ri,
0507:                                                true, registry, formatName,
0508:                                                encodingParam, decodingParam);
0509:                                    } catch (java.io.NotSerializableException nse) {
0510:                                        throw new RuntimeException(nse
0511:                                                .getMessage());
0512:                                    }
0513:                                } else {
0514:                                    sri = new SerializableRenderedImage(ri,
0515:                                            true);
0516:                                }
0517:
0518:                                try {
0519:                                    objectOut.writeObject(sri);
0520:                                } catch (Exception e) {
0521:                                    throw new RuntimeException(e.getMessage());
0522:                                }
0523:                            }
0524:                        } else {
0525:                            throw new RuntimeException(JaiI18N
0526:                                    .getString("SerializableRenderableImage0"));
0527:                        }
0528:
0529:                        // XXX Concerning serialization of properties, perhaps the
0530:                        // best approach would be to serialize all the properties up
0531:                        // front if a deep copy were being made but otherwise to wait
0532:                        // until the first property request was received before
0533:                        // transmitting any property values. When the first request
0534:                        // was made, all property values would be transmitted and then
0535:                        // cached. Up front serialization might in both cases include
0536:                        // transmitting all names. If property serialization were
0537:                        // deferred, then a new message branch would be added here
0538:                        // to retrieve the properties which could be obtained as
0539:                        // a PropertySourceImpl. If properties are also served up
0540:                        // then this inner class should be renamed "DataServer".
0541:
0542:                        // Close the various streams and the socket itself.
0543:                        try {
0544:                            objectOut.close();
0545:                            objectIn.close();
0546:                            out.close();
0547:                            in.close();
0548:                            socket.close();
0549:                        } catch (Exception e) {
0550:                            throw new RuntimeException(e.getMessage());
0551:                        }
0552:                    }
0553:                }
0554:            }
0555:
0556:            // --- Begin implementation of java.awt.image.RenderableImage. ---
0557:
0558:            /**
0559:             * Returns a <code>RenderedImage</code> which is the result of
0560:             * calling <code>createDefaultRendering</code> on the wrapped
0561:             * <code>RenderableImage</code>. 
0562:             */
0563:            public RenderedImage createDefaultRendering() {
0564:
0565:                if (isServer) {
0566:                    return source.createDefaultRendering();
0567:                }
0568:
0569:                // Connect to the data server.
0570:                Socket socket = connectToServer();
0571:
0572:                // Get the socket input and output streams and wrap object
0573:                // input and output streams around them, respectively.
0574:                OutputStream out = null;
0575:                ObjectOutputStream objectOut = null;
0576:                InputStream in = null;
0577:                ObjectInputStream objectIn = null;
0578:                try {
0579:                    out = socket.getOutputStream();
0580:                    objectOut = new ObjectOutputStream(out);
0581:                    in = socket.getInputStream();
0582:                    objectIn = new ObjectInputStream(in);
0583:                } catch (Exception e) {
0584:                    throw new RuntimeException(e.getMessage());
0585:                }
0586:
0587:                // Write the name of the method to the object output stream.
0588:                try {
0589:                    objectOut.writeObject("createDefaultRendering");
0590:                } catch (Exception e) {
0591:                    throw new RuntimeException(e.getMessage());
0592:                }
0593:
0594:                // Read serialized form of the RenderedImage from object output stream.
0595:                Object object = null;
0596:                try {
0597:                    object = objectIn.readObject();
0598:                } catch (Exception e) {
0599:                    throw new RuntimeException(e.getMessage());
0600:                }
0601:
0602:                RenderedImage ri;
0603:                if (object instanceof  SerializableRenderedImage) {
0604:                    ri = (RenderedImage) object;
0605:                } else {
0606:                    ri = null;
0607:                }
0608:
0609:                // Close the various streams and the socket.
0610:                try {
0611:                    out.close();
0612:                    objectOut.close();
0613:                    in.close();
0614:                    objectIn.close();
0615:                    socket.close();
0616:                } catch (Exception e) {
0617:                    throw new RuntimeException(e.getMessage());
0618:                }
0619:
0620:                return ri;
0621:            }
0622:
0623:            public RenderedImage createRendering(RenderContext renderContext) {
0624:
0625:                if (isServer) {
0626:                    return source.createRendering(renderContext);
0627:                }
0628:
0629:                // Connect to the data server.
0630:                Socket socket = connectToServer();
0631:
0632:                // Get the socket input and output streams and wrap object
0633:                // input and output streams around them, respectively.
0634:                OutputStream out = null;
0635:                ObjectOutputStream objectOut = null;
0636:                InputStream in = null;
0637:                ObjectInputStream objectIn = null;
0638:                try {
0639:                    out = socket.getOutputStream();
0640:                    objectOut = new ObjectOutputStream(out);
0641:                    in = socket.getInputStream();
0642:                    objectIn = new ObjectInputStream(in);
0643:                } catch (Exception e) {
0644:                    throw new RuntimeException(e.getMessage());
0645:                }
0646:
0647:                // Write the name of the method and the RenderContext to the
0648:                // object output stream.
0649:                try {
0650:                    objectOut.writeObject("createRendering");
0651:                    objectOut.writeObject(SerializerFactory.getState(
0652:                            renderContext, null));
0653:                } catch (Exception e) {
0654:                    throw new RuntimeException(e.getMessage());
0655:                }
0656:
0657:                // Read serialized form of the RenderedImage from object output stream.
0658:                Object object = null;
0659:                try {
0660:                    object = objectIn.readObject();
0661:                } catch (Exception e) {
0662:                    throw new RuntimeException(e.getMessage());
0663:                }
0664:
0665:                RenderedImage ri = (RenderedImage) object;
0666:
0667:                // Close the various streams and the socket.
0668:                try {
0669:                    out.close();
0670:                    objectOut.close();
0671:                    in.close();
0672:                    objectIn.close();
0673:                    socket.close();
0674:                } catch (Exception e) {
0675:                    throw new RuntimeException(e.getMessage());
0676:                }
0677:
0678:                return ri;
0679:            }
0680:
0681:            public RenderedImage createScaledRendering(int w, int h,
0682:                    RenderingHints hints) {
0683:
0684:                if (isServer) {
0685:                    return source.createScaledRendering(w, h, hints);
0686:                }
0687:
0688:                // Connect to the data server.
0689:                Socket socket = connectToServer();
0690:
0691:                // Get the socket input and output streams and wrap object
0692:                // input and output streams around them, respectively.
0693:                OutputStream out = null;
0694:                ObjectOutputStream objectOut = null;
0695:                InputStream in = null;
0696:                ObjectInputStream objectIn = null;
0697:                try {
0698:                    out = socket.getOutputStream();
0699:                    objectOut = new ObjectOutputStream(out);
0700:                    in = socket.getInputStream();
0701:                    objectIn = new ObjectInputStream(in);
0702:                } catch (Exception e) {
0703:                    throw new RuntimeException(e.getMessage());
0704:                }
0705:
0706:                // Write the name of the method and the necessary method argument
0707:                // to the object output stream.
0708:                try {
0709:                    objectOut.writeObject("createScaledRendering");
0710:                    objectOut.writeObject(new Integer(w));
0711:                    objectOut.writeObject(new Integer(h));
0712:                    objectOut.writeObject(SerializerFactory.getState(hints,
0713:                            null));
0714:                } catch (Exception e) {
0715:                    throw new RuntimeException(e.getMessage());
0716:                }
0717:
0718:                // Read serialized form of the RenderedImage from object output stream.
0719:                Object object = null;
0720:                try {
0721:                    object = objectIn.readObject();
0722:                } catch (Exception e) {
0723:                    throw new RuntimeException(e.getMessage());
0724:                }
0725:
0726:                RenderedImage ri = (RenderedImage) object;
0727:
0728:                // Close the various streams and the socket.
0729:                try {
0730:                    out.close();
0731:                    objectOut.close();
0732:                    in.close();
0733:                    objectIn.close();
0734:                    socket.close();
0735:                } catch (Exception e) {
0736:                    throw new RuntimeException(e.getMessage());
0737:                }
0738:
0739:                return ri;
0740:            }
0741:
0742:            public float getHeight() {
0743:                return height;
0744:            }
0745:
0746:            public float getMinX() {
0747:                return minX;
0748:            }
0749:
0750:            public float getMinY() {
0751:                return minY;
0752:            }
0753:
0754:            // XXX Should getProperty() request property values over a socket
0755:            // connection also?
0756:            public Object getProperty(String name) {
0757:                Object property = properties.get(new CaselessStringKey(name));
0758:                return property == null ? Image.UndefinedProperty : property;
0759:            }
0760:
0761:            public String[] getPropertyNames() {
0762:                String[] names = null;
0763:                if (!properties.isEmpty()) {
0764:                    names = new String[properties.size()];
0765:                    Enumeration keys = properties.keys();
0766:                    int index = 0;
0767:                    CaselessStringKey key;
0768:                    while (keys.hasMoreElements()) {
0769:                        key = (CaselessStringKey) keys.nextElement();
0770:                        names[index++] = key.getName();
0771:                    }
0772:                }
0773:                return names;
0774:            }
0775:
0776:            /**
0777:             * If this <code>SerializableRenderableImage</code> has not been
0778:             * serialized, this method returns a <code>Vector</code> containing
0779:             * only the <code>RenderableImage</code> passed to the constructor; if
0780:             * this image has been deserialized, it returns <code>null</code>.
0781:             */
0782:            public Vector getSources() {
0783:                return sources;
0784:            }
0785:
0786:            /**
0787:             *
0788:             */
0789:            public boolean isDynamic() {
0790:                return isDynamic;
0791:            }
0792:
0793:            public float getWidth() {
0794:                return width;
0795:            }
0796:
0797:            // --- End implementation of java.awt.image.RenderableImage. ---
0798:
0799:            /**
0800:             * Create a server socket and start the server in a separate thread.
0801:             *
0802:             * <p> Note that this method should be called only the first time this
0803:             * object is serialized and only if a deep copy is not being used. If
0804:             * a deep copy is used there is no need to serve clients data on demand.
0805:             * However if data service is being provided, there is no need to create
0806:             * multiple threads for the single object as a single server thread
0807:             * should be able to service multiple remote objects.
0808:             */
0809:            private synchronized void openServer() throws IOException,
0810:                    SocketException {
0811:                if (!serverOpen) {
0812:                    // Create a ServerSocket.
0813:                    serverSocket = new ServerSocket(0);
0814:
0815:                    // Set the ServerSocket accept() method timeout period.
0816:                    serverSocket.setSoTimeout(SERVER_TIMEOUT);
0817:
0818:                    // Initialize the port field.
0819:                    port = serverSocket.getLocalPort();
0820:
0821:                    // Set the server availability flag.
0822:                    serverOpen = true;
0823:
0824:                    // Spawn a child thread and return the parent thread to the caller.
0825:                    serverThread = new Thread(new RenderingServer());
0826:                    serverThread.start();
0827:
0828:                    // Increment the remote reference count.
0829:                    incrementRemoteReferenceCount(this );
0830:                }
0831:            }
0832:
0833:            /**
0834:             * Transmit a message to the data server to indicate that the client
0835:             * will no longer request socket connections.
0836:             */
0837:            private void closeClient() {
0838:                // Connect to the data server.
0839:                Socket socket = connectToServer();
0840:
0841:                // Get the socket output stream and wrap an object
0842:                // output stream around it.
0843:                OutputStream out = null;
0844:                ObjectOutputStream objectOut = null;
0845:                try {
0846:                    out = socket.getOutputStream();
0847:                    objectOut = new ObjectOutputStream(out);
0848:                } catch (Exception e) {
0849:                    throw new RuntimeException(e.getMessage());
0850:                }
0851:
0852:                // Write CLOSE_MESSAGE to the object output stream.
0853:                try {
0854:                    objectOut.writeObject(CLOSE_MESSAGE);
0855:                } catch (Exception e) {
0856:                    throw new RuntimeException(e.getMessage());
0857:                }
0858:
0859:                // Close the streams and the socket.
0860:                try {
0861:                    out.close();
0862:                    objectOut.close();
0863:                    socket.close();
0864:                } catch (Exception e) {
0865:                    throw new RuntimeException(e.getMessage());
0866:                }
0867:            }
0868:
0869:            /**
0870:             * Obtain a connection to the data server socket. This is used only if a
0871:             * deep copy of the image Raster has not been made.
0872:             */
0873:            private Socket connectToServer() {
0874:                // Open a connection to the data server.
0875:                Socket socket = null;
0876:                try {
0877:                    socket = new Socket(host, port);
0878:                    socket.setSoLinger(true, 1);
0879:                } catch (Exception e) {
0880:                    throw new RuntimeException(e.getMessage());
0881:                }
0882:
0883:                return socket;
0884:            }
0885:
0886:            /**
0887:             * If a deep copy is not being used, unset the data server availability
0888:             * flag and wait for the server thread to rejoin the current thread.
0889:             */
0890:            protected void finalize() throws Throwable {
0891:                dispose();
0892:
0893:                // Forward to the parent class.
0894:                super .finalize();
0895:            }
0896:
0897:            /**
0898:             * Provides a hint that an image will no longer be accessed from a
0899:             * reference in user space.  The results are equivalent to those
0900:             * that occur when the program loses its last reference to this
0901:             * image, the garbage collector discovers this, and finalize is
0902:             * called.  This can be used as a hint in situations where waiting
0903:             * for garbage collection would be overly conservative, e.g., there
0904:             * are a large number of socket connections which may be opened to
0905:             * transmit tile data.
0906:             *
0907:             * <p> <code>SerializableRenderableImage</code> defines this method to
0908:             * behave as follows:
0909:             * <ul>
0910:             * <li>if the image is acting as a server, i.e., has never been
0911:             * serialized and may be providing data to serialized
0912:             * versions of itself, it makes itself unavailable to further
0913:             * client requests and closes its socket;</li>
0914:             * <li>if the image is acting as a client, i.e., has been serialized
0915:             * and may be requesting data from a remote, pre-serialization version
0916:             * of itself, it sends a message to its remote self indicating that it
0917:             * will no longer be making requests.</li>
0918:             * </ul>
0919:             *
0920:             * <p> The results of referencing an image after a call to
0921:             * <code>dispose()</code> are undefined.
0922:             */
0923:            public void dispose() {
0924:                // Rejoin the server thread if using a socket-based server.
0925:                if (isServer) {
0926:                    if (serverOpen) {
0927:                        // Unset availability flag so server loop exits.
0928:                        serverOpen = false;
0929:
0930:                        // Wait for the server (child) thread to die.
0931:                        try {
0932:                            serverThread.join(2 * SERVER_TIMEOUT);
0933:                        } catch (Exception e) {
0934:                            // Ignore the Exception.
0935:                        }
0936:
0937:                        // Close the server socket.
0938:                        try {
0939:                            serverSocket.close();
0940:                        } catch (Exception e) {
0941:                            // Ignore the Exception.
0942:                        }
0943:                    }
0944:                } else { // client
0945:                    // Transmit a message to the server to indicate the child's exit.
0946:                    closeClient();
0947:                }
0948:            }
0949:
0950:            /**
0951:             * Custom serialization method. In addition to all non-transient fields,
0952:             * the SampleModel, source vector, and properties table are serialized.
0953:             * If a deep copy of the source image Raster is being used this is also
0954:             * serialized.
0955:             */
0956:            private void writeObject(ObjectOutputStream out) throws IOException {
0957:
0958:                // Start the data server.
0959:                try {
0960:                    openServer();
0961:                } catch (Exception e1) {
0962:                    if (e1 instanceof  SocketException) { // setSoTimeout() failed.
0963:                        if (serverSocket != null) { // XXX Facultative
0964:                            try {
0965:                                serverSocket.close();
0966:                            } catch (IOException e2) {
0967:                                // Ignore the exception.
0968:                            }
0969:                        }
0970:                    }
0971:
0972:                    // Since server socket creation failed, use a deep copy.
0973:                    serverOpen = false; // XXX Facultative
0974:                }
0975:
0976:                // Write non-static and non-transient fields.
0977:                out.defaultWriteObject();
0978:
0979:                // Remove non-serializable elements from table of properties.
0980:                Hashtable propertyTable = properties;
0981:                boolean propertiesCloned = false;
0982:                Enumeration keys = propertyTable.keys();
0983:                while (keys.hasMoreElements()) {
0984:                    Object key = keys.nextElement();
0985:                    if (!(properties.get(key) instanceof  Serializable)) {
0986:                        if (!propertiesCloned) {
0987:                            propertyTable = (Hashtable) properties.clone();
0988:                            propertiesCloned = true;
0989:                        }
0990:                        propertyTable.remove(key);
0991:                    }
0992:                }
0993:
0994:                // Write the properties table.
0995:                out.writeObject(propertyTable);
0996:            }
0997:
0998:            /**
0999:             * Custom deserialization method. In addition to all non-transient fields,
1000:             * the SampleModel, source vector, and properties table are deserialized.
1001:             * If a deep copy of the source image Raster is being used this is also
1002:             * deserialized.
1003:             */
1004:            private void readObject(ObjectInputStream in) throws IOException,
1005:                    ClassNotFoundException {
1006:                isServer = false;
1007:                source = null;
1008:                serverOpen = false;
1009:                serverSocket = null;
1010:                serverThread = null;
1011:
1012:                // Read non-static and non-transient fields.
1013:                in.defaultReadObject();
1014:
1015:                // Read the properties table.
1016:                properties = (Hashtable) in.readObject();
1017:            }
1018:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.