/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.hayabusa.servlet;

import org.opengion.fukurou.system.OgRuntimeException;				// 6.4.2.0 (2016/01/29)
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Files;											// 8.5.0.0 (2023/04/21) Add
import java.nio.file.Path;											// 8.5.0.0 (2023/04/21) Add
import java.nio.file.Paths;											// 8.5.0.0 (2023/04/21) Add
import java.util.ArrayList;											// 8.5.0.0 (2023/04/21) Add
import java.util.stream.Stream;										// 8.5.0.0 (2023/04/21) Add
import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;							// 6.4.3.3 (2016/03/04)
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import org.opengion.fukurou.db.ConnectionFactory;
import org.opengion.fukurou.util.Attributes;
import org.opengion.fukurou.util.HybsEntry;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.fileexec.MainProcess;					// 7.2.5.0 (2020/06/01)
import org.opengion.fukurou.system.BuildNumber;						// 6.4.2.0 (2016/01/29) hayabusa.common.BuildNumber → fukurou.system.BuildNumber に移動
import org.opengion.fukurou.system.Closer;							// 5.5.2.6 (2012/05/25)
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.SystemManager;
import org.opengion.hayabusa.common.SystemParameter;
import org.opengion.hayabusa.common.UserSummary;
import static org.opengion.fukurou.system.HybsConst.CR;				// 6.1.0.0 (2014/12/26)
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;	// 6.1.0.0 (2014/12/26) refactoring

import org.opengion.hayabusa.resource.ResourceFactory;				// 5.9.1.0 (2015/10/02)
import org.opengion.hayabusa.resource.UserInfo;						// 5.9.1.0 (2015/10/02)

import jakarta.servlet.ServletRegistration;							// 6.3.4.0 (2015/08/01)
import jakarta.servlet.FilterRegistration;							// 6.3.4.0 (2015/08/01)
import jakarta.servlet.annotation.WebServlet;						// 7.3.0.0 (2021/01/06)

/**
 * ｻｰﾊﾞｰ管理情報を取得するAdminｻｰﾌﾞﾚｯﾄです。
 *
 * 引数(URL)に応じて、ｻｰﾊﾞｰの状態結果を返します。
 * 一般には、http://ｻｰﾊﾞｰ:ﾎﾟｰﾄ/ｼｽﾃﾑID/jsp/admin?COMMAND=ｺﾏﾝﾄﾞ の
 * 形式のURL でｱｸｾｽします。
 *
 *  ･COMMAND=infomation
 *     【ｻｰﾊﾞｰ情報】
 *        OS情報      = Windows 7 Service Pack 1 x86 (32)
 *        ｻｰﾊﾞｰ名     = 10374232-0004 ( 172.27.26.164 )
 *        ｻｰﾌﾞﾚｯﾄ     = Apache Tomcat/8.0.22
 *        TOMCAT_HOME = C:/opengionV6/apps/tomcat8.0.22
 *        JDKﾊﾞｰｼﾞｮﾝ  = Java HotSpot(TM) Server VM 1.8.0_45-b15
 *        JAVA_HOME   = C:/opengionV6/apps/jdk180u45/jre
 *     【実行環境】
 *        ｻｰﾋﾞｽ起動   = true [ GF ]
 *        REAL_PATH   = C:/opengionV6/uap/webapps/gf/
 *        ﾊﾞｰｼﾞｮﾝNo   = openGion 6.2.4.0 Release6 Builds (2015142)
 *        作成日時    = 2015/05/22 15:31:53
 *        pache有無   = false [ C:/opengionV8/uap/webapps/gf/WEB-INF/classes ]
 *     【ﾛｸﾞｲﾝ情報】
 *        ﾛｸﾞｲﾝ人数   = 2 名 ( 明細情報 )
 *     【ﾒﾓﾘ情報】
 *        空きﾒﾓﾘ     = 129 [MByte]
 *        合計ﾒﾓﾘ     = 209 [MByte]
 *        使用率      = 38 [％]
 *     【ﾃﾞｨｽｸ情報】
 *
 *  ･COMMAND=close
 *       ﾘｿｰｽ情報のｷｬｯｼｭを全てｸﾘｱします。
 *
 *  ･COMMAND=loginUser
 *       現在のﾛｸﾞｲﾝﾕｰｻﾞｰの明細情報を表示します。
 *       SORT=[JNAME,ID,ROLES,IPADDRESS,LOGINTIME] ｿｰﾄｷｰ
 *       DIREC=[true,false] true:昇順/false:降順
 *  ･COMMAND=systemResource
 *       現在のｼｽﾃﾑﾘｿｰｽの設定情報を表示します。
 *
 *  ･COMMAND=AccessStop&amp;stop=[true/false]
 *       ｱｸｾｽｽﾄｯﾌﾟﾌｨﾙﾀｰの制御(停止、許可)を行います。
 *  ･common/gamen/01_ADMIN/parameter.jsp
 *       現在のｼｽﾃﾑﾘｿｰｽの設定情報を表示します。
 *
 *  ･common/gamen/01_ADMIN/systemInfo.jsp
 *       ｼｽﾃﾑ定数のｼｽﾃﾑ起動情報を表示します。
 *
 *    ※ 7.1.0.0 (2020/01/20)
 *  ･common/gamen/01_ADMIN/logLink.jsp
 *       Tomcatのlogを表示します。
 *
 *    ※ 7.1.0.0 (2020/01/20)
 *  ･common/gamen/01_ADMIN/serviceRestart.jsp
 *       Tomcatのｻｰﾋﾞｽを再起動(停止―開始)します。
 *
 * @og.rev 3.5.3.0 (2003/10/27) Admin JSP を Servlet化して、ｴﾝｼﾞﾝと共に供給します。
 * @og.rev 4.0.0.0 (2005/08/31) ﾌﾟﾗｸﾞｲﾝのﾊﾞｰｼﾞｮﾝ情報の表示機能を追加
 * @og.rev 8.2.0.2 (2022/06/24) HTML5廃止対応
 * @og.group その他機能
 *
 * @version	4.0
 * @author	Kazuhiko Hasegawa
 * @since	JDK5.0,
 */
@WebServlet( "/jsp/admin" )
public final class HybsAdmin extends HttpServlet {
	private static final long serialVersionUID = 624120150522L ;				// 6.2.4.1 (2015/05/22)

	private static final String JSP = HybsSystem.sys( "JSP" );					// jspフォルダの正規パス
	private static final String REALPATH = HybsSystem.sys( "REAL_PATH" );		// 8.5.0.0 (2023/04/21) Add
	private static final String CLSPATH  = REALPATH + "WEB-INF\\classes";		// 8.5.0.0 (2023/04/21) Add

	private static final long MB = 1024*1024 ;									// 6.2.4.1 (2015/05/22)
	private static final long GB = 1024*1024*1024 ;								// 6.2.4.1 (2015/05/22)

	// 7.0.1.0 (2018/10/15) XHTML → HTML5 対応
	// 8.1.0.0 (2021/12/28) HTML5 準拠に見直し
//	private static final String HEADER =
//		"<!DOCTYPE html>"																			+ CR +
//		"<html class=\"headtype-query\">"															+ CR +
//		"<head>"																					+ CR +
//		"	<meta charset=\"UTF-8\" >"																+ CR +
//		"	<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" >"								+ CR +
//		"	<link rel=\"stylesheet\" href=\"" + JSP + "/common/default.css\" type=\"text/css\" >"	+ CR +
//		"	<link rel=\"stylesheet\" href=\"" + JSP + "/custom/custom.css\" type=\"text/css\" >"	+ CR +
//		"	<title>Hybs Admin</title>"																+ CR +
//		"</head>"																					+ CR;

	// 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(lang="ja",content="IE=edge" 不要,type="text/css" 不要)
	private static final String HEADER =
		"<!DOCTYPE html>"														+ CR +
		"<html lang=\"ja\" class=\"headtype-query\">"							+ CR +
		"<head>"																+ CR +
		"	<meta charset=\"UTF-8\" >"											+ CR +
		"	<link rel=\"stylesheet\" href=\"" + JSP + "/common/default.css\" >"	+ CR +
		"	<link rel=\"stylesheet\" href=\"" + JSP + "/custom/custom.css\" >"	+ CR +
		"	<title>Hybs Admin</title>"											+ CR +
		"</head>"																+ CR;

