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 */
016 package org.opengion.hayabusa.taglib;
017
018 import org.opengion.hayabusa.common.HybsSystem;
019 import org.opengion.hayabusa.common.HybsSystemException;
020 import org.opengion.hayabusa.resource.GUIInfo;
021 import org.opengion.fukurou.db.Transaction;
022 import org.opengion.fukurou.db.TransactionReal;
023 import org.opengion.fukurou.util.FileUtil;
024 import org.opengion.fukurou.util.Closer ;
025 import org.opengion.fukurou.util.StringUtil;
026 import org.opengion.fukurou.xml.HybsXMLSave ;
027
028 import static org.opengion.fukurou.util.StringUtil.nval ;
029
030 import java.sql.Connection;
031
032 import java.io.File;
033 import java.io.BufferedReader;
034 import java.util.Map;
035 import java.util.HashMap;
036
037 /**
038 * æŒ?®šã?拡張XDK形式ファイルを直接ãƒ??タベã?スに登録するãƒ??タ入力タグですã?
039 *
040 * こã?クラスは、オラクル XDKの oracle.xml.sql.dml.OracleXMLSave クラスと
041 * ほぼ同様ã?目çš?�§使用できる org.opengion.fukurou.xml.HybsXMLSave のラãƒ?ƒ‘ークラスですã?
042 * 拡張XDK形式ã?XMLファイルを読み込み、データベã?スに INSERT しますã?
043 * 拡張XDK形式ã?å…?�¨なã‚?オラクル XDK(Oracle XML Developer's Kit)につã�?�¦は、以下ã?
044 * リンクを参照願いますã?
045 * <a href="http://otn.oracle.co.jp/software/tech/xml/xdk/index.html" target="_blank" >
046 * XDK(Oracle XML Developer's Kit)</a>
047 *
048 * こã?タグでは、keys,vals を登録することにより、MLファイルに存在しなã�?‚«ラãƒ?‚’
049 * 追åŠ?�—たり、XMLファイルのæƒ??を書き換えることが可能になりますã?
050 * 例えば、登録日ã‚??登録è€??またã?、テンプレートより各シスãƒ?ƒ ID毎に
051 * 登録するなどですã?
052 *
053 * 拡張XDK形式とは、ROW 以外に、SQL処ç�?”¨タグ(EXEC_SQL)を持つ XML ファイルですã?
054 * またã?登録するãƒ??ブル(table)ã‚?ROWSETタグの属æ?æƒ??として付与することができますã?
055 * (大æ–?—小文字に注æ„?
056 * これは、オラクルXDKで処ç�?�™るå?合ã?無視されますã?で、同様に扱ã�?�“とがå?来ますã?
057 * こã?、EXEC_SQL は、それそれã? XMLãƒ??タをデータベã?スに登録する際にã€?
058 * SQL処ç�?‚’自動的に流す為の、SQLæ–?‚’記載しますã?
059 * こã?処ç�??、イベント毎に実行される為、その配置é ??重要ですã?
060 * こã?タグは、è¤?•°記述することもå?来ますが、BODY部にはã€?¼‘つのSQLæ–??み記述しますã?
061 *
062 * ※ こã?タグは、Transaction タグの対象ですã?
063 *
064 * <ROWSET tableName="XX" >
065 * <EXEC_SQL> æœ??に記載して、å?期å?ç�?ãƒ??タクリアç?を実行させるã€?
066 * delete from GEXX where YYYYY
067 * </EXEC_SQL>
068 * <MERGE_SQL> こã?SQLæ–?�§ UPDATEして、結果が0件ならINSERTを行いますã?
069 * update GEXX set AA=[AA] , BB=[BB] where CC=[CC]
070 * </MERGE_SQL>
071 * <ROW num="1">
072 * <カラãƒ?>値1</カラãƒ?>
073 * ?¥?¥?¥
074 * <カラãƒ?>値n</カラãƒ?>
075 * </ROW>
076 * ?¥?¥?¥
077 * <ROW num="n">
078 * ?¥?¥?¥
079 * </ROW>
080 * <EXEC_SQL> æœ?¾Œに記載してã€??目の設å®?整合æ?登録)を行うã€?
081 * update GEXX set AA='XX' , BB='XX' where YYYYY
082 * </EXEC_SQL>
083 * <ROWSET>
084 *
085 * @og.formSample
086 * ●形式ï¼?lt;og:directXMLSave filename="[?¥?¥?¥]" ?¥?¥?¥ />
087 * ●body?šなã�?
088 *
089 * ●Tag定義??
090 * <og:directXMLSave
091 * dbid 【TAGã€?通常は使ã�?�¾せん)検索時ã?DB接続IDを指定しまã�?初期値:DEFAULT)
092 * fileURL 【TAG】読み取りå…?ƒ‡ィレクトリ名をæŒ?®šしまã�?(初期値:FILE_URL[=filetemp/])
093 * filename 【TAG】ファイルを作æ?するときã?ファイル名をセãƒ?ƒˆしまã�?(初期値:FILE_FILENAME[=file.xls])
094 * displayMsg 【TAG】query の結果を画面上に表示するメãƒ?‚»ージIDを指定しまã�?初期値:MSG0040[ã€?»¶登録しました])
095 * keys 【TAG】XMLファイルを読み取った後でæŒ?®šするキーをCSV形式でè¤?•°æŒ?®šしまã�?
096 * vals 【TAG】XMLファイルを読み取った後でæŒ?®šするå?をCSV形式でè¤?•°æŒ?®šしまã�?
097 * caseKey 【TAG】このタグ自体を利用するかどã�?�‹の条件キーを指定しまã�?初期値:null)
098 * caseVal 【TAG】このタグ自体を利用するかどã�?�‹の条件値を指定しまã�?初期値:null)
099 * caseNN 【TAG】指定ã?値がã?null/ゼロæ–?—å? でなã�??å�?Not Null=NN)は、このタグは使用されまã�?初期値:true)
100 * caseNull 【TAG】指定ã?値がã?null/ゼロæ–?—å? の場合ã?、このタグは使用されまã�?初期値:true)
101 * debug 【TAG】デバッグæƒ??をå?力するかどã�?�‹[true/false]を指定しまã�?初期値:false)
102 * />
103 *
104 * ●使用ä¾?
105 * <og:directXMLSave
106 * dbid = "ORCL" 接続データベã?スID(初期値:DEFAULT)
107 * fileURL = "{@USER.ID}" 読み取りå…?ƒ‡ィレクトリå�?
108 * filename = "{@filename}" 読み取りå…?ƒ•ァイルå�?
109 * displayMsg = "MSG0040" 登録完äº?¾Œã?メãƒ?‚»ージ
110 * />
111 *
112 * @og.group ファイル入åŠ?
113 * @og.rev 4.0.0.0 (2007/03/08) 新規追åŠ?
114 *
115 * @version 4.0
116 * @author Kazuhiko Hasegawa
117 * @since JDK5.0,
118 */
119 public class DirectXMLSaveTag extends CommonTagSupport {
120 //* こã?プログラãƒ??VERSIONæ–?—å?を設定しますã? {@value} */
121 private static final String VERSION = "5.6.7.0 (2013/07/27)" ;
122
123 private static final long serialVersionUID = 567020130727L ;
124
125 private static final String ENCODE = "UTF-8";
126 // 4.0.0.0 (2007/10/10) dbid の初期値をã?"DEFAULT" から null に変更
127 // private String dbid = "DEFAULT";
128 private String dbid = null;
129 private String fileURL = HybsSystem.sys( "FILE_URL" ); // 4.0.0 (2005/01/31)
130 private String filename = HybsSystem.sys( "FILE_FILENAME" ); // ファイルå�?
131 private String displayMsg = "MSG0040"; // ã€?»¶登録しましたã€?
132 private String[] keys = null;
133 private String[] vals = null;
134 private long dyStart = 0; // 実行時間測定用のDIV要ç´?‚’出力しますã?
135
136 /**
137 * Taglibの開始タグが見つかったときに処ç�?�™ã‚?doStartTag() ã‚?オーバã?ライドしますã?
138 *
139 * @og.rev 5.6.6.1 (2013/07/12) caseKey 、caseVal 属æ?対å¿?
140 *
141 * @return 後続å?ç�??æŒ?¤º( SKIP_BODY )
142 */
143 @Override
144 public int doStartTag() {
145 // 5.6.6.1 (2013/07/12) caseKey 、caseVal 属æ?対å¿?
146 if( useTag() ) {
147 dyStart = System.currentTimeMillis(); // 時間測定用
148 }
149 return( SKIP_BODY ); // Body を評価しなã�?
150 }
151
152 /**
153 * Taglibの終äº?‚¿グが見つかったときに処ç�?�™ã‚?doEndTag() ã‚?オーバã?ライドしますã?
154 *
155 * @og.rev 4.0.0.0 (2007/10/18) メãƒ?‚»ージリソース統å�? getResource().getMessage â‡?getResource().getLabel )
156 * @og.rev 4.0.0.1 (2007/12/03) try ??catch ??finally をきちんと行うã€?
157 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対å¿?
158 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
159 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応ã?例外経路で null 値を利用することが保証されてã�?�¾すã?
160 * @og.rev 5.6.6.1 (2013/07/12) caseKey 、caseVal 属æ?対å¿?
161 * @og.rev 5.6.7.0 (2013/07/27) DDL?ˆデータ定義è¨?ªž:Data Definition Language?‰ã?処ç�?»¶数追åŠ?
162 *
163 * @return 後続å?ç�??æŒ?¤º
164 */
165 @Override
166 public int doEndTag() {
167 debugPrint(); // 4.0.0 (2005/02/28)
168 // 5.6.6.1 (2013/07/12) caseKey 、caseVal 属æ?対å¿?
169 if( !useTag() ) { return(EVAL_PAGE); }
170
171 BufferedReader reader = null;
172 final int insCnt ;
173 final int updCnt ;
174 final int delCnt ;
175 final int ddlCnt ; // 5.6.7.0 (2013/07/27) DDL処ç�?»¶数追åŠ?
176 boolean errFlag = true;
177 // Connection conn = null;
178 Transaction tran = null; // 5.1.9.0 (2010/08/01) Transaction 対å¿?
179 try {
180 // 5.1.9.0 (2010/08/01) Transaction 対å¿?
181 TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class );
182 if( tranTag == null ) {
183 // tran = new TransactionReal( dbid,getApplicationInfo() );
184 tran = new TransactionReal( getApplicationInfo() ); // 5.3.7.0 (2011/07/01) 引数変更
185 }
186 else {
187 tran = tranTag.getTransaction();
188 }
189 // conn = ConnectionFactory.connection( dbid,getApplicationInfo() ); // 3.8.7.0 (2006/12/15)
190
191 Connection conn = tran.getConnection( dbid ); // 5.1.9.0 (2010/08/01) Transaction 対å¿?
192 HybsXMLSave save = new HybsXMLSave( conn );
193 if( keys != null ) { save.setAfterMap( getAfterMap() ); }
194
195 reader = getBufferedReader();
196 save.insertXML( reader );
197 insCnt = save.getInsertCount();
198 updCnt = save.getUpdateCount();
199 delCnt = save.getDeleteCount();
200 ddlCnt = save.getDDLCount(); // 5.6.7.0 (2013/07/27) DDL処ç�?»¶数追åŠ?
201 // Closer.commit( conn );
202 tran.commit(); // 5.1.9.0 (2010/08/01) Transaction 対å¿?
203 errFlag = false; // エラーではなã�?
204 }
205 catch( Throwable ex ) {
206 // Closer.rollback( conn );
207 if( tran != null ) { // 5.5.2.6 (2012/05/25) findbugs対å¿?
208 tran.rollback(); // 5.1.9.0 (2010/08/01) Transaction 対å¿?
209 }
210 throw new HybsSystemException( ex );
211 }
212 finally {
213 if( tran != null ) { // 5.5.2.6 (2012/05/25) findbugs対å¿?
214 tran.close( errFlag );
215 }
216 // if( errFlag ) { ConnectionFactory.remove( conn,dbid ); } // 削除
217 // else { ConnectionFactory.close( conn,dbid ); } // 返却
218 // Closer.connClose( conn );
219 Closer.ioClose( reader );
220 }
221
222 // 実行件数の表示
223 // 4.0.0 (2005/11/30) 出力é?の変更。ä¸?•ªæœ??に出力しますã?
224 if( displayMsg != null && displayMsg.length() > 0 ) {
225 StringBuilder buf = new StringBuilder();
226 buf.append( "INS:" ).append( insCnt );
227 buf.append( " / UPD:" ).append( updCnt );
228 buf.append( " / DEL:" ).append( delCnt );
229 buf.append( " / DDL:" ).append( ddlCnt ); // 5.6.7.0 (2013/07/27) DDL処ç�?»¶数追åŠ?
230 // buf.append( getResource().getMessage( displayMsg ) );
231 buf.append( getResource().getLabel( displayMsg ) );
232 buf.append( HybsSystem.BR );
233
234 jspPrint( buf.toString() );
235 }
236
237 // 時間測定用の DIV 要ç´?‚’出åŠ?
238 long dyTime = System.currentTimeMillis()-dyStart;
239 jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" ); // 3.5.6.3 (2004/07/12)
240
241 // 4.0.0 (2005/01/31) セキュリãƒ?‚£チェãƒ?‚¯(ãƒ??タアクセス件数登録)
242 GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
243 if( guiInfo != null ) { guiInfo.addWriteCount( insCnt,dyTime,fileURL + filename ); }
244
245 return(EVAL_PAGE);
246 }
247
248 /**
249 * タグリブオブジェクトをリリースしますã?
250 * キャãƒ?‚·ュされて再利用されるã?で、フィールドã?初期設定を行いますã?
251 *
252 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値をã?"DEFAULT" から null に変更
253 */
254 @Override
255 protected void release2() {
256 super.release2();
257 // dbid = "DEFAULT";
258 dbid = null;
259 fileURL = HybsSystem.sys( "FILE_URL" ); // 4.0.0 (2005/01/31)
260 filename = HybsSystem.sys( "FILE_FILENAME" ); // ファイルå�?
261 displayMsg = "MSG0040"; // ã€?»¶登録しましたã€?
262 keys = null;
263 vals = null;
264 }
265
266 /**
267 * BufferedReader を取得しますã?
268 *
269 * ここでは、ä¸?ˆ¬çš?�ªファイル出力をè€??した BufferedReader を作æ?しますã?
270 *
271 * @return ファイル入力用BufferedReaderオブジェクãƒ?
272 */
273 private BufferedReader getBufferedReader() {
274 if( filename == null ) {
275 String errMsg = "ファイル名がセãƒ?ƒˆされてã�?�¾せんã€?;
276 throw new HybsSystemException( errMsg );
277 }
278 String directory = HybsSystem.url2dir( fileURL );
279 File file = new File( StringUtil.urlAppend( directory,filename ) );
280
281 BufferedReader out = FileUtil.getBufferedReader( file,ENCODE );
282
283 return out ;
284 }
285
286 /**
287 * BufferedReader を取得しますã?
288 *
289 * ここでは、ä¸?ˆ¬çš?�ªファイル出力をè€??した BufferedReader を作æ?しますã?
290 *
291 * @og.rev 5.6.6.1 (2013/07/12) key ã�?null ã‚?ゼロæ–?—å?の場合ã?、Map に追åŠ?�—ませんã€?
292 *
293 * @return ファイル入力用BufferedReader
294 */
295 private Map<String,String> getAfterMap() {
296 Map<String,String> map = new HashMap<String,String>();
297
298 for( int i=0; i<keys.length; i++ ) {
299 if( keys[i] != null && keys[i].length() > 0 ) { // 5.6.6.1 (2013/07/12)
300 map.put( keys[i],vals[i] );
301 }
302 }
303 return map ;
304 }
305
306 /**
307 * 【TAGã€?通常は使ã�?�¾せん)検索時ã?DB接続IDを指定しまã�?初期値:DEFAULT)ã€?
308 *
309 * @og.tag
310 * 検索時ã?DB接続IDを指定しますã?初期値は、DEFAULT ですã?
311 *
312 * @param id ãƒ??タベã?ス接続ID
313 */
314 public void setDbid( final String id ) {
315 dbid = nval( getRequestParameter( id ),dbid );
316 }
317
318 /**
319 * 【TAG】読み取りå…?ƒ‡ィレクトリ名をæŒ?®šしまã�?
320 * (初期値:FILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])ã€?
321 *
322 * @og.tag
323 * こã?属æ?でæŒ?®šされるãƒ?‚£レクトリより、ファイルを読み取りますã?
324 * æŒ?®š方法ã?ã€??常の fileURL 属æ?と同様に、å?頭がã?'/' (UNIX) またã?ã€?¼’文字目がã?
325 * ":" (Windows)の場合ã?、指定ã?URLそã?ままのãƒ?‚£レクトリに、そã�?�§なã�??合ã?ã€?
326 * fileURL = "{@USER.ID}" とæŒ?®šすると、FILE_URL 属æ?でæŒ?®šã?フォルãƒ??下にã€?
327 * さらに、各個人ID別のフォルãƒ??下よりã?読み取りますã?
328 * (初期値:シスãƒ?ƒ 定数のFILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])ã€?
329 *
330 * @og.rev 4.0.0.0 (2007/11/20) æŒ?®šされたãƒ?‚£レクトリ名ã?æœ?¾Œが"\"or"/"で終わってã�?�ªã�??合にã€?/"を付加するã€?
331 *
332 * @param url ファイルURL
333 * @see org.opengion.hayabusa.common.SystemData#FILE_URL
334 */
335 public void setFileURL( final String url ) {
336 String furl = nval( getRequestParameter( url ),null );
337 if( furl != null ) {
338 char ch = furl.charAt( furl.length()-1 );
339 if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
340 fileURL = StringUtil.urlAppend( fileURL,furl );
341 }
342 }
343
344 /**
345 * 【TAG】ファイルを作æ?するときã?ファイル名をセãƒ?ƒˆしまã�?
346 * (初期値:FILE_FILENAME[={@og.value org.opengion.hayabusa.common.SystemData#FILE_FILENAME}])ã€?
347 *
348 * @og.tag
349 * ファイルを作æ?するときã?ファイル名をセãƒ?ƒˆしますã?
350 * (初期値:シスãƒ?ƒ 定数のFILE_FILENAME[={@og.value org.opengion.hayabusa.common.SystemData#FILE_FILENAME}])ã€?
351 *
352 * @param filename ファイルå�?
353 * @see org.opengion.hayabusa.common.SystemData#FILE_FILENAME
354 */
355 public void setFilename( final String filename ) {
356 this.filename = nval( getRequestParameter( filename ),this.filename );
357 }
358
359 /**
360 * 【TAG】query の結果を画面上に表示するメãƒ?‚»ージIDを指定しまã�?初期値:MSG0040[ã€?»¶登録しました])ã€?
361 *
362 * @og.tag
363 * ここでは、検索結果の件数ã‚?™»録された件数をまずå?力しã€?
364 * そã?次に、ここでæŒ?®šしたメãƒ?‚»ージをリソースから取得して
365 * 表示しますã?
366 * 表示させたくなã�??合ã?, displayMsg = "" をセãƒ?ƒˆしてくださいã€?
367 * 初期値は、検索件数を表示しますã?
368 * ※ こã?属æ?には、リクエスト変数({@XXXX})は使用できませんã€?
369 *
370 * @param id ãƒ?‚£スプレイに表示させるメãƒ?‚»ージ ID
371 */
372 public void setDisplayMsg( final String id ) {
373 if( id != null ) { displayMsg = id; }
374 }
375
376 /**
377 * 【TAG】XMLファイルを読み取った後でæŒ?®šするキーをCSV形式でè¤?•°æŒ?®šしますã?
378 *
379 * @og.tag
380 * XMLファイルを読み取った後で、データを変更できますã?
381 * 変更するカラãƒ?��(キー)をCSV形式でæŒ?®šしますã?
382 * XMLファイルにキーが存在してã�?�Ÿ場合ã?、vals でæŒ?®šã?値に書き換えますã?
383 * キーが存在してã�?�ªã�??合ã?、ここでæŒ?®šするキーと値がã?ãƒ??タとして
384 * 追åŠ?�•れますã?
385 * 例えば、登録日ã‚??登録è€??またã?、テンプレートより各シスãƒ?ƒ ID毎に
386 * 登録するなどの使ã�?–¹を想定してã�?�¾すã?
387 * åˆ?§£方法ã?、CSV変数をå?にåˆ?§£してから、getRequestParameter で値を取得しますã?
388 * こうしなã�?�¨ãƒ??タ自身にカンマを持ってã�?‚‹場合にåˆ?§£をミスる為ですã?
389 *
390 * @param key リンク先に渡すキー
391 * @see #setVals( String )
392 */
393 public void setKeys( final String key ) {
394 keys = getCSVParameter( key );
395 }
396
397 /**
398 * 【TAG】XMLファイルを読み取った後でæŒ?®šするå?をCSV形式でè¤?•°æŒ?®šしますã?
399 *
400 * @og.tag
401 * XMLファイルを読み取った後で、データを変更できますã?
402 * 変更する値をCSV形式でæŒ?®šしますã?
403 * XMLファイルにキーが存在してã�?�Ÿ場合ã?、vals でæŒ?®šã?値に書き換えますã?
404 * キーが存在してã�?�ªã�??合ã?、ここでæŒ?®šするキーと値がã?ãƒ??タとして
405 * 追åŠ?�•れますã?
406 * 例えば、登録日ã‚??登録è€??またã?、テンプレートより各シスãƒ?ƒ ID毎に
407 * 登録するなどの使ã�?–¹を想定してã�?�¾すã?
408 * åˆ?§£方法ã?、CSV変数をå?にåˆ?§£してから、getRequestParameter で値を取得しますã?
409 * こうしなã�?�¨ãƒ??タ自身にカンマを持ってã�?‚‹場合にåˆ?§£をミスる為ですã?
410 *
411 * @param val keys属æ?に対応するå?
412 * @see #setKeys( String )
413 */
414 public void setVals( final String val ) {
415 vals = getCSVParameter( val );
416 }
417
418 /**
419 * こã?オブジェクトã?æ–?—å?表現を返しますã?
420 * 基本çš?�«ãƒ?ƒ�ãƒ?‚°目çš?�«使用しますã?
421 *
422 * @return こã?クラスのæ–?—å?表現
423 */
424 @Override
425 public String toString() {
426 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
427 .println( "VERSION" ,VERSION )
428 .println( "dbid" ,dbid )
429 .println( "fileURL" ,fileURL )
430 .println( "filename" ,filename )
431 .println( "displayMsg" ,displayMsg )
432 .println( "dyStart" ,dyStart )
433 .println( "Other..." ,getAttributes().getAttribute() )
434 .fixForm().toString() ;
435 }
436 }