View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.protocol.utils;
22  
23  import goldengate.common.digest.FilesystemBasedDigest;
24  import goldengate.common.file.DirInterface;
25  import goldengate.common.file.filesystembased.FilesystemBasedFileParameterImpl;
26  
27  import java.io.File;
28  import java.io.FileInputStream;
29  import java.io.FileNotFoundException;
30  import java.io.FileOutputStream;
31  import java.io.FilenameFilter;
32  import java.io.IOException;
33  import java.nio.channels.FileChannel;
34  
35  import openr66.protocol.configuration.Configuration;
36  import openr66.protocol.exception.OpenR66ProtocolSystemException;
37  
38  import org.jboss.netty.buffer.ChannelBuffer;
39  import org.jboss.netty.buffer.ChannelBuffers;
40  
41  /**
42   * File Utils
43   * @author Frederic Bregier
44   *
45   */
46  public class FileUtils {
47      /**
48       *
49       * @param base
50       *            in absolute
51       * @param path
52       *            path in absolute or relative
53       * @return a new String for a file from the base and the path (according to
54       *         relative or absolute path)
55       * @throws OpenR66ProtocolSystemException
56       */
57      public static String consolidatePath(String base, String path)
58              throws OpenR66ProtocolSystemException {
59          if (base == null || base.length() == 0 || path == null ||
60                  path.length() == 0) {
61              throw new OpenR66ProtocolSystemException(
62                      "base and path must not be empty");
63          }
64          // First check if the path is relative or absolute
65          String extDir = null;
66          if (path.charAt(0) == DirInterface.SEPARATORCHAR) {
67              extDir = Configuration.configuration.baseDirectory +
68                      DirInterface.SEPARATOR + path;
69          } else {
70              extDir = Configuration.configuration.baseDirectory +
71                      DirInterface.SEPARATOR + base + DirInterface.SEPARATOR +
72                      path;
73          }
74          return extDir;
75      }
76  
77      /**
78       * Copy one file to another one
79       *
80       * @param from
81       * @param to
82       * @param move
83       *            True if the copy is in fact a move operation
84       * @param append
85       *            True if the copy is in append
86       * @throws OpenR66ProtocolSystemException
87       */
88      public static void copy(File from, File to, boolean move, boolean append)
89              throws OpenR66ProtocolSystemException {
90          if (from == null || to == null) {
91              throw new OpenR66ProtocolSystemException(
92                      "Source or Destination is null");
93          }
94          File directoryTo = to.getParentFile();
95          if (createDir(directoryTo)) {
96              if (move && from.renameTo(to)) {
97                  return;
98              }
99              FileChannel fileChannelIn = getFileChannel(from, false, false);
100             if (fileChannelIn == null) {
101                 throw new OpenR66ProtocolSystemException(
102                         "Cannot read source file");
103                 // return false;
104             }
105             FileChannel fileChannelOut = getFileChannel(to, true, append);
106             if (fileChannelOut == null) {
107                 try {
108                     fileChannelIn.close();
109                 } catch (IOException e) {
110                 }
111                 throw new OpenR66ProtocolSystemException(
112                         "Cannot write destination file");
113             }
114             if (write(fileChannelIn, fileChannelOut) > 0) {
115                 if (move) {
116                     // do not test the delete
117                     from.delete();
118                 }
119                 return;
120             }
121             throw new OpenR66ProtocolSystemException("Cannot copy");
122         }
123         throw new OpenR66ProtocolSystemException(
124                 "Cannot access to parent dir of destination");
125     }
126 
127     /**
128      * Copy a group of files to a directory
129      *
130      * @param from
131      * @param directoryTo
132      * @param move
133      *            True if the copy is in fact a move operation
134      * @return the group of copy files or null (partially or totally) if an
135      *         error occurs
136      * @throws OpenR66ProtocolSystemException
137      */
138     public static File[] copy(File[] from, File directoryTo, boolean move)
139             throws OpenR66ProtocolSystemException {
140         if (from == null || directoryTo == null) {
141             return null;
142         }
143         File[] to = null;
144         if (createDir(directoryTo)) {
145             to = new File[from.length];
146             for (int i = 0; i < from.length; i ++) {
147                 try {
148                     to[i] = copyToDir(from[i], directoryTo, move);
149                 } catch (OpenR66ProtocolSystemException e) {
150                     throw e;
151                 }
152             }
153         }
154         return to;
155     }
156 
157     /**
158      * Copy one file to a directory
159      *
160      * @param from
161      * @param directoryTo
162      * @param move
163      *            True if the copy is in fact a move operation
164      * @return The copied file or null if an error occurs
165      * @throws OpenR66ProtocolSystemException
166      */
167     public static File copyToDir(File from, File directoryTo, boolean move)
168             throws OpenR66ProtocolSystemException {
169         if (from == null || directoryTo == null) {
170             throw new OpenR66ProtocolSystemException(
171                     "Source or Destination is null");
172         }
173         if (createDir(directoryTo)) {
174             File to = new File(directoryTo, from.getName());
175             if (move && from.renameTo(to)) {
176                 return to;
177             }
178             FileChannel fileChannelIn = getFileChannel(from, false, false);
179             if (fileChannelIn == null) {
180                 throw new OpenR66ProtocolSystemException(
181                         "Cannot read source file");
182             }
183             FileChannel fileChannelOut = getFileChannel(to, true, false);
184             if (fileChannelOut == null) {
185                 try {
186                     fileChannelIn.close();
187                 } catch (IOException e) {
188                 }
189                 throw new OpenR66ProtocolSystemException(
190                         "Cannot write destination file");
191             }
192             if (write(fileChannelIn, fileChannelOut) > 0) {
193                 if (move) {
194                     // do not test the delete
195                     from.delete();
196                 }
197                 return to;
198             }
199             throw new OpenR66ProtocolSystemException(
200                     "Cannot write destination file");
201         }
202         throw new OpenR66ProtocolSystemException(
203                 "Cannot access to parent dir of destination");
204     }
205 
206     /**
207      * Create the directory associated with the File as path
208      *
209      * @param directory
210      * @return True if created, False else.
211      */
212     public static boolean createDir(File directory) {
213         if (directory == null) {
214             return false;
215         }
216         if (directory.isDirectory()) {
217             return true;
218         }
219         return directory.mkdirs();
220     }
221 
222     /**
223      * Delete physically the file
224      *
225      * @param file
226      * @return True if OK, else if not (or if the file never exists).
227      */
228     public static boolean delete(File file) {
229         if (!file.exists()) {
230             return true;
231         }
232         return file.delete();
233     }
234 
235     /**
236      * Delete the directory associated with the File as path if empty
237      *
238      * @param directory
239      * @return True if deleted, False else.
240      */
241     public static boolean deleteDir(File directory) {
242         if (directory == null) {
243             return true;
244         }
245         if (!directory.exists()) {
246             return true;
247         }
248         if (!directory.isDirectory()) {
249             return false;
250         }
251         return directory.delete();
252     }
253 
254     /**
255      * Delete physically the file but when the JVM exits (useful for temporary
256      * file)
257      *
258      * @param file
259      */
260     public static void deleteOnExit(File file) {
261         if (!file.exists()) {
262             return;
263         }
264         file.deleteOnExit();
265     }
266 
267     /**
268      * Delete the directory and its subdirs associated with the File as path if
269      * empty
270      *
271      * @param directory
272      * @return True if deleted, False else.
273      */
274     public static boolean deleteRecursiveDir(File directory) {
275         if (directory == null) {
276             return true;
277         }
278         boolean retour = true;
279         if (!directory.exists()) {
280             return true;
281         }
282         if (!directory.isDirectory()) {
283             return false;
284         }
285         File[] list = directory.listFiles();
286         if (list == null || list.length == 0) {
287             list = null;
288             retour = directory.delete();
289             return retour;
290         }
291         int len = list.length;
292         for (int i = 0; i < len; i ++) {
293             if (list[i].isDirectory()) {
294                 if (!deleteRecursiveFileDir(list[i])) {
295                     retour = false;
296                 }
297             } else {
298                 retour = false;
299             }
300         }
301         list = null;
302         if (retour) {
303             retour = directory.delete();
304         }
305         return retour;
306     }
307 
308     /**
309      * Delete the directory and its subdirs associated with the File dir if
310      * empty
311      *
312      * @param dir
313      * @return True if deleted, False else.
314      */
315     private static boolean deleteRecursiveFileDir(File dir) {
316         if (dir == null) {
317             return true;
318         }
319         boolean retour = true;
320         if (!dir.exists()) {
321             return true;
322         }
323         File[] list = dir.listFiles();
324         if (list == null || list.length == 0) {
325             list = null;
326             return dir.delete();
327         }
328         int len = list.length;
329         for (int i = 0; i < len; i ++) {
330             if (list[i].isDirectory()) {
331                 if (!deleteRecursiveFileDir(list[i])) {
332                     retour = false;
333                 }
334             } else {
335                 retour = false;
336                 list = null;
337                 return retour;
338             }
339         }
340         list = null;
341         if (retour) {
342             retour = dir.delete();
343         }
344         return retour;
345     }
346 
347     /**
348      * @param _FileName
349      * @param _Path
350      * @return true if the file exist in the specified path
351      */
352     public static boolean FileExist(String _FileName, String _Path) {
353         boolean exist = false;
354         String fileString = _Path + File.separator + _FileName;
355         File file = new File(fileString);
356         if (file.exists()) {
357             exist = true;
358         }
359         return exist;
360     }
361 
362     /**
363      * Returns the FileChannel in Out MODE (if isOut is True) or in In MODE (if
364      * isOut is False) associated with the file. In out MODE, it can be in
365      * append MODE.
366      *
367      * @param isOut
368      * @param append
369      * @return the FileChannel (OUT or IN)
370      * @throws OpenR66ProtocolSystemException
371      */
372     private static FileChannel getFileChannel(File file, boolean isOut,
373             boolean append) throws OpenR66ProtocolSystemException {
374         FileChannel fileChannel = null;
375         try {
376             if (isOut) {
377                 FileOutputStream fileOutputStream = new FileOutputStream(file
378                         .getPath(), append);
379                 fileChannel = fileOutputStream.getChannel();
380                 if (append) {
381                     // Bug in JVM since it does not respect the API (position
382                     // should be set as length)
383                     try {
384                         fileChannel.position(file.length());
385                     } catch (IOException e) {
386                     }
387                 }
388             } else {
389                 if (!file.exists()) {
390                     throw new OpenR66ProtocolSystemException(
391                             "File does not exist");
392                 }
393                 FileInputStream fileInputStream = new FileInputStream(file
394                         .getPath());
395                 fileChannel = fileInputStream.getChannel();
396             }
397         } catch (FileNotFoundException e) {
398             throw new OpenR66ProtocolSystemException("File not found", e);
399         }
400         return fileChannel;
401     }
402 
403     /**
404      * Get the list of files from a given directory
405      *
406      * @param directory
407      * @return the list of files (as an array)
408      */
409     public static File[] getFiles(File directory) {
410         if (directory == null || !directory.isDirectory()) {
411             return null;
412         }
413         return directory.listFiles();
414     }
415 
416     /**
417      * Get the list of files from a given directory and a filter
418      *
419      * @param directory
420      * @param filter
421      * @return the list of files (as an array)
422      */
423     public static File[] getFiles(File directory, FilenameFilter filter) {
424         if (directory == null || !directory.isDirectory()) {
425             return null;
426         }
427         return directory.listFiles(filter);
428     }
429 
430     /**
431      * Calculates and returns the hash of the contents of the given file.
432      *
433      * @param f
434      *            FileInterface to hash
435      * @return the hash from the given file
436      * @throws OpenR66ProtocolSystemException
437      **/
438     public static String getHash(File f) throws OpenR66ProtocolSystemException {
439         try {
440             return FilesystemBasedDigest.getHex(FilesystemBasedDigest.getHash(f,
441                     FilesystemBasedFileParameterImpl.useNio, Configuration.configuration.digest));
442         } catch (IOException e) {
443             throw new OpenR66ProtocolSystemException(e);
444         }
445     }
446 
447     /**
448      *
449      * @param buffer
450      * @return the hash from the given Buffer
451      */
452     public static ChannelBuffer getHash(ChannelBuffer buffer) {
453         byte[] newkey;
454         try {
455             newkey = FilesystemBasedDigest.getHash(buffer, Configuration.configuration.digest);
456         } catch (IOException e) {
457             return ChannelBuffers.EMPTY_BUFFER;
458         }
459         return ChannelBuffers.wrappedBuffer(newkey);
460     }
461 
462     /**
463      * Write one fileChannel to another one. Close the fileChannels
464      *
465      * @param fileChannelIn
466      *            source of file
467      * @param fileChannelOut
468      *            destination of file
469      * @return The size of copy if is OK
470      * @throws AtlasIoException
471      */
472     private static long write(FileChannel fileChannelIn,
473             FileChannel fileChannelOut) throws OpenR66ProtocolSystemException {
474         if (fileChannelIn == null) {
475             if (fileChannelOut != null) {
476                 try {
477                     fileChannelOut.close();
478                 } catch (IOException e) {
479                 }
480             }
481             throw new OpenR66ProtocolSystemException("FileChannelIn is null");
482         }
483         if (fileChannelOut == null) {
484             try {
485                 fileChannelIn.close();
486             } catch (IOException e) {
487             }
488             throw new OpenR66ProtocolSystemException("FileChannelOut is null");
489         }
490         long size = 0;
491         long transfert = 0;
492         try {
493             transfert = fileChannelOut.position();
494             size = fileChannelIn.size();
495             int chunkSize = 8192;
496             while (transfert < size) {
497                 if (chunkSize < size - transfert) {
498                     chunkSize = (int) (size - transfert);
499                 }
500                 transfert += fileChannelOut.transferFrom(fileChannelIn, transfert, chunkSize);
501             }
502         } catch (IOException e) {
503             try {
504                 fileChannelOut.close();
505                 fileChannelIn.close();
506             } catch (IOException e1) {
507             }
508             throw new OpenR66ProtocolSystemException(
509                     "An error during copy occurs", e);
510         }
511         try {
512             fileChannelOut.close();
513             fileChannelIn.close();
514         } catch (IOException e) {// Close error can be ignored
515         }
516         boolean retour = size == transfert;
517         if (!retour) {
518             throw new OpenR66ProtocolSystemException("Copy is not complete: " +
519                     transfert + " bytes instead of " + size + " original bytes");
520         }
521         return size;
522     }
523 }