package org.itscool.weber.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.itscool.commons.bean.BeanFactory;
import org.itscool.commons.bean.BeanUtil;
import org.itscool.commons.bean.BeanUtilRuntimeException;
import org.itscool.commons.collection.InitParamMap;
import org.itscool.weber.action.*;
import org.itscool.commons.dao.EntityInfoMapping;
import org.itscool.commons.document.XmlConfigReader;
import org.itscool.commons.logging.AbstractLog;
import org.itscool.commons.logging.SimpleLog;
import org.itscool.commons.request.GeneralForm;
import org.itscool.commons.request.GeneralFormFactory;
import org.itscool.commons.request.UploadFile;
import org.itscool.commons.util.DateFormatUtil;
import org.itscool.weber.io.ActionConfigReader;
import org.itscool.weber.io.ExceptionConfigReader;
import org.itscool.weber.io.MessageConfigReader;
import org.itscool.weber.mapping.ActionMapping;
import org.itscool.weber.mapping.ActionMappings;
import org.itscool.weber.mapping.ExceptionMapping;
import org.itscool.weber.mapping.ExceptionMappings;
import org.itscool.weber.mapping.MessageMappings;
import org.itscool.weber.user.UserManager;

/**
 * FrontControllerパターンに基づくFrontServletクラスです<BR>
 * クライアントから発生したリクエストは、まずControllerの機能を請け負う
 * FrontServletが受け取ります。<br>
 * FrontServletはMVCモデルのCの役割を持つコンポーネントです。<BR>
 * このフレームワークでは、ひとつのアプリケーションで一つのFrontServlet
 * クラスが全てのリクエストを処理します。<BR>
 * FrontServletはこのフレームワークで使用される各コンポーネントを連携させ
 * アプリケーション全体の制御を行うコンポーネントですが、開発者は原則として
 * 直接扱う必要はありません。<BR>
 * <p>
 *【FrontServletと関連するクラス】<BR>
 * <table border="1" width="500">
 *     <tr><td>
 *     <font face="ＭＳ ゴシック" size="3">
 *     <br>
 *     　+--------+ (1)　+------------+　　　+----------+<br>
 *     　|　　　　|----->|　Front 　　| (2)　|　Action　|<br>
 *     　|　Web 　| (7)　|　Servlet 　|----->|　Mapping |<br>
 *     　|　　　　|<-----|　　　　　　|　　　|　　　　　|<br>
 *     　+--------+　　　+------------+　　　+----------+<br>
 *     　　　　　　　　　　　A 　|　|<br>
 *     　　　　　　　　　　　| 　|　|　　　　　　　　　　<br>
 *     　　　　　　　　　　　| 　|　|(3)+------------+<br>
 *     　　　　　　　　　　　| 　|　+-->|　　　　　　|<br>
 *     　　　　　　　　　　　| 　|　　　|　 Bean　 　|<---+   <br>
 *     　　　　　　　　　　　| 　|　　　|　　　　　　|　　|   <br>
 *     　　　　　　　　　　　| 　|　　　+------------+　　|   <br>
 *     　　　　　　　　　　　| 　|　　　　　　　　　　　　|(5)<br>
 *     　　　　　　　　　　　| 　| (4)　+------------+　　|   <br>
 *     　　　　　　　　　　　| 　+----->|　　　　　　|　　|   <br>
 *     　　　　　　　　　　　| 　　(6)　|　 Action 　|----+   <br>
 *     　　　　　　　　　　　+----------|　　　　　　|<br>
 *     　　　　　　　　　　　　　　　　 +------------+<br>
 *     </font>
 * <br>
 * </td></tr>
 * </table>
 * <p>
 *【処理の説明】<br>
 * <table border="1" width="500">
 *
 *     <tr>
 *         <td width="40" align="center">No</td><td>説明</td>
 *     </tr>
 *     <tr>
 *         <td align="center">1</td>
 *         <td>
 *         クライアントから発生したリクエストはFrontServletクラスが受け取ります
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">2</td>
 *         <td>
 *         FrontServletはクライアントから受け取ったリクエストURIを元にActionMapping
 *         を取得します<br>
 *         ActionMappingにはリクエストURIに関連するActionクラス名及びフォームBean名
 *         が登録されています
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">3</td>
 *         <td>
 *         FrontServletクラスはActionMappingクラスからBeanオブジェクトを生成し、
 *         クライアントからのリクエストパラメータをBeanオブジェクトにセットします
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">4</td>
 *         <td>
 *         FrontServletクラスはActionMappingクラスからActionを生成します。<br>
 *         次に生成したActionに対してexecuteメソッドを実行します。<BR>
 *         executeメソッドの引数には、フォームBeanの他にHttpServletReqeust
 *         インスタンスやHttpServletResponceインスタンスも含まれます
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">5</td>
 *         <td>
 *         ActionクラスはクライアントからのリクエストパラメータをBeanオブジェクト
 *         から取得します
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">6</td>
 *         <td>
 *         リクエストパラメータに従って、ビジネスロジックを処理します<br>
 *         Actionの実行結果をFrontServletに返却します<br>
 *         </td>
 *     </tr>
 *     <tr>
 *         <td align="center">7</td>
 *         <td>
 *         FrontServletはActionの実行結果からJSPページを作成し、
 *      クライアントに返却します
 *         </td>
 *     </tr>
 * </table>
 * <p>
 *
 * @author KANO
 * @since jdk1.4.1
 * @version 1.00A 2004/11/1
 * @version 1.10A 2004/12/11 Include機能を追加
 * @version 1.11A 2005/05/20 Include機能を削除（Stylistとの分離）
 * @version 1.20A 2005/05/29 FileUpload対応
 */
public class FrontServlet extends HttpServlet {
    protected AbstractLog log;
    protected ServletConfig config = null;

    /**
     * FrontServletの初期化処理
     * @see javax.servlet.GenericServlet#init()
     */
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        BeanFactory factory = BeanFactory.getInstance();
        if( !factory.isInit() ){
            try{
                factory.createForUrl("di-config.xml");
            }catch(Exception ex){
                ex.printStackTrace();
                throw new ServletException(ex.getMessage());
            }
        }
        
        try{
            if( factory.isDefined("Log") ){
                log = (AbstractLog)factory.getInstance("Log");
                if(!log.isInit()){
                    log = (AbstractLog)factory.createInstance("Log");
                }
            }else{
                log = SimpleLog.getInstance();
            }
        }catch(Exception ioe){
            throw new ServletException(ioe.getMessage());
        }
        
        initConfig(factory);
        
    }
    
    /**
     * サーブレットが初期化されるときに呼ばれます<br>
     * 初期データを設定します
     * @param factory di-config.xmlファイルから初期設定情報を取得するインスタンス
     */
    protected void initConfig(BeanFactory factory) throws ServletException{
        try{
            ActionMappings actionMappings = ActionMappings.getInstance();
            ExceptionMappings exception = ExceptionMappings.getInstance();
            MessageMappings messages = MessageMappings.getInstance();

            InitParamMap params = (InitParamMap)factory.createInstance("InitParams");
            //必須項目
            String weberConf=params.getParam("weber-config");
            if(weberConf==null){
                String msg = "no define \"weber-config\" path from diconfig.xml[InitParams]";
                log.error(msg);
                throw new IOException(msg);
            }
            //任意項目
            String msgConf=params.getParam("message-config");
            XmlConfigReader actionReader = new ActionConfigReader();
            actionReader.setConfigName(weberConf);
            actionReader.create(actionMappings);
            
            try{
                XmlConfigReader exceptionReader = new ExceptionConfigReader();
                exceptionReader.setConfigName(weberConf);
                exceptionReader.create(exception);
            }catch(Exception ioe){
                log.info("ExceptionConfigReaderは実行されません");
            }
            
            try{
                XmlConfigReader messageReader = new MessageConfigReader();
                messageReader.setConfigName(msgConf);
                messageReader.create(messages);
            }catch(Exception ioe){
                log.info("MessageConfigReaderは実行されません");
            }
            try{
                EntityInfoMapping daoMapping = (EntityInfoMapping)factory.createInstance("EntityInfoMapping");
            }catch(Exception ioe){
                log.info("DaoConfigReaderは実行されません");
            }
            try{
                UserManager roleManager = (UserManager)factory.createInstance("UserManager");
                roleManager.init();
            }catch(Exception ioe){
                log.info("WeberUserManagerは実行されません");
            }
            
        }catch(Exception e){
            String name1 = e.getClass().getName();
            String name2 = Exception.class.getName();
            StackTraceElement[] traceList = e.getStackTrace();
            log.error(getStackTrace(traceList));
            throw new ServletException(e.getMessage());
        }
    }
    
    /**
     * doGetを実装します
     * @see javax.servlet.http.HttpServlet#doGet(
     *         javax.servlet.http.HttpServletRequest,
     *         javax.servlet.http.HttpServletResponse)
     */
    public void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
    throws ServletException, IOException {
        execute(arg0, arg1);
    }
    
    /**
     * doPostを実装します
     * @see javax.servlet.http.HttpServlet#doPost(
     *         javax.servlet.http.HttpServletRequest,
     *         javax.servlet.http.HttpServletResponse)
     */
    public void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
    throws ServletException, IOException {
        execute(arg0, arg1);
    }
    
    /**
     * doGet()、doPost()メソッドの処理を実行するためのexecuteメソッドを呼びます<br>
     * execute実行後はメソッド戻り値にセットされたJSP名に遷移します。<BR>
     * システム例外が発生した場合はexceptionメソッドを呼び出します。
     * @param req Httpリクエストインスタンス
     * @param res Httpレスポンスインスタンス
     */
    private void execute(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        try {
            String jsp = invoke(req, res);
            if(jsp.equals(Globals.RET_NOFORWARD)){
                return;
            }
            //==========================================================================================
            //jspを返信
            //==========================================================================================
            //** servletの初期化をinit()で行う場合はこちら
            //ServletContext sc = this.getServletContext();
            //RequestDispatcher rd = sc.getRequestDispatcher(jsp);
            //rd.forward(req, res);
            //** servletの初期化をinit(ServletConfig config)で行う場合はこちら
            try{
                RequestDispatcher rd = req.getRequestDispatcher(jsp);
                rd.forward(req, res);
            }catch(IOException e){
                String msg = jsp + "に指定されたコンテンツの呼出でエラーが発生しました\n" + e.getMessage();
                throw new IOException(msg);
            }
        } catch (IOException e) {
            String name1 = e.getClass().getName();
            String name2 = IOException.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw e;
            }
        } catch (ServletException e) {
            String name1 = e.getClass().getName();
            String name2 = ServletException.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw e;
            }
        } catch (NullPointerException e) {
            String name1 = e.getClass().getName();
            String name2 = NullPointerException.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw e;
            }
        } catch (RuntimeException e) {
            String name1 = e.getClass().getName();
            String name2 = RuntimeException.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw e;
            }
        } catch (Exception e) {
            String name1 = e.getClass().getName();
            String name2 = Exception.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw new ServletException(e.getMessage());
            }
        } catch (Error e){
            String name1 = e.getClass().getName();
            String name2 = Exception.class.getName();
            if (!exception(req, res, name1, name2, e)) {
                throw new ServletException(e.getMessage());
            }
        }
    }
    
    /**
     * 業務処理を呼び出します
     * @param req HttpServletRequestインスタンス
     * @param res HttpServletResponseインスタンス
     * @return 実行結果を表示する画面URLを返します
     */
    protected String invoke(HttpServletRequest req, HttpServletResponse res)
    throws Exception{
        String jsp = process(req, res);
        return jsp;
    }
    
    /**
     * doGet()、doPost()メソッドの処理を実行します                          <BR>
     * FrontServletクラスは、受け取ったリクエストパスから指定のアクションと
     * フォームBeanインスタンスを生成します。                               <BR>
     * リクエストパスとアクション及びフォームBeanとの括り付けは
     * /WEB-INF/itscool-config.xmlの<action-mappings>要素で定義します。     <BR>
     *
     *                                                                      <P>
     * 【定義ファイルの記述例】                                             <BR>
     * <font size="2">                                                      <BR>
     * &lt;action-mappings&gt;                                              <BR>
     * 　&lt;!-- ログインアクション --&gt;                                  <BR>
     * 　&lt;action                                                         <BR>
     * 　　&lt;-- ログイン実行時のリクエストパスを指定します。 --&gt;       <BR>
     * 　　path="/login.do"                                                 <BR>
     * 　　&lt;-- リクエストに対応するアクションクラスを設定 --&gt;         <BR>
     * 　　type="org.itscoolSample.action.LoginAction"&gt;                  <BR>
     * 　　&lt;-- フォームにセットされるパラメータをチェック                <BR>
     * 　　　　　するクラスを設定 ---&gt;                                   <BR>
     * 　　&lt;-- フォワードの遷移先を設定 --&gt;                           <BR>
     * 　　&lt;forward name="success" path="/input.jsp"/&gt;                <BR>
     * 　　&lt;forward name="fail" path="/fail.jsp"/&gt;                    <BR>
     * 　　&lt;/action&gt;                                                  <BR>
     *                                                                      <BR>
     * 　　&lt;-- 帳票入力アクション --&gt;                                 <BR>
     * 　　&lt;action                                                       <BR>
     * 　　　　path="/input.do"                                             <BR>
     * 　　　　type="org.itscoolSample.action.InputAction" &gt;             <BR>
     * 　　　　&lt;forward name="success" path="/confirm.jsp"/&gt;          <BR>
     * 　　　　&lt;forward name="fail" path="/fail.jsp"/&gt;                <BR>
     * 　　&lt;/action&gt;                                                  <BR>
     * &lt;/action-mappings&gt;                                             <BR>
     * </font>                                                              <BR>
     *                                                                      <BR>
     *
     * @param req Httpリクエストインスタンス
     * @param res Httpレスポンスインスタンス
     * @return 処理後の遷移先JSP名を返します
     * @throws Exception proecess処理に失敗すると例外Exceptionをスローします。
     */
    protected String process( HttpServletRequest req, HttpServletResponse res )
    throws Exception{
        String ret = Globals.RET_SUCCESS;
        String jsp = null;
        String encode = getEncoding();
        
        //==========================================================================================
        //ファイル転送か通常のPOSTか判定
        //ファイル転送の場合はデフォルトのMultipartPostItemsインスタンスを返却
        //通常のPOSTならSimplePostRequestを返却
        //==========================================================================================
        GeneralFormFactory factory = GeneralFormFactory.getInstance();
        GeneralForm hgForm = factory.create(req, encode);
        
        String path = req.getServletPath();
//add 2005/11/10 kano start
        //pathInfoは単体テスト用に使用
        String pathInfo = req.getPathInfo();
        if(pathInfo != null){
            path = pathInfo;
        }
//add 2005/11/10 kano end
        
        log.trace("---------- servlet infomation!!! --------------- ");
        log.trace("[ServerName]" + req.getServerName() );
        log.trace("[ContextPath]" + req.getContextPath());
        log.trace("[ServletPath]" + req.getServletPath());
        log.trace("[PathInfo]" + req.getPathInfo());
        log.trace("[QueryString]" + req.getQueryString());
        log.trace("[RequestURI]" + req.getRequestURI());
        log.trace("[RequestURL]" + req.getRequestURL());
        
        //input.doやsave.doのパス名からActionを取得
        Action action = getAction(req, path);
        if (action == null) {
            String err = "[" + path + "]" + "Can not found action ("
                + FrontServlet.class.getName() + ")";
            throw new ServletException(err);
        }
        
        //======================================================================================
        //ユーザ情報を取得する
        //======================================================================================
        HashMap roles = getRoles(path);
        
        //=========================
        //execute()引数ラップクラスを生成
        //=========================
        ActionBucketImpl bucket = new ActionBucketImpl();
        bucket.setServlet(this);
        bucket.setRequest(req);
        bucket.setResponse(res);
//        bucket.setForm(bean);
        bucket.setRoles(roles);
        
        //======================================================================================
        //ビジネスロジックの初期化と前処理
        //======================================================================================
        action.init(bucket, hgForm);
        ret = action.beforeExecute();
        //入力チェックにて入力エラー時はエラー情報をセットしてエラー画面に遷移
        if( !ret.equals(Globals.RET_SUCCESS) ){
            //入力チェックにて遷移無しを受けたときはdoExecuteを実行せずに処理終了
            if(ret.equals(Globals.RET_NOFORWARD )){
                return ret;
            }
            jsp= getForward(action, ret, path);
//            jsp = action.getForward(ret);
            if (jsp == null) {
                String err = "["  + "ACTION:" + action.getClass().getName()
                    + "NAME:" + ret  + "]" + "Can not found forward ("
                    + FrontServlet.class.getName() + ")";
                throw new ServletException(err);
            }
            return jsp;
        }
        
        //======================================================================================
        //リクエストパラメータのセット
        //======================================================================================
        Object bean = getForm(path);
        String bean_maped_kind = (String)hgForm.getParameter("bean_maped_kind");
        if (bean == null) {
//modify 2006/01/19 kano start
            //GereralForm対応(澤村さんプレゼンツ)
            bean = (GeneralForm)hgForm;
//modify 2006/01/19 kano end
            //フォームBeanが存在する場合はBeanオブジェクトにパラメータをセット
        }else if( bean_maped_kind == null || bean_maped_kind.length() == 0 ||
        bean_maped_kind.equals("bean")){
            setRequestParam(bean, hgForm);
        }else if( bean_maped_kind.equals("list")){
            //同一の名前を持つ複数のリクエストパラメータからオブジェクトのリストにマッピング
            bean = setRequestParameBeanToList(bean, hgForm);
        }else if( bean_maped_kind.equals("array")){
            //同一の名前を持つ複数のリクエストパラメータからオブジェクトの配列にマッピング
            bean = setRequestParameBeanToArray(bean, hgForm);
        }
        action.setForm(bean);
        
        //======================================================================================
        //ビジネスロジックの実行
        //======================================================================================
        ret = action.execute();
        
        //実行結果が「画面遷移無し」の場合
        if(ret != null && ret.equals(Globals.RET_NOFORWARD)){
            return Globals.RET_NOFORWARD;
        }
        jsp = getForward(action, ret, path);
        return jsp;
    }
    
    /**
     * 文字エンコード情報を取得します
     * @return 文字エンコーディング
     */
    protected String getEncoding() {
        //==========================================================================================
        //文字エンコーディング
        //==========================================================================================
        BeanFactory factory = BeanFactory.getInstance();
        InitParamMap params = (InitParamMap)factory.getInstance("InitParams");
//        InitParamMap params = InitParamMap.getInstance();
//        InitParamMap info = InitParamMap.getInstance();
        String encode = (String) params.getParam("encoding");
        return encode;
    }

    /**
     * 業務処理実行後の遷移先URLを取得します
     * @param action Actionインスタンス
     * @param ret Actionの実行結果
     * @param path リクエストパス情報
     */
    protected String getForward(Action action, String ret, String path) throws ServletException {
        String jsp;
        jsp = action.getForward(ret);
        if (jsp == null) {
            String err =  "[ACTION:" + action.getClass().getName()
                + "NAME:" + ret + "] Can not found forward ("
                + FrontServlet.class.getName() + ")";
            throw new ServletException(err);
        }
        return jsp;
    }
    
    /**
     * スタックトレースを文字列に変換します
     * @param traceList スタックトレース
     * return 文字列に変換されたスタックトレース
     */
    protected String getStackTrace(StackTraceElement[] traceList){
        String LINE = System.getProperty("line.separator");
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < traceList.length; i++) {
            StackTraceElement trace = traceList[i];
            sb.append(trace.toString()).append(LINE);
        }
        return sb.toString();
    }
    
    /**
     * 例外を出力します<BR
     * 例外は発生元のクラスでキャッチして呼出もとのクラスにthrowする
     * ことにより、例外のトレースを追跡する事ができます<BR>
     * 例外のトレースはJDK1.4で導入されたException.getStackTrace()
     * メソッドを使って例外をトレースしています
     * @param e Exceptionインスタンス
     * @return エラーページに遷移する場合はtrueを返します
     */
    protected boolean exception(
        HttpServletRequest req,
        HttpServletResponse res,
        String exceptionName1,
        String exceptionName2,
        Exception e)
        throws IOException, ServletException {
        String msg = e.getMessage();
        if( msg == null ){
            msg =e.getClass().getName();
        }
        log.error(msg);
        StackTraceElement[] traceList = e.getStackTrace();
        log.error(getStackTrace(traceList));
        
        //---------------------
        //エラーページの遷移判定
        //---------------------
        String jsp = getExceptionPage(e);
        if (jsp != null) {
//            req.setAttribute(Globals.REQ_PARAM_SYSTEM_ERR_MSG, msg);
//            req.setAttribute(Globals.REQ_PARAM_SYSTEM_ERR, traceList);
//            //getServletContext().getRequestDispatcher(path).forward(req, res);
//            RequestDispatcher rd = req.getRequestDispatcher(jsp);
//            rd.forward(req, res);
            responseException(jsp, traceList, req, res, msg);
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 例外を出力します<BR
     * 例外は発生元のクラスでキャッチして呼出もとのクラスにthrowする
     * ことにより、例外のトレースを追跡する事ができます<BR>
     * 例外のトレースはJDK1.4で導入されたException.getStackTrace()
     * メソッドを使って例外をトレースしています
     * @param e Exceptionインスタンス
     * @return エラーページに遷移する場合はtrueを返します
     */
    protected boolean exception(
        HttpServletRequest req,
        HttpServletResponse res,
        String exceptionName1,
        String exceptionName2,
        Error e)
        throws IOException, ServletException {
        String msg = e.getMessage();
        if( msg == null ){
            msg =e.getClass().getName();
        }
        log.error(msg);
        StackTraceElement[] traceList = e.getStackTrace();
        log.error(getStackTrace(traceList));
//        for (int i = 0; i < traceList.length; i++) {
//            StackTraceElement trace = traceList[i];
//            log.error(trace.toString());
//        }
        
        //---------------------
        //エラーページの遷移判定
        //---------------------
        String jsp = getExceptionPage(e);
        if (jsp != null) {
            responseException(jsp, traceList, req, res, msg);
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * エラーページ出力処理
     */
    protected void responseException(String jsp, StackTraceElement[] traceList, 
        HttpServletRequest req, HttpServletResponse res, String msg) throws IOException, ServletException {
        req.setAttribute(Globals.REQ_PARAM_SYSTEM_ERR_MSG, msg);
        req.setAttribute(Globals.REQ_PARAM_SYSTEM_ERR, traceList);
        //getServletContext().getRequestDispatcher(path).forward(req, res);
        RequestDispatcher rd = req.getRequestDispatcher(jsp);
        rd.forward(req, res);
    }
    
    /**
     * 例外発生時の遷移先URLを取得します
     * @param e Exception/Errorインスタンス
     * @return 例外発生時の遷移先URL
     */
    protected String getExceptionPage(Object e){
        ExceptionMappings mapping = ExceptionMappings.getInstance();
        ExceptionMapping exception = null;
        if(e instanceof Exception){
            exception = mapping.get((Exception)e);
        }else{
            exception = mapping.get((Error)e);
        }
        if( exception == null) return null;
        return exception.getPath();
    }
    
    /**
     * リクエストパスからActionインスタンスを取得します。
     * @param path リクエストパスを指定します
     * @return 生成されたActionインスタンス
     */
    public Action getAction(HttpServletRequest req, String path)
    throws IOException {
        ActionMappings mappings = ActionMappings.getInstance();
        ActionMapping mapping = (ActionMapping) mappings.get(path);
        
        if (mapping == null) {
            String err = "Not found action for path(" + path + ")";
            throw new IOException(err);
        }
        
        Action action = (Action) BeanUtil.createInstance(mapping.getType());
        
        if( log.getLevel().equals(SimpleLog.TRACE) ){
            HashMap roles = mapping.getRoles();
            StringBuffer roleNames = new StringBuffer();
            if( roles != null ){
                Set keySet = roles.keySet();
                Iterator it = keySet.iterator();
                while(it.hasNext()){
                    Object key = it.next();
                    roleNames.append(roles.get(key).toString());
                    if(it.hasNext()){
                        roleNames.append(", ");
                    }
                }
            }else{
                roleNames.append("null");
            }
            log.trace("---------- request recieved!!!!! --------------- ");
            log.trace("PATH   : " + mapping.getPath());
            log.trace("ACTION : " + mapping.getType());
            log.trace("FORM   : " + mapping.getName());
            log.trace("ROLE   : " + roleNames.toString());
        }
        action.setForwards(mapping.getForwards());
        action.setValidates(mapping.getValidates());
        return action;
    }
    
    /**
     * リクエストパスからFormBeanインスタンスを取得します。
     * @param path リクエストパスを指定します
     * @return 生成されたFormBeanインスタンス
     */
    public Object getForm(String path) throws IOException{
        ActionMappings mappings = ActionMappings.getInstance();
        ActionMapping mapping = (ActionMapping) mappings.get(path);
        String beanName = mapping.getName();
        
        if (beanName == null)
            return null;
        Object bean = (Object) BeanUtil.createInstance(beanName);
        //setRequestParam(req, bean);
        
        return bean;
    }
    
    /**
     * 同一の名前を持つ複数のリクエストパラメータからオブジェクトの配列にマッピング
     * します。
     * @param bean セット対象となるオブジェクトを渡します（メソッド実行後は、パラメータが
     * セットされたオブジェクトが返されます）
     * @param gForm HttpServletRequestのパラメータセット
     * @return オブジェクトの配列を返します
     */
    public Object[] setRequestParameBeanToArray(Object bean, GeneralForm gForm) throws IOException{
        List beanList = setRequestParameBeanToList(bean, gForm);
        return beanList.toArray();
    }
    
    /**
     * 同一の名前を持つ複数のリクエストパラメータからオブジェクトのリストにマッピング
     * します。
     * @param bean セット対象となるオブジェクトを渡します（メソッド実行後は、パラメータが
     * セットされたオブジェクトが返されます）
     * @param gForm HttpServletRequestのパラメータセット
     * @return オブジェクトのリストを返します
     */
    public List setRequestParameBeanToList(Object bean, GeneralForm gForm) throws IOException{
        List beanList = new ArrayList();
        String clazzName = bean.getClass().getName();
        Set keySet = gForm.keySet();
        Iterator it = keySet.iterator();
//        int beanNum = 0;
        boolean isCreateNewBeanFlg = false;
        while( it.hasNext() ){
            String paramName = (String)it.next();
            Object paramValues = gForm.getParameter(paramName);
            if( paramValues instanceof List){
                List list = (List)paramValues;
                int beanNum = list.size();
                for( int i=0; i<beanNum; i++){
                    Object beanElement = null;
                    if( !isCreateNewBeanFlg ){
                        beanElement = BeanUtil.createInstance(clazzName);
                        beanList.add(beanElement);
                    }else{
                        if( i >= beanList.size() ){
                            continue;
                        }
                        beanElement = beanList.get(i);
                    }
                    Object paramValue = list.get(i);
                    //パラメータの型を取得
                    Class clazz = BeanUtil.getReturnType(bean, paramName);
                    try{
                        if(Date.class.isAssignableFrom(clazz) && paramValue instanceof String){
                            Date date = DateFormatUtil.parse(paramValue.toString());
                            if( date != null){
                                BeanUtil.setProperty(beanElement, paramName, date);
                            }
                        }else{
                            BeanUtil.setProperty(beanElement, paramName, paramValue );
                        }
                    }catch(BeanUtilRuntimeException e){}
                }
                isCreateNewBeanFlg = true;
            }
        }
        
//add 2007/05/15 kano start
        //配列要素が無い場合は単一のオブジェクトを配列にセット
        if( !isCreateNewBeanFlg && beanList.size() == 0){
            setRequestParam(bean, gForm);
            beanList.add(bean);
        }
//add 2007/05/15 kano end
        
        return beanList;
    }
    
    /**
     * リクエストパラメータを取得しオブジェクトBeanにパラメータをセットします
     * @param bean セット対象となるオブジェクトを渡します（メソッド実行後は、パラメータが
     * セットされたオブジェクトが返されます）
     * @param gForm HttpServletRequestのパラメータセット
     */
    public void setRequestParam(Object bean, GeneralForm gForm) throws IOException{
        Set keySet = gForm.keySet();
        Iterator it = keySet.iterator();
        
        if( it.hasNext() ){
            log.trace("---------- request parameter!!!! --------------- ");
        }
        
        while( it.hasNext() ){
            String paramName = (String)it.next();
            Object paramValue = gForm.getParameter(paramName);
            try {
                //パラメータの型を取得
                Class clazz = BeanUtil.getReturnType(bean, paramName);
                //複数チェックボックス対応
                //複数チェックボックス指定において、単一のデータしか選択
                //しなかった場合の対応
                if(List.class.isAssignableFrom(clazz)
                && !List.class.isAssignableFrom(paramValue.getClass())){
                    ArrayList list = new ArrayList();
                    list.add(paramValue);
                    
//                    log.info("パラメータ名["+paramName+"] このパラメータは複数存在するためListインターフェースでセットされます");
                    
                    BeanUtil.setProperty(bean, paramName, list);
                    
                }else if(Date.class.isAssignableFrom(clazz) && paramValue instanceof String){
                    Date date = DateFormatUtil.parse(paramValue.toString());
                    if( date != null){
                        BeanUtil.setProperty(bean, paramName, date);
                    }
                    
                }else if(paramValue instanceof String || paramValue instanceof UploadFile
                    || paramValue instanceof List){
                    
                    //アップロードされたファイルはUploadFileでセットされる
                    //ので受信側のBeanにはUploadFile型変数と対応するアクセッサメソッド
                    //が必要！
                    BeanUtil.setProperty(bean, paramName, paramValue);
                }else{
                    throw new ClassCastException(paramName + " is not match ["
                        + clazz.getName() + "] but was [" + paramValue.getClass().getName() + "]");
                }
                log.trace(paramName + " = " + paramValue);
            } catch (BeanUtilRuntimeException e) {
                //submitの名前(NAME)属性など、Beanに関係しないパラメータ
                //は無視する
//                log.info("パラメータ名["+paramName+"] このパラメータはフォームBeanのメンバに存在しないので無視されます");
            }
            
        }
    }
    
    /**
     * リクエストURIに指定された権限情報を取得します<BR>
     * 権限情報が定義されていないばあはNULLを返します
     * @param path リクエストされたURI情報
     * @return HashMap このアクションを許可する権限リストを返します
     */
    public HashMap getRoles(String path) {
        ActionMappings actionMappings = ActionMappings.getInstance();
        ActionMapping actionMapping = (ActionMapping) actionMappings.get(path);
        
        if (actionMapping.getRoles() == null) {
            return null;
        }
        HashMap roles = actionMapping.getRoles();
        return roles;
    }

    public ServletConfig getServletConfig() {
        return config;
    }
}
