/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	OfficeLo　リソースアクセスクラス
//			変更履歴
//				2004.01.08	新規作成	二條智文
//
package jp.co.ntt.lms.lo.Office;

// XMS2 API
import jp.co.ntt.lms.lo.LoTopClient;
import jp.co.ntt.lms.lo.LOException;
import jp.co.ntt.lms.lo.Office.OfficeLoEnv;
import jp.co.ntt.lms.lo.Office.OfficeLoData;
import jp.co.ntt.lms.lo.LoComData;
import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.MessageData;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.XMOPropertyDef;
import jp.co.ntt.lms.xmo.Base.XMSBaseClient;
import jp.co.ntt.lms.xmo.Lo.LoData;
import jp.co.ntt.lms.xmo.LoRelation.LoRelationClient;

// JAVA API
import java.io.File;
import java.util.*;
import java.io.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import javax.servlet.RequestDispatcher;

/**
 * OfficeLo　リソースアクセスクラス<BR>
 * ログインチェック、権限チェックを行い、権限があるユーザのみOffice文書を公開する
 */
public class OfficeMaterialServlet extends HttpServlet
{
	/** バッファサイズ */
	private static final int BUF_SIZE = 8 * 1024;


	/** LOが存在しないエラー */
	private static final String NO_EXIST_LO = "指定されたOfficeLOは存在しません。";
	/** ファイルが存在しないエラー */
	private static final String NO_EXIST_FILE = "指定されたOffice文書が存在しません。";
	/** 権限がない場合のエラー */
	private static final String NO_AUTH_ERR = "権限がないためこのページは表示できません。";

	/**
	 * コンストラクタ
	 */
	public OfficeMaterialServlet() {}

	/**
	 * ＧＥＴ要求を処理するメソッド<BR>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	public void doGet(
		HttpServletRequest request,HttpServletResponse response)
			throws ServletException, IOException
	{
		// リクエスト処理を呼び出します
		this.doRequest(request, response);
	}

	/**
	 * ＰＯＳＴ要求を処理するメソッド<BR>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	public void doPost(
		HttpServletRequest request,HttpServletResponse response)
			throws ServletException, IOException
	{
		// リクエスト処理を呼び出します
		this.doRequest(request, response);
	}

	/**
	 * 要求を処理するメソッド<BR>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 */
	private void doRequest(
		HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{
		String strLoID			= request.getParameter( "LoID" );		// LoID
		String strRefLoID		= request.getParameter( "RefLoID" );	// 参照LOID
		String strLoType		= request.getParameter( "LoType" );		// LoType
		String strExtension		= request.getParameter( "extension" );		// 拡張子
		String strLoginUserID	= null;										// ログインユーザID


		// セッションからログインユーザIDを取得する
		HttpSession session = request.getSession();
		strLoginUserID = (String)session.getAttribute("userId");

		// パラメータチェック
		if( strLoID == null ||
			strRefLoID == null ||
			strLoType == null ||
			strLoginUserID == null )
		{
			// ログインしていない場合またはパラメータが不正の場合は権限エラー画面に遷移する。
			goWarningpage( request, response, NO_AUTH_ERR );
			return;
		}

		try {

			// 権限チェック
			if( !checkAuth( strLoginUserID, strRefLoID ) ) {
				// 権限がない場合は権限エラー画面に遷移する。
				goWarningpage( request, response, NO_AUTH_ERR );
				return;
			}

			// フォルダパス取得
			OfficeLoEnv objOfficeEnv = new OfficeLoEnv();
			String strMatPath = objOfficeEnv.getMaterialPath();

			// Loサーバ名を取得する
			Environment objEnv = new Environment();
			String strLoServerName = objEnv.getLoServerName();
			// Loディレクトリを取得する
			String strSystemDir = objEnv.getSystemDir();

			LoTopClient objLoTop = new LoTopClient( strLoServerName, strLoType );
			// 検索処理
			if( !objLoTop.getData(strLoID) ) {
				// 検索がうまくいかなかった場合
				MessageData objMessage = objLoTop.getMessageData();
				response.sendRedirect( objMessage.getURL() );
				return;
			}

			// 検索件数をチェックし、0件名ならエラーとする
			// (すでに削除されている)
			if( objLoTop.getDataLength() == 0 ) {
				// すでにLOが存在しない場合はLO未存在エラー画面
				goWarningpage( request, response, NO_EXIST_LO );
				return;
			}

			// 検索がうまくいった場合はデータを取得する
			LoComData objData = objLoTop.getDataInfo(0);
			OfficeLoData objOfficeLoData = (OfficeLoData)objData;
			String strFileName = objOfficeLoData.getLOUrl();

			// 拡張子からMimeTypeを取得し、Response のContent-typeに設定します。
			// 拡張子から'.'を取り除く
			if( strExtension != null ) {
				int intPos = strExtension.indexOf( '.' );
				if( intPos >= 0 ) {
					strExtension = strExtension.substring( intPos + 1, strExtension.length() );
				}
			}

			// 拡張子からMimeTypeを取得します。
			OfficeMIMEType objMimeType = new OfficeMIMEType();
			String strMimeType = objMimeType.getMimeType( strExtension );

			if( strMimeType != null ) {
				response.setContentType( strMimeType );
			}

			// ヘッダにキャッシュ無効設定がしてある場合は書き換えます。
			response.setHeader( "Pragma", "cache");
			response.setHeader( "cache-control", "cache" );

			// ファイルパスの生成
			String strFilePath = strMatPath + "/" + strLoType + "/" + strLoID + "/" + strFileName;

			byte[] buff = new byte[BUF_SIZE];
			int intSize = -1;

			// ファイルの読み込み
			FileInputStream input = new FileInputStream( strFilePath );
			OutputStream out = response.getOutputStream();

			while( ( intSize = input.read( buff ) ) >= 0 ) {
				out.write( buff ,0 , intSize );
			}

			input.close();

		}
		catch( FileNotFoundException fe ) {
			// ファイルが存在しない場合は画面にその旨を表示する
			goWarningpage( request, response, NO_EXIST_FILE );
			return;
		}
		catch( Exception e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			goErrorPage( request, response, e.getMessage() );
		}
	}

	/**
	 * 警告ページ画面へフォワードするメソッド<BR>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @param HttpServletResponse	エラーメッセージ
	 * @return void
	 */
	private void goErrorPage(
		HttpServletRequest request, HttpServletResponse response,
		String strErrorMessage)
			throws ServletException, IOException
	{
		request.setAttribute("ErrorMessage", strErrorMessage);
		ServletContext objSc    = getServletContext();
		RequestDispatcher objRd = objSc.getRequestDispatcher("/view/lo/Com/ComErr.vm");
		objRd.forward(request, response);
	}

	/**
	 * エラーページ画面へフォワードするメソッド<BR>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @param HttpServletResponse	エラーメッセージ
	 * @return void
	 */
	private void goWarningpage(
		HttpServletRequest request, HttpServletResponse response,
		String strErrorMessage)
			throws ServletException, IOException
	{
		request.setAttribute("WarningMessage", strErrorMessage);
		ServletContext objSc    = getServletContext();
		RequestDispatcher objRd = objSc.getRequestDispatcher("/view/lo/Office/OfficeWarning.vm");
		objRd.forward(request, response);
	}

	/**
	 * 権限チェック
	 *  以下のチェックをする
	 *    LOのアサインチェック
	 *    指定されたLOがアサインされていない場合はエラーとする
	 * @return boolean true: 権限有り false: 権限なし
	 */
	private boolean checkAuth( String strUserID, String strLoID )
		throws LOException, Exception
	{
		// ユーザIDがスーパユーザの場合は無条件にOK
		if( strUserID.equals(XMOPropertyDef.ROOT_USER) ) {
			return true;
		}

		// 権限チェックフラグ
		boolean isAuth = false;

		// 権限対象LOのリストを取得します。
		// XMSBaseを使用して、ログインユーザが使用できるLOリストを取得します。
		XMSBaseClient objBase = new XMSBaseClient();
		if( !objBase.searchRootLoList( strUserID ) ) {
			throw new LOException( objBase.getMessage() );
		}

		LoData[] objRootLo = objBase.getRootLoList();
		// 権限フィルタ用のIDリストを作成する。
		Vector vecAuthList = new Vector();
		for( int i = 0; i < objRootLo.length; i++ ) {
			vecAuthList.add( objRootLo[i].getLoID() );
		}

		// 指定LOIDのパスを取得します。
		// 参照LOIDのパスを取得する
		LoRelationClient objLoRelation = new LoRelationClient();
		if( !objLoRelation.searchPath(strLoID) ) {
			// パス検索がうまくいかなかった場合
			throw new LOException( objLoRelation.getMessage() );
		}

		// パス毎に権限チェックを行う。
		while( objLoRelation.next() ) {
			String[] strPath = objLoRelation.getPath();
			for( int i = 0; i < strPath.length; i++ ) {

				// 権限フィルターが設定されていた場合は権限によるチェックをします。
				if( vecAuthList.contains( strPath[i] ) ) {
					// 権限フィルターにIDが含まれていたら権限フラグをtrueにする
					isAuth = true;
					break;
				}

			}

			if( isAuth ) {
				break;
			}
		}

		return isAuth;
	}

}
