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.taglib;
017
018import java.io.File;
019import java.io.IOException;
020import java.io.Writer;
021import java.nio.charset.StandardCharsets;
022import java.nio.file.Files;
023import java.nio.file.Paths;
024import java.util.LinkedHashMap;
025import java.util.Locale;
026import java.util.Map;
027import java.util.Set;
028
029import org.opengion.fukurou.system.Closer;
030import org.opengion.fukurou.util.ArraySet;
031import org.opengion.fukurou.util.ErrorMessage;
032import org.opengion.fukurou.util.FileUtil;
033import org.opengion.fukurou.util.HttpConnect;
034import org.opengion.fukurou.util.JSONScan;
035import org.opengion.fukurou.util.StringUtil;
036import org.opengion.fukurou.util.ToString;
037import org.opengion.hayabusa.common.HybsSystem;
038import org.opengion.hayabusa.common.HybsSystemException;
039import org.opengion.hayabusa.db.DBColumn;
040import org.opengion.hayabusa.db.DBTableModel;
041import org.opengion.hayabusa.db.DBTableModelUtil;
042
043import static org.opengion.fukurou.util.StringUtil.nval;
044
045/**
046 * IOr (Information Organizer) に接続し、取得したデータベースを表示するタグです。
047 *
048 * IOr へデータ取得を要求して受取った JSON形式 の文字列を、DBTableModel にセットします。
049 * IOr から取得したデータより loadFile が優先されます。
050 *
051 * このタグの結果(DBTableModel)は、通常の QueryTag と同様に
052 * ViewFormTag で一覧表示や、WriteTableTag でファイル出力が可能です。
053 *
054 * SystemData の USE_SQL_INJECTION_CHECK が true か、quotCheck 属性が true の場合は、
055 * SQLインジェクション対策用のシングルクォートチェックを行います。リクエスト引数に
056 * シングルクォート(')が含まれると、エラーになります。
057 * 同様にUSE_XSS_CHECKがtrueか、xssCheck属性がtrueの場合は、
058 * クロスサイトススクリプティング(XSS)対策のためless/greater than signのチェックを行います。
059 *
060 * 実行後にリクエストパラメータに以下の値がセットされます。
061 *   DB.COUNT    : 実行結果の件数
062 *   DB.ERR_CODE : 実行結果のエラーコード
063 *   DB.ERR_MSG  : 実行結果のエラーメッセージ
064 *
065 * ※ このタグは、Transaction タグの対象です。
066 *
067 * @og.formSample
068 * ●形式:
069 *     <og:iorQuery
070 *         url           = "http://・・・ "    必須
071 *         authURL       = "http://・・・ "    必須
072 *         authUserPass  = "admin:******"   必須
073 *         appliName     = "データテーブル名"
074 *     >
075 *     </og:iorQuery>
076 *
077 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
078 *
079 * ●Tag定義:
080 *   <og:iorQuery
081 *       url              ○【TAG】アクセスする URL を指定します (必須)
082 *       proxyHost          【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します
083 *       proxyPort          【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します
084 *       timeout            【TAG】通信リンクのオープン時に、指定された秒単位のタイム・アウト値を使用します
085 *                                  (初期値:URL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])
086 *       authURL          ○【TAG】JSONコードで認証するURLを指定します (必須)
087 *       authUserPass     ○【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します (必須)
088 *       companyId          【TAG】企業IDを指定します
089 *       appliName        ○【TAG】アプリケーションの名前を指定します
090 *       display            【TAG】接続の結果を表示するかどうかを指定します (初期値:false)
091 *       saveFile           【TAG】接続の結果をファイルに保存します
092 *       loadFile           【TAG】ファイルからURL接続結果に相当するデータを読み取ります
093 *       command            【TAG】コマンド(NEW,RENEW)をセットします
094 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します (初期値:session)
095 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
096 *       notfoundMsg        【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します
097 *                                  (初期値:MSG0077[対象データはありませんでした])
098 *       stopZero           【TAG】検索結果が0件のとき処理を続行するかどうか[true/false]を指定します (初期値:false[続行する])
099 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
100 *       stopError          【TAG】処理エラーの時に処理を中止するかどうか[true/false]を設定します (初期値:true)
101 *       dispError          【TAG】エラー時にメッセージを表示するか[true/false]を設定します。通常はstopErrorと併用 (初期値:true)
102 *       quotCheck          【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します
103 *                                  (初期値:USE_SQL_INJECTION_CHECK)
104 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します
105 *                                  (初期値:USE_XSS_CHECK[=true])
106 *       mainTrans          【TAG】(通常は使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します (初期値:false)
107 *       useBeforeHtmlTag   【TAG】処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します (初期値:true)
108 *       useTimeView        【TAG】処理時間を表示する TimeView を表示するかどうかを指定します
109 *                                  (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])
110 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します (初期値:null)
111 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します (初期値:null)
112 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます (初期値:判定しない)
113 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます (初期値:判定しない)
114 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます (初期値:判定しない)
115 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します (初期値:false)
116 *   >   ... Body ...
117 *   </og:iorQuery>
118 *
119 * ●使用例
120 *     <og:iorQuery
121 *         url           = "http://・・・ "
122 *         authURL       = "http://・・・ "
123 *         authUserPass  = "admin:******"
124 *         appliName     = "データテーブル名"
125 *     >
126 *         <og:iorParam
127 *             key  = "where_lk"  value  = "{'PN':'{@PN}%','TANI':'{@TANI}'}"  />
128 *     </og:iorQuery>
129 *
130 * @og.rev 8.0.2.0 (2021/11/30) 新規作成
131 * @og.group その他部品
132 *
133 * @version  8.0
134 * @author   LEE.M
135 * @since    JDK17.0,
136 */
137public class IorQueryTag extends CommonTagSupport {
138        /** このプログラムのVERSION文字列を設定します。 {@value} */
139        private static final String VERSION = "8.0.2.0 (2021/11/30)" ;
140        private static final long serialVersionUID = 802020211130L ;
141
142        /** command 引数に渡す事の出来る コマンド  新規 {@value} */
143        public static final String CMD_NEW              = "NEW";                                                                                        // コマンド(新規)
144        /** command 引数に渡す事の出来る コマンド  再検索 {@value} */
145        public static final String CMD_RENEW    = "RENEW";                                                                                      // コマンド(再検索)
146        // String配列 から、Setに置き換えます。
147        private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_NEW, CMD_RENEW );            // コマンド(Set)
148
149        /** エラーメッセージID */
150        protected static final String ERR_MSG_ID        = HybsSystem.ERR_MSG_KEY;
151
152        // IOr 応答結果のキー
153        private   static final String IOR_HTTP_STTS     = "status";                                                                             // ステータス
154        private   static final String IOR_HTTP_MSG      = "message";                                                                    // エラーメッセージ
155        /** ヘッダ配列のラベル */
156        protected static final String IOR_DISP_LBL      = "display_label";                                                              // ヘッダ配列のラベル
157        /** ヘッダ配列のキー */
158        protected static final String IOR_DISP_KEY      = "display";                                                                    // ヘッダ配列のキー
159        private   static final String IOR_SQL_CNT       = "count";                                                                              // 実行件数
160
161        // JSONによるフェーズ認証フォーマット
162        private static final String AUTH_JSON_FMT       = "{\"userInfo\":{\"companyId\":\"%s\",\"userId\":\"%s\",\"password\":\"%s\"}}";
163
164        /** JSONコード */
165        protected final Map<String,String> mapParam = new LinkedHashMap<>();
166        /** テーブルモデル */
167        protected transient DBTableModel table;
168
169        /** 接続するURL */
170        private   String        urlStr                          ;
171        /** プロキシホスト名 */
172        private   String        proxyHost                       = HybsSystem.sys( "HTTP_PROXY_HOST" );
173        /** プロキシポート番号 */
174        private   int           proxyPort                       = HybsSystem.sysInt( "HTTP_PROXY_PORT" );
175        /** 接続タイムアウト時間 */
176        private   int           timeout                         = HybsSystem.sysInt( "URL_CONNECT_TIMEOUT" );
177        /** JSONコードで認証するURL */
178        private   String        authURL                         ;
179        /** ユーザー:パスワード */
180        private   String        authUserPass            ;
181        /** 企業ID */
182        private   String        companyId                       = HybsSystem.sys( "IOR_COMPANYID" );
183        /** アプリ名 */
184        private   String        appliName                       ;
185        /** 結果の表示可否 */
186        private   boolean       display                         ;
187        /** 保存ファイル */
188        private   String        saveFile                        ;
189        /** 読取ファイル */
190        protected String        loadFile                        ;
191        /** コマンド */
192        private   String        command                         = CMD_NEW;
193        /** ディスプレイメッセージ */
194        private   String        displayMsg                      = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
195        /** 対象データはありませんでした。 */
196        private   String        notfoundMsg                     = "MSG0077";
197        /** 処理の停止可否 */
198        private   boolean       stopZero                        ;
199        /** テーブルモデルID */
200        protected String        tableId                         = HybsSystem.TBL_MDL_KEY;
201        /** エラー時の処理中止可否 */
202        protected boolean       stopError                       = true;
203        /** 画面上のエラー出力可否 */
204        private   boolean       dispError                       = true;
205        /** クオートチェック */
206        protected boolean       quotCheck                       = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );
207        /** XSSチェック */
208        private   boolean       xssCheck                        = HybsSystem.sysBool( "USE_XSS_CHECK" );
209        /** 処理時間(queryTime)などの情報出力の可否 */
210        private   boolean       useBeforeHtmlTag        = true;
211        /** タイムバーの使用可否 */
212        protected boolean       useTimeView                     = HybsSystem.sysBool( "VIEW_USE_TIMEBAR" );
213
214        /** ユーザー */
215        private   String        user                            ;
216        /** パスワード */
217        private   String        pass                            ;
218        /** BODY部 */
219        protected String        postData                        ;
220        /** 取得データ */
221        protected String        rtnData                         ;
222        /** 実行件数 */
223        protected int           executeCount            ;
224        /** 現在時刻 */
225        protected long          dyStart                         ;
226        /** DBLastSqlの処理見直し */
227        private   boolean       isMainTrans                     = true;
228        /** ファイルURL */
229        private   String        fileURL                         = HybsSystem.sys( "FILE_URL" );
230
231        /**
232         * デフォルトコンストラクター
233         *
234         */
235        public IorQueryTag() { super(); }       // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
236
237        /**
238         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
239         *
240         * @return      後続処理の指示
241         */
242        @Override
243        public int doStartTag() {
244                if( !useTag() ) { return SKIP_BODY ; }
245
246                useXssCheck( xssCheck );
247                dyStart = System.currentTimeMillis();                                                                   // 現在時刻
248
249                if( ! check( command, COMMAND_SET ) ) {
250                        table = (DBTableModel)getObject( tableId );
251                        if( table == null )     { executeCount = 0; }
252                        else                            { executeCount = table.getRowCount(); }
253                        return SKIP_BODY;
254                }
255
256                useMainTrans( isMainTrans );
257                startQueryTransaction( tableId );
258
259                // scope="session" の場合のみ、削除します。
260                if( "session".equals( getScope() ) ) {
261                        removeSessionAttribute( tableId );
262                        removeSessionAttribute( HybsSystem.VIEWFORM_KEY );
263                }
264
265                // ユーザー:パスワード から ユーザーとパスワードを取得します。
266                checkUsrPw();
267
268                // 読取ファイル指定無し
269                if( loadFile == null ) {
270                        // JSON形式の共通要求キーを設定します。
271                        setComJson();
272                }
273                return EVAL_BODY_BUFFERED;                                                                                              // Body を評価する (extends BodyTagSupport 時)
274        }
275
276        /**
277         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
278         *
279         * @return      後続処理の指示(SKIP_BODY)
280         */
281        @Override
282        public int doAfterBody() {
283                // useQuotCheck() によるSQLインジェクション対策
284                useQuotCheck( quotCheck );
285
286                postData = getBodyString();
287
288                return SKIP_BODY;
289        }
290
291        /**
292         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
293         *
294         * @return      後続処理の指示
295         */
296        @Override
297        public int doEndTag() {
298                debugPrint();
299                if( !useTag() ) { return EVAL_PAGE; }
300
301                int errCode = ErrorMessage.OK;                                                                                  // エラーコード
302                if( check( command, COMMAND_SET ) ) {
303                        // URLに対して応答結果を取得します。
304                        rtnData = outJson();
305
306                        // IOr の応答結果を特定のキーワードで分割します。
307                        final SplitReqJson splitJson = new SplitReqJson( rtnData );
308
309                        // 応答結果の HTTPステータスコード を設定します。
310                        final String rtnStts = splitJson.getSttsJson();
311                        errCode = getStatus( rtnStts );
312
313                        if( errCode == ErrorMessage.OK ) {
314                                // 応答結果の 実行件数 を取得します。
315                                final String rtnCnt = splitJson.getCntJson();
316                                executeCount = getCount( rtnCnt );
317                                if( ! stopZero ) {
318                                        // テーブルモデル作成します。
319                                        table = makeDBTable( splitJson );
320                                        // 処理後のメッセージを作成します。
321                                        errCode = makeMessage();
322                                }
323                        }
324                }
325
326                final int rtnCode;
327                // 異常
328                if( errCode >= ErrorMessage.NG ) {
329                        rtnCode = stopError ? SKIP_PAGE : EVAL_PAGE ;
330                }
331                // 正常/警告
332                else {
333                        // 実行件数 = ゼロ 且つ stopZero = true
334                        rtnCode = executeCount == 0 && stopZero ? SKIP_PAGE : EVAL_PAGE ;
335                }
336
337                // 処理時間(queryTime)などの情報出力の有効/無効を指定します。
338                if( useTimeView && useBeforeHtmlTag ) {
339                        final long dyTime = System.currentTimeMillis() - dyStart;
340                        jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" );
341                }
342                return rtnCode;
343        }
344
345        /**
346         * タグリブオブジェクトをリリースします。
347         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
348         */
349        @Override
350        protected void release2() {
351                super.release2();
352                mapParam.clear();                                                                                                               // JSONコードのクリア
353                table                           = null;                                                                                         // テーブルモデル
354                urlStr                          = null;                                                                                         // 接続するURL
355                proxyHost                       = HybsSystem.sys( "HTTP_PROXY_HOST" );                          // プロキシホスト名
356                proxyPort                       = HybsSystem.sysInt( "HTTP_PROXY_PORT" );                       // プロキシポート番号
357                timeout                         = HybsSystem.sysInt( "URL_CONNECT_TIMEOUT" );           // 接続タイムアウト時間
358                authURL                         = null;                                                                                         // JSONコードで認証するURL
359                authUserPass            = null;                                                                                         // ユーザー:パスワード
360                companyId                       = HybsSystem.sys( "IOR_COMPANYID" );                            // 企業ID
361                appliName                       = null;                                                                                         // アプリ名
362                display                         = false;                                                                                        // 結果の表示可否
363                saveFile                        = null;                                                                                         // 保存ファイル
364                loadFile                        = null;                                                                                         // 読取ファイル
365                command                         = CMD_NEW;                                                                                      // コマンド
366                displayMsg                      = HybsSystem.sys( "VIEW_DISPLAY_MSG" );                         // ディスプレイメッセージ
367                notfoundMsg                     = "MSG0077";                                                                            // 対象データはありませんでした。
368                stopZero                        = false;                                                                                        // 処理の停止可否
369                tableId                         = HybsSystem.TBL_MDL_KEY;                                                       // テーブルモデル
370                stopError                       = true;                                                                                         // エラー時の処理中止可否
371                dispError                       = true;                                                                                         // 画面上のエラー出力可否
372                quotCheck                       = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );      // クオートチェック
373                xssCheck                        = HybsSystem.sysBool( "USE_XSS_CHECK" );                        // XSSチェック
374                useBeforeHtmlTag        = true;                                                                                         // 処理時間(queryTime)などの情報出力の可否
375                useTimeView                     = HybsSystem.sysBool( "VIEW_USE_TIMEBAR" );                     // タイムバーの使用可否
376
377                user                            = null;                                                                                         // ユーザー
378                pass                            = null;                                                                                         // パスワード
379                postData                        = null;                                                                                         // BODY部
380                rtnData                         = null;                                                                                         // 取得データ
381                executeCount            = 0;                                                                                            // 実行件数
382                dyStart                         = 0;                                                                                            // 現在時刻
383                isMainTrans                     = true;                                                                                         // DBLastSqlの処理見直し
384                fileURL                         = HybsSystem.sys( "FILE_URL" );                                         // ファイルURL
385        }
386
387        /**
388         * IorQuery オブジェクトに渡すパラメータをマッピングします。
389         *
390         * IorParamTag クラスよりセットされます。
391         * 但し、以下のキーに対して IorParamTag では指定できません。
392         * company_id、user_id、session_id、report_name、method
393         *
394         * @param       key     パラメータキー
395         * @param       val     パラメータ値
396         */
397        protected void addParam( final String key, final String val ) {
398                if( mapParam.containsKey( key ) ){
399                        final String errMsg = key + "のキーが重複しています。";
400                        throw new HybsSystemException( errMsg );
401                }
402                else {
403                        mapParam.put( key, val );
404                }
405        }
406
407        /**
408         * ユーザー:パスワード から ユーザーとパスワードを分割します。
409         */
410        protected void checkUsrPw() {
411                if( authUserPass.contains(":") ) {
412                        // ユーザー:パスワードを分割します。
413                        final String[] prm = StringUtil.csv2Array( authUserPass, ':' ,2 );
414                        user = prm[0];                                                                                                          // ユーザー
415                        pass = prm[1];                                                                                                          // パスワード
416                }
417                else {
418                        final String errMsg = "ユーザー:パスワード の形式で記述してください。";
419                        throw new HybsSystemException( errMsg );
420                }
421        }
422
423        /**
424         * JSON形式の共通要求キーを設定します。
425         * ・company_id   : 企業ID
426         * ・user_id      : ユーザーID
427         * ・session_id   : セッションID
428         * ・report_name  : アプリ名
429         * ・method       : 登録条件
430         * 例:{"company_id":"XXXXX","user_id":"admin","session_id":"$session_id$" …}
431         */
432        protected void setComJson() {
433                // 企業ID
434                if( companyId != null ) { mapParam.put( "company_id", companyId ); }
435                // ユーザーID
436                if( !user.isEmpty() ) { mapParam.put( "user_id", user ); }
437                // セッションID
438                mapParam.put( "session_id", "$session_id$" );
439                // アプリ名
440                if( appliName != null ) { mapParam.put( "report_name", appliName ); }
441        }
442
443        /**
444         * loadFile 指定がある場合は、ファイルからデータを読取ります。
445         * loadFile 指定がない場合は、URLに対して応答結果を取得します。
446         *
447         * @return      JSON形式の文字列
448         * @og.rtnNotNull
449         */
450        protected String outJson() {
451                final String str;
452
453                // 読取ファイル指定無し
454                if( loadFile == null ) {
455                        if( postData == null || postData.isEmpty() ){
456                                postData = JSONScan.map2Json( mapParam );
457                        }
458                        // URLに対して応答結果を取得します。
459                        str = retResponse();
460                }
461                // 読取ファイル指定有り
462                else {
463                        final StringBuilder buf = new StringBuilder(BUFFER_MIDDLE);
464                        try {
465                                for (final String text : Files.readAllLines( Paths.get(loadFile), StandardCharsets.UTF_8 )) {
466                                        buf.append( text )
467                                                .append( CR );
468                                }
469                                str = buf.toString();
470                        }
471                        catch( final IOException ex ) {
472                                final String errMsg = "loadFile 処理中でエラーが発生しました。"        + CR
473                                                        + "\t " + ex.getMessage()                                                       + CR ;
474                                throw new HybsSystemException( errMsg, ex );
475                        }
476                }
477                return str;
478        }
479
480        /**
481         * URLに対して応答結果を取得します。
482         *
483         * @return      URL接続先のデータ
484         * @og.rtnNotNull
485         */
486        protected String retResponse() {
487                HttpConnect conn = null;
488                Writer outWriter = null;
489                String getData = null;
490                try {
491                        conn = connect();
492
493                        // URL接続先のデータを取得します。
494                        getData = conn.readData();
495                        // 実行結果のステータスコードが'200'(正常)ではないとき、例外を発生させます。
496                        if( conn.getCode() != 200 ) { throw new Throwable(); }
497
498                        if( display ) {
499                                outWriter = FileUtil.getNonFlushPrintWriter( pageContext.getOut() ) ;   // JspWriter の取得
500                        }
501                        else if( saveFile != null ) {
502                                outWriter = FileUtil.getPrintWriter( new File( saveFile ), "UTF-8" );
503                        }
504
505                        // Unicode文字列から元の文字列に変換します。
506                        getData = StringUtil.convertToOiginal( getData );
507
508                        // 出力先が存在する場合
509                        if( outWriter != null ) {
510                                outWriter.write( getData );
511                        }
512                }
513                catch( final Throwable th ) {
514                        final String errMsg = "データ処理中にエラーが発生しました。"     + CR
515                                                + " url=[" + urlStr + "]"                                                       + CR
516                                                + " message=[" + ( conn == null ? "NO_CONNECTION" : conn.getMessage() ) + "]" + CR
517                                                + " Exception=[" + th.getMessage() + "]" ;
518                        throw new HybsSystemException( errMsg, th );
519                }
520                finally {
521                        Closer.ioClose( outWriter );
522                }
523                return getData;
524        }
525
526        /**
527         * URLに対して接続を行います。
528         *
529         * @return      接続オブジェクト
530         * @og.rtnNotNull
531         * @throws      IOException     入出力エラーが発生したとき
532         */
533        protected HttpConnect connect() throws IOException {
534                // HttpConnect は、後付で引数を渡せます。
535                final HttpConnect conn = new HttpConnect( urlStr, authUserPass );
536                conn.setDebug( isDebug() );
537                conn.usePost( true );
538
539                // プロキシ
540                if( proxyHost != null ) {
541                        conn.setProxy( proxyHost,proxyPort );
542                }
543                // JSONによるフェーズ認証
544                if( authUserPass != null && authURL != null ) {
545                        final String authJson = String.format( AUTH_JSON_FMT, companyId, user, pass ) ;
546                        conn.setAuthJson( authJson , authURL );
547                }
548                // 接続タイムアウト時間
549                if( timeout >= 0 ) {
550                        conn.setTimeout( timeout );
551                }
552                // JSONコードでリクエストするパラメータを指定
553                if( postData != null ) {
554                        conn.setReqJson( postData );
555                }
556                return conn;
557        }
558
559        /**
560         * IOr の要求結果から、HTTPステータスコード を設定します。
561         *
562         * @param       strJson Json形式の文字列
563         * @return      エラーコード
564         * @og.rtnNotNull
565         */
566        protected int getStatus( final String strJson ) {
567                int errCode = ErrorMessage.OK;                                                                                  // エラーコード
568                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );                   // バッファ
569
570                // ---------------------------------------------------------------------
571                // HTTPステータスコード (先頭から"data"までの文字列)
572                // 例:{"status": 200, "message": "OK", "sessionInfo": "51b16"
573                // ---------------------------------------------------------------------
574                // キーと値をマッピングします。
575                final Map<String,String> mapStts = JSONScan.json2Map( strJson );
576                final String stts = mapStts.get( IOR_HTTP_STTS );                                               // ステータス
577
578                // ステータスが'200'(正常)である
579                if( stts.equals( String.valueOf( 200 ) ) ) {
580                        errCode = ErrorMessage.OK;                                                                                      // 正常
581                }
582                // ステータスが'200'(正常)ではない
583                else {
584                        errCode = ErrorMessage.NG;                                                                                              // エラーコード
585                        final String msg = mapStts.get( IOR_HTTP_MSG );                                                         // エラーメッセージ
586
587                        final ErrorMessage errMessage = new ErrorMessage( "iorQueryTag Error!" );
588                        errMessage.addMessage( 0, errCode, stts, msg );
589
590                        // TaglibUtil.makeHTMLErrorTable メソッドを利用します。
591                        final String err = TaglibUtil.makeHTMLErrorTable( errMessage, getResource() );
592                        if( err != null && err.length() > 0 ) {
593                                buf.append( err );
594                                setSessionAttribute( ERR_MSG_ID, errMessage );
595                        }
596                        // 以前処理のエラーメッセージを削除します。
597                        else if( CMD_NEW.equals( command ) ) {
598                                removeSessionAttribute( ERR_MSG_ID );
599                        }
600                }
601
602                final String label = buf.toString();
603                // dispErrorで表示をコントロール
604                if( dispError ) { jspPrint( label ); }
605
606                // 検索結果を、"DB.ERR_CODE" キーでリクエストにセットします。
607                setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
608                // エラーメッセージを、"DB.ERR_MSG" キーでリクエストにセットします。
609                setRequestAttribute( "DB.ERR_MSG", label );
610
611                return errCode;
612        }
613
614        /**
615         * IOr の要求結果から、実行件数 を取得します。
616         *
617         * @param       strJson Json形式の文字列
618         * @return      実行件数
619         * @og.rtnNotNull
620         */
621        protected int getCount( final String strJson ) {
622                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );                   // バッファ
623
624                // ---------------------------------------------------------------------
625                // 件数 ("count"からの文字列)
626                // 例:"count": 10
627                // ---------------------------------------------------------------------
628                // キーと値をマッピングします。
629                final Map<String,String> mapCnt = JSONScan.json2Map( strJson );
630                final int count = nval( mapCnt.get( IOR_SQL_CNT ), -1 );                                // 実行件数
631
632                // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。
633                if( CMD_NEW.equals( command ) ) {
634                        if( count > 0 && displayMsg != null && displayMsg.length() > 0 ) {
635                                buf.append( count )
636                                        .append( getResource().getLabel( displayMsg ) )
637                                        .append( BR );
638                        }
639                        else if( count == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) {
640                                        buf.append( getResource().getLabel( notfoundMsg ) )
641                                                .append( BR );
642                        }
643                }
644
645                final String label = buf.toString();
646                // dispErrorで表示をコントロール
647                if( dispError ) { jspPrint( label ); }
648
649                // 検索結果の件数を、"DB.COUNT" キーでリクエストにセットします。
650                setRequestAttribute( "DB.COUNT" , String.valueOf( count ) );
651
652                return count;
653        }
654
655        /**
656         * IOr の 要求結果から、値を取り出し、DBTableModel を作成します。
657         *
658         * @param       strJson Json形式の文字列
659         * @return      テーブルモデル
660         * @og.rtnNotNull
661         */
662        private DBTableModel makeDBTable( final SplitReqJson strJson ) {
663                final DBTableModel table = DBTableModelUtil.newDBTable();
664
665                // ---------------------------------------------------------------------
666                // テーブルモデルの列 ("headers"から"rows"までの文字列)
667                // 例:"headers": [{"display_label": "品目番号", "display": "PN"}, … ]
668                // ---------------------------------------------------------------------
669                final String rtnClm = strJson.getClmJson();
670
671                // 中括弧({})で分割
672                final JSONScan scanClm = new JSONScan( rtnClm, '{', '}' );
673                final int cntClm = scanClm.countBlock();
674                table.init( cntClm );
675                int i = 0;
676
677                while( scanClm.hasNext() ) {
678                        final String clms = scanClm.next();
679
680                        // キーと値をマッピングします。
681                        final Map<String,String> mapClm = JSONScan.json2Map( clms );
682                        final String clmLbl = mapClm.get( IOR_DISP_LBL );                                       // ラベル(例:品目番号)
683                        final String clmKey = mapClm.get( IOR_DISP_KEY );                                       // キー(例:PN)
684
685                        // テーブルモデルに列を追加します。
686                        final DBColumn dbColumn = getResource().makeDBColumn( clmKey, clmLbl );
687                        table.setDBColumn( i++, dbColumn );
688                }
689
690                if( executeCount > 0 ){
691                        // ---------------------------------------------------------------------
692                        // テーブルモデルの行 ("cols"から最後の文字列)
693                        // 例:"rows": [{"cols": [1, "GEN", "20211130", 32.4, "kg"]}, … ]}}
694                        // ---------------------------------------------------------------------
695                        final String rtnRow = strJson.getRowJson();
696
697                        // 大括弧([])で分割
698                        final JSONScan scanRow = new JSONScan( rtnRow, '[', ']' );
699                        while( scanRow.hasNext() ) {
700                                final String rows = scanRow.next();
701                                final String[] vals = JSONScan.json2Array( rows );
702                                // テーブルモデルに行の値を追加します。
703                                table.addColumnValues( vals );
704                        }
705                }
706                return table;
707        }
708
709        /**
710         * 処理後のメッセージを作成します。
711         *
712         * @return      エラーコード
713         * @og.rtnNotNull
714         */
715        protected int makeMessage() {
716                int errCode = ErrorMessage.OK;                                                                                          // エラーコード
717                final ErrorMessage errMessage = new ErrorMessage( "iorQueryTag Error!" );       // エラーメッセージ
718                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );                           // バッファ
719
720                // 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。
721                if( table != null && ! commitTableObject( tableId, table ) ) {
722                        // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。
723                        errCode = ErrorMessage.NG;
724                        errMessage.addMessage( 0, errCode, "ERR0041" );
725                }
726
727                // TaglibUtil.makeHTMLErrorTable メソッドを利用します。
728                final String err = TaglibUtil.makeHTMLErrorTable( errMessage, getResource() );
729                if( err != null && err.length() > 0 ) {
730                        buf.append( err );
731                        setSessionAttribute( ERR_MSG_ID, errMessage );
732                }
733                else if( CMD_NEW.equals( command ) ) {
734                        removeSessionAttribute( ERR_MSG_ID );
735                }
736                final String label = buf.toString();
737                // dispErrorで表示をコントロール
738                if( dispError ) { jspPrint( label ); }
739
740                // 検索結果を、"DB.ERR_CODE" キーでリクエストにセットします。
741                setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
742                // エラーメッセージを、"DB.ERR_MSG" キーでリクエストにセットします。
743                setRequestAttribute( "DB.ERR_MSG", label );
744
745                return errCode;
746        }
747
748        /**
749         * 【TAG】アクセスする接続先URLを指定します。
750         *
751         * @og.tag
752         * 接続するURLを指定します。(例:http:// ・・・・・・)
753         *
754         * @param       url     接続先
755         */
756        public void setUrl( final String url ) {
757                urlStr = nval( getRequestParameter( url ),urlStr );
758        }
759
760        /**
761         * 【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します。
762         *
763         * @og.tag
764         * 接続先が、プロキシ経由の場合、プロキシのホスト名を指定します。
765         * 例:proxy.opengion.org
766         *
767         * @param       host    プロキシホスト名
768         */
769        public void setProxyHost( final String host ) {
770                proxyHost = nval( getRequestParameter( host ),proxyHost );
771        }
772
773        /**
774         * 【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します。
775         *
776         * @og.tag
777         * 接続先が、プロキシ経由の場合、プロキシのポート番号を指定します。
778         * 例:8080
779         *
780         * @param       port    プロキシポート番号
781         */
782        public void setProxyPort( final String port ) {
783                proxyPort = nval( getRequestParameter( port ),proxyPort );
784        }
785
786        /**
787         * 【TAG】接続タイムアウト時間を(秒)で指定します
788         *        (初期値:URL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])。
789         *
790         * @og.tag
791         * 実際には、java.net.URLConnection#setConnectTimeout(int) に 1000倍して設定されます。
792         * 0 は、無限のタイムアウト、マイナスは、設定しません。(つまりJavaの初期値のまま)
793         * (初期値:システム定数のURL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])。
794         *
795         * @param       tout    タイムアウト時間(秒) (ゼロは、無制限)
796         * @see         org.opengion.fukurou.util.HttpConnect#setTimeout(int)
797         * @see         java.net.URLConnection#setConnectTimeout(int)
798         */
799        public void setTimeout( final String tout ) {
800                timeout = nval( getRequestParameter( tout ),timeout );
801        }
802
803        /**
804         * 【TAG】JSONコードで認証するURLを指定します。
805         *
806         * @og.tag
807         * JSONコードで認証するURLを指定します。
808         *
809         * @param       url     JSONコードで認証するURL
810         */
811        public void setAuthURL( final String url ) {
812                authURL = nval( getRequestParameter( url ), authURL );
813        }
814
815        /**
816         * 【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します。
817         *
818         * @og.tag
819         * 接続時のユーザーとパスワードを、USER:PASSWD 形式で指定します。
820         *
821         * @param       userPass        ユーザーとパスワード (USER:PASSWD形式)
822         */
823        public void setAuthUserPass( final String userPass ) {
824                authUserPass = nval( getRequestParameter( userPass ),authUserPass );
825        }
826
827        /**
828         * 【TAG】企業IDを指定します。
829         *
830         * @og.tag
831         * 企業IDを指定します。
832         *
833         * @param       compId  企業ID
834         */
835        public void setCompanyId( final String compId ) {
836                companyId = nval( getRequestParameter( compId ),companyId );
837        }
838
839        /**
840         * 【TAG】アプリケーションの名前を指定します。
841         *
842         * @og.tag
843         * アプリケーションの名前を指定します。
844         *
845         * @param       appName データテーブル情報
846         */
847        public void setAppliName( final String appName ) {
848                appliName = nval( getRequestParameter( appName ),appliName );
849        }
850
851        /**
852         * 【TAG】接続の結果を表示するかどうかを指定します(初期値:false)。
853         *
854         * @og.tag
855         * true で、接続結果を表示します。 false では、何も表示しません(初期値:false)
856         * 接続結果を表示する使い方より、admin 画面に接続して、キャッシュクリアするような
857         * 使い方が多いと考え、初期値は、false になっています。
858         * display="true" と、saveFile を併用することはできません。
859         *
860         * @param       flag    結果表示 [true:する/false:しない]
861         * @see         #setSaveFile( String )
862         */
863        public void setDisplay( final String flag ) {
864                display = nval( getRequestParameter( flag ),display );
865
866                if( display && saveFile != null ) {
867                        final String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
868                        throw new HybsSystemException( errMsg );
869                }
870        }
871
872        /**
873         * 【TAG】接続の結果をファイルに保存します。
874         *
875         * @og.tag
876         * 接続先のデータを受け取って、ファイルに保存します。
877         * display="true" と、saveFile を併用することはできません。
878         * loadFile が指定されていない時のみ処理を行います。
879         *
880         * @param       file    保存先ファイル
881         * @see         #setDisplay( String )
882         */
883        public void setSaveFile( final String file ) {
884                saveFile = nval( getRequestParameter( file ),saveFile );
885                if( saveFile != null ) {
886                        saveFile = HybsSystem.url2dir( StringUtil.urlAppend( fileURL,saveFile ) );
887                        if( display ) {
888                                final String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
889                                throw new HybsSystemException( errMsg );
890                        }
891                }
892        }
893
894        /**
895         * 【TAG】ファイルからURL接続結果に相当するデータを読み取ります。
896         *
897         * @og.tag
898         * 主にデバッグ用として使われます。
899         *
900         * @param       file    検索するファイル
901         */
902        public void setLoadFile( final String file ) {
903                loadFile = nval( getRequestParameter( file ),loadFile );
904                if( loadFile != null ) {
905                        loadFile = HybsSystem.url2dir( StringUtil.urlAppend( fileURL,loadFile ) );
906                }
907        }
908
909        /**
910         * 【TAG】コマンド (NEW,RENEW)をセットします。
911         *
912         * @og.tag
913         * コマンドは、HTMLから(get/post)指定されますので、
914         * CMD_xxx で設定されるフィールド定数値のいづれかを指定できます。
915         *
916         * @param       cmd     コマンド (public static final 宣言されている文字列)
917         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.QueryTag.CMD_NEW">コマンド定数</a>
918         */
919        public void setCommand( final String cmd ) {
920                final String cmd2 = getRequestParameter( cmd );
921                if( cmd2 != null && cmd2.length() >= 0 ) { command = cmd2.toUpperCase( Locale.JAPAN ); }
922        }
923
924        /**
925         * 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します
926         *        (初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
927         *
928         * @og.tag
929         * ここでは、検索結果の件数や登録された件数をまず出力し、
930         * その次に、ここで指定したメッセージをリソースから取得して表示します。
931         * 件数を表示させる場合は、displayMsg = "MSG0033"[ 件検索しました] をセットしてください。
932         * 表示させたくない場合は、displayMsg = "" をセットしてください。
933         * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
934         *
935         * @param       id      表示メッセージID
936         * @see         org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG
937         */
938        public void setDisplayMsg( final String id ) {
939                final String ids = getRequestParameter( id );
940                if( ids != null ) { displayMsg = ids; }
941        }
942
943        /**
944         * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
945         *
946         * @og.tag
947         * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。
948         * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、
949         * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。
950         * 表示させたくない場合は、notfoundMsg = "" をセットしてください。
951         * 初期値は、MSG0077[対象データはありませんでした]です。
952         *
953         * @param       id      ゼロ件メッセージID
954         */
955        public void setNotfoundMsg( final String id ) {
956                final String ids = getRequestParameter( id );
957                if( ids != null ) { notfoundMsg = ids; }
958        }
959
960        /**
961         * 【TAG】検索結果が0件のとき処理を停止するかどうか[true/false]を指定します(初期値:false[続行する])。
962         *
963         * @og.tag
964         * 初期値は、false(続行する)です。
965         *
966         * @param       flag    0件時停止可否 [true:処理を中止する/false:続行する]
967         */
968        public void setStopZero( final String flag ) {
969                stopZero = nval( getRequestParameter( flag ),stopZero );
970        }
971
972        /**
973         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
974         *        (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
975         *
976         * @og.tag
977         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
978         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
979         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
980         * この tableId 属性を利用して、メモリ空間を分けます。
981         *(初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
982         *
983         * @param       id      テーブルID (sessionに登録する時のID)
984         */
985        public void setTableId( final String id ) {
986                tableId = nval( getRequestParameter( id ),tableId );
987        }
988
989        /**
990         * 【TAG】処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true)。
991         *
992         * @og.tag
993         * false(中止しない)に設定する場合、後続処理では、{&#064;DB.ERR_CODE}の値により、
994         * IOr の異常/正常終了によって分岐処理は可能となります。
995         * 初期値は、true(中止する)です。
996         *
997         * @param       flag    エラー時処理中止 [true:中止する/false:中止しない]
998         */
999        public void setStopError( final String flag ) {
1000                stopError = nval( getRequestParameter( flag ),stopError );
1001        }
1002
1003        /**
1004         * 【TAG】PLSQL/SQL処理エラーの時にエラーを画面表示するか[true/false]を設定します(初期値:true)。
1005         *
1006         * @og.tag
1007         * false(表示しない)に設定する場合、後続処理では、{&#064;DB.ERR_MSG}の値により、
1008         * 本来表示されるはずだったメッセージを取得可能です。
1009         * stopErrorと併用して、JSON形式でエラーを返す場合等に利用します。
1010         * 初期値は、true(表示する)です。
1011         * ※false指定の場合は件数や、overFlowメッセージ等も表示されなくなります。
1012         *
1013         * @param       flag    [true:表示する/false:表示しない]
1014         */
1015        public void setDispError( final String flag ) {
1016                dispError = nval( getRequestParameter( flag ),dispError );
1017        }
1018
1019        /**
1020         * 【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します
1021         *        (初期値:USE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])。
1022         *
1023         * @og.tag
1024         * SQLインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに
1025         * 渡す文字列にシングルクォート(') を許さない設定にすれば、ある程度は防止できます。
1026         * 数字タイプの引数には、 or 5=5 などのシングルクォートを使用しないコードを埋めても、
1027         * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、
1028         * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。
1029         * (') が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
1030         * 初期値は、SystemData#USE_SQL_INJECTION_CHECK です。
1031         *
1032         * @param       flag    クォートチェック [true:する/それ以外:しない]
1033         */
1034        public void setQuotCheck( final String flag ) {
1035                quotCheck = nval( getRequestParameter( flag ),quotCheck );
1036        }
1037
1038        /**
1039         * 【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します
1040         *        (初期値:USE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])。
1041         *
1042         * @og.tag
1043         * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
1044         * (&gt;&lt;) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
1045         * (初期値:システム定数のUSE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])
1046         *
1047         * @param       flag    XSSチェック [true:する/false:しない]
1048         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
1049         */
1050        public void setXssCheck( final String flag ) {
1051                xssCheck = nval( getRequestParameter( flag ),xssCheck );
1052        }
1053
1054        /**
1055         * 【TAG】(通常は使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。
1056         *
1057         * @og.tag
1058         * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
1059         * ファイルダウンロードの対象の表になります。
1060         *
1061         * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
1062         * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
1063         * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
1064         * 除外することができます。
1065         *
1066         * @param       flag    メイントランザクションかどうか [true:メイン/false:その他]
1067         */
1068        public void setMainTrans( final String flag ) {
1069                isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
1070        }
1071
1072        /**
1073         * 【TAG】処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true)。
1074         *
1075         * @og.tag
1076         * Query で、検索する場合に、処理時間(queryTime)などの情報を出力していますが、
1077         * ViewForm で、CustomData などの 非HTML表示ビューを使用する場合、データとして、
1078         * 紛れ込んでしまうため、出力を抑制する必要があります。
1079         * true(有効)にすると、これらのHTMLが出力されます。false にすると、出力されません。
1080         * 初期値は、true(有効) です。
1081         *
1082         * @param       useTag  情報出力の有効/無効 [true:有効/false:無効]
1083         */
1084        public void setUseBeforeHtmlTag( final String useTag ) {
1085                useBeforeHtmlTag = nval( getRequestParameter( useTag ),useBeforeHtmlTag );
1086        }
1087
1088        /**
1089         * 【TAG】処理時間を表示する TimeView を表示するかどうか[true:する/false:しない]を指定します
1090         *        (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。
1091         *
1092         * @og.tag
1093         * true に設定すると、処理時間を表示するバーイメージが表示されます。
1094         * これは、DB検索、APサーバー処理、画面表示の各処理時間をバーイメージで
1095         * 表示させる機能です。処理時間の目安になります。
1096         * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。
1097         *
1098         * @param       flag    処理時間を表示 [true:する/false:しない]
1099         */
1100        public void setUseTimeView( final String flag ) {
1101                useTimeView = nval( getRequestParameter( flag ),useTimeView );
1102        }
1103
1104        /**
1105         * IOr の応答結果を特定のキーワードで分割します。(内部クラス)
1106         *
1107         * フォーマット形式のチェック と データの切り出しを行います。
1108         * JSONフォーマットの例:{"status": … "data": {"headers": [ … ], "rows": [ {cols:[ … ]} ]}}
1109         */
1110        private static final class SplitReqJson {
1111                private final String    strJson;                                                                                // JSON形式の文字列
1112                private int                             endPos;                                                                                 // 終了位置
1113
1114                /**
1115                 * コンストラクター
1116                 *
1117                 * @param       strJson JSON形式の文字列
1118                 */
1119                public SplitReqJson( final String str ) {
1120                        strJson         = str;                                                                                                  // JSON形式の文字列
1121                        endPos          = strJson.indexOf( "\"data\"" );                                                // 終了位置
1122                }
1123
1124                /**
1125                 * HTTPステータス(先頭から "data"まで) の文字列を返します。
1126                 *
1127                 * @return      JSON形式の文字列
1128                 */
1129                public String getSttsJson() {
1130                        if( endPos >= 0 ) {
1131                                return strJson.substring( 0, endPos );
1132                        } else {
1133                                final String errMsg = "data キーが存在しません。";
1134                                throw new HybsSystemException( errMsg );
1135                        }
1136                }
1137
1138                /**
1139                 * 列データ("headers"から "rows"まで) の文字列を返します。
1140                 *
1141                 * @return      JSON形式の文字列
1142                 */
1143                public String getClmJson() {
1144                        final int startPos = strJson.indexOf( "\"headers\"", endPos );          // 開始位置
1145                        endPos = strJson.indexOf( "\"rows\"", startPos );                                       // 終了位置
1146                        if( startPos >= 0 && endPos >= 0) {
1147                                return strJson.substring( startPos, endPos );
1148                        } else {
1149                                final String errMsg = "headers、rows キーのいずれかが存在しません。";
1150                                throw new HybsSystemException( errMsg );
1151                        }
1152                }
1153
1154                /**
1155                 * 行データ("cols"から 最後まで) の文字列を返します。
1156                 *
1157                 * @return      JSON形式の文字列
1158                 */
1159                public String getRowJson() {
1160                        final int startPos = strJson.indexOf( "\"cols\"", endPos );                     // 開始位置
1161                        if( startPos >= 0 ) {
1162                                return strJson.substring( startPos );
1163                        } else {
1164                                final String errMsg = "cols キーが存在しません。";
1165                                throw new HybsSystemException( errMsg );
1166                        }
1167                }
1168
1169                /**
1170                 * 行データ(最後から "count") の文字列を返します。
1171                 *
1172                 * @return      JSON形式の文字列
1173                 */
1174                public String getCntJson() {
1175                        final int startPos = strJson.lastIndexOf( "\"count\"" );                        // 開始位置
1176                        if( startPos >= 0 ) {
1177                                return strJson.substring( startPos );
1178                        } else {
1179                                final String errMsg = "count キーが存在しません。";
1180                                throw new HybsSystemException( errMsg );
1181                        }
1182                }
1183        }
1184
1185        /**
1186         * このオブジェクトの文字列表現を返します。
1187         * 基本的にデバッグ目的に使用します。
1188         *
1189         * @return      このクラスの文字列表現
1190         * @og.rtnNotNull
1191         */
1192        @Override
1193        public String toString() {
1194                return ToString.title( this.getClass().getName() )
1195                                .println( "VERSION"                     ,VERSION                )
1196                                .println( "urlStr"                      ,urlStr                 )
1197                                .println( "timeout"                     ,timeout                )
1198                                .println( "authURL"                     ,authURL                )
1199                                .println( "authUserPass"        ,authUserPass   )
1200                                .println( "companyId"           ,companyId              )
1201                                .println( "appliName"           ,appliName              )
1202                                .println( "display"                     ,display                )
1203                                .println( "postData"            ,postData               )
1204                                .println( "saveFile"            ,saveFile               )
1205                                .println( "loadFile"            ,loadFile               )
1206                                .println( "tableId"                     ,tableId                )
1207                                .println( "Other..."            ,getAttributes().getAttribute() )
1208                                .fixForm().toString() ;
1209        }
1210}