View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, 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 Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.utility;
21  
22  
23  import org.waarp.common.command.exception.Reply550Exception;
24  import org.waarp.common.file.FileUtils;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  import org.waarp.common.logging.WaarpSlf4JLoggerFactory;
28  
29  import java.io.File;
30  import java.io.FileInputStream;
31  import java.io.FileNotFoundException;
32  import java.io.FileOutputStream;
33  import java.io.IOException;
34  import java.util.ArrayList;
35  import java.util.List;
36  import java.util.regex.Pattern;
37  
38  /**
39   * Description: Converts Unix files to Dos and vice versa
40   */
41  public class FileConvert extends Thread {
42    /**
43     * Internal Logger
44     */
45    private static volatile WaarpLogger logger;
46  
47    private final boolean unix2dos;
48    private final boolean recursive;
49    private File tmpDir = new File(System.getProperty("java.io.tmpdir"));
50    private final List<File> files;
51  
52    /**
53     * @param files list of files
54     * @param unix2dos True for Unix2Dos, False for Dos2Unix
55     * @param recursive True for Recursive from files, else unitary
56     *     files
57     * @param tmpDir if not null, specific tmp directory
58     */
59    public FileConvert(final List<File> files, final boolean unix2dos,
60                       final boolean recursive, final File tmpDir) {
61      if (logger == null) {
62        logger = WaarpLoggerFactory.getLogger(FileConvert.class);
63      }
64      this.files = files;
65      this.unix2dos = unix2dos;
66      this.recursive = recursive;
67      if (tmpDir != null) {
68        this.tmpDir = tmpDir;
69      }
70    }
71  
72    /**
73     * Direct call
74     *
75     * @param args
76     */
77    public static void main(final String[] args) {
78      WaarpLoggerFactory.setDefaultFactoryIfNotSame(
79          new WaarpSlf4JLoggerFactory(null));
80      if (logger == null) {
81        logger = WaarpLoggerFactory.getLogger(FileConvert.class);
82      }
83  
84      final ArrayList<File> files = new ArrayList<File>();
85      boolean unix2dos = false;
86      boolean dos2unix = false;
87      boolean recursive = false;
88      File tmpDir = null;
89      for (int i = 0; i < args.length; i++) {
90        if (Pattern.compile("^-(u|-unix2dos|-unixtodos)$",
91                            Pattern.CASE_INSENSITIVE).matcher(args[i])
92                   .matches()) {
93          unix2dos = true;
94        } else if (Pattern.compile("^-(d|-dos2unix|-dostounix)$",
95                                   Pattern.CASE_INSENSITIVE).matcher(args[i])
96                          .matches()) {
97          dos2unix = true;
98        } else if (Pattern.compile("^-(r|-recursive)$", Pattern.CASE_INSENSITIVE)
99                          .matcher(args[i]).matches()) {
100         recursive = true;
101       } else if (Pattern.compile("^-(t|-temporary)$", Pattern.CASE_INSENSITIVE)
102                         .matcher(args[i]).matches()) {
103         tmpDir = new File(args[++i]);
104       } else {
105         files.add(new File(args[i]));
106       }
107     }
108     if (unix2dos && dos2unix) {
109       syntax();
110       System.exit(1);//NOSONAR
111     }
112     if (!unix2dos && !dos2unix) {
113       syntax();
114       System.exit(1);//NOSONAR
115     }
116     final FileConvert fileConvert =
117         new FileConvert(files, unix2dos, recursive, tmpDir);
118     fileConvert.run();//NOSONAR
119   }
120 
121   /**
122    * Use parameters given in instantiation
123    */
124   @Override
125   public void run() {
126     if (files == null) {
127       return;
128     }
129     for (final File file : files) {
130       if (file.isDirectory()) {
131         if (recursive) {
132           recursive(file);
133         }
134       } else {
135         convert(file, unix2dos);
136       }
137     }
138   }
139 
140   private void recursive(final File directory) {
141     final File[] listFiles = directory.listFiles();
142     if (listFiles != null) {
143       for (final File file : listFiles) {
144         if (file.isDirectory()) {
145           recursive(file);
146         } else {
147           convert(file, unix2dos);
148         }
149       }
150     }
151   }
152 
153   private boolean copyFile(final File source, final File destination) {
154     try {
155       FileUtils.copy(source, destination, false, false);
156       return true;
157     } catch (final Reply550Exception e) {
158       logger.error("FileConvert copy back in error: {}", e.getMessage());
159       return false;
160     }
161   }
162 
163   /**
164    * Convert Unix2Dos or Dos2Unix file in place, according to second argument
165    *
166    * @param input File to change
167    * @param unix2dos True for UnixToDos, False for DosToUnix
168    *
169    * @return True if OK
170    */
171   public final boolean convert(final File input, final boolean unix2dos) {
172     if (unix2dos) {
173       logger.info("unix2Dos conversion of '{}'... ", input);
174     } else {
175       logger.info("dos2Unix conversion of '{}'... ", input);
176     }
177     FileInputStream fis = null;
178     FileOutputStream fos = null;
179     File tmpFile = null;
180     try {
181       fis = new FileInputStream(input);
182       tmpFile =
183           File.createTempFile("FileConevrt_" + input.getName(), null, tmpDir);
184       fos = new FileOutputStream(tmpFile);
185       if (unix2dos) {
186         byte pb = -1;
187         byte b;
188         while ((b = (byte) fis.read()) != -1) {
189           if (b == 10 && pb != 13) {
190             fos.write((byte) 13);
191           }
192           fos.write(b);
193           pb = b;
194         }
195       } else {
196         byte b;
197         byte nb;
198         while ((b = (byte) fis.read()) != -1) {
199           if (b == 13) {
200             nb = (byte) fis.read();
201             if (nb == -1) {
202               fos.write(b);
203             } else {
204               if (nb != 10) {
205                 fos.write(b);
206               }
207               fos.write(nb);
208             }
209           } else {
210             fos.write(b);
211           }
212         }
213       }
214       final boolean result = copyFile(tmpFile, input);
215       if (result) {
216         logger.info("done.");
217       } else {
218         logger.error("FileConvert in error during final copy: " + input + ':' +
219                      unix2dos);
220       }
221       return result;
222     } catch (final FileNotFoundException e) {
223       logger.error("FileConvert in error: " + input + ':' + unix2dos + ": {}",
224                    e.getMessage());
225       return false;
226     } catch (final IOException e) {
227       logger.error("FileConvert in error: " + input + ':' + unix2dos + ": {}",
228                    e.getMessage());
229       return false;
230     } finally {
231       if (tmpFile != null) {
232         if (!tmpFile.delete()) {
233           logger.debug("Cannot delete temp file");
234         }
235       }
236       FileUtils.close(fis);
237       FileUtils.close(fos);
238     }
239   }
240 
241   private static void syntax() {
242     logger.error(
243         "Syntax: Covnert -(u|-nix2dos|-unixtodos) | -(d|-dos2unix|-dostounix) -(t|-temporary) directory  -(r|-recursive) file directory");
244   }
245 
246 }