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.common;
017
018import org.opengion.fukurou.system.OgRuntimeException ;                         // 6.4.2.0 (2016/01/29)
019import org.opengion.fukurou.system.LogWriter;
020import org.opengion.fukurou.system.DateSet;                                                     // 6.4.2.0 (2016/01/29)
021import org.opengion.fukurou.system.MsgUtil;                                                     // 6.4.3.2 (2016/02/19)
022// import org.opengion.fukurou.system.HybsConst;                                                // 5.10.9.0 (2019/03/01)
023import org.opengion.fukurou.util.StringUtil;
024import org.opengion.fukurou.util.HybsEntry;
025import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
026import static org.opengion.fukurou.system.HybsConst.FS;                         // 6.1.0.0 (2014/12/26) refactoring
027import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.2.6.0 (2015/06/19)
028
029import java.util.Set;
030import java.util.TreeSet;                                                                                       // 6.4.3.3 (2016/03/04)
031
032import java.util.Map;
033import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
034import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.1 (2016/02/12) refactoring
035import java.util.concurrent.ConcurrentSkipListMap;                                      // 6.4.3.3 (2016/03/04)
036import java.util.Locale;                                                                                        // 6.4.3.2 (2016/02/19)
037import java.io.File;                                                                                            // 6.2.4.1 (2015/05/22) REAL_PATH 対応
038import java.net.InetAddress;
039// import java.net.UnknownHostException;                                                        // 7.0.6.4 (2019/11/29) エラー全てを捉える
040
041import javax.print.PrintServiceLookup;                                                          // 6.2.6.0 (2015/06/19)
042import javax.print.PrintService;                                                                        // 6.2.6.0 (2015/06/19)
043
044/**
045 * 共通的に、使用されるシステム関連メソッドを集約したクラスです。
046 *
047 * 全変数は、public static final 宣言されています。
048 * メソッドは、日付取得,エラーメッセージ処理 を行っています。
049 *
050 * @og.group 初期化
051 *
052 * @version  4.0
053 * @author       Kazuhiko Hasegawa
054 * @since    JDK5.0,
055 */
056public final class HybsSystem {
057
058        /** システム設定DBのキーと値を、Map に読み込みます。  */
059        // 4.0.0 (2005/01/31) システムパラメータの管理オブジェクト
060        /** 6.4.3.1 (2016/02/12) ConcurrentHashMap で同期処理を行います。  */
061        private static final ConcurrentMap<String,String> SYS_MAP = new ConcurrentHashMap<>();                                  // 6.4.3.3 (2016/03/04)
062
063        // 4.3.1.0 (2008/09/03) リクエストでのみ生成できる設定値のキャッシュ
064        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。  */
065        private static final ConcurrentMap<String, String> REQ_CACHE = new ConcurrentHashMap<>();               // 6.4.9.1 (2016/08/05) reqCache → REQ_CACHE 変更
066
067        /** URL の /(ルート)に対応する物理ディレクトリ  */
068        private static String  realPath ;                       // 4.0.0 (2005/01/31)
069
070        /** リクエスト関係パラメータの初期設定フラグ */
071        private static boolean paramSetFlag     ;               // 4.0.0 (2005/11/30)
072
073        /**
074         * テーブル表示時のチェックボックスのname属性  {@value}
075         * テーブル表示時にチェックボックスを表示しておき、どの行が選ばれたかを
076         * 指定する場合に、その name 属性に指定するキーの値です。
077         * 受け取る側は、このキーで、request 情報より選ばれた行番号を知ることができます。
078         */
079        public static final String ROW_SEL_KEY = "h_rowSel";
080
081        /**
082         * テーブル表示のチェックボックスを特定する id の 名称( id は、この名称+行番号)   {@value}
083         */
084        public static final String ROW_ID_KEY = "cb";   // 3.6.0.0 (2004/09/17)
085
086        /** session オブジェクトに関連付ける DBTableModel インスタンスのデフォルトキー {@value} */
087        public static final String TBL_MDL_KEY = "h_tblmdl" ;
088
089        // 3.8.1.1 (2005/11/21) ExcelOut の整合性を取る為の仕掛け
090        /** session オブジェクトに関連付ける ExcelOut の整合性チェック用のキー */
091        public static final String TBL_MDL_CONKEY = "h_tblmdlCon" ;
092
093        /** session オブジェクトに関連付ける Viewform インスタンスのデフォルトキー {@value} */
094        public static final String VIEWFORM_KEY = "h_vform" ;
095
096        /** session オブジェクトに関連付ける ViewLink インスタンスのデフォルトキー {@value} */
097        public static final String VIEWLINK_KEY = "h_vlink" ;
098
099        /** session オブジェクトに関連付ける ViewMark インスタンスのデフォルトキー {@value} */
100        public static final String VIEW_MARK_KEY = "h_vmark" ;
101
102        // 3.8.6.1 (2006/10/20) 編集時にカラムを置き換える 機能に対応
103        /** session オブジェクトに関連付ける ViewMark:editor インスタンスのデフォルトキー */
104        public static final String EDIT_MARK_KEY = "h_emark" ;
105
106        /** session オブジェクトに関連付ける UserInfo インスタンスのキー {@value} */
107        public static final String USERINFO_KEY = "h_uInfo" ;
108
109        /** session オブジェクトに関連付ける GUIInfo インスタンスのキー {@value} */
110        public static final String GUIINFO_KEY = "h_gInfo" ;
111
112        /** session オブジェクトに関連付ける リクエスト情報キャッシュのキー {@value} */
113        public static final String REQ_CACHE_KEY = "h_req" ;
114
115        /** session オブジェクトに関連付ける エラーメッセージ情報キャッシュのキー {@value} */
116        public static final String ERR_MSG_KEY = "h_errMsg" ;
117
118        /** 6.4.4.1 (2016/03/18) application オブジェクトに関連付ける 共通メッセージ情報のキー {@value} */
119        public static final String COMMON_MSG_KEY = "h_cmnMsg" ;
120
121        // 2.3.1.0 (2002/12/20) 管理者が全てのユーザーにメッセージを同報できるタグを追加
122        /** session 管理者がステータスバーに設定するオブジェクトのキー {@value} */
123        public static final String ST_BAR_OBJ_KEY = "h_stBar" ;
124
125        // 3.0.0.0 (2002/12/25) SceduleTag 追加の伴う、Timerオブジェクトの管理用キー追加
126        /** Timerオブジェクトの管理用キー {@value} */
127        public static final String SCEDULE_KEY = "h_timer" ;
128
129        // 3.0.0.0 (2002/12/25) SceduleTag 追加の伴う、Timerオブジェクトの管理用キー追加
130        /** TimerTaskオブジェクトの管理用キー {@value} */
131        public static final String SCEDULE_TASK_KEY = "h_timer_task" ;
132
133        // 3.1.2.0 (2003/04/07) ソースコード中の固定値を、定義ファイルを使用するように変更する。
134        /** Forward時の転送先ページ名をセッションに登録するときのキー {@value} */
135        public static final String FORWARD_PAGE_KEY = "h_fpg" ;
136
137        // 3.1.2.0 (2003/04/07) ソースコード中の固定値を、定義ファイルを使用するように変更する。
138        /** Forward時の転送元ページ名をセッションに登録するときのキー {@value} */
139        public static final String REVIEW_PAGE_KEY = "h_rpg" ;
140
141        // 3.1.8.0 (2003/05/16) BACK_GAMENID のキャッシュ方法を、通常のリクエスト情報と分離して、管理する。
142        /** BACK_GAMENID情報をセッションに登録するときのキー {@value} */
143        public static final String BACK_GAMENID_KEY = "h_bgid" ;
144
145        // 4.0.1.0 (2007/12/17) BACK_ADDRESS のキャッシュ方法を、通常のリクエスト情報と分離して、管理する。
146        /** BACK_GAMENID情報をセッションに登録するときのキー {@value} */
147        public static final String BACK_ADDRESS_KEY = "h_bgadrs" ;
148
149        // 3.7.0.3 (2005/03/01) 戻るリンクで戻る行番号を指定します。(BACK_GAMENIDとセット)
150        /** BACK_ROW情報をセッションに登録するときのキー {@value} */
151        public static final String BACK_ROW_KEY = "h_brow" ;
152
153        // 3.1.9.0 (2003/05/16) ShellTag で、Shell オブジェクトをキープする為のキーを作成。
154        /** Shell オブジェクトをセッションに登録するときのキー {@value} */
155        public static final String SHELL_KEEP_KEY = "h_shKeepKey" ;
156
157        // 3.5.0.0 (2003/09/17) ユーザー変更時の、旧ユーザーIDのをキープする為のキーを作成。
158        /** oldUserId 文字列をセッションに登録するときのキー {@value} */
159        public static final String OLD_USERID_KEY = "h_oldID" ;
160
161        // 3.5.4.7 (2004/02/06) DBTableModelのソート時のカラム名の受け渡しキー。
162        /** sortColumns 文字列をリクエスト情報より取得するときのキー {@value} */
163        public static final String SORT_COLUMNS = "h_sortClmns" ;
164
165        // 3.5.4.7 (2004/02/06) DBTableModelのソート時のソート方向の受け渡しキー。
166        /** sortAscending をリクエスト情報より取得するときのキー {@value} */
167        public static final String SORT_ASCENDING = "h_sortAsc" ;
168
169        // 3.5.5.0 (2004/03/12) キー+行番号の連結文字列(例:__)を設定します。
170        /** カラムID(連結文字列)行番号の連結文字列を定義 {@value} */
171        public static final String JOINT_STRING = "__" ;
172
173        // 3.5.5.5 (2004/04/23) DBTableModel の整合性パラメータを hidden で出力します。
174        /** DBTableModel の整合性パラメータをリクエスト情報より取得するときのキー {@value} */
175        public static final String CONSISTENCY_KEY = "h_consisKey" ;
176
177        // 3.5.5.5 (2004/04/23) 転送不要パラメータの先頭に付けるキーワードです。
178        /** SubmitTag で出力されるボタンパラメータは、次ページへ転送しません。 {@value} */
179        public static final String NO_XFER_KEY = "hX_" ;
180
181        // 3.8.0.0 (2005/06/07) 同一セッションでのマルチ起動対策用キーワードです。
182        /** 同一セッションでのマルチ起動された場合に、前に開かれた画面からのアクセスを禁止します。 */
183        public static final String MULTI_SESSION_CHECK = "MSC" ;
184
185        /** 3.8.9.1 (2005/07/29) JFreeChart オブジェクトのキャッシュ {@value}  */
186        public static final String JF_CHART_CACHE_KEY = "h_chartKey" ;
187
188        // 3.8.0.8 (2005/10/03) GET時のURL に使用可能な文字数制限
189        /** URL に使用可能な文字数は最大 2,083 文字
190         * http://support.microsoft.com/default.aspx?scid=kb;ja;208427
191         */
192        public static final int MAX_GET_LENGTH = 2083 ;
193
194        /** 4.0.0 (2005/01/31) GUIのロールを区切る、区切り文字                {@value}  */
195        public static final char GUI_DELIMITER = '|' ;
196
197        /** 4.0.0 (2005/01/31) ローカルリソースのオブジェクト保存時のキー    {@value}  */
198        public static final String LOCAL_RES_KEY = "h_lclRes" ;
199
200        /** 4.0.0 (2005/02/28) Tomcat起動時エラーが発生した場合のエラーキー        {@value}  */
201        public static final String LOCAL_CONTX_ERR_KEY = "h_lclConErr" ;
202
203        /** 4.0.0 (2005/08/31) グループメニューのキャッシュキー {@value} */
204        public static final String GUI_GR_MENU_CACHE_KEY = "h_grpCache" ;
205
206        /** 4.0.0 (2005/09/30) 個人別お気に入りメニューの GE16 登録キーワード       {@value} */
207        public static final String GUI_FAV_MENU_KEY = "GUI_FAV_MENU_KEY" ;
208
209        /** 4.0.0 (2005/06/04) DBTableWriter の columns 属性のセッション登録キーワード  {@value} */
210        public static final String TBL_WRITER_CLMS = "TBL_WRITER_CLMS" ;
211
212        /** 4.1.2.1 (2008/03/13) must 属性をrequest変数にセットする場合の キー {@value} */
213        public static final String MUST_KEY = "h_must_" ;
214
215        /** 6.2.0.0 (2015/02/27) aimai 属性をrequest変数にセットする場合の キー {@value} */
216        public static final String AIMAI_KEY = "h_aimai_" ;
217
218        /** 4.3.0.0 (2008/07/04) 最後に Queryを実行した情報の保存時のキー {@value} */
219        public static final String DB_LAST_SQL_KEY = "h_lastSql" ;
220
221        /** 4.3.3.0 (2008/10/01) ページ内で画面遷移なしモードを指定しようする場合のキー    {@value}  */
222        public static final String NO_TRANSITION_MODE_KEY = "h_noTrnsKey" ;
223
224        /** 4.3.6.0 (2009/04/01) イベントカラムを利用したかどうかのチェックキー        {@value}  */
225        public static final String USE_EVENT_COLUMN_KEY = "h_eventColumn" ;
226
227        /** 5.1.7.0 (2010/06/01) イベントカラムをラップするspanタグのクラス        {@value}  */
228        public static final String EVENT_COLUMN_CLASS = "h_evElm";
229
230        /** 5.1.7.0 (2010/06/01) イベントカラムをラップするspanタグで、子カラムの書き込み可/不可を設定する属性名     {@value}  */
231        public static final String EVENT_COLUMN_WRITABLE = "h_evWrtbl";
232
233        /** 5.1.7.0 (2010/06/01) イベントカラムをラップするspanタグで、子カラムのIDを設定する属性名   {@value}  */
234        public static final String EVENT_COLUMN_ID = "h_evCid";
235
236        /** 5.1.7.0 (2010/06/01) イベントカラムをラップするspanタグで、子カラムの初期値を設定する属性名  {@value}  */
237        public static final String EVENT_COLUMN_INITVAL = "h_evVal";
238
239        /** 4.3.7.0 (2009/06/01) linkタグのurlCheckキーを出力する際のパラメーターキー       {@value}  */
240        public static final String URL_CHECK_KEY = "h_urlCheck" ;
241
242        /** 4.3.7.5 (2009/07/08) ページ内でajaxSubmitを利用する場合のキー      {@value}  */
243        public static final String USE_AJAX_SUBMIT_KEY = "h_ajaxSubmit" ;
244
245        /** 5.1.6.0 (2010/05/01) Viewでソート済みかどうかを判定する際のキー        {@value} */
246        public static final String VIEW_SORT_KEY = "h_viewSrt";
247
248        /** 5.1.9.0 (2010/08/01) トランザクションを実現する際のキー      {@value} */
249        public static final String TRANSACTION_KEY = "h_tran";
250
251        /** 5.2.2.0 (2010/11/01) URLの引数部をハッシュする際のリクエストキー        {@value} */
252        public static final String URL_HASH_REQ_KEY = "h_r";
253
254        /** 5.3.2.0 (2011/02/01) リクエストパラメーターのキー一覧を保存する際のキー      {@value} */
255        public static final String PARAM_NAMES_KEY = "h_prmNms";
256
257        /** 5.3.6.0 (2011/06/01) クエリを呼び出し時のフォーカスを制御するためのキー      {@value} */
258        public static final String QUERY_FOCUS_KEY = "h_qryFcs";
259
260        /** 5.5.9.1 (2012/12/07) セッション作成時に、セッションIDを保存しておく、規定のキー {@value} */
261        public static final String SESSION_KEY = "h_session_key";
262
263        /** 5.7.6.2 (2014/05/16) セッション作成時に、セッションIDを保存しておく、規定のキー {@value} */
264        public static final String IE_HTML5_KEY = "h_html5_key";
265
266        /** 6.4.5.2 (2016/05/06) UPLOADから呼ばれたかどうかを判定するための、規定のキー {@value} */
267        public static final String USE_UPLOAD_KEY = "h_UPLOAD";
268
269        /** 6.8.4.2 (2017/12/25) エンコード変換対応対応のキー(fileDownloadサーブレットでエンコードをON/OFF指定に利用)   {@value} */
270        public static final String USE_STR_CONV_KEY = "useStringConvert";
271
272        /**
273         * 帳票エンコーディング   {@value}
274         * 設定されていない場合は、UTF-8 に設定されます。
275         */
276        public static final String REPORT_ENCODE = "UTF-8" ;
277
278        /** 7.0.6.4 (2019/11/29) コンテキストがロードされた時刻(yyyyMMddHHmmss) */
279        public static final String START_TIME = DateSet.getDate( "yyyyMMddHHmmss" );
280
281        /** 実行しているサーバーの名称 */
282        public static final String HOST_NAME ;
283        /** 実行しているサーバーのIPアドレス */
284        public static final String HOST_ADRS ;
285
286        static {
287                String dmnHost ;
288                String dmnAdrs ;
289                try {
290                        final InetAddress address = InetAddress.getLocalHost();
291                        dmnHost = address.getHostName() ;
292                        dmnAdrs = address.getHostAddress() ;
293                }
294//              catch( final UnknownHostException ex ) {
295                catch( final Throwable th ) {                                           // 7.0.6.4 (2019/11/29) エラー全てを捉える
296                        dmnHost = "Unknown";
297                        dmnAdrs = "Unknown";
298                }
299                HOST_NAME = dmnHost;
300                HOST_ADRS = dmnAdrs;
301        }
302
303        /**
304         * デフォルトコンストラクターをprivateにして、
305         * オブジェクトの生成をさせないようにする。
306         *
307         */
308        private HybsSystem() {}
309
310        /**
311         * 内部システムリソースマップオブジェクトを設定します。
312         *
313         * @og.rev 3.5.3.1 (2003/10/31) 新規作成
314         * @og.rev 4.0.0.0 (2005/01/31) Ver4 のシステムパラメータ情報の取得処理を追加します。
315         * @og.rev 4.3.1.0 (2008/09/03) SERVER_NAME,SERVER_URL,CONTEXT_URLをキャッシュから復元
316         * @og.rev 4.3.1.0 (2008/09/03) SERVER_NAME,SERVER_URL,CONTEXT_URLをキャッシュから復元
317         * @og.rev 6.2.4.1 (2015/05/22) REAL_PATH 対応。realPath は、setInitialData ではなく、setRealPathメソッドで設定する。
318         * @og.rev 6.4.3.1 (2016/02/12) ConcurrentHashMap で同期処理を行います。
319         * @og.rev 6.4.3.3 (2016/03/04) SYS_MAP を、ConcurrentHashMap で同期するため、not null制限チェックを追加します。
320         * @og.rev 6.4.9.1 (2016/08/05) reqCache → REQ_CACHE 変更
321         *
322         * @param       param   システムリソースマップ
323         */
324        public static void setInitialData( final Map<String,String> param ) {
325                // key,val の not null 制限が解除できないので、とりあえず、ConcurrentHashMap で対応。
326                SYS_MAP.clear();                                        // 初期化した上で、全部コピーします。
327                if( param != null ) {
328                        // 6.4.3.3 (2016/03/04) SYS_MAP を、ConcurrentHashMap で同期するため、not null制限チェックを追加します。
329                        param.forEach( (k,v) -> { if( k != null && v != null ) { SYS_MAP.put( k,v ); } } );
330                }
331                // 4.3.1.0 (2008/09/03) SERVER_NAME,SERVER_URL,CONTEXT_URLをキャッシュから復元
332                if( paramSetFlag ) {
333                        SYS_MAP.putAll( REQ_CACHE );    // 6.4.9.1 (2016/08/05)
334                }
335
336                System.out.println( "    [" + SYS_MAP.get( "CONTEXT_NAME" ) + "] のシステムパラメータが、[" + SYS_MAP.size() + "] 件設定されました。" );
337        }
338
339        /**
340         * 内部システムパラメータ に、realPath を設定します。
341         *
342         * その際、Tomcatのバージョン(過去の一部バージョン)で、最後のファイルセパレータが
343         * 付かないケースがありましたので、付ける方向で、統一します。
344         * このメソッドは、SystemParameter#loadInitialParameter( ServletContext , String )からのみ
345         * 呼ばれることを想定しています。
346         *
347         * @og.rev 6.2.4.1 (2015/05/22) REAL_PATH 対応。realPath は、setInitialData ではなく、setRealPathメソッドで設定する。
348         *
349         * @param       path    context.getRealPath( "" ) を引数で渡してきます。
350         */
351        /* default */ static void setRealPath( final String path ) {
352                if( path != null && path.endsWith( File.separator ) ) {
353                        realPath = path ;                                                                               // 後ろにセパレータが付いていれば、そのまま。
354                }
355                else {
356                        realPath = path + File.separator ;                                              // 付いていなければ、付ける。
357                }
358        }
359
360        /**
361         * 内部システムパラメータ に、realPath を取得します。
362         *
363         * その際、Tomcatのバージョン(過去の一部バージョン)で、最後のファイルセパレータが
364         * 付かないケースがありましたので、付ける方向で、統一します。
365         *
366         * @og.rev 6.2.4.1 (2015/05/22) REAL_PATH 対応。realPath は、setInitialData ではなく、setRealPathメソッドで設定する。
367         *
368         * @return      REAL_PATH コンテキストのトップパス
369         */
370        public static String getRealPath() {
371                return realPath ;
372        }
373
374        /**
375         * システムパラメータ情報を取得します。
376         * Ver3 では、プロパティーファイルでリソースを提供している為、
377         * 立ち上げタイミングとの関係で始めて使用する場合にデータを取得します。
378         *
379         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
380         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
381         *
382         * @param       key     システムパラメータのキー(not null)
383         *
384         * @return      システムパラメータ の値
385         */
386        private static String getParam( final String key ) {
387                        return SYS_MAP.get( key );
388        }
389
390        /**
391         * システムパラメータの追加情報セットが終了しているかどうかを取得します。
392         * 設定処理を行うかどうかの判定に使用します。
393         *
394         * @og.rev 4.0.0.0 (2005/11/30) 新規作成
395         *
396         * @return      true:設定完了 / false:未完了(設定可能)
397         * @see #setRequestParam( String,String,int,String )
398         */
399        public static boolean isParamSet() {
400                return paramSetFlag;
401        }
402
403        /**
404         * システムパラメータ情報を追加設定します。
405         * これは、SERVER_NAME、SERVER_URL、CONTEXT_URL などのリクエストオブジェクトから
406         * しか取得できない共有情報を、登録する場合に使用します。
407         * これらの値は、taglib/JspInitTag タグでセットされます。
408         * セットする前に、isParamSet() で設定済みかどうか判断してください。
409         * このメソッドは、isParamSet() の値に関係なく、セットします。
410         *
411         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
412         * @og.rev 4.3.1.0 (2008/09/03) SERVER_NAME,SERVER_URL,CONTEXT_URLのキャッシュ処理追加
413         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
414         * @og.rev 6.4.9.1 (2016/08/05) reqCache → REQ_CACHE 変更
415         *
416         * @param       serverName      サーバー名
417         * @param       scheme  スキーマ
418         * @param       port    ポート番号
419         * @param       path    コンテキストパス
420         * @see #isParamSet()
421         */
422        public static void setRequestParam( final String serverName,final String scheme,
423                                                                                final int port,final String path ) {
424
425                        final String portStr = ( port == 80 ) ? "" : ":" + port ;
426                        final String serverURL = scheme + "://" + serverName + portStr ;
427                        final String contextURL = serverURL + path + "/" ;
428
429                        SYS_MAP.put( "SERVER_NAME"      , serverName );
430                        SYS_MAP.put( "SERVER_URL"       , serverURL + "/" );
431                        SYS_MAP.put( "CONTEXT_URL"      , contextURL );
432
433                        // 4.3.1.0 (2008/09/03) SERVER_NAME,SERVER_URL,CONTEXT_URLをキャッシュして置く
434                        // 6.4.9.1 (2016/08/05) reqCache → REQ_CACHE 変更
435                        REQ_CACHE.put( "SERVER_NAME"    , serverName );
436                        REQ_CACHE.put( "SERVER_URL"             , serverURL + "/" );
437                        REQ_CACHE.put( "CONTEXT_URL"    , contextURL );
438                        paramSetFlag = true;
439        }
440
441        /**
442         * 現在日付、時刻を所得します。
443         * 出力フォーマットは、システムパラメータ の SYS_TIME の
444         * 設定を適用します。( "yyyy/MM/dd HH:mm:ss" )
445         *
446         * @og.rev 4.0.0.0 (2005/01/31) getSystemResource() ⇒ sysParam に変更
447         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
448         *
449         * @return      現在日付、時刻 ( 例 2001/04/17 15:48:22 )
450         */
451        public static String getDate() {
452                return DateSet.getDate( getParam( "SYS_TIME" ) );
453        }
454
455        /**
456         * 指定時刻をデフォルトのフォーマットで、所得します。
457         * フォーマットの指定方法は、java.text.SimpleDateFormat の指定方法と同一です。
458         * 出力フォーマットは、システムパラメータ の SYS_TIME の
459         * 設定を適用します。( "yyyy/MM/dd HH:mm:ss" )
460         *
461         * @og.rev 4.0.0.0 (2005/01/31) getSystemResource() ⇒ sysParam に変更
462         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
463         *
464         * @param       time 指定のカレントタイム
465         *
466         * @return      現在日付、時刻( 例 2001/04/17 15:48:22 )
467         */
468        public static String getDate( final long time ) {
469                final String form = getParam( "SYS_TIME" );
470                return DateSet.getDate( time , form );
471        }
472
473        /**
474         * システム設定ファイルのデータを所得します。
475         * キーが存在しない場合は、null を返します。
476         * キーがnullの場合は、HybsSystemException をスローします。
477         *
478         * @og.rev 6.7.4.1 (2017/02/17) キーが存在しなかった場合のログ出力を出すかどうか(true:出す)
479         *
480         * @param       key システム設定 キー
481         *
482         * @return      システム設定値
483         * @og.rtnNotNull
484         * @throws HybsSystemException キーが null の場合。
485         */
486        public static String sys( final String key ) throws HybsSystemException {
487                return sys( key , true );
488        }
489
490        /**
491         * システム設定ファイルのデータを所得します。
492         * キーが存在しない場合は、null を返します。
493         * キーがnullの場合は、HybsSystemException をスローします。
494         *
495         * @og.rev 3.5.5.0 (2004/03/12) {&#064;SYS.XXXX} で使用できる変数を増やします。
496         * @og.rev 3.5.5.3 (2004/04/09) {&#064;SYS.XXXX} に、DATE というキーを追加します。
497         * @og.rev 4.0.0.0 (2005/01/31) getSystemResource() ⇒ sysParam に変更
498         * @og.rev 6.7.4.1 (2017/02/17) キーが存在しなかった場合のログ出力を出すかどうか(true:出す)
499         *
500         * @param       key システム設定 キー
501         * @param       useNoKeyLog システムリソースキーが存在しない場合に、ログ出力するかどうか [true:出力する/false:出力しない]
502         *
503         * @return      システム設定値
504         * @og.rtnNotNull
505         * @throws HybsSystemException キーが null の場合。
506         */
507        public static String sys( final String key , final boolean useNoKeyLog ) throws HybsSystemException {
508                if( key == null ) {
509                        final String errMsg = "キーが null です。";
510                        throw new HybsSystemException( errMsg );                // 3.5.5.4 (2004/04/15) 引数の並び順変更
511                }
512
513                if( "DATE".equals( key ) ) { return getDate() ; }       // 3.5.5.3 (2004/04/09)
514
515                final String rtn = getParam( key );
516                if( rtn == null && ! key.startsWith( "h_" ) && useNoKeyLog ) {
517                        final String errMsg = CR + "システムリソースキーが存在しません。key = " + key;
518                        LogWriter.log( errMsg );
519                }
520                return rtn;
521        }
522
523        /**
524         * システム設定ファイルから、複数のデータを所得します。
525         * キーが,"ABC" とすれば、それで始まるデータ( ABCD, ABC_01 など)
526         * を配列で取得できます。
527         * リターン配列は、ソートされています。
528         *
529         * @og.rev 4.0.0.0 (2005/01/31) getSystemResource() ⇒ sysParam に変更
530         * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。
531         * @og.rev 6.4.3.3 (2016/03/04) HybsSystem.newInstance(String,String) への置き換え。
532         *
533         * @param       key システム設定 キー(の先頭の部分文字列)
534         *
535         * @return      システム設定配列 HybsEntry
536         */
537        public static HybsEntry[] sysEntry( final String key ) {
538                final Set<HybsEntry> entSet = new TreeSet<>();
539
540                // 6.4.3.3 (2016/03/04) SYS_MAP を、ConcurrentHashMap で同期するため、not null制限チェックを追加します。
541                SYS_MAP.forEach( (k,v) -> { if( k.startsWith( key ) ) { entSet.add( new HybsEntry( k,v ) ); } } );
542
543                return entSet.toArray( new HybsEntry[entSet.size()] );
544        }
545
546        /**
547         * システム設定ファイルのデータを所得します。
548         * 特別に,int 型にデータを変換して,渡します。
549         * 変換できない場合は,NumberFormatException がスローされます。
550         *
551         * @og.rev 3.5.3.1 (2003/10/31) エラー時に、判るようにメッセージを出します。
552         * @og.rev 4.0.0.0 (2005/01/31) getSystemResource() ⇒ sysParam に変更
553         *
554         * @param       key システム設定 キー
555         *
556         * @return      システム設定値
557         */
558        public static int sysInt( final String key ) {
559                if( key == null ) {
560                        final String errMsg = "キーが null です。";
561                        throw new HybsSystemException( errMsg );                // 3.5.5.4 (2004/04/15) 引数の並び順変更
562                }
563
564                final String tmp = getParam( key );
565                int rtn ;
566                try {
567                        rtn = Integer.parseInt( tmp );
568                }
569                catch( final NumberFormatException ex2 ) {
570                        final String errMsg = "システムリソース の値が数字ではありません。" + CR
571                                        + "  Resource key=[" + key + "] val=[" + tmp + "]"  ;
572                        throw new HybsSystemException( errMsg,ex2 );            // 3.5.5.4 (2004/04/15) 引数の並び順変更
573                }
574
575                return rtn;
576        }
577
578        /**
579         * システム設定ファイルのデータを所得します。
580         * 特別に,boolean 型にデータを変換して,渡します。
581         * 変換できない場合は,NumberFormatException がスローされます。
582         *
583         * @og.rev 3.5.6.0 (2004/06/18) Booleanのコンストラクタの代わりに、Boolean.valueOf(...) を使用します。
584         *
585         * @param       key システム設定 キー
586         *
587         * @return      システム設定値
588         */
589        public static boolean sysBool( final String key ) {
590                return Boolean.parseBoolean( HybsSystem.sys( key ) );           // 6.1.0.0 (2014/12/26) refactoring
591        }
592
593        /**
594         * システム依存のURL文字列から,実際のディレクトリ名を所得します。
595         * UNIX と Windows を URL パス名から判断して、実ディレクトリを返します。
596         * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、
597         * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
598         * システムパラメータ の FILE_URL 属性で指定のフォルダの下に、作成されます。
599         * 相対パス、または、URL の場合は、頭に / を入れないでください。UNIX の
600         * 絶対パスと判断されます。
601         * また、絶対パスの最後には、/ を入れておいてください。
602         *
603         * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
604         * @og.rev 6.4.2.1 (2016/02/05) 引数をすべて、StringUtil.urlAppend していきます。
605         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
606         * @og.rev 7.0.2.2 (2019/03/25) StringBuilder を使わなくします。
607         *
608         * @param       urls URL文字列(可変長配列)
609         *
610         * @return      ディレクトリ文字列
611         */
612        public static String url2dir( final String... urls ) {
613//              return StringUtil.urlAppend( realPath,urls ).replace( '/',FS );
614//              // 5.10.9.0 (2019/03/01) ADD
615//              final StringBuilder sb = new StringBuilder( BUFFER_MIDDLE );
616
617                // \を/に変換する処理を追加。
618                final String path = StringUtil.urlAppend( realPath,urls ).replace('\\','/').replace( '/',FS );
619
620                // linux環境かつ、2文字目が「:」Windows環境のドライブ指定の場合は、頭に「/」を付与して、絶対パスとして扱う。
621                return FS == '/' && path.charAt(1) == ':' ? "/" + path : path ;
622
623                // linux環境かつ、2文字目が「:」Windows環境のドライブ指定の場合は、頭に「/」を付与して、絶対パスとして扱う。
624//              if(FS == '/' && path.charAt(1) == ':') {
625//                      sb.append("/").append(path);
626//              }else {
627//                      sb.append(path);
628//              }
629//
630//              return sb.toString();
631        }
632
633        /**
634         * 絶対パスと判断されるものは変換せず、それ以外を絶対パスに変換します。
635         *
636         * @og.rev 5.10.9.2 (2019/03/15) クラウドストレージ対応を追加。
637         * @og.rev 7.0.2.2 (2019/03/25) StringBuilder を使わなくします。
638         *
639         * @param       url URL文字列
640         *
641         * @return      ディレクトリ文字列
642         */
643        public static String url2absPath( final String url ) {
644                final String absPath ;
645
646                // 2文字目が「:」の場合はそのままWindowsの絶対パスとして扱う。
647                if( url.charAt(1) == ':' ) {
648                        absPath = url;
649                }
650                else {
651                        // それ以外は絶対パスに変換する
652                        final String path = StringUtil.urlAppend( realPath,url ).replace('\\','/').replace( '/',FS );
653                        absPath = new File( path ).getAbsolutePath().toString();
654                }
655
656                return absPath;
657
658//              // 5.10.9.0 (2019/03/01) ADD
659//              final StringBuilder sb = new StringBuilder(BUFFER_MIDDLE);
660//              
661//              // 2文字目が「:」の場合はそのままWindowsの絶対パスとして扱う。
662//              if( url.charAt(1) == ':' ) {
663//                      sb.append(url);
664//              }
665//              else {
666//                      // それ以外は絶対パスに変換する
667//                      final String path = StringUtil.urlAppend( realPath,url ).replace('\\','/').replace( '/',FS );
668//                      sb.append( new File( path ).getAbsolutePath().toString() );
669//              }
670//              
671//              return sb.toString();
672        }
673
674        /**
675         * システムリソース情報を取得します。
676         * 形式は、Map です。
677         * 実質的には、キーでソーティングされた、ConcurrentSkipListMap を返します。
678         *
679         * @og.rev 6.4.3.3 (2016/03/04) 配列返しではなく、Map を返します。
680         *
681         * @return      システムリソース情報:キー([0])、値([1])の2次元配列
682         */
683        public static ConcurrentMap<String,String> getSystemResourceMap() {
684                return new ConcurrentSkipListMap<String,String>( SYS_MAP );
685        }
686
687        /**
688         * システムのコンテキスト名を取得します。
689         * コンテキスト名は、Tomcat の servr.xml で指定する仮想フォルダ名です。
690         *
691         * @og.rev 3.5.4.3 (2004/01/05) 新規追加
692         *
693         * @return      コンテキスト名(仮想フォルダ名)
694         */
695        public static String getContextName() {
696                return sys( "CONTEXT_NAME" );   // 4.0.0 (2005/01/31)
697        }
698
699        /**
700         * サーバーのプリンター一覧のスペース区切り文字列を返します。
701         * プリンタ名にスペースが含まれる場合は、前後にダブルクオートを付けます。
702         * ここで求めた値は、"SYS.PRINTER" で、取得可能です。(最初の取得時に内部キャッシュされます。)
703         * SystemData#OMIT_PRINTER_NAMES に登録されている一覧名と先頭一致するプリンタは除外します。
704         * 例えば、Windows等で、初めから登録されている Fax,Microsoft XPS などは、不要なのでOMITします。
705         *
706         * @og.rev 6.2.6.0 (2015/06/19) サーバーのプリンター一覧のスペース区切り文字列対応。
707         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
708         *
709         * @return      サーバーのプリンター一覧のスペース区切り文字列
710         */
711        public static String getPrinter() {
712                String rtn = getParam( "PRINTER" );
713                if( rtn == null ) {
714                        final String[] omitNames = HybsSystem.sys( "OMIT_PRINTER_NAMES" ).split( "," ) ;
715
716                        final PrintService[] service = PrintServiceLookup.lookupPrintServices( null,null );
717
718                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) ;
719                        for( int i=0; i<service.length; i++ ) {
720                                final String name = service[i].getName() ;
721                                boolean isAdd = true;   // true:追加する/false:追加しない
722                                for( int j=0; j<omitNames.length; j++ ) {
723                                        if( name.startsWith( omitNames[j] ) ) { isAdd = false; break; }
724                                }
725                                if( isAdd ) {
726                                        if( name.contains( " " ) ) {
727                                                buf.append( '"' ).append( name ).append( "\" " );
728                                        }
729                                        else {
730                                                buf.append( name ).append( ' ' );
731                                        }
732                                }
733                        }
734                        buf.setLength( buf.length()-1 );                // 最後のスペースを削除
735
736                        rtn = buf.toString();
737                                SYS_MAP.put( "PRINTER",rtn );
738                }
739                return rtn ;
740        }
741
742        /**
743         * HybsSystem.sys から識別idとなるクラス名を取得して、オブジェクトを作成します。
744         * 簡易的なメソッドです。
745         *
746         * @og.rev 6.4.3.3 (2016/03/04) 新規作成。
747         *
748         * @param       <T>             キャストされて生成される新しいオブジェクト
749         * @param       sysKey  クラスのキーとなるID(共通キー)
750         * @param       cls             作成するクラスの個別キー
751         *
752         * @return      Tオブジェクト
753         * @throws RuntimeException 何らかのエラーが発生した場合
754         */
755        @SuppressWarnings(value={"unchecked"})
756        public static <T> T newInstance( final String sysKey,final String cls ) {
757                final String clsStr = HybsSystem.sys( sysKey + cls );
758
759                // NullPointerException が発生するので、事前にチェックします。
760                if( clsStr == null ) {
761                        final String errMsg = sysKey + " クラスが見つかりません。class=" + sysKey + cls;
762                        throw new OgRuntimeException( errMsg );
763                }
764
765                return (T) newInstance( clsStr );
766        }
767
768        /**
769         * 標準のクラスローダを使って、識別id に応じた オブジェクトを作成します。
770         * 作成するには、デフォルトコンストラクターが必要です。
771         *
772         * @og.rev 6.4.3.3 (2016/03/04) リフレクション系の見直しと、例外の共通クラスに置き換えます。
773         * @og.rev 6.8.2.3 (2017/11/10) java9対応(cls.newInstance() → cls.getDeclaredConstructor().newInstance())
774         *
775         * @param       <T>             キャストされて生成される新しいオブジェクト
776         * @param       cls     作成するクラスのフルネーム(識別id)
777         *
778         * @return      Tオブジェクト
779         * @throws RuntimeException 何らかのエラーが発生した場合
780         */
781        @SuppressWarnings(value={"unchecked"})
782        public static <T> T newInstance( final String cls ) {
783                try {
784                        return (T) Class.forName( cls ).getDeclaredConstructor().newInstance();                 // 6.8.2.3 (2017/11/10)
785                }
786                catch( final ReflectiveOperationException ex ) {
787                        final String errMsg = "Class.forName( String ).newInstance() 処理に失敗しました class=[" + cls + "]" + CR
788                                                + ex.getMessage() ;
789                        throw new OgRuntimeException( errMsg,ex );
790                }
791        }
792
793        /**
794         * "org.opengion.hayabusa.message" の、Locale.JAPANESE リソースから取得するメッセージを文字列で返します。
795         *
796         * id と引数を受け取り、ResourceBundle と、MessageFormat.format で加工した
797         * 文字列を返します。
798         * baseName は、F_BS_NM で、Locale に、Locale.JAPANESE を指定したメッセージを作成します。
799         * hayabusaパッケージと、pluginパッケージで主に使われる、メッセージの取得方法です。
800         *
801         * @og.rev 6.4.3.2 (2016/02/19) 新規追加
802         *
803         * @param id    リソースのキーとなるID。
804         * @param args  リソースを、MessageFormat.format で加工する場合の引数。
805         *
806         * @return MessageFormat.formatで加工された文字列
807         * @see         MsgUtil#H_BS_NM
808         */
809        public static String getMsg( final String id , final Object... args ) {
810                return MsgUtil.getMsg( MsgUtil.H_BS_NM , Locale.JAPANESE , id , args );
811        }
812
813        /**
814         * 入力文字列に、{&#064;SYS},{&#064;ENV} の文字列変換を行います。
815         *
816         *   {&#064;SYS.XXX}  システムリソースMapを元に、文字列を変換します。
817         *   {&#064;ENV.XXX}  環境変数(Javaオプション)の文字列を変換します。(java -Dkey=value オプション)
818         *
819         * @og.rev 6.9.0.1 (2018/02/05) 新規追加
820         *
821         * @param  inMsg 入力文字列(nullの場合、そのまま返します)
822         *
823         * @return  変換後文字列
824         */
825        public static String changeParam( final String inMsg ) {
826                if( inMsg == null ) { return inMsg; }
827
828                String message = inMsg;
829
830                // {@SYS.XXXX} 変数の置換処理
831                int adrs = message.indexOf( "{@SYS." ) ;
832                while( adrs >= 0 ) {
833                        final int end = message.indexOf( '}',adrs ) ;
834                        final String key = message.substring( adrs+6,end );                     // 6 = "{@SYS.".length のこと。
835                        final String oldData = "{@SYS." + key + "}" ;
836                        final String newData = SYS_MAP.getOrDefault( key , "" );        // SYS_MAP は、ConcurrentMap なので、null は、返らない。
837                        message = StringUtil.replace( message,oldData,newData );
838                        adrs = message.indexOf( "{@SYS.",adrs ) ;
839                }
840                // {@ENV.XXXX} 変数の置換処理
841                adrs = message.indexOf( "{@ENV." ) ;
842                while( adrs >= 0 ) {
843                        final int end = message.indexOf( '}',adrs ) ;
844                        final String key = message.substring( adrs+6,end );                     // // 6 = "{@ENV.".length のこと。
845                        final String oldData = "{@ENV." + key + "}" ;
846                        final String newData = System.getProperty( key,"" );
847                        message = StringUtil.replace( message,oldData,newData );
848                        adrs = message.indexOf( "{@ENV.",adrs ) ;
849                }
850
851                return message;
852        }
853}