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.fukurou.process; 017 018import org.opengion.fukurou.util.FileUtil; 019import org.opengion.fukurou.util.Closer; 020import org.opengion.fukurou.util.HybsDateUtil; 021import org.opengion.fukurou.util.CommentLineParser; 022 023import org.opengion.fukurou.security.HybsCryptography ; // 5.7.2.1 (2014/01/17) 024 025import java.io.File; 026import java.io.BufferedReader; 027import java.io.PrintWriter; 028import java.io.IOException; 029 030/** 031 * FileLineModel は、LineModel を継承した ファイルリスト専用の 032 * LineModel の実装クラスです。 033 * 034 * FileLineModel オブジェクトには、ファイル属性(Level,File,Length,Modify,LineCnt,Biko,MD5) 035 * が設定されます。 036 * LineCnt と、MD5 は、それぞれ、計算するかどうかのフラグを設定する必要があります。 037 * 038 * ※ useLineCnt=false の場合のLength(文字数)は、File#length() メソッドで求めます。 039 * 一方、useLineCnt=true にすると、行単位に、String#length() を加算するため、 040 * 先のLength(文字数)値とは異なりますのでご注意ください。 041 * 042 * omitCmnt=true にすると、コメント部分を削除した行数と文字数を求めます。 043 * これは、/* から */ の間、// から改行までです。 044 * ただし、"(二重引用符)で囲まれた文字列は、コメントとみなしません。 045 * 046 * データの1行分を FileLineModel に割り当てます。 047 * カラム番号は、0 から始まります。カラム名よりカラム番号を求める場合に、 048 * 存在しない場合は、-1 を返します。 049 * カラム番号が -1 の場合は、処理を行いません。 050 * 051 * 注意:このクラスは、同期処理されていません。 052 * 053 * @version 4.0 054 * @author Kazuhiko Hasegawa 055 * @since JDK5.0, 056 */ 057public class FileLineModel extends LineModel { 058 // 5.7.2.1 (2014/01/17) MD5 項目追加 059 private static final String[] KEYS = new String[] { "Level","File","Length","Modify","LineCnt","Biko","MD5" }; 060 061 private static final int LEVEL = 0; 062 private static final int FILE = 1; 063 private static final int LENGTH = 2; 064 private static final int MODIFY = 3; 065 private static final int LINECNT = 4; 066 private static final int BIKO = 5; 067 private static final int MD5 = 6; // 5.7.2.1 (2014/01/17) 068 069 private final boolean useLineCnt ; 070 private final boolean useMD5 ; // 5.7.2.1 (2014/01/17) MD5 項目追加 071 private final boolean omitCmnt ; // 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する) 072 private String encode = "JISAutoDetect"; // 5.7.4.0 (2014/03/07) コメント削除時の文字数計算で利用するファイルのエンコード 073 074 /** 075 * コンストラクターです。 076 * useLineCnt=false , useMD5=false , omitCmnt=false で初期化されます。 077 * 078 * @og.rev 5.7.2.1 (2014/01/17) MD5対応 079 * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応 080 * 081 */ 082 public FileLineModel() { 083 this( false,false,false ); // 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する) 084 } 085 086 /** 087 * ラインカウントの有無を指定した、コンストラクターです。 088 * useMD5=false , omitCmnt=false で初期化されます。 089 * 090 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無 091 * @og.rev 5.7.2.1 (2014/01/17) MD5対応 092 * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応 093 * 094 * @param isLineCnt 行数カウントの使用有無 095 */ 096 public FileLineModel( final boolean isLineCnt ) { 097 this( isLineCnt,false,false ); // 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する) 098 } 099 100 /** 101 * ラインカウントの有無と、MD5計算の有無を指定した、コンストラクターです。 102 * omitCmnt=false で初期化されます。 103 * 104 * @og.rev 5.7.2.1 (2014/01/17) 新規追加(MD5対応) 105 * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応 106 * 107 * @param isLineCnt 行数カウントの使用有無 108 * @param isMD5 ファイルのMD5の使用有無 109 */ 110 public FileLineModel( final boolean isLineCnt,final boolean isMD5 ) { 111 this( isLineCnt,isMD5,false ); // 5.7.4.0 (2014/03/07) コメント除外 112 } 113 114 /** 115 * ラインカウントの有無と、MD5計算の有無と、コメント除外の可否を指定した、コンストラクターです。 116 * 117 * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する) 118 * 119 * @param isLineCnt 行数カウントの使用有無 120 * @param isMD5 ファイルのMD5の使用有無 121 * @param isOmit コメント除外の可否(true:除外する) 122 */ 123 public FileLineModel( final boolean isLineCnt,final boolean isMD5,final boolean isOmit ) { 124 // 4.3.4.4 (2009/01/01) 125 useLineCnt = isLineCnt; 126 useMD5 = isMD5; // 5.7.2.1 (2014/01/17) 127 omitCmnt = isOmit; // 5.7.4.0 (2014/03/07) 128 init( KEYS ); 129 } 130 131 /** 132 * LineModel を元に、FileLineModel を構築します。 133 * これは、一旦ファイル等にセーブされた FileLineModel 形式を 134 * 元に戻す簡易コンストラクタです。 135 * 136 * @og.rev 4.2.3.0 (2008/05/26) 新規追加 137 * @og.rev 5.7.2.1 (2014/01/17) MD5の設定処理追加 138 * 139 * @param model 元のLineModel 140 */ 141 public FileLineModel( final LineModel model ) { 142 // 4.3.4.4 (2009/01/01) 143 init( model.getNames() ); 144 145 Object[] obj = model.getValues(); 146 147 setValue( LEVEL ,Integer.valueOf( (String)obj[LEVEL] ) ); 148 setValue( FILE ,new File((String)obj[FILE]) ); 149 setValue( LENGTH ,Long.valueOf( (String)obj[LENGTH] ) ); 150 setValue( MODIFY ,(String)obj[MODIFY] ); 151 152 String cnt = (String)obj[LINECNT] ; 153 useLineCnt = cnt != null && cnt.length() > 0 && ! "null".equalsIgnoreCase( cnt ) ; 154 if( useLineCnt ) { setValue( LINECNT ,cnt ); } 155 156 setValue( BIKO ,(String)obj[BIKO] ); 157 158 // 5.7.2.1 (2014/01/17) 159 String md5Data = (String)obj[MD5] ; 160 useMD5 = md5Data != null && md5Data.length() > 0 && ! "null".equalsIgnoreCase( md5Data ) ; 161 if( useMD5 ) { setValue( MD5 ,md5Data ); } 162 163 omitCmnt = false; // 5.7.4.0 (2014/03/07) 既存の LineModel から取得できないので、強制設定します。 164 } 165 166 /** 167 * File属性値をセットします。 168 * LEVEL,FILE,LENGTH,MODIFY,LINECNT,MD5 の各属性を設定します。 169 * 170 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無 171 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 172 * @og.rev 5.7.2.1 (2014/01/17) MD5計算処理の追加 173 * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応 174 * @og.rev 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理 175 * 176 * @param level ファイルのディレクトリ階層 177 * @param file ファイルオブジェクト 178 */ 179 public void setFileVals( final int level, final File file ) { 180 setValue( LEVEL ,Integer.valueOf( level ) ); 181 setValue( FILE ,file ); 182 setValue( MODIFY ,HybsDateUtil.getDate( file.lastModified(),"yyyy/MM/dd HH:mm:ss" ) ); // 5.5.7.2 (2012/10/09) HybsDateUtil を利用する 183 184 // 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理 185 // 別にコメント除去されたファイルを作成して、それの MD5 を求める。 186 File ocFile = null; 187 if( omitCmnt && useMD5 ) { 188 try { 189 ocFile = File.createTempFile( "temp",".tmp" ); 190 ocFile.deleteOnExit(); // 一応、このメソッド内で削除しますが、念のため。 191 } 192 catch( IOException ex ) { 193 String errMsg = "コメント除外のMD5計算用 temp ファイルの作成に失敗しました。" + ex.getMessage() ; 194 throw new RuntimeException( errMsg,ex ); 195 } 196 } 197 198 if( useLineCnt || omitCmnt ) { 199// long[] cntVals = getLineCnt( file ); 200 long[] cntVals = getLineCnt( file,ocFile ); // 5.7.7.1 (2014/06/13) 出力ファイルを渡します。 201 setValue( LINECNT ,String.valueOf( cntVals[0] ) ); 202 setValue( LENGTH ,Long.valueOf( cntVals[1] ) ); 203 } 204 else { 205 setValue( LENGTH ,Long.valueOf( file.length() ) ); 206 } 207 208 // 5.7.2.1 (2014/01/17) MD5計算がtrue で、かつ、ファイルの場合、MD5 計算を行います。 209 if( useMD5 && file.isFile() ) { 210 // 5.7.7.1 (2014/06/13) omitCmnt を考慮したMD5計算 211 if( ocFile == null ) { 212 setValue( MD5 ,HybsCryptography.getMD5( file ) ); 213 } 214 else { 215 setValue( MD5 ,HybsCryptography.getMD5( ocFile ) ); 216 ocFile.delete(); 217 } 218 } 219 } 220 221 /** 222 * コメント削除時の文字数計算で利用するファイルのエンコードをセットします。 223 * 初期値:JISAutoDetect 224 * 225 * @og.rev 5.7.4.0 (2014/03/07) 新規追加 226 * 227 * @param encode コメント削除時の文字数計算で利用するファイルのエンコード 228 */ 229 public void setEncode( final String encode ) { 230 this.encode = encode; 231 } 232 233 /** 234 * File属性値をセットします。 235 * 236 * @param file ファイルオブジェクト 237 */ 238 public void setFile( final File file ) { 239 setValue( FILE,file ); 240 } 241 242 /** 243 * 備考情報属性値をセットします。 244 * 245 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無 246 * 247 * @param biko 備考情報 248 */ 249 public void setBiko( final String biko ) { 250 setValue( BIKO,biko ); 251 } 252 253 /** 254 * レベル File属性値を取得します。 255 * 256 * @return ファイルのディレクトリ階層 257 */ 258 public int getLebel() { 259 return ((Integer)getValue( LEVEL )).intValue(); 260 } 261 262 /** 263 * ファイルを取得します。 264 * 265 * @return ファイル 266 */ 267 public File getFile() { 268 return (File)getValue( FILE ); 269 } 270 271 /** 272 * ファイルサイズ File属性値を取得します。 273 * 274 * @return ファイルサイズ 275 */ 276 public long getLength() { 277 return ((Long)getValue( LENGTH )).longValue(); 278 } 279 280 /** 281 * 更新日時 File属性値を取得します。 282 * 283 * @return 更新日時(yyyy/MM/dd HH:mm:ss) 284 */ 285 public String getModify() { 286 return (String)getValue( MODIFY ); 287 } 288 289 /** 290 * MD5 File属性値を取得します。 291 * ただし、useMD5 が true でないと値は返しません。 292 * 293 * @og.rev 5.7.2.1 (2014/01/17) 新規追加(MD5対応) 294 * 295 * @return MD5の値 296 */ 297 public String getMD5() { 298 return (String)getValue( MD5 ); 299 } 300 301 /** 302 * 行数と文字数を取得します。 303 * 行数カウントとファイルの文字数カウント(バイト数ではありません)を行います。 304 * ※ useLineCnt=false の場合のLength(文字数)は、File#length() メソッドで求めます。 305 * 一方、useLineCnt=true にすると、行単位に、String#length() を加算するため、 306 * 先のLength(文字数)値とは異なりますのでご注意ください。 307 * 308 * 結果は、long型の配列で返します。[0]が行数で、[1]が文字数です。 309 * omitCmnt 属性を使用した場合は、コメント部分を削除した行数と文字数を求めます。 310 * これは、/* から */ の間、// から改行までです。 311 * ただし、"(二重引用符)で囲まれた文字列は、コメントとみなしません。 312 * 313 * @og.rev 5.7.4.0 (2014/03/07) 行数カウントとファイルの文字数カウントを行う。 314 * @og.rev 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理 315 * 316 * @param file 行数を数えるファイルオブジェクト 317 * @param ocFile omitCmnt=trueの場合に、MD5計算する時の、仮出力ファイル(nullの場合は、無視) 318 * 319 * @return long型の配列([0]が行数で、[1]が文字数) 320 */ 321// private long[] getLineCnt( final File file ) { 322 private long[] getLineCnt( final File file,final File ocFile ) { 323 long lineCnt = 0L; // 行数 324 long charCnt = 0L; // 文字数 325 326 BufferedReader reader = FileUtil.getBufferedReader( file,encode ); 327 328 // 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理 329 PrintWriter writer = null; 330 if( ocFile != null ) { writer = FileUtil.getPrintWriter( ocFile ,encode ); } 331 332 CommentLineParser clp = omitCmnt ? new CommentLineParser() : null; 333 try { 334 if( ! file.isDirectory() ) { 335 String line ; 336 while((line = reader.readLine()) != null) { 337 if( omitCmnt ) { 338 line = clp.line( line ); 339 if( line == null ) { continue; } // 戻り値が null の場合は、行として不成立 340 if( writer != null ) { writer.println( line ); } // 5.7.7.1 (2014/06/13) 341 } 342 343 lineCnt++; 344 charCnt += line.length(); 345 } 346 } 347 } 348 catch( IOException ex ) { 349 String errMsg = "ファイルカウント中に例外が発生しました。[" + file + "]" ; 350 throw new RuntimeException( errMsg,ex ); 351 } 352 finally { 353 Closer.ioClose( reader ) ; 354 Closer.ioClose( writer ) ; // 5.7.7.1 (2014/06/13) ioClose は、引数が null なら無視します。 355 } 356 357 return new long[] { lineCnt,charCnt }; 358 } 359}