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