1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2000-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9package com.sleepycat.bind.serial; 10 11import java.io.IOException; 12import java.io.InputStream; 13import java.io.ObjectInputStream; 14import java.io.ObjectStreamClass; 15 16import com.sleepycat.db.DatabaseException; 17import com.sleepycat.util.RuntimeExceptionWrapper; 18 19/** 20 * A specialized <code>ObjectInputStream</code> that gets class description 21 * information from a <code>ClassCatalog</code>. It is used by 22 * <code>SerialBinding</code>. 23 * 24 * <p>This class is used instead of an {@link ObjectInputStream}, which it 25 * extends, to read an object stream written by the {@link SerialOutput} class. 26 * For reading objects from a database normally one of the serial binding 27 * classes is used. {@link SerialInput} is used when an {@link 28 * ObjectInputStream} is needed along with compact storage. A {@link 29 * ClassCatalog} must be supplied, however, to stored shared class 30 * descriptions.</p> 31 * 32 * @see <a href="SerialBinding.html#evolution">Class Evolution</a> 33 * 34 * @author Mark Hayes 35 */ 36public class SerialInput extends ObjectInputStream { 37 38 private ClassCatalog classCatalog; 39 private ClassLoader classLoader; 40 41 /** 42 * Creates a serial input stream. 43 * 44 * @param in is the input stream from which compact serialized objects will 45 * be read. 46 * 47 * @param classCatalog is the catalog containing the class descriptions 48 * for the serialized objects. 49 */ 50 public SerialInput(InputStream in, ClassCatalog classCatalog) 51 throws IOException { 52 53 this(in, classCatalog, null); 54 } 55 56 /** 57 * Creates a serial input stream. 58 * 59 * @param in is the input stream from which compact serialized objects will 60 * be read. 61 * 62 * @param classCatalog is the catalog containing the class descriptions 63 * for the serialized objects. 64 * 65 * @param classLoader is the class loader to use, or null if a default 66 * class loader should be used. 67 */ 68 public SerialInput(InputStream in, 69 ClassCatalog classCatalog, 70 ClassLoader classLoader) 71 throws IOException { 72 73 super(in); 74 75 this.classCatalog = classCatalog; 76 this.classLoader = classLoader; 77 } 78 79 // javadoc is specified elsewhere 80 protected ObjectStreamClass readClassDescriptor() 81 throws IOException, ClassNotFoundException { 82 83 try { 84 byte len = readByte(); 85 byte[] id = new byte[len]; 86 readFully(id); 87 88 return classCatalog.getClassFormat(id); 89 } catch (DatabaseException e) { 90 /* 91 * Do not throw IOException from here since ObjectOutputStream 92 * will write the exception to the stream, which causes another 93 * call here, etc. 94 */ 95 throw new RuntimeExceptionWrapper(e); 96 } 97 } 98 99 // javadoc is specified elsewhere 100 protected Class resolveClass(ObjectStreamClass desc) 101 throws IOException, ClassNotFoundException { 102 103 if (classLoader != null) { 104 try { 105 return Class.forName(desc.getName(), false, classLoader); 106 } catch (ClassNotFoundException e) { 107 return super.resolveClass(desc); 108 } 109 } else { 110 return super.resolveClass(desc); 111 } 112 } 113} 114