package com.eactive.eai.adapter.socket2.protocol.object.codec;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

import java.io.NotSerializableException;
import java.io.Serializable;

public class ObjectSerializationEncoder extends ProtocolEncoderAdapter {
	private int maxObjectSize = Integer.MAX_VALUE; // 2GB

	/**
	 * Creates a new instance.
	 */
	public ObjectSerializationEncoder() {
		// empty
	}

	/**
	 * Returns the allowed maximum size of the encoded object. If the size of
	 * the encoded object exceeds this value, this encoder will throw a
	 * {@link IllegalArgumentException}. The default value is
	 * {@link Integer#MAX_VALUE}.
	 */
	public int getMaxObjectSize() {
		return maxObjectSize;
	}

	/**
	 * Sets the allowed maximum size of the encoded object. If the size of the
	 * encoded object exceeds this value, this encoder will throw a
	 * {@link IllegalArgumentException}. The default value is
	 * {@link Integer#MAX_VALUE}.
	 */
	public void setMaxObjectSize(int maxObjectSize) {
		if (maxObjectSize <= 0) {
			throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
		}

		this.maxObjectSize = maxObjectSize;
	}

	public void encode(IoSession session, Object message, ProtocolEncoderOutput out)
			throws Exception {
		if (!(message instanceof Serializable)) {
			throw new NotSerializableException();
		}

		ByteBuffer buf = ByteBuffer.allocate(64);
		buf.setAutoExpand(true);
		buf.putObject(message);

		int objectSize = buf.position() - 4;
		if (objectSize > maxObjectSize) {
			buf.release();
			throw new IllegalArgumentException("The encoded object is too big: " + objectSize
					+ " (> " + maxObjectSize + ')');
		}

		buf.flip();
		out.write(buf);
	}
}
