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.openr66.context.task;
21  
22  import org.waarp.common.logging.WaarpLogger;
23  import org.waarp.common.logging.WaarpLoggerFactory;
24  import org.waarp.common.transcode.CharsetsUtil;
25  import org.waarp.common.utility.FileConvert;
26  import org.waarp.openr66.context.ErrorCode;
27  import org.waarp.openr66.context.R66Result;
28  import org.waarp.openr66.context.R66Session;
29  import org.waarp.openr66.database.data.DbTaskRunner;
30  import org.waarp.openr66.protocol.configuration.Configuration;
31  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
32  
33  import java.io.File;
34  
35  /**
36   * Transcode the current file from one Charset to another Charset as
37   * specified<br>
38   * <br>
39   * Arguments are:<br>
40   * -dos2unix or -unix2dos (only one) ; optional argument, but if present -from
41   * and -to might be omitted;<br>
42   * -from charset<br>
43   * -to charset<br>
44   * -newfile newfilename ; optional argument ; if not used, will be current
45   * filename.extension ; if used,
46   * extension is ignored<br>
47   * -extension extension ; optional argument ; if not used, will be
48   * filename.transcode<br>
49   * <br>
50   * A convenient method (from Waarp Common) allows to list in html (-html), csv
51   * (-csv) or text format (-text)
52   * all the supported Charsets from your JVM. To use it, run the following
53   * command:<br>
54   * java -cp WaarpCommon-1.2.7.jar org.waarp.common.transcode.CharsetsUtil [-csv
55   * | -html | -text ]<br>
56   * <br>
57   * It could also be used as a test of transcode outside R66:<br>
58   * java -cp WaarpCommon-1.2.7.jar org.waarp.common.transcode.CharsetsUtil -from
59   * fromFilename fromCharset -to
60   * toFilename toCharset<br>
61   * <p>
62   * The current file is not touched and is not marked as moved.
63   */
64  public class TranscodeTask extends AbstractTask {
65    /**
66     * Internal Logger
67     */
68    private static final WaarpLogger logger =
69        WaarpLoggerFactory.getLogger(TranscodeTask.class);
70  
71    /**
72     * @param argRule
73     * @param delay
74     * @param argTransfer
75     * @param session
76     */
77    public TranscodeTask(final String argRule, final int delay,
78                         final String argTransfer, final R66Session session) {
79      super(TaskType.TRANSCODE, delay, argRule, argTransfer, session);
80    }
81  
82    @Override
83    public final void run() {
84      final boolean success;
85      final DbTaskRunner runner = session.getRunner();
86      String arg = argRule;
87      arg = getReplacedValue(arg, BLANK.split(argTransfer));
88      final String[] args = BLANK.split(arg);
89      boolean dos2unix = false;
90      boolean unix2dos = false;
91      String fromCharset = null;
92      String toCharset = null;
93      String newfilename = null;
94      String extension = null;
95      for (int i = 0; i < args.length; i++) {
96        if ("-from".equalsIgnoreCase(args[i])) {
97          i++;
98          if (i < args.length) {
99            fromCharset = args[i];
100         }
101       } else if ("-to".equalsIgnoreCase(args[i])) {
102         i++;
103         if (i < args.length) {
104           toCharset = args[i];
105         }
106       } else if ("-newfile".equalsIgnoreCase(args[i])) {
107         i++;
108         if (i < args.length) {
109           newfilename = args[i];
110         }
111       } else if ("-extension".equalsIgnoreCase(args[i])) {
112         i++;
113         if (i < args.length) {
114           extension = args[i];
115         }
116       } else if ("-dos2unix".equalsIgnoreCase(args[i])) {
117         dos2unix = true;
118       } else if ("-unix2dos".equalsIgnoreCase(args[i])) {
119         unix2dos = true;
120       }
121     }
122     if (dos2unix && unix2dos) {
123       final R66Result result =
124           new R66Result(session, false, ErrorCode.Warning, runner);
125       futureCompletion.setResult(result);
126       logger.warn(
127           "Dos2Unix and Unix2Dos cannot be used simultaneously in Transcode: " +
128           runner.toShortString());
129       futureCompletion.setFailure(new OpenR66ProtocolSystemException(
130           "Dos2Unix and Unix2Dos cannot be used simultaneously in Transcode"));
131       return;
132     }
133     if (fromCharset == null || toCharset == null) {
134       if (!(dos2unix || unix2dos)) {
135         final R66Result result =
136             new R66Result(session, false, ErrorCode.Warning, runner);
137         futureCompletion.setResult(result);
138         logger.warn(
139             "Not enough argument in Transcode: " + runner.toShortString());
140         futureCompletion.setFailure(new OpenR66ProtocolSystemException(
141             "Not enough argument in Transcode"));
142       } else {
143         // only 1 of Dos2Unix/Unix2Dos
144         final FileConvert convert =
145             new FileConvert(null, unix2dos, false, null);
146         final File from = session.getFile().getTrueFile();
147         if (convert.convert(from, unix2dos)) {
148           futureCompletion.setSuccess();
149         } else {
150           final R66Result result =
151               new R66Result(session, false, ErrorCode.Internal, runner);
152           futureCompletion.setResult(result);
153           logger.error(
154               "Cannot Transcode " + argRule + ':' + argTransfer + " and " +
155               session);
156           futureCompletion.setFailure(
157               new OpenR66ProtocolSystemException("Cannot Transcode file"));
158         }
159       }
160       return;
161     }
162     final File from = session.getFile().getTrueFile();
163     String finalname = newfilename;
164     if (newfilename != null) {
165       finalname = newfilename;
166     } else if (extension != null) {
167       finalname = from.getAbsolutePath() + '.' + extension;
168     } else {
169       finalname = from.getAbsolutePath() + ".transcode";
170     }
171     success =
172         CharsetsUtil.transcode(from.getAbsolutePath(), fromCharset, finalname,
173                                toCharset, Configuration.BUFFERSIZEDEFAULT);
174     if (success && (dos2unix || unix2dos)) {
175       // now convert it
176       // only 1 of Dos2Unix/Unix2Dos
177       final FileConvert convert = new FileConvert(null, unix2dos, false, null);
178       final File to = new File(finalname);
179       if (convert.convert(to, unix2dos)) {
180         futureCompletion.setSuccess();
181       } else {
182         // only warning
183         logger.warn("Cannot Unix/Dos Transcode " + to + " : " + argRule + ':' +
184                     argTransfer + " and " + session);
185         futureCompletion.setSuccess();
186       }
187       return;
188     }
189     if (success) {
190       futureCompletion.setSuccess();
191     } else {
192       logger.error("Cannot Transcode from " + fromCharset + " to " + toCharset +
193                    " with " + argRule + ':' + argTransfer + " and " + session);
194       futureCompletion.setFailure(
195           new OpenR66ProtocolSystemException("Cannot Transcode file"));
196     }
197   }
198 
199 }