/*
 * $Id: InteractiveCommunicationServlet.java,v 0.0 2008/10/25 11:31:41 t-imamura Exp $
 *
 * Copyright (c) 2008 t-imamura, All rights reserved.
 */
package objsend;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * オブジェクト双方向通信 サーバ(HttpServlet)サイド.
 */
public class InteractiveCommunicationServlet extends HttpServlet {

	/** Serial Version */
	private static final long serialVersionUID = 1L;

	/**
	 * コンストラクタ.
	 */
	public InteractiveCommunicationServlet() {
	}

	/**
	 * サーブレットを初期化します。
	 * @see javax.servlet.GenericServlet#init()
	 * @throws ServletException
	 */
	@Override
	public void init(ServletConfig SC) throws ServletException {
		super.init(SC);
	}

	/**
	 * サーブレットを破棄します。
	 * @see javax.servlet.GenericServlet#destroy()
	 */
	@Override
	public void destroy() {
		super.destroy();
	}

	/**
	 * オブジェクトの送受信を行う。
	 * @param	req	HTTPリクエスト
	 * @param	res	HTTPレスポンス
	 * @throws ServletException
	 * @throws IOException
	 */
	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

		Object reqData = null;
		Object resData = null;

		// オブジェクトストリームから要求オブジェクトの受信
		ObjectInputStream in = null;
		try {
			String encoding = req.getHeader("Content-Encoding");
			if("gzip".equals( encoding ) ){
				// リクエストヘッダの "Content-Encoding" が "gzip" だったらGZIP圧縮されている
				in = new ObjectInputStream(new GZIPInputStream(new BufferedInputStream(req.getInputStream())));
			}else{
				in = new ObjectInputStream(new BufferedInputStream(req.getInputStream()));
			}
			reqData = (Object)in.readObject();
		} catch (ClassNotFoundException e) {
			// オブジェクトストリームから要求オブジェクトが復元できない
			throw new ServletException("a request object of input stream is not found.", e);
		} catch (ObjectStreamException e) {
			// オブジェクトストリームから要求オブジェクトが復元できない
			throw new ServletException("a request object of input stream is not restorable.", e);
		} catch (IOException e) {
			throw e; // IOException はそのままサーブレットに通知
		} finally {
			// オブジェクトストリームのクローズ
			if (in  != null) {
				in.close();
				in  = null;
			}
		}

		// 要求の実行と結果の取得
		resData = execute(reqData);

		// オブジェクトストリームへ応答オブジェクトの送信
		ObjectOutputStream out = null;
		try {
			res.setContentType("application/octet-stream");

			String encoding = req.getHeader("Accept-Encoding");
			if( encoding != null && encoding.indexOf("gzip") != -1 ){
				res.setHeader("Content-Encoding", "gzip");
				out = new ObjectOutputStream(new GZIPOutputStream(new BufferedOutputStream(res.getOutputStream())));
			}else{
				out = new ObjectOutputStream(new BufferedOutputStream(res.getOutputStream()));
			}

			out.writeObject(resData);
			out.flush();

		} catch (ObjectStreamException e) {
			// 応答オブジェクトを直列化してオブジェクトストリームに渡せない
			throw new ServletException("a response object of output stream is not serialize.", e);
		} catch (IOException e) {
			throw e; // IOException はそのままサーブレットに通知
		} finally {
			// オブジェクトストリームのクローズ
			if (out != null) {
				out.close();
				out = null;
			}
		}

	}

	/**
	 * 処理を行います。
	 * @param reqData 要求オブジェクト
	 * @return 応答オブジェクト
	 */
	protected Object execute(Object reqData) {
		return reqData;
	}

}
