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 org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBErrMsg; 021import org.opengion.hayabusa.resource.GUIInfo; 022import org.opengion.hayabusa.resource.ResourceManager; 023import org.opengion.fukurou.db.Transaction; 024import org.opengion.fukurou.db.TransactionReal; 025import org.opengion.fukurou.util.ErrorMessage; 026import org.opengion.fukurou.util.FileUtil; 027import org.opengion.fukurou.util.StringUtil; 028import org.opengion.fukurou.util.Closer ; 029import static org.opengion.fukurou.util.StringUtil.nval ; 030 031import java.util.Locale ; 032 033import java.sql.Connection; 034import java.sql.Statement; 035import java.sql.CallableStatement; 036import java.sql.ResultSet; 037import java.sql.ResultSetMetaData; 038import java.sql.SQLException; 039import java.sql.Types; 040import java.sql.Array; // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ) 対応。oracle.sql.ARRAY の置き換え 041import oracle.jdbc.OracleConnection; // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ) 対応 042 043import oracle.jdbc.OracleTypes; // CURSOR が残る 044import oracle.jdbc.OracleCallableStatement; // CURSOR が残る 045 046import java.io.File; 047import java.io.PrintWriter; 048import java.io.FileOutputStream; 049import java.io.IOException; 050import java.io.ObjectOutputStream; 051import java.io.ObjectInputStream; 052import java.util.zip.ZipOutputStream; 053import java.util.zip.ZipEntry; 054 055import java.util.Map; 056 057/** 058 * SELECT文を直接実行して、指定のファイルに出力するタグです。 059 * 060 * 中間の、データ(DBTableModel)を作成しないため、余計なメモリを取らず、 061 * 高速にデータを抜き出すことが可能です。 062 * 一方、抜き出すデータは生データのため、データの再利用等、システム的な 063 * 使用を想定しています。 064 * JDBCErrMsg 形式のPL/SQL をコールして、その検索結果(カーソル)を抜きこともできます。 065 * 066 * ※ このタグは、Transaction タグの対象です。 067 * 068 * @og.formSample 069 * ●形式:<og:directWriteTable filename="[・・・]" ・・・ >SELECT * FROM ZYXX </og:directWriteTable > 070 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 071 * 072 * ●Tag定義: 073 * <og:directWriteTable 074 * fileURL 【TAG】保存先ディレクトリ名を指定します (初期値:FILE_URL[=filetemp/]) 075 * filename 【TAG】ファイルを作成するときのファイル名をセットします(初期値:システムパラメータのFILE_FILENAME) 076 * zipFilename 【TAG】ZIPファイルを作成するときのZIPファイル名をセットします(初期値:filename + ".zip") 077 * encode 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします (初期値:FILE_ENCODE[=UnicodeLittle]) 078 * fileAppend 【TAG】追加モードで書き込むかどうか[true/false]を指定します(初期値:false[通常モード]) 079 * zip 【TAG】結果をファイルに出力するときに、ZIPで圧縮するかどうか[true/false]を指定します(初期値:false) 080 * separator 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします (初期値:TAB_SEPARATOR[= ]) 081 * useHeader 【TAG】ヘッダーを書き込むかどうか[true/false]を指定します(初期値:true) 082 * displayMsg 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0033[ 件検索しました]) 083 * notfoundMsg 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした]) 084 * fetchSize 【TAG】(通常は使いません)データのフェッチサイズを指定します(初期値:100) 085 * names 【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します 086 * queryType 【TAG】Query を発行する為のクラスID(JDBC,JDBCErrMsg)を指定します({@og.doc03Link queryType 初期値:JDBC}) 087 * dbid 【TAG】(通常は使いません)検索時のDB接続IDを指定します(初期値:DEFAULT) 088 * useNumber 【TAG】行番号を出力するかどうか(初期値:true) 089 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 090 * > ... Body ... 091 * </og:directWriteTable> 092 * 093 * ●使用例 094 * <og:directWriteTable 095 * dbid = "ORCL" 接続データベースID(初期値:DEFAULT) 096 * separator = "," ファイルの区切り文字(初期値:タブ) 097 * fileURL = "{@USER.ID}" 保存先ディレクトリ名 098 * filename = "{@filename}" 保存ファイル名 099 * encode = "UnicodeLittle" 保存ファイルエンコード名 100 * useHeader = "true" 保存ファイルにヘッダーを出力するかどうか 101 * zip = "true" ZIPファイルに圧縮するかどうか 102 * zipFilename = "Sample.zip" ZIPファイルのファイル名 103 * fileAppend = "true" ファイルを追加モードで登録するかどうか 104 * displayMsg = "MSG0033" 実行後の表示メッセージ 105 * fetchSize = "200" DB検索する場合のフェッチするサイズ 106 * > 107 * SELECT * FROM ZYXX 108 * </og:directWriteTable > 109 * 110 * <og:directWriteTable 111 * fileURL = "{@USER.ID}" 保存先ディレクトリ名 112 * filename = "{@filename}" 保存ファイル名 113 * names = "AAA,BBB,CCC,・・・" 指定のキーに対応するリクエスト値を ARG_ARRAY にセットします。 114 * queryType = "JDBCErrMsg" JDBCErrMsg 形式のPL/SQL をコールします。 115 * > 116 * { call PL/SQL(?,?,?,? ) } 117 * </og:directWriteTable > 118 * 119 * @og.rev 3.5.6.0 (2004/06/18) 新規作成 120 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)の実行を追加 121 * @og.group ファイル出力 122 * 123 * @version 4.0 124 * @author Kazuhiko Hasegawa 125 * @since JDK5.0, 126 */ 127public class DirectWriteTableTag extends CommonTagSupport { 128 //* このプログラムのVERSION文字列を設定します。 {@value} */ 129 private static final String VERSION = "6.0.0.0 (2014/04/11)" ; 130 131 private static final long serialVersionUID = 600020140411L ; 132 133 private static final String TAB_SEPARATOR = "\t" ; 134 private static final String errMsgId = HybsSystem.ERR_MSG_KEY; 135 136 private final int DB_MAX_QUERY_TIMEOUT = HybsSystem.sysInt( "DB_MAX_QUERY_TIMEOUT" ) ; 137 private static final String ARG_ARRAY = "ARG_ARRAY" ; 138 private static final String ERR_MSG = "ERR_MSG" ; 139 private static final String ERR_MSG_ARRAY = "ERR_MSG_ARRAY" ; 140 141 // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 142 private String dbid = null; 143 private String separator = TAB_SEPARATOR; // 項目区切り文字 144 private boolean useHeader = true; // ヘッダーの使用可否 145 private String fileURL = HybsSystem.sys( "FILE_URL" ); 146 private String filename = HybsSystem.sys( "FILE_FILENAME" ); // ファイル名 147 private String zipFilename = null; // ZIPファイル名 148 private String sql = null; 149 private String encode = HybsSystem.sys( "FILE_ENCODE" ); // ファイルエンコーディング "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS" 150 private boolean fileAppend = false; // ファイルをAPPENDモードで出力するか 151 private boolean zip = false; // ファイルをZIPするか 152 private String displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); 153 private String notfoundMsg = "MSG0077"; // 対象データはありませんでした。 154 private long dyStart = 0; // 実行時間測定用のDIV要素を出力します。 155 private int fetchSize = 100 ; // フェッチする行数(初期値:100) 156 private boolean useNumber = true; // 5.5.7.1(2012/10/05) 行番号出力 157 158 // 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 159 private boolean queryType = true; // ノーマルは、true/ JDBCErrMsg の時は、false 160 private String names = null; // 指定のリクエスト変数を、ARG_ARRAY にセットします。 161 private int errCode = ErrorMessage.OK; 162 private transient ErrorMessage errMessage = null; 163 164 /** 165 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 166 * 167 * @return 後続処理の指示( EVAL_BODY_BUFFERED ) 168 */ 169 @Override 170 public int doStartTag() { 171 dyStart = System.currentTimeMillis(); // 時間測定用 172 return EVAL_BODY_BUFFERED ; // Body を評価する。( extends BodyTagSupport 時) 173 } 174 175 /** 176 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 177 * 178 * @og.rev 3.8.6.3 (2006/11/30) SQL 文の前後のスペースを取り除きます。 179 * 180 * @return 後続処理の指示(SKIP_BODY) 181 */ 182 @Override 183 public int doAfterBody() { 184 sql = getBodyString(); 185 if( sql == null || sql.length() == 0 ) { 186 String errMsg = "BODY 部の検索用 Select文は、必須です。"; 187 throw new HybsSystemException( errMsg ); 188 } 189 sql = sql.trim(); 190 return SKIP_BODY ; // Body を評価しない 191 } 192 193 /** 194 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 195 * 196 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 197 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel ) 198 * 199 * @return 後続処理の指示 200 */ 201 @Override 202 public int doEndTag() { 203 debugPrint(); // 4.0.0 (2005/02/28) 204 205 PrintWriter pw = null; 206 final int executeCount; 207 try { 208 if( zip ) { 209 String directory = HybsSystem.url2dir( fileURL ); 210 211 if( zipFilename == null ) { zipFilename = filename + ".zip"; } 212 ZipOutputStream gzip = null; 213 try { 214 gzip = new ZipOutputStream( 215 new FileOutputStream( 216 StringUtil.urlAppend( directory,zipFilename ))); 217 gzip.putNextEntry( new ZipEntry( filename ) ); 218 pw = new PrintWriter( gzip ); 219 executeCount = create( pw ) ; 220 221 pw.flush(); 222 gzip.closeEntry(); 223 gzip.finish() ; 224 } 225 finally { 226 Closer.ioClose( gzip ); // 4.0.0 (2006/01/31) close 処理時の IOException を無視 227 } 228 } 229 else { 230 pw = getPrintWriter(); 231 executeCount = create( pw ); 232 } 233 } catch( IOException ex ) { 234 String errMsg = "Error in DirectWriteTableTag: " + toString(); 235 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 236 } finally { 237 Closer.ioClose( pw ); // 4.0.0 (2006/01/31) close 処理時の IOException を無視 238 } 239 240 // 3.6.1.0 (2005/01/05) 検索結果の件数を、"DB.COUNT" キーでリクエストにセットする。 241 setRequestAttribute( "DB.COUNT" , String.valueOf( executeCount ) ); 242 setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) ); 243 244 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL ); 245 246 // 実行件数の表示 247 if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) { 248 buf.append( executeCount ); 249 buf.append( getResource().getLabel( displayMsg ) ); 250 buf.append( HybsSystem.BR ); 251 } 252 else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) { 253 buf.append( getResource().getLabel( notfoundMsg ) ); 254 buf.append( HybsSystem.BR ); 255 } 256 257 // 3.6.1.0 (2005/01/05) TaglibUtil.makeHTMLErrorTable メソッドを利用 258 String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() ); 259 if( err != null && err.length() > 0 ) { 260 buf.append( err ); 261 setSessionAttribute( errMsgId,errMessage ); 262 } 263 else { 264 removeSessionAttribute( errMsgId ); 265 } 266 267 jspPrint( buf.toString() ); 268 269 // 時間測定用の DIV 要素を出力 270 long dyTime = System.currentTimeMillis()-dyStart; 271 jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" ); // 3.5.6.3 (2004/07/12) 272 273 // 3.6.1.0 (2005/01/05) 警告時に停止していましたが、継続処理させます。 274 int rtnCode = EVAL_PAGE; 275 if( errCode >= ErrorMessage.NG ) { // 異常 276 rtnCode = SKIP_PAGE; 277 } 278 279 // 4.0.0 (2005/01/31) セキュリティチェック(データアクセス件数登録) 280 GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY ); 281 if( guiInfo != null ) { guiInfo.addReadCount( executeCount,dyTime,sql ); } 282 283 return rtnCode ; 284 } 285 286 /** 287 * タグリブオブジェクトをリリースします。 288 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 289 * 290 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 291 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 292 * @og.rev 5.5.7.1 (2012/10/05) useNumber追加 293 */ 294 @Override 295 protected void release2() { 296 super.release2(); 297 separator = TAB_SEPARATOR; // 項目区切り文字 298 fileURL = HybsSystem.sys( "FILE_URL" ); 299 filename = HybsSystem.sys( "FILE_FILENAME" ); // ファイル名 300 zipFilename = null; // ZIPファイル名 301 sql = null; 302 encode = HybsSystem.sys( "FILE_ENCODE" ); // ファイルエンコーディング "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS" 303 fileAppend = false; // ファイルをAPPENDモードで出力するか 304 zip = false; // ファイルをZIPするか 305 displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); 306 notfoundMsg = "MSG0077"; // 対象データはありませんでした。 307 dbid = null; 308 fetchSize = 100 ; // フェッチする行数(初期値:0 参考にしない) 309 dyStart = 0; 310 queryType = true; // ノーマルは、true/ JDBCErrMsg の時は、false 311 names = null; // 指定のリクエスト変数を、ARG_ARRAY にセットします。 312 errCode = ErrorMessage.OK; 313 errMessage = null; 314 useNumber = true; // 5.5.7.1 (2012/10/05) 315 } 316 317 /** 318 * 実オブジェクトを生成して,OutputStream に書き込みます。 319 * 320 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 321 * @og.rev 3.8.6.0 (2006/09/29) ヘッダーにラベルを出力するように修正 322 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 323 * @og.rev 4.3.4.3 (2008/12/22) (Oracle11gDriver対応)PL/SQLコールの場合に、"クローズされた文です。"のエラーが発生する問題に対応 324 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応 325 * @og.rev 5.2.2.0 (2010/11/01) 改行を含む場合は、ダブルクオートを強制的に前後に追加する。 326 * @og.rev 5.2.2.0 (2010/11/01) ダブルクオートを含む場合は、その直前にダブルクオートを強制的に追加する。 327 * @og.rev 5.3.0.0 (2010/12/01) executeCall メソッドの引数見直し 328 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 329 * @og.rev 5.5.7.1 (2012/10/05) useNumberの追加 330 * 331 * @param out PrintWriterオブジェクト 332 * 333 * @return 検索件数 334 */ 335 private int create( final PrintWriter out ) { 336 final int executeCount; 337 Statement stmt = null; 338 CallableStatement callStmt = null; // 4.3.4.3 (2008/12/22) 339 ResultSet resultSet = null ; 340 boolean errFlag = true; 341 Transaction tran = null; // 5.1.9.0 (2010/08/01) Transaction 対応 342 try { 343 // 5.1.9.0 (2010/08/01) Transaction 対応 344 TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class ); 345 if( tranTag == null ) { 346 tran = new TransactionReal( getApplicationInfo() ); // 5.3.7.0 (2011/07/01) 引数変更 347 } 348 else { 349 tran = tranTag.getTransaction(); 350 } 351 352 Connection conn = tran.getConnection( dbid ); // 5.1.9.0 (2010/08/01) Transaction 対応 353 // 3.6.1.0 (2005/01/05) 354 if( queryType ) { // JDBC 通常の SELECT 文 355 stmt = conn.createStatement(); 356 if( fetchSize > 0 ) { stmt.setFetchSize( fetchSize ); } 357 resultSet = stmt.executeQuery( sql ); 358 } 359 else { // PL/SQL Call 文 360 String[] values = null; 361 if( names != null ) { 362 String[] nameArray = StringUtil.csv2Array( names ); 363 values = getRequest( nameArray ); 364 } 365 callStmt = conn.prepareCall( sql ); 366 resultSet = executeCall( conn,callStmt,values ); // 5.3.0.0 (2010/12/01) 367 } 368 if( resultSet == null ) { return 0; } 369 370 ResultSetMetaData metaData = resultSet.getMetaData(); 371 int numberOfColumns = metaData.getColumnCount(); 372 373 // ヘッダー部の出力 374 if( useHeader && numberOfColumns > 0 ) { 375 StringBuilder headName = new StringBuilder(); 376 StringBuilder headLabel = new StringBuilder(); 377 headName.append( "#Name" ); 378 headLabel.append( "#Label" ); 379 String clm ; 380 ResourceManager resource = getResource(); 381 for(int column = 1; column <= numberOfColumns; column++) { 382 clm = metaData.getColumnLabel(column).toUpperCase(Locale.JAPAN); 383 headName.append( TAB_SEPARATOR ).append( clm ); 384 headLabel.append( TAB_SEPARATOR ).append( resource.getLabel( clm ) ); 385 } 386 out.println( headName.toString() ); 387 out.println( headLabel.toString() ); 388 } 389 390 int rowNo = 0; 391 Object obj ; 392 while( resultSet.next() ) { 393 if( useNumber ){ // 5.5.7.1 (2012/10/05) 394 out.print( rowNo ); // 行番号 395 } 396 for(int column = 1; column <= numberOfColumns; column++) { 397 if( column == 1 && !useNumber && !useHeader ){ // 5.5.7.1 (2012/10/05) 398 //この場合だけセパレータ出力しない 399 } 400 else{ 401 out.print( separator ); 402 } 403 obj = resultSet.getObject(column); 404 if( obj != null ) { 405 // 5.2.2.0 (2010/11/01) 改行、ダブルクオート等の処理 406 String sval = obj.toString(); 407 if( sval.indexOf( '"' ) >= 0 ) { sval = sval.replaceAll( "\"" ,"\"\"" ) ; } 408 if( sval.indexOf( HybsSystem.CR ) >= 0 ) { 409 sval = "\"" + sval + "\"" ; 410 } 411 out.print( sval ); 412 } 413 } 414 out.println(); 415 rowNo++ ; 416 } 417 executeCount = rowNo ; 418 errFlag = false; // エラーではない 419 } 420 catch ( SQLException ex ) { // 3.6.1.0 (2005/01/05) 421 String errMsg = "データベース処理を実行できませんでした。" 422 + HybsSystem.CR + stmt + HybsSystem.CR 423 + "err=[" + ex.getSQLState() + "]" 424 + ex.getMessage(); 425 throw new HybsSystemException( errMsg,ex ); 426 } 427 finally { 428 Closer.resultClose( resultSet ); 429 Closer.stmtClose( stmt ); 430 Closer.stmtClose( callStmt ); // 4.3.4.3 (2008/12/22) 431 if( tran != null ) { // 5.5.2.6 (2012/05/25) findbugs対応 432 tran.close( errFlag ); // 5.1.9.0 (2010/08/01) Transaction 対応 433 } 434 } 435 436 return executeCount ; 437 } 438 439 /** 440 * 引数配列付のクエリーを実行します。 441 * 処理自体は, #execute() と同様に、各サブクラスの実装に依存します。 442 * これは、CallableStatement を用いて、データベース検索処理を行います。 443 * {call TYPE3B01.TYPE3B01(?,?,?,?)} で、4番目の引数には、 444 * names で指定したリクエスト情報が、ARG_ARRAY 配列に順次セットされます。 445 * 使用する場合は、一旦わかり易い変数に受けて利用してください。 446 * 呼び出す PL/SQL では、検索系PL/SQL です。 447 * 448 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 449 * @og.rev 4.3.4.3 (2008/12/22) (Oracle11gDriver対応)PL/SQLコールの場合に、"クローズされた文です。"のエラーが発生する問題に対応 450 * @og.rev 5.3.0.0 (2010/12/01) executeCall メソッドの引数見直し 451 * @og.rev 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 452 * 453 * @param conn コネクション 454 * @param callStmt コーラブルステートメント 455 * @param args オブジェクトの引数配列 456 * 457 * @return 結果オブジェクト 458 */ 459 private ResultSet executeCall( final Connection conn,final CallableStatement callStmt,final String[] args ) throws SQLException { 460 ResultSet resultSet = null; 461// try { 462// callStmt = conn.prepareCall( sql ); 463 callStmt.setQueryTimeout( DB_MAX_QUERY_TIMEOUT ); 464 if( fetchSize > 0 ) { callStmt.setFetchSize( fetchSize ); } 465 Map<String,Class<?>> map = conn.getTypeMap(); 466 try { 467 map.put( ERR_MSG,Class.forName( "org.opengion.hayabusa.db.DBErrMsg" ) ); 468 } 469 catch( ClassNotFoundException ex ) { 470 String errMsg = "org.opengion.hayabusa.db.DBErrMsg クラスが見つかりません。" + HybsSystem.CR 471 + ex.getMessage(); // // 5.1.8.0 (2010/07/01) errMsg 修正 472 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 473 } 474 475 // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 http://docs.oracle.com/cd/E28389_01/web.1111/b60995/thirdparty.htm 476// ArrayDescriptor sd = ArrayDescriptor.createDescriptor( ARG_ARRAY, conn ); 477// ARRAY newArray = new ARRAY( sd,conn,StringUtil.rTrims( args ) ); 478 Array newArray = ((OracleConnection)conn).createOracleArray( ARG_ARRAY, StringUtil.rTrims( args )); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 479 480 callStmt.registerOutParameter(1, Types.INTEGER); 481// callStmt.registerOutParameter(2, OracleTypes.ARRAY,ERR_MSG_ARRAY); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 482 callStmt.registerOutParameter(2, Types.ARRAY,ERR_MSG_ARRAY); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 483 callStmt.registerOutParameter(3, OracleTypes.CURSOR); 484// ((OracleCallableStatement)callStmt).setARRAY( 4,newArray ); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 485 callStmt.setArray( 4,newArray ); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 486 487 callStmt.execute(); 488 489 errCode = callStmt.getInt(1); 490 491 if( errCode < ErrorMessage.NG ) { // 異常以外の場合 492 resultSet = ((OracleCallableStatement)callStmt).getCursor(3); 493 } 494 if( errCode > ErrorMessage.OK ) { // 正常以外の場合 495// ARRAY rtn3 = ((OracleCallableStatement)callStmt).getARRAY(2); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 496 Array rtn3 = callStmt.getArray(2); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 497 Object[] rtnval3 = (Object[])rtn3.getArray(); 498 errMessage = new ErrorMessage( "Query_JDBCErrMsg Error!!" ); 499 for( int i=0; i<rtnval3.length; i++ ) { 500 DBErrMsg er = (DBErrMsg)rtnval3[i]; 501 if( er == null ) { break; } 502 errMessage.addMessage( er.getErrMsg() ); 503 } 504 } 505// } 506// finally { 507// Closer.stmtClose( callStmt ); 508// callStmt = null; 509// } 510 return resultSet; 511 } 512 513 /** 514 * PrintWriter を取得します。 515 * 516 * ここでは、一般的なファイル出力を考慮した PrintWriter を作成します。 517 * 518 * @og.rev 3.7.1.1 (2005/05/23) フォルダがない場合は、複数階層分のフォルダを自動で作成します。 519 * @og.rev 3.8.0.0 (2005/06/07) FileUtil#getPrintWriter を利用。 520 * @og.rev 5.6.1.0 (2013/02/01) 3.7.1.1のコメントに入っているが対応されていないのでフォルダ作成追加 521 * 522 * @return 出力用PrintWriterオブジェクト 523 */ 524 private PrintWriter getPrintWriter() { 525 if( filename == null ) { 526 String errMsg = "ファイル名がセットされていません。"; 527 throw new HybsSystemException( errMsg ); 528 } 529 String directory = HybsSystem.url2dir( fileURL ); 530 531 // 5.6.1.0 (2013/02/01) 532 File dir = new File(directory); 533 if( ! dir.exists() && ! dir.mkdirs() ) { 534 String errMsg = "ディレクトリの作成に失敗しました。[" + directory + "]"; 535 throw new HybsSystemException( errMsg ); 536 } 537 538 // ※ 注意 StringUtil.urlAppend を組み込んでいる意図が不明。一旦削除していますが、注意 539 // 3.8.0.0 (2005/06/07) FileUtil#getPrintWriter を利用。 540 // out = FileUtil.getPrintWriter( StringUtil.urlAppend( directory,filename ),fileAppend,encode); 541 542 // 処理を簡素化します。 543 return FileUtil.getPrintWriter( new File( directory,filename ),encode,fileAppend ); 544 } 545 546 /** 547 * 名称配列を元に、リクエスト情報のデータを取得します。 548 * 549 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 550 * 551 * @param nameArray キーとなる名称の配列 552 * 553 * @return そのリクエスト情報 554 */ 555 private String[] getRequest( final String[] nameArray ) { 556 String[] rtn = new String[nameArray.length]; 557 558 for( int i=0; i<rtn.length; i++ ) { 559 rtn[i] = getRequestValue( nameArray[i] ); 560 } 561 562 return rtn; 563 } 564 565 /** 566 * 【TAG】(通常は使いません)検索時のDB接続IDを指定します(初期値:DEFAULT)。 567 * 568 * @og.tag 569 * 検索時のDB接続IDを指定します。初期値は、DEFAULT です。 570 * 571 * @param id データベース接続ID 572 */ 573 public void setDbid( final String id ) { 574 dbid = nval( getRequestParameter( id ),dbid ); 575 } 576 577 /** 578 * 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします 579 * (初期値:TAB_SEPARATOR[={@og.value #TAB_SEPARATOR}])。 580 * 581 * @og.tag 可変長ファイルを作成するときの項目区切り文字をセットします。 582 * (初期値:ローカル定義のTAB_SEPARATOR[={@og.value #TAB_SEPARATOR}])。 583 * 584 * @param sep 項目区切り文字 585 * @see #TAB_SEPARATOR 586 */ 587 public void setSeparator( final String sep ) { 588 separator = nval( getRequestParameter( sep ),TAB_SEPARATOR ); 589 } 590 591 /** 592 * 【TAG】保存先ディレクトリ名を指定します 593 * (初期値:FILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。 594 * 595 * @og.tag 596 * この属性で指定されるディレクトリに、ファイルをセーブします。 597 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、 598 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、 599 * fileURL = "{@USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、 600 * さらに、各個人ID別のフォルダを作成して、そこにセーブします。 601 * (初期値:システム定数のFILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。 602 * 603 * @og.rev 3.5.4.3 (2004/01/05) 内部処理を、makeFileURL に移動。 604 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用 605 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。 606 * 607 * @param url 保存先ディレクトリ名 608 * @see org.opengion.hayabusa.common.SystemData#FILE_URL 609 */ 610 public void setFileURL( final String url ) { 611 String furl = nval( getRequestParameter( url ),null ); 612 if( furl != null ) { 613 char ch = furl.charAt( furl.length()-1 ); 614 if( ch != '/' && ch != '\\' ) { furl = furl + "/"; } 615 fileURL = StringUtil.urlAppend( fileURL,furl ); 616 } 617 } 618 619 /** 620 * 【TAG】ファイルを作成するときのファイル名をセットします(初期値:システムパラメータのFILE_FILENAME)。 621 * 622 * @og.tag ファイルを作成するときのファイル名をセットします。 623 * 624 * @param fname ファイル名 625 */ 626 public void setFilename( final String fname ) { 627 filename = nval( getRequestParameter( fname ),filename ); 628 } 629 630 /** 631 * 【TAG】ZIPファイルを作成するときのZIPファイル名をセットします(初期値:filename + ".zip")。 632 * 633 * @og.tag 634 * zip 属性に、true を指定した場合に、ZIPファイル化します。その場合のファイル名を指定します。 635 * なにも指定しない場合は、filename + ".zip" になります。 636 * 637 * @param zipFile ZIPファイル名 638 * @see #setZip( String ) 639 */ 640 public void setZipFilename( final String zipFile ) { 641 zipFilename = nval( getRequestParameter( zipFile ),zipFilename ); 642 } 643 644 /** 645 * 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします 646 * (初期値:FILE_ENCODE[={@og.value org.opengion.hayabusa.common.SystemData#FILE_ENCODE}])。 647 * 648 * @og.tag 649 * "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS" 650 * (初期値:システム定数のFILE_ENCODE[={@og.value org.opengion.hayabusa.common.SystemData#FILE_ENCODE}])。 651 * 652 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更 653 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。 654 * 655 * @param enc ファイルエンコーディング名 656 * @see <a href="http://www.iana.org/assignments/character-sets">IANA Charset Registry</a> 657 * @see org.opengion.hayabusa.common.SystemData#FILE_ENCODE 658 */ 659 public void setEncode( final String enc ) { 660 encode = nval( getRequestParameter( enc ),encode ); 661 } 662 663 /** 664 * 【TAG】ヘッダーを書き込むかどうか[true/false]を指定します(初期値:true)。 665 * 666 * @og.tag 667 * #Name ・・・・ ヘッダーの書き込みを指定します。 668 * 通常は、書き込み(true)にしておき、使用側でコメントと解釈するように 669 * 処理を行うべきです。コメントのため、append モードで途中に現れても 670 * 無視できます。また、エンジン標準でデータを取り込む場合に、データの配置が 671 * 変更されても取り込みプログラムはそのまま使用できます。 672 * 初期値は、true(書き込む)です。 673 * 674 * @param flag ヘッダーを書き込むかどうか [true:書き込む/false:書き込まない] 675 */ 676 public void setUseHeader( final String flag ) { 677 useHeader = nval( getRequestParameter( flag ),useHeader ); 678 } 679 680 /** 681 * 【TAG】追加モードで書き込むかどうか[true/false]を指定します(初期値:false[通常モード])。 682 * 683 * @og.tag 684 * ファイルを書き込む場合、追加モードで書き込むかどうかをセットします。 685 * 新規モード(true)の場合、既存のファイルが存在し、かつ書き込み許可があれば、 686 * 上書きで新規に作成します。 687 * 初期値は、false(新規モード)です。 688 * 689 * @param flag [true:追加モード/false:新規モード] 690 */ 691 public void setFileAppend( final String flag ) { 692 fileAppend = nval( getRequestParameter( flag ),fileAppend ); 693 } 694 695 /** 696 * 【TAG】結果をファイルに出力するときに、ZIPで圧縮するかどうか[true/false]を指定します(初期値:false)。 697 * 698 * @og.tag 699 * 大量に抜き出す場合、そのまま、サーバーから取り出すだけでも大変です。 700 * zip 属性を、true にすると、GZIP で圧縮したファイルを作成します。 701 * 初期値は、false(圧縮しない)です。 702 * 703 * @param flag ZIPで圧縮 [true:する/それ以外:しない] 704 * @see #setZipFilename( String ) 705 */ 706 public void setZip( final String flag ) { 707 zip = nval( getRequestParameter( flag ),zip ); 708 } 709 710 /** 711 * 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0033[ 件検索しました])。 712 * 713 * @og.tag 714 * ここでは、検索結果の件数や登録された件数をまず出力し、 715 * その次に、ここで指定したメッセージをリソースから取得して 716 * 表示します。 717 * 表示させたくない場合は, displayMsg = "" をセットしてください。 718 * 初期値は、検索件数を表示します。 719 * 720 * @param id ディスプレイに表示させるメッセージ ID 721 */ 722 public void setDisplayMsg( final String id ) { 723 String ids = getRequestParameter( id ); 724 if( ids != null ) { displayMsg = ids; } 725 } 726 727 /** 728 * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。 729 * 730 * @og.tag 731 * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。 732 * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、 733 * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。 734 * 表示させたくない場合は, notfoundMsg = "" をセットしてください。 735 * 初期値は、MSG0077[対象データはありませんでした]です。 736 * 737 * @param id ディスプレイに表示させるメッセージ ID 738 */ 739 public void setNotfoundMsg( final String id ) { 740 String ids = getRequestParameter( id ); 741 if( ids != null ) { notfoundMsg = ids; } 742 } 743 744 /** 745 * 【TAG】(通常は使いません)データのフェッチサイズを指定します(初期値:100)。 746 * 747 * @og.tag 748 * より多くの行が必要なときに、データベースから取り出す必要がある行数に 749 * ついてのヒントを JDBC ドライバに提供します。 750 * 指定された行数は、この Statement を使って作成された結果セットにだけ影響します。 751 * 指定された値が 0 の場合、ヒントは無視されます。 752 * 初期値は、100 です。 753 * 754 * @param size フェッチする行数(初期値:100) 755 */ 756 public void setFetchSize( final String size ) { 757 fetchSize = nval( getRequestParameter( size ),fetchSize ); 758 } 759 760 /** 761 * 【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します。 762 * 763 * @og.tag 764 * 複数ある場合は、カンマ区切り文字で渡します。 765 * PL/SQL を使用しない場合は、無視されます。 766 * 767 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 768 * 769 * @param nm 引数の名称(複数ある場合は、カンマ区切り文字) 770 */ 771 public void setNames( final String nm ) { 772 names = nval( getRequestParameter( nm ),names ); 773 } 774 775 /** 776 * 【TAG】Query を発行する為のクラスID(JDBC,JDBCErrMsg)を指定します({@og.doc03Link queryType 初期値:JDBC})。 777 * 778 * @og.tag 779 * ストアドプロシージャ等を実行する場合に、queryType="JDBCErrMsg" を 780 * 指定する必要があります。(それ以外の指定は、初期値の JDBC になります。) 781 * 初期値は、"JDBC" です。 782 * {@og.doc03Link queryType Query_**** クラス} 783 * 784 * @og.rev 3.6.1.0 (2005/01/05) PL/SQLコール(JDBCErrMsg 形式)への対応 785 * 786 * @param id Query を発行する為の実クラス ID 787 */ 788 public void setQueryType( final String id ) { 789 // 内部的には、JDBCErrMsg:false / それ以外:true で管理しています。 790 queryType = ! "JDBCErrMsg".equalsIgnoreCase( getRequestParameter( id ) ); 791 } 792 793 /** 794 * 【TAG】ファイルに行番号を出力するかどうか(初期値:true) 795 * 796 * @og.tag 797 * ファイルに行番号を出力するかどうかを指定します。 798 * 初期値は、true(出力する)です。 799 * 800 * @og.rev 5.5.7.1 (2012/10/05) 新規追加 801 * @param flag 行番号出力 [true:する/それ以外:しない] 802 */ 803 public void setUseNumber( final String flag ) { 804 useNumber = nval( getRequestParameter( flag ),useNumber ); 805 } 806 807 /** 808 * シリアライズ用のカスタムシリアライズ書き込みメソッド 809 * 810 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 811 * @serialData 一部のオブジェクトは、シリアライズされません。 812 * 813 * @param strm ObjectOutputStreamオブジェクト 814 * @throws IOException シリアライズに関する入出力エラーが発生した場合 815 */ 816 private void writeObject( final ObjectOutputStream strm ) throws IOException { 817 strm.defaultWriteObject(); 818 } 819 820 /** 821 * シリアライズ用のカスタムシリアライズ読み込みメソッド 822 * 823 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 824 * 825 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 826 * @serialData 一部のオブジェクトは、シリアライズされません。 827 * 828 * @param strm ObjectInputStreamオブジェクト 829 * @see #release2() 830 * @throws IOException シリアライズに関する入出力エラーが発生した場合 831 * @throws ClassNotFoundException クラスを見つけることができなかった場合 832 */ 833 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 834 strm.defaultReadObject(); 835 } 836 837 /** 838 * このオブジェクトの文字列表現を返します。 839 * 基本的にデバッグ目的に使用します。 840 * 841 * @return このクラスの文字列表現 842 */ 843 @Override 844 public String toString() { 845 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 846 .println( "VERSION" ,VERSION ) 847 .println( "dbid" ,dbid ) 848 .println( "separator" ,separator ) 849 .println( "useHeader" ,useHeader ) 850 .println( "fileURL" ,fileURL ) 851 .println( "filename" ,filename ) 852 .println( "zipFilename" ,zipFilename) 853 .println( "sql" ,sql ) 854 .println( "encode" ,encode ) 855 .println( "fileAppend" ,fileAppend ) 856 .println( "zip" ,zip ) 857 .println( "displayMsg" ,displayMsg ) 858 .println( "dyStart" ,dyStart ) 859 .println( "fetchSize" ,fetchSize ) 860 .println( "queryType" ,queryType ) 861 .println( "names" ,names ) 862 .println( "errCode" ,errCode ) 863 .println( "Other..." ,getAttributes().getAttribute() ) 864 .fixForm().toString() ; 865 } 866}