    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.servlet;
    017
    018import java.io.File;
    019import java.io.IOException;
    020import java.io.PrintWriter;
    021import java.lang.reflect.Field;
    022import java.net.URL;
    023import java.util.Enumeration;
    024import java.util.Map;
    025import java.util.jar.JarEntry;
    026import java.util.jar.JarFile;
    027
    028import javax.servlet.ServletContext;
    029import javax.servlet.ServletException;
    030import javax.servlet.http.HttpServlet;
    031import javax.servlet.http.HttpServletRequest;
    032import javax.servlet.http.HttpServletResponse;
    033import javax.servlet.http.HttpSession;
    034
    035import org.opengion.fukurou.db.ConnectionFactory;
    036import org.opengion.fukurou.util.Attributes;
    037import org.opengion.fukurou.util.HybsEntry;
    038import org.opengion.fukurou.util.StringUtil;
    039import org.opengion.fukurou.util.Closer ;                               // 5.5.2.6 (2012/05/25)
    040import org.opengion.hayabusa.common.BuildNumber;
    041import org.opengion.hayabusa.common.HybsSystem;
    042import org.opengion.hayabusa.common.SystemManager;
    043import org.opengion.hayabusa.common.SystemParameter;
    044import org.opengion.hayabusa.common.UserSummary;
    045import org.opengion.hayabusa.resource.ResourceFactory;
    046import org.opengion.hayabusa.resource.UserInfo;
    047
    048/**
    049 * サーバー管理情報を取得するAdminサーブレットです。
    050 *
    051 * 引数(URL)に応じて、サーバーの状態結果を返します。
    052 * 一般には、http://サーバー:ポート/システムID/jsp/admin?COMMAND=コマンド の
    053 * 形式のURL でアクセスします。
    054 *
    055 *  ・COMMAND=infomation
    056 *     【サーバー情報】
    057 *        ＯＳ情報      = Windows 7 Service Pack 1
    058 *        サーバー名    = 10374232-0004 ( 172.27.26.192 )
    059 *        サーブレット  = Apache Tomcat/7.0.42
    060 *        TOMCAT_HOME   = C:/opengionV6/uap/bin//../../apps/tomcat7.0.42
    061 *        JDKバージョン = Java HotSpot(TM) Server VM 23.25-b01
    062 *        JAVA_HOME     = C:/opengionV6/apps/jdk170u25/jre
    063 *
    064 *     【実行環境】
    065 *        REAL_PATH     = C:/opengionV6/uap/webapps/gf/
    066 *        バージョンNo  = 6.0.0.0 Release6 Builds (2013233)
    067 *        作成日時      = 2013/08/21 14:57:29
    068 *
    069 *     【ログイン情報】
    070 *        ログイン人数  = 2 名 ( 明細情報 )
    071 *
    072 *     【メモリ情報】
    073 *        空きメモリ    = 15977 [KByte]
    074 *        合計メモリ    = 32448 [KByte]
    075 *        使用率        = 50 [％]
    076 *
    077 *  ・COMMAND=close
    078 *       リソース情報のキャッシュを全てクリアします。
    079 *
    080 *  ・COMMAND=loginUser
    081 *       現在のログインユーザーの明細情報を表示します。
    082 *       SORT=[JNAME,ID,ROLES,IPADDRESS,LOGINTIME] ソートキー
    083 *       DIREC=[true,false] true:昇順/false:降順
    084 *
    085 *  ・COMMAND=plugin
    086 *       現在のプラグインのバージョン情報を表示します。
    087 *
    088 *  ・COMMAND=systemResource
    089 *       現在のシステムリソースの設定情報を表示します。
    090 *
    091 *  ・COMMAND=AccessStop
    092 *       アクセスストップフィルターの制御(停止、許可)を行います。
    093 *
    094 * @og.rev 3.5.3.0 (2003/10/27) Admin JSP を Servlet化して、エンジンと共に供給します。
    095 * @og.rev 4.0.0.0 (2005/08/31) プラグインのバージョン情報の表示機能を追加
    096 * @og.group その他機能
    097 *
    098 * @version  4.0
    099 * @author   Kazuhiko Hasegawa
    100 * @since    JDK5.0,
    101 */
    102public final class HybsAdmin extends HttpServlet {
    103        private static final long serialVersionUID = 4000 ;     // 4.0.0 (2005/01/31)
    104
    105        private static final String CR = HybsSystem.CR ;
    106
    107        private static final String JSP = HybsSystem.sys( "JSP" );      // jspフォルダの正規パス
    108
    109        private static final String HEADER =
    110                "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"                                                                                             + CR +
    111                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""                                                   + CR +
    112                "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"                                                   + CR +
    113                "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"                                                                                  + CR +
    114                "<head>"                                                                                                                                                                  + CR +
    115                "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"                           + CR +
    116                "    <meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />"                                             + CR +
    117                "    <link rel=\"stylesheet\" href=\"" + JSP + "/common/default.css\" type=\"text/css\" />"       + CR +
    118                "    <link rel=\"stylesheet\" href=\"" + JSP + "/custom/custom.css\" type=\"text/css\" />"                                + CR +
    119                "    <title>Hybs Admin</title>"                                                                                                                             + CR +
    120                "</head>"                                                                                                                                                                 + CR;
    121
    122        // 3.5.3.1 (2003/10/31) User情報のテーブルの設定を、システムリソース より行う。
    123        private static final String TABLE_HEADER = getTableHeaderTag() ;
    124
    125        private static final String OS_INFO      = HybsSystem.sys( "OS_INFO"      );            // Windows 7 Service Pack 1
    126        private static final String SERVER_INFO  = HybsSystem.sys( "SERVER_INFO"  );            // 10374232-0004 ( 200.1.50.239 )
    127        private static final String SERVLET_INFO = HybsSystem.sys( "SERVLET_INFO" );            // Apache Tomcat/7.0.39
    128        private static final String REAL_PATH    = HybsSystem.sys( "REAL_PATH"    );            // C:/opengion/uap/webapps/gf/
    129//      private static final String TOMCAT_WORK  = HybsSystem.sys( "TOMCAT_WORK"  );            // 5.6.7.3 (2013/08/23) TOMCAT_HOME に置き換え、廃止
    130        private static final String TOMCAT_HOME  = HybsSystem.sys( "TOMCAT_HOME"  );            // C:/opengion/apps/tomcat5.5.17
    131        private static final String JDK_INFO     = HybsSystem.sys( "JDK_INFO"     );            // Java HotSpot(TM) Server VM 23.25-b01
    132        private static final String JAVA_HOME    = HybsSystem.sys( "JAVA_HOME"    );            // C:/opengion/apps/jdk170u25/jre
    133        private static final String ENGINE_INFO  = HybsSystem.sys( "ENGINE_INFO"  );            // 5.6.6.0 Release5 Builds (2013182)
    134
    135        /**
    136         * GET メソッドが呼ばれたときに実行します。
    137         *
    138         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    139         * @og.rev 3.5.4.1 (2003/12/01) getAdminLink() メソッドを追加
    140         * @og.rev 5.9.1.0 (2015/10/02) UserInfoセット機能追加
    141         *
    142         * @param       req     HttpServletRequestオブジェクト
    143         * @param       res     HttpServletResponseオブジェクト
    144         *
    145         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
    146         * @throws IOException 入出力エラーが発生したとき
    147         */
    148        @Override
    149        public void doGet( final HttpServletRequest req, final HttpServletResponse res)
    150                                                                throws ServletException, IOException {
    151
    152                res.setContentType( "text/html; charset=UTF-8" );
    153                PrintWriter out = res.getWriter();
    154
    155                String command = req.getParameter( "COMMAND" );
    156
    157                out.println( HEADER );
    158                out.println("<body>");
    159
    160                out.print("<h2>");
    161                out.print( req.getServerName() );
    162                out.print( ":" );
    163                out.print( req.getServerPort() );
    164                out.print( req.getContextPath() );
    165                out.println("</h2>");
    166
    167                if( "infomation".equalsIgnoreCase( command ) ) {
    168                        out.print( getInfomation() );
    169                }
    170                else if( "close".equalsIgnoreCase( command ) ) {
    171                        out.print( getCloseMessage( req.getSession() ) );
    172                }
    173                else if( "loginUser".equalsIgnoreCase( command ) ) {
    174                        String sort  = req.getParameter( "sort" );
    175                        String direc = req.getParameter( "direc" );
    176                        boolean dir = (direc == null) ? true :  Boolean.valueOf( direc ).booleanValue();
    177                        out.print( getLoginUser(sort,dir) );
    178                }
    179                else if( "plugin".equalsIgnoreCase( command ) ) {
    180                        out.print( getPlugInInfo() );
    181                }
    182                else if( "taglib".equalsIgnoreCase( command ) ) {
    183                        out.print( getTaglibInfo() );
    184                }
    185                else if( "systemResource".equalsIgnoreCase( command ) ) {
    186                        out.print( getSystemResource() );
    187                }
    188                else if( "AccessStop".equalsIgnoreCase( command ) ) {
    189                        out.print( getAccessStop() );
    190                }
    191                else if( "UserInfo".equalsIgnoreCase( command ) ){ // 5.9.1.0 (2015/10/02)
    192                        out.print( setUserinfo( req ) );
    193                }
    194                else {
    195                        out.print( getAdminLink() );            // 3.5.4.1 (2003/12/01) 追加
    196                }
    197
    198                out.println("</body></html>");
    199        }
    200
    201        /**
    202         * infomation 情報を作成します。
    203         *
    204         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    205         * @og.rev 5.6.7.3 (2013/08/23) TOMCAT_WORKは、TOMCAT_HOME に置き換えます。
    206         *
    207         * @return      infomation情報
    208         */
    209        private String getInfomation() {
    210                // 4.0.0 (2005/01/31) ログイン数の取得方法の変更。
    211                int loginCount = SystemManager.getRunningCount() ;
    212
    213                int freeMemory  = (int)( Runtime.getRuntime().freeMemory()/1024 ) ;
    214                int totalMemory = (int)( Runtime.getRuntime().totalMemory()/1024 );
    215                int useMemoryRatio = (((totalMemory - freeMemory) * 100 )/totalMemory) ;
    216
    217                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    218
    219                rtn.append( "<table border = \"0px\" >" ).append( CR );
    220                tableTr1( rtn,"サーバー情報" );
    221                tableTr( rtn,"ＯＳ情報"             , OS_INFO               );
    222                tableTr( rtn,"サーバー名"    , SERVER_INFO   );
    223                tableTr( rtn,"サーブレット"   , SERVLET_INFO  );
    224//              tableTr( rtn,"TOMCAT_WORK"      , TOMCAT_WORK   );              // 5.6.7.3 (2013/08/23) TOMCAT_HOME に置き換え、廃止
    225                tableTr( rtn,"TOMCAT_HOME"      , TOMCAT_HOME   );              // 5.6.7.3 (2013/08/23)
    226                tableTr( rtn,"JDKバージョン", JDK_INFO               );
    227                tableTr( rtn,"JAVA_HOME"        , JAVA_HOME             );
    228
    229                tableTr1( rtn,"実行環境" );
    230                tableTr( rtn,"REAL_PATH"        , REAL_PATH             );
    231                tableTr( rtn,"バージョンNo"  , ENGINE_INFO   );
    232                tableTr( rtn,"作成日時"             , BuildNumber.TIMESTAMP );
    233
    234                tableTr1( rtn,"ログイン情報" );
    235                tableTr( rtn,"ログイン人数"   , String.valueOf( loginCount )," 名 ","( <a href=\"admin?COMMAND=loginUser\">明細情報</a> )" );
    236
    237                tableTr1( rtn,"メモリ情報" );
    238                tableTr( rtn,"空きメモリ"    , String.valueOf( freeMemory )          , " [KByte]" );
    239                tableTr( rtn,"合計メモリ"    , String.valueOf( totalMemory )         , " [KByte]" );
    240                tableTr( rtn,"使用率"              , String.valueOf( useMemoryRatio )      , " [％]"    );
    241
    242                rtn.append( "</table>" ).append( CR );
    243                rtn.append( CR );
    244
    245//              rtn.append( "   <tr><td colspan = \"4\">サーバー情報</td></tr>" ).append( CR );
    246//              rtn.append( "   <tr><td></td><td>ＯＳ情報</td><td>=</td><td>" ).append( OS_INFO ).append( "</td></tr>" ).append( CR );
    247//              rtn.append( "   <tr><td></td><td>サーバー名</td><td>=</td><td>" ).append( SERVER_INFO ).append( "</td></tr>" ).append( CR );
    248//              rtn.append( "   <tr><td></td><td>サーブレット</td><td>=</td><td>" ).append( SERVLET_INFO ).append( "</td></tr>" ).append( CR );
    249//              rtn.append( "   <tr><td></td><td>REAL_PATH</td><td>=</td><td>" ).append( REAL_PATH ).append( "</td></tr>" ).append( CR );
    250//              rtn.append( "   <tr><td></td><td>TOMCAT_WORK</td><td>=</td><td>" ).append( TOMCAT_WORK ).append( "</td></tr>" ).append( CR );
    251//              rtn.append( "   <tr><td></td><td>JDKバージョン</td><td>=</td><td>" ).append( JDK_INFO ).append( "</td></tr>" ).append( CR );
    252//              rtn.append( "   <tr><td></td><td>JAVA_HOME</td><td>=</td><td>" ).append( JAVA_HOME ).append( "</td></tr>" ).append( CR );
    253//              rtn.append( "   <th><td></td><td colspan = \"2\"></td></th>" ).append( CR );
    254//              rtn.append( "   <tr><td colspan = \"4\">エンジンバージョン</td></tr>" ).append( CR );
    255//              rtn.append( "   <tr><td></td><td>バージョンNo</td><td>=</td><td>" ).append( ENGINE_INFO ).append( "</td></tr>" ).append( CR );
    256//              rtn.append( "   <tr><td></td><td>作成日時</td><td>=</td><td>" ).append( BuildNumber.TIMESTAMP ).append( "</td></tr>" ).append( CR );
    257//              rtn.append( "   <th><td></td><td colspan = \"2\"></td></th>" ).append( CR );
    258//              rtn.append( "   <tr><td colspan = \"4\">ログインユーザー</td></tr>" ).append( CR );
    259//              rtn.append( "   <tr><td></td><td>ログイン人数    </td><td>=</td><td>" ).append( loginCount ).append( " 名 " );
    260//              rtn.append( "( <a href=\"admin?COMMAND=loginUser\">明細情報</a> )</td></tr>" ).append( CR );
    261//              rtn.append( "   <tr><td colspan = \"4\">メモリ情報</td></tr>" ).append( CR );
    262//              rtn.append( "   <tr><td></td><td>空きメモリ</td><td>=</td><td>" ).append( freeMemory ).append( " [KByte]</td></tr>" ).append( CR );
    263//              rtn.append( "   <tr><td></td><td>合計メモリ</td><td>=</td><td>" ).append( totalMemory ).append( " [KByte]</td></tr>" ).append( CR );
    264//              rtn.append( "   <tr><td></td><td>使用率</td><td>=</td><td>" ).append( useMemoryRatio ).append( " [％]</td></tr>" ).append( CR );
    265//              rtn.append( "</table>" ).append( CR );
    266//              rtn.append( CR );
    267
    268                rtn.append( "<table width=\"50%\" frame=\"box\" border = \"1px\" cellspacing=\"0px\" cellpadding=\"0px\" >" ).append( CR );
    269//              rtn.append( "   <tr><td width=\"" ).append( useMemoryRatio ).append( "%\" bgcolor=\"red\" >" ).append( CR );
    270//              rtn.append( "           <img width=\"100%\" height=\"10px\" src=\"" ).append( JSP ).append( "/image/space.gif\" alt=\"" ).append( useMemoryRatio ).append( "%\"></td>" ).append( CR );
    271//              rtn.append( "           <td></td>" ).append( CR );
    272//              rtn.append( "   </tr>" ).append( CR );
    273                rtn.append( "   <tr><td align=\"center\" width=\"" ).append( useMemoryRatio ).append( "%\" bgcolor=\"red\" >" ).append( CR );
    274                rtn.append( useMemoryRatio ).append( "%</td>" ).append( CR );
    275                rtn.append( "           <td align=\"center\">" ).append( 100-useMemoryRatio ).append( "%</td>" ).append( CR );
    276                rtn.append( "   </tr>" ).append( CR );
    277                rtn.append( "</table>" ).append( CR );
    278
    279                rtn.append( "<hr />" ).append( CR );
    280                rtn.append( "<pre>" ).append( CR );
    281                rtn.append( ConnectionFactory.information() ).append( CR );
    282                rtn.append( "</pre>" ).append( CR );
    283
    284                return rtn.toString();
    285        }
    286
    287        /**
    288         * infomation 情報を作成します。
    289         *
    290         * @og.rev 5.6.6.0 (2013/07/05) &lt;/td&gt;&lt;/tr&gt;漏れ追加
    291         * @og.rev 5.6.7.3 (2013/08/23) 前後に、【】を付けます。
    292         *
    293         * @param       buf     情報登録用のStringBuilder(出力と同じオブジェクト)
    294         * @param       key     キー
    295         *
    296         * @return      infomation情報
    297         */
    298        private StringBuilder tableTr1( final StringBuilder buf, final String key ) {
    299//              buf.append( "<tr><td colspan = \"4\">" ).append( key ).append( CR );
    300//              buf.append( "<tr><td colspan=\"4\"><b>" ).append( key ).append( "</b></td></tr>" ).append( CR );            // td,tr 漏れ追加
    301                buf.append( "<tr><td colspan=\"4\"><b>【" ).append( key ).append( "】</b></td></tr>" ).append( CR );  // 【】追加
    302                return buf ;
    303        }
    304
    305        /**
    306         * infomation 情報を作成します。
    307         *
    308         * @og.rev 5.6.6.0 (2013/07/05) 最初の td に、全角スペース２個 追加
    309         *
    310         * @param       buf     情報登録用のStringBuilder(出力と同じオブジェクト)
    311         * @param       key     キー
    312         * @param       val     値の可変長引数
    313         *
    314         * @return      infomation情報
    315         */
    316        private StringBuilder tableTr( final StringBuilder buf, final String key, final String... val ) {
    317//              buf.append( "\t<tr><td></td><td>" ).append( key ).append( "</td><td>=</td><td>" );
    318                buf.append( "<tr><td width=\"20px\">　</td><td>" ).append( key ).append( "</td><td> = </td><td>" );                      // 段を作成する為に、width指定 追加
    319                for( int i=0; i<val.length; i++ ) {
    320                        buf.append( val[i] );
    321                }
    322                buf.append( "</td></tr>" ).append( CR );
    323                return buf ;
    324        }
    325
    326        /**
    327         * close 情報を作成します。
    328         *
    329         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    330         * @og.rev 3.6.0.0 (2004/09/17) CalendarFactory.clear() を追加します。
    331         * @og.rev 4.0.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
    332         * @og.rev 4.1.0.2 (2008/01/29) UserInfoをsessionから消去する(超暫定対応)
    333         * @og.rev 5.6.6.0 (2013/07/05) UserSummary の削除処理は、SystemManager から行う。
    334         *
    335         * @param       session HttpSessionオブジェクト
    336         *
    337         * @return      close情報
    338         */
    339        private String getCloseMessage( final HttpSession session ) {
    340
    341                // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
    342                SystemManager.allClear( false ) ;
    343
    344                ServletContext context = session.getServletContext();
    345                Map<String,String> param = SystemParameter.makeSystemParameter( context );
    346                HybsSystem.setInitialData( param );                     // 4.0.0 (2005/01/31)
    347
    348                // 5.6.6.0 (2013/07/05) UserSummary の削除処理は、SystemManager から行う。
    349                SystemManager.removeSession( session ) ;
    350
    351//              UserSummary userInfo = (UserSummary)session.getAttribute( HybsSystem.USERINFO_KEY );
    352////            if( userInfo != null ) { userInfo.clear(); }
    353//              if( userInfo != null ) { // 4.1.0.2 (2008/01/29)
    354//                      userInfo.clear();
    355//                      session.removeAttribute( HybsSystem.USERINFO_KEY );
    356//              }
    357
    358                String rtn = "<pre>"
    359                                        + "キャッシュ情報をクリアーしました。"
    360                                        + CR
    361                                        + "ユーザー情報の初期化に関しては、ブラウザを閉じて、再ログインが必要です。"
    362                                        + CR
    363                                        + ConnectionFactory.information()
    364                                        + "</pre>" ;
    365                return rtn ;
    366        }
    367
    368        // 5.6.6.0 (2013/07/05) getLoginUser( String,boolean ) で、指定するキーを配列で持っておきます。
    369        // キーは、SystemManager.getRunningUserSummary 処理内で大文字化されるため、この配列は、表示用と兼用します。
    370        private static final String[] USER_KEYS = new String[] { "ID","Jname","Roles","IPAddress","LoginTime","LastAccess","LastGamenNm" };
    371
    372        /**
    373         * loginUser 情報を作成します。
    374         *
    375         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    376         * @og.rev 3.8.5.3 (2006/08/07) ユーザー情報をソートするためのキー情報を追加
    377         * @og.rev 3.8.7.0 (2006/12/15) USER.LASTACCESS情報を追加します。
    378         * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属性(CLS_NM)から、DBTYPEに変更
    379         * @og.rev 4.4.0.1 (2009/08/08) 最終ログイン画面名称を追加
    380         * @og.rev 5.6.6.0 (2013/07/05) table作成処理を、変更します。
    381         * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
    382         *
    383         * @param       sort    ソートするキー項目を指定
    384         * @param       direc   ソートする方向 [true:昇順/false:降順]
    385         *
    386         * @return      loginUser情報
    387         */
    388        private String getLoginUser( final String sort,final boolean direc ) {
    389                // 4.0.0 (2005/01/31) ログイン数の取得方法の変更。
    390                int loginCount = SystemManager.getRunningCount() ;
    391
    392                // 4.0.0 (2005/01/31)
    393                UserSummary[] userInfos = SystemManager.getRunningUserSummary( sort,direc );
    394
    395                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    396
    397                rtn.append( "現在 " ).append( loginCount ).append( " 名の方がログイン中です。" );
    398                rtn.append( CR );
    399
    400                rtn.append( "<table " ).append( TABLE_HEADER ).append( " >" ).append( CR );
    401                rtn.append( " <thead><tr><th>No</th>" );
    402
    403                // 5.6.6.0 (2013/07/05) table作成処理を、変更します。
    404                for( String sortKey : USER_KEYS ) {
    405                        rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=" ).append( sortKey )
    406                                .append( "&direc=" ).append( !direc )
    407                                .append( "\">" ).append( sortKey ).append( "</a></th>" );
    408                }
    409
    410//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=ID&direc="                        ).append( !direc );
    411//              rtn.append(                             "\">UserID</a></th>" );
    412//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=JNAME&direc="             ).append( !direc );
    413//              rtn.append(                             "\">Jname</a></th>" );
    414//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=ROLES&direc="             ).append( !direc );
    415//              rtn.append(                             "\">Roles</th>" );
    416//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=IPADDRESS&direc=" ).append( !direc );
    417//              rtn.append(                             "\">IPAddress</a></th>" );
    418//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=LOGINTIME&direc=" ).append( !direc );
    419//              rtn.append(                             "\">LoginTime</a></th>" );
    420//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=LASTACCESS&direc="        ).append( !direc );
    421//              rtn.append(                             "\">LastAccess</a></th>" );
    422//              rtn.append( "  <th><a href=\"?COMMAND=loginUser&sort=LASTGAMENNM&direc=").append( !direc ); // 4.4.0.1 (2009/08/08)
    423//              rtn.append(                             "\">LastGamenName</a></th>" );
    424                rtn.append( " </tr></thead>" ).append( CR );
    425//              rtn.append( " <colgroup class=\"S9\" />" ).append( CR );
    426//              rtn.append( " <colgroup class=\"X\" span=\"6\" />" ).append( CR );
    427                rtn.append( " <colgroup class=\"S9\" ><!-- --></colgroup>" ).append( CR ); // 5.9.1.2 (2015/10/23)
    428                rtn.append( " <colgroup class=\"X\" span=\"6\" ><!-- --></colgroup>" ).append( CR );
    429                rtn.append( CR );
    430
    431                for( int i=0; i<userInfos.length; i++ ) {
    432                        UserSummary userInfo = userInfos[i] ;
    433                        rtn.append( " <tr class=\"row_" ).append( i%2 ).append( "\" >" ).append( CR );
    434                        rtn.append( "  <td>" ).append( String.valueOf( i+1 )   ).append( "</td>" ).append( CR );
    435                        rtn.append( "  <td>" ).append( userInfo.getUserID()    ).append( "</td>" ).append( CR );
    436                        rtn.append( "  <td>" ).append( userInfo.getJname()     ).append( "</td>" ).append( CR );
    437                        rtn.append( "  <td>" ).append( userInfo.getRoles()     ).append( "</td>" ).append( CR );
    438                        rtn.append( "  <td>" ).append( userInfo.getIPAddress() ).append( "</td>" ).append( CR );
    439                        rtn.append( "  <td>" ).append( HybsSystem.getDate( userInfo.getLoginTime() ) ).append( "</td>" ).append( CR );
    440                        rtn.append( "  <td>" ).append( userInfo.getAttribute( "LASTACCESS") ).append( "</td>" ).append( CR );
    441                        rtn.append( "  <td>" ).append( StringUtil.nval( userInfo.getAttribute( "LASTGAMENNM"), "" ) ).append( "</td>" ).append( CR );  // 4.4.0.1 (2009/08/08)
    442                        rtn.append( " </tr>" ).append( CR );
    443                }
    444                rtn.append( "</table>" ).append( CR );
    445
    446                return rtn.toString() ;
    447        }
    448
    449        /**
    450         * PlugIn 情報を作成します。
    451         *
    452         * @og.rev 4.0.0.0 (2005/08/31) 新規作成
    453         * @og.rev 5.6.6.0 (2013/07/05) "DBConstValue","Daemon","JspCreate" を、追加します。
    454         *
    455         * @return      PlugIn情報
    456         */
    457        private String getPlugInInfo() {
    458
    459                String[] pluginType = new String[] {
    460                                                                "Query","Renderer","Editor","DBType","ViewForm",
    461                                                                "TableReader","TableWriter","TableFilter","ChartWriter","CalendarQuery",
    462                                                                "DBConstValue","Daemon","JspCreate"                                     // 5.6.6.0 (2013/07/05) 追加
    463                                                        } ;
    464
    465                ClassInfo info = new ClassInfo();
    466
    467                for( int j=0; j<pluginType.length; j++ ) {
    468                        String type = pluginType[j] ;
    469                        HybsEntry[] names = HybsSystem.sysEntry( type + "_" );
    470                        for( int i=0; i<names.length; i++ ) {
    471                                String key              = names[i].getKey().substring( type.length()+1 );
    472                                String clsName  = names[i].getValue();
    473                                info.addLine( type,key,clsName );
    474                        }
    475                }
    476                return info.getClassInfoData() ;
    477        }
    478
    479        /**
    480         * Taglib 情報を作成します。
    481         *
    482         * @og.rev 4.0.0.0 (2006/01/31) 新規作成
    483         * @og.rev 5.3.6.0 (2011/06/01) Taglib クラス名の求め方を変更します。(jar版のみ)
    484         * @og.rev 5.5.2.6 (2012/05/25) JarFile を、Closer#zipClose( ZipFile ) メソッドを利用して、close します。
    485         *
    486         * @return      Taglib情報
    487         */
    488        private String getTaglibInfo() {
    489                ClassInfo info = new ClassInfo();
    490
    491                // 5.5.2.6 (2012/05/25) findbugs対応
    492                JarFile jarFile = null;
    493                try {
    494                        ClassLoader loader = Thread.currentThread().getContextClassLoader();
    495                        Enumeration<URL> enume = loader.getResources( "org/opengion/hayabusa/taglib/" );          // 4.3.3.6 (2008/11/15) Generics警告対応
    496                        while( enume.hasMoreElements() ) {
    497                                URL url = enume.nextElement();          // 4.3.3.6 (2008/11/15) Generics警告対応
    498                                // jar:file:/実ディレクトリ または、file:/実ディレクトリ
    499                                String dir = url.getFile();
    500                                if( "jar".equals( url.getProtocol() ) ) {
    501                                        // dir = file:/G:/webapps/gf/WEB-INF/lib/hayabusa4.0.0.jar!/org/opengion/hayabusa/taglib 形式です。
    502                                        String jar = dir.substring(dir.indexOf( ':' )+1,dir.lastIndexOf( '!' ));
    503                                        // jar = /G:/webapps/gf/WEB-INF/lib/hayabusa4.0.0.jar 形式に切り出します。
    504//                                      JarFile jarFile = new JarFile( jar );
    505                                        jarFile = new JarFile( jar );
    506                                        Enumeration<JarEntry> en = jarFile.entries() ;            // 4.3.3.6 (2008/11/15) Generics警告対応
    507                                        while( en.hasMoreElements() ) {
    508                                                JarEntry ent = en.nextElement();                // 4.3.3.6 (2008/11/15) Generics警告対応
    509                                                String file = ent.getName();
    510                                                if( ! ent.isDirectory() && file.endsWith( "Tag.class" ) ) {
    511                                                        String type             = "Taglib";
    512                                                        // 5.3.6.0 (2011/06/01) Taglib クラス名の求め方を変更します。(jar版のみ)
    513//                                                      String key              = file.substring( 0,file.length()-6 );
    514                                                        String key              = file.substring( file.lastIndexOf( '/' )+1,file.length()-6 );  // -6 は、.class 分
    515//                                                      String clsName  = "org.opengion.hayabusa.taglib." + key ;
    516                                                        String clsName  = file.replace( '/','.' ).substring( 0,file.length()-6 );
    517                                                        info.addLine( type,key,clsName );
    518                                                }
    519                                        }
    520                                        Closer.zipClose( jarFile );             // 5.5.2.6 (2012/05/25) findbugs対応
    521                                        jarFile = null;                                 // 正常終了時に、close() が２回呼ばれるのを防ぐため。
    522                                }
    523                                else {
    524                                        // dir = /G:/webapps/gf/WEB-INF/classes/org/opengion/hayabusa/taglib/ 形式です。
    525                                        File fileObj = new File( dir );
    526                                        File[] list = fileObj.listFiles();
    527                                        for( int i=0; i<list.length; i++ ) {
    528                                                String file = list[i].getName() ;
    529                                                if( list[i].isFile() && file.endsWith( "Tag.class" ) ) {
    530                                                        String type             = "Taglib";
    531                                                        String key              = file.substring( 0,file.length()-6 );
    532                                                        String clsName  = "org.opengion.hayabusa.taglib." + key ;
    533                                                        info.addLine( type,key,clsName );
    534                                                }
    535                                        }
    536                                }
    537                        }
    538                }
    539                catch( IOException ex ) {
    540                        String errMsg = "taglibファイル読み取りストリームを失敗しました。"
    541                                        + CR + ex.getMessage();
    542                        throw new RuntimeException( errMsg,ex );
    543                }
    544                finally {
    545                        Closer.zipClose( jarFile );             // 5.5.2.6 (2012/05/25) findbugs対応
    546                }
    547
    548                return info.getClassInfoData() ;
    549        }
    550
    551        /**
    552         * クラス情報を表示するためのデータを管理します。
    553         * ここでは、引数に渡された、分類(Classify)、名称(Key Name)、クラス名(Class Name)、
    554         * バージョン(Version)情報をテーブル形式で表示します。
    555         * バージョン情報は、クラス名から、インスタンスを作成して、private static final String VERSION
    556         *  フィールドの値を読み取ります。
    557         *
    558         * @og.rev 4.0.0.0 (2006/01/31) 新規作成
    559         */
    560        private static final class ClassInfo {
    561                private final StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    562                private int cnt = 0;
    563
    564                /**
    565                 * コンストラクター
    566                 *
    567                 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
    568                 * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
    569                 */
    570                public ClassInfo() {
    571                        rtn.append( "<table " ).append( TABLE_HEADER ).append( " >" ).append( CR );
    572                        rtn.append( "   <thead><tr><th>No</th><th>Classify</th><th>Key Name</th><th>Class Name</th><th>Version</th></tr></thead>" ).append( CR );
    573//                      rtn.append( "   <colgroup class=\"S9\" />" ).append( CR );
    574//                      rtn.append( "   <colgroup class=\"X\" />"  ).append( CR );
    575//                      rtn.append( "   <colgroup class=\"X\" />"  ).append( CR );
    576//                      rtn.append( "   <colgroup class=\"X\" />"  ).append( CR );
    577//                      rtn.append( "   <colgroup class=\"X\" />"  ).append( CR );
    578//                      rtn.append( "   <colgroup class=\"X\" />"  ).append( CR );
    579                        rtn.append( "   <colgroup class=\"S9\" ><!-- --></colgroup>" ).append( CR ); // 5.9.1.2 (2015/10/23)
    580                        rtn.append( "   <colgroup class=\"X\" ><!-- --></colgroup>"  ).append( CR );
    581                        rtn.append( "   <colgroup class=\"X\" ><!-- --></colgroup>"  ).append( CR );
    582                        rtn.append( "   <colgroup class=\"X\" ><!-- --></colgroup>"  ).append( CR );
    583                        rtn.append( "   <colgroup class=\"X\" ><!-- --></colgroup>"  ).append( CR );
    584                        rtn.append( "   <colgroup class=\"X\" ><!-- --></colgroup>"  ).append( CR );
    585                        rtn.append( CR );
    586                }
    587
    588                /**
    589                 * テーブル表示用のデータを追加します。
    590                 *
    591                 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
    592                 *
    593                 * @param       type    タイプ属性
    594                 * @param       key     キー属性
    595                 * @param       clsName クラス名(このクラス名からインスタンス化します。)
    596                 */
    597                public void addLine( final String type, final String key, final String clsName ) {
    598                        String version  = getFieldValue( clsName );
    599
    600                        boolean isCustom = ( version.compareTo( BuildNumber.VERSION_NO ) > 0 ) ||
    601                                                                version.indexOf( "Pache"   ) >= 0 ||
    602                                                                version.indexOf( "Nightly" ) >= 0 ;
    603
    604                        String trType = ( isCustom ) ? "warning" : String.valueOf( cnt%2 );
    605
    606                        rtn.append( "   <tr class=\"row_" ).append( trType ).append( "\" >" ).append( CR );
    607                        rtn.append( "           <td>" ).append( cnt++    ).append( "</td>" ).append( CR );
    608                        rtn.append( "           <td>" ).append( type     ).append( "</td>" ).append( CR );
    609                        rtn.append( "           <td>" ).append( key      ).append( "</td>" ).append( CR );
    610                        rtn.append( "           <td>" ).append( clsName  ).append( "</td>" ).append( CR );
    611                        rtn.append( "           <td>" ).append( version  ).append( "</td>" ).append( CR );
    612                        rtn.append( "   </tr>" ).append( CR );
    613                }
    614
    615                /**
    616                 * すべての内部のデータを文字列化して返します。
    617                 *
    618                 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
    619                 *
    620                 * @return      作成されたテーブルデータ
    621                 */
    622                public String getClassInfoData() {
    623                        rtn.append( "</table>" ).append( CR );
    624                        return rtn.toString() ;
    625                }
    626
    627                /**
    628                 * 指定のオブジェクトの  VERSION staticフィールドの値を取得します。
    629                 *
    630                 * @og.rev 4.0.0.0 (2005/08/31) 新規作成
    631                 *
    632                 * @param       clsName 指定のクラスを表す名称
    633                 * @return      VERSION staticフィールドの値(エラー時は、そのメッセージ)
    634                 */
    635                private String getFieldValue( final String clsName ) {
    636                        String rtn ;
    637                        try {
    638                                Object obj = HybsSystem.newInstance( clsName );
    639                                Field fld = obj.getClass().getDeclaredField( "VERSION" ) ;
    640                                // privateフィールドの取得には、accessibleフラグを trueにする必要があります。
    641                                fld.setAccessible( true );
    642
    643                                rtn = (String)fld.get( null );
    644                        }
    645                        catch( Throwable ex ) {
    646                                rtn = ex.getMessage();
    647                        }
    648                        return rtn ;
    649                }
    650        }
    651
    652        /**
    653         * systemResource 情報を作成します。
    654         *
    655         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    656         * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属性(CLS_NM)から、DBTYPEに変更
    657         * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
    658         *
    659         * @return      systemResource情報
    660         */
    661        private String getSystemResource() {
    662                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    663
    664                rtn.append( "<table " ).append( TABLE_HEADER ).append( " >" ).append( CR );
    665                rtn.append( "   <thead><tr><th>No</th><th>Key</th><th>Value</th></tr></thead>" ).append( CR );
    666//              rtn.append( "   <colgroup class=\"S9\" />" ).append( CR );
    667//              rtn.append( "   <colgroup class=\"X\" span=\"2\" />" ).append( CR );
    668                rtn.append( "   <colgroup class=\"S9\" ><!-- --></colgroup>" ).append( CR ); // 5.9.1.2 (2015/10/23)
    669                rtn.append( "   <colgroup class=\"X\" span=\"2\" ><!-- --></colgroup>" ).append( CR );
    670                rtn.append( CR );
    671
    672                String[][] str = HybsSystem.getSystemResourceData();
    673                for( int i=0; i<str[0].length; i++ ) {
    674                        rtn.append( "   <tr class=\"row_" ).append( i%2 ).append( "\" >" ).append( CR );
    675                        rtn.append( "           <td>" ).append( String.valueOf( i+1 ) ).append( "</td>" ).append( CR );
    676                        rtn.append( "           <td>" ).append( str[0][i] ).append( "</td>" ).append( CR );
    677                        rtn.append( "           <td>" ).append( str[1][i] ).append( "</td>" ).append( CR );
    678                        rtn.append( "   </tr>" ).append( CR );
    679                }
    680                rtn.append( "</table>" ).append( CR );
    681
    682                return rtn.toString();
    683        }
    684
    685        /**
    686         * AccessStop 情報を作成します。
    687         *
    688         * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにメソッドを呼び出すように修正します。
    689         * @og.rev 4.0.0.0 (2007/11/29) AccessStopFilter#getStopFilter() ⇒ isStopFilter() に変更
    690         *
    691         * @return      AccessStop情報
    692         */
    693        private String getAccessStop() {
    694
    695//              boolean flag = org.opengion.hayabusa.filter.AccessStopFilter.getStopFilter();
    696                boolean flag = org.opengion.hayabusa.filter.AccessStopFilter.isStopFilter();
    697                flag = !flag ;
    698
    699                final String rtn ;
    700                if( flag ) {
    701                        rtn = "Webアプリケーションのサービスを停止します。";
    702                }
    703                else {
    704                        rtn = "Webアプリケーションのサービスを開始します。";
    705                }
    706                org.opengion.hayabusa.filter.AccessStopFilter.setStopFilter( flag );
    707
    708                return rtn ;
    709        }
    710
    711        /**
    712         * admin リンク情報を作成します。
    713         * 簡易メソッドなので、国際化対応していません。
    714         *
    715         * @og.rev 3.5.4.1 (2003/12/01) 新規作成
    716         * @og.rev 5.1.1.2 (2009/12/10) 画面IDを変更
    717         * @og.rev 5.6.3.4 (2013/04/26) ｸｲｯｸﾘﾌｧﾚﾝｽ 画面を追加
    718         *
    719         * @return      アドミンリンク情報
    720         */
    721        private String getAdminLink() {
    722                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    723
    724                rtn.append( "<table><tr>" ).append( CR );
    725                rtn.append( "<td width=\"10px\"/>" ).append( CR );
    726                rtn.append( "<td>[<a href=\"admin?COMMAND=infomation\" target=\"RESULT\" >状況表示</a>]</td>" ).append( CR );
    727                rtn.append( "<td width=\"10px\"/>" ).append( CR );
    728                rtn.append( "<td>[<a href=\"admin?COMMAND=close\" target=\"RESULT\" >ﾌﾟｰﾙ削除</a>]</td>" ).append( CR );
    729                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    730                rtn.append( "[<a href=\"admin?COMMAND=loginUser\" target=\"RESULT\" >ﾛｸﾞｲﾝﾕｰｻﾞｰ</a>]</td>" ).append( CR );
    731                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    732                rtn.append( "[<a href=\"admin?COMMAND=plugin\" target=\"RESULT\" >ﾌﾟﾗｸﾞｲﾝ情報</a>]</td>" ).append( CR );
    733                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    734                rtn.append( "[<a href=\"admin?COMMAND=taglib\" target=\"RESULT\" >ﾀｸﾞﾘﾌﾞ情報</a>]</td>" ).append( CR );
    735                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    736                rtn.append( "[<a href=\"common/quickReference.html\" target=\"RESULT\" >ｸｲｯｸﾘﾌｧﾚﾝｽ</a>]</td>" ).append( CR ); // 5.6.3.4 (2013/04/26)
    737                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    738                rtn.append( "[<a href=\"admin?COMMAND=systemResource\" target=\"RESULT\" >ｼｽﾃﾑﾘｿｰｽ</a>]</td>" ).append( CR );
    739                rtn.append( "<td width=\"10px\"/><td>" ).append( CR );
    740//              rtn.append( "[<a href=\"common/gamen/01_ADMIN/parameter.jsp?GAMENID=ADMIN\" target=\"RESULT\" >Parameter</a>]</td>" ).append( CR );
    741                rtn.append( "[<a href=\"common/gamen/01_ADMIN/parameter.jsp?GAMENID=01_ADMIN\" target=\"RESULT\" >Parameter</a>]</td>" ).append( CR );
    742                rtn.append( "</tr></table>" ).append( CR );
    743
    744                return rtn.toString();
    745        }
    746
    747        /**
    748         * DBTableModel から テーブルのタグ文字列を作成して返します。
    749         *
    750         * @og.rev 3.5.3.1 (2003/10/31) User情報のテーブルの設定を、システムリソース より行う。
    751         * @og.rev 5.2.2.0 (2010/11/01) SystemData 見直し漏れの対応。
    752         *
    753         * @return      テーブルのタグ文字列
    754         */
    755        private static String getTableHeaderTag() {
    756                Attributes attri = new Attributes();
    757                attri.set( "id" ,"viewTable" );         // 3.6.0.5 (2004/10/18)
    758                attri.set( "summary"     ,"layout"        );                    // サマリー
    759
    760//              // 4.0.0 (2005/08/31) テーブル表示の CSSファイル利用の有無
    761//              boolean useCSSfile = HybsSystem.sysBool( "USE_HTML_TABLE_CSS" ) ;
    762//
    763//              if( ! useCSSfile ) {
    764//                      attri.set( "summary"     ,"layout"        );                    // サマリー
    765//                      attri.set( "border"      ,HybsSystem.sys( "HTML_BORDER" ) ) ;     // 外枠の太さ
    766//                      attri.set( "width"               ,HybsSystem.sys( "HTML_WIDTH" )  ) ;     // 表の大きさ(幅)ピクセルまたは,％
    767//                      attri.set( "frame"               ,HybsSystem.sys( "HTML_FRAME" )  ) ;     // 外枠の表示形式  void,above,below,lhs,rhs,hsides,vsides,box,border
    768//                      attri.set( "rules"               ,HybsSystem.sys( "HTML_RULES" )  ) ;     // セルを区切る線の形式 none,rows,cols,groups,all
    769//                      attri.set( "cellspacing" ,HybsSystem.sys( "HTML_CELLSPACING" ) );  // セルの間隔
    770//                      attri.set( "cellpadding" ,HybsSystem.sys( "HTML_CELLPADDING" ) );  // セル内のマージン
    771//              }
    772
    773                return attri.getAttribute();
    774        }
    775
    776        /**
    777         * userInfo 情報をセットします。
    778         * 現状、このメソッドではLANGのみ設定可能です。
    779         * （予約語以外のセットはuserInfoタグで行う）
    780         *
    781         * LANGではuserInfoを切り替えた後にユーザのGUIInfoを再ロードします。
    782         *
    783         * @og.rev 5.9.1.0 (2015/10/02) 新規作成
    784         *
    785         * @return      結果
    786         */
    787        private String setUserinfo( final HttpServletRequest req ) {
    788                HttpSession session = req.getSession();
    789                UserInfo userInfo = (UserInfo)(session.getAttribute( HybsSystem.USERINFO_KEY ));
    790
    791                String infoLang  = req.getParameter( "LANG" );
    792
    793                String rtn = null ;
    794                if( userInfo != null && infoLang != null && infoLang.length() > 0) {
    795                        userInfo.setLang( infoLang );
    796                        ResourceFactory.newInstance( userInfo.getLang() ).makeGUIInfos( userInfo );
    797                        rtn = "User language : " + infoLang;
    798                }
    799
    800                if ( rtn == null || rtn.length() == 0 ) {
    801                        rtn = "Error";
    802                }
    803
    804                return rtn ;
    805        }
    806}