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.server;
21  
22  import org.apache.commons.io.FileUtils;
23  import org.waarp.common.database.exception.WaarpDatabaseException;
24  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
25  import org.waarp.common.logging.SysErrLogger;
26  import org.waarp.common.logging.WaarpLogger;
27  import org.waarp.common.logging.WaarpLoggerFactory;
28  import org.waarp.common.logging.WaarpSlf4JLoggerFactory;
29  import org.waarp.common.utility.ParametersChecker;
30  import org.waarp.common.utility.WaarpStringUtils;
31  import org.waarp.common.utility.WaarpSystemUtil;
32  import org.waarp.openr66.configuration.AuthenticationFileBasedConfiguration;
33  import org.waarp.openr66.configuration.FileBasedConfiguration;
34  import org.waarp.openr66.configuration.RuleFileBasedConfiguration;
35  import org.waarp.openr66.database.data.DbHostConfiguration;
36  import org.waarp.openr66.protocol.configuration.Configuration;
37  import org.waarp.openr66.protocol.configuration.Messages;
38  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
39  
40  import java.io.File;
41  import java.io.IOException;
42  
43  import static org.waarp.common.database.DbConstant.*;
44  
45  /**
46   * Utility class to initiate the database for a server
47   */
48  public class ServerInitDatabase {
49    /**
50     * Internal Logger
51     */
52    static volatile WaarpLogger logger;
53  
54    protected static final String INFO_ARGS =
55        Messages.getString("ServerInitDatabase.Help");
56  
57    static String sxml;
58    static boolean database;
59    static boolean upgradeDb;
60    static String sbusiness;
61    static String salias;
62    static String sroles;
63    static String sdirconfig;
64    static String shostauth;
65    static String slimitconfig;
66    static String sextendedFactoryClassList = null;
67    static long minimalSequenceValue = ILLEGALVALUE;
68  
69    private ServerInitDatabase() {
70    }
71  
72    protected static boolean getParams(final String[] args) {
73      if (logger == null) {
74        logger = WaarpLoggerFactory.getLogger(ServerInitDatabase.class);
75      }
76      if (args.length < 1) {
77        logger.error(INFO_ARGS);
78        return false;
79      }
80      sxml = args[0];
81      for (int i = 1; i < args.length; i++) {
82        if ("-initdb".equalsIgnoreCase(args[i])) {
83          database = true;
84          FileBasedConfiguration.autoupgrade = false;
85          upgradeDb = true;
86        } else if ("-upgradeDb".equalsIgnoreCase(args[i])) {
87          upgradeDb = true;
88        } else if ("-loadBusiness".equalsIgnoreCase(args[i])) {
89          i++;
90          sbusiness = args[i];
91        } else if ("-loadAlias".equalsIgnoreCase(args[i])) {
92          i++;
93          salias = args[i];
94        } else if ("-loadRoles".equalsIgnoreCase(args[i])) {
95          i++;
96          sroles = args[i];
97        } else if ("-dir".equalsIgnoreCase(args[i])) {
98          i++;
99          sdirconfig = args[i];
100       } else if ("-limit".equalsIgnoreCase(args[i])) {
101         i++;
102         slimitconfig = args[i];
103       } else if ("-auth".equalsIgnoreCase(args[i])) {
104         i++;
105         shostauth = args[i];
106       } else if ("-loadExtendedTaskFactory".equalsIgnoreCase(args[i])) {
107         i++;
108         sextendedFactoryClassList = args[i];
109       } else if ("-minimalSeq".equalsIgnoreCase(args[i])) {
110         i++;
111         try {
112           minimalSequenceValue = Long.parseLong(args[i]);
113         } catch (final NumberFormatException e) {
114           logger.error("Number for restart sequence is not a long: {}",
115                        args[i]);
116           minimalSequenceValue = ILLEGALVALUE;
117         }
118       }
119     }
120     return true;
121   }
122 
123   /**
124    * @param args as config_database file [rules_directory host_authent
125    *     limit_configuration]
126    */
127   public static void main(final String[] args) {
128     WaarpLoggerFactory.setDefaultFactoryIfNotSame(
129         new WaarpSlf4JLoggerFactory(null));
130     if (logger == null) {
131       logger = WaarpLoggerFactory.getLogger(ServerInitDatabase.class);
132     }
133     if (!getParams(args)) {
134       SysErrLogger.FAKE_LOGGER.sysout(INFO_ARGS);
135       if (admin != null) {
136         admin.close();
137       }
138       WaarpSystemUtil.systemExit(2);
139       return;
140     }
141 
142     try {
143       if (!FileBasedConfiguration.setConfigurationInitDatabase(
144           Configuration.configuration, args[0], database)) {
145         System.err.format(
146             Messages.getString("Configuration.NeedCorrectConfig"));
147         SysErrLogger.FAKE_LOGGER.syserr();
148         WaarpSystemUtil.systemExit(2);
149         return;
150       }
151       if (database) {
152         // Init database
153         SysErrLogger.FAKE_LOGGER.sysoutFormat(
154             Messages.getString("ServerInitDatabase.Create.Start"));
155         SysErrLogger.FAKE_LOGGER.sysout();
156         initdb();
157         SysErrLogger.FAKE_LOGGER.sysoutFormat(
158             Messages.getString("ServerInitDatabase.Create.Done"));
159         SysErrLogger.FAKE_LOGGER.sysout();
160       }
161       if (sextendedFactoryClassList != null) {
162         // Load extended Factory for Task Type
163         final String[] extendedFactories = sextendedFactoryClassList.split(",");
164         for (final String extendedFactory : extendedFactories) {
165           try {
166             WaarpSystemUtil.newInstance(extendedFactory);
167           } catch (final Exception e) {
168             SysErrLogger.FAKE_LOGGER.sysoutFormat(Messages.getString(
169                 "ServerInitDatabase.ExtendedTaskFactory.error") +
170                                                   e.getMessage());
171             SysErrLogger.FAKE_LOGGER.sysout();
172           }
173         }
174       }
175       if (upgradeDb) {
176         // try to upgrade DB schema
177         SysErrLogger.FAKE_LOGGER.sysoutFormat(
178             Messages.getString("ServerInitDatabase.Upgrade.Start"));
179         SysErrLogger.FAKE_LOGGER.sysout();
180         // TODO Split check for update and upgrade actions
181         if (!upgradedb()) {
182           SysErrLogger.FAKE_LOGGER.syserr(
183               Messages.getString("ServerInitDatabase.SchemaNotUptodate"));
184           SysErrLogger.FAKE_LOGGER.syserr();
185           updateMinimalValueSequence();
186           WaarpSystemUtil.systemExit(1);
187           return;
188         }
189         SysErrLogger.FAKE_LOGGER.sysoutFormat(
190             Messages.getString("ServerInitDatabase.Upgrade.Done"));
191         SysErrLogger.FAKE_LOGGER.sysout();
192       }
193       updateMinimalValueSequence();
194       // Try to load some element directly into database from first
195       // configuration file
196       FileBasedConfiguration.setConfigurationServerFromXml(
197           Configuration.configuration, args[0], false);
198       if (sdirconfig != null) {
199         // load Rules
200         SysErrLogger.FAKE_LOGGER.sysoutFormat(
201             Messages.getString("ServerInitDatabase.LoadRule.Start"),
202             sdirconfig);
203         SysErrLogger.FAKE_LOGGER.sysout();
204         final File dirConfig = new File(sdirconfig);
205         if (dirConfig.isDirectory()) {
206           if (!loadRules(dirConfig)) {
207             SysErrLogger.FAKE_LOGGER.sysoutFormat(
208                 Messages.getString("ServerInitDatabase.LoadRule.Failed"));
209             WaarpSystemUtil.systemExit(1);
210             return;
211           }
212         } else {
213           System.err.format(
214               Messages.getString("ServerInitDatabase.LoadRule.NoDirectory"),
215               sdirconfig);
216           SysErrLogger.FAKE_LOGGER.syserr();
217           WaarpSystemUtil.systemExit(1);
218           return;
219         }
220         SysErrLogger.FAKE_LOGGER.sysoutFormat(
221             Messages.getString("ServerInitDatabase.LoadRule.Done"));
222         SysErrLogger.FAKE_LOGGER.sysout();
223       }
224       if (shostauth != null) {
225         // Load Host Authentications
226         System.out.format(
227             Messages.getString("ServerInitDatabase.LoadAuth.Start"), shostauth);
228         SysErrLogger.FAKE_LOGGER.sysout();
229         if (!loadHostAuth(shostauth)) {
230           System.err.format(
231               Messages.getString("ServerInitDatabase.LoadAuth.Failed"));
232           SysErrLogger.FAKE_LOGGER.syserr();
233           WaarpSystemUtil.systemExit(1);
234           return;
235         }
236         System.out.format(
237             Messages.getString("ServerInitDatabase.LoadAuth.Done"));
238         SysErrLogger.FAKE_LOGGER.sysout();
239       }
240       if (slimitconfig != null) {
241         // Load configuration
242         System.out.format(
243             Messages.getString("ServerInitDatabase.LoadLimit.Start"),
244             slimitconfig);
245         SysErrLogger.FAKE_LOGGER.sysout();
246         if (!FileBasedConfiguration.setConfigurationLoadLimitFromXml(
247             Configuration.configuration, slimitconfig)) {
248           System.err.format(
249               Messages.getString("ServerInitDatabase.LoadLimit.Failed"));
250           SysErrLogger.FAKE_LOGGER.syserr();
251           WaarpSystemUtil.systemExit(1);
252           return;
253         }
254         System.out.format(
255             Messages.getString("ServerInitDatabase.LoadLimit.Done"));
256         SysErrLogger.FAKE_LOGGER.sysout();
257       }
258       if (sbusiness != null || salias != null || sroles != null) {
259         if (sbusiness != null) {
260           sbusiness = getXMLFromFile(sbusiness);
261         }
262         if (salias != null) {
263           salias = getXMLFromFile(salias);
264         }
265         if (sroles != null) {
266           sroles = getXMLFromFile(sroles);
267         }
268         DbHostConfiguration hostConfiguration;
269         try {
270           hostConfiguration =
271               new DbHostConfiguration(Configuration.configuration.getHostId());
272           if (ParametersChecker.isNotEmpty(salias)) {
273             hostConfiguration.setAliases(salias);
274           }
275           if (ParametersChecker.isNotEmpty(sbusiness)) {
276             hostConfiguration.setBusiness(sbusiness);
277           }
278           if (ParametersChecker.isNotEmpty(sroles)) {
279             hostConfiguration.setRoles(sroles);
280           }
281           hostConfiguration.update();
282         } catch (final WaarpDatabaseException e) {
283           hostConfiguration =
284               new DbHostConfiguration(Configuration.configuration.getHostId(),
285                                       sbusiness, sroles, salias, "");
286           hostConfiguration.insert();
287         }
288       }
289       SysErrLogger.FAKE_LOGGER.sysout(
290           Messages.getString("ServerInitDatabase.LoadDone"));
291       SysErrLogger.FAKE_LOGGER.sysout();
292       WaarpSystemUtil.systemExit(0);
293     } catch (final WaarpDatabaseException e) {
294       SysErrLogger.FAKE_LOGGER.syserr(
295           Messages.getString("ServerInitDatabase.ErrDatabase"));
296       SysErrLogger.FAKE_LOGGER.syserr();
297       WaarpSystemUtil.systemExit(3);
298     } finally {
299       if (admin != null) {
300         admin.close();
301       }
302     }
303   }
304 
305   private static void updateMinimalValueSequence() {
306     if (minimalSequenceValue != ILLEGALVALUE) {
307       try {
308         admin.getSession().getAdmin().getDbModel()
309              .resetSequence(admin.getSession(), minimalSequenceValue);
310       } catch (final WaarpDatabaseNoConnectionException e) {
311         logger.error("Cannot update sequence restart value: {}",
312                      e.getMessage());
313       }
314     }
315   }
316 
317   private static String getXMLFromFile(final String path) {
318     String res = "";
319     final File file = new File(path);
320     if (file.canRead()) {
321       try {
322         final String value =
323             FileUtils.readFileToString(file, WaarpStringUtils.UTF8);
324         if (ParametersChecker.isNotEmpty(value)) {
325           res = value.replaceAll("\r|\n|  ", " ").trim();
326         }
327       } catch (final IOException e) {
328         SysErrLogger.FAKE_LOGGER.syserr(e);
329       }
330     }
331     return res;
332   }
333 
334   public static void initdb() throws WaarpDatabaseNoConnectionException {
335     // Create tables: configuration, hosts, rules, runner, cptrunner
336     admin.getSession().getAdmin().getDbModel().createTables(admin.getSession());
337   }
338 
339   /**
340    * @return True if the base is up to date, else False (need Upgrade)
341    */
342   public static boolean upgradedb() {
343     if (logger == null) {
344       logger = WaarpLoggerFactory.getLogger(ServerInitDatabase.class);
345     }
346     // Update tables: runner
347     boolean uptodate = true;
348     // Check if the database is up to date
349     final String version = DbHostConfiguration.getVersionDb(
350         Configuration.configuration.getHostId());
351     try {
352       if (version != null) {
353         uptodate = admin.getSession().getAdmin().getDbModel()
354                         .needUpgradeDb(admin.getSession(), version, true);
355       } else {
356         uptodate = admin.getSession().getAdmin().getDbModel()
357                         .needUpgradeDb(admin.getSession(), "1.1.0", true);
358       }
359       if (uptodate) {
360         logger.error(Messages.getString(
361             "ServerInitDatabase.SchemaNotUptodate")); //$NON-NLS-1$
362         return false;
363       } else {
364         logger.debug(Messages.getString(
365             "ServerInitDatabase.SchemaUptodate")); //$NON-NLS-1$
366       }
367     } catch (final WaarpDatabaseNoConnectionException e) {
368       logger.error(Messages.getString("Database.CannotConnect"),
369                    e); //$NON-NLS-1$
370       return false;
371     }
372     return !uptodate;
373   }
374 
375   public static boolean loadRules(final File dirConfig)
376       throws WaarpDatabaseException {
377     try {
378       RuleFileBasedConfiguration.importRules(dirConfig);
379     } catch (final OpenR66ProtocolSystemException e) {
380       SysErrLogger.FAKE_LOGGER.syserr(e);
381       return false;
382     }
383     return true;
384   }
385 
386   public static boolean loadHostAuth(final String filename) {
387     return AuthenticationFileBasedConfiguration.loadAuthentication(
388         Configuration.configuration, filename);
389   }
390 }