2 * Copyright (c) 2009 The openGion Project.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
16 package org.opengion.hayabusa.taglib;
19 import java.io.IOException;
20 import java.io.Writer;
21 import java.nio.charset.StandardCharsets;
22 import java.nio.file.Files;
23 import java.nio.file.Paths;
24 import java.util.LinkedHashMap;
25 import java.util.Locale;
29 import org.opengion.fukurou.system.Closer;
30 import org.opengion.fukurou.util.ArraySet;
31 import org.opengion.fukurou.util.ErrorMessage;
32 import org.opengion.fukurou.util.FileUtil;
33 import org.opengion.fukurou.util.HttpConnect;
34 import org.opengion.fukurou.util.JSONScan;
35 import org.opengion.fukurou.util.StringUtil;
36 import org.opengion.fukurou.util.ToString;
37 import org.opengion.hayabusa.common.HybsSystem;
38 import org.opengion.hayabusa.common.HybsSystemException;
39 import org.opengion.hayabusa.db.DBColumn;
40 import org.opengion.hayabusa.db.DBTableModel;
41 import org.opengion.hayabusa.db.DBTableModelUtil;
43 import static org.opengion.fukurou.util.StringUtil.nval;
46 * IOr (Information Organizer) に接続し、取得したデータベースを表示するタグです。
48 * IOr へデータ取得を要求して受取った JSON形式 の文字列を、DBTableModel にセットします。
49 * IOr から取得したデータより loadFile が優先されます。
51 * このタグの結果(DBTableModel)は、通常の QueryTag と同様に
52 * ViewFormTag で一覧表示や、WriteTableTag でファイル出力が可能です。
54 * SystemData の USE_SQL_INJECTION_CHECK が true か、quotCheck 属性が true の場合は、
55 * SQLインジェクション対策用のシングルクォートチェックを行います。リクエスト引数に
56 * シングルクォート(')が含まれると、エラーになります。
57 * 同様にUSE_XSS_CHECKがtrueか、xssCheck属性がtrueの場合は、
58 * クロスサイトススクリプティング(XSS)対策のためless/greater than signのチェックを行います。
60 * 実行後にリクエストパラメータに以下の値がセットされます。
62 * DB.ERR_CODE : 実行結果のエラーコード
63 * DB.ERR_MSG : 実行結果のエラーメッセージ
65 * ※ このタグは、Transaction タグの対象です。
70 * url = "http://・・・ " 必須
71 * authURL = "http://・・・ " 必須
72 * authUserPass = "admin:******" 必須
73 * appliName = "データテーブル名"
75 * </og:iorQuery>
77 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
81 * url ○【TAG】アクセスする URL を指定します (必須)
82 * proxyHost 【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します
83 * proxyPort 【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します
84 * timeout 【TAG】通信リンクのオープン時に、指定された秒単位のタイム・アウト値を使用します
85 * (初期値:URL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])
86 * authURL ○【TAG】JSONコードで認証するURLを指定します (必須)
87 * authUserPass ○【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します (必須)
88 * companyId 【TAG】企業IDを指定します
89 * appliName ○【TAG】アプリケーションの名前を指定します
90 * display 【TAG】接続の結果を表示するかどうかを指定します (初期値:false)
91 * saveFile 【TAG】接続の結果をファイルに保存します
92 * loadFile 【TAG】ファイルからURL接続結果に相当するデータを読み取ります
93 * command 【TAG】コマンド(NEW,RENEW)をセットします
94 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します (初期値:session)
95 * displayMsg 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
96 * notfoundMsg 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します
97 * (初期値:MSG0077[対象データはありませんでした])
98 * stopZero 【TAG】検索結果が0件のとき処理を続行するかどうか[true/false]を指定します (初期値:false[続行する])
99 * 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)
117 * </og:iorQuery>
121 * url = "http://・・・ "
122 * authURL = "http://・・・ "
123 * authUserPass = "admin:******"
124 * appliName = "データテーブル名"
127 * key = "where_lk" value = "{'PN':'{@PN}%','TANI':'{@TANI}'}" />
128 * </og:iorQuery>
130 * @og.rev 8.0.2.0 (2021/11/30) 新規作成
137 public 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 ;
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)
150 protected static final String ERR_MSG_ID = HybsSystem.ERR_MSG_KEY;
153 private static final String IOR_HTTP_STTS = "status"; // ステータス
154 private static final String IOR_HTTP_MSG = "message"; // エラーメッセージ
156 protected static final String IOR_DISP_LBL = "display_label"; // ヘッダ配列のラベル
158 protected static final String IOR_DISP_KEY = "display"; // ヘッダ配列のキー
159 private static final String IOR_SQL_CNT = "count"; // 実行件数
161 // JSONによるフェーズ認証フォーマット
162 private static final String AUTH_JSON_FMT = "{\"userInfo\":{\"companyId\":\"%s\",\"userId\":\"%s\",\"password\":\"%s\"}}";
165 protected final Map<String,String> mapParam = new LinkedHashMap<>();
167 protected transient DBTableModel table;
170 private String urlStr ;
172 private String proxyHost = HybsSystem.sys( "HTTP_PROXY_HOST" );
174 private int proxyPort = HybsSystem.sysInt( "HTTP_PROXY_PORT" );
176 private int timeout = HybsSystem.sysInt( "URL_CONNECT_TIMEOUT" );
177 /** JSONコードで認証するURL */
178 private String authURL ;
180 private String authUserPass ;
182 private String companyId = HybsSystem.sys( "IOR_COMPANYID" );
184 private String appliName ;
186 private boolean display ;
188 private String saveFile ;
190 protected String loadFile ;
192 private String command = CMD_NEW;
193 /** ディスプレイメッセージ */
194 private String displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
195 /** 対象データはありませんでした。 */
196 private String notfoundMsg = "MSG0077";
198 private boolean stopZero ;
200 protected String tableId = HybsSystem.TBL_MDL_KEY;
202 protected boolean stopError = true;
204 private boolean dispError = true;
206 protected boolean quotCheck = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );
208 private boolean xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" );
209 /** 処理時間(queryTime)などの情報出力の可否 */
210 private boolean useBeforeHtmlTag = true;
212 protected boolean useTimeView = HybsSystem.sysBool( "VIEW_USE_TIMEBAR" );
215 private String user ;
217 private String pass ;
219 protected String postData ;
221 protected String rtnData ;
223 protected int executeCount ;
225 protected long dyStart ;
226 /** DBLastSqlの処理見直し */
227 private boolean isMainTrans = true;
229 private String fileURL = HybsSystem.sys( "FILE_URL" );
235 public IorQueryTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
238 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
243 public int doStartTag() {
244 if( !useTag() ) { return SKIP_BODY ; }
246 useXssCheck( xssCheck );
247 dyStart = System.currentTimeMillis(); // 現在時刻
249 if( ! check( command, COMMAND_SET ) ) {
250 table = (DBTableModel)getObject( tableId );
251 if( table == null ) { executeCount = 0; }
252 else { executeCount = table.getRowCount(); }
256 useMainTrans( isMainTrans );
257 startQueryTransaction( tableId );
259 // scope="session" の場合のみ、削除します。
260 if( "session".equals( getScope() ) ) {
261 removeSessionAttribute( tableId );
262 removeSessionAttribute( HybsSystem.VIEWFORM_KEY );
265 // ユーザー:パスワード から ユーザーとパスワードを取得します。
269 if( loadFile == null ) {
270 // JSON形式の共通要求キーを設定します。
273 return EVAL_BODY_BUFFERED; // Body を評価する (extends BodyTagSupport 時)
277 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
279 * @return 後続処理の指示(SKIP_BODY)
282 public int doAfterBody() {
283 // useQuotCheck() によるSQLインジェクション対策
284 useQuotCheck( quotCheck );
286 postData = getBodyString();
292 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
297 public int doEndTag() {
299 if( !useTag() ) { return EVAL_PAGE; }
301 int errCode = ErrorMessage.OK; // エラーコード
302 if( check( command, COMMAND_SET ) ) {
303 // URLに対して応答結果を取得します。
306 // IOr の応答結果を特定のキーワードで分割します。
307 final SplitReqJson splitJson = new SplitReqJson( rtnData );
309 // 応答結果の HTTPステータスコード を設定します。
310 final String rtnStts = splitJson.getSttsJson();
311 errCode = getStatus( rtnStts );
313 if( errCode == ErrorMessage.OK ) {
314 // 応答結果の 実行件数 を取得します。
315 final String rtnCnt = splitJson.getCntJson();
316 executeCount = getCount( rtnCnt );
319 table = makeDBTable( splitJson );
321 errCode = makeMessage();
328 if( errCode >= ErrorMessage.NG ) {
329 rtnCode = stopError ? SKIP_PAGE : EVAL_PAGE ;
333 // 実行件数 = ゼロ 且つ stopZero = true
334 rtnCode = executeCount == 0 && stopZero ? SKIP_PAGE : EVAL_PAGE ;
337 // 処理時間(queryTime)などの情報出力の有効/無効を指定します。
338 if( useTimeView && useBeforeHtmlTag ) {
339 final long dyTime = System.currentTimeMillis() - dyStart;
340 jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" );
346 * タグリブオブジェクトをリリースします。
347 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
350 protected void 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" ); // タイムバーの使用可否
377 user = null; // ユーザー
378 pass = null; // パスワード
379 postData = null; // BODY部
380 rtnData = null; // 取得データ
381 executeCount = 0; // 実行件数
383 isMainTrans = true; // DBLastSqlの処理見直し
384 fileURL = HybsSystem.sys( "FILE_URL" ); // ファイルURL
388 * IorQuery オブジェクトに渡すパラメータをマッピングします。
390 * IorParamTag クラスよりセットされます。
391 * 但し、以下のキーに対して IorParamTag では指定できません。
392 * company_id、user_id、session_id、report_name、method
394 * @param key パラメータキー
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 );
403 mapParam.put( key, val );
408 * ユーザー:パスワード から ユーザーとパスワードを分割します。
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]; // パスワード
418 final String errMsg = "ユーザー:パスワード の形式で記述してください。";
419 throw new HybsSystemException( errMsg );
424 * JSON形式の共通要求キーを設定します。
427 * ・session_id : セッションID
428 * ・report_name : アプリ名
430 * 例:{"company_id":"XXXXX","user_id":"admin","session_id":"$session_id$" …}
432 protected void setComJson() {
434 if( companyId != null ) { mapParam.put( "company_id", companyId ); }
436 if( !user.isEmpty() ) { mapParam.put( "user_id", user ); }
438 mapParam.put( "session_id", "$session_id$" );
440 if( appliName != null ) { mapParam.put( "report_name", appliName ); }
444 * loadFile 指定がある場合は、ファイルからデータを読取ります。
445 * loadFile 指定がない場合は、URLに対して応答結果を取得します。
450 protected String outJson() {
454 if( loadFile == null ) {
455 if( postData == null || postData.isEmpty() ){
456 postData = JSONScan.map2Json( mapParam );
458 // URLに対して応答結果を取得します。
463 final StringBuilder buf = new StringBuilder(BUFFER_MIDDLE);
465 for (final String text : Files.readAllLines( Paths.get(loadFile), StandardCharsets.UTF_8 )) {
469 str = buf.toString();
471 catch( final IOException ex ) {
472 final String errMsg = "loadFile 処理中でエラーが発生しました。" + CR
473 + "\t " + ex.getMessage() + CR ;
474 throw new HybsSystemException( errMsg, ex );
483 * @return URL接続先のデータ
486 protected String retResponse() {
487 HttpConnect conn = null;
488 Writer outWriter = null;
489 String getData = null;
493 // URL接続先のデータを取得します。
494 getData = conn.readData();
495 // 実行結果のステータスコードが'200'(正常)ではないとき、例外を発生させます。
496 if( conn.getCode() != 200 ) { throw new Throwable(); }
499 outWriter = FileUtil.getNonFlushPrintWriter( pageContext.getOut() ) ; // JspWriter の取得
501 else if( saveFile != null ) {
502 outWriter = FileUtil.getPrintWriter( new File( saveFile ), "UTF-8" );
505 // Unicode文字列から元の文字列に変換します。
506 getData = StringUtil.convertToOiginal( getData );
509 if( outWriter != null ) {
510 outWriter.write( getData );
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 );
521 Closer.ioClose( outWriter );
531 * @throws IOException 入出力エラーが発生したとき
533 protected HttpConnect connect() throws IOException {
534 // HttpConnect は、後付で引数を渡せます。
535 final HttpConnect conn = new HttpConnect( urlStr, authUserPass );
536 conn.setDebug( isDebug() );
537 conn.usePost( true );
540 if( proxyHost != null ) {
541 conn.setProxy( proxyHost,proxyPort );
544 if( authUserPass != null && authURL != null ) {
545 final String authJson = String.format( AUTH_JSON_FMT, companyId, user, pass ) ;
546 conn.setAuthJson( authJson , authURL );
550 conn.setTimeout( timeout );
552 // JSONコードでリクエストするパラメータを指定
553 if( postData != null ) {
554 conn.setReqJson( postData );
560 * IOr の要求結果から、HTTPステータスコード を設定します。
562 * @param strJson Json形式の文字列
566 protected int getStatus( final String strJson ) {
567 int errCode = ErrorMessage.OK; // エラーコード
568 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); // バッファ
570 // ---------------------------------------------------------------------
571 // HTTPステータスコード (先頭から"data"までの文字列)
572 // 例:{"status": 200, "message": "OK", "sessionInfo": "51b16"
573 // ---------------------------------------------------------------------
575 final Map<String,String> mapStts = JSONScan.json2Map( strJson );
576 final String stts = mapStts.get( IOR_HTTP_STTS ); // ステータス
578 // ステータスが'200'(正常)である
579 if( stts.equals( String.valueOf( 200 ) ) ) {
580 errCode = ErrorMessage.OK; // 正常
582 // ステータスが'200'(正常)ではない
584 errCode = ErrorMessage.NG; // エラーコード
585 final String msg = mapStts.get( IOR_HTTP_MSG ); // エラーメッセージ
587 final ErrorMessage errMessage = new ErrorMessage( "iorQueryTag Error!" );
588 errMessage.addMessage( 0, errCode, stts, msg );
590 // TaglibUtil.makeHTMLErrorTable メソッドを利用します。
591 final String err = TaglibUtil.makeHTMLErrorTable( errMessage, getResource() );
592 if( err != null && err.length() > 0 ) {
594 setSessionAttribute( ERR_MSG_ID, errMessage );
596 // 以前処理のエラーメッセージを削除します。
597 else if( CMD_NEW.equals( command ) ) {
598 removeSessionAttribute( ERR_MSG_ID );
602 final String label = buf.toString();
603 // dispErrorで表示をコントロール
604 if( dispError ) { jspPrint( label ); }
606 // 検索結果を、"DB.ERR_CODE" キーでリクエストにセットします。
607 setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
608 // エラーメッセージを、"DB.ERR_MSG" キーでリクエストにセットします。
609 setRequestAttribute( "DB.ERR_MSG", label );
615 * IOr の要求結果から、実行件数 を取得します。
617 * @param strJson Json形式の文字列
621 protected int getCount( final String strJson ) {
622 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); // バッファ
624 // ---------------------------------------------------------------------
625 // 件数 ("count"からの文字列)
627 // ---------------------------------------------------------------------
629 final Map<String,String> mapCnt = JSONScan.json2Map( strJson );
630 final int count = nval( mapCnt.get( IOR_SQL_CNT ), -1 ); // 実行件数
632 // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。
633 if( CMD_NEW.equals( command ) ) {
634 if( count > 0 && displayMsg != null && displayMsg.length() > 0 ) {
636 .append( getResource().getLabel( displayMsg ) )
639 else if( count == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) {
640 buf.append( getResource().getLabel( notfoundMsg ) )
645 final String label = buf.toString();
646 // dispErrorで表示をコントロール
647 if( dispError ) { jspPrint( label ); }
649 // 検索結果の件数を、"DB.COUNT" キーでリクエストにセットします。
650 setRequestAttribute( "DB.COUNT" , String.valueOf( count ) );
656 * IOr の 要求結果から、値を取り出し、DBTableModel を作成します。
658 * @param strJson Json形式の文字列
662 private DBTableModel makeDBTable( final SplitReqJson strJson ) {
663 final DBTableModel table = DBTableModelUtil.newDBTable();
665 // ---------------------------------------------------------------------
666 // テーブルモデルの列 ("headers"から"rows"までの文字列)
667 // 例:"headers": [{"display_label": "品目番号", "display": "PN"}, … ]
668 // ---------------------------------------------------------------------
669 final String rtnClm = strJson.getClmJson();
672 final JSONScan scanClm = new JSONScan( rtnClm, '{', '}' );
673 final int cntClm = scanClm.countBlock();
674 table.init( cntClm );
677 while( scanClm.hasNext() ) {
678 final String clms = scanClm.next();
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)
685 // テーブルモデルに列を追加します。
686 final DBColumn dbColumn = getResource().makeDBColumn( clmKey, clmLbl );
687 table.setDBColumn( i++, dbColumn );
690 if( executeCount > 0 ){
691 // ---------------------------------------------------------------------
692 // テーブルモデルの行 ("cols"から最後の文字列)
693 // 例:"rows": [{"cols": [1, "GEN", "20211130", 32.4, "kg"]}, … ]}}
694 // ---------------------------------------------------------------------
695 final String rtnRow = strJson.getRowJson();
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 );
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 ); // バッファ
720 // 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。
721 if( table != null && ! commitTableObject( tableId, table ) ) {
722 // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。
723 errCode = ErrorMessage.NG;
724 errMessage.addMessage( 0, errCode, "ERR0041" );
727 // TaglibUtil.makeHTMLErrorTable メソッドを利用します。
728 final String err = TaglibUtil.makeHTMLErrorTable( errMessage, getResource() );
729 if( err != null && err.length() > 0 ) {
731 setSessionAttribute( ERR_MSG_ID, errMessage );
733 else if( CMD_NEW.equals( command ) ) {
734 removeSessionAttribute( ERR_MSG_ID );
736 final String label = buf.toString();
737 // dispErrorで表示をコントロール
738 if( dispError ) { jspPrint( label ); }
740 // 検索結果を、"DB.ERR_CODE" キーでリクエストにセットします。
741 setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
742 // エラーメッセージを、"DB.ERR_MSG" キーでリクエストにセットします。
743 setRequestAttribute( "DB.ERR_MSG", label );
749 * 【TAG】アクセスする接続先URLを指定します。
752 * 接続するURLを指定します。(例:http:// ・・・・・・)
756 public void setUrl( final String url ) {
757 urlStr = nval( getRequestParameter( url ),urlStr );
761 * 【TAG】プロキシ経由で接続する場合の、プロキシホスト名を指定します。
764 * 接続先が、プロキシ経由の場合、プロキシのホスト名を指定します。
765 * 例:proxy.opengion.org
767 * @param host プロキシホスト名
769 public void setProxyHost( final String host ) {
770 proxyHost = nval( getRequestParameter( host ),proxyHost );
774 * 【TAG】プロキシ経由で接続する場合の、プロキシポート番号を指定します。
777 * 接続先が、プロキシ経由の場合、プロキシのポート番号を指定します。
780 * @param port プロキシポート番号
782 public void setProxyPort( final String port ) {
783 proxyPort = nval( getRequestParameter( port ),proxyPort );
787 * 【TAG】接続タイムアウト時間を(秒)で指定します
788 * (初期値:URL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])。
791 * 実際には、java.net.URLConnection#setConnectTimeout(int) に 1000倍して設定されます。
792 * 0 は、無限のタイムアウト、マイナスは、設定しません。(つまりJavaの初期値のまま)
793 * (初期値:システム定数のURL_CONNECT_TIMEOUT[={@og.value SystemData#URL_CONNECT_TIMEOUT}])。
795 * @param tout タイムアウト時間(秒) (ゼロは、無制限)
796 * @see org.opengion.fukurou.util.HttpConnect#setTimeout(int)
797 * @see java.net.URLConnection#setConnectTimeout(int)
799 public void setTimeout( final String tout ) {
800 timeout = nval( getRequestParameter( tout ),timeout );
804 * 【TAG】JSONコードで認証するURLを指定します。
807 * JSONコードで認証するURLを指定します。
809 * @param url JSONコードで認証するURL
811 public void setAuthURL( final String url ) {
812 authURL = nval( getRequestParameter( url ), authURL );
816 * 【TAG】Basic認証を使用して接続する場合のユーザー:パスワードを指定します。
819 * 接続時のユーザーとパスワードを、USER:PASSWD 形式で指定します。
821 * @param userPass ユーザーとパスワード (USER:PASSWD形式)
823 public void setAuthUserPass( final String userPass ) {
824 authUserPass = nval( getRequestParameter( userPass ),authUserPass );
835 public void setCompanyId( final String compId ) {
836 companyId = nval( getRequestParameter( compId ),companyId );
840 * 【TAG】アプリケーションの名前を指定します。
843 * アプリケーションの名前を指定します。
845 * @param appName データテーブル情報
847 public void setAppliName( final String appName ) {
848 appliName = nval( getRequestParameter( appName ),appliName );
852 * 【TAG】接続の結果を表示するかどうかを指定します(初期値:false)。
855 * true で、接続結果を表示します。 false では、何も表示しません(初期値:false)
856 * 接続結果を表示する使い方より、admin 画面に接続して、キャッシュクリアするような
857 * 使い方が多いと考え、初期値は、false になっています。
858 * display="true" と、saveFile を併用することはできません。
860 * @param flag 結果表示 [true:する/false:しない]
861 * @see #setSaveFile( String )
863 public void setDisplay( final String flag ) {
864 display = nval( getRequestParameter( flag ),display );
866 if( display && saveFile != null ) {
867 final String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
868 throw new HybsSystemException( errMsg );
873 * 【TAG】接続の結果をファイルに保存します。
876 * 接続先のデータを受け取って、ファイルに保存します。
877 * display="true" と、saveFile を併用することはできません。
878 * loadFile が指定されていない時のみ処理を行います。
880 * @param file 保存先ファイル
881 * @see #setDisplay( String )
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 ) );
888 final String errMsg = "display=\"true\" と、saveFile を併用することはできません。";
889 throw new HybsSystemException( errMsg );
895 * 【TAG】ファイルからURL接続結果に相当するデータを読み取ります。
898 * 主にデバッグ用として使われます。
900 * @param file 検索するファイル
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 ) );
910 * 【TAG】コマンド (NEW,RENEW)をセットします。
913 * コマンドは、HTMLから(get/post)指定されますので、
914 * CMD_xxx で設定されるフィールド定数値のいづれかを指定できます。
916 * @param cmd コマンド (public static final 宣言されている文字列)
917 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.QueryTag.CMD_NEW">コマンド定数</a>
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 ); }
925 * 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します
926 * (初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
929 * ここでは、検索結果の件数や登録された件数をまず出力し、
930 * その次に、ここで指定したメッセージをリソースから取得して表示します。
931 * 件数を表示させる場合は、displayMsg = "MSG0033"[ 件検索しました] をセットしてください。
932 * 表示させたくない場合は、displayMsg = "" をセットしてください。
933 * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
935 * @param id 表示メッセージID
936 * @see org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG
938 public void setDisplayMsg( final String id ) {
939 final String ids = getRequestParameter( id );
940 if( ids != null ) { displayMsg = ids; }
944 * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
947 * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。
948 * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、
949 * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。
950 * 表示させたくない場合は、notfoundMsg = "" をセットしてください。
951 * 初期値は、MSG0077[対象データはありませんでした]です。
953 * @param id ゼロ件メッセージID
955 public void setNotfoundMsg( final String id ) {
956 final String ids = getRequestParameter( id );
957 if( ids != null ) { notfoundMsg = ids; }
961 * 【TAG】検索結果が0件のとき処理を停止するかどうか[true/false]を指定します(初期値:false[続行する])。
964 * 初期値は、false(続行する)です。
966 * @param flag 0件時停止可否 [true:処理を中止する/false:続行する]
968 public void setStopZero( final String flag ) {
969 stopZero = nval( getRequestParameter( flag ),stopZero );
973 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
974 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
977 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
978 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
979 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
980 * この tableId 属性を利用して、メモリ空間を分けます。
981 *(初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
983 * @param id テーブルID (sessionに登録する時のID)
985 public void setTableId( final String id ) {
986 tableId = nval( getRequestParameter( id ),tableId );
990 * 【TAG】処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true)。
993 * false(中止しない)に設定する場合、後続処理では、{@DB.ERR_CODE}の値により、
994 * IOr の異常/正常終了によって分岐処理は可能となります。
997 * @param flag エラー時処理中止 [true:中止する/false:中止しない]
999 public void setStopError( final String flag ) {
1000 stopError = nval( getRequestParameter( flag ),stopError );
1004 * 【TAG】PLSQL/SQL処理エラーの時にエラーを画面表示するか[true/false]を設定します(初期値:true)。
1007 * false(表示しない)に設定する場合、後続処理では、{@DB.ERR_MSG}の値により、
1008 * 本来表示されるはずだったメッセージを取得可能です。
1009 * stopErrorと併用して、JSON形式でエラーを返す場合等に利用します。
1010 * 初期値は、true(表示する)です。
1011 * ※false指定の場合は件数や、overFlowメッセージ等も表示されなくなります。
1013 * @param flag [true:表示する/false:表示しない]
1015 public void setDispError( final String flag ) {
1016 dispError = nval( getRequestParameter( flag ),dispError );
1020 * 【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します
1021 * (初期値:USE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])。
1024 * SQLインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに
1025 * 渡す文字列にシングルクォート(') を許さない設定にすれば、ある程度は防止できます。
1026 * 数字タイプの引数には、 or 5=5 などのシングルクォートを使用しないコードを埋めても、
1027 * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、
1028 * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。
1029 * (') が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
1030 * 初期値は、SystemData#USE_SQL_INJECTION_CHECK です。
1032 * @param flag クォートチェック [true:する/それ以外:しない]
1034 public void setQuotCheck( final String flag ) {
1035 quotCheck = nval( getRequestParameter( flag ),quotCheck );
1039 * 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します
1040 * (初期値:USE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])。
1043 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
1044 * (><) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
1045 * (初期値:システム定数のUSE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])
1047 * @param flag XSSチェック [true:する/false:しない]
1048 * @see org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
1050 public void setXssCheck( final String flag ) {
1051 xssCheck = nval( getRequestParameter( flag ),xssCheck );
1055 * 【TAG】(通常は使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。
1058 * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
1059 * ファイルダウンロードの対象の表になります。
1061 * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
1062 * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
1063 * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
1066 * @param flag メイントランザクションかどうか [true:メイン/false:その他]
1068 public void setMainTrans( final String flag ) {
1069 isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
1073 * 【TAG】処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true)。
1076 * Query で、検索する場合に、処理時間(queryTime)などの情報を出力していますが、
1077 * ViewForm で、CustomData などの 非HTML表示ビューを使用する場合、データとして、
1078 * 紛れ込んでしまうため、出力を抑制する必要があります。
1079 * true(有効)にすると、これらのHTMLが出力されます。false にすると、出力されません。
1082 * @param useTag 情報出力の有効/無効 [true:有効/false:無効]
1084 public void setUseBeforeHtmlTag( final String useTag ) {
1085 useBeforeHtmlTag = nval( getRequestParameter( useTag ),useBeforeHtmlTag );
1089 * 【TAG】処理時間を表示する TimeView を表示するかどうか[true:する/false:しない]を指定します
1090 * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。
1093 * true に設定すると、処理時間を表示するバーイメージが表示されます。
1094 * これは、DB検索、APサーバー処理、画面表示の各処理時間をバーイメージで
1095 * 表示させる機能です。処理時間の目安になります。
1096 * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。
1098 * @param flag 処理時間を表示 [true:する/false:しない]
1100 public void setUseTimeView( final String flag ) {
1101 useTimeView = nval( getRequestParameter( flag ),useTimeView );
1105 * IOr の応答結果を特定のキーワードで分割します。(内部クラス)
1107 * フォーマット形式のチェック と データの切り出しを行います。
1108 * JSONフォーマットの例:{"status": … "data": {"headers": [ … ], "rows": [ {cols:[ … ]} ]}}
1110 private static final class SplitReqJson {
1111 private final String strJson; // JSON形式の文字列
1112 private int endPos; // 終了位置
1117 * @param strJson JSON形式の文字列
1119 public SplitReqJson( final String str ) {
1120 strJson = str; // JSON形式の文字列
1121 endPos = strJson.indexOf( "\"data\"" ); // 終了位置
1125 * HTTPステータス(先頭から "data"まで) の文字列を返します。
1127 * @return JSON形式の文字列
1129 public String getSttsJson() {
1131 return strJson.substring( 0, endPos );
1133 final String errMsg = "data キーが存在しません。";
1134 throw new HybsSystemException( errMsg );
1139 * 列データ("headers"から "rows"まで) の文字列を返します。
1141 * @return JSON形式の文字列
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 );
1149 final String errMsg = "headers、rows キーのいずれかが存在しません。";
1150 throw new HybsSystemException( errMsg );
1155 * 行データ("cols"から 最後まで) の文字列を返します。
1157 * @return JSON形式の文字列
1159 public String getRowJson() {
1160 final int startPos = strJson.indexOf( "\"cols\"", endPos ); // 開始位置
1161 if( startPos >= 0 ) {
1162 return strJson.substring( startPos );
1164 final String errMsg = "cols キーが存在しません。";
1165 throw new HybsSystemException( errMsg );
1170 * 行データ(最後から "count") の文字列を返します。
1172 * @return JSON形式の文字列
1174 public String getCntJson() {
1175 final int startPos = strJson.lastIndexOf( "\"count\"" ); // 開始位置
1176 if( startPos >= 0 ) {
1177 return strJson.substring( startPos );
1179 final String errMsg = "count キーが存在しません。";
1180 throw new HybsSystemException( errMsg );
1186 * このオブジェクトの文字列表現を返します。
1187 * 基本的にデバッグ目的に使用します。
1189 * @return このクラスの文字列表現
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() ;