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.gateway.ftp;
21  
22  import org.waarp.common.command.ReplyCode;
23  import org.waarp.common.database.DbPreparedStatement;
24  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
25  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
26  import org.waarp.common.file.DirInterface;
27  import org.waarp.common.file.filesystembased.FilesystemBasedFileParameterImpl;
28  import org.waarp.common.logging.SysErrLogger;
29  import org.waarp.common.utility.WaarpStringUtils;
30  import org.waarp.common.utility.WaarpSystemUtil;
31  import org.waarp.gateway.ftp.config.FileBasedConfiguration;
32  import org.waarp.gateway.ftp.control.ExecBusinessHandler;
33  import org.waarp.gateway.ftp.data.FileSystemBasedDataBusinessHandler;
34  import org.waarp.gateway.ftp.database.DbConstantFtp;
35  import org.waarp.gateway.ftp.database.data.DbTransferLog;
36  
37  import java.io.FileWriter;
38  import java.io.IOException;
39  import java.io.OutputStreamWriter;
40  import java.io.Writer;
41  import java.sql.Timestamp;
42  
43  /**
44   * Program to export log history from database to a file and optionally purge
45   * exported entries.
46   */
47  public class LogExport {
48    /**
49     * Command Flags
50     */
51    private static boolean purge;
52    private static boolean correctOnly;
53    private static String destinationPath;
54    protected static Timestamp start;
55    protected static Timestamp stop;
56  
57    /**
58     * Internal pointer to the destination writer object
59     */
60    private static Writer destinationWriter;
61  
62    /**
63     * Internal pointer to the configuration
64     */
65    private static FileBasedConfiguration config;
66  
67    /**
68     * Usage for the command
69     */
70    private static final String USAGE =
71        "Need at least the configuration file as first argument then optionally\n" +
72        "    -correctOnly      Only exports successful transfers\n" +
73        "    -purge            Purge exported transfers\n" +
74        "    -out [filepath|-] The path to the file created\n" +
75        "                      Use '-' for stdout\n" +
76        "    -start timestamp  in format yyyyMMddHHmmssSSS possibly truncated and where one of ':-. ' can be separators\n" +
77        "    -stop timestamp   in same format than start\n";
78  
79    private LogExport() {
80    }
81  
82    /**
83     * Verifies command line arguments and initialize internals (mainly config)
84     *
85     * @param args command line arguments
86     *
87     * @return the result of the initialization. if an error occured at this
88     *     stage, return value will be false
89     */
90    protected static boolean initialize(final String[] args) {
91      if (!getParams(args)) {
92        return false;
93      }
94  
95      config = new FileBasedConfiguration(ExecGatewayFtpServer.class,
96                                          ExecBusinessHandler.class,
97                                          FileSystemBasedDataBusinessHandler.class,
98                                          new FilesystemBasedFileParameterImpl());
99  
100     if (!config.setConfigurationServerFromXml(args[0])) {
101       SysErrLogger.FAKE_LOGGER.syserr("Bad main configuration");
102       if (DbConstantFtp.gatewayAdmin != null) {
103         DbConstantFtp.gatewayAdmin.close();
104       }
105       return false;
106     }
107 
108     FileBasedConfiguration.fileBasedConfiguration = config;
109 
110     return setDestinationWriter();
111   }
112 
113   /**
114    * Creates and sets destinationWriter according to the following logic based
115    * on the value of the '-out'
116    * command line argument: - if no value is given, a default path is computed
117    * (the same as online export, i.e.
118    * in [data directory]/[admin name]) - if the value '-' is given,
119    * destinationWriter is the standard output
120    * (System.out) - if any other value is given, then it is considered as the
121    * path to the destination file
122    *
123    * @return a bollean indicating the success in opening the Writer.
124    */
125   public static boolean setDestinationWriter() {
126     if (destinationPath == null) {
127       destinationPath = config.getBaseDirectory() + DirInterface.SEPARATOR +
128                         config.getAdminName() + DirInterface.SEPARATOR +
129                         config.getHostId() + "_logs_" +
130                         System.currentTimeMillis() + ".xml";
131     }
132 
133     if ("-".equalsIgnoreCase(destinationPath)) {
134       destinationWriter = new OutputStreamWriter(System.out);
135     } else {
136       try {
137         destinationWriter = new FileWriter(destinationPath);
138       } catch (final IOException e) {
139         SysErrLogger.FAKE_LOGGER.syserr(
140             "Cannot open out file " + destinationPath);
141         return false;
142       }
143     }
144     return true;
145   }
146 
147   /**
148    * Parses command line arguments
149    *
150    * @param args command line arguments to parse
151    *
152    * @return [description]
153    */
154   protected static boolean getParams(final String[] args) {
155     if (args.length < 1) {
156       SysErrLogger.FAKE_LOGGER.syserr(USAGE);
157       return false;
158     }
159 
160     for (int i = 1; i < args.length; i++) {
161       if ("-purge".equalsIgnoreCase(args[i])) {
162         purge = true;
163       } else if ("-correctOnly".equalsIgnoreCase(args[i])) {
164         correctOnly = true;
165       } else if ("-out".equalsIgnoreCase(args[i])) {
166         i++;
167         if (i >= args.length ||
168             args[i].charAt(0) == '-' && args[i].length() > 1) {
169           SysErrLogger.FAKE_LOGGER.syserr(
170               "Error: -out needs a value.\n\n" + USAGE);
171           return false;
172         }
173         destinationPath = args[i].trim();
174       } else if ("-start".equalsIgnoreCase(args[i])) {
175         i++;
176         if (i >= args.length ||
177             args[i].charAt(0) == '-' && args[i].length() > 1) {
178           SysErrLogger.FAKE_LOGGER.syserr(
179               "Error: -start needs a value.\n\n" + USAGE);
180           return false;
181         }
182         start = WaarpStringUtils.fixDate(args[i]);
183       } else if ("-stop".equalsIgnoreCase(args[i])) {
184         i++;
185         if (i >= args.length ||
186             args[i].charAt(0) == '-' && args[i].length() > 1) {
187           SysErrLogger.FAKE_LOGGER.syserr(
188               "Error: -stop needs a value.\n\n" + USAGE);
189           return false;
190         }
191         stop = WaarpStringUtils.fixDate(args[i]);
192       }
193     }
194     return true;
195   }
196 
197   /**
198    * Main logic for the command.
199    *
200    * @return an error message or null
201    */
202   protected static String run() {
203     ReplyCode status = null;
204     if (correctOnly) {
205       status = ReplyCode.REPLY_226_CLOSING_DATA_CONNECTION;
206     }
207 
208     final DbPreparedStatement preparedStatement;
209     try {
210       preparedStatement = DbTransferLog.getLogPrepareStament(
211           DbConstantFtp.gatewayAdmin.getSession(), start, stop, status);
212 
213     } catch (final WaarpDatabaseNoConnectionException e) {
214       return "An error occured while connecting to the database: " +
215              e.getMessage();
216 
217     } catch (final WaarpDatabaseSqlException e) {
218       return "An error occured with the database: " + e.getMessage();
219     }
220 
221     return DbTransferLog.saveDbTransferLogFile(preparedStatement,
222                                                destinationWriter, purge);
223   }
224 
225   /**
226    * Command Entry point
227    *
228    * @param args command line arguments
229    */
230   public static void main(final String[] args) {
231     try {
232       if (!initialize(args)) {
233         WaarpSystemUtil.systemExit(1);
234         return;
235       }
236 
237       final String message = run();
238 
239       if (message.contains("successfully")) {
240         WaarpSystemUtil.systemExit(0);
241       } else {
242         SysErrLogger.FAKE_LOGGER.syserr(message);
243         WaarpSystemUtil.systemExit(1);
244       }
245 
246     } finally {
247       if (DbConstantFtp.gatewayAdmin != null) {
248         DbConstantFtp.gatewayAdmin.close();
249       }
250     }
251   }
252 }