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.NotSerializableException;
023import java.io.Serializable;
024
025import org.apache.mina.core.buffer.IoBuffer;
026import org.apache.mina.core.session.IoSession;
027import org.apache.mina.filter.codec.ProtocolEncoder;
028import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
029import org.apache.mina.filter.codec.ProtocolEncoderOutput;
030
031/**
032 * A {@link ProtocolEncoder} which serializes {@link Serializable} Java objects
033 * using {@link IoBuffer#putObject(Object)}.
034 *
035 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
036 */
037public class ObjectSerializationEncoder extends ProtocolEncoderAdapter {
038    private int maxObjectSize = Integer.MAX_VALUE; // 2GB
039
040    /**
041     * Creates a new instance.
042     */
043    public ObjectSerializationEncoder() {
044        // Do nothing
045    }
046
047    /**
048     * @return the allowed maximum size of the encoded object.
049     * If the size of the encoded object exceeds this value, this encoder
050     * will throw a {@link IllegalArgumentException}.  The default value
051     * is {@link Integer#MAX_VALUE}.
052     */
053    public int getMaxObjectSize() {
054        return maxObjectSize;
055    }
056
057    /**
058     * Sets 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     * @param maxObjectSize the maximum size for an encoded object
064     */
065    public void setMaxObjectSize(int maxObjectSize) {
066        if (maxObjectSize <= 0) {
067            throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
068        }
069
070        this.maxObjectSize = maxObjectSize;
071    }
072
073    /**
074     * {@inheritDoc}
075     */
076    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
077        if (!(message instanceof Serializable)) {
078            throw new NotSerializableException();
079        }
080
081        IoBuffer buf = IoBuffer.allocate(64);
082        buf.setAutoExpand(true);
083        buf.putObject(message);
084
085        int objectSize = buf.position() - 4;
086        if (objectSize > maxObjectSize) {
087            throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + maxObjectSize
088                    + ')');
089        }
090
091        buf.flip();
092        out.write(buf);
093    }
094}