View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  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,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.filter.codec.serialization;
21  
22  import java.io.DataInput;
23  import java.io.DataInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.ObjectInput;
27  import java.io.StreamCorruptedException;
28  
29  import org.apache.mina.core.buffer.BufferDataException;
30  import org.apache.mina.core.buffer.IoBuffer;
31  
32  /**
33   * An {@link ObjectInput} and {@link InputStream} that can read the objects encoded
34   * by {@link ObjectSerializationEncoder}.
35   *
36   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
37   */
38  public class ObjectSerializationInputStream extends InputStream implements ObjectInput {
39  
40      private final DataInputStream in;
41  
42      private final ClassLoader classLoader;
43  
44      private int maxObjectSize = 1048576;
45  
46      /**
47       * Create a new instance of an ObjectSerializationInputStream
48       * @param in The {@link InputStream} to use
49       */
50      public ObjectSerializationInputStream(InputStream in) {
51          this(in, null);
52      }
53  
54      /**
55       * Create a new instance of an ObjectSerializationInputStream
56       * @param in The {@link InputStream} to use
57       * @param classLoader The class loader to use
58       */
59      public ObjectSerializationInputStream(InputStream in, ClassLoader classLoader) {
60          if (in == null) {
61              throw new IllegalArgumentException("in");
62          }
63          
64          if (classLoader == null) {
65              this.classLoader = Thread.currentThread().getContextClassLoader();
66          } else {
67              this.classLoader = classLoader;
68          }
69  
70          if (in instanceof DataInputStream) {
71              this.in = (DataInputStream) in;
72          } else {
73              this.in = new DataInputStream(in);
74          }
75      }
76  
77      /**
78       * @return the allowed maximum size of the object to be decoded.
79       * If the size of the object to be decoded exceeds this value, this
80       * decoder will throw a {@link BufferDataException}.  The default
81       * value is <tt>1048576</tt> (1MB).
82       */
83      public int getMaxObjectSize() {
84          return maxObjectSize;
85      }
86  
87      /**
88       * Sets the allowed maximum size of the object to be decoded.
89       * If the size of the object to be decoded exceeds this value, this
90       * decoder will throw a {@link BufferDataException}.  The default
91       * value is <tt>1048576</tt> (1MB).
92       * 
93       * @param maxObjectSize The maximum decoded object size
94       */
95      public void setMaxObjectSize(int maxObjectSize) {
96          if (maxObjectSize <= 0) {
97              throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
98          }
99  
100         this.maxObjectSize = maxObjectSize;
101     }
102 
103     /**
104      * {@inheritDoc}
105      */
106     @Override
107     public int read() throws IOException {
108         return in.read();
109     }
110 
111     /**
112      * {@inheritDoc}
113      */
114     @Override
115     public Object readObject() throws ClassNotFoundException, IOException {
116         int objectSize = in.readInt();
117         if (objectSize <= 0) {
118             throw new StreamCorruptedException("Invalid objectSize: " + objectSize);
119         }
120         if (objectSize > maxObjectSize) {
121             throw new StreamCorruptedException("ObjectSize too big: " + objectSize + " (expected: <= " + maxObjectSize
122                     + ')');
123         }
124 
125         IoBuffer buf = IoBuffer.allocate(objectSize + 4, false);
126         buf.putInt(objectSize);
127         in.readFully(buf.array(), 4, objectSize);
128         buf.position(0);
129         buf.limit(objectSize + 4);
130 
131         return buf.getObject(classLoader);
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public boolean readBoolean() throws IOException {
139         return in.readBoolean();
140     }
141 
142     /**
143      * {@inheritDoc}
144      */
145     @Override
146     public byte readByte() throws IOException {
147         return in.readByte();
148     }
149 
150     /**
151      * {@inheritDoc}
152      */
153     @Override
154     public char readChar() throws IOException {
155         return in.readChar();
156     }
157 
158     /**
159      * {@inheritDoc}
160      */
161     @Override
162     public double readDouble() throws IOException {
163         return in.readDouble();
164     }
165 
166     /**
167      * {@inheritDoc}
168      */
169     @Override
170     public float readFloat() throws IOException {
171         return in.readFloat();
172     }
173 
174     /**
175      * {@inheritDoc}
176      */
177     @Override
178     public void readFully(byte[] b) throws IOException {
179         in.readFully(b);
180     }
181 
182     /**
183      * {@inheritDoc}
184      */
185     @Override
186     public void readFully(byte[] b, int off, int len) throws IOException {
187         in.readFully(b, off, len);
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
194     public int readInt() throws IOException {
195         return in.readInt();
196     }
197 
198     /**
199      * @see DataInput#readLine()
200      * @deprecated Bytes are not properly converted to chars
201      */
202     @Deprecated
203     @Override
204     public String readLine() throws IOException {
205         return in.readLine();
206     }
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     public long readLong() throws IOException {
213         return in.readLong();
214     }
215 
216     /**
217      * {@inheritDoc}
218      */
219     @Override
220     public short readShort() throws IOException {
221         return in.readShort();
222     }
223 
224     /**
225      * {@inheritDoc}
226      */
227     @Override
228     public String readUTF() throws IOException {
229         return in.readUTF();
230     }
231 
232     /**
233      * {@inheritDoc}
234      */
235     @Override
236     public int readUnsignedByte() throws IOException {
237         return in.readUnsignedByte();
238     }
239 
240     /**
241      * {@inheritDoc}
242      */
243     @Override
244     public int readUnsignedShort() throws IOException {
245         return in.readUnsignedShort();
246     }
247 
248     /**
249      * {@inheritDoc}
250      */
251     @Override
252     public int skipBytes(int n) throws IOException {
253         return in.skipBytes(n);
254     }
255 }