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    *   https://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 io.netty.util.internal.ObjectUtil;
19  
20  import java.io.BufferedReader;
21  import java.io.DataInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.ObjectInput;
25  import java.io.StreamCorruptedException;
26  
27  /**
28   * An {@link ObjectInput} which is interoperable with {@link ObjectEncoder}
29   * and {@link ObjectEncoderOutputStream}.
30   */
31  public class ObjectDecoderInputStream extends InputStream implements
32          ObjectInput {
33  
34      private final DataInputStream in;
35      private final int maxObjectSize;
36      private final ClassResolver classResolver;
37  
38      /**
39       * Creates a new {@link ObjectInput}.
40       *
41       * @param in
42       *        the {@link InputStream} where the serialized form will be
43       *        read from
44       */
45      public ObjectDecoderInputStream(InputStream in) {
46          this(in, null);
47      }
48  
49      /**
50       * Creates a new {@link ObjectInput}.
51       *
52       * @param in
53       *        the {@link InputStream} where the serialized form will be
54       *        read from
55       * @param classLoader
56       *        the {@link ClassLoader} which will load the class of the
57       *        serialized object
58       */
59      public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader) {
60          this(in, classLoader, 1048576);
61      }
62  
63      /**
64       * Creates a new {@link ObjectInput}.
65       *
66       * @param in
67       *        the {@link InputStream} where the serialized form will be
68       *        read from
69       * @param maxObjectSize
70       *        the maximum byte length of the serialized object.  if the length
71       *        of the received object is greater than this value,
72       *        a {@link StreamCorruptedException} will be raised.
73       */
74      public ObjectDecoderInputStream(InputStream in, int maxObjectSize) {
75          this(in, null, maxObjectSize);
76      }
77  
78      /**
79       * Creates a new {@link ObjectInput}.
80       *
81       * @param in
82       *        the {@link InputStream} where the serialized form will be
83       *        read from
84       * @param classLoader
85       *        the {@link ClassLoader} which will load the class of the
86       *        serialized object
87       * @param maxObjectSize
88       *        the maximum byte length of the serialized object.  if the length
89       *        of the received object is greater than this value,
90       *        a {@link StreamCorruptedException} will be raised.
91       */
92      public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader, int maxObjectSize) {
93          ObjectUtil.checkNotNull(in, "in");
94          ObjectUtil.checkPositive(maxObjectSize, "maxObjectSize");
95  
96          if (in instanceof DataInputStream) {
97              this.in = (DataInputStream) in;
98          } else {
99              this.in = new DataInputStream(in);
100         }
101         classResolver = ClassResolvers.weakCachingResolver(classLoader);
102         this.maxObjectSize = maxObjectSize;
103     }
104 
105     @Override
106     public Object readObject() throws ClassNotFoundException, IOException {
107         int dataLen = readInt();
108         if (dataLen <= 0) {
109             throw new StreamCorruptedException("invalid data length: " + dataLen);
110         }
111         if (dataLen > maxObjectSize) {
112             throw new StreamCorruptedException(
113                     "data length too big: " + dataLen + " (max: " + maxObjectSize + ')');
114         }
115 
116         return new CompactObjectInputStream(in, classResolver).readObject();
117     }
118 
119     @Override
120     public int available() throws IOException {
121         return in.available();
122     }
123 
124     @Override
125     public void close() throws IOException {
126         in.close();
127     }
128 
129     // Suppress a warning since the class is not thread-safe
130     @Override
131     public void mark(int readlimit) {   // lgtm[java/non-sync-override]
132         in.mark(readlimit);
133     }
134 
135     @Override
136     public boolean markSupported() {
137         return in.markSupported();
138     }
139 
140     // Suppress a warning since the class is not thread-safe
141     @Override
142     public int read() throws IOException {  // lgtm[java/non-sync-override]
143         return in.read();
144     }
145 
146     @Override
147     public final int read(byte[] b, int off, int len) throws IOException {
148         return in.read(b, off, len);
149     }
150 
151     @Override
152     public final int read(byte[] b) throws IOException {
153         return in.read(b);
154     }
155 
156     @Override
157     public final boolean readBoolean() throws IOException {
158         return in.readBoolean();
159     }
160 
161     @Override
162     public final byte readByte() throws IOException {
163         return in.readByte();
164     }
165 
166     @Override
167     public final char readChar() throws IOException {
168         return in.readChar();
169     }
170 
171     @Override
172     public final double readDouble() throws IOException {
173         return in.readDouble();
174     }
175 
176     @Override
177     public final float readFloat() throws IOException {
178         return in.readFloat();
179     }
180 
181     @Override
182     public final void readFully(byte[] b, int off, int len) throws IOException {
183         in.readFully(b, off, len);
184     }
185 
186     @Override
187     public final void readFully(byte[] b) throws IOException {
188         in.readFully(b);
189     }
190 
191     @Override
192     public final int readInt() throws IOException {
193         return in.readInt();
194     }
195 
196     /**
197      * @deprecated Use {@link BufferedReader#readLine()} instead.
198      */
199     @Override
200     @Deprecated
201     public final String readLine() throws IOException {
202         return in.readLine();
203     }
204 
205     @Override
206     public final long readLong() throws IOException {
207         return in.readLong();
208     }
209 
210     @Override
211     public final short readShort() throws IOException {
212         return in.readShort();
213     }
214 
215     @Override
216     public final int readUnsignedByte() throws IOException {
217         return in.readUnsignedByte();
218     }
219 
220     @Override
221     public final int readUnsignedShort() throws IOException {
222         return in.readUnsignedShort();
223     }
224 
225     @Override
226     public final String readUTF() throws IOException {
227         return in.readUTF();
228     }
229 
230     @Override
231     public void reset() throws IOException {
232         in.reset();
233     }
234 
235     @Override
236     public long skip(long n) throws IOException {
237         return in.skip(n);
238     }
239 
240     @Override
241     public final int skipBytes(int n) throws IOException {
242         return in.skipBytes(n);
243     }
244 }