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 *        OS情報      = 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情報"             , 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>OS情報</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 に、全角スペース2個 追加
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() が2回呼ばれるのを防ぐため。
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}