001: /*
002:
003: Derby - Class org.apache.derby.iapi.services.io.FormatIdInputStream
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.services.io;
023:
024: import java.io.DataInputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.io.ObjectInputStream;
028: import java.io.StreamCorruptedException;
029: import org.apache.derby.iapi.reference.SQLState;
030: import org.apache.derby.iapi.services.monitor.Monitor;
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032: import org.apache.derby.iapi.error.StandardException;
033: import org.apache.derby.iapi.services.loader.ClassFactory;
034: import org.apache.derby.iapi.services.loader.ClassFactoryContext;
035: import org.apache.derby.iapi.types.Resetable;
036:
037: import org.apache.derby.iapi.services.context.ContextService;
038:
039: /**
040: A stream for reading objects with format id tags which was
041: produced by a FormatIdOutputStream.
042:
043: <P>Please see the documentation for FormatIdOutputStream for
044: information about the streams format and capabilites.
045: */
046: public final class FormatIdInputStream extends DataInputStream
047: implements ErrorObjectInput, Resetable {
048: protected ClassFactory cf;
049: private ErrorInfo errorInfo;
050: private Exception myNestedException;
051:
052: /**
053: Constructor for a FormatIdInputStream
054:
055: @param in bytes come from here.
056: */
057: public FormatIdInputStream(InputStream in) {
058: super (in);
059: }
060:
061: /**
062: Read an object from this stream.
063:
064: @return The read object.
065: @exception java.io.IOException An IO or serialization error occured.
066: @exception java.lang.ClassNotFoundException A class for an object in
067: the stream could not be found.
068: */
069:
070: public Object readObject() throws IOException,
071: ClassNotFoundException {
072: setErrorInfo(null);
073:
074: int fmtId = FormatIdUtil.readFormatIdInteger(this );
075:
076: if (fmtId == StoredFormatIds.NULL_FORMAT_ID) {
077: return null;
078: }
079:
080: if (fmtId == StoredFormatIds.STRING_FORMAT_ID) {
081: return readUTF();
082: }
083:
084: try {
085:
086: if (fmtId == StoredFormatIds.SERIALIZABLE_FORMAT_ID) {
087: ObjectInputStream ois = getObjectStream();
088: try {
089: Object result = ois.readObject();
090: return result;
091: } catch (IOException ioe) {
092: setErrorInfo((ErrorInfo) ois);
093: throw ioe;
094: } catch (ClassNotFoundException cnfe) {
095: setErrorInfo((ErrorInfo) ois);
096: throw cnfe;
097: } catch (LinkageError le) {
098: setErrorInfo((ErrorInfo) ois);
099: throw le;
100: } catch (ClassCastException cce) {
101: setErrorInfo((ErrorInfo) ois);
102: throw cce;
103: }
104: }
105:
106: try {
107:
108: Formatable f = (Formatable) Monitor
109: .newInstanceFromIdentifier(fmtId);
110: if (f instanceof Storable) {
111: boolean isNull = this .readBoolean();
112: if (isNull == true) {
113: Storable s = (Storable) f;
114: s.restoreToNull();
115: return s;
116: }
117: }
118:
119: f.readExternal(this );
120: return f;
121: } catch (StandardException se) {
122: throw new ClassNotFoundException(se.toString());
123: }
124:
125: } catch (ClassCastException cce) {
126: // We catch this here as it is usuall a user error.
127: // they have readExternal (or SQLData) that doesn't match
128: // the writeExternal. and thus the object read is of
129: // the incorrect type, e.g. Integer i = (Integer) in.readObject();
130: throw new StreamCorruptedException(cce.toString());
131: }
132: }
133:
134: /**
135: Set the InputStream for this FormatIdInputStream to the stream
136: provided.
137:
138: @param in The new input stream.
139: */
140: public void setInput(InputStream in) {
141: this .in = in;
142: }
143:
144: public InputStream getInputStream() {
145: return in;
146: }
147:
148: public String getErrorInfo() {
149: if (errorInfo == null)
150: return "";
151:
152: return errorInfo.getErrorInfo();
153: }
154:
155: public Exception getNestedException() {
156: if (myNestedException != null)
157: return null;
158:
159: if (errorInfo == null)
160: return null;
161:
162: return errorInfo.getNestedException();
163: }
164:
165: private void setErrorInfo(ErrorInfo ei) {
166: errorInfo = ei;
167: }
168:
169: ClassFactory getClassFactory() {
170: if (cf == null) {
171:
172: ClassFactoryContext cfc = (ClassFactoryContext) ContextService
173: .getContextOrNull(ClassFactoryContext.CONTEXT_ID);
174:
175: if (cfc != null)
176: cf = cfc.getClassFactory();
177: }
178: return cf;
179: }
180:
181: /*
182: ** Class private methods
183: */
184:
185: private ObjectInputStream getObjectStream() throws IOException {
186:
187: return getClassFactory() == null ? new ObjectInputStream(this )
188: : new ApplicationObjectInputStream(this , cf);
189: }
190:
191: /*** Resetable interface ***/
192:
193: public void resetStream() throws IOException, StandardException {
194: if (SanityManager.DEBUG)
195: SanityManager.ASSERT(in instanceof Resetable);
196: ((Resetable) in).resetStream();
197: }
198:
199: public void initStream() throws StandardException {
200: if (SanityManager.DEBUG)
201: SanityManager.ASSERT(in instanceof Resetable);
202: ((Resetable) in).initStream();
203: }
204:
205: public void closeStream() {
206: if (SanityManager.DEBUG)
207: SanityManager.ASSERT(in instanceof Resetable);
208: ((Resetable) in).closeStream();
209: }
210:
211: }
|