OSDN Git Service

Add Ethna_Plugin_Abstract for all plugins abstract
[ethna/ethna.git] / class / Ethna_Controller.php
index af8cb71..f844092 100644 (file)
@@ -11,7 +11,9 @@
 
 // {{{ Ethna_Controller
 /**
- *  ¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹
+ *  コントローラクラス
+ *
+ *  @todo       gatewayでswitchしてるところがダサダサ
  *
  *  @author     Masaki Fujimoto <fujimoto@php.net>
  *  @access     public
@@ -23,22 +25,29 @@ class Ethna_Controller
      *  @access private
      */
 
-    /** @var    string      ¥¢¥×¥ê¥±¡¼¥·¥ç¥óID */
+    /** @var    string      アプリケーションID */
     var $appid = 'ETHNA';
 
-    /** @var    string      ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹¥Ç¥£¥ì¥¯¥È¥ê */
+    /** @var    string      アプリケーションベースディレクトリ */
     var $base = '';
 
-    /** @var    string      ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹URL */
+    /** @var    string      ã\82¢ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³ã\83\99ã\83¼ã\82¹URL */
     var $url = '';
 
-    /** @var    string      ¥¢¥×¥ê¥±¡¼¥·¥ç¥óDSN(Data Source Name) */
+    /** @var    string      アプリケーションDSN(Data Source Name) */
     var $dsn;
 
-    /** @var    array       ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê */
-    var $directory = array(
+    /** @var    array       アプリケーションディレクトリ */
+    var $directory = array();
+
+    /** @var    array       アプリケーションディレクトリ(デフォルト) */
+    var $directory_default = array(
         'action'        => 'app/action',
+        'action_cli'    => 'app/action_cli',
+        'action_xmlrpc' => 'app/action_xmlrpc',
         'app'           => 'app',
+        'plugin'        => 'app/plugin',
+        'bin'           => 'bin',
         'etc'           => 'etc',
         'filter'        => 'app/filter',
         'locale'        => 'locale',
@@ -48,21 +57,26 @@ class Ethna_Controller
         'template_c'    => 'tmp',
         'tmp'           => 'tmp',
         'view'          => 'app/view',
+        'www'           => 'www',
+        'test'          => 'app/test',
     );
 
-    /** @var    array       DB¥¢¥¯¥»¥¹ÄêµÁ */
+    /** @var    array       DBアクセス定義 */
     var $db = array(
         ''              => DB_TYPE_RW,
     );
 
-    /** @var    array       ³ÈÄ¥»ÒÀßÄê */
+    /** @var    array       拡張子設定 */
     var $ext = array(
         'php'           => 'php',
         'tpl'           => 'tpl',
     );
 
-    /** @var    array       ¥¯¥é¥¹ÀßÄê */
-    var $class = array(
+    /** @var    array       クラス設定 */
+    var $class = array();
+
+    /** @var    array       クラス設定(デフォルト) */
+    var $class_default = array(
         'class'         => 'Ethna_ClassFactory',
         'backend'       => 'Ethna_Backend',
         'config'        => 'Ethna_Config',
@@ -71,96 +85,131 @@ class Ethna_Controller
         'form'          => 'Ethna_ActionForm',
         'i18n'          => 'Ethna_I18N',
         'logger'        => 'Ethna_Logger',
+        'plugin'        => 'Ethna_Plugin',
+        'renderer'      => 'Ethna_Renderer_Smarty',
         'session'       => 'Ethna_Session',
         'sql'           => 'Ethna_AppSQL',
         'view'          => 'Ethna_ViewClass',
+        'url_handler'   => 'Ethna_UrlHandler',
     );
 
-    /** @var    array       ¥Õ¥£¥ë¥¿ÀßÄê */
+    /** @var    array       フィルタ設定 */
     var $filter = array(
     );
 
-    /** @var    string      »ÈÍѸÀ¸ìÀßÄê */
-    var $language;
+    /** @var    string      使用ロケール設定 */
+    var $locale;
 
-    /** @var    string      ¥·¥¹¥Æ¥à¦¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° */
+    /** @var    string      ã\82·ã\82¹ã\83\86ã\83 å\81´ã\82¨ã\83³ã\82³ã\83¼ã\83\87ã\82£ã\83³ã\82° */
     var $system_encoding;
 
-    /** @var    string      ¥¯¥é¥¤¥¢¥ó¥È¦¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° */
+    /** @var    string      クライアント側エンコーディング */
+    /**                     ブラウザからのエンコーディングを指す  */
     var $client_encoding;
 
-    /** @var    string  ¸½ºß¼Â¹ÔÃæ¤Î¥¢¥¯¥·¥ç¥ó̾ */
+    /** @var    string  現在実行中のアクション名 */
     var $action_name;
 
-    /** @var    array   forwardÄêµÁ */
-    var $forward = array();
+    /** @var    string  現在実行中のXMLRPCメソッド名 */
+    var $xmlrpc_method_name;
 
-    /** @var    array   actionÄêµÁ */
-    var $action = array();
+    /** @var    array   forward定義 */
+    var $forward = array();
 
-    /** @var    array   ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ãÄêµÁ */
-    var $manager = array();
+    /** @var    array   デフォルトのforward定義 */
+    var $forward_default = array(
+        '403' => array( 'view_name' => 'Ethna_View_403',),
+        '404' => array( 'view_name' => 'Ethna_View_404',),
+        '500' => array( 'view_name' => 'Ethna_View_500',), 
+        'json' => array( 'view_name' => 'Ethna_View_Json',),
+        'redirect' => array( 'view_name' => 'Ethna_View_Redirect',),
+    );
 
-    /** @var    array   smarty modifierÄêµÁ */
-    var $smarty_modifier_plugin = array();
+    /** @var    array   action定義 */
+    var $action = array();
 
-    /** @var    array   smarty functionÄêµÁ */
-    var $smarty_function_plugin = array();
+    /** @var    array   action(CLI)定義 */
+    var $action_cli = array();
 
-    /** @var    array   smarty prefilterÄêµÁ */
-    var $smarty_prefilter_plugin = array();
+    /** @var    array   action(XMLRPC)定義 */
+    var $action_xmlrpc = array();
 
-    /** @var    array   smarty postfilterÄêµÁ */
-    var $smarty_postfilter_plugin = array();
+    /** @var    array   アプリケーションマネージャ定義 */
+    var $manager = array();
 
-    /** @var    array   smarty outputfilterÄêµÁ */
-    var $smarty_outputfilter_plugin = array();
+    /** @var    object  レンダラー */
+    var $renderer = null;
 
-    /** @var    array   ¥Õ¥£¥ë¥¿¡¼¥Á¥§¥¤¥ó(Ethna_Filter¥ª¥Ö¥¸¥§¥¯¥È¤ÎÇÛÎó) */
+    /** @var    array   フィルターチェイン(Ethna_Filterオブジェクトの配列) */
     var $filter_chain = array();
 
-    /** @var    object  Ethna_ClassFactory  ¥¯¥é¥¹¥Õ¥¡¥¯¥È¥ê¥ª¥Ö¥¸¥§¥¯¥È */
+    /** @var    object  Ethna_ClassFactory  クラスファクトリオブジェクト */
     var $class_factory = null;
 
-    /** @var    object  Ethna_ActionForm    ¥Õ¥©¡¼¥à¥ª¥Ö¥¸¥§¥¯¥È */
+    /** @var    object  Ethna_ActionForm    フォームオブジェクト */
     var $action_form = null;
 
-    /** @var    object  Ethna_Config        ÀßÄꥪ¥Ö¥¸¥§¥¯¥È */
+    /** @var    object  Ethna_View          ビューオブジェクト */
+    var $view = null;
+
+    /** @var    object  Ethna_Config        設定オブジェクト */
     var $config = null;
 
-    /** @var    object  Ethna_Logger        ¥í¥°¥ª¥Ö¥¸¥§¥¯¥È */
+    /** @var    object  Ethna_Logger        ログオブジェクト */
     var $logger = null;
 
-    /** @var    string  ¥ê¥¯¥¨¥¹¥È¤Î¥²¡¼¥È¥¦¥§¥¤(www/cli/rest/xmlrpc/soap...) */
+    /** @var    object  Ethna_Plugin        プラグインオブジェクト */
+    var $plugin = null;
+
+    /** @var    string  リクエストのゲートウェイ(www/cli/rest/xmlrpc/soap...) */
     var $gateway = GATEWAY_WWW;
 
     /**#@-*/
 
 
     /**
-     *  Ethna_Controller¥¯¥é¥¹¤Î¥³¥ó¥¹¥È¥é¥¯¥¿
+     *  Ethna_Controllerã\82¯ã\83©ã\82¹ã\81®ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
      *
      *  @access     public
      */
-    function Ethna_Controller()
+    function Ethna_Controller($gateway = GATEWAY_WWW)
     {
         $GLOBALS['_Ethna_controller'] =& $this;
-        if ($this->base == "") {
-            $this->base = BASE;
+        if ($this->base === "") {
+            // EthnaコマンドなどでBASEが定義されていない場合がある
+            if (defined('BASE')) {
+                $this->base = BASE;
+            }
+        }
+
+        $this->gateway = $gateway;
+
+        // クラス設定の未定義値を補完
+        foreach ($this->class_default as $key => $val) {
+            if (isset($this->class[$key]) == false) {
+                $this->class[$key] = $val;
+            }
         }
 
-        // ¥¯¥é¥¹¥Õ¥¡¥¯¥È¥ê¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®
+        // ディレクトリ設定の未定義値を補完
+        foreach ($this->directory_default as $key => $val) {
+            if (isset($this->directory[$key]) == false) {
+                $this->directory[$key] = $val;
+            }
+        }
+
+        // クラスファクトリオブジェクトの生成
         $class_factory = $this->class['class'];
         $this->class_factory =& new $class_factory($this, $this->class);
 
-        // ¥¨¥é¡¼¥Ï¥ó¥É¥é¤ÎÀßÄê
+        // エラーハンドラの設定
         Ethna::setErrorCallback(array(&$this, 'handleError'));
 
-        // ¥Ç¥£¥ì¥¯¥È¥ê̾¤ÎÀßÄê(ÁêÂХѥ¹->ÀäÂХѥ¹)
+        // ã\83\87ã\82£ã\83¬ã\82¯ã\83\88ã\83ªå\90\8dã\81®è¨­å®\9a\9b¸å¯¾ã\83\91ã\82¹->絶対ã\83\91ã\82¹)
         foreach ($this->directory as $key => $value) {
             if ($key == 'plugins') {
-                // Smarty¥×¥é¥°¥¤¥ó¥Ç¥£¥ì¥¯¥È¥ê¤ÏÇÛÎó¤Ç»ØÄꤹ¤ë
-                $tmp = array(SMARTY_DIR . 'plugins');
+                // Smartyプラグインディレクトリは配列で指定する
+                $tmp = array();
                 foreach (to_array($value) as $elt) {
                     if (Ethna_Util::isAbsolute($elt) == false) {
                         $tmp[] = $this->base . (empty($this->base) ? '' : '/') . $elt;
@@ -174,26 +223,60 @@ class Ethna_Controller
             }
         }
 
-        // ½é´üÀßÄê
-        list($this->language, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
+        // 遷移先設定をマージ
+        // 但し、キーは完全に維持する
+        $this->forward = $this->forward + $this->forward_default;
 
+        // 初期設定
+        // フレームワークとしての内部エンコーディングはクライアント
+        // エンコーディング(=ブラウザからのエンコーディング)
+        //
+        // @see Ethna_Controller#_getDefaultLanguage
+        list($this->locale, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
+        if (mb_enabled()) {
+            mb_internal_encoding($this->client_encoding);
+            mb_regex_encoding($this->client_encoding);
+        }
         $this->config =& $this->getConfig();
         $this->dsn = $this->_prepareDSN();
         $this->url = $this->config->get('url');
 
-        // ¥í¥°½ÐÎϳ«»Ï
+        // プラグインオブジェクトの用意
+        $this->plugin =& $this->getPlugin();
+
+        //// assert (experimental)
+        //if ($this->config->get('debug') === false) {
+        //    ini_set('assert.active', 0);
+        //}
+
+        // ログ出力開始
         $this->logger =& $this->getLogger();
+        $this->plugin->setLogger($this->logger);
         $this->logger->begin();
 
-        // Ethna¥Þ¥Í¡¼¥¸¥ãÀßÄê
+        // include Ethna_Plugin_Abstract for all plugins
+        $this->plugin->includePlugin('Abstract');
+
+        // Ethnaマネージャ設定
         $this->_activateEthnaManager();
     }
 
     /**
-     *  (¸½ºß¥¢¥¯¥Æ¥£¥Ö¤Ê)¥³¥ó¥È¥í¡¼¥é¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÊÖ¤¹
+     *  アプリケーション実行後の後始末を行います。
+     *
+     *  @access protected
+     */
+    function end()
+    {
+        //  必要に応じてオーバライドして下さい。
+        $this->logger->end();
+    }
+
+    /**
+     *  (現在アクティブな)コントローラのインスタンスを返す
      *
      *  @access public
-     *  @return object  Ethna_Controller    ¥³¥ó¥È¥í¡¼¥é¤Î¥¤¥ó¥¹¥¿¥ó¥¹
+     *  @return object  Ethna_Controller    ã\82³ã\83³ã\83\88ã\83­ã\83¼ã\83©ã\81®ã\82¤ã\83³ã\82¹ã\82¿ã\83³ã\82¹
      *  @static
      */
     function &getInstance()
@@ -207,10 +290,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥óID¤òÊÖ¤¹
+     *  アプリケーションIDを返す
      *
      *  @access public
-     *  @return string  ¥¢¥×¥ê¥±¡¼¥·¥ç¥óID
+     *  @return string  アプリケーションID
      */
     function getAppId()
     {
@@ -218,29 +301,74 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥óID¤ò¥Á¥§¥Ã¥¯¤¹¤ë
+     *  アプリケーションIDをチェックする
      *
      *  @access public
-     *  @param  string  $id     ¥¢¥×¥ê¥±¡¼¥·¥ç¥óID
+     *  @param  string  $id     アプリケーションID
      *  @return mixed   true:OK Ethna_Error:NG
+     *  @static
      */
-    function checkAppId($id)
+    function &checkAppId($id)
     {
-        if (strcasecmp($id, 'ethna') == 0) {
-            return Ethna::raiseError(sprintf("Application Id [%s] is reserved\n", $id));
+        $true = true;
+        if (strcasecmp($id, 'ethna') === 0
+            || strcasecmp($id, 'app') === 0) {
+            return Ethna::raiseError("Application Id [$id] is reserved\n");
         }
-        if (preg_match('/^[0-9a-zA-Z]+$/', $id) == 0) {
-            return Ethna::raiseError(sprintf("Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n"));
+
+        //    アプリケーションIDはクラス名のprefixともなるため、
+        //    数字で始まっていてはいけない
+        //    @see http://www.php.net/manual/en/language.variables.php
+        if (preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $id) === 0) {
+            $msg = (preg_match('/^[0-9]$/', $id[0]))
+                 ? "Application ID must NOT start with Number.\n"
+                 : "Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n";
+            return Ethna::raiseError($msg);
         }
+        return $true;
+    }
 
-        return true;
+    /**
+     *  アクション名をチェックする
+     *
+     *  @access public
+     *  @param  string  $action_name    アクション名
+     *  @return mixed   true:OK Ethna_Error:NG
+     *  @static
+     */
+    function &checkActionName($action_name)
+    {
+        $true = true;
+        if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
+                       $action_name) === 0) {
+            return Ethna::raiseError("invalid action name [$action_name]");
+        }
+        return $true;
+    }
+
+    /**
+     *  ビュー名をチェックする
+     *
+     *  @access public
+     *  @param  string  $view_name    ビュー名
+     *  @return mixed   true:OK Ethna_Error:NG
+     *  @static
+     */
+    function &checkViewName($view_name)
+    {
+        $true = true;
+        if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
+                       $view_name) === 0) {
+            return Ethna::raiseError("invalid view name [$view_name]");
+        }
+        return $true;
     }
 
     /**
-     *  DSN¤òÊÖ¤¹
+     *  DSNを返す
      *
      *  @access public
-     *  @param  string  $db_key DB¥­¡¼
+     *  @param  string  $db_key DBã\82­ã\83¼
      *  @return string  DSN
      */
     function getDSN($db_key = "")
@@ -252,11 +380,11 @@ class Ethna_Controller
     }
 
     /**
-     *  DSN¤Î»ý³ÀܳÀßÄê¤òÊÖ¤¹
+     *  DSNの持続接続設定を返す
      *
      *  @access public
-     *  @param  string  $db_key DB¥­¡¼
-     *  @return bool    true:persistent false:non-persistent(¤¢¤ë¤¤¤ÏÀßÄê̵¤·)
+     *  @param  string  $db_key DBã\82­ã\83¼
+     *  @return bool    true:persistent false:non-persistent(あるいは設定無し)
      */
     function getDSN_persistent($db_key = "")
     {
@@ -270,16 +398,16 @@ class Ethna_Controller
     }
 
     /**
-     *  DBÀßÄê¤òÊÖ¤¹
+     *  DB設定を返す
      *
      *  @access public
-     *  @param  string  $db_key DB¥­¡¼("", "r", "rw", "default", "blog_r"...)
-     *  @return string  $db_key¤ËÂбþ¤¹¤ëDB¼ïÊÌÄêµÁ(ÀßÄ̵꤬¤¤¾ì¹ç¤Ïnull)
+     *  @param  string  $db_key DBã\82­ã\83¼("", "r", "rw", "default", "blog_r"...)
+     *  @return string  $db_keyに対応するDB種別定義(設定が無い場合はnull)
      */
     function getDBType($db_key = null)
     {
         if (is_null($db_key)) {
-            // °ìÍ÷¤òÊÖ¤¹
+            // 一覧を返す
             return $this->db;
         }
 
@@ -290,10 +418,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹URL¤òÊÖ¤¹
+     *  アプリケーションベースURLを返す
      *
      *  @access public
-     *  @return string  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹URL
+     *  @return string  ã\82¢ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³ã\83\99ã\83¼ã\82¹URL
      */
     function getURL()
     {
@@ -301,10 +429,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹¥Ç¥£¥ì¥¯¥È¥ê¤òÊÖ¤¹
+     *  アプリケーションベースディレクトリを返す
      *
      *  @access public
-     *  @return string  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ù¡¼¥¹¥Ç¥£¥ì¥¯¥È¥ê
+     *  @return string  アプリケーションベースディレクトリ
      */
     function getBasedir()
     {
@@ -312,39 +440,58 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¯¥é¥¤¥¢¥ó¥È¥¿¥¤¥×/¸À¸ì¤«¤é¥Æ¥ó¥×¥ì¡¼¥È¥Ç¥£¥ì¥¯¥È¥ê̾¤ò·èÄꤹ¤ë
+     *  クライアントタイプ/言語からテンプレートディレクトリ名を決定する
+     *  デフォルトでは [appid]/template/ja_JP/ (ja_JPはロケール名)
+     *  ロケール名は _getDefaultLanguage で決定される。
      *
      *  @access public
-     *  @return string  ¥Æ¥ó¥×¥ì¡¼¥È¥Ç¥£¥ì¥¯¥È¥ê
+     *  @return string  テンプレートディレクトリ
+     *  @see    Ethna_Controller#_getDefaultLanguage
      */
     function getTemplatedir()
     {
         $template = $this->getDirectory('template');
 
-        // ¸À¸ìÊ̥ǥ£¥ì¥¯¥È¥ê
-        if (file_exists($template . '/' . $this->language)) {
-            $template .= '/' . $this->language;
+        // 言語別ディレクトリ
+        // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、
+        // テンプレートディレクトリにも自動的にそれを付加する。
+        if (!empty($this->locale)) {
+            $template .= '/' . $this->locale;
         }
 
         return $template;
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê̾¤ò·èÄꤹ¤ë
+     *  アクションディレクトリ名を決定する
      *
      *  @access public
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê
+     *  @return string  アクションディレクトリ
      */
-    function getActiondir()
+    function getActiondir($gateway = null)
     {
-        return (empty($this->directory['action']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['action'] . "/"));
+        $key = 'action';
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+            $key = 'action';
+            break;
+        case GATEWAY_CLI:
+            $key = 'action_cli';
+            break;
+        case GATEWAY_XMLRPC:
+            $key = 'action_xmlrpc';
+            break;
+        }
+
+        return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
     }
 
     /**
-     *  ¥Ó¥å¡¼¥Ç¥£¥ì¥¯¥È¥ê̾¤ò·èÄꤹ¤ë
+     *  ビューディレクトリ名を決定する
      *
      *  @access public
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê
+     *  @return string  ビューディレクトリ
      */
     function getViewdir()
     {
@@ -352,19 +499,25 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥êÀßÄê¤òÊÖ¤¹
+     *  (action,view以外の)テストケースを置くディレクトリ名を決定する
      *
      *  @access public
-     *  @param  string  $key    ¥Ç¥£¥ì¥¯¥È¥ê¥¿¥¤¥×("tmp", "template"...)
-     *  @return string  $key¤ËÂбþ¤·¤¿¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê(ÀßÄ̵꤬¤¤¾ì¹ç¤Ïnull)
+     *  @return string  テストケースを置くディレクトリ
      */
-    function getDirectory($key)
+    function getTestdir()
     {
-        // for B.C.
-        if ($key == 'app' && isset($this->directory[$key]) == false) {
-            return BASE . '/app';
-        }
+        return (empty($this->directory['test']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['test'] . "/"));
+    }
 
+    /**
+     *  アプリケーションディレクトリ設定を返す
+     *
+     *  @access public
+     *  @param  string  $key    ディレクトリタイプ("tmp", "template"...)
+     *  @return string  $keyに対応したアプリケーションディレクトリ(設定が無い場合はnull)
+     */
+    function getDirectory($key)
+    {
         if (isset($this->directory[$key]) == false) {
             return null;
         }
@@ -372,11 +525,11 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó³ÈÄ¥»ÒÀßÄê¤òÊÖ¤¹
+     *  アプリケーション拡張子設定を返す
      *
      *  @access public
-     *  @param  string  $key    ³ÈÄ¥»Ò¥¿¥¤¥×("php", "tpl"...)
-     *  @return string  $key¤ËÂбþ¤·¤¿³ÈÄ¥»Ò(ÀßÄ̵꤬¤¤¾ì¹ç¤Ïnull)
+     *  @param  string  $key    拡張子タイプ("php", "tpl"...)
+     *  @return string  $keyに対応した拡張子(設定が無い場合はnull)
      */
     function getExt($key)
     {
@@ -387,10 +540,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¯¥é¥¹¥Õ¥¡¥¯¥È¥ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ(R)
+     *  ã\82¯ã\83©ã\82¹ã\83\95ã\82¡ã\82¯ã\83\88ã\83ªã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ(R)
      *
      *  @access public
-     *  @return object  Ethna_ClassFactory  ¥¯¥é¥¹¥Õ¥¡¥¯¥È¥ê¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_ClassFactory  クラスファクトリオブジェクト
      */
     function &getClassFactory()
     {
@@ -398,10 +551,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¥¨¥é¡¼¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  ã\82¢ã\82¯ã\82·ã\83§ã\83³ã\82¨ã\83©ã\83¼ã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_ActionError   ¥¢¥¯¥·¥ç¥ó¥¨¥é¡¼¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_ActionError   アクションエラーオブジェクト
      */
     function &getActionError()
     {
@@ -409,22 +562,34 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥àform¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  ã\82¢ã\82¯ã\82·ã\83§ã\83³ã\83\95ã\82©ã\83¼ã\83 ã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_ActionForm    ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥àform¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_ActionForm    アクションフォームオブジェクト
      */
     function &getActionForm()
     {
-        // ÌÀ¼¨Åª¤Ë¥¯¥é¥¹¥Õ¥¡¥¯¥È¥ê¤òÍøÍѤ·¤Æ¤¤¤Ê¤¤
+        // 明示的にクラスファクトリを利用していない
         return $this->action_form;
     }
 
     /**
-     *  backend¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  ã\83\93ã\83¥ã\83¼ã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_Backend   backend¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_View          ビューオブジェクト
+     */
+    function &getView()
+    {
+        // 明示的にクラスファクトリを利用していない
+        return $this->view;
+    }
+
+    /**
+     *  backendオブジェクトのアクセサ
+     *
+     *  @access public
+     *  @return object  Ethna_Backend   backendオブジェクト
      */
     function &getBackend()
     {
@@ -432,10 +597,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ÀßÄꥪ¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  è¨­å®\9aã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_Config    ÀßÄꥪ¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_Config    設定オブジェクト
      */
     function &getConfig()
     {
@@ -443,10 +608,10 @@ class Ethna_Controller
     }
 
     /**
-     *  i18n¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ(R)
+     *  i18nã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ(R)
      *
      *  @access public
-     *  @return object  Ethna_I18N  i18n¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_I18N  i18nオブジェクト
      */
     function &getI18N()
     {
@@ -454,10 +619,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥í¥°¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  ã\83­ã\82°ã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_Logger        ¥í¥°¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_Logger        ログオブジェクト
      */
     function &getLogger()
     {
@@ -465,10 +630,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  ã\82»ã\83\83ã\82·ã\83§ã\83³ã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_Session       ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_Session       セッションオブジェクト
      */
     function &getSession()
     {
@@ -476,10 +641,10 @@ class Ethna_Controller
     }
 
     /**
-     *  SQL¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥¯¥»¥µ
+     *  SQLã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ã\82¢ã\82¯ã\82»ã\82µ
      *
      *  @access public
-     *  @return object  Ethna_AppSQL    SQL¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_AppSQL    SQLオブジェクト
      */
     function &getSQL()
     {
@@ -487,10 +652,33 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Þ¥Í¡¼¥¸¥ã°ìÍ÷¤òÊÖ¤¹
+     *  プラグインオブジェクトのアクセサ
+     *
+     *  @access public
+     *  @return object  Ethna_Plugin    プラグインオブジェクト
+     */
+    function &getPlugin()
+    {
+        return $this->class_factory->getObject('plugin');
+    }
+
+    /**
+     *  URLハンドラオブジェクトのアクセサ
      *
      *  @access public
-     *  @return array   ¥Þ¥Í¡¼¥¸¥ã°ìÍ÷
+     *  @return object  Ethna_UrlHandler    URLハンドラオブジェクト
+     */
+    function &getUrlHandler()
+    {
+        return $this->class_factory->getObject('url_handler');
+    }
+
+    /**
+     *  マネージャ一覧を返す
+     *
+     *  @access public
+     *  @return array   マネージャ一覧
+     *  @obsolete
      */
     function getManagerList()
     {
@@ -498,10 +686,10 @@ class Ethna_Controller
     }
 
     /**
-     *  ¼Â¹ÔÃæ¤Î¥¢¥¯¥·¥ç¥ó̾¤òÊÖ¤¹
+     *  実行中のアクション名を返す
      *
      *  @access public
-     *  @return string  ¼Â¹ÔÃæ¤Î¥¢¥¯¥·¥ç¥ó̾
+     *  @return string  実行中のアクション名
      */
     function getCurrentActionName()
     {
@@ -509,18 +697,83 @@ class Ethna_Controller
     }
 
     /**
-     *  »ÈÍѸÀ¸ì¤ò¼èÆÀ¤¹¤ë
+     *  実行中のXMLRPCメソッド名を返す
      *
      *  @access public
-     *  @return array   »ÈÍѸÀ¸ì,¥·¥¹¥Æ¥à¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°Ì¾,¥¯¥é¥¤¥¢¥ó¥È¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°Ì¾
+     *  @return string  実行中のXMLRPCメソッド名
+     */
+    function getXmlrpcMethodName()
+    {
+        return $this->xmlrpc_method_name;
+    }
+
+    /**
+     *  ロケール設定、使用言語を取得する
+     *
+     *  @access public
+     *  @return array   ロケール名(e.x ja_JP, en_US 等),
+     *                  システムエンコーディング名,
+     *                  クライアントエンコーディング名 の配列
+     *                  (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
+     *  @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
      */
     function getLanguage()
     {
-        return array($this->language, $this->system_encoding, $this->client_encoding);
+        return array($this->locale, $this->system_encoding, $this->client_encoding);
+    }
+
+    /**
+     *  ロケール名へのアクセサ(R)
+     *
+     *  @access public
+     *  @return string  ロケール名(e.x ja_JP, en_US 等),
+     *                  (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
+     */
+    function getLocale()
+    {
+        return $this->locale;
     }
 
     /**
-     *  ¥²¡¼¥È¥¦¥§¥¤¤ò¼èÆÀ¤¹¤ë
+     *  ロケール名へのアクセサ(W)
+     *
+     *  @access public
+     *  @param $locale ロケール名(e.x ja_JP, en_US 等),
+     *                 (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
+     */
+    function setLocale($locale)
+    {
+        $this->locale = $locale;
+        $i18n =& $this->getI18N();
+        $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
+    }
+
+    /**
+     *  クライアントエンコーディング名へのアクセサ(R)
+     *
+     *  @access public
+     *  @return string  $client_encoding クライアントエンコーディング名
+     */
+    function getClientEncoding()
+    {
+        return $this->client_encoding;
+    }
+
+    /**
+     *  クライアントエンコーディング名へのアクセサ(W)
+     *
+     *  @access public
+     *  @param  string  $client_encoding クライアントエンコーディング名
+     */
+    function setClientEncoding($client_encoding)
+    {
+        $this->client_encoding = $client_encoding;
+        $i18n =& $this->getI18N();
+        $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
+    }
+
+    /**
+     *  ゲートウェイを取得する
      *
      *  @access public
      */
@@ -530,97 +783,98 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥²¡¼¥È¥¦¥§¥¤¥â¡¼¥É¤òÀßÄꤹ¤ë
+     *  ゲートウェイモードを設定する
      *
      *  @access public
      */
     function setGateway($gateway)
     {
-        // TODO: check value?
         $this->gateway = $gateway;
     }
 
     /**
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È
+     *  アプリケーションのエントリポイント
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥³¥ó¥È¥í¡¼¥é¤Î¥¯¥é¥¹Ì¾
-     *  @param  mixed   $action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
+     *  @param  string  $class_name     アプリケーションコントローラのクラス名
+     *  @param  mixed   $action_name    指定のアクション名(省略可)
+     *  @param  mixed   $fallback_action_name   アクションが決定できなかった場合に実行されるアクション名(省略可)
      *  @static
      */
     function main($class_name, $action_name = "", $fallback_action_name = "")
     {
         $c =& new $class_name;
         $c->trigger($action_name, $fallback_action_name);
+        $c->end();
     }
 
     /**
-     *  CLI¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È
+     *  CLIアプリケーションのエントリポイント
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥³¥ó¥È¥í¡¼¥é¤Î¥¯¥é¥¹Ì¾
-     *  @param  string  $action_name    ¼Â¹Ô¤¹¤ë¥¢¥¯¥·¥ç¥ó̾
-     *  @param  bool    $enable_filter  ¥Õ¥£¥ë¥¿¥Á¥§¥¤¥ó¤òÍ­¸ú¤Ë¤¹¤ë¤«¤É¤¦¤«
+     *  @param  string  $class_name     アプリケーションコントローラのクラス名
+     *  @param  string  $action_name    実行するアクション名
+     *  @param  bool    $enable_filter  フィルタチェインを有効にするかどうか
      *  @static
      */
     function main_CLI($class_name, $action_name, $enable_filter = true)
     {
-        $c =& new $class_name;
-        $c->setGateway(GATEWAY_CLI);
-        $c->action[$action_name] = array();
+        $c =& new $class_name(GATEWAY_CLI);
+        $c->action_cli[$action_name] = array();
         $c->trigger($action_name, "", $enable_filter);
+        $c->end();
     }
 
     /**
-     *  XMLRPC¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È
+     *  XMLRPCアプリケーションのエントリポイント
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥³¥ó¥È¥í¡¼¥é¤Î¥¯¥é¥¹Ì¾
-     *  @param  mixed   $action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
      *  @static
      */
-    function main_XMLRPC($class_name, $action_name = "", $fallback_action_name = "")
+    function main_XMLRPC($class_name)
     {
-        $c =& new $class_name;
-        $c->setGateway(GATEWAY_XMLRPC);
-        $c->trigger($action_name, $fallback_action_name);
+        if (extension_loaded('xmlrpc') == false) {
+            die("xmlrpc extension is required to enable this gateway");
+        }
+
+        $c =& new $class_name(GATEWAY_XMLRPC);
+        $c->trigger("", "", false);
+        $c->end();
     }
 
     /**
-     *  SOAP¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È
+     *  SOAPアプリケーションのエントリポイント
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥³¥ó¥È¥í¡¼¥é¤Î¥¯¥é¥¹Ì¾
-     *  @param  mixed   $action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
+     *  @param  string  $class_name     アプリケーションコントローラのクラス名
+     *  @param  mixed   $action_name    指定のアクション名(省略可)
+     *  @param  mixed   $fallback_action_name   アクションが決定できなかった場合に実行されるアクション名(省略可)
      *  @static
      */
     function main_SOAP($class_name, $action_name = "", $fallback_action_name = "")
     {
-        $c =& new $class_name;
-        $c->setGateway(GATEWAY_SOAP);
+        $c =& new $class_name(GATEWAY_SOAP);
         $c->trigger($action_name, $fallback_action_name);
+        $c->end();
     }
 
     /**
-     *  ¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î½èÍý¤ò³«»Ï¤¹¤ë
+     *  フレームワークの処理を開始する
      *
      *  @access public
-     *  @param  mixed   $default_action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó̾¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾
-     *  @param  bool    $enable_filter  ¥Õ¥£¥ë¥¿¥Á¥§¥¤¥ó¤òÍ­¸ú¤Ë¤¹¤ë¤«¤É¤¦¤«
-     *  @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
+     *  @param  mixed   $default_action_name    指定のアクション名
+     *  @param  mixed   $fallback_action_name   アクション名が決定できなかった場合に実行されるアクション名
+     *  @param  bool    $enable_filter  フィルタチェインを有効にするかどうか
+     *  @return mixed   0:正常çµ\82äº\86 Ethna_Error:ã\82¨ã\83©ã\83¼
      */
     function trigger($default_action_name = "", $fallback_action_name = "", $enable_filter = true)
     {
-        // ¥Õ¥£¥ë¥¿¡¼¤ÎÀ¸À®
+        // フィルターの生成
         if ($enable_filter) {
             $this->_createFilterChain();
         }
 
-        // ¼Â¹ÔÁ°¥Õ¥£¥ë¥¿
+        // å®\9fè¡\8cå\89\8dã\83\95ã\82£ã\83«ã\82¿
         for ($i = 0; $i < count($this->filter_chain); $i++) {
             $r = $this->filter_chain[$i]->preFilter();
             if (Ethna::isError($r)) {
@@ -644,7 +898,7 @@ class Ethna_Controller
             break;
         }
 
-        // ¼Â¹Ô¸å¥Õ¥£¥ë¥¿
+        // å®\9fè¡\8cå¾\8cã\83\95ã\82£ã\83«ã\82¿
         for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
             $r = $this->filter_chain[$i]->postFilter();
             if (Ethna::isError($r)) {
@@ -654,23 +908,26 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î½èÍý¤ò¼Â¹Ô¤¹¤ë(WWW)
+     *  フレームワークの処理を実行する(WWW)
      *
-     *  °ú¿ô$default_action_name¤ËÇÛÎ󤬻ØÄꤵ¤ì¤¿¾ì¹ç¡¢¤½¤ÎÇÛÎó¤Ç»ØÄꤵ¤ì¤¿
-     *  ¥¢¥¯¥·¥ç¥ó°Ê³°¤Ï¼õ¤±ÉÕ¤±¤Ê¤¤(»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤¥¢¥¯¥·¥ç¥ó¤¬»ØÄꤵ¤ì¤¿
-     *  ¾ì¹ç¡¢ÇÛÎó¤ÎÀèƬ¤Ç»ØÄꤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó¤¬¼Â¹Ô¤µ¤ì¤ë)
+     *  引数$default_action_nameに配列が指定された場合、その配列で指定された
+     *  アクション以外は受け付けない(指定されていないアクションが指定された
+     *  場合、配列の先頭で指定されたアクションが実行される)
      *
      *  @access private
-     *  @param  mixed   $default_action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó̾¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾
-     *  @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
+     *  @param  mixed   $default_action_name    指定のアクション名
+     *  @param  mixed   $fallback_action_name   アクション名が決定できなかった場合に実行されるアクション名
+     *  @return mixed   0:正常çµ\82äº\86 Ethna_Error:ã\82¨ã\83©ã\83¼
      */
     function _trigger_WWW($default_action_name = "", $fallback_action_name = "")
     {
-        // ¥¢¥¯¥·¥ç¥ó̾¤Î¼èÆÀ
+        // アクション名の取得
         $action_name = $this->_getActionName($default_action_name, $fallback_action_name);
 
-        // ¥¢¥¯¥·¥ç¥óÄêµÁ¤Î¼èÆÀ
+        // マネージャ実行チェック
+        $this->_ethnaManagerEnabledCheck($action_name);
+
+        // アクション定義の取得
         $action_obj =& $this->_getAction($action_name);
         if (is_null($action_obj)) {
             if ($fallback_action_name != "") {
@@ -684,7 +941,7 @@ class Ethna_Controller
             }
         }
 
-        // ¥¢¥¯¥·¥ç¥ó¼Â¹ÔÁ°¥Õ¥£¥ë¥¿
+        // ã\82¢ã\82¯ã\82·ã\83§ã\83³å®\9fè¡\8cå\89\8dã\83\95ã\82£ã\83«ã\82¿
         for ($i = 0; $i < count($this->filter_chain); $i++) {
             $r = $this->filter_chain[$i]->preActionFilter($action_name);
             if ($r != null) {
@@ -694,20 +951,26 @@ class Ethna_Controller
         }
         $this->action_name = $action_name;
 
-        // ¸À¸ìÀßÄê
-        $this->_setLanguage($this->language, $this->system_encoding, $this->client_encoding);
+        // オブジェクト生成
+        $backend =& $this->getBackend();
+        $session =& $this->getSession();
+        $session->restore();
+
+        // 言語切り替えフックを呼ぶ
+        $this->_setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
 
-        // ¥ª¥Ö¥¸¥§¥¯¥ÈÀ¸À®
+        // アクションフォーム初期化
+        // フォーム定義、フォーム値設定
         $form_name = $this->getActionFormName($action_name);
         $this->action_form =& new $form_name($this);
+        $this->action_form->setFormDef_PreHelper();
+        $this->action_form->setFormVars();
+        $backend->setActionForm($this->action_form);
 
-        // ¥Ð¥Ã¥¯¥¨¥ó¥É½èÍý¼Â¹Ô
-        $backend =& $this->getBackend();
-        $session =& $this->getSession();
-        $session->restore();
+        // バックエンド処理実行
         $forward_name = $backend->perform($action_name);
 
-        // ¥¢¥¯¥·¥ç¥ó¼Â¹Ô¸å¥Õ¥£¥ë¥¿
+        // ã\82¢ã\82¯ã\82·ã\83§ã\83³å®\9fè¡\8cå¾\8cã\83\95ã\82£ã\83«ã\82¿
         for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
             $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name);
             if ($r != null) {
@@ -716,31 +979,35 @@ class Ethna_Controller
             }
         }
 
-        // ¥³¥ó¥È¥í¡¼¥é¤ÇÁ«°ÜÀè¤ò·èÄꤹ¤ë(¥ª¥×¥·¥ç¥ó)
-        $forward_name = $this->_sortForward($action_name, $forward_name);
+        // コントローラで遷移先を決定する(オプション)
+        $forward_name_params = $this->_sortForward($action_name, $forward_name);
+
+        // Viewへの引数があれば取り出す
+        $preforward_params = array();
+        if (is_array($forward_name_params)) {
+            $forward_name = array_shift($forward_name_params);
+            $preforward_params = $forward_name_params;
+        }
+        else {
+            $forward_name = $forward_name_params;
+        }
 
         if ($forward_name != null) {
             $view_class_name = $this->getViewClassName($forward_name);
-            $view_class =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
-            $view_class->preforward();
-
-            // ¸åÊý¸ß´¹½èÍý:(
-            $view_class_name = $this->class_factory->getObjectName('view');
-            if (is_subclass_of($view_class, $view_class_name) == false) {
-                $view_class =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
-            }
-            $view_class->forward();
+            $this->view =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
+            call_user_func_array(array($this->view, 'preforward'), $preforward_params);
+            $this->view->forward();
         }
 
         return 0;
     }
 
     /**
-     *  ¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î½èÍý¤ò¼Â¹Ô¤¹¤ë(CLI)
+     *  フレームワークの処理を実行する(CLI)
      *
      *  @access private
-     *  @param  mixed   $default_action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾
-     *  @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
+     *  @param  mixed   $default_action_name    指定のアクション名
+     *  @return mixed   0:正常çµ\82äº\86 Ethna_Error:ã\82¨ã\83©ã\83¼
      */
     function _trigger_CLI($default_action_name = "")
     {
@@ -748,60 +1015,141 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î½èÍý¤ò¼Â¹Ô¤¹¤ë(XMLRPC)
+     *  フレームワークの処理を実行する(XMLRPC)
      *
      *  @access private
-     *  @param  mixed   $action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾
-     *  @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
+     *  @param  mixed   $action_name    指定のアクション名
+     *  @return mixed   0:正常çµ\82äº\86 Ethna_Error:ã\82¨ã\83©ã\83¼
      */
     function _trigger_XMLRPC($action_name = "")
     {
-        die("sorry, xmlrpc gateway is not supported yet");
+        // prepare xmlrpc server
+        $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway";
+        $xmlrpc_server = xmlrpc_server_create();
+
+        $method = null;
+        $param = xmlrpc_decode_request(file_get_contents('php://input'), $method);
+        $this->xmlrpc_method_name = $method;
+
+        $request = xmlrpc_encode_request(
+            $xmlrpc_gateway_method_name,
+            $param,
+            array(
+                'output_type'   => 'xml',
+                'verbosity'     => 'pretty',
+                'escaping'      => array('markup'),
+                'version'       => 'xmlrpc',
+                'encoding'      => 'utf-8'
+            )
+        );
+
+        xmlrpc_server_register_method(
+            $xmlrpc_server,
+            $xmlrpc_gateway_method_name,
+            $xmlrpc_gateway_method_name
+        );
+
+        // send request
+        $r = xmlrpc_server_call_method(
+            $xmlrpc_server,
+            $request,
+            null,
+            array(
+                'output_type'   => 'xml',
+                'verbosity'     => 'pretty',
+                'escaping'      => array('markup'),
+                'version'       => 'xmlrpc',
+                'encoding'      => 'utf-8'
+            )
+        );
+
+        header('Content-Length: ' . strlen($r));
+        header('Content-Type: text/xml; charset=UTF-8');
+        print $r;
+    }
+
+    /**
+     *  _trigger_XMLRPCのコールバックメソッド
+     *
+     *  @access public
+     */
+    function trigger_XMLRPC($method, $param)
+    {
+        // アクション定義の取得
+        $action_obj =& $this->_getAction($method);
+        if (is_null($action_obj)) {
+            return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
+        }
+
+        // オブジェクト生成
+        $backend =& $this->getBackend();
+
+        $form_name = $this->getActionFormName($method);
+        $this->action_form =& new $form_name($this);
+        $def = $this->action_form->getDef();
+        $n = 0;
+        foreach ($def as $key => $value) {
+            if (isset($param[$n]) == false) {
+                $this->action_form->set($key, null);
+            } else {
+                $this->action_form->set($key, $param[$n]);
+            }
+            $n++;
+        }
+
+        // バックエンド処理実行
+        $backend->setActionForm($this->action_form);
+
+        $session =& $this->getSession();
+        $session->restore();
+        $r = $backend->perform($method);
+
+        return $r;
     }
 
     /**
-     *  SOAP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î½èÍý¤ò¼Â¹Ô¤¹¤ë
+     *  SOAPフレームワークの処理を実行する
      *
      *  @access private
      */
     function _trigger_SOAP()
     {
-        // SOAP¥¨¥ó¥È¥ê¥¯¥é¥¹
+        // SOAPã\82¨ã\83³ã\83\88ã\83ªã\82¯ã\83©ã\82¹
         $gg =& new Ethna_SOAP_GatewayGenerator();
         $script = $gg->generate();
         eval($script);
 
-        // SOAP¥ê¥¯¥¨¥¹¥È½èÍý
+        // SOAPリクエスト処理
         $server =& new SoapServer(null, array('uri' => $this->config->get('url')));
         $server->setClass($gg->getClassName());
         $server->handle();
     }
 
     /**
-     *  ¥¨¥é¡¼¥Ï¥ó¥É¥é
+     *  エラーハンドラ
      *
-     *  ¥¨¥é¡¼È¯À¸»þ¤ÎÄɲýèÍý¤ò¹Ô¤¤¤¿¤¤¾ì¹ç¤Ï¤³¤Î¥á¥½¥Ã¥É¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
-     *  (¥¢¥é¡¼¥È¥á¡¼¥ëÁ÷¿®Åù¡Ý¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¥í¥°½ÐÎÏ»þ¤Ë¥¢¥é¡¼¥È¥á¡¼¥ë
-     *  ¤¬Á÷¿®¤µ¤ì¤ë¤¬¡¢¥¨¥é¡¼È¯À¸»þ¤ËÊ̤˥¢¥é¡¼¥È¥á¡¼¥ë¤ò¤³¤³¤ÇÁ÷¿®
-     *  ¤µ¤»¤ë¤³¤È¤â²Äǽ)
+     *  エラー発生時の追加処理を行いたい場合はこのメソッドをオーバーライドする
+     *  (アラートメール送信等−デフォルトではログ出力時にアラートメール
+     *  が送信されるが、エラー発生時に別にアラートメールをここで送信
+     *  ã\81\95ã\81\9bã\82\8bã\81\93ã\81¨ã\82\82å\8f¯è\83½)
      *
      *  @access public
-     *  @param  object  Ethna_Error     ¥¨¥é¡¼¥ª¥Ö¥¸¥§¥¯¥È
+     *  @param  object  Ethna_Error     エラーオブジェクト
      */
     function handleError(&$error)
     {
-        // ¥í¥°½ÐÎÏ
+        // ログ出力
         list ($log_level, $dummy) = $this->logger->errorLevelToLogLevel($error->getLevel());
         $message = $error->getMessage();
         $this->logger->log($log_level, sprintf("%s [ERROR CODE(%d)]", $message, $error->getCode()));
     }
 
     /**
-     *  ¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸¤ò¼èÆÀ¤¹¤ë
+     *  エラーメッセージを取得する
      *
      *  @access public
-     *  @param  int     $code       ¥¨¥é¡¼¥³¡¼¥É
-     *  @return string  ¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸
+     *  @param  int     $code       エラーコード
+     *  @return string  ã\82¨ã\83©ã\83¼ã\83¡ã\83\83ã\82»ã\83¼ã\82¸
      */
     function getErrorMessage($code)
     {
@@ -815,26 +1163,26 @@ class Ethna_Controller
     }
 
     /**
-     *  ¼Â¹Ô¤¹¤ë¥¢¥¯¥·¥ç¥ó̾¤òÊÖ¤¹
+     *  実行するアクション名を返す
      *
      *  @access private
-     *  @param  mixed   $default_action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  ¼Â¹Ô¤¹¤ë¥¢¥¯¥·¥ç¥ó̾
+     *  @param  mixed   $default_action_name    指定のアクション名
+     *  @return string  実行するアクション名
      */
     function _getActionName($default_action_name, $fallback_action_name)
     {
-        // ¥Õ¥©¡¼¥à¤«¤éÍ׵ᤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾¤ò¼èÆÀ¤¹¤ë
+        // フォームから要求されたアクション名を取得する
         $form_action_name = $this->_getActionName_Form();
         $form_action_name = preg_replace('/[^a-z0-9\-_]+/i', '', $form_action_name);
         $this->logger->log(LOG_DEBUG, 'form_action_name[%s]', $form_action_name);
 
-        // Ethna¥Þ¥Í¡¼¥¸¥ã¤Ø¤Î¥Õ¥©¡¼¥à¤«¤é¤Î¥ê¥¯¥¨¥¹¥È¤ÏµñÈÝ
+        // Ethnaマネージャへのフォームからのリクエストは拒否
         if ($form_action_name == "__ethna_info__" ||
             $form_action_name == "__ethna_unittest__") {
             $form_action_name = "";
         }
 
-        // ¥Õ¥©¡¼¥à¤«¤é¤Î»ØÄ̵꤬¤¤¾ì¹ç¤Ï¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È¤Ë»ØÄꤵ¤ì¤¿¥Ç¥Õ¥©¥ë¥ÈÃͤòÍøÍѤ¹¤ë
+        // フォームからの指定が無い場合はエントリポイントに指定されたデフォルト値を利用する
         if ($form_action_name == "" && count($default_action_name) > 0) {
             $tmp = is_array($default_action_name) ? $default_action_name[0] : $default_action_name;
             if ($tmp{strlen($tmp)-1} == '*') {
@@ -846,10 +1194,10 @@ class Ethna_Controller
             $action_name = $form_action_name;
         }
 
-        // ¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È¤ËÇÛÎ󤬻ØÄꤵ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ï»ØÄê°Ê³°¤Î¥¢¥¯¥·¥ç¥ó̾¤ÏµñÈݤ¹¤ë
+        // エントリポイントに配列が指定されている場合は指定以外のアクション名は拒否する
         if (is_array($default_action_name)) {
             if ($this->_isAcceptableActionName($action_name, $default_action_name) == false) {
-                // »ØÄê°Ê³°¤Î¥¢¥¯¥·¥ç¥ó̾¤Ç¹ç¤Ã¤¿¾ì¹ç¤Ï$fallback_action_name(or ¥Ç¥Õ¥©¥ë¥È)
+                // 指定以外のアクション名で合った場合は$fallback_action_name(or デフォルト)
                 $tmp = $fallback_action_name != "" ? $fallback_action_name : $default_action_name[0];
                 if ($tmp{strlen($tmp)-1} == '*') {
                     $tmp = substr($tmp, 0, -1);
@@ -865,14 +1213,14 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Õ¥©¡¼¥à¤Ë¤è¤êÍ׵ᤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾¤òÊÖ¤¹
+     *  フォームにより要求されたアクション名を返す
      *
-     *  ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ÎÀ­¼Á¤Ë±þ¤¸¤Æ¤³¤Î¥á¥½¥Ã¥É¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤Æ²¼¤µ¤¤¡£
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï"action_"¤Ç»Ï¤Þ¤ë¥Õ¥©¡¼¥àÃͤÎ"action_"¤ÎÉôʬ¤ò½ü¤¤¤¿¤â¤Î
-     *  ("action_sample"¤Ê¤é"sample")¤¬¥¢¥¯¥·¥ç¥ó̾¤È¤·¤Æ°·¤ï¤ì¤Þ¤¹
+     *  アプリケーションの性質に応じてこのメソッドをオーバーライドして下さい。
+     *  デフォルトでは"action_"で始まるフォーム値の"action_"の部分を除いたもの
+     *  ("action_sample"なら"sample")がアクション名として扱われます
      *
      *  @access protected
-     *  @return string  ¥Õ¥©¡¼¥à¤Ë¤è¤êÍ׵ᤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾
+     *  @return string  フォームにより要求されたアクション名
      */
     function _getActionName_Form()
     {
@@ -880,13 +1228,33 @@ class Ethna_Controller
             return null;
         }
 
+        $url_handler =& $this->getUrlHandler();
+        if ($_SERVER['REQUEST_METHOD'] == "GET") {
+            $tmp_vars = $_GET;
+        } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
+            $tmp_vars = $_POST;
+        }
+
+        if (empty($_SERVER['URL_HANDLER']) == false) {
+            $tmp_vars['__url_handler__'] = $_SERVER['URL_HANDLER'];
+            $tmp_vars['__url_info__'] = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null;
+            $tmp_vars = $url_handler->requestToAction($tmp_vars);
+
+            if ($_SERVER['REQUEST_METHOD'] == "GET") {
+                $_GET = array_merge($_GET, $tmp_vars);
+            } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
+                $_POST = array_merge($_POST, $tmp_vars);
+            }
+            $_REQUEST = array_merge($_REQUEST, $tmp_vars);
+        }
+
         if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
             $http_vars =& $_POST;
         } else {
             $http_vars =& $_GET;
         }
 
-        // ¥Õ¥©¡¼¥àÃͤ«¤é¥ê¥¯¥¨¥¹¥È¤µ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾¤ò¼èÆÀ¤¹¤ë
+        // フォーム値からリクエストされたアクション名を取得する
         $action_name = $sub_action_name = null;
         foreach ($http_vars as $name => $value) {
             if ($value == "" || strncmp($name, 'action_', 7) != 0) {
@@ -895,12 +1263,12 @@ class Ethna_Controller
 
             $tmp = substr($name, 7);
 
-            // type="image"Âбþ
+            // type="image"対応
             if (preg_match('/_x$/', $name) || preg_match('/_y$/', $name)) {
                 $tmp = substr($tmp, 0, strlen($tmp)-2);
             }
 
-            // value="dummy"¤È¤Ê¤Ã¤Æ¤¤¤ë¤â¤Î¤ÏÍ¥ÀèÅÙ¤ò²¼¤²¤ë
+            // value="dummy"となっているものは優先度を下げる
             if ($value == "dummy") {
                 $sub_action_name = $tmp;
             } else {
@@ -915,15 +1283,46 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Õ¥©¡¼¥à¤Ë¤è¤êÍ׵ᤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾¤ËÂбþ¤¹¤ëÄêµÁ¤òÊÖ¤¹
+     *  アクション名を指定するクエリ/HTMLを生成する
+     *
+     *  @access public
+     *  @param  string  $action action to request
+     *  @param  string  $type   hidden, url...
+     *  @todo   consider gateway
+     */
+    function getActionRequest($action, $type = "hidden")
+    {
+        $s = null;
+        if ($type == "hidden") {
+            $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES));
+        } else if ($type == "url") {
+            $s = sprintf('action_%s=true', urlencode($action));
+        }
+        return $s;
+    }
+
+    /**
+     *  フォームにより要求されたアクション名に対応する定義を返す
      *
      *  @access private
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return array   ¥¢¥¯¥·¥ç¥óÄêµÁ
+     *  @param  string  $action_name    アクション名
+     *  @return array   アクション定義
      */
-    function &_getAction($action_name)
+    function &_getAction($action_name, $gateway = null)
     {
-        $action =& $this->action;
+        $action = array();
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+            $action =& $this->action;
+            break;
+        case GATEWAY_CLI:
+            $action =& $this->action_cli;
+            break;
+        case GATEWAY_XMLRPC:
+            $action =& $this->action_xmlrpc;
+            break;
+        }
 
         $action_obj = array();
         if (isset($action[$action_name])) {
@@ -935,10 +1334,10 @@ class Ethna_Controller
             $this->logger->log(LOG_DEBUG, "action [%s] is not defined -> try default", $action_name);
         }
 
-        // ¥¢¥¯¥·¥ç¥ó¥¹¥¯¥ê¥×¥È¤Î¥¤¥ó¥¯¥ë¡¼¥É
+        // アクションスクリプトのインクルード
         $this->_includeActionScript($action_obj, $action_name);
 
-        // ¾ÊάÃͤÎÊäÀµ
+        // 省略値の補正
         if (isset($action_obj['class_name']) == false) {
             $action_obj['class_name'] = $this->getDefaultActionClass($action_name);
         }
@@ -946,18 +1345,18 @@ class Ethna_Controller
         if (isset($action_obj['form_name']) == false) {
             $action_obj['form_name'] = $this->getDefaultFormClass($action_name);
         } else if (class_exists($action_obj['form_name']) == false) {
-            // ÌÀ¼¨»ØÄꤵ¤ì¤¿¥Õ¥©¡¼¥à¥¯¥é¥¹¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï·Ù¹ð
+            // 明示指定されたフォームクラスが定義されていない場合は警告
             $this->logger->log(LOG_WARNING, 'stated form class is not defined [%s]', $action_obj['form_name']);
         }
 
-        // É¬Í×¾ò·ï¤Î³Îǧ
+        // 必要条件の確認
         if (class_exists($action_obj['class_name']) == false) {
-            $this->logger->log(LOG_WARNING, 'action class is not defined [%s]', $action_obj['class_name']);
+            $this->logger->log(LOG_NOTICE, 'action class is not defined [%s]', $action_obj['class_name']);
             $_ret_object = null;
             return $_ret_object;
         }
         if (class_exists($action_obj['form_name']) == false) {
-            // ¥Õ¥©¡¼¥à¥¯¥é¥¹¤Ï̤ÄêµÁ¤Ç¤âÎɤ¤
+            // フォームクラスは未定義でも良い
             $class_name = $this->class_factory->getObjectName('form');
             $this->logger->log(LOG_DEBUG, 'form class is not defined [%s] -> falling back to default [%s]', $action_obj['form_name'], $class_name);
             $action_obj['form_name'] = $class_name;
@@ -969,12 +1368,12 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó̾¤È¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤«¤é¤ÎÌá¤êÃͤ˴ð¤Å¤¤¤ÆÁ«°ÜÀè¤ò·èÄꤹ¤ë
+     *  アクション名とアクションクラスからの戻り値に基づいて遷移先を決定する
      *
      *  @access protected
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @param  string  $retval         ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤«¤é¤ÎÌá¤êÃÍ
-     *  @return string  Á«°ÜÀè
+     *  @param  string  $action_name    アクション名
+     *  @param  string  $retval         アクションクラスからの戻り値
+     *  @return string  遷移先
      */
     function _sortForward($action_name, $retval)
     {
@@ -982,7 +1381,7 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Õ¥£¥ë¥¿¡¼¥Á¥§¥¤¥ó¤òÀ¸À®¤¹¤ë
+     *  フィルタチェインを生成する
      *
      *  @access private
      */
@@ -990,23 +1389,22 @@ class Ethna_Controller
     {
         $this->filter_chain = array();
         foreach ($this->filter as $filter) {
-            $file = sprintf("%s/%s.%s", $this->getDirectory('filter'), $filter, $this->getExt('php'));
-            if (file_exists($file)) {
-                include_once($file);
-            }
-            if (class_exists($filter)) {
-                $this->filter_chain[] =& new $filter($this);
+            $filter_plugin =& $this->plugin->getPlugin('Filter', $filter);
+            if (Ethna::isError($filter_plugin)) {
+                continue;
             }
+
+            $this->filter_chain[] =& $filter_plugin;
         }
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó̾¤¬¼Â¹Ôµö²Ä¤µ¤ì¤Æ¤¤¤ë¤â¤Î¤«¤É¤¦¤«¤òÊÖ¤¹
+     *  アクション名が実行許可されているものかどうかを返す
      *
      *  @access private
-     *  @param  string  $action_name            ¥ê¥¯¥¨¥¹¥È¤µ¤ì¤¿¥¢¥¯¥·¥ç¥ó̾
-     *  @param  array   $default_action_name    µö²Ä¤µ¤ì¤Æ¤¤¤ë¥¢¥¯¥·¥ç¥ó̾
-     *  @return bool    true:µö²Ä false:ÉÔµö²Ä
+     *  @param  string  $action_name            リクエストされたアクション名
+     *  @param  array   $default_action_name    許可されているアクション名
+     *  @return bool    true:許可 false:不許可
      */
     function _isAcceptableActionName($action_name, $default_action_name)
     {
@@ -1023,11 +1421,11 @@ class Ethna_Controller
     }
 
     /**
-     *  »ØÄꤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó¤Î¥Õ¥©¡¼¥à¥¯¥é¥¹Ì¾¤òÊÖ¤¹(¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤Ï¹Ô¤ï¤Ê¤¤)
+     *  指定されたアクションのフォームクラス名を返す(オブジェクトの生成は行わない)
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¤Î¥Õ¥©¡¼¥à¥¯¥é¥¹Ì¾
+     *  @param  string  $action_name    アクション名
+     *  @return string  アクションのフォームクラス名
      */
     function getActionFormName($action_name)
     {
@@ -1040,38 +1438,40 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥Õ¥©¡¼¥à¥¯¥é¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥¯¥é¥¹Ì¾¤òÊÖ¤¹
+     *  アクションに対応するフォームクラス名が省略された場合のデフォルトクラス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï[¥×¥í¥¸¥§¥¯¥ÈID]_Form_[¥¢¥¯¥·¥ç¥ó̾]¤È¤Ê¤ë¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは[プロジェクトID]_Form_[アクション名]となるので好み応じてオーバライドする
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥à̾
+     *  @param  string  $action_name    アクション名
+     *  @return string  アクションフォーム名
      */
-    function getDefaultFormClass($action_name)
+    function getDefaultFormClass($action_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
-        $r = sprintf("%s_Form_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
 
         return $r;
     }
 
     /**
-     *  getDefaultFormClass()¤Ç¼èÆÀ¤·¤¿¥¯¥é¥¹Ì¾¤«¤é¥¢¥¯¥·¥ç¥ó̾¤ò¼èÆÀ¤¹¤ë
+     *  getDefaultFormClass()で取得したクラス名からアクション名を取得する
      *
-     *  getDefaultFormClass()¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤¿¾ì¹ç¡¢¤³¤Á¤é¤â¹ç¤ï¤»¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É
-     *  ¤¹¤ë¤³¤È¤ò¿ä¾©(ɬ¿Ü¤Ç¤Ï¤Ê¤¤)
+     *  getDefaultFormClass()をオーバーライドした場合、こちらも合わせてオーバーライド
+     *  することを推奨(必須ではない)
      *
      *  @access public
-     *  @param  string  $class_name     ¥Õ¥©¡¼¥à¥¯¥é¥¹Ì¾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó̾
+     *  @param  string  $class_name     フォームクラス名
+     *  @return string  アクション名
      */
     function actionFormToName($class_name)
     {
         $prefix = sprintf("%s_Form_", $this->getAppId());
         if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
-            // ÉÔÌÀ¤Ê¥¯¥é¥¹Ì¾
+            // 不明なクラス名
             return null;
         }
         $target = $match[1];
@@ -1082,15 +1482,15 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥Õ¥©¡¼¥à¥Ñ¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥Ñ¥¹Ì¾¤òÊÖ¤¹
+     *  アクションに対応するフォームパス名が省略された場合のデフォルトパス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï_getDefaultActionPath()¤ÈƱ¤¸·ë²Ì¤òÊÖ¤¹(1¥Õ¥¡¥¤¥ë¤Ë
-     *  ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤È¥Õ¥©¡¼¥à¥¯¥é¥¹¤¬µ­½Ò¤µ¤ì¤ë)¤Î¤Ç¡¢¹¥¤ß¤Ë±þ¤¸¤Æ
-     *  ¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは_getDefaultActionPath()と同じ結果を返す(1ファイルに
+     *  アクションクラスとフォームクラスが記述される)ので、好みに応じて
+     *  オーバーライドする
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  form class¤¬ÄêµÁ¤µ¤ì¤ë¥¹¥¯¥ê¥×¥È¤Î¥Ñ¥¹Ì¾
+     *  @param  string  $action_name    アクション名
+     *  @return string  form classが定義されるスクリプトのパス名
      */
     function getDefaultFormPath($action_name)
     {
@@ -1098,11 +1498,11 @@ class Ethna_Controller
     }
 
     /**
-     *  »ØÄꤵ¤ì¤¿¥¢¥¯¥·¥ç¥ó¤Î¥¯¥é¥¹Ì¾¤òÊÖ¤¹(¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤Ï¹Ô¤ï¤Ê¤¤)
+     *  指定されたアクションのクラス名を返す(オブジェクトの生成は行わない)
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó¤Î̾¾Î
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¤Î¥¯¥é¥¹Ì¾
+     *  @param  string  $action_name    アクションの名称
+     *  @return string  アクションのクラス名
      */
     function getActionClassName($action_name)
     {
@@ -1115,38 +1515,40 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥¯¥é¥¹Ì¾¤òÊÖ¤¹
+     *  アクションに対応するアクションクラス名が省略された場合のデフォルトクラス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï[¥×¥í¥¸¥§¥¯¥ÈID]_Action_[¥¢¥¯¥·¥ç¥ó̾]¤È¤Ê¤ë¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは[プロジェクトID]_Action_[アクション名]となるので好み応じてオーバライドする
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹Ì¾
+     *  @param  string  $action_name    アクション名
+     *  @return string  アクションクラス名
      */
-    function getDefaultActionClass($action_name)
+    function getDefaultActionClass($action_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
-        $r = sprintf("%s_Action_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
 
         return $r;
     }
 
     /**
-     *  getDefaultActionClass()¤Ç¼èÆÀ¤·¤¿¥¯¥é¥¹Ì¾¤«¤é¥¢¥¯¥·¥ç¥ó̾¤ò¼èÆÀ¤¹¤ë
+     *  getDefaultActionClass()で取得したクラス名からアクション名を取得する
      *
-     *  getDefaultActionClass()¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤¿¾ì¹ç¡¢¤³¤Á¤é¤â¹ç¤ï¤»¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É
-     *  ¤¹¤ë¤³¤È¤ò¿ä¾©(ɬ¿Ü¤Ç¤Ï¤Ê¤¤)
+     *  getDefaultActionClass()をオーバーライドした場合、こちらも合わせてオーバーライド
+     *  することを推奨(必須ではない)
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹Ì¾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó̾
+     *  @param  string  $class_name     アクションクラス名
+     *  @return string  アクション名
      */
     function actionClassToName($class_name)
     {
         $prefix = sprintf("%s_Action_", $this->getAppId());
         if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
-            // ÉÔÌÀ¤Ê¥¯¥é¥¹Ì¾
+            // 不明なクラス名
             return null;
         }
         $target = $match[1];
@@ -1157,13 +1559,13 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥¢¥¯¥·¥ç¥ó¥Ñ¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥Ñ¥¹Ì¾¤òÊÖ¤¹
+     *  アクションに対応するアクションパス名が省略された場合のデフォルトパス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï"foo_bar" -> "/Foo/Bar.php"¤È¤Ê¤ë¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
      *
      *  @access public
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
-     *  @return string  ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤¬ÄêµÁ¤µ¤ì¤ë¥¹¥¯¥ê¥×¥È¤Î¥Ñ¥¹Ì¾
+     *  @param  string  $action_name    アクション名
+     *  @return string  アクションクラスが定義されるスクリプトのパス名
      */
     function getDefaultActionPath($action_name)
     {
@@ -1174,11 +1576,11 @@ class Ethna_Controller
     }
 
     /**
-     *  »ØÄꤵ¤ì¤¿Á«°Ü̾¤ËÂбþ¤¹¤ë¥Ó¥å¡¼¥¯¥é¥¹Ì¾¤òÊÖ¤¹(¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤Ï¹Ô¤ï¤Ê¤¤)
+     *  指定された遷移名に対応するビュークラス名を返す(オブジェクトの生成は行わない)
      *
      *  @access public
-     *  @param  string  $forward_name   Á«°ÜÀè¤Î̾¾Î
-     *  @return string  view class¤Î¥¯¥é¥¹Ì¾
+     *  @param  string  $forward_name   遷移先の名称
+     *  @return string  view classのクラス名
      */
     function getViewClassName($forward_name)
     {
@@ -1201,7 +1603,7 @@ class Ethna_Controller
             $class_name = null;
         }
 
-        // view¤Î¥¤¥ó¥¯¥ë¡¼¥É
+        // viewのインクルード
         $this->_includeViewScript($forward_obj, $forward_name);
 
         if (is_null($class_name) == false && class_exists($class_name)) {
@@ -1221,31 +1623,33 @@ class Ethna_Controller
     }
 
     /**
-     *  Á«°Ü̾¤ËÂбþ¤¹¤ë¥Ó¥å¡¼¥¯¥é¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥¯¥é¥¹Ì¾¤òÊÖ¤¹
+     *  遷移名に対応するビュークラス名が省略された場合のデフォルトクラス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï[¥×¥í¥¸¥§¥¯¥ÈID]_View_[Á«°Ü̾]¤È¤Ê¤ë¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは[プロジェクトID]_View_[遷移名]となるので好み応じてオーバライドする
      *
      *  @access public
-     *  @param  string  $forward_name   forward̾
-     *  @return string  view class¥¯¥é¥¹Ì¾
+     *  @param  string  $forward_name   forward
+     *  @return string  view classクラス名
      */
-    function getDefaultViewClass($forward_name)
+    function getDefaultViewClass($forward_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
-        $r = sprintf("%s_View_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
 
         return $r;
     }
 
     /**
-     *  Á«°Ü̾¤ËÂбþ¤¹¤ë¥Ó¥å¡¼¥Ñ¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥Ñ¥¹Ì¾¤òÊÖ¤¹
+     *  遷移名に対応するビューパス名が省略された場合のデフォルトパス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï"foo_bar" -> "/Foo/Bar.php"¤È¤Ê¤ë¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
      *
      *  @access public
-     *  @param  string  $forward_name   forward̾
-     *  @return string  view class¤¬ÄêµÁ¤µ¤ì¤ë¥¹¥¯¥ê¥×¥È¤Î¥Ñ¥¹Ì¾
+     *  @param  string  $forward_name   forward
+     *  @return string  view classが定義されるスクリプトのパス名
      */
     function getDefaultViewPath($forward_name)
     {
@@ -1256,29 +1660,29 @@ class Ethna_Controller
     }
 
     /**
-     *  Á«°Ü̾¤ËÂбþ¤¹¤ë¥Æ¥ó¥×¥ì¡¼¥È¥Ñ¥¹Ì¾¤¬¾Êά¤µ¤ì¤¿¾ì¹ç¤Î¥Ç¥Õ¥©¥ë¥È¥Ñ¥¹Ì¾¤òÊÖ¤¹
+     *  遷移名に対応するテンプレートパス名が省略された場合のデフォルトパス名を返す
      *
-     *  ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï"foo_bar"¤È¤¤¤¦forward̾¤¬"foo/bar" + ¥Æ¥ó¥×¥ì¡¼¥È³ÈÄ¥»Ò¤È¤Ê¤ë
-     *  ¤Î¤Ç¹¥¤ß±þ¤¸¤Æ¥ª¡¼¥Ð¥é¥¤¥É¤¹¤ë
+     *  デフォルトでは"foo_bar"というforward名が"foo/bar" + テンプレート拡張子となる
+     *  ので好み応じてオーバライドする
      *
      *  @access public
-     *  @param  string  $forward_name   forward̾
-     *  @return string  forward¥Ñ¥¹Ì¾
+     *  @param  string  $forward_name   forward
+     *  @return string  forwardパス名
      */
     function getDefaultForwardPath($forward_name)
     {
         return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
     }
-    
+
     /**
-     *  ¥Æ¥ó¥×¥ì¡¼¥È¥Ñ¥¹Ì¾¤«¤éÁ«°Ü̾¤ò¼èÆÀ¤¹¤ë
+     *  テンプレートパス名から遷移名を取得する
      *
-     *  getDefaultForwardPath()¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤¿¾ì¹ç¡¢¤³¤Á¤é¤â¹ç¤ï¤»¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É
-     *  ¤¹¤ë¤³¤È¤ò¿ä¾©(ɬ¿Ü¤Ç¤Ï¤Ê¤¤)
+     *  getDefaultForwardPath()をオーバーライドした場合、こちらも合わせてオーバーライド
+     *  することを推奨(必須ではない)
      *
      *  @access public
-     *  @param  string  $forward_path   ¥Æ¥ó¥×¥ì¡¼¥È¥Ñ¥¹Ì¾
-     *  @return string  Á«°Ü̾
+     *  @param  string  $forward_path   テンプレートパス名
+     *  @return string  遷移名
      */
     function forwardPathToName($forward_path)
     {
@@ -1289,11 +1693,11 @@ class Ethna_Controller
     }
 
     /**
-     *  Á«°Ü̾¤«¤é¥Æ¥ó¥×¥ì¡¼¥È¥Õ¥¡¥¤¥ë¤Î¥Ñ¥¹Ì¾¤ò¼èÆÀ¤¹¤ë
+     *  遷移名からテンプレートファイルのパス名を取得する
      *
      *  @access private
-     *  @param  string  $forward_name   forward̾
-     *  @return string  ¥Æ¥ó¥×¥ì¡¼¥È¥Õ¥¡¥¤¥ë¤Î¥Ñ¥¹Ì¾
+     *  @param  string  $forward_name   forward
+     *  @return string  テンプレートファイルのパス名
      */
     function _getForwardPath($forward_name)
     {
@@ -1305,7 +1709,7 @@ class Ethna_Controller
         }
         $forward_obj =& $this->forward[$forward_name];
         if (isset($forward_obj['forward_path']) == false) {
-            // ¾ÊάÃÍÊäÀµ
+            // 省略値補正
             $forward_obj['forward_path'] = $this->getDefaultForwardPath($forward_name);
         }
 
@@ -1313,129 +1717,102 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Æ¥ó¥×¥ì¡¼¥È¥¨¥ó¥¸¥ó¼èÆÀ¤¹¤ë(¸½ºß¤Ïsmarty¤Î¤ßÂбþ)
+     *  レンダラを取得する(getTemplateEngine()はそのうち廃止されgetRenderer()に統合される予定)
      *
      *  @access public
-     *  @return object  Smarty  ¥Æ¥ó¥×¥ì¡¼¥È¥¨¥ó¥¸¥ó¥ª¥Ö¥¸¥§¥¯¥È
+     *  @return object  Ethna_Renderer  レンダラオブジェクト
      */
-    function &getTemplateEngine()
+    function &getRenderer()
     {
-        $smarty =& new Smarty();
-        $smarty->template_dir = $this->getTemplatedir();
-        $smarty->compile_dir = $this->getDirectory('template_c');
-        $smarty->compile_id = md5($smarty->template_dir);
-
-        // °ì±þ¤¬¤ó¤Ð¤Ã¤Æ¤ß¤ë
-        if (@is_dir($smarty->compile_dir) == false) {
-            mkdir($smarty->compile_dir, 0755);
-        }
-        $smarty->plugins_dir = $this->getDirectory('plugins');
-
-        // default modifiers
-        $smarty->register_modifier('number_format', 'smarty_modifier_number_format');
-        $smarty->register_modifier('strftime', 'smarty_modifier_strftime');
-        $smarty->register_modifier('count', 'smarty_modifier_count');
-        $smarty->register_modifier('join', 'smarty_modifier_join');
-        $smarty->register_modifier('filter', 'smarty_modifier_filter');
-        $smarty->register_modifier('unique', 'smarty_modifier_unique');
-        $smarty->register_modifier('wordwrap_i18n', 'smarty_modifier_wordwrap_i18n');
-        $smarty->register_modifier('truncate_i18n', 'smarty_modifier_truncate_i18n');
-        $smarty->register_modifier('i18n', 'smarty_modifier_i18n');
-        $smarty->register_modifier('checkbox', 'smarty_modifier_checkbox');
-        $smarty->register_modifier('select', 'smarty_modifier_select');
-        $smarty->register_modifier('form_value', 'smarty_modifier_form_value');
-
-        // user defined modifiers
-        foreach ($this->smarty_modifier_plugin as $modifier) {
-            $name = str_replace('smarty_modifier_', '', $modifier);
-            $smarty->register_modifier($name, $modifier);
-        }
-
-        // default functions
-        $smarty->register_function('is_error', 'smarty_function_is_error');
-        $smarty->register_function('message', 'smarty_function_message');
-        $smarty->register_function('uniqid', 'smarty_function_uniqid');
-        $smarty->register_function('select', 'smarty_function_select');
-        $smarty->register_function('checkbox_list', 'smarty_function_checkbox_list');
-
-        // user defined functions
-        foreach ($this->smarty_function_plugin as $function) {
-            
-            if ( !is_array($function) ) {
-                $name = str_replace('smarty_function_', '', $function);
-                $smarty->register_function($name, $function);
-            } else {
-                $smarty->register_function($function[1], $function);
-            }
-
-        }
-
-        // user defined prefilters
-        foreach ($this->smarty_prefilter_plugin as $prefilter) {
-            $smarty->register_prefilter($prefilter);
-        }
+        $_ret_object =& $this->getTemplateEngine();
+        return $_ret_object;
+    }
 
-        // user defined postfilters
-        foreach ($this->smarty_postfilter_plugin as $postfilter) {
-            $smarty->register_postfilter($postfilter);
+    /**
+     *  テンプレートエンジン取得する
+     *
+     *  @access public
+     *  @return object  Ethna_Renderer  レンダラオブジェクト
+     *  @obsolete
+     */
+    function &getTemplateEngine()
+    {
+        if (is_object($this->renderer)) {
+            return $this->renderer;
         }
 
-        // user defined outputfilters
-        foreach ($this->smarty_outputfilter_plugin as $outputfilter) {
-            $smarty->register_outputfilter($outputfilter);
-        }
+        $this->renderer =& $this->class_factory->getObject('renderer');
 
-        $this->_setDefaultTemplateEngine($smarty);
+        //テンプレートエンジンのデフォルトの設定
+        $this->_setDefaultTemplateEngine($this->renderer);
+        // }}}
 
-        return $smarty;
+        return $this->renderer;
     }
 
     /**
-     *  ¥Æ¥ó¥×¥ì¡¼¥È¥¨¥ó¥¸¥ó¤Î¥Ç¥Õ¥©¥ë¥È¾õÂÖ¤òÀßÄꤹ¤ë
+     *  テンプレートエンジンのデフォルト状態を設定する
      *
      *  @access protected
-     *  @param  object  Smarty  $smarty ¥Æ¥ó¥×¥ì¡¼¥È¥¨¥ó¥¸¥ó¥ª¥Ö¥¸¥§¥¯¥È
+     *  @param  object  Ethna_Renderer  レンダラオブジェクト
+     *  @obsolete
      */
-    function _setDefaultTemplateEngine(&$smarty)
+    function _setDefaultTemplateEngine(&$renderer)
     {
     }
 
     /**
-     *  »ÈÍѸÀ¸ì¤òÀßÄꤹ¤ë
-     *
-     *  ¾­Íè¤Ø¤Î³ÈÄ¥¤Î¤¿¤á¤Î¤ß¤Ë¸ºß¤·¤Æ¤¤¤Þ¤¹¡£¸½ºß¤ÏÆä˥ª¡¼¥Ð¡¼¥é¥¤¥É¤ÎɬÍפϤ¢¤ê¤Þ¤»¤ó¡£
+     *  使用言語、ロケールを設定する
+     *  条件によって使用言語、ロケールを切り替えたい場合は、
+     *  このメソッドをオーバーライドする。
      *
      *  @access protected
-     *  @param  string  $language           ¸À¸ìÄêµÁ(LANG_JA, LANG_EN...)
-     *  @param  string  $system_encoding    ¥·¥¹¥Æ¥à¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°Ì¾
-     *  @param  string  $client_encoding    ¥¯¥é¥¤¥¢¥ó¥È¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°
+     *  @param  string  $locale             ロケール名(ja_JP, en_US等)
+     *                                      (ll_cc の形式。ll = 言語コード cc = 国コード)
+     *  @param  string  $system_encoding    システムエンコーディング名
+     *  @param  string  $client_encoding    クライアントエンコーディング(テンプレートのエンコーディングと考えれば良い)
+     *  @see    http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
+     *  @see    Ethna_Controller#_getDefaultLanguage
      */
-    function _setLanguage($language, $system_encoding = null, $client_encoding = null)
+    function _setLanguage($locale, $system_encoding = null, $client_encoding = null)
     {
-        $this->language = $language;
+        $this->locale = $locale;
         $this->system_encoding = $system_encoding;
         $this->client_encoding = $client_encoding;
 
+        //   $this->locale, $this->client_encoding を書き換えた場合は
+        //   必ず Ethna_I18N クラスの setLanguageメソッドも呼ぶこと!
+        //   さもないとカタログその他が再ロードされない!
         $i18n =& $this->getI18N();
-        $i18n->setLanguage($language, $system_encoding, $client_encoding);
+        $i18n->setLanguage($locale, $system_encoding, $client_encoding);
     }
 
     /**
-     *  ¥Ç¥Õ¥©¥ë¥È¾õÂ֤ǤλÈÍѸÀ¸ì¤ò¼èÆÀ¤¹¤ë
+     *  デフォルト状態での使用言語を取得する
+     *  外部に出力されるEthnaのエラーメッセージ等のエンコーディングを
+     *  切り替えたい場合は、このメソッドをオーバーライドする。
      *
      *  @access protected
-     *  @return array   »ÈÍѸÀ¸ì,¥·¥¹¥Æ¥à¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°Ì¾,¥¯¥é¥¤¥¢¥ó¥È¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°Ì¾
+     *  @return array   ロケール名(e.x ja_JP, en_US 等),
+     *                  システムエンコーディング名,
+     *                  クライアントエンコーディング名
+     *                  (= テンプレートのエンコーディングと考えてよい) の配列
+     *                  (ロケール名は ll_cc の形式。ll = 言語コード cc = 国コード)
+     *
+     *  WARNING!! : クライアントエンコーディング名が、フレームワークの内部エンコーデ
+     *              ィングとして設定されます。つまり、クライアントエンコーディングで
+     *              ブラウザからの入力は入ってくるものと想定しています!
      */
     function _getDefaultLanguage()
     {
-        return array(LANG_JA, null, null);
+        return array('ja_JP', 'UTF-8', 'UTF-8');
     }
 
     /**
-     *  ¥Ç¥Õ¥©¥ë¥È¾õÂ֤ǤΥ²¡¼¥È¥¦¥§¥¤¤ò¼èÆÀ¤¹¤ë
+     *  デフォルト状態でのゲートウェイを取得する
      *
      *  @access protected
-     *  @return int     ¥²¡¼¥È¥¦¥§¥¤ÄêµÁ(GATEWAY_WWW, GATEWAY_CLI...)
+     *  @return int     ゲートウェイ定義(GATEWAY_WWW, GATEWAY_CLI...)
      */
     function _getDefaultGateway($gateway)
     {
@@ -1446,25 +1823,74 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Þ¥Í¡¼¥¸¥ã¥¯¥é¥¹Ì¾¤ò¼èÆÀ¤¹¤ë
+     *  ゲートウェイに対応したクラス名のプレフィクスを取得する
      *
      *  @access public
-     *  @param  string  $name   ¥Þ¥Í¡¼¥¸¥ã̾
-     *  @return string  ¥Þ¥Í¡¼¥¸¥ã¥¯¥é¥¹Ì¾
+     *  @param  string  $gateway    ゲートウェイ
+     *  @return string  ゲートウェイクラスプレフィクス
+     */
+    function _getGatewayPrefix($gateway = null)
+    {
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+            $prefix = '';
+            break;
+        case GATEWAY_CLI:
+            $prefix = 'Cli';
+            break;
+        case GATEWAY_XMLRPC:
+            $prefix = 'Xmlrpc';
+            break;
+        default:
+            $prefix = '';
+            break;
+        }
+
+        return $prefix;
+    }
+
+    /**
+     *  マネージャクラス名を取得する
+     *
+     *  @access public
+     *  @param  string  $name   マネージャキー
+     *  @return string  マネージャクラス名
      */
     function getManagerClassName($name)
     {
-        return sprintf('%s_%sManager', $this->getAppId(), ucfirst($name));
+        //   アプリケーションIDと、渡された名前のはじめを大文字にして、
+        //   組み合わせたものが返される
+        $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
+        return sprintf('%s_%sManager', $this->getAppId(), ucfirst($manager_id));
+    }
+
+    /**
+     *  アプリケーションオブジェクトクラス名を取得する
+     *
+     *  @access public
+     *  @param  string  $name   アプリケーションオブジェクトキー
+     *  @return string  マネージャクラス名
+     */
+    function getObjectClassName($name)
+    {
+        //  引数のはじめの一文字目と、アンダーバー直後の
+        //  1文字を必ず大文字にする。アンダーバーは削除される。
+        $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
+
+        //  $name に foo_bar を渡し、AppID が Hogeの場合
+        //  [Appid]_FooBar が返される
+        return sprintf('%s_%s', $this->getAppId(), $name);
     }
 
     /**
-     *  ¥¢¥¯¥·¥ç¥ó¥¹¥¯¥ê¥×¥È¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë
+     *  アクションスクリプトをインクルードする
      *
-     *  ¤¿¤À¤·¡¢¥¤¥ó¥¯¥ë¡¼¥É¤·¤¿¥Õ¥¡¥¤¥ë¤Ë¥¯¥é¥¹¤¬Àµ¤·¤¯ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤ÏÊݾڤ·¤Ê¤¤
+     *  ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
      *
      *  @access private
-     *  @param  array   $action_obj     ¥¢¥¯¥·¥ç¥óÄêµÁ
-     *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
+     *  @param  array   $action_obj     アクション定義
+     *  @param  string  $action_name    アクション名
      */
     function _includeActionScript($action_obj, $action_name)
     {
@@ -1472,9 +1898,9 @@ class Ethna_Controller
 
         $action_dir = $this->getActiondir();
 
-        // class_path°À­¥Á¥§¥Ã¥¯
+        // class_pathå±\9eæ\80§ã\83\81ã\82§ã\83\83ã\82¯
         if (isset($action_obj['class_path'])) {
-            // ¥Õ¥ë¥Ñ¥¹»ØÄꥵ¥Ý¡¼¥È
+            // フルパス指定サポート
             $tmp_path = $action_obj['class_path'];
             if (Ethna_Util::isAbsolute($tmp_path) == false) {
                 $tmp_path = $action_dir . $tmp_path;
@@ -1483,32 +1909,26 @@ class Ethna_Controller
             if (file_exists($tmp_path) == false) {
                 $this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
             } else {
-                include_once($tmp_path);
+                include_once $tmp_path;
                 $class_path = $tmp_path;
             }
         }
 
-        // ¥Ç¥Õ¥©¥ë¥È¥Á¥§¥Ã¥¯
+        // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\83\81ã\82§ã\83\83ã\82¯
         if (is_null($class_path)) {
             $class_path = $this->getDefaultActionPath($action_name);
             if (file_exists($action_dir . $class_path)) {
-                include_once($action_dir . $class_path);
+                include_once $action_dir . $class_path;
             } else {
                 $this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
-                $class_path = null;
+                return;
             }
         }
-        
-        // Á´¥Õ¥¡¥¤¥ë¥¤¥ó¥¯¥ë¡¼¥É
-        if (is_null($class_path)) {
-            $this->_includeDirectory($this->getActiondir());
-            return;
-        }
 
-        // form_path°À­¥Á¥§¥Ã¥¯
+        // form_pathå±\9eæ\80§ã\83\81ã\82§ã\83\83ã\82¯
         if (isset($action_obj['form_path'])) {
-            // ¥Õ¥ë¥Ñ¥¹»ØÄꥵ¥Ý¡¼¥È
-            $tmp_path = $action_obj['class_path'];
+            // フルパス指定サポート
+            $tmp_path = $action_obj['form_path'];
             if (Ethna_Util::isAbsolute($tmp_path) == false) {
                 $tmp_path = $action_dir . $tmp_path;
             }
@@ -1519,19 +1939,19 @@ class Ethna_Controller
             if (file_exists($tmp_path) == false) {
                 $this->logger->log(LOG_WARNING, 'form_path file not found [%s] -> try default', $tmp_path);
             } else {
-                include_once($tmp_path);
+                include_once $tmp_path;
                 $form_path = $tmp_path;
             }
         }
 
-        // ¥Ç¥Õ¥©¥ë¥È¥Á¥§¥Ã¥¯
+        // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\83\81ã\82§ã\83\83ã\82¯
         if (is_null($form_path)) {
             $form_path = $this->getDefaultFormPath($action_name);
             if ($form_path == $class_path) {
                 return;
             }
             if (file_exists($action_dir . $form_path)) {
-                include_once($action_dir . $form_path);
+                include_once $action_dir . $form_path;
             } else {
                 $this->logger->log(LOG_DEBUG, 'default form file not found [%s] -> maybe falling back to default form class', $form_path);
             }
@@ -1539,21 +1959,21 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Ó¥å¡¼¥¹¥¯¥ê¥×¥È¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë
+     *  ビュースクリプトをインクルードする
      *
-     *  ¤¿¤À¤·¡¢¥¤¥ó¥¯¥ë¡¼¥É¤·¤¿¥Õ¥¡¥¤¥ë¤Ë¥¯¥é¥¹¤¬Àµ¤·¤¯ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤ÏÊݾڤ·¤Ê¤¤
+     *  ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
      *
      *  @access private
-     *  @param  array   $forward_obj    Á«°ÜÄêµÁ
-     *  @param  string  $forward_name   Á«°Ü̾
+     *  @param  array   $forward_obj    遷移定義
+     *  @param  string  $forward_name   遷移名
      */
     function _includeViewScript($forward_obj, $forward_name)
     {
         $view_dir = $this->getViewdir();
 
-        // view_path°À­¥Á¥§¥Ã¥¯
+        // view_pathå±\9eæ\80§ã\83\81ã\82§ã\83\83ã\82¯
         if (isset($forward_obj['view_path'])) {
-            // ¥Õ¥ë¥Ñ¥¹»ØÄꥵ¥Ý¡¼¥È
+            // フルパス指定サポート
             $tmp_path = $forward_obj['view_path'];
             if (Ethna_Util::isAbsolute($tmp_path) == false) {
                 $tmp_path = $view_dir . $tmp_path;
@@ -1562,15 +1982,15 @@ class Ethna_Controller
             if (file_exists($tmp_path) == false) {
                 $this->logger->log(LOG_WARNING, 'view_path file not found [%s] -> try default', $tmp_path);
             } else {
-                include_once($tmp_path);
+                include_once $tmp_path;
                 return;
             }
         }
 
-        // ¥Ç¥Õ¥©¥ë¥È¥Á¥§¥Ã¥¯
+        // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\83\81ã\82§ã\83\83ã\82¯
         $view_path = $this->getDefaultViewPath($forward_name);
         if (file_exists($view_dir . $view_path)) {
-            include_once($view_dir . $view_path);
+            include_once $view_dir . $view_path;
             return;
         } else {
             $this->logger->log(LOG_DEBUG, 'default view file not found [%s]', $view_path);
@@ -1579,7 +1999,7 @@ class Ethna_Controller
     }
 
     /**
-     *  ¥Ç¥£¥ì¥¯¥È¥ê°Ê²¼¤ÎÁ´¤Æ¤Î¥¹¥¯¥ê¥×¥È¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë
+     *  ディレクトリ以下の全てのスクリプトをインクルードする
      *
      *  @access private
      */
@@ -1601,19 +2021,19 @@ class Ethna_Controller
                 if (substr($file, -$ext_len, $ext_len) != $ext) {
                     continue;
                 }
-                include_once("$dir/$file");
+                include_once $dir . '/' . $file;
             }
         }
         closedir($dh);
     }
 
     /**
-     *  ÀßÄê¥Õ¥¡¥¤¥ë¤ÎDSNÄêµÁ¤«¤é»ÈÍѤ¹¤ë¥Ç¡¼¥¿¤òºÆ¹½ÃÛ¤¹¤ë(¥¹¥ì¡¼¥Ö¥¢¥¯¥»¥¹Ê¬´ôÅù)
+     *  設定ファイルのDSN定義から使用するデータを再構築する(スレーブアクセス分岐等)
      *
-     *  DSN¤ÎÄêµÁÊýË¡(¥Ç¥Õ¥©¥ë¥È:ÀßÄê¥Õ¥¡¥¤¥ë)¤òÊѤ¨¤¿¤¤¾ì¹ç¤Ï¤³¤³¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
+     *  DSNの定義方法(デフォルト:設定ファイル)を変えたい場合はここをオーバーライドする
      *
      *  @access protected
-     *  @return array   DSNÄêµÁ(array('DB¥­¡¼1' => 'dsn1', 'DB¥­¡¼2' => 'dsn2', ...))
+     *  @return array   DSNå®\9a義(array('DBã\82­ã\83¼1' => 'dsn1', 'DBã\82­ã\83¼2' => 'dsn2', ...))
      */
     function _prepareDSN()
     {
@@ -1626,7 +2046,7 @@ class Ethna_Controller
             }
             $dsn = $this->config->get($config_key);
             if (is_array($dsn)) {
-                // ¼ïÊÌ1¤Ä¤Ë¤Ä¤­Ê£¿ôDSN¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ï¥¢¥¯¥»¥¹Ê¬´ô
+                // 種別1つにつき複数DSNが定義されている場合はアクセス分岐
                 $dsn = $this->_selectDSN($key, $dsn);
             }
             $r[$key] = $dsn;
@@ -1635,14 +2055,14 @@ class Ethna_Controller
     }
 
     /**
-     *  DSN¤Î¥¢¥¯¥»¥¹Ê¬´ô¤ò¹Ô¤¦
-     *  
-     *  ¥¹¥ì¡¼¥Ö¥µ¡¼¥Ð¤Ø¤Î¿¶Ê¬¤±½èÍý(¥Ç¥Õ¥©¥ë¥È:¥é¥ó¥À¥à)¤òÊѹ¹¤·¤¿¤¤¾ì¹ç¤Ï¤³¤Î¥á¥½¥Ã¥É¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤¹¤ë
+     *  DSNのアクセス分岐を行う
+     *
+     *  スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする
      *
      *  @access protected
-     *  @param  string  $type       DB¼ïÊÌ
-     *  @param  array   $dsn_list   DSN°ìÍ÷
-     *  @return string  ÁªÂò¤µ¤ì¤¿DSN
+     *  @param  string  $type       DB種別
+     *  @param  array   $dsn_list   DSN一覧
+     *  @return string  選択されたDSN
      */
     function _selectDSN($type, $dsn_list)
     {
@@ -1650,18 +2070,18 @@ class Ethna_Controller
             return $dsn_list;
         }
 
-        // ¥Ç¥Õ¥©¥ë¥È:¥é¥ó¥À¥à
+        // デフォルト:ランダム
         list($usec, $sec) = explode(' ', microtime());
         mt_srand($sec + ((float) $usec * 100000));
         $n = mt_rand(0, count($dsn_list)-1);
-        
+
         return $dsn_list[$n];
     }
 
     /**
-     *  Ethna¥Þ¥Í¡¼¥¸¥ã¤òÀßÄꤹ¤ë
+     *  Ethnaマネージャを設定する
      *
-     *  ÉÔÍפʾì¹ç¤Ï¶õ¤Î¥á¥½¥Ã¥É¤È¤·¤Æ¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤Æ¤â¤è¤¤
+     *  不要な場合は空のメソッドとしてオーバーライドしてもよい
      *
      *  @access protected
      */
@@ -1671,14 +2091,14 @@ class Ethna_Controller
             return;
         }
 
-        include_once(ETHNA_BASE . '/class/Ethna_InfoManager.php');
-        
+        require_once ETHNA_BASE . '/class/Ethna_InfoManager.php';
+
         // see if we have simpletest
         if (file_exists_ex('simpletest/unit_tester.php', true)) {
-            include_once(ETHNA_BASE . '/class/Ethna_UnitTestManager.php');
+            require_once ETHNA_BASE . '/class/Ethna_UnitTestManager.php';
         }
 
-        // actionÀßÄê
+        // action設定
         $this->action['__ethna_info__'] = array(
             'form_name' =>  'Ethna_Form_Info',
             'form_path' =>  sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
@@ -1686,15 +2106,15 @@ class Ethna_Controller
             'class_path' => sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
         );
 
-        // forwardÀßÄê
+        // forward設定
         $this->forward['__ethna_info__'] = array(
             'forward_path'  => sprintf('%s/tpl/info.tpl', ETHNA_BASE),
             'view_name'     => 'Ethna_View_Info',
             'view_path'     => sprintf('%s/class/View/Ethna_View_Info.php', ETHNA_BASE),
         );
-        
-        
-        // actionÀßÄê
+
+
+        // action設定
         $this->action['__ethna_unittest__'] = array(
             'form_name' =>  'Ethna_Form_UnitTest',
             'form_path' =>  sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
@@ -1702,7 +2122,7 @@ class Ethna_Controller
             'class_path' => sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
         );
 
-        // forwardÀßÄê
+        // forward設定
         $this->forward['__ethna_unittest__'] = array(
             'forward_path'  => sprintf('%s/tpl/unittest.tpl', ETHNA_BASE),
             'view_name'     => 'Ethna_View_UnitTest',
@@ -1712,10 +2132,47 @@ class Ethna_Controller
     }
 
     /**
-     *  CLI¼Â¹ÔÃæ¥Õ¥é¥°¤ò¼èÆÀ¤¹¤ë
+     *  Ethnaマネージャが実行可能かをチェックする
+     *
+     *  Ethnaマネージャを実行するよう指示されているにも関わらず、
+     *  debug が trueでない場合は実行を停止する。
+     *
+     *  @access private
+     */
+    function _ethnaManagerEnabledCheck($action_name)
+    {
+        if ($this->config->get('debug') == false
+         && ($action_name == '__ethna_info__' || $action_name == '__ethna_unittest__')) {
+            $this->ethnaManagerCheckErrorMsg($action_name);
+            exit(0);
+        }
+    }
+
+    /**
+     *  Ethnaマネージャが実行不能な場合のエラーメッセージを
+     *  表示する。運用上の都合でこのメッセージを出力したくない
+     *  場合は、このメソッドをオーバーライドせよ
+     *
+     *  @access protected
+     */
+     function ethnaManagerCheckErrorMsg($action_name)
+     {
+         $appid = strtolower($this->getAppId());
+         $run_action = ($action_name == '__ethna_info__')
+                     ? ' show Application Info List '
+                     : ' run Unit Test ';
+         echo "Ethna cannot {$run_action} under your application setting.<br>";
+         echo "HINT: You must set {$appid}/etc/{$appid}-ini.php debug setting 'true'.<br>";
+         echo "<br>";
+         echo "In {$appid}-ini.php, please set as follows :<br><br>";
+         echo "\$config = array ( 'debug' => true, );";
+     }
+
+    /**
+     *  CLI実行中フラグを取得する
      *
      *  @access public
-     *  @return bool    CLI¼Â¹ÔÃæ¥Õ¥é¥°
+     *  @return bool    CLIå®\9fè¡\8c中ã\83\95ã\83©ã\82°
      *  @obsolete
      */
     function getCLI()
@@ -1724,10 +2181,10 @@ class Ethna_Controller
     }
 
     /**
-     *  CLI¼Â¹ÔÃæ¥Õ¥é¥°¤òÀßÄꤹ¤ë
+     *  CLI実行中フラグを設定する
      *
      *  @access public
-     *  @param  bool    CLI¼Â¹ÔÃæ¥Õ¥é¥°
+     *  @param  bool    CLIå®\9fè¡\8c中ã\83\95ã\83©ã\82°
      *  @obsolete
      */
     function setCLI($cli)
@@ -1736,4 +2193,23 @@ class Ethna_Controller
     }
 }
 // }}}
+
+/**
+ *  XMLRPCゲートウェイのスタブクラス
+ *
+ *  @access     public
+ */
+function _Ethna_XmlrpcGateway($method_stub, $param)
+{
+    $ctl =& Ethna_Controller::getInstance();
+    $method = $ctl->getXmlrpcMethodName();
+    $r = $ctl->trigger_XMLRPC($method, $param);
+    if (Ethna::isError($r)) {
+        return array(
+            'faultCode' => $r->getCode(),
+            'faultString' => $r->getMessage(),
+        );
+    }
+    return $r;
+}
 ?>