/*
 * $Id: Shell.java,v 1.5 2005/04/05 15:39:22 rampil Exp $
 * Copyright (c) 2004 LOGICAL-PARADOX.ORG
 */
package org.logical_paradox.shell;

import java.io.OutputStream;
import java.util.ResourceBundle;

import org.logical_paradox.shell.exception.*;
import org.logical_paradox.shell.exception.TerminationException;

/**
 * 抽象シェルクラス
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.5 $
 */
public abstract class Shell {
	private CommandLineParser parser;
	private ShellEnv env;

	/**
	 * コンストラクタ
	 * @throws Exception インスタンスの初期化処理中に発生した例外
	 */
	public Shell() throws Exception {
		setup();
	}
	/**
	 * インスタンスの初期化処理
	 * @throws Exception 初期化に失敗した場合の例外
	 */
	protected void setup() throws Exception {
		// シェルリソースのロード
		ResourceBundle rb = ResourceBundle.getBundle("shell");
		// シェル環境変数の作成
		env = new ShellEnv(rb);
		parser = createCommandLineParser(env);
	}
	/**
	 * コマンドラインパーザーを生成する
	 * このメソッドは具象クラスで実装する
	 * @param se シェル環境変数
	 * @return 生成されたパーザー
	 * @throws Exception パーザーの生成に失敗した場合に発生する例外
	 */
	protected abstract CommandLineParser createCommandLineParser(ShellEnv se) throws Exception;

	/**
	 * 環境変数クラスを返す
	 * @return 環境変数クラス
	 */
	public ShellEnv getEnv() {
		return env;
	}
	/**
	 * 画面初期化時に実行されるメソッド
	 * @param ostream 出力ストリーム
	 */
	public void onInitDisplay(OutputStream ostream) {
	}
	/**
	 * コマンド行を実行する
	 * @param ostream 出力ストリーム
	 * @param script コマンド行の内容
	 * @return 結果ステータス
	 * @throws CommandExecutionException コマンドの実行中に発生した例外
	 * @throws ParserException コマンド行の解析に失敗した場合に発生する例外
	 * @throws TerminationException 終了シグナルが送信された場合の例外
	 */
	public int execute(OutputStream ostream, String script) throws CommandExecutionException, ParserException, TerminationException {
		// 事前処理
		int rc = preExecution(ostream, script);
		if(rc != ResultCode.STATUS_OK) {
			return rc;
		}
		try {
			CommandLineParameters param = parser.parse(script);
			ResultCode exitCode = param.getCommand().execute(ostream, env, param.getArgument());
			return exitCode.getStatus();
		} finally {
			// 事後処理
			int postResultCode = postExecution(ostream, script);
			if(postResultCode != ResultCode.STATUS_OK) {
				return postResultCode;
			}
		}
	}
	/**
	 * コマンド行実行前に呼び出される処理
	 * コマンド実行前に何か処理したい場合、このメソッドをオーバーライドして実装する
	 * @param ostream 出力ストリーム
	 * @param script コマンド行の内容
	 * @return 結果ステータス
	 * @throws CommandExecutionException コマンドの実行中に発生した例外
	 * @throws TerminationException 終了シグナルが送信された場合の例外
	 */
	protected int preExecution(OutputStream ostream, String script) throws CommandExecutionException, TerminationException {
		return ResultCode.STATUS_OK;
	}
	/**
	 * コマンド行実行後に呼び出される処理
	 * コマンド実行後に何か処理したい場合、このメソッドをオーバーライドして実装する
	 * @param ostream 出力ストリーム
	 * @param script コマンド行の内容
	 * @return 結果ステータス
	 * @throws CommandExecutionException コマンドの実行中に発生した例外
	 * @throws TerminationException 終了シグナルが送信された場合の例外
	 */
	protected int postExecution(OutputStream ostream, String script) throws CommandExecutionException, TerminationException {
		return ResultCode.STATUS_OK;
	}
}
