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.Argument;
019 import org.opengion.fukurou.util.FileUtil;
020 import org.opengion.fukurou.util.Closer ;
021 import org.opengion.fukurou.util.LogWriter;
022
023 import java.util.Map ;
024 import java.util.LinkedHashMap ;
025
026 import java.io.File;
027 import java.io.PrintWriter;
028 import java.io.BufferedReader;
029 import java.io.IOException;
030
031 /**
032 * Process_FileCopy は、上流から受け取っã�?FileLineModel をå?ç�?�™るã?
033 * ChainProcess インターフェースの実è£?‚¯ラスですã?
034 *
035 * 上流から受け取っã�?FileLineModel の ファイルから、inPath の共通パス
036 * 以下ã?ファイルをã?outPath の共通パス以下にコピã?しますã?
037 * コピã?の種類ã?、バイナリかã?ãƒ?‚ストで、テキストã?場合ã?、エンコーãƒ?
038 * 変換も行うことが可能ですã?
039 * inPath と outPath が同じã?またã?、outPath が未設定ã?場合ã?、å?力と出力が
040 * 同じですã?で、è?åˆ??身のエンコード変換処ç�?‚’行うことになりますã?
041 *
042 * コピã?されるファイルのファイル名ã?、å?力ファイル名と同ä¸?�§すã?保存される
043 * フォルãƒ?�Œ異なりますã?(同ä¸?�«することも可能ですã?)
044 *
045 * 上流ã?ロセスでは、Name 属æ?として、ã?File』を持ち、å?は、Fileオブジェクãƒ?
046 * である、Process_FileSearch を使用するのがã?便利ですã?それ以外ã?クラスã‚?
047 * 使用する場合でもã?Name属æ?と、File オブジェクトを持つ LineModel を受け渡ã�?
048 * できれば、使用可能ですã?
049 *
050 * 引数æ–?—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション("") で括って下さã�??
051 * 引数æ–?—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に
052 * 繋げてくださいã€?
053 *
054 * @og.formSample
055 * Process_FileCopy -inPath=入力å?通パス -inEncode=Windows-31J -outPath=出力å?通パス -outEncode=UTF-8
056 *
057 * -inPath=入力å?通パス ?š上流で検索されたファイルパスの共通部åˆ?
058 * [-inEncode=入力エンコーãƒ? ] ?šå?力ファイルのエンコードタイãƒ?
059 * [-outPath=出力å?通パス ] ?šå?力するファイルパスの共通部åˆ?
060 * [-outEncode=出力エンコーãƒ? ] ?šå?力ファイルのエンコードタイãƒ?
061 * [-binary=[false/true] ] ?štrueは、バイナリファイルのコピã?(初期値:false)
062 * [-changeCrLf=[false/true] ] ?štrueは、バイナリファイルのコピã?時にCR+LFに変換しまã�?初期値:false)
063 * [-keepTimeStamp=[false/true]] ?štrueは、コピã?å…??ファイルのタイãƒ?‚¹タンプで作æ?しまã�?初期値:false)
064 * [-display=[false/true] ] ?štrueは、コピã?状況を表示しまã�?初期値:false)
065 *
066 * @version 4.0
067 * @author Kazuhiko Hasegawa
068 * @since JDK5.0,
069 */
070 public class Process_FileCopy extends AbstractProcess implements ChainProcess {
071 private File tempFile = null;
072
073 private String inPath = null;
074 private String inEncode = null;
075 private String outPath = null;
076 private String outEncode = null;
077 private boolean binary = false;
078 private boolean changeCrLf = false; // 4.2.2.0 (2008/05/10)
079 private boolean keepTimeStamp = false; // 5.1.5.0 (2010/04/01)
080 private boolean display = false;
081
082 private int inPathLen = 0;
083 private boolean isEquals = false;
084 private int inCount = 0;
085
086 private static final Map<String,String> mustProparty ; // ?»プロパティ?½å¿??チェãƒ?‚¯用 Map
087 private static final Map<String,String> usableProparty ; // ?»プロパティ?½整合æ?チェãƒ?‚¯ Map
088
089 static {
090 mustProparty = new LinkedHashMap<String,String>();
091 mustProparty.put( "inPath", "コピã?å…??ファイル基準パス" );
092
093 usableProparty = new LinkedHashMap<String,String>();
094 usableProparty.put( "inEncode", "コピã?å…??ファイルのエンコードタイãƒ? );
095 usableProparty.put( "outPath", "コピã?先ã?ファイル基準パス" );
096 usableProparty.put( "outEncode", "コピã?先ã?ファイルのエンコードタイãƒ? );
097 usableProparty.put( "binary", "trueは、バイナリファイルをコピã?しまã�?初期値:false)" );
098 usableProparty.put( "changeCrLf", "trueは、バイナリファイルのコピã?時にCR+LFに変換しまã�?初期値:false)" ); // 4.2.2.0 (2008/05/10)
099 usableProparty.put( "keepTimeStamp", "trueは、コピã?å…??ファイルのタイãƒ?‚¹タンプで作æ?しまã�?初期値:false)" ); // 5.1.5.0 (2010/04/01)
100 usableProparty.put( "display", "trueは、コピã?状況を表示しまã�?初期値:false)" );
101 }
102
103 /**
104 * ãƒ?ƒ•ォルトコンストラクターã€?
105 * こã?クラスは、動çš?½œæ?されますã?ãƒ?ƒ•ォルトコンストラクターでã€?
106 * super クラスに対して、å¿?¦�な初期化を行っておきますã?
107 *
108 */
109 public Process_FileCopy() {
110 super( "org.opengion.fukurou.process.Process_FileCopy",mustProparty,usableProparty );
111 }
112
113 /**
114 * プロセスの初期化を行いますã?初めにä¸?º¦ã�?�‘、呼び出されますã?
115 * 初期処ç�?ファイルオープンã€?¼¤?¢オープンç?に使用しますã?
116 *
117 * @og.rev 4.2.2.0 (2008/05/10) changeCrLf 属æ?対å¿?
118 * @og.rev 5.1.5.0 (2010/04/01) keepTimeStamp 属æ?の追åŠ?
119 *
120 * @param paramProcess ãƒ??タベã?スの接続å?æƒ??などを持ってã�?‚‹オブジェクãƒ?
121 */
122 public void init( final ParamProcess paramProcess ) {
123 Argument arg = getArgument();
124
125 inPath = arg.getProparty("inPath" );
126 outPath = arg.getProparty("outPath" );
127 inEncode = arg.getProparty("inEncode" ,System.getProperty("file.encoding"));
128 outEncode = arg.getProparty("outEncode",System.getProperty("file.encoding"));
129 binary = arg.getProparty("binary" ,binary);
130 changeCrLf = arg.getProparty("changeCrLf" ,changeCrLf); // 4.2.2.0 (2008/05/10)
131 keepTimeStamp = arg.getProparty("keepTimeStamp" ,keepTimeStamp); // 5.1.5.0 (2010/04/01)
132 display = arg.getProparty("display",display);
133
134 inPathLen = inPath.length();
135
136 // 入力と出力が同じかï¼?
137 isEquals = outPath == null || inPath.equalsIgnoreCase( outPath );
138
139 if( binary ) {
140 // 4.2.2.0 (2008/05/10) 判定ミスの修正
141 if( ! inEncode.equalsIgnoreCase( outEncode ) ) {
142 String errMsg = "バイナリコピã?時には、å?出力ã?エンコードã?同じå¿?¦�がありますã?" + CR
143 + " inEncode=[" + inEncode + "] , outEncode=[" + outEncode + "]" ;
144 throw new RuntimeException( errMsg );
145 }
146 if( isEquals ) {
147 String errMsg = "入出力が同じファイルのバイナリコピã?はできませんã€? + CR
148 + " inPath=[" + inPath + "] , outPath=[" + outPath + "]" ;
149 throw new RuntimeException( errMsg );
150 }
151 }
152
153 // 入力と出力が同じ場合ã?、中間ファイルを作æ?しますã?
154 if( isEquals ) {
155 try {
156 tempFile = File.createTempFile( "X", ".tmp", new File( outPath ) );
157 tempFile.deleteOnExit();
158 }
159 catch( IOException ex ) {
160 String errMsg = "中間ファイル作æ?でエラーが発生しましたã€? + CR
161 + " outPath=[" + outPath + "]" ;
162 throw new RuntimeException( errMsg,ex );
163 }
164 }
165 }
166
167 /**
168 * プロセスの終äº?‚’行いますã?æœ?¾Œにä¸?º¦ã�?�‘、呼び出されますã?
169 * 終äº??ç�?ファイルクローズã€?¼¤?¢クローズç?に使用しますã?
170 *
171 * @param isOK トã?タルで、OKã�?�£たかどã�?�‹[true:成功/false:失敗]
172 */
173 public void end( final boolean isOK ) {
174 tempFile = null;
175 }
176
177 /**
178 * 引数の LineModel をå?ç�?�™るメソãƒ?ƒ‰ですã?
179 * 変換処ç�?¾Œã? LineModel を返しますã?
180 * 後続å?ç�?‚’行わなã�??å�?ãƒ??タのフィルタリングを行う場å�?はã€?
181 * null ãƒ??タを返しますã?つまりã?null ãƒ??タは、後続å?ç�?‚’行わなã�?
182 * フラグの代わりにも使用してã�?�¾すã?
183 * なおã?変換処ç�?¾Œã? LineModel と、オリジナルの LineModel がã?
184 * 同ä¸?�‹、コピã?(クローン)かã?、各処ç�?ƒ¡ソãƒ?ƒ‰å†?�§決めてã�?�¾すã?
185 * ドキュメントに明記されてã�?�ªã�??合ã?、副作用が問題になるå?合ã?ã€?
186 * å�??ç�?�”とに自åˆ?�§コピã?(クローン)して下さã�??
187 *
188 * @og.rev 4.0.0.0 (2007/11/28) メソãƒ?ƒ‰の戻りå?をチェãƒ?‚¯しますã?
189 * @og.rev 4.2.2.0 (2008/05/10) changeCrLf 属æ?対å¿?
190 * @og.rev 4.2.3.0 (2008/05/26) LineModel ã�?FileLineModel でなã�??合ã?処ç�?
191 * @og.rev 5.1.5.0 (2010/04/01) keepTimeStamp 属æ?の追åŠ?
192 * @og.rev 5.1.6.0 (2010/05/01) changeCrLf 属æ?がã?.FileUtil#changeCrLfcopy メソãƒ?ƒ‰への移動に伴ã�?¯¾å¿?
193 *
194 * @param data オリジナルのLineModel
195 *
196 * @return 処ç�?¤‰換後ã?LineModel
197 */
198 public LineModel action( final LineModel data ) {
199 inCount++ ;
200 final FileLineModel fileData ;
201 if( data instanceof FileLineModel ) {
202 fileData = (FileLineModel)data ;
203 }
204 else {
205 // LineModel ã�?FileLineModel でなã�??合ã?オブジェクトを作æ?しますã?
206 fileData = new FileLineModel( data );
207 // String errMsg = "ãƒ??タã�?FileLineModel オブジェクトではありませんã€? + CR ;
208 // throw new RuntimeException( errMsg );
209 }
210
211 File inFile = fileData.getFile() ;
212 if( ! inFile.isFile() ) {
213 if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
214 return data;
215 }
216
217 // ファイル名を作æ?しますã?
218 // ファイル名ã?、引数ファイルå�?から、inPath を引き、outPath を加えますã?
219 File outFile = new File( outPath, inFile.getAbsolutePath().substring( inPathLen ) );
220 fileData.setFile( outFile );
221
222 // if( display ) { println( inFile + " => " + outFile ); }
223
224 // 入出力が異なるå?å�?
225 if( !isEquals ) {
226 tempFile = outFile;
227 File parent = outFile.getParentFile();
228 if( parent != null && ! parent.exists() && !parent.mkdirs() ) {
229 String errMsg = "æ‰?®šã?フォルãƒ?�Œ作æ?できませんでしたã€?" + parent + "]" ;
230 throw new RuntimeException( errMsg );
231 }
232 }
233
234 if( binary ) {
235 // FileUtil.copy( inFile,tempFile );
236 // FileUtil.copy( inFile,tempFile,changeCrLf ); // 4.2.2.0 (2008/05/10)
237 // 5.1.6.0 (2010/05/01) changeCrLfcopy 対å¿?
238 if( changeCrLf ) { FileUtil.changeCrLfcopy( inFile,tempFile ); }
239 else { FileUtil.copy( inFile,tempFile,keepTimeStamp ); }
240 }
241 else {
242 BufferedReader reader = FileUtil.getBufferedReader( inFile ,inEncode );
243 PrintWriter writer = FileUtil.getPrintWriter( tempFile ,outEncode );
244
245 try {
246 String line1;
247 while((line1 = reader.readLine()) != null) {
248 writer.println( line1 );
249 }
250 }
251 catch( IOException ex ) {
252 String errMsg = "ファイルコピã?中に例外が発生しましたã€?" + data.getRowNo() + "]件目" + CR
253 + " inFile=[" + inFile + "] , tempFile=[" + tempFile + "]" ;
254 throw new RuntimeException( errMsg,ex );
255 }
256 finally {
257 Closer.ioClose( reader ) ;
258 Closer.ioClose( writer ) ;
259 }
260 }
261
262 if( isEquals ) {
263 if( !outFile.delete() ) {
264 String errMsg = "æ‰?®šã?ファイルを削除できませんでしたã€?" + outFile + "]" ;
265 throw new RuntimeException( errMsg );
266 }
267
268 if( !tempFile.renameTo( outFile ) ) {
269 String errMsg = "æ‰?®šã?ファイルをリネã?ãƒ?�§きませんでしたã€?" + tempFile + "]" ;
270 throw new RuntimeException( errMsg );
271 }
272 }
273
274 // 5.1.5.0 (2010/04/01) keepTimeStamp 属æ?の追åŠ?
275 if( keepTimeStamp ) {
276 if( !outFile.setLastModified( inFile.lastModified() ) ) {
277 String errMsg = "lastModified 時間の設定が、できませんでしたã€?" + outFile + "]" ;
278 throw new RuntimeException( errMsg );
279 }
280 }
281
282 if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
283 return data ;
284 }
285
286 /**
287 * プロセスの処ç�?µ�果のレポã?ト表現を返しますã?
288 * 処ç�??ログラãƒ?��、å?力件数、å?力件数などのæƒ??ですã?
289 * こã?æ–?—å?をそのまま、標準å?力に出すことで、結果レポã?トと出来るよã�?�ª
290 * 形式で出してくださいã€?
291 *
292 * @return 処ç�?µ�果のレポã?ãƒ?
293 */
294 public String report() {
295 String report = "[" + getClass().getName() + "]" + CR
296 + TAB + "Copy Count : " + inCount + CR
297 + TAB + "inPath : " + inPath + CR
298 + TAB + "inEncode : " + inEncode + CR
299 + TAB + "outPath : " + outPath + CR
300 + TAB + "outEncode : " + outEncode + CR
301 + TAB + "binary : " + binary ;
302
303 return report ;
304 }
305
306 /**
307 * こã?クラスの使用方法を返しますã?
308 *
309 * @return こã?クラスの使用方æ³?
310 */
311 public String usage() {
312 StringBuilder buf = new StringBuilder();
313
314 buf.append( "Process_FileCopy は、上流から受け取っã�?FileLineModelをå?ç�?�™るã?" ).append( CR );
315 buf.append( "ChainProcess インターフェースの実è£?‚¯ラスですã?" ).append( CR );
316 buf.append( CR );
317 buf.append( "上流から受け取っã�?FileLineModel の ファイルから、inPath の共通パス" ).append( CR );
318 buf.append( "以下ã?ファイルをã?outPath の共通パス以下にコピã?しますã?" ).append( CR );
319 buf.append( "コピã?の種類ã?、バイナリかã?ãƒ?‚ストで、テキストã?場合ã?、エンコーãƒ? ).append( CR );
320 buf.append( "変換も行うことが可能ですã?" ).append( CR );
321 buf.append( "inPath と outPath が同じã?またã?、outPath が未設定ã?場合ã?、å?力と出力が" ).append( CR );
322 buf.append( "同じですã?で、è?åˆ??身のエンコード変換処ç�?‚’行うことになりますã?" ).append( CR );
323 buf.append( CR );
324 buf.append( "コピã?されるファイルのファイル名ã?、å?力ファイル名と同ä¸?�§すã?保存される" ).append( CR );
325 buf.append( "フォルãƒ?�Œ異なりますã?(同ä¸?�«することも可能ですã?)" ).append( CR );
326 buf.append( CR );
327 buf.append( "上流ã?ロセスでは、Name 属æ?として、ã?File』を持ち、å?は、Fileオブジェクãƒ? ).append( CR );
328 buf.append( "である、Process_FileSearch を使用するのがã?便利ですã?それ以外ã?クラスã‚? ).append( CR );
329 buf.append( "使用する場合でもã?Name属æ?と、File オブジェクトを持つ LineModel を受け渡ã�? ).append( CR );
330 buf.append( "できれば、使用可能ですã?" ).append( CR );
331 buf.append( CR );
332 buf.append( "引数æ–?—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション(\"\") で括って下さã�??" ).append( CR );
333 buf.append( "引数æ–?—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に" ).append( CR );
334 buf.append( "繋げてくださいã€? ).append( CR );
335 buf.append( CR ).append( CR );
336
337 buf.append( getArgument().usage() ).append( CR );
338
339 return buf.toString();
340 }
341
342 /**
343 * こã?クラスは、main メソãƒ?ƒ‰から実行できませんã€?
344 *
345 * @param args コマンド引数配å?
346 */
347 public static void main( final String[] args ) {
348 LogWriter.log( new Process_FileCopy().usage() );
349 }
350 }