View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.serialization;
17  
18  import java.io.BufferedReader;
19  import java.io.DataInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.ObjectInput;
23  import java.io.StreamCorruptedException;
24  
25  /**
26   * An {@link ObjectInput} which is interoperable with {@link ObjectEncoder}
27   * and {@link ObjectEncoderOutputStream}.
28   */
29  public class ObjectDecoderInputStream extends InputStream implements
30          ObjectInput {
31  
32      private final DataInputStream in;
33      private final int maxObjectSize;
34      private final ClassResolver classResolver;
35  
36      /**
37       * Creates a new {@link ObjectInput}.
38       *
39       * @param in
40       *        the {@link InputStream} where the serialized form will be
41       *        read from
42       */
43      public ObjectDecoderInputStream(InputStream in) {
44          this(in, null);
45      }
46  
47      /**
48       * Creates a new {@link ObjectInput}.
49       *
50       * @param in
51       *        the {@link InputStream} where the serialized form will be
52       *        read from
53       * @param classLoader
54       *        the {@link ClassLoader} which will load the class of the
55       *        serialized object
56       */
57      public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader) {
58          this(in, classLoader, 1048576);
59      }
60  
61      /**
62       * Creates a new {@link ObjectInput}.
63       *
64       * @param in
65       *        the {@link InputStream} where the serialized form will be
66       *        read from
67       * @param maxObjectSize
68       *        the maximum byte length of the serialized object.  if the length
69       *        of the received object is greater than this value,
70       *        a {@link StreamCorruptedException} will be raised.
71       */
72      public ObjectDecoderInputStream(InputStream in, int maxObjectSize) {
73          this(in, null, maxObjectSize);
74      }
75  
76      /**
77       * Creates a new {@link ObjectInput}.
78       *
79       * @param in
80       *        the {@link InputStream} where the serialized form will be
81       *        read from
82       * @param classLoader
83       *        the {@link ClassLoader} which will load the class of the
84       *        serialized object
85       * @param maxObjectSize
86       *        the maximum byte length of the serialized object.  if the length
87       *        of the received object is greater than this value,
88       *        a {@link StreamCorruptedException} will be raised.
89       */
90      public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader, int maxObjectSize) {
91          if (in == null) {
92              throw new NullPointerException("in");
93          }
94          if (maxObjectSize <= 0) {
95              throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
96          }
97          if (in instanceof DataInputStream) {
98              this.in = (DataInputStream) in;
99          } else {
100             this.in = new DataInputStream(in);
101         }
102         classResolver = ClassResolvers.weakCachingResolver(classLoader);
103         this.maxObjectSize = maxObjectSize;
104     }
105 
106     @Override
107     public Object readObject() throws ClassNotFoundException, IOException {
108         int dataLen = readInt();
109         if (dataLen <= 0) {
110             throw new StreamCorruptedException("invalid data length: " + dataLen);
111         }
112         if (dataLen > maxObjectSize) {
113             throw new StreamCorruptedException(
114                     "data length too big: " + dataLen + " (max: " + maxObjectSize + ')');
115         }
116 
117         return new CompactObjectInputStream(in, classResolver).readObject();
118     }
119 
120     @Override
121     public int available() throws IOException {
122         return in.available();
123     }
124 
125     @Override
126     public void close() throws IOException {
127         in.close();
128     }
129 
130     @Override
131     public void mark(int readlimit) {
132         in.mark(readlimit);
133     }
134 
135     @Override
136     public boolean markSupported() {
137         return in.markSupported();
138     }
139 
140     @Override
141     public int read() throws IOException {
142         return in.read();
143     }
144 
145     @Override
146     public final int read(byte[] b, int off, int len) throws IOException {
147         return in.read(b, off, len);
148     }
149 
150     @Override
151     public final int read(byte[] b) throws IOException {
152         return in.read(b);
153     }
154 
155     @Override
156     public final boolean readBoolean() throws IOException {
157         return in.readBoolean();
158     }
159 
160     @Override
161     public final byte readByte() throws IOException {
162         return in.readByte();
163     }
164 
165     @Override
166     public final char readChar() throws IOException {
167         return in.readChar();
168     }
169 
170     @Override
171     public final double readDouble() throws IOException {
172         return in.readDouble();
173     }
174 
175     @Override
176     public final float readFloat() throws IOException {
177         return in.readFloat();
178     }
179 
180     @Override
181     public final void readFully(byte[] b, int off, int len) throws IOException {
182         in.readFully(b, off, len);
183     }
184 
185     @Override
186     public final void readFully(byte[] b) throws IOException {
187         in.readFully(b);
188     }
189 
190     @Override
191     public final int readInt() throws IOException {
192         return in.readInt();
193     }
194 
195     /**
196      * @deprecated Use {@link BufferedReader#readLine()} instead.
197      */
198     @Override
199     @Deprecated
200     public final String readLine() throws IOException {
201         return in.readLine();
202     }
203 
204     @Override
205     public final long readLong() throws IOException {
206         return in.readLong();
207     }
208 
209     @Override
210     public final short readShort() throws IOException {
211         return in.readShort();
212     }
213 
214     @Override
215     public final int readUnsignedByte() throws IOException {
216         return in.readUnsignedByte();
217     }
218 
219     @Override
220     public final int readUnsignedShort() throws IOException {
221         return in.readUnsignedShort();
222     }
223 
224     @Override
225     public final String readUTF() throws IOException {
226         return in.readUTF();
227     }
228 
229     @Override
230     public void reset() throws IOException {
231         in.reset();
232     }
233 
234     @Override
235     public long skip(long n) throws IOException {
236         return in.skip(n);
237     }
238 
239     @Override
240     public final int skipBytes(int n) throws IOException {
241         return in.skipBytes(n);
242     }
243 }