KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > common > protocol > SQLDataSerialization


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2005 Emic Networks
4  * Contact: sequoia@continuent.org
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Initial developer(s): Marc Herbert
19  * Contributor(s): ______________________.
20  */

21
22 package org.continuent.sequoia.common.protocol;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.ObjectInputStream JavaDoc;
28 import java.io.ObjectOutputStream JavaDoc;
29 import java.io.Serializable JavaDoc;
30 import java.math.BigDecimal JavaDoc;
31 import java.math.BigInteger JavaDoc;
32 import java.sql.Clob JavaDoc;
33 import java.sql.SQLException JavaDoc;
34 import java.sql.Timestamp JavaDoc;
35
36 import org.continuent.sequoia.common.exceptions.NotImplementedException;
37 import org.continuent.sequoia.common.stream.LongUTFDataInputStream;
38 import org.continuent.sequoia.common.stream.LongUTFDataOutputStream;
39
40 /**
41  * This class defines Serializers for SQL Data: per type serialization +
42  * deserialization methods and information wrapped in one object. Serializers
43  * are implemented as singletons for efficiency.
44  *
45  * @author <a HREF="mailto:Marc.Herbert@continuent.com">Marc Herbert </a>
46  * @author <a HREF="mailto:Gilles.Rayrat@continuent.com">Gilles Rayrat </a>
47  * @version 1.0
48  */

49 public final class SQLDataSerialization
50 {
51
52   /**
53    * Unsupported types listed in {@link TypeTag}won't be added in the near
54    * future, except maybe java.net.URL for JDBC 3.0
55    */

56   /**
57    * CLOB support should be easy to base on BLOB implementation once we figure
58    * out the encoding issues.
59    */

60
61   private static final Serializer JAVA_STRING = new StringSerializer();
62   private static final Serializer MATH_BIGDECIMAL = new BigDecimalBytesSerializer();
63   private static final Serializer JAVA_BOOLEAN = new BooleanSerializer();
64   private static final Serializer JAVA_INTEGER = new IntegerSerializer();
65   private static final Serializer JAVA_LONG = new LongSerializer();
66   private static final Serializer JAVA_FLOAT = new FloatSerializer();
67   private static final Serializer JAVA_DOUBLE = new DoubleSerializer();
68   private static final Serializer JAVA_BYTES = new BytesSerializer();
69
70   private static final Serializer SQL_DATE = new DateSerializer();
71   private static final Serializer SQL_TIME = new TimeSerializer();
72   private static final Serializer SQL_TIMESTAMP = new TimestampSerializer();
73
74   // CLOB: TODO
75
private static final Serializer SQL_BLOB = new BlobSerializer();
76
77   private static final Serializer JAVA_SERIALIZABLE = new JavaSerializableSerializer();
78
79   /** Serializer returned for nulls. Public static final so we can == */
80   private static final Serializer UNKNOWN_TYPE = new UndefinedSerializer();
81
82   private static final int STREAM_BUF_SIZE = 65536;
83
84   // java.net.URL: TODO
85

86   /** Abstract class hiding type-specific serialization methods and information */
87   public abstract static class Serializer
88   {
89     protected TypeTag typeTag;
90
91     /**
92      * Special value: non-existing serializer of null references.
93      *
94      * @return true if undefined
95      */

96     public boolean isUndefined()
97     {
98       return this == UNKNOWN_TYPE;
99     }
100
101     /**
102      * @return the corresponding TypeTag
103      */

104     public TypeTag getTypeTag()
105     {
106       return typeTag;
107     }
108
109     /**
110      * Serialize the object to the stream. Warning: the caller must ensure that
111      * Serializer subtype and Object subtype are compatible.
112      *
113      * @param obj object to send
114      * @param output Output stream
115      * @throws IOException stream error
116      * @throws ClassCastException wrong serializer for this object type
117      */

118
119     public abstract void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
120         throws IOException JavaDoc, ClassCastException JavaDoc;
121
122     /**
123      * De-serialize an object from the stream. Warning: the caller must ensure
124      * that Serializer subtype and the incoming object are compatible.
125      *
126      * @param input Input stream
127      * @return the object received from the stream
128      * @throws IOException stream error
129      */

130     public abstract Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
131         throws IOException JavaDoc;
132
133   }
134
135   /**
136    * Returns the de/serializer appropriate for the given TypeTag, or for the
137    * type of the given SQL object if argument is not a TypeTag (TypeTag already
138    * knows how to serialize itself).
139    *
140    * @param sqlObjOrTypeTag a typetag or a sample SQL object of the type of
141    * interest
142    * @return appropriate serialization + deserialization methods. Returns the
143    * UNKNOWN_TYPE serializer on "null" arg.
144    * @throws NotImplementedException if we don't know how to serialize objects
145    * such as the given one. Set with a default message but caller has
146    * generally more useful information and should catch and replace
147    * (not even chain) this NotImplementedException by a better one.
148    * @throws IllegalArgumentException if we gave a wrong TypeTag
149    */

150   public static Serializer getSerializer(Object JavaDoc sqlObjOrTypeTag)
151       throws NotImplementedException, IllegalArgumentException JavaDoc
152   {
153     return getSerializerImpl(sqlObjOrTypeTag);
154   }
155
156   /** @see #getSerializer(Object) */
157   public static Serializer getSerializer(TypeTag t)
158       throws IllegalArgumentException JavaDoc
159   {
160     try
161     {
162       return getSerializerImpl(t);
163     }
164     catch (NotImplementedException nie)
165     {
166       // since we passed a TypeTag it's really impossible to come here
167
IllegalArgumentException JavaDoc ipe = new IllegalArgumentException JavaDoc(
168           "Internal bug: there should be a serializer available for every"
169               + " existing TypeTag, including:" + t);
170       ipe.initCause(nie);
171       throw ipe;
172     }
173   }
174
175   private static Serializer getSerializerImpl(Object JavaDoc sqlObjOrTypeTag)
176       throws NotImplementedException, IllegalArgumentException JavaDoc
177   {
178     /*
179      * Default values that never match anything: we just need any reference that
180      * is both non-SQL and non-null.
181      */

182     TypeTag tag = TypeTag.CONTROLLER_READY;
183     Object JavaDoc obj = JAVA_STRING;
184
185     /**
186      * Now let's get rid of all these nasty type issues for good by casting once
187      * for all.
188      */

189     if (sqlObjOrTypeTag instanceof TypeTag)
190       tag = (TypeTag) sqlObjOrTypeTag;
191     else
192       obj = sqlObjOrTypeTag;
193
194     if (obj == null || TypeTag.UNDEFINED.equals(tag))
195       return UNKNOWN_TYPE;
196
197     /**
198      * THE big switch on (type). "instanceof" is used on the serialization side,
199      * "TypeTag.equals()" is used on the de-serialization side. We could for
200      * performance split this method into two different methods (with the added
201      * burden of keeping them perfectly synchronized)
202      *
203      * @see TypeTag
204      */

205     // STRING
206
if (obj instanceof String JavaDoc || TypeTag.STRING.equals(tag))
207       return JAVA_STRING;
208
209     // BIGDECIMAL
210
if (obj instanceof BigDecimal JavaDoc || TypeTag.BIGDECIMAL.equals(tag))
211       return MATH_BIGDECIMAL;
212
213     // BOOLEAN
214
if (obj instanceof Boolean JavaDoc || TypeTag.BOOLEAN.equals(tag))
215       return JAVA_BOOLEAN;
216
217     // INTEGER
218
if (obj instanceof Integer JavaDoc || TypeTag.INTEGER.equals(tag))
219       return JAVA_INTEGER;
220
221     // LONG
222
if (obj instanceof Long JavaDoc || TypeTag.LONG.equals(tag))
223       return JAVA_LONG;
224
225     // FLOAT
226
if (obj instanceof Float JavaDoc || TypeTag.FLOAT.equals(tag))
227       return JAVA_FLOAT;
228
229     // DOUBLE
230
if (obj instanceof Double JavaDoc || TypeTag.DOUBLE.equals(tag))
231       return JAVA_DOUBLE;
232
233     // BYTE ARRAY
234
if (obj instanceof byte[] || TypeTag.BYTE_ARRAY.equals(tag))
235       return JAVA_BYTES;
236
237     // DATE
238
if (obj instanceof java.sql.Date JavaDoc || TypeTag.SQL_DATE.equals(tag))
239       return SQL_DATE;
240
241     // TIME
242
if (obj instanceof java.sql.Time JavaDoc || TypeTag.SQL_TIME.equals(tag))
243       return SQL_TIME;
244
245     // TIMESTAMP
246
if (obj instanceof Timestamp JavaDoc || TypeTag.SQL_TIMESTAMP.equals(tag))
247       return SQL_TIMESTAMP;
248
249     // CLOB: TODO
250
if (obj instanceof Clob JavaDoc || TypeTag.CLOB.equals(tag))
251       throw new NotImplementedException(
252           "Clob serialization not yet implemented");
253
254     // BLOB
255
if (obj instanceof java.sql.Blob JavaDoc || TypeTag.BLOB.equals(tag))
256       return SQL_BLOB;
257
258     // java.net.URL: TODO
259

260     // Serializable Java object, MUST be last!
261
if (sqlObjOrTypeTag instanceof Serializable JavaDoc
262         || TypeTag.JAVA_SERIALIZABLE.equals(tag))
263       return JAVA_SERIALIZABLE;
264
265     if (sqlObjOrTypeTag instanceof TypeTag)
266       throw new IllegalArgumentException JavaDoc(
267           "Internal error: getSerializer() misused with unknown TypeTag argument:"
268               + tag);
269
270     // An alternative could be to tag only the problematic column, return a
271
// "do-nothing" serializer and send the rest of the result set anyway.
272

273     // Should be replaced by caller, see javadoc above
274
throw new NotImplementedException("Unable to serialize unknown type "
275         + sqlObjOrTypeTag.getClass() + " of object " + sqlObjOrTypeTag);
276   }
277
278   /*
279    * These classes define one serializer per type
280    */

281
282   // STRING
283
private static final class StringSerializer extends Serializer
284   {
285     {
286       typeTag = TypeTag.STRING;
287     }
288
289     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
290         throws IOException JavaDoc
291     {
292       output.writeLongUTF((String JavaDoc) obj);
293     }
294
295     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
296         throws IOException JavaDoc
297     {
298       return input.readLongUTF();
299
300     }
301   }
302
303   // we serialize this by sending the value as 4-bytes packs inside ints,
304
// then by sending the scale as an integer
305
private static final class BigDecimalBytesSerializer extends Serializer
306   {
307     {
308       typeTag = TypeTag.BIGDECIMAL;
309     }
310
311     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
312         throws IOException JavaDoc
313     {
314       // A BigDecimal is a BigInteger called 'value' and a scale
315
// To serialize it, we first convert the value to a byte array using
316
// BigInteger.toByteArray(). Then we serialize it using integers (for
317
// perfomance purpose)
318
// NOTE: we cannot directly use the int array reprensentation of the
319
// BigIntegers because there is no public accessor for it (!!!)
320

321       // The array of bytes returned by .toByteArray() is the two's-complement
322
// representation of the BigInteger in big-endian byte-order.
323
// But to save everyone's time and sweat, we actually split the
324
// BigInteger into its sign and absolute value, avoiding the useless cost
325
// of computing the two's complement for both the sender and the receiver.
326

327       // To send this array of bytes in integers, we have to align the bytes.
328
// This is done by padding the first bytes
329
// For example, let's take the byte array AA BB CC DD EE (hexa values)
330
// We will need two integers for these five bytes:
331
// i1, the first integer, will be padded until byte array tail is aligned,
332
// so i1 will be equal to '00 00 00 AA' while i2 will be 'BB CC DD EE'
333

334       // Number to serialize
335
BigDecimal JavaDoc toBeSerialized = (BigDecimal JavaDoc) obj;
336
337       // 1. Send unscaled, absolute value:
338
// 1.1 Send byte array size
339
byte[] byteArray = toBeSerialized.unscaledValue().abs().toByteArray();
340       output.writeInt(byteArray.length);
341
342       // 1.2 Compute head-padding. The padding is done on the beginning of the
343
// array. Zeros are send before first "real" byte in order to align the
344
// array on integers
345
int idx = 0, word = 0;
346       int padding = byteArray.length % 4;
347       if (padding > 0)
348       {
349         // This should be hard to read so:
350
// bytes are shifted so that last byte is the least-significant byte of
351
// the integer 'word'. More materially:
352
// if padding is 1, no shift -> byte[0] is put at the tail of the int
353
// if padding is 2, shift first byte from 8 while 2nd has no shift
354
// if padding is 3, shift 1st byte from 16, 2nd from 8, none for 3rd
355
for (idx = 0; idx < padding; idx++)
356         {
357           // 0xFF is needed because of sign extension
358
word |= (byteArray[idx] & 0xFF) << (8 * (padding - idx - 1));
359         }
360         // let's write this padded bytes-as-integer
361
output.writeInt(word);
362       }
363       // 1.3 Send the rest of the byte array 4 bytes by 4 bytes in an int
364
// we start from the first aligned byte
365
for (; idx < byteArray.length; idx += 4)
366       {
367         word = (byteArray[idx] & 0xFF) << 24
368             | (byteArray[idx + 1] & 0xFF) << 16
369             | (byteArray[idx + 2] & 0xFF) << 8 | byteArray[idx + 3] & 0xFF;
370         output.writeInt(word);
371       }
372
373       // 1.4 Send sign as an int
374
output.writeInt(toBeSerialized.signum());
375
376       // 2. Send scale
377
output.writeInt(toBeSerialized.scale());
378     }
379
380     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
381         throws IOException JavaDoc
382     {
383       // new method - Deserialize int value then scale
384
// 1. Read intVal:
385
// 1.1 Read byte array length
386
int byteArrayLength = input.readInt();
387       byte[] byteArray = new byte[byteArrayLength];
388       // 1.2 Compute padding
389
int idx = 0, wordRead = 0;
390       int padding = byteArrayLength % 4;
391       // If there is a padding, we must read the first 'padding' bytes
392
// so we are aligned for the rest of the bytes
393
if (padding > 0)
394       {
395         wordRead = input.readInt();
396         for (idx = 0; idx < padding; idx++)
397         {
398           byteArray[idx] = (byte) ((wordRead >> (8 * (padding - idx - 1))) & 0xFF);
399         }
400       }
401       // 1.3 Read the byte array from integers
402
// we start from the first aligned byte
403
for (; idx < byteArrayLength; idx += 4)
404       {
405         wordRead = input.readInt();
406         byteArray[idx] = (byte) ((wordRead >> 24) & 0xFF);
407         byteArray[idx + 1] = (byte) ((wordRead >> 16) & 0xFF);
408         byteArray[idx + 2] = (byte) ((wordRead >> 8) & 0xFF);
409         byteArray[idx + 3] = (byte) (wordRead & 0xFF);
410       }
411       BigInteger JavaDoc intVal = new BigInteger JavaDoc(byteArray);
412
413       // 1.4 read sign as an int
414
if (input.readInt() < 0)
415         intVal = intVal.negate();
416
417       // 2. Read scale
418
int scale = input.readInt();
419
420       return new BigDecimal JavaDoc(intVal, scale);
421     }
422   }
423
424   // BOOLEAN
425
private static final class BooleanSerializer extends Serializer
426   {
427     {
428       typeTag = TypeTag.BOOLEAN;
429     }
430
431     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
432         throws IOException JavaDoc
433     {
434       output.writeBoolean(((Boolean JavaDoc) obj).booleanValue());
435     }
436
437     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
438         throws IOException JavaDoc
439     {
440       return new Boolean JavaDoc(input.readBoolean());
441     }
442   }
443
444   // INTEGER
445
private static final class IntegerSerializer extends Serializer
446   {
447     {
448       typeTag = TypeTag.INTEGER;
449     }
450
451     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
452         throws IOException JavaDoc
453     {
454       /**
455        * let's also accept Short, see PostgreSQL bug explained here
456        *
457        * @see org.continuent.sequoia.driver.DriverResultSet#initSerializers()
458        */

459       output.writeInt(((Number JavaDoc) obj).intValue());
460     }
461
462     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
463         throws IOException JavaDoc
464     {
465       return new Integer JavaDoc(input.readInt());
466     }
467   }
468
469   // LONG
470
private static final class LongSerializer extends Serializer
471   {
472     {
473       typeTag = TypeTag.LONG;
474     }
475
476     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
477         throws IOException JavaDoc
478     {
479       output.writeLong(((Long JavaDoc) obj).longValue());
480     }
481
482     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
483         throws IOException JavaDoc
484     {
485       return new Long JavaDoc(input.readLong());
486     }
487   }
488
489   // FLOAT
490
private static final class FloatSerializer extends Serializer
491   {
492     {
493       typeTag = TypeTag.FLOAT;
494     }
495
496     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
497         throws IOException JavaDoc
498     {
499       output.writeFloat(((Float JavaDoc) obj).floatValue());
500     }
501
502     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
503         throws IOException JavaDoc
504     {
505       return new Float JavaDoc(input.readFloat());
506     }
507   }
508
509   // DOUBLE
510
private static final class DoubleSerializer extends Serializer
511   {
512     {
513       typeTag = TypeTag.DOUBLE;
514     }
515
516     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
517         throws IOException JavaDoc
518     {
519       output.writeDouble(((Double JavaDoc) obj).doubleValue());
520     }
521
522     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
523         throws IOException JavaDoc
524     {
525       return new Double JavaDoc(input.readDouble());
526     }
527   }
528
529   // BYTE ARRAY
530
private static final class BytesSerializer extends Serializer
531   {
532     {
533       typeTag = TypeTag.BYTE_ARRAY;
534     }
535
536     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
537         throws IOException JavaDoc
538     {
539       byte[] b = (byte[]) obj;
540       output.writeInt(b.length);
541       output.write(b);
542     }
543
544     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
545         throws IOException JavaDoc
546     {
547       int len = input.readInt();
548       byte[] b = new byte[len];
549       input.readFully(b);
550       return b;
551     }
552   }
553
554   // DATE
555
private static final class DateSerializer extends Serializer
556   {
557     {
558       typeTag = TypeTag.SQL_DATE;
559     }
560
561     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
562         throws IOException JavaDoc
563     {
564       output.writeLong(((java.sql.Date JavaDoc) obj).getTime());
565     }
566
567     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
568         throws IOException JavaDoc
569     {
570       return new java.sql.Date JavaDoc(input.readLong());
571     }
572   }
573
574   // TIME
575
private static final class TimeSerializer extends Serializer
576   {
577     {
578       typeTag = TypeTag.SQL_TIME;
579     }
580
581     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
582         throws IOException JavaDoc
583     {
584       output.writeInt((int) ((java.sql.Time JavaDoc) obj).getTime());
585     }
586
587     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
588         throws IOException JavaDoc
589     {
590       return new java.sql.Time JavaDoc(input.readInt());
591     }
592   }
593
594   // TIMESTAMP
595
private static final class TimestampSerializer extends Serializer
596   {
597     {
598       typeTag = TypeTag.SQL_TIMESTAMP;
599     }
600
601     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
602         throws IOException JavaDoc
603     {
604       Timestamp JavaDoc ts = (Timestamp JavaDoc) obj;
605       // put the milliseconds trick/CPU load on the driver side
606
output.writeLong(ts.getTime());
607       output.writeInt(ts.getNanos());
608     }
609
610     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
611         throws IOException JavaDoc
612     {
613       long tsWithMilli = input.readLong();
614       // we don't want the milliseconds twice
615
Timestamp JavaDoc ts = new Timestamp JavaDoc((tsWithMilli / 1000) * 1000);
616       ts.setNanos(input.readInt());
617       return ts;
618     }
619   }
620
621   // CLOB: TODO
622

623   // BLOB
624
private static final class BlobSerializer extends Serializer
625   {
626     {
627       typeTag = TypeTag.BLOB;
628     }
629
630     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
631         throws IOException JavaDoc
632     {
633       java.sql.Blob JavaDoc blob = (java.sql.Blob JavaDoc) obj;
634       try
635       {
636         // Be very careful to be compatible with JAVA_BYTES.sendToStream(),
637
// since we use JAVA_BYTES.receiveFromStream on the other side.
638
// We don't use it on this side to save memory.
639

640         if (blob.length() > Integer.MAX_VALUE)
641           // FIXME: this is currently corrupting protocol with driver
642
throw new IOException JavaDoc("Blobs bigger than " + Integer.MAX_VALUE
643               + " are not supported");
644
645         // send the size of the byte array
646
output.writeInt((int) blob.length());
647
648         byte[] tempBuffer = new byte[STREAM_BUF_SIZE];
649         java.io.InputStream JavaDoc input = blob.getBinaryStream();
650         int nbRead;
651         while (true)
652         {
653           nbRead = input.read(tempBuffer);
654           if (-1 == nbRead)
655             break;
656           output.write(tempBuffer, 0, nbRead);
657         }
658       }
659       catch (SQLException JavaDoc e)
660       {
661         // Exceptions for Blobs is unfortunately tricky because we can't know in
662
// advance if a java array will be big enough (2^31) to hold them.
663
throw (IOException JavaDoc) new IOException JavaDoc(e.getLocalizedMessage())
664             .initCause(e);
665       }
666     }
667
668     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
669         throws IOException JavaDoc
670     {
671       byte[] b = (byte[]) JAVA_BYTES.receiveFromStream(input);
672       return new org.continuent.sequoia.common.protocol.ByteArrayBlob(b);
673     }
674   }
675
676   // JAVA_SERIALIZABLE
677
private static final class JavaSerializableSerializer extends Serializer
678   {
679     {
680       typeTag = TypeTag.JAVA_SERIALIZABLE;
681     }
682
683     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
684         throws IOException JavaDoc
685     {
686       ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
687       ObjectOutputStream JavaDoc oos = new ObjectOutputStream JavaDoc(baos);
688       oos.writeObject(obj);
689       oos.close();
690
691       // send first the size of the byte array
692
output.writeInt(baos.size());
693       baos.writeTo(output);
694       baos.close();
695     }
696
697     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
698         throws IOException JavaDoc
699     {
700       byte[] b = (byte[]) JAVA_BYTES.receiveFromStream(input);
701       ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(b));
702       try
703       {
704         Object JavaDoc obj = ois.readObject();
705         return obj;
706       }
707       catch (ClassNotFoundException JavaDoc e)
708       {
709         ClassCastException JavaDoc ioe = new ClassCastException JavaDoc(
710             "Class of deserialized object not found");
711         ioe.initCause(e);
712         throw ioe;
713       }
714     }
715   }
716
717   // UNKNOWN TYPE
718
private static final class UndefinedSerializer extends Serializer
719   {
720     {
721       typeTag = TypeTag.UNDEFINED;
722     }
723
724     public void sendToStream(Object JavaDoc obj, LongUTFDataOutputStream output)
725     {
726       throw new RuntimeException JavaDoc(
727           "Internal bug: tried to send using the UNDEFINED serializer");
728     }
729
730     public Object JavaDoc receiveFromStream(LongUTFDataInputStream input)
731         throws ClassCastException JavaDoc
732     {
733       throw new RuntimeException JavaDoc(
734           "Internal bug: tried to receive using the UNDEFINED deserializer");
735     }
736   }
737
738 }
739
Popular Tags