	// 3.5.3.1 (2003/10/31) User情報のﾃｰﾌﾞﾙの設定を、ｼｽﾃﾑﾘｿｰｽ より行う。
	private static final String TABLE_HEADER = getTableHeaderTag() ;

	// 5.6.6.0 (2013/07/05) getLoginUser( String,boolean ) で、指定するｷｰを配列で持っておきます。
	// ｷｰは、SystemManager.getRunningUserSummary 処理内で大文字化されるため、この配列は、表示用と兼用します。
	private static final String[] USER_KEYS = { "ID","Jname","Roles","IPAddress","LoginTime","LastAccess","LastGamenNm" };

	// 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
//	private static final String TABLE_WAKU  = "<table style=\"margin: 0px 0px 0px 20px;\" frame=\"box\" border=\"1px\" cellspacing=\"0px\" cellpadding=\"0px\" " ;
	private static final String TABLE_WAKU  = "<table border=\"1px\" style=\"margin-left:20px; border-width:medium; border-style:solid; border-collapse:collapse; ";	// 8.2.0.2 (2022/06/24) Modify
	private static final String TABLE_END   = "</table>" + CR ;

	// 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"／＞" 止めを、"＞" に変更します)。
	private static final String COMMON_MESSAGE =
			"【共通メッセージを表示する場合は、このテキストフィールドに入力してください。】<br>"	+ CR +
			"<form method=\"GET\" action=\"" + JSP + "/admin\" target=\"RESULT\" >"					+ CR +
			"    <input name=\"message\" size=\"50\" >"												+ CR +
			"    <button type=\"submit\" name=\"type\" value=\"set\"   >Set</button>"				+ CR +
			"    <button type=\"submit\" name=\"type\" value=\"clear\" >Clear</button>"				+ CR +
			"    <input type=\"hidden\" name=\"COMMAND\" value=\"commonMessage\" >"					+ CR +
			"</form><br><br>"																		+ CR ;

	// 7.1.0.0 (2020/01/27) static で定義しておきます。
	private static final String[] PLUGIN_TYPE = new String[] {
				"Query","Renderer","Editor","DBType","ViewForm",
				"TableReader","TableWriter","TableFilter","ChartWriter","CalendarQuery",
				"DBConstValue","Daemon","JspCreate"								// 5.6.6.0 (2013/07/05) 追加
	} ;

	// 7.1.0.0 (2020/01/27) static で定義しておきます。
	private static final String TD_CMD = "  <td>　　[<a href=\"" + JSP + "/admin?COMMAND=" ;
	private static final String TD_QREF= "  <td>　　[<a href=\"" + JSP + "/common/quickReference.html" ;		// ｸｲｯｸﾘﾌｧﾚﾝｽ 専用
	private static final String TD_GMN = "  <td>　　[<a href=\"" + JSP + "/common/gamen/01_ADMIN/" ;

	// 8.4.2.2 (2023/03/17) 戻る を用意しておく
	private static final String TD_BAK = "  <td>　　[<a href='' onclick='window.history.back(); return false;'>" ;

	private static final String YESNO  = "\" onclick=\"return confirm( '実行してよろしいでしょうか？' );" ;
	private static final String TGT    = "\" target=\"RESULT\" >" ;
	private static final String END_TD = "</a>]</td>" + CR ;

	private static final String INFOMATION		= TD_CMD + "infomation"			+ TGT + "状況表示"			+ END_TD ;
	private static final String CLOSE			= TD_CMD + "close"				+ TGT + "ﾌﾟｰﾙ削除"			+ END_TD ;
	private static final String LOGIN_USER		= TD_CMD + "loginUser"			+ TGT + "ﾛｸﾞｲﾝﾕｰｻﾞｰ"		+ END_TD ;
	private static final String QUICK_REFERENCE	= TD_QREF						+ TGT + "ｸｲｯｸﾘﾌｧﾚﾝｽ"		+ END_TD ;
	private static final String SYSTEM_RESOURCE	= TD_CMD + "systemResource"		+ TGT + "ｼｽﾃﾑﾘｿｰｽ"			+ END_TD ;
	private static final String PARAMETER		= TD_GMN + "parameter.jsp?GAMENID=01_ADMIN" + TGT + "ﾊﾟﾗﾒｰﾀ"+ END_TD ;
	private static final String LOGLINK			= TD_GMN + "logLink.jsp"		+ TGT + "ﾛｸﾞ"				+ END_TD ;
	private static final String SERVICE_RESTART	= TD_GMN + "serviceRestart.jsp" + YESNO + TGT + "ｻｰﾋﾞｽ再起動" + END_TD ;

	// 8.4.2.2 (2023/03/17) 戻る を用意しておく
	private static final String HISTORY_BACK	= TD_BAK						+		"戻る"				+ END_TD ;

	private static final String PLUGIN			= TD_CMD + "plugin"				+ TGT + "ﾌﾟﾗｸﾞｲﾝ情報"		+ END_TD ;
	private static final String TAGLIB			= TD_CMD + "taglib"				+ TGT + "ﾀｸﾞﾘﾌﾞ情報"		+ END_TD ;
	private static final String REGISTRATION	= TD_CMD + "registrationInfo"	+ TGT + "Servlet/Filter"	+ END_TD ;
	private static final String SYSTEM_INFO		= TD_GMN + "systemInfo.jsp"		+ TGT + "ｼｽﾃﾑ状況"			+ END_TD ;
	private static final String ACCESS_STOP		= "<td colspan=\"2\">　　ｱｸｾｽ制限"
														+ "[<a href=\"" + JSP + "/admin?COMMAND=AccessStop&stop=true"	+ TGT + "停止</a>]/"
														+ "[<a href=\"" + JSP + "/admin?COMMAND=AccessStop&stop=false"	+ TGT + "開始" + END_TD ;

	// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
	private static final String TD_TD = "</td><td>" ;			// tdの終了とtdの開始を連結したもの
	private static final String TD_TR = "</td></tr>" + CR ;		// tdの終了とtrの終了を連結したもの

	/**
	 * fileexecのMainProcess の処理が起動しているかどうかを表示。
	 *
	 * @og.rev 7.2.5.0 (2020/06/01) fileexecのMainProcess の処理が起動しているかどうかを表示
	 *
	 * @return	fileexecの起動情報
	 * @og.rtnNotNull
	 */
	public static String fileExecCmnt() {
		final boolean isStart = MainProcess.isStarted();
		return "ﾌｧｲﾙ取込(" + ( isStart ? "起動中" : "停止中" ) + ")　　" ;

//		return "<td colspan=\"2\">　　ﾌｧｲﾙ取込("
//					+ ( isStart ? "起動中" : "停止中" ) + ")　"
//					+ "[<a href=\"" + JSP + "/admin?COMMAND=fileexec&start=" + !isStart + TGT		// 他の admin もJSP が必要なはず。
//					+ "<b>" + ( isStart ? "待機する" : "実行する" ) + "</b>" + END_TD
//					+ "<td>　　起動するには、ｼｽﾃﾑ定数で、ﾊﾟﾗﾒｰﾀID=USE_FILEEXEC を、true に登録してください。(要[ﾌﾟｰﾙ削除])</td>" ;
	}

	/**
	 * GET ﾒｿｯﾄﾞが呼ばれたときに実行します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 3.5.4.1 (2003/12/01) getAdminLink() ﾒｿｯﾄﾞを追加
	 * @og.rev 6.3.8.0 (2015/09/11) AccessStop を外部から制御できるように、ｺﾏﾝﾄﾞと状態を受けるようにする。
	 * @og.rev 5.9.1.0 (2015/10/02) UserInfoｾｯﾄ機能追加
	 * @og.rev 6.3.8.3 (2015/10/03) Servlet/Filter 情報を作成。
	 * @og.rev 6.3.9.1 (2015/11/27) ３項演算子を || or &amp;&amp; で簡素化できる(PMD)。
	 * @og.rev 6.4.4.1 (2016/03/18) application ｵﾌﾞｼﾞｪｸﾄに関連付ける 共通ﾒｯｾｰｼﾞを設定します。
//	 * @og.rev 7.2.5.0 (2020/06/01) fileexecのMainProcess の処理が起動しているかどうかを表示
	 *
	 * @param	req	HttpServletRequestｵﾌﾞｼﾞｪｸﾄ
	 * @param	res	HttpServletResponseｵﾌﾞｼﾞｪｸﾄ
	 *
	 * @throws	ServletException	ｻｰﾌﾞﾚｯﾄ関係のｴﾗｰが発生した場合、throw されます。
	 * @throws	IOException			入出力ｴﾗｰが発生したとき
	 */
	@Override
	public void doGet( final HttpServletRequest req, final HttpServletResponse res)
								throws ServletException, IOException {

		req.setCharacterEncoding( "UTF-8" );								// 6.4.4.1 (2016/03/18)
		res.setContentType( "text/html; charset=UTF-8" );
		final PrintWriter out = res.getWriter();

		final String command = req.getParameter( "COMMAND" );

		out.println( HEADER );
		out.println( "<body>" );

//		out.print("<h2>");
		out.print("<div style=\"font-size:1.5em;\">");
		out.print( req.getServerName() );
		out.print( ":" );
		out.print( req.getServerPort() );
		out.print( req.getContextPath() );
//		out.println("</h2>");
		out.println("</div>");

		if( "infomation".equalsIgnoreCase( command ) ) {
			out.print( getInfomation() );
		}
		else if( "close".equalsIgnoreCase( command ) ) {
			out.print( getCloseMessage( req.getSession() ) );
		}
		else if( "loginUser".equalsIgnoreCase( command ) ) {
			final String sort  = req.getParameter( "sort" );
			final String direc = req.getParameter( "direc" );
			// 6.3.9.1 (2015/11/27) 3項演算子を || or && で簡素化できる(PMD)。
			final boolean dir = direc == null || Boolean.parseBoolean( direc );	// 6.3.9.1 (2015/11/27)

			out.print( COMMON_MESSAGE );										// 6.4.4.1 (2016/03/18)
			out.print( getLoginUser(sort,dir) );
		}
		// 6.4.4.1 (2016/03/18) application ｵﾌﾞｼﾞｪｸﾄに関連付ける 共通ﾒｯｾｰｼﾞを設定します。
		else if( "commonMessage".equalsIgnoreCase( command ) ) {
			final String type    = req.getParameter( "type" );
			final String message = req.getParameter( "message" );
			out.print( setCommonMessage( type , message , req.getSession() ) );
		}
		else if( "plugin".equalsIgnoreCase( command ) ) {
			out.print( getPlugInInfo() );
		}
		else if( "taglib".equalsIgnoreCase( command ) ) {
			out.print( getTaglibInfo() );
		}
		else if( "systemResource".equalsIgnoreCase( command ) ) {
			out.print( getSystemResource() );
		}
		// 6.3.8.0 (2015/09/11) AccessStop を外部から制御できるように、ｺﾏﾝﾄﾞと状態を受けるようにする。
		else if( "AccessStop".equalsIgnoreCase( command ) ) {
			out.print( getAccessStop( req.getParameter( "stop" ) ) );		// 6.3.8.0 (2015/09/11)
		}
		// 5.9.1.0 (2015/10/02) UserInfoｾｯﾄ機能追加
		else if( "UserInfo".equalsIgnoreCase( command ) ){					// 5.9.1.0 (2015/10/02)
			out.print( setUserinfo( req ) );
		}
		// 6.3.8.3 (2015/10/03) Servlet/Filter 情報を作成。
		else if( "registrationInfo".equalsIgnoreCase( command ) ) {
			out.print( getRegistrationMessage( req.getSession() ) );
		}
//		else if( "fileexec".equalsIgnoreCase( command ) ) {					// 7.2.5.0 (2020/06/01)
//			out.print( getFileExecInfo( req.getParameter( "start" ) ) );
//		}
		else {
			out.print( getAdminLink() );									// 3.5.4.1 (2003/12/01) 追加
		}

		out.println("</body></html>");
	}

	/**
	 * infomation 情報を作成します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 5.6.7.3 (2013/08/23) TOMCAT_WORKは、TOMCAT_HOME に置き換えます。
	 * @og.rev 6.2.4.1 (2015/05/22) ﾃﾞｨｽｸ容量を求めます。
	 * @og.rev 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
	 * @og.rev 6.3.9.0 (2015/11/06) 整数値演算なので、Math.round 不要
	 * @og.rev 6.5.0.1 (2016/10/21) ENGINE_INFO は、直接、BuildNumber から取得する。
	 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"／＞" 止めを、"＞" に変更します)。
	 * @og.rev 7.1.0.0 (2020/01/20) OFFICE_HOME,EXT_DIR,SYS_LOG_URL,LOGS_DIR 環境変数の追加。
	 * @og.rev 8.2.0.2 (2022/06/24) HTML5廃止対応
	 * @og.rev 8.5.0.0 (2023/04/21) pache有無判定
	 *
	 * @return	infomation情報
	 * @og.rtnNotNull
	 */
	private String getInfomation() {
		// 4.0.0 (2005/01/31) ログイン数の取得方法の変更。
		final int loginCount = SystemManager.getRunningCount() ;

		final long freeMemory     = Runtime.getRuntime().freeMemory()/MB ;		// 6.3.9.0 (2015/11/06) 整数値演算なので、Math.round 不要
		final long totalMemory    = Runtime.getRuntime().totalMemory()/MB;		// 6.3.9.0 (2015/11/06) 整数値演算なので、Math.round 不要
		final long useMemoryRatio = (totalMemory-freeMemory)*100/totalMemory ;	// 6.3.9.0 (2015/11/06) 整数値演算なので、Math.round 不要
		final String bgCls = useMemoryRatio <= 50 ? "OK" : useMemoryRatio <= 80 ? "CAUT" : "NG" ;	// 6.9.7.0 (2018/05/14) PMD Useless parentheses.

		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );

		rtn.append( "<table border = \"0px\" >" );
//		// 7.1.0.0 (2020/01/20) static定義をやめて、getInfomation() ﾒｿｯﾄﾞ内で都度呼びます。
		tableTr1( rtn,"ｻｰﾊﾞｰ情報" );
		tableTr(  rtn,"OS情報"			, BuildNumber.OS_INFO );				// 6.5.0.1 (2016/10/21)
		tableTr(  rtn,"ｻｰﾊﾞｰ名"			, HybsSystem.sys( "SERVER_INFO"  ) );	// 10759278-0002
		tableTr(  rtn,"ｻｰﾌﾞﾚｯﾄ"			, HybsSystem.sys( "SERVLET_INFO" ) );	// Apache Tomcat/X.X.XX
		tableTr(  rtn,"TOMCAT_HOME"		, HybsSystem.sys( "TOMCAT_HOME"  ) );	// /apps/tomcatX.X.XX
		tableTr(  rtn,"　　ﾛｸﾞﾌｫﾙﾀﾞ"	, HybsSystem.sys( "TOMCAT_LOGS"  ) );	// /apps/tomcatX.X.XX/logs
		tableTr(  rtn,"JDKﾊﾞｰｼﾞｮﾝ"		, BuildNumber.JDK_INFO             );	// OpenJDK 64-Bit Server VM 11.0.5+10-LTS
		tableTr(  rtn,"JAVA_HOME"		, HybsSystem.sys( "JAVA_HOME"    ) );	// apps/jdkX.X.X
		tableTr(  rtn,"　　拡張ﾌｫﾙﾀﾞ"	, HybsSystem.sys( "EXT_DIR"      ) );	// /uap/bin/../../apps/endorsedX.X.X
		tableTr(  rtn,"OFFICE_HOME"		, HybsSystem.sys( "OFFICE_HOME"  ) );	// /uap/bin/../../apps/LibreOffice_X.X.X

//		// 7.1.0.0 (2020/01/20) static定義をやめて、getInfomation() ﾒｿｯﾄﾞ内で都度呼びます。
		tableTr1( rtn,"実行環境" );
		tableTr(  rtn,"ｻｰﾋﾞｽ起動"		, HybsSystem.sys( "IS_SERVICE"   ) , " [ " , HybsSystem.sys( "SERVICE_NAME" ) , " ] " );	// true [ ｻｰﾋﾞｽ名 ]
//		tableTr(  rtn,"REAL_PATH"		, HybsSystem.sys( "REAL_PATH"    ) );	// /uap/webapps/gf/
		tableTr(  rtn,"REAL_PATH"		, REALPATH                         );	// /uap/webapps/gf/ 8.5.0.0 (2023/04/21) Modify
		tableTr(  rtn,"ﾊﾞｰｼﾞｮﾝNo"		, BuildNumber.ENGINE_INFO          );	// 7.1.0.0 Release7 Builds (26324783)
		tableTr(  rtn,"作成日時"		, BuildNumber.TIMESTAMP            );	// 2020/01/20 11:23:37
		tableTr(  rtn,"pache有無"		, String.valueOf( isPache() ) , " [ " , CLSPATH , " ] " );	// true [ WEB-INF/classes ] 8.5.0.0 (2023/04/21) Add

		tableTr1( rtn,"ﾛｸﾞｲﾝ情報" );
		tableTr(  rtn,"ﾛｸﾞｲﾝ人数"		, String.valueOf( loginCount )," 名 ","( <a href=\"admin?COMMAND=loginUser\">明細情報</a> )" );

		tableTr1( rtn,"ﾒﾓﾘ情報" );
		tableTr(  rtn,"空きﾒﾓﾘ"			, String.valueOf( freeMemory     ) , " [MByte]" );	// 6.2.4.1 (2015/05/22) 単位を MB に変更
		tableTr(  rtn,"合計ﾒﾓﾘ"			, String.valueOf( totalMemory    ) , " [MByte]" );	// 6.2.4.1 (2015/05/22) 単位を MB に変更
		tableTr(  rtn,"使用率"			, String.valueOf( useMemoryRatio ) , " [％]"    );
		rtn.append( TABLE_END )
			// 6.2.4.1 (2015/05/22) default.css で、memory、disc、discTD を定義
//			.append( TABLE_WAKU ).append( "width=\"300px\" >" ).append( CR )
			.append( TABLE_WAKU ).append( "width:300px;\" >" ).append( CR )		// 8.2.0.2 (2022/06/24) Modify
			.append( "\t<tr><td class=\"memory " ).append( bgCls ).append( "\" style=\"width:" )
			.append( useMemoryRatio ).append( "%;\" >" ).append( useMemoryRatio ).append( "%</td>" )
			.append( "<td class=\"BIT\">" ).append( 100-useMemoryRatio ).append( "%</td></tr>" ).append( CR )
			.append( TABLE_END )

			// 6.2.4.1 (2015/05/22) ﾃﾞｨｽｸ容量を求めます。
			.append( "<table border=\"0px\" >" ).append( CR );
		tableTr1( rtn,"ﾃﾞｨｽｸ情報" );
		rtn.append( TABLE_END )
//			.append( TABLE_WAKU ).append( "width=\"500px\" >" ).append( CR )
			.append( TABLE_WAKU ).append( "width:500px;\" >" ).append( CR )		// 8.2.0.2 (2022/06/24) Modify
			.append( "<th>名前</th><th>合計ｻｲｽﾞ</th><th>空き領域</th><th>使用率</th></tr>" ).append( CR ).append( CR );

		final File[] driv = File.listRoots();
		for( final File file : driv ) {
			// 6.3.9.0 (2015/11/06) 整数値演算なので、Math.round 不要
			final long total	= file.getTotalSpace()/GB ;						// ﾊﾟｰﾃｨｼｮﾝのｻｲｽﾞ
			final long usable	= file.getUsableSpace()/GB ;					// 仮想ﾏｼﾝが利用できるﾊﾞｲﾄ数
			tableTr2( rtn, file.getPath() , total , usable );					// ﾃﾞｨｽｸ容量専用3
		}
		rtn.append( TABLE_END )

		// information
			.append( "<hr>" ).append( CR )										// 7.0.1.0 (2018/10/15) XHTML → HTML5
			.append( "<pre>" ).append( CR )
			.append( ConnectionFactory.information() ).append( CR )
			.append( "</pre>" ).append( CR );

		return rtn.toString();
	}

	/**
	 * infomation 情報を作成します。
	 *
	 * @og.rev 5.6.6.0 (2013/07/05) &lt;/td&gt;&lt;/tr&gt;漏れ追加
	 * @og.rev 5.6.7.3 (2013/08/23) 前後に、【】を付けます。
	 *
	 * @param	buf	情報登録用のStringBuilder
	 * @param	key	ｷｰ
	 *
	 * @return	infomation情報(入力bufと同じｵﾌﾞｼﾞｪｸﾄ)
	 * @og.rtnNotNull
	 */
	private StringBuilder tableTr1( final StringBuilder buf, final String key ) {
		return buf.append( "\t<tr><td colspan=\"4\"><b>【" )
				.append( key ).append( "】</b></td></tr>" )
				.append( CR );	// 【】追加
	}

	/**
	 * infomation 情報を作成します。
	 *
	 * @og.rev 5.6.6.0 (2013/07/05) 最初の td に、全角ｽﾍﾟｰｽ２個 追加
	 * @og.rev 8.2.0.2 (2022/06/24) HTML5廃止対応
	 *
	 * @param	buf	情報登録用のStringBuilder
	 * @param	key	ｷｰ
	 * @param	val	値の可変長引数
	 *
	 * @return	infomation情報(入力bufと同じｵﾌﾞｼﾞｪｸﾄ)
	 * @og.rtnNotNull
	 */
	private StringBuilder tableTr( final StringBuilder buf, final String key, final String... val ) {
		// 段を作成する為に、width指定 追加
//		buf.append( "\t<tr><td width=\"20px\">　</td><td>" ).append( key ).append( "</td><td> = </td><td>" );
		buf.append( "\t<tr><td style=\"width:20px;\">　</td><td>" ).append( key ).append( "</td><td> = </td><td>" );	// 8.2.0.2 (2022/06/24) Modify
		for( int i=0; i<val.length; i++ ) {
			buf.append( val[i] );
		}
//		return buf.append( "</td></tr>" ).append( CR );
		return buf.append( TD_TR );
	}

	/**
	 * infomation 情報を作成します。
	 *
	 * @og.rev 6.2.4.1 (2015/05/22) ﾃﾞｨｽｸ容量専用
	 * @og.rev 6.2.4.2 (2015/05/29) total が 0 の場合の対応
	 * @og.rev 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
	 *
	 * @param	buf		情報登録用のStringBuilder
	 * @param	name	ﾄﾞﾗｲﾌﾞ名
	 * @param	total	ﾊﾟｰﾃｨｼｮﾝのｻｲｽﾞ(GB)
	 * @param	usable	仮想ﾏｼﾝが利用できるｻｲｽﾞ(GB)
	 *
	 * @return	infomation情報(入力bufと同じｵﾌﾞｼﾞｪｸﾄ)
	 * @og.rtnNotNull
	 */
	private StringBuilder tableTr2( final StringBuilder buf, final String name, final long total, final long usable ) {
		final long useRatio = total == 0L ? 0L : (total-usable)*100/total ;		// 6.3.9.0 (2015/11/06) findBugs

		final String bgCls = useRatio <= 50 ? "OK" : useRatio <= 80 ? "CAUT" : useRatio <= 95 ? "WARN" : "NG" ;	// 6.9.7.0 (2018/05/14) PMD Useless parentheses.

//		return buf.append( "\t<tr><td class=\"BIT\">" ).append( name ).append( "</td>" )
//			.append( "<td class=\"S9\" >" ).append( total  ).append( " GB</td>" )
//			.append( "<td class=\"S9\" >" ).append( usable ).append( " GB</td>" ).append( CR )
//			.append( "\t\t<td class=\"discTD\" ><span class=\"disc " ).append( bgCls )
//			.append( "\" style=\"width:" ).append( useRatio ).append( "%;\" >" )
//			.append( useRatio ).append( "%</span>　</td></tr>" ).append( CR );

		// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
		return buf.append( "\t<tr><td class=\"BIT\">"	)
			.append( name		).append( "</td><td class=\"S9\" >" )
			.append( total		).append( " GB</td><td class=\"S9\" >" )
			.append( usable		).append( " GB</td>" ).append( CR )
			.append( "\t\t<td class=\"discTD\" ><span class=\"disc " )
			.append( bgCls		).append( "\" style=\"width:" )
			.append( useRatio	).append( "%;\" >" )
			.append( useRatio	).append( "%</span>　</td></tr>" ).append( CR );
	}

	/**
	 * infomation 情報の pache有無 を判定します。
	 *
	 * @og.rev 8.5.0.0 (2023/04/21) pache有無判定
	 *
	 * @return	pache有無[true:有/false:無]
	 */
	private boolean isPache() {
		final ArrayList<File> list = new ArrayList<>();

		final Path path = Paths.get( CLSPATH );
		// ﾌｧｲﾙやﾃﾞｨﾚｸﾄﾘの一覧をｻﾌﾞﾃﾞｨﾚｸﾄﾘの中まで含めて取得する
		try( final Stream<Path> stream = Files.walk(path) ) {
			stream.map(Path::toFile)
				  .filter(file -> !file.isDirectory())
				  .filter(file -> file.getName().endsWith(".class"))
				  .forEach(list::add);
		}catch( final IOException ex ) {
			return false;
		}
		return ! list.isEmpty();
	}

	/**
	 * close 情報を作成します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 3.6.0.0 (2004/09/17) CalendarFactory.clear() を追加します。
	 * @og.rev 4.0.0.0 (2005/01/31) Cleanable ｲﾝﾀｰﾌｪｰｽによる初期化処理
	 * @og.rev 4.1.0.2 (2008/01/29) UserInfoをsessionから消去する(超暫定対応)
	 * @og.rev 5.6.6.0 (2013/07/05) UserSummary の削除処理は、SystemManager から行う。
	 * @og.rev 6.3.7.0 (2015/09/04) ﾌｧｲﾅﾗｲｽﾞを呼び出します。
	 * @og.rev 7.2.9.4 (2020/11/20) PMD:Do not explicitly trigger a garbage collection.
	 *
	 * @param	session	HttpSessionｵﾌﾞｼﾞｪｸﾄ
	 *
	 * @return	close情報
	 * @og.rtnNotNull
	 */
	private String getCloseMessage( final HttpSession session ) {

		// 4.0.0 (2005/01/31) Cleanable ｲﾝﾀｰﾌｪｰｽによる初期化処理
		SystemManager.allClear( false ) ;

		final ServletContext context = session.getServletContext();
		final Map<String,String> param = SystemParameter.makeSystemParameter( context );
		HybsSystem.setInitialData( param );			// 4.0.0 (2005/01/31)

		// 5.6.6.0 (2013/07/05) UserSummary の削除処理は、SystemManager から行う。
		SystemManager.removeSession( session ) ;

		// 6.3.7.0 (2015/09/04) ﾌｧｲﾅﾗｲｽﾞを呼び出します。
		// 7.2.9.4 (2020/11/20) PMD:Do not explicitly trigger a garbage collection.
//		System.runFinalization();
//	//	System.gc();					// 取りあえず、GCは呼びません。

		return "<pre>"
			+ "キャッシュ情報をクリアしました。"											+ CR
			+ "ユーザー情報の初期化に関しては、ブラウザを閉じて、再ログインが必要です。"	+ CR
			+ ConnectionFactory.information()
			+ "</pre>" ;
	}

	/**
	 * loginUser 情報を作成します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 3.8.5.3 (2006/08/07) ﾕｰｻﾞｰ情報をｿｰﾄするためのｷｰ情報を追加
	 * @og.rev 3.8.7.0 (2006/12/15) USER.LASTACCESS情報を追加します。
	 * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属性(CLS_NM)から、DBTYPEに変更
	 * @og.rev 4.4.0.1 (2009/08/08) 最終ﾛｸﾞｲﾝ画面名称を追加
	 * @og.rev 5.6.6.0 (2013/07/05) table作成処理を、変更します。
	 * @og.rev 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
	 * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
	 * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
	 * @og.rev 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
	 *
	 * @param	sort	ｿｰﾄするｷｰ項目を指定
	 * @param	direc	ｿｰﾄする方向 [true:昇順/false:降順]
	 *
	 * @return	loginUser情報
	 * @og.rtnNotNull
	 */
	private String getLoginUser( final String sort,final boolean direc ) {
		// 4.0.0 (2005/01/31) ﾛｸﾞｲﾝ数の取得方法の変更。
		final int loginCount = SystemManager.getRunningCount() ;

		// 4.0.0 (2005/01/31)
		final UserSummary[] userInfos = SystemManager.getRunningUserSummary( sort,direc );

		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
			.append( "現在 "   ).append( loginCount   ).append( " 名の方がログイン中です。" ).append( CR )
			.append( "<table " ).append( TABLE_HEADER ).append( " >" )
			.append( "<thead><tr><th>No</th>" );

		// 5.6.6.0 (2013/07/05) table作成処理を、変更します。
		for( final String sortKey : USER_KEYS ) {
			rtn.append( "<th><a href=\"?COMMAND=loginUser&sort=" ).append( sortKey )
				.append( "&direc=" ).append( !direc )
				.append( "\">" ).append( sortKey ).append( "</a></th>" );
		}

		// 7.0.4.0 (2019/05/31) colgroup 廃止
		rtn.append( "</tr></thead>" ).append( CR )
			.append( CR );

//		for( int i=0; i<userInfos.length; i++ ) {
//			final UserSummary userInfo = userInfos[i] ;
//			rtn.append( " <tr class=\"row_" ).append( i%2 ).append( "\" >" )
//				.append( "<td class='S9'>" ).append( String.valueOf( i+1 )	).append( "</td>"	)	// 7.0.4.0 (2019/05/31)
//				.append( "<td>" ).append( userInfo.getUserID()				).append( "</td>"	)
//				.append( "<td>" ).append( userInfo.getJname()				).append( "</td>"	)
//				.append( "<td>" ).append( userInfo.getRoles()				).append( "</td>"	)
//				.append( "<td>" ).append( userInfo.getIPAddress()			).append( "</td>"	)
//				.append( "<td>" ).append( HybsSystem.getDate( userInfo.getLoginTime() ) ).append( "</td>" )
//				.append( "<td>" ).append( userInfo.getAttribute( "LASTACCESS" )			).append( "</td>" )
//				.append( "<td>" ).append( StringUtil.nval( userInfo.getAttribute( "LASTGAMENNM" ), "" ) ).append( "</td>" )	// 4.4.0.1 (2009/08/08)
//				.append( " </tr>" ).append( CR );
//		}

		// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
		for( int i=0; i<userInfos.length; i++ ) {
			final UserSummary userInfo = userInfos[i] ;
			rtn.append( " <tr class=\"row_" ).append( i%2 )
				.append( "\" ><td class='S9'>" ).append( String.valueOf( i+1 )	)	// 7.0.4.0 (2019/05/31)
				.append( TD_TD ).append( userInfo.getUserID()			)
				.append( TD_TD ).append( userInfo.getJname()			)
				.append( TD_TD ).append( userInfo.getRoles()			)
				.append( TD_TD ).append( userInfo.getIPAddress()		)
				.append( TD_TD ).append( HybsSystem.getDate( userInfo.getLoginTime() ) )
				.append( TD_TD ).append( userInfo.getAttribute( "LASTACCESS" )			)
				.append( TD_TD ).append( StringUtil.nval( userInfo.getAttribute( "LASTGAMENNM" ), "" ) )	// 4.4.0.1 (2009/08/08)
				.append( TD_TR );
		}
		return rtn.append( TABLE_END ).toString();
	}

	/**
	 * PlugIn 情報を作成します。
	 *
	 * @og.rev 4.0.0.0 (2005/08/31) 新規作成
	 * @og.rev 5.6.6.0 (2013/07/05) "DBConstValue","Daemon","JspCreate" を、追加します。
	 * @og.rev 7.1.0.0 (2020/01/27) pluginType をstatic で定義しておきます。
	 *
	 * @return	PlugIn情報
	 * @og.rtnNotNull
	 */
	private String getPlugInInfo() {
		final ClassInfo info = new ClassInfo();

		for( int j=0; j<PLUGIN_TYPE.length; j++ ) {
			final String type = PLUGIN_TYPE[j] ;
			final HybsEntry[] names = HybsSystem.sysEntry( type + "_" );
			for( int i=0; i<names.length; i++ ) {
				final String key		= names[i].getKey().substring( type.length()+1 );
				final String clsName	= names[i].getValue();
				info.addLine( type,key,clsName );
			}
		}
		return info.getClassInfoData() ;
	}

	/**
	 * Taglib 情報を作成します。
	 *
	 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
	 * @og.rev 5.3.6.0 (2011/06/01) Taglib ｸﾗｽ名の求め方を変更します。(jar版のみ)
	 * @og.rev 5.5.2.6 (2012/05/25) JarFile を、Closer#zipClose( ZipFile ) ﾒｿｯﾄﾞを利用して、close します。
	 * @og.rev 6.8.5.1 (2018/01/15) ﾌｧｲﾙ名は、##ﾊﾞｰｼﾞｮﾝ番号を変換しておく必要がある。
	 *
	 * @return	Taglib情報
	 * @og.rtnNotNull
	 */
	private String getTaglibInfo() {
		final ClassInfo info = new ClassInfo();

		// 5.5.2.6 (2012/05/25) findbugs対応
		JarFile jarFile = null;
		try {
			final ClassLoader loader = Thread.currentThread().getContextClassLoader();
			final Enumeration<URL> enume = loader.getResources( "org/opengion/hayabusa/taglib/" );	// 4.3.3.6 (2008/11/15) Generics警告対応
			while( enume.hasMoreElements() ) {
				final URL url = enume.nextElement();							// 4.3.3.6 (2008/11/15) Generics警告対応
				// jar:file:/実ディレクトリ または、file:/実ディレクトリ
				final String dir = url.getFile().replaceAll( "%23%23","##" );	// 6.8.5.1 (2018/01/15)
				if( "jar".equals( url.getProtocol() ) ) {
					// dir = file:/G:/webapps/gf/WEB-INF/lib/hayabusa4.0.0.jar!/org/opengion/hayabusa/taglib 形式です。
					final String jar = dir.substring(dir.indexOf( ':' )+1,dir.lastIndexOf( '!' ));
					// jar = /G:/webapps/gf/WEB-INF/lib/hayabusa4.0.0.jar 形式に切り出します。
					jarFile = new JarFile( jar );
					final Enumeration<JarEntry> en = jarFile.entries() ;		// 4.3.3.6 (2008/11/15) Generics警告対応
					while( en.hasMoreElements() ) {
						final JarEntry ent = en.nextElement();					// 4.3.3.6 (2008/11/15) Generics警告対応
						final String file = ent.getName();
						if( ! ent.isDirectory() && file.endsWith( "Tag.class" ) ) {
							final String type		= "Taglib_jar";
							// 5.3.6.0 (2011/06/01) Taglib クラス名の求め方を変更します。(jar版のみ)
							final String key		= file.substring( file.lastIndexOf( '/' )+1,file.length()-6 );	// -6 は、.class 分
							final String clsName	= file.replace( '/','.' ).substring( 0,file.length()-6 );
							info.addLine( type,key,clsName );
						}
					}
					Closer.zipClose( jarFile );									// 5.5.2.6 (2012/05/25) findbugs対応
					jarFile = null;												// 正常終了時に、close() が2回呼ばれるのを防ぐため。
				}
				else {
					// dir = /G:/webapps/gf/WEB-INF/classes/org/opengion/hayabusa/taglib/ 形式です。
					final File[] list = new File( dir ).listFiles();
					// 6.3.9.0 (2015/11/06) null になっている可能性がある(findbugs)
					if( list != null ) {
						for( final File file : list ) {
							final String name = file.getName() ;
							if( file.isFile() && name.endsWith( "Tag.class" ) ) {
								final String type		= "Taglib_file";
								final String key		= name.substring( 0,name.length()-6 );
								final String clsName	= "org.opengion.hayabusa.taglib." + key ;
								info.addLine( type,key,clsName );
							}
						}
					}
				}
			}
		}
		catch( final IOException ex ) {
			final String errMsg = "taglibファイル読み取りストリームを失敗しました。"
					+ CR + ex.getMessage();
			throw new OgRuntimeException( errMsg,ex );
		}
		finally {
			Closer.zipClose( jarFile );		// 5.5.2.6 (2012/05/25) findbugs対応
		}

		return info.getClassInfoData() ;
	}

	/**
	 * ｸﾗｽ情報を表示するためのﾃﾞｰﾀを管理します。
	 * ここでは、引数に渡された、分類(Classify)、名称(Key Name)、ｸﾗｽ名(Class Name)、
	 * ﾊﾞｰｼﾞｮﾝ(Version)情報をﾃｰﾌﾞﾙ形式で表示します。
	 * ﾊﾞｰｼﾞｮﾝ情報は、ｸﾗｽ名から、ｲﾝｽﾀﾝｽを作成して、private static final String VERSION
	 * ﾌｨｰﾙﾄﾞの値を読み取ります。
	 *
	 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
	 * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
	 * @og.rev 7.1.0.0 (2020/01/27) ﾍｯﾀﾞｰ部分をstatic で定義しておきます。
	 */
	private static final class ClassInfo {
		private static final String HEADER =
			"<table " + TABLE_HEADER + " >" + CR +
			"	<thead><tr><th>No</th><th>Classify</th><th>Key Name</th><th>Class Name</th><th>Version</th></tr></thead>" + CR ;

		private final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
		private int cnt;

		/**
		 * ｺﾝｽﾄﾗｸﾀｰ
		 *
		 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
		 * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
		 * @og.rev 7.1.0.0 (2020/01/27) ﾍｯﾀﾞｰ部分をstatic で定義しておきます。
		 */
		public ClassInfo() {
			rtn.append( HEADER );			// 7.1.0.0 (2020/01/27)
		}

		/**
		 * ﾃｰﾌﾞﾙ表示用のﾃﾞｰﾀを追加します。
		 *
		 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
		 * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
		 * @og.rev 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
		 *
		 * @param	type	ﾀｲﾌﾟ属性
		 * @param	key		ｷｰ属性
		 * @param	clsName	ｸﾗｽ名(このｸﾗｽ名からｲﾝｽﾀﾝｽ化します。)
		 */
		public void addLine( final String type, final String key, final String clsName ) {
			final String version	= getFieldValue( clsName );

			final boolean isCustom =   version.compareTo( BuildNumber.VERSION_NO ) > 0
									|| version.indexOf( "Pache"   ) >= 0
									|| version.indexOf( "Nightly" ) >= 0 ;

			final String trType = isCustom ? "warning" : String.valueOf( cnt%2 );

//			rtn.append( "<tr class=\"row_" ).append( trType ).append( "\" >" )
//				.append( "<td class='S9'>"	).append( cnt++		).append( "</td>" )	// 7.0.4.0 (2019/05/31)
//				.append( "<td>"				).append( type		).append( "</td>" )
//				.append( "<td>"				).append( key		).append( "</td>" )
//				.append( "<td>"				).append( clsName	).append( "</td>" )
//				.append( "<td>"				).append( version	).append( "</td>" )
//				.append( "</tr>" ).append( CR );

			// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
			rtn.append( "<tr class=\"row_" ).append( trType )
				.append( "\" ><td class='S9'>"	).append( cnt++		)			// 7.0.4.0 (2019/05/31)
				.append( TD_TD ).append( type	)
				.append( TD_TD ).append( key		)
				.append( TD_TD ).append( clsName	)
				.append( TD_TD ).append( version	)
				.append( TD_TR );
		}

		/**
		 * すべての内部のﾃﾞｰﾀを文字列化して返します。
		 *
		 * @og.rev 4.0.0.0 (2006/01/31) 新規作成
		 * @og.rev 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
		 *
		 * @return	作成されたﾃｰﾌﾞﾙﾃﾞｰﾀ
		 * @og.rtnNotNull
		 */
		public String getClassInfoData() {
			return rtn.append( TABLE_END ).toString();
		}

		/**
		 * 指定のｵﾌﾞｼﾞｪｸﾄの VERSION staticﾌｨｰﾙﾄﾞの値を取得します。
		 *
		 * @og.rev 4.0.0.0 (2005/08/31) 新規作成
		 * @og.rev 6.4.3.3 (2016/03/04) HybsSystem#newInstance(String) ではなく、直接Class#forName(String)から、求めます。
		 *
		 * @param	clsName	指定のｸﾗｽを表す名称
		 * @return	VERSIONﾌｨｰﾙﾄﾞの値(ｴﾗｰ時は、そのﾒｯｾｰｼﾞ)
		 */
		private String getFieldValue( final String clsName ) {
			String rtn ;
			try {
				final Field fld = Class.forName( clsName ).getDeclaredField( "VERSION" ) ;

				// privateﾌｨｰﾙﾄﾞの取得には、accessibleﾌﾗｸﾞを trueにする必要があります。
				fld.setAccessible( true );

				rtn = (String)fld.get( null );
			}
			catch( final Throwable ex ) {
				rtn = ex.getMessage();
			}
			return rtn ;
		}
	}

	/**
	 * systemResource 情報を作成します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属性(CLS_NM)から、DBTYPEに変更
	 * @og.rev 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
	 * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
	 * @og.rev 6.4.3.3 (2016/03/04) 配列返しではなく、Map を返します。
	 * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
	 * @og.rev 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
	 *
	 * @return	systemResource情報
	 * @og.rtnNotNull
	 */
	private String getSystemResource() {
		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
			.append( "<table " ).append( TABLE_HEADER ).append( " >" ).append( CR )
			.append( "<thead><tr><th>No</th><th>Key</th><th>Value</th></tr></thead>" ).append( CR )
			.append( CR );

		// 6.4.3.3 (2016/03/04) 配列返しではなく、Map を返します。
		final ConcurrentMap<String,String> rscMap = HybsSystem.getSystemResourceMap();
		int i=0;
//		for( final Map.Entry<String,String> entry : rscMap.entrySet() ) {
//			rtn.append( "<tr class=\"row_" ).append( i%2 ).append( "\" >" ).append( CR )
//				.append( "<td class='S9'>" ).append( ++i	).append( "</td>" )	// 7.0.4.0 (2019/05/31)
//				.append( "<td>" ).append( entry.getKey()	).append( "</td>" )
//				.append( "<td>" ).append( entry.getValue()	).append( "</td>" )
//				.append( "</tr>" ).append( CR );
//		}
		// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
		for( final Map.Entry<String,String> entry : rscMap.entrySet() ) {
			rtn.append( "<tr class=\"row_" ).append( i%2 )
				.append( "\" ><td class='S9'>" ).append( ++i )					// 7.0.4.0 (2019/05/31)
				.append( TD_TD ).append( entry.getKey()		)
				.append( TD_TD ).append( entry.getValue()	)
				.append( TD_TR );
		}
		return rtn.append( TABLE_END ).toString();
	}

	/**
	 * AccessStop 情報を作成します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) 機能ごとにﾒｿｯﾄﾞを呼び出すように修正します。
	 * @og.rev 4.0.0.0 (2007/11/29) AccessStopFilter#getStopFilter() ⇒ isStopFilter() に変更
	 * @og.rev 6.1.1.0 (2015/01/17) ﾊﾟｯｹｰｼﾞを import するのと、ﾛｼﾞｯｸ見直し。
	 * @og.rev 6.3.8.0 (2015/09/11) AccessStop を外部から制御できるように、ｺﾏﾝﾄﾞと状態を受けるようにする。
	 * @og.rev 7.1.0.0 (2020/01/20) 本物のｻｰﾋﾞｽと混同しないようにﾒｯｾｰｼﾞを変更します。
	 *
	 * @param	isStop		true:停止/false:実行
	 * @return	AccessStop情報
	 * @og.rtnNotNull
	 */
	private String getAccessStop( final String isStop ) {
		final boolean flag = Boolean.parseBoolean( isStop );					// 6.3.8.0 (2015/09/11)

		return flag ? "Webアプリケーションへのアクセスを停止します。"
					: "Webアプリケーションへのアクセスを開始します。";
	}

//	/**
//	 * fileexecのMainProcess 情報を作成します。
//	 *
//	 * @og.rev 7.2.5.0 (2020/06/01) fileexecのMainProcess の処理が起動しているかどうかを表示
//	 *
//	 * @param	isStart		true:実行/false:停止
//	 * @return	fileexec情報
//	 * @og.rtnNotNull
//	 */
//	private String getFileExecInfo( final String isStart ) {
//		final String reload = "<script>parent.QUERY.location.reload(true);</script>" ;
//
//		final String msg ;
//
//		if( Boolean.parseBoolean( isStart ) ) {
//			MainProcess.start();
//			msg = "ﾌｧｲﾙ取込処理を実行しました。";
//		}
//		else {
//			MainProcess.shutdown( false );	// 再実行できるようにしておきます。
//			msg = "ﾌｧｲﾙ取込処理を停止しました。";
//		}
//
//		return msg + reload;
//	}

	/**
	 * application ｵﾌﾞｼﾞｪｸﾄに関連付ける 共通ﾒｯｾｰｼﾞを設定します。
	 *
	 * 取り出しは、errorMessageﾀｸﾞで行います。これは、個々のrequest.jsp に組み込まれている
	 * ﾒｯｾｰｼﾞなので、ここで登録したﾒｯｾｰｼﾞは、同時に、すべてのｱｸｾｽしているﾕｰｻﾞｰが
	 * 見ることになります。
	 *
	 * @og.rev 6.4.4.1 (2016/03/18) application ｵﾌﾞｼﾞｪｸﾄに関連付ける 共通ﾒｯｾｰｼﾞを設定します。
	 * @og.rev 6.8.5.0 (2018/01/09) 共通ﾒｯｾｰｼﾞで、strongﾀｸﾞのﾊﾞｸﾞ修正と、class="common_msg" 追加。
	 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"／＞" 止めを、"＞" に変更します)。
	 *
	 * @param	type	[set/clear] を指定します。
	 * @param	message	共通ﾒｯｾｰｼﾞを指定します。
	 * @param	session	HttpSessionｵﾌﾞｼﾞｪｸﾄ
	 *
	 * @return	Servlet/Filter情報
	 * @og.rtnNotNull
	 */
	private String setCommonMessage( final String type , final String message , final HttpSession session ) {
		final ServletContext context = session.getServletContext();

		String rtMsg = "";
		if( "set".equalsIgnoreCase( type ) && message != null && message.length() > 0 ) {
			rtMsg = "<strong class=\"common_msg\">" + message + "</strong><br>";	// 7.0.1.0 (2018/10/15)
			context.setAttribute( HybsSystem.COMMON_MSG_KEY,rtMsg );
		}
		else if( "get".equalsIgnoreCase( type ) ) {
			rtMsg = (String)context.getAttribute( HybsSystem.COMMON_MSG_KEY );
		}
		else if( "clear".equalsIgnoreCase( type ) ) {
			context.removeAttribute( HybsSystem.COMMON_MSG_KEY );
		}

		return rtMsg;
	}

	/**
	 * Servlet/Filter 情報を作成します。
	 *
	 * @og.rev 6.3.8.3 (2015/10/03) Servlet/Filter 情報を作成。
	 * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
	 * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
	 * @og.rev 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
	 *
	 * @param	session	HttpSessionｵﾌﾞｼﾞｪｸﾄ
	 *
	 * @return	Servlet/Filter情報
	 * @og.rtnNotNull
	 */
	private String getRegistrationMessage( final HttpSession session ) {
		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
			// 速度よりｿｰｽの見易さ
			.append( "<table " ).append( TABLE_HEADER ).append( " >" )
			.append( "<thead><tr><th>No</th><th>Type</th><th>Key</th><th>Class</th><th>Mappings</th></tr></thead>" )
			.append( CR );

		int no = 0;
		final ServletContext context = session.getServletContext();
		for( final ServletRegistration reg : context.getServletRegistrations().values() ) {
//			// 速度よりｿｰｽの見易さ
//			rtn.append( "<tr class=\"row_" ).append( no%2 ).append( "\" >" )
//				.append( "<td class='S9'>" ).append( String.valueOf( ++no ) ).append( "</td>" )	// 7.0.4.0 (2019/05/31)
//				.append( "<td>Servlet</td>" )
//				.append( "<td>" ).append( reg.getName()			).append( "</td>" )
//				.append( "<td>" ).append( reg.getClassName()	).append( "</td>" )
//				.append( "<td>" ).append( reg.getMappings()		).append( "</td>" )
//				.append( "</tr>" ).append( CR );
			// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
			rtn.append( "<tr class=\"row_" ).append( no%2 )
				.append( "\" ><td class='S9'>" ).append( String.valueOf( ++no ) )	// 7.0.4.0 (2019/05/31)
				.append( TD_TD ).append( "Servlet"			)
				.append( TD_TD ).append( reg.getName()		)
				.append( TD_TD ).append( reg.getClassName()	)
				.append( TD_TD ).append( reg.getMappings()	)
				.append( TD_TR );
		}

		for( final FilterRegistration reg : context.getFilterRegistrations().values() ) {
//			// 速度よりｿｰｽの見易さ
//			rtn.append( "<tr class=\"row_" ).append( no%2 ).append( "\" >" )
//				.append( "<td class='S9'>" ).append( String.valueOf( ++no )	  ).append( "</td>" )	// 7.0.4.0 (2019/05/31)
//				.append( "<td>Filter</td>" )
//				.append( "<td>" ).append( reg.getName()				  ).append( "</td>" )
//				.append( "<td>" ).append( reg.getClassName()		  ).append( "</td>" )
//				.append( "<td>" ).append( reg.getUrlPatternMappings() ).append( "</td>" )
//				.append( "</tr>" ).append( CR );
			// 7.2.6.0 (2020/06/30) StringBuilderの連結部見直し
			rtn.append( "<tr class=\"row_" ).append( no%2 )
				.append( "\" ><td class='S9'>" ).append( String.valueOf( ++no ) )	// 7.0.4.0 (2019/05/31)
				.append( TD_TD ).append( "Filter"						)
				.append( TD_TD ).append( reg.getName()					)
				.append( TD_TD ).append( reg.getClassName()				)
				.append( TD_TD ).append( reg.getUrlPatternMappings()	)
				.append( TD_TR );
		}
		return rtn.append( TABLE_END ).toString();
	}

	/**
	 * admin ﾘﾝｸ情報を作成します。
	 * 簡易ﾒｿｯﾄﾞなので、国際化対応していません。
	 *
	 * @og.rev 3.5.4.1 (2003/12/01) 新規作成
	 * @og.rev 5.1.1.2 (2009/12/10) 画面IDを変更
	 * @og.rev 5.6.3.4 (2013/04/26) ｸｲｯｸﾘﾌｧﾚﾝｽ 画面を追加
	 * @og.rev 6.3.6.1 (2015/08/28) <table> 枠の指定と、</table> の static final String 化
	 * @og.rev 6.3.8.0 (2015/09/11) AccessStop を外部から制御できるように、ｺﾏﾝﾄﾞと状態を受けるようにする。
	 * @og.rev 6.9.2.1 (2018/03/12) ﾘﾝｸが横に長くなってきたので、２段に折り返します。
	 * @og.rev 7.0.0.1 (2018/10/09) 一旦、[ﾌﾟﾗｸﾞｲﾝ情報],[ﾀｸﾞﾘﾌﾞ情報],[Servlet/Filter情報],[ｼｽﾃﾑ状況] を削除します。
	 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"／＞" 止めを、"＞" に変更します)。
	 * @og.rev 7.1.0.0 (2020/01/20) logLink.jsp 、serviceRestart.jsp 追加。AccessStopのON/OFF追加
	 * @og.rev 7.1.0.0 (2020/01/27) static で定義しておきます。
	 * @og.rev 8.4.2.2 (2023/03/17) 戻る を用意しておく
	 *
	 * @return	ｱﾄﾞﾐﾝﾘﾝｸ情報
	 * @og.rtnNotNull
	 */
	private String getAdminLink() {
		// 7.1.0.0 (2020/01/20) AccessStopのON/OFF追加
		final String accessStop = "true".equalsIgnoreCase( System.getProperty( "AccessStopFilter" ) )
										? ACCESS_STOP : "" ;

		// 7.1.0.0 (2020/01/20) logLink.jsp 、serviceRestart.jsp 追加
		final String serviceRestart = "true".equalsIgnoreCase( HybsSystem.sys( "IS_SERVICE" ) )
										? SERVICE_RESTART : "" ;

		// 7.1.0.0 (2020/01/27) static で定義しておきます。
		return new StringBuilder( BUFFER_MIDDLE )
			.append( "<style> body { overflow-y: hidden; } </style>" )
			.append( "<table><tr>"	 ).append( CR )
			.append( INFOMATION		 )
			.append( CLOSE			 )
			.append( LOGIN_USER		 )
			.append( QUICK_REFERENCE )
			.append( SYSTEM_RESOURCE )
			.append( PARAMETER		 )
			.append( LOGLINK		 )
			.append( serviceRestart	 )
//			.append( "</tr>" ).append( CR ).append( "<tr><td /><td />" ).append( CR )
//			.append( "</tr>" ).append( CR ).append( "<tr><td />" ).append( CR )	// 7.2.5.0 (2020/06/01)

			.append( "</tr>" ).append( CR ).append( "<tr>" ).append( CR )	// 8.4.2.2 (2023/03/17) 戻る を用意しておく
			.append( HISTORY_BACK	 )										// 8.4.2.2 (2023/03/17) 戻る を用意しておく
			.append( PLUGIN			 )
			.append( TAGLIB			 )
			.append( REGISTRATION	 )
			.append( SYSTEM_INFO	 )
			.append( accessStop		 )
	//		.append( fileExecCmnt()	 )											// 7.2.5.0 (2020/06/01)
			.append( "</tr>" ).append( TABLE_END )
			.toString();
	}

	/**
	 * DBTableModel から ﾃｰﾌﾞﾙのﾀｸﾞ文字列を作成して返します。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) User情報のﾃｰﾌﾞﾙの設定を、ｼｽﾃﾑﾘｿｰｽ より行う。
	 * @og.rev 5.2.2.0 (2010/11/01) SystemData 見直し漏れの対応。
	 * @og.rev 8.2.0.2 (2022/06/24) HTML5廃止対応
	 *
	 * @return	ﾃｰﾌﾞﾙのﾀｸﾞ文字列
	 * @og.rtnNotNull
	 */
	private static String getTableHeaderTag() {
		// 6.1.1.0 (2015/01/17) Attributesの連結記述
		return new Attributes()
					.set( "id"		,"viewTable"	)							// 3.6.0.5 (2004/10/18)
//					.set( "summary"	,"layout"		)							// ｻﾏﾘｰ 8.2.0.2 (2022/06/24) Delete
					.getAttribute();
	}

	/**
	 * userInfo 情報をｾｯﾄします。
	 * 現状、このﾒｿｯﾄﾞではLANGのみ設定可能です。
	 * (予約語以外のｾｯﾄはuserInfoﾀｸﾞで行う)
	 *
	 * LANGではuserInfoを切り替えた後にﾕｰｻﾞのGUIInfoを再ﾛｰﾄﾞします。
	 *
	 * @og.rev 5.9.1.0 (2015/10/02) 新規作成
	 *
	 * @param	req	HttpServletRequestｵﾌﾞｼﾞｪｸﾄ
	 * @return	結果情報
	 */
	private String setUserinfo( final HttpServletRequest req ) {
		final HttpSession session = req.getSession();
		final UserInfo userInfo = (UserInfo)(session.getAttribute( HybsSystem.USERINFO_KEY ));

		final String infoLang = req.getParameter( "LANG" );

		String rtn = null ;
		if( userInfo != null && infoLang != null && infoLang.length() > 0) {
			userInfo.setLang( infoLang );
			ResourceFactory.newInstance( userInfo.getLang() ).makeGUIInfos( userInfo );
			rtn = "User language : " + infoLang;
		}

		if( rtn == null || rtn.length() == 0 ) {
			rtn = "Error";
		}

		return rtn ;
	}
}
