001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.filter.codec.serialization;
021
022import java.io.DataInput;
023import java.io.DataInputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.ObjectInput;
027import java.io.StreamCorruptedException;
028
029import org.apache.mina.core.buffer.BufferDataException;
030import org.apache.mina.core.buffer.IoBuffer;
031
032/**
033 * An {@link ObjectInput} and {@link InputStream} that can read the objects encoded
034 * by {@link ObjectSerializationEncoder}.
035 *
036 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
037 */
038public class ObjectSerializationInputStream extends InputStream implements ObjectInput {
039
040    private final DataInputStream in;
041
042    private final ClassLoader classLoader;
043
044    private int maxObjectSize = 1048576;
045
046    /**
047     * Create a new instance of an ObjectSerializationInputStream
048     * @param in The {@link InputStream} to use
049     */
050    public ObjectSerializationInputStream(InputStream in) {
051        this(in, null);
052    }
053
054    /**
055     * Create a new instance of an ObjectSerializationInputStream
056     * @param in The {@link InputStream} to use
057     * @param classLoader The class loader to use
058     */
059    public ObjectSerializationInputStream(InputStream in, ClassLoader classLoader) {
060        if (in == null) {
061            throw new IllegalArgumentException("in");
062        }
063        
064        if (classLoader == null) {
065            classLoader = Thread.currentThread().getContextClassLoader();
066        }
067
068        if (in instanceof DataInputStream) {
069            this.in = (DataInputStream) in;
070        } else {
071            this.in = new DataInputStream(in);
072        }
073
074        this.classLoader = classLoader;
075    }
076
077    /**
078     * @return the allowed maximum size of the object to be decoded.
079     * If the size of the object to be decoded exceeds this value, this
080     * decoder will throw a {@link BufferDataException}.  The default
081     * value is <tt>1048576</tt> (1MB).
082     */
083    public int getMaxObjectSize() {
084        return maxObjectSize;
085    }
086
087    /**
088     * Sets the allowed maximum size of the object to be decoded.
089     * If the size of the object to be decoded exceeds this value, this
090     * decoder will throw a {@link BufferDataException}.  The default
091     * value is <tt>1048576</tt> (1MB).
092     * 
093     * @param maxObjectSize The maximum decoded object size
094     */
095    public void setMaxObjectSize(int maxObjectSize) {
096        if (maxObjectSize <= 0) {
097            throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
098        }
099
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    public Object readObject() throws ClassNotFoundException, IOException {
115        int objectSize = in.readInt();
116        if (objectSize <= 0) {
117            throw new StreamCorruptedException("Invalid objectSize: " + objectSize);
118        }
119        if (objectSize > maxObjectSize) {
120            throw new StreamCorruptedException("ObjectSize too big: " + objectSize + " (expected: <= " + maxObjectSize
121                    + ')');
122        }
123
124        IoBuffer buf = IoBuffer.allocate(objectSize + 4, false);
125        buf.putInt(objectSize);
126        in.readFully(buf.array(), 4, objectSize);
127        buf.position(0);
128        buf.limit(objectSize + 4);
129
130        return buf.getObject(classLoader);
131    }
132
133    /**
134     * {@inheritDoc}
135     */
136    public boolean readBoolean() throws IOException {
137        return in.readBoolean();
138    }
139
140    /**
141     * {@inheritDoc}
142     */
143    public byte readByte() throws IOException {
144        return in.readByte();
145    }
146
147    /**
148     * {@inheritDoc}
149     */
150    public char readChar() throws IOException {
151        return in.readChar();
152    }
153
154    /**
155     * {@inheritDoc}
156     */
157    public double readDouble() throws IOException {
158        return in.readDouble();
159    }
160
161    /**
162     * {@inheritDoc}
163     */
164    public float readFloat() throws IOException {
165        return in.readFloat();
166    }
167
168    /**
169     * {@inheritDoc}
170     */
171    public void readFully(byte[] b) throws IOException {
172        in.readFully(b);
173    }
174
175    /**
176     * {@inheritDoc}
177     */
178    public void readFully(byte[] b, int off, int len) throws IOException {
179        in.readFully(b, off, len);
180    }
181
182    /**
183     * {@inheritDoc}
184     */
185    public int readInt() throws IOException {
186        return in.readInt();
187    }
188
189    /**
190     * @see DataInput#readLine()
191     * @deprecated
192     */
193    @Deprecated
194    public String readLine() throws IOException {
195        return in.readLine();
196    }
197
198    /**
199     * {@inheritDoc}
200     */
201    public long readLong() throws IOException {
202        return in.readLong();
203    }
204
205    /**
206     * {@inheritDoc}
207     */
208    public short readShort() throws IOException {
209        return in.readShort();
210    }
211
212    /**
213     * {@inheritDoc}
214     */
215    public String readUTF() throws IOException {
216        return in.readUTF();
217    }
218
219    /**
220     * {@inheritDoc}
221     */
222    public int readUnsignedByte() throws IOException {
223        return in.readUnsignedByte();
224    }
225
226    /**
227     * {@inheritDoc}
228     */
229    public int readUnsignedShort() throws IOException {
230        return in.readUnsignedShort();
231    }
232
233    /**
234     * {@inheritDoc}
235     */
236    public int skipBytes(int n) throws IOException {
237        return in.skipBytes(n);
238    }
239}