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.DataOutputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.ObjectOutput;
026import java.io.OutputStream;
027
028import org.apache.mina.core.buffer.IoBuffer;
029
030/**
031 * An {@link ObjectOutput} and {@link OutputStream} that can write the objects as
032 * the serialized form that {@link ObjectSerializationDecoder} can decode.
033 *
034 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
035 */
036public class ObjectSerializationOutputStream extends OutputStream implements ObjectOutput {
037
038    private final DataOutputStream out;
039
040    private int maxObjectSize = Integer.MAX_VALUE;
041
042    /**
043     * Create a new instance of an ObjectSerializationOutputStream
044     * @param out The {@link OutputStream} to use
045     */
046    public ObjectSerializationOutputStream(OutputStream out) {
047        if (out == null) {
048            throw new IllegalArgumentException("out");
049        }
050
051        if (out instanceof DataOutputStream) {
052            this.out = (DataOutputStream) out;
053        } else {
054            this.out = new DataOutputStream(out);
055        }
056    }
057
058    /**
059     * @return the allowed maximum size of the encoded object.
060     * If the size of the encoded object exceeds this value, this encoder
061     * will throw a {@link IllegalArgumentException}.  The default value
062     * is {@link Integer#MAX_VALUE}.
063     */
064    public int getMaxObjectSize() {
065        return maxObjectSize;
066    }
067
068    /**
069     * Sets the allowed maximum size of the encoded object.
070     * If the size of the encoded object exceeds this value, this encoder
071     * will throw a {@link IllegalArgumentException}.  The default value
072     * is {@link Integer#MAX_VALUE}.
073     * 
074     * @param maxObjectSize The maximum object size
075     */
076    public void setMaxObjectSize(int maxObjectSize) {
077        if (maxObjectSize <= 0) {
078            throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
079        }
080
081        this.maxObjectSize = maxObjectSize;
082    }
083
084    /**
085     * {@inheritDoc}
086     */
087    @Override
088    public void close() throws IOException {
089        out.close();
090    }
091
092    /**
093     * {@inheritDoc}
094     */
095    @Override
096    public void flush() throws IOException {
097        out.flush();
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    @Override
104    public void write(int b) throws IOException {
105        out.write(b);
106    }
107
108    /**
109     * {@inheritDoc}
110     */
111    @Override
112    public void write(byte[] b) throws IOException {
113        out.write(b);
114    }
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public void write(byte[] b, int off, int len) throws IOException {
121        out.write(b, off, len);
122    }
123
124    /**
125     * {@inheritDoc}
126     */
127    public void writeObject(Object obj) throws IOException {
128        IoBuffer buf = IoBuffer.allocate(64, false);
129        buf.setAutoExpand(true);
130        buf.putObject(obj);
131
132        int objectSize = buf.position() - 4;
133        if (objectSize > maxObjectSize) {
134            throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + maxObjectSize
135                    + ')');
136        }
137
138        out.write(buf.array(), 0, buf.position());
139    }
140
141    /**
142     * {@inheritDoc}
143     */
144    public void writeBoolean(boolean v) throws IOException {
145        out.writeBoolean(v);
146    }
147
148    /**
149     * {@inheritDoc}
150     */
151    public void writeByte(int v) throws IOException {
152        out.writeByte(v);
153    }
154
155    /**
156     * {@inheritDoc}
157     */
158    public void writeBytes(String s) throws IOException {
159        out.writeBytes(s);
160    }
161
162    /**
163     * {@inheritDoc}
164     */
165    public void writeChar(int v) throws IOException {
166        out.writeChar(v);
167    }
168
169    /**
170     * {@inheritDoc}
171     */
172    public void writeChars(String s) throws IOException {
173        out.writeChars(s);
174    }
175
176    /**
177     * {@inheritDoc}
178     */
179    public void writeDouble(double v) throws IOException {
180        out.writeDouble(v);
181    }
182
183    /**
184     * {@inheritDoc}
185     */
186    public void writeFloat(float v) throws IOException {
187        out.writeFloat(v);
188    }
189
190    /**
191     * {@inheritDoc}
192     */
193    public void writeInt(int v) throws IOException {
194        out.writeInt(v);
195    }
196
197    /**
198     * {@inheritDoc}
199     */
200    public void writeLong(long v) throws IOException {
201        out.writeLong(v);
202    }
203
204    /**
205     * {@inheritDoc}
206     */
207    public void writeShort(int v) throws IOException {
208        out.writeShort(v);
209    }
210
211    /**
212     * {@inheritDoc}
213     */
214    public void writeUTF(String str) throws IOException {
215        out.writeUTF(str);
216    }
217}