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