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.DBTableModel; 021import org.opengion.hayabusa.develop.JspCreateFactory; 022import org.opengion.hayabusa.develop.JspConvertEntity; 023import org.opengion.fukurou.util.ErrorMessage; 024import org.opengion.fukurou.util.StringUtil; 025import static org.opengion.fukurou.util.StringUtil.nval ; 026import org.opengion.fukurou.xml.JspSaxParser; 027 028import java.util.Map; 029import java.util.HashMap; 030import java.util.List; 031import java.util.ArrayList; 032import java.util.Locale ; 033 034import java.io.File; 035import java.io.ObjectOutputStream; 036import java.io.ObjectInputStream; 037import java.io.IOException; 038 039/** 040 * JspCreateTag は、画面定義情報より、JSP画面を自動作成するツールです。 041 * 042 * 画面作成するにあたり、3箇所の参照元が存在します。 043 * 044 * 1.画面属性の設定 : 雛形 → 仮画面 ・・・ hpgid で指定の画面ID 045 * 2.仮画面修正 : 仮画面 → 仮画面 ・・・ jsp/customUserDef/画面ID 046 * 3.本環境修正 : 本画面 → 本画面 ・・・ jsp/画面ID 047 * 048 * それぞれ、作成先の画面IDフォルダが存在する場合は、取込元を作成先に設定します。 049 * つまり、一度作成すると、それ以降は、作成された画面を基準に処理を行います。 050 * 051 * @og.formSample 052 * ●形式:<og:jspCreate outdir="…" pgid="…" /> 053 * ●body:なし 054 * 055 * ●Tag定義: 056 * <og:jspCreate 057 * pgid ○【TAG】プログラムIDを指定します(必須)。 058 * outdir 【TAG】作成先のディレクトリを指定します 059 * hpgid 【TAG】雛形のプログラムIDを指定します 060 * useUserDef 【TAG】仮環境を使用するかどうか[true/false]を指定します(初期値:true:使用する) 061 * tagNames 【TAG】処理を行うタグを部分指定します(初期値:内部登録タグすべて) 062 * tableId 【TAG】(通常は使いません)DBTableModel が登録されているメモリのキーを指定します 063 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session) 064 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 065 * /> 066 * 067 * ●使用例 068 * ・先に、query タグでDBTableModel が作成済み 069 * <og:jspCreate 070 * outdir = "{@SYS.REAL_PATH}jsp/" :出力先フォルダ 071 * pgid = "{@PGID}" :作成画面ID 072 * hpgid = "{@HPGID}" :雛形画面ID 073 * useUserDef = "true/false" :仮環境の使用可否(初期値:true 使用する) 074 * /> 075 * 076 * @og.group 開発補助 077 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 078 * 079 * @version 0.9.0 2000/10/17 080 * @author Kazuhiko Hasegawa 081 * @since JDK1.6, 082 */ 083public class JspCreateTag extends CommonTagSupport { 084 //* このプログラムのVERSION文字列を設定します。 {@value} */ 085 private static final String VERSION = "5.6.8.0 (2013/09/06)" ; 086 087 private static final long serialVersionUID = 568020130906L ; // 5.6.8.0 (2013/09/06) 088 089// private static final String ENCODE = "UTF-8" ; 090 091// private static String JSP_DIR = "C:/opengion/uap/webapps/gf/jsp/"; 092 private static String JSP_DIR = HybsSystem.sys( "REAL_PATH" ) + "jsp/" ; 093 094 private static final String CUST_DEF = "customUserDef/" ; 095 096 private transient DBTableModel table = null; 097 098 private String tableId = HybsSystem.TBL_MDL_KEY; 099 private String outdir = JSP_DIR; // 出力先フォルダ 100 private String pgid = null; // 作成画面ID 101 private String hpgid = null; // 雛形画面ID 102 private String[] tagNames = null; // 5.6.8.0 (2013/09/06) 処理を行うタグを部分指定 103 private boolean useUserDef = true; // 仮環境の使用可否(初期値:true 使用する) 104 105// private static final String[] JCF_LIST = new String[] { "COMMENT" , "COLUMN" , "ORDER_BY" , "QUERY" , "VIEW" , "TABLE_UPDATE" }; 106 private static final String[] JCF_LIST = new String[] { "COMMENT" , "HIDEMENU" , "COLUMN" , "ORDER_BY" , "QUERY" , "VIEW" , "TABLE_UPDATE" }; // 5.6.4.4 (2013/05/31) 107 108 /** 109 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 110 * 111 * @return 後続処理の指示(SKIP_BODY) 112 */ 113 @Override 114 public int doStartTag() { 115 table = (DBTableModel)getObject( tableId ); 116 117 return(SKIP_BODY); // Body を評価しない 118// return ( EVAL_BODY_BUFFERED ); // Body を評価する 119 } 120 121 /** 122 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 123 * 124 * @return int 125 */ 126// @Override 127// public int doAfterBody() { 128// body = nval( getBodyString(),body ); 129// 130// return(SKIP_BODY); 131// } 132 133 /** 134 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 135 * 136 * @return 後続処理の指示 137 */ 138 @Override 139 public int doEndTag() { 140 // デバッグ時には、オブジェクト内部情報を表示する。 141 if( isDebug() ) { 142 debugPrint(); 143 } 144 145 boolean okFlag = execute(); 146 147 if( okFlag ) { // 正常 148 return(EVAL_PAGE); 149 } 150 else { 151 return(SKIP_PAGE); 152 } 153 } 154 155 /** 156 * タグリブオブジェクトをリリースします。 157 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 158 * 159 * @og.rev 5.6.8.0 (2013/09/06) tagNames 追加 160 */ 161 @Override 162 protected void release2() { 163 super.release2(); 164 table = null; 165 tableId = HybsSystem.TBL_MDL_KEY; 166 outdir = JSP_DIR; 167 pgid = null; 168 hpgid = null; 169 useUserDef = true; 170 tagNames = null; // 5.6.8.0 (2013/09/06) 処理を行うタグを部分指定 171 } 172 173 /** 174 * DBTableModel処理を実行します。 175 * 176 * @og.rev 5.2.1.0 (2010/10/01) 実行クラスのクラス名を変更します。 _OG_ を削除 177 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応。JspConvertEntity.DBKEY を、JspConvertEntity.getDBKEY() に変更。 178 * @og.rev 5.6.8.0 (2013/09/06) 処理対象タグの部分指定対応 (tagNames 追加) 179 * 180 * @return 処理の実行結果 181 */ 182 public boolean execute() { 183 boolean okFlag = false; 184 185 // 出力先(セーブ先)のフォルダ 186 File saveDir = (useUserDef) ? new File( outdir + CUST_DEF , pgid ) : new File( outdir , pgid ) ; 187 188 // 雛形(参照元)のフォルダ 189 final File refDir ; 190 if( saveDir.exists() ) { // 出力先フォルダが存在した場合 191 refDir = saveDir ; // 出力先フォルダが、雛形フォルダになる。 192 } 193 else { // 出力先フォルダが存在しない場合 194 refDir = new File( outdir , hpgid ); // 雛形画面IDをそのまま使用します。 195 if( ! saveDir.mkdirs() ) { 196 String errMsg = "出力先のフォルダが作成できませんでした。[" + saveDir + "]" ; 197 throw new HybsSystemException( errMsg ); 198 } 199 } 200 201 if( ! refDir.exists() ) { // 雛形(参照元)フォルダが存在しない場合、エラー 202 String errMsg = "雛形(参照元)フォルダが存在しません。[" + refDir + "]" ; 203 throw new HybsSystemException( errMsg ); 204 } 205 206// PrintWriter writer = null; 207 208// int[] clmNo = getTableColumnNo( JspConvertEntity.DBKEY ); 209 int[] clmNo = getTableColumnNo( JspConvertEntity.getDBKEY() ); // 5.5.2.6 (2012/05/25) findbugs対応 210 int rowCnt = table.getRowCount(); 211 212 int row = 0; 213 boolean unCmntSet = true; 214 String[] data = null; 215 try { 216 //JSPを書く為に必要な情報を設定 217 Map<String,List<JspConvertEntity>> tables = new HashMap<String,List<JspConvertEntity>>(); 218 219 for( row=0; row<rowCnt; row++ ) { 220 data = table.getValues( row ); 221 JspConvertEntity entry = JspConvertEntity.newInstance( data, clmNo ); 222 223 if( entry != null ) { 224 List<JspConvertEntity> array = tables.get( entry.getType() ); 225 if( array == null ) { array = new ArrayList<JspConvertEntity>(); } 226 array.add( entry ); 227 tables.put( entry.getType(),array ); 228 if( unCmntSet ) { 229 tables.put( "COMMENT",array ); 230 unCmntSet = false; 231 } 232 } 233 } 234 235 // 参照先フォルダから、出力先フォルダに、XMLコピー処理を行います。 236 JspSaxParser spar = new JspSaxParser(); 237 238 // 5.2.1.0 (2010/10/01) 実行クラスのクラス名を変更します。 _OG_ を削除 239// spar.addFilter( JspCreateFactory.newInstance( "COMMENT" ,tables) ); 240// spar.addFilter( JspCreateFactory.newInstance( "COLUMN" ,tables) ); 241// spar.addFilter( JspCreateFactory.newInstance( "SELECT" ,tables) ); 242// spar.addFilter( JspCreateFactory.newInstance( "QUERY" ,tables) ); 243// spar.addFilter( JspCreateFactory.newInstance( "VIEW" ,tables) ); 244 245 // 5.6.8.0 (2013/09/06) 処理対象タグの部分指定対応 (tagNames 追加) 246 if( tagNames == null ) { tagNames = JCF_LIST; } 247// for( String jcf : JCF_LIST ) { 248 for( String jcf : tagNames ) { 249 spar.addFilter( JspCreateFactory.newInstance( jcf , tables ) ); 250 } 251 252 spar.copyDirectry( refDir,saveDir ); 253 254// //query.jsp作成 255// writer = FileUtil.getPrintWriter( new File( saveDir,"query.jsp" ),ENCODE ); 256// writer.print(writeQueryJSP( refDir , tables )); 257// writer.println(); 258// writer.flush(); 259// 260// //result.jsp作成 261// writer = FileUtil.getPrintWriter( new File( saveDir,"result.jsp" ),ENCODE ); 262// writer.print(writeResultJSP( refDir , tables )); 263// writer.println(); 264// writer.flush(); 265 266 okFlag = true; 267 } 268 catch( RuntimeException ex ) { 269 ex.printStackTrace(); 270 ErrorMessage errMessage = new ErrorMessage( "JspCreateTag Error" ); 271 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT",ex.getMessage() ); 272 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT",StringUtil.array2csv( data ) ); 273 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT","PRGID=[" + pgid + "]" ); 274 // BAT から呼び出す場合があるため、標準エラー出力にも情報を出しておきます。 275 System.out.println( errMessage ); 276 } 277// finally { 278// Closer.ioClose( writer ); 279// } 280 281 return okFlag; 282 } 283 284 /** 285 * query.jspファイルの内容を生成します。 286 * 287 * @param refDir 288 * @param tables 289 * 290 * @return 生成した内容 291 */ 292// private String writeQueryJSP( File refDir , HashMap<String , ArrayList<JspConvertEntity>> tables ) { 293// String jsp = ""; 294// try{ 295// //利用する生成クラスを設定 296// HashMap< String , JspCreate > generates = new HashMap< String , JspCreate >(); 297// generates.put( "og:comment" , JspCreateFactory.newInstance( "OG_COMMENT",tables) ); 298// generates.put( "table" , JspCreateFactory.newInstance( "OG_COLUMN",tables) ); 299// generates.put( "og:select" , JspCreateFactory.newInstance( "OG_SELECT",tables) ); 300// 301// //JSPの作成処理を実施。 302// JspHandler handler = new JspHandler(); 303// jsp = handler.generate( new File( refDir , "query.jsp" ), ENCODE , generates); 304// 305// }catch(Throwable ex){ 306// ex.printStackTrace(); 307// throw new RuntimeException(ex); 308// } 309// return jsp; 310// } 311 312 /** 313 * result.jspファイルの内容を生成します。 314 * 315 * @param refDir 316 * @param tables 317 * 318 * @return 生成した内容 319 */ 320// private String writeResultJSP(File refDir , HashMap<String , ArrayList<JspConvertEntity>> tables ) { 321// String jsp = ""; 322// try{ 323// //利用する生成クラスを設定 324// HashMap< String , JspCreate > generates = new HashMap< String , JspCreate >(); 325// generates.put( "og:comment" , JspCreateFactory.newInstance( "OG_COMMENT",tables) ); 326// generates.put( "og:query" , JspCreateFactory.newInstance( "OG_QUERY",tables ) ); 327// generates.put( "og:view" , JspCreateFactory.newInstance( "OG_VIEW",tables) ); 328// 329// //JSPの作成処理を実施。 330// JspHandler handler = new JspHandler(); 331// jsp = handler.generate( new File( refDir , "result.jsp" ) , ENCODE , generates); 332// 333// }catch(Throwable ex){ 334// ex.printStackTrace(); 335// throw new RuntimeException(ex); 336// } 337// return jsp; 338// } 339 340 /** 341 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 342 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 343 * 344 * @og.tag 345 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 346 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 347 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 348 * この tableId 属性を利用して、メモリ空間を分けます。 349 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 350 * 351 * @param id sessionに登録する時の ID 352 */ 353 public void setTableId( final String id ) { 354 tableId = nval( getRequestParameter( id ),tableId ); 355 } 356 357 /** 358 * 【TAG】作成先のディレクトリを指定します。 359 * 360 * @og.tag 361 * 作成先のディレクトリを指定します。 362 * 初期値は、実際に実行しているアプリケーションの REAL_PATH + jsp フォルダ以下です。 363 * 作成先のフォルダも、useUserDef の設定によって異なります。 364 * 365 * @param dir 出力先のディレクトリ 366 */ 367 public void setOutdir( final String dir ) { 368 outdir = nval( getRequestParameter( dir ),outdir ); 369 } 370 371 /** 372 * 【TAG】プログラムIDを指定します。 373 * 374 * @og.tag 375 * 作成先のプログラムIDを指定します。 376 * ただし、作成先の実際のフォルダは、useUserDef の設定によって異なります。 377 * 378 * @param id プログラムID 379 */ 380 public void setPgid( final String id ) { 381 pgid = nval( getRequestParameter( id ),pgid ); 382 } 383 384 /** 385 * 【TAG】雛形のプログラムIDを指定します。 386 * 387 * @og.tag 388 * 雛形のプログラムIDをパースして、実際のプログラムを作成します。 389 * ただし、作成先の実際のフォルダは、useUserDef の設定によって異なります。 390 * また、パースするのは、作成先の画面IDのフォルダが存在しない場合のみです。 391 * すでに、存在している場合は、元の画面IDのフォルダを読み取って、パースを 392 * 行います。基本的に、作成先のソースを手で修正した場合でも、パースと 393 * 無関係な箇所の修正はそのまま反映のこされます。 394 * 395 * @param id 雛形のプログラムID 396 */ 397 public void setHpgid( final String id ) { 398 hpgid = nval( getRequestParameter( id ),hpgid ); 399 } 400 401 /** 402 * 【TAG】仮環境を使用するかどうか[true/false]を指定します(初期値:true:使用する)。 403 * 404 * @og.tag 405 * true:使用する を設定すると、"customUserDef" フォルダの下に、画面IDの 406 * フォルダを作成します。 407 * false:使用しない を設定すると、実際の リアルパス(REAL_PATH/jsp)の下に、 408 * 画面IDのフォルダを作成します。こちらは、実際の画面と同様に、画面リソース等を 409 * 作成してアクセスすることになります。 410 * 411 * @param flag 仮環境を使用するかどうか [true:使用する/false:使用しない] 412 */ 413 public void setUseUserDef( final String flag ) { 414 useUserDef = nval( getRequestParameter( flag ),useUserDef ); 415 } 416 417 /** 418 * 【TAG】処理を行うタグを部分指定します(初期値:内部登録タグすべて)。 419 * 420 * @og.tag 421 * 処理を行うタグは、内部的に、COMMENT,HIDEMENU,COLUMN,ORDER_BY,QUERY,VIEW,TABLE_UPDATE だけ 422 * 予約されており、初期値は、すべてのタグを処理します。 423 * ここでは、その一部のみ実行できるように、カンマ区切り文字で指定できるようにします。 424 * 実行不可のタグ名を指定すると、エラーになります。 425 * 426 * @og.rev 5.6.8.0 (2013/09/06) 新規追加 427 * 428 * @param tags 処理を行うタグを部分指定する。 429 */ 430 public void setTagNames( final String tags ) { 431 String tagNms = nval( getRequestParameter( tags ),null ); 432 433 if( tagNms != null ) { 434 tagNames = tagNms.split( "," ); 435 436 for( int i=0; i<tagNames.length; i++ ) { 437 String tag = tagNames[i].trim().toUpperCase(Locale.JAPAN); 438 if( ! check( tag, JCF_LIST ) ) { 439 String errMsg = "指定の tagNames は、下記の範囲で指定してください。" 440 + "tagNames=" + tagNms + " (NG=" + tag + ") : " 441 + JCF_LIST.toString(); 442 throw new HybsSystemException( errMsg ); 443 } 444 tagNames[i] = tag ; // 大文字に変換した値を戻す。 445 } 446 } 447 } 448 449 /** 450 * カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。 451 * 452 * @param nameArray カラム名配列 453 * 454 * @return カラムNo配列 455 */ 456 private int[] getTableColumnNo( final String[] nameArray ) { 457 int[] clmNo = new int[ nameArray.length ]; 458 for( int i=0; i<clmNo.length; i++ ) { 459 clmNo[i] = table.getColumnNo( nameArray[i] ); 460 } 461 return clmNo; 462 } 463 464 /** 465 * シリアライズ用のカスタムシリアライズ書き込みメソッド 466 * 467 * @param strm ObjectOutputStreamオブジェクト 468 * @serialData 一部のオブジェクトは、シリアライズされません。 469 * 470 * @throws IOException 入出力エラーが発生した場合 471 */ 472 private void writeObject( final ObjectOutputStream strm ) throws IOException { 473 strm.defaultWriteObject(); 474 } 475 476 /** 477 * シリアライズ用のカスタムシリアライズ読み込みメソッド 478 * 479 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 480 * 481 * @param strm ObjectInputStreamオブジェクト 482 * @see #release2() 483 * @serialData 一部のオブジェクトは、シリアライズされません。 484 * 485 * @throws IOException シリアライズに関する入出力エラーが発生した場合 486 * @throws ClassNotFoundException クラスを見つけることができなかった場合 487 */ 488 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 489 strm.defaultReadObject(); 490 } 491 492 /** 493 * このオブジェクトの文字列表現を返します。 494 * 基本的にデバッグ目的に使用します。 495 * 496 * @return このクラスの文字列表現 497 */ 498 @Override 499 public String toString() { 500 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 501 .println( "VERSION" ,VERSION ) 502 .println( "tableId" ,tableId ) 503 .println( "outdir" ,outdir ) 504 .println( "pgid" ,pgid ) 505 .println( "hpgid" ,hpgid ) 506 .println( "useUserDef" ,useUserDef ) 507 .fixForm().toString() ; 508 } 509}