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.configuration;
21  
22  import org.dom4j.Document;
23  import org.dom4j.DocumentException;
24  import org.dom4j.DocumentHelper;
25  import org.dom4j.Element;
26  import org.dom4j.tree.DefaultElement;
27  import org.waarp.common.database.exception.WaarpDatabaseException;
28  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
29  import org.waarp.common.database.exception.WaarpDatabaseNoDataException;
30  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
31  import org.waarp.common.file.DirInterface;
32  import org.waarp.common.file.FileUtils;
33  import org.waarp.common.logging.SysErrLogger;
34  import org.waarp.common.logging.WaarpLogger;
35  import org.waarp.common.logging.WaarpLoggerFactory;
36  import org.waarp.common.xml.XmlDecl;
37  import org.waarp.common.xml.XmlHash;
38  import org.waarp.common.xml.XmlType;
39  import org.waarp.common.xml.XmlUtil;
40  import org.waarp.common.xml.XmlValue;
41  import org.waarp.openr66.context.task.TaskType;
42  import org.waarp.openr66.dao.DAOFactory;
43  import org.waarp.openr66.dao.RuleDAO;
44  import org.waarp.openr66.dao.exception.DAOConnectionException;
45  import org.waarp.openr66.dao.xml.XMLDAOFactory;
46  import org.waarp.openr66.dao.xml.XMLRuleDAO;
47  import org.waarp.openr66.database.data.DbRule;
48  import org.waarp.openr66.protocol.configuration.Configuration;
49  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoDataException;
50  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
51  
52  import java.io.File;
53  import java.io.IOException;
54  import java.util.ArrayList;
55  import java.util.List;
56  
57  import static org.waarp.common.database.DbConstant.*;
58  
59  /**
60   * Rule File Based Configuration
61   */
62  public final class RuleFileBasedConfiguration {
63    private static final String UNABLE_TO_READ_THE_XML_RULE_FILE =
64        "Unable to read the XML Rule file: ";
65  
66    /**
67     * Internal Logger
68     */
69    private static final WaarpLogger logger =
70        WaarpLoggerFactory.getLogger(RuleFileBasedConfiguration.class);
71  
72    public static final String MULTIPLEROOT = "rules";
73    public static final String ROOT = "rule";
74    public static final String XIDRULE = "idrule";
75    public static final String XHOSTIDS = "hostids";
76    public static final String XHOSTID = "hostid";
77    public static final String XMODE = "mode";
78    public static final String XRECVPATH = "recvpath";
79    public static final String XSENDPATH = "sendpath";
80    public static final String XARCHIVEPATH = "archivepath";
81    public static final String XWORKPATH = "workpath";
82    public static final String XRPRETASKS = "rpretasks";
83    public static final String XRPOSTTASKS = "rposttasks";
84    public static final String XRERRORTASKS = "rerrortasks";
85    public static final String XSPRETASKS = "spretasks";
86    public static final String XSPOSTTASKS = "sposttasks";
87    public static final String XSERRORTASKS = "serrortasks";
88    public static final String XTASKS = "tasks";
89    public static final String XTASK = "task";
90  
91    private static final String HOSTIDS_HOSTID = '/' + XHOSTIDS + '/' + XHOSTID;
92  
93    private static final String TASK = "/tasks/task";
94  
95    private static final XmlDecl[] taskDecl = {
96        new XmlDecl(XmlType.STRING, DbRule.TASK_TYPE),
97        new XmlDecl(XmlType.STRING, DbRule.TASK_PATH),
98        new XmlDecl(XmlType.LONG, DbRule.TASK_DELAY),
99        new XmlDecl(XmlType.INTEGER, DbRule.TASK_RANK),
100       new XmlDecl(XmlType.STRING, DbRule.TASK_COMMENT)
101   };
102   public static final XmlDecl[] tasksDecl =
103       { new XmlDecl(XTASK, XmlType.XVAL, TASK, taskDecl, true) };
104   private static final XmlDecl[] subruleDecls = {
105       new XmlDecl(XmlType.STRING, XIDRULE),
106       new XmlDecl(XHOSTIDS, XmlType.STRING, HOSTIDS_HOSTID, true),
107       new XmlDecl(XmlType.INTEGER, XMODE),
108       new XmlDecl(XmlType.STRING, XRECVPATH),
109       new XmlDecl(XmlType.STRING, XSENDPATH),
110       new XmlDecl(XmlType.STRING, XARCHIVEPATH),
111       new XmlDecl(XmlType.STRING, XWORKPATH),
112       new XmlDecl(XRPRETASKS, XmlType.XVAL, XRPRETASKS, tasksDecl, false),
113       new XmlDecl(XRPOSTTASKS, XmlType.XVAL, XRPOSTTASKS, tasksDecl, false),
114       new XmlDecl(XRERRORTASKS, XmlType.XVAL, XRERRORTASKS, tasksDecl, false),
115       new XmlDecl(XSPRETASKS, XmlType.XVAL, XSPRETASKS, tasksDecl, false),
116       new XmlDecl(XSPOSTTASKS, XmlType.XVAL, XSPOSTTASKS, tasksDecl, false),
117       new XmlDecl(XSERRORTASKS, XmlType.XVAL, XSERRORTASKS, tasksDecl, false)
118   };
119   private static final XmlDecl[] ruleDecls =
120       { new XmlDecl(ROOT, XmlType.XVAL, ROOT, subruleDecls, false) };
121   private static final XmlDecl[] multipleruleDecls = {
122       new XmlDecl(MULTIPLEROOT, XmlType.XVAL, '/' + MULTIPLEROOT + '/' + ROOT,
123                   subruleDecls, true)
124   };
125   public static final XmlDecl[] hostsDecls =
126       { new XmlDecl(XHOSTIDS, XmlType.STRING, HOSTIDS_HOSTID, true), };
127 
128   /**
129    * Extension of rule files
130    */
131   public static final String EXT_RULE = ".rule.xml";
132   /**
133    * Extension of multiple rules in one file
134    */
135   public static final String EXT_RULES = ".rules.xml";
136   private static final String[][] STRINGS_0_0_LENGTH = new String[0][0];
137   private static final String[] STRING_0_LENGTH = new String[0];
138 
139   private RuleFileBasedConfiguration() {
140   }
141 
142   /**
143    * Import all Rule files into the HashTable of Rules
144    *
145    * @param configDirectory
146    *
147    * @throws OpenR66ProtocolSystemException
148    * @throws WaarpDatabaseException
149    */
150   public static void importRules(final File configDirectory)
151       throws OpenR66ProtocolSystemException, WaarpDatabaseException {
152     final DAOFactory daoFactory = DAOFactory.getInstance();
153     if (daoFactory instanceof XMLDAOFactory) {
154       RuleDAO ruleDAO = null;
155       try {
156         ruleDAO = daoFactory.getRuleDAO(false);
157         if (ruleDAO instanceof XMLRuleDAO) {
158           final XMLRuleDAO xmlRuleDAO = (XMLRuleDAO) ruleDAO;
159           // To allow loading into cache all Rules
160           xmlRuleDAO.getAll();
161         }
162       } catch (final DAOConnectionException e) {
163         SysErrLogger.FAKE_LOGGER.syserr(e);
164       } finally {
165         if (ruleDAO != null) {
166           ruleDAO.close();
167         }
168       }
169     }
170     File[] files =
171         FileUtils.getFiles(configDirectory, new ExtensionFilter(EXT_RULE));
172     for (final File file : files) {
173       logger.info("Load rule from {}", file.getAbsolutePath());
174       final DbRule rule = getFromFile(file);
175       logger.debug("{}", rule);
176     }
177     files = FileUtils.getFiles(configDirectory, new ExtensionFilter(EXT_RULES));
178     for (final File file : files) {
179       getMultipleFromFile(file);
180     }
181   }
182 
183   /**
184    * Utility function
185    *
186    * @param value
187    *
188    * @return the array of tasks or empty array if in error.
189    */
190   @SuppressWarnings("unchecked")
191   public static String[][] getTasksRule(final XmlValue value) {
192     final List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
193     if (list == null || list.isEmpty()) {
194       // Unable to find the tasks for Rule, setting to the default
195       return STRINGS_0_0_LENGTH;
196     }
197     final String[][] taskArray = new String[list.size()][5];
198     for (int i = 0; i < list.size(); i++) {
199       taskArray[i][0] = null;
200       taskArray[i][1] = null;
201       taskArray[i][2] = null;
202       taskArray[i][3] = null;
203       taskArray[i][4] = null;
204     }
205     int rank = 0;
206     for (final XmlValue[] subvals : list) {
207       final XmlHash hash = new XmlHash(subvals);
208       final XmlValue valtype = hash.get(DbRule.TASK_TYPE);
209       if (valtype == null || valtype.isEmpty() ||
210           valtype.getString().isEmpty()) {
211         continue;
212       }
213       final XmlValue valpath = hash.get(DbRule.TASK_PATH);
214       if (valpath == null || valpath.isEmpty() ||
215           valtype.getString().isEmpty()) {
216         continue;
217       }
218       final XmlValue valdelay = hash.get(DbRule.TASK_DELAY);
219       final String delay;
220       if (valdelay == null || valdelay.isEmpty()) {
221         delay = Long.toString(Configuration.configuration.getTimeoutCon());
222       } else {
223         delay = valdelay.getIntoString();
224       }
225       final XmlValue valcomment = hash.get(DbRule.TASK_COMMENT);
226       final String comment;
227       if (valcomment == null || valcomment.isEmpty() ||
228           valcomment.getString().isEmpty()) {
229         comment = "";
230       } else {
231         comment = valcomment.getString();
232       }
233       final XmlValue valrank = hash.get(DbRule.TASK_RANK);
234       final String srank;
235       if (valrank == null || valrank.isEmpty()) {
236         srank = Integer.toString(rank);
237       } else {
238         srank = valrank.getIntoString();
239       }
240       taskArray[rank][0] = valtype.getString().toUpperCase();
241       // CHECK TASK_TYPE
242       if (!TaskType.isValidTask(taskArray[rank][0])) {
243         // Bad Type
244         logger.warn("Bad Type of Task: " + taskArray[rank][0]);
245         continue;
246       }
247       taskArray[rank][1] = valpath.getString();
248       taskArray[rank][2] = delay;
249       taskArray[rank][3] = comment;
250       taskArray[rank][4] = srank;
251       rank++;
252       hash.clear();
253     }
254     list.clear();
255     return taskArray;
256   }
257 
258   /**
259    * @param value the XmlValue hosting hostids/hostid
260    *
261    * @return the array of HostIds allowed for the current rule
262    */
263   public static String[] getHostIds(final XmlValue value) {
264     String[] idsArray = STRING_0_LENGTH;
265     if (value == null || value.getList() == null || value.getList().isEmpty()) {
266       logger.debug(
267           "Unable to find the Hostid for Rule, setting to the default");
268     } else {
269       @SuppressWarnings("unchecked")
270       final List<String> ids = (List<String>) value.getList();
271       idsArray = new String[ids.size()];
272       int i = 0;
273       for (final String sval : ids) {
274         if (sval.isEmpty()) {
275           continue;
276         }
277         idsArray[i] = sval;
278         i++;
279       }
280       ids.clear();
281     }
282     return idsArray;
283   }
284 
285   /**
286    * Load and update a Rule from a file
287    *
288    * @param file
289    *
290    * @return the newly created R66Rule from XML File
291    *
292    * @throws OpenR66ProtocolSystemException
293    * @throws WaarpDatabaseException
294    * @throws WaarpDatabaseNoDataException
295    * @throws WaarpDatabaseSqlException
296    * @throws WaarpDatabaseNoConnectionException
297    * @throws OpenR66ProtocolNoDataException
298    */
299   public static DbRule getFromFile(final File file)
300       throws OpenR66ProtocolSystemException, WaarpDatabaseNoConnectionException,
301              WaarpDatabaseSqlException, WaarpDatabaseNoDataException,
302              WaarpDatabaseException {
303     final DbRule newRule;
304     final Document document;
305     // Open config file
306     try {
307       document = XmlUtil.getNewSaxReader().read(file);
308     } catch (final DocumentException e) {
309       logger.error(UNABLE_TO_READ_THE_XML_RULE_FILE + file.getName() + ": {}",
310                    e.getMessage());
311       throw new OpenR66ProtocolSystemException(UNABLE_TO_READ_THE_XML_RULE_FILE,
312                                                e);
313     }
314     if (document == null) {
315       logger.error(UNABLE_TO_READ_THE_XML_RULE_FILE + file.getName());
316       throw new OpenR66ProtocolSystemException(
317           UNABLE_TO_READ_THE_XML_RULE_FILE);
318     }
319     final XmlValue[] values = XmlUtil.read(document, ruleDecls);
320     newRule = getFromXmlValue(values);
321     return newRule;
322   }
323 
324   /**
325    * Load and update multiple Rules from one file
326    *
327    * @param file
328    *
329    * @return a list of newly created R66Rule from XML File
330    *
331    * @throws OpenR66ProtocolSystemException
332    * @throws WaarpDatabaseException
333    * @throws WaarpDatabaseNoDataException
334    * @throws WaarpDatabaseSqlException
335    * @throws WaarpDatabaseNoConnectionException
336    * @throws OpenR66ProtocolNoDataException
337    */
338   public static List<DbRule> getMultipleFromFile(final File file)
339       throws OpenR66ProtocolSystemException, WaarpDatabaseNoConnectionException,
340              WaarpDatabaseSqlException, WaarpDatabaseNoDataException,
341              WaarpDatabaseException {
342     final Document document;
343     // Open config file
344     try {
345       document = XmlUtil.getNewSaxReader().read(file);
346     } catch (final DocumentException e) {
347       logger.error(UNABLE_TO_READ_THE_XML_RULE_FILE + file.getName() + ": {}",
348                    e.getMessage());
349       throw new OpenR66ProtocolSystemException(UNABLE_TO_READ_THE_XML_RULE_FILE,
350                                                e);
351     }
352     if (document == null) {
353       logger.error(UNABLE_TO_READ_THE_XML_RULE_FILE + file.getName());
354       throw new OpenR66ProtocolSystemException(
355           UNABLE_TO_READ_THE_XML_RULE_FILE);
356     }
357     final XmlValue[] values = XmlUtil.read(document, multipleruleDecls);
358     if (values.length <= 0) {
359       return new ArrayList<DbRule>(0);
360     }
361     final XmlValue value = values[0];
362     @SuppressWarnings("unchecked")
363     final List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
364     final List<DbRule> result = new ArrayList<DbRule>(list.size());
365     for (final XmlValue[] xmlValue : list) {
366       result.add(getFromXmlValue(xmlValue));
367     }
368     return result;
369   }
370 
371   /**
372    * Load and update one Rule from a XmlValue
373    *
374    * @param root
375    *
376    * @return the newly created R66Rule from XML File
377    *
378    * @throws OpenR66ProtocolSystemException
379    * @throws WaarpDatabaseException
380    * @throws WaarpDatabaseNoDataException
381    * @throws WaarpDatabaseSqlException
382    * @throws WaarpDatabaseNoConnectionException
383    * @throws OpenR66ProtocolNoDataException
384    */
385   private static DbRule getFromXmlValue(final XmlValue[] root)
386       throws OpenR66ProtocolSystemException, WaarpDatabaseNoConnectionException,
387              WaarpDatabaseSqlException, WaarpDatabaseNoDataException,
388              WaarpDatabaseException {
389     final DbRule newRule;
390     final XmlHash hash = new XmlHash(root);
391     XmlValue value = hash.get(XIDRULE);
392     if (value == null || value.isEmpty() || value.getString().isEmpty()) {
393       logger.error("Unable to find in Rule field: " + XIDRULE);
394       throw new OpenR66ProtocolSystemException();
395     }
396     final String idrule = value.getString();
397     value = hash.get(XMODE);
398     if (value == null || value.isEmpty()) {
399       logger.error("Unable to find in Rule field: " + XMODE);
400       throw new OpenR66ProtocolSystemException();
401     }
402     final int mode = value.getInteger();
403     final String recvpath;
404     value = hash.get(XRECVPATH);
405     if (value == null || value.isEmpty() || value.getString().isEmpty()) {
406       recvpath = Configuration.configuration.getInPath();
407     } else {
408       recvpath = DirInterface.SEPARATOR + value.getString();
409     }
410     final String sendpath;
411     value = hash.get(XSENDPATH);
412     if (value == null || value.isEmpty() || value.getString().isEmpty()) {
413       sendpath = Configuration.configuration.getOutPath();
414     } else {
415       sendpath = DirInterface.SEPARATOR + value.getString();
416     }
417     final String archivepath;
418     value = hash.get(XARCHIVEPATH);
419     if (value == null || value.isEmpty() || value.getString().isEmpty()) {
420       archivepath = Configuration.configuration.getArchivePath();
421     } else {
422       archivepath = DirInterface.SEPARATOR + value.getString();
423     }
424     final String workpath;
425     value = hash.get(XWORKPATH);
426     if (value == null || value.isEmpty() || value.getString().isEmpty()) {
427       workpath = Configuration.configuration.getWorkingPath();
428     } else {
429       workpath = DirInterface.SEPARATOR + value.getString();
430     }
431     final String[] idsArray;
432     value = hash.get(XHOSTIDS);
433     idsArray = getHostIds(value);
434     String[][] rpretasks = STRINGS_0_0_LENGTH;
435     value = hash.get(XRPRETASKS);
436     if (value != null && !value.isEmpty()) {
437       final XmlValue[] subvalues = value.getSubXml();
438       if (subvalues.length > 0) {
439         rpretasks = getTasksRule(subvalues[0]);
440       }
441     }
442     String[][] rposttasks = STRINGS_0_0_LENGTH;
443     value = hash.get(XRPOSTTASKS);
444     if (value != null && !value.isEmpty()) {
445       final XmlValue[] subvalues = value.getSubXml();
446       if (subvalues.length > 0) {
447         rposttasks = getTasksRule(subvalues[0]);
448       }
449     }
450     String[][] rerrortasks = STRINGS_0_0_LENGTH;
451     value = hash.get(XRERRORTASKS);
452     if (value != null && !value.isEmpty()) {
453       final XmlValue[] subvalues = value.getSubXml();
454       if (subvalues.length > 0) {
455         rerrortasks = getTasksRule(subvalues[0]);
456       }
457     }
458     String[][] spretasks = STRINGS_0_0_LENGTH;
459     value = hash.get(XSPRETASKS);
460     if (value != null && !value.isEmpty()) {
461       final XmlValue[] subvalues = value.getSubXml();
462       if (subvalues.length > 0) {
463         spretasks = getTasksRule(subvalues[0]);
464       }
465     }
466     String[][] sposttasks = STRINGS_0_0_LENGTH;
467     value = hash.get(XSPOSTTASKS);
468     if (value != null && !value.isEmpty()) {
469       final XmlValue[] subvalues = value.getSubXml();
470       if (subvalues.length > 0) {
471         sposttasks = getTasksRule(subvalues[0]);
472       }
473     }
474     String[][] serrortasks = STRINGS_0_0_LENGTH;
475     value = hash.get(XSERRORTASKS);
476     if (value != null && !value.isEmpty()) {
477       final XmlValue[] subvalues = value.getSubXml();
478       if (subvalues.length > 0) {
479         serrortasks = getTasksRule(subvalues[0]);
480       }
481     }
482 
483     newRule =
484         new DbRule(idrule, idsArray, mode, recvpath, sendpath, archivepath,
485                    workpath, rpretasks, rposttasks, rerrortasks, spretasks,
486                    sposttasks, serrortasks);
487     if (admin != null && admin.getSession() != null) {
488       if (newRule.exist()) {
489         newRule.update();
490       } else {
491         newRule.insert();
492       }
493     } else {
494       // put in hashtable
495       newRule.insert();
496     }
497     hash.clear();
498     return newRule;
499   }
500 
501   /**
502    * Construct a new Element with value
503    *
504    * @param name
505    * @param value
506    *
507    * @return the new Element
508    */
509   private static Element newElement(final String name, final String value) {
510     final Element node = new DefaultElement(name);
511     node.addText(value);
512     return node;
513   }
514 
515   /**
516    * Add a rule from root element (ROOT = rule)
517    *
518    * @param element
519    * @param rule
520    */
521   private static void addToElement(final Element element, final DbRule rule) {
522     element.add(newElement(XIDRULE, rule.getIdRule()));
523     final Element hosts = new DefaultElement(XHOSTIDS);
524     if (rule.getIdsArray() != null) {
525       for (final String host : rule.getIdsArray()) {
526         hosts.add(newElement(XHOSTID, host));
527       }
528     }
529     element.add(hosts);
530     element.add(newElement(XMODE, Integer.toString(rule.getMode())));
531     String dir = rule.getRuleRecvPath();
532     if (dir != null) {
533       if (dir.startsWith(File.separator) ||
534           dir.startsWith(DirInterface.SEPARATOR)) {
535         element.add(newElement(XRECVPATH, dir.substring(1)));
536       } else {
537         element.add(newElement(XRECVPATH, dir));
538       }
539     }
540     dir = rule.getRuleSendPath();
541     if (dir != null) {
542       if (dir.startsWith(File.separator) ||
543           dir.startsWith(DirInterface.SEPARATOR)) {
544         element.add(newElement(XSENDPATH, dir.substring(1)));
545       } else {
546         element.add(newElement(XSENDPATH, dir));
547       }
548     }
549     dir = rule.getRuleArchivePath();
550     if (dir != null) {
551       if (dir.startsWith(File.separator) ||
552           dir.startsWith(DirInterface.SEPARATOR)) {
553         element.add(newElement(XARCHIVEPATH, dir.substring(1)));
554       } else {
555         element.add(newElement(XARCHIVEPATH, dir));
556       }
557     }
558     dir = rule.getRuleWorkPath();
559     if (dir != null) {
560       if (dir.startsWith(File.separator) ||
561           dir.startsWith(DirInterface.SEPARATOR)) {
562         element.add(newElement(XWORKPATH, dir.substring(1)));
563       } else {
564         element.add(newElement(XWORKPATH, dir));
565       }
566     }
567     Element tasks = new DefaultElement(XRPRETASKS);
568     Element roottasks = new DefaultElement(XTASKS);
569     int rank;
570     String[][] array = rule.getRpreTasksArray();
571     if (array != null) {
572       for (rank = 0; rank < array.length; rank++) {
573         final Element task = new DefaultElement(XTASK);
574         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
575         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
576         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
577         if (array[rank].length > 3) {
578           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
579         }
580         if (array[rank].length > 4) {
581           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
582         }
583         roottasks.add(task);
584       }
585     }
586     tasks.add(roottasks);
587     element.add(tasks);
588     tasks = new DefaultElement(XRPOSTTASKS);
589     roottasks = new DefaultElement(XTASKS);
590     array = rule.getRpostTasksArray();
591     if (array != null) {
592       for (rank = 0; rank < array.length; rank++) {
593         final Element task = new DefaultElement(XTASK);
594         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
595         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
596         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
597         if (array[rank].length > 3) {
598           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
599         }
600         if (array[rank].length > 4) {
601           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
602         }
603         roottasks.add(task);
604       }
605     }
606     tasks.add(roottasks);
607     element.add(tasks);
608     tasks = new DefaultElement(XRERRORTASKS);
609     roottasks = new DefaultElement(XTASKS);
610     array = rule.getRerrorTasksArray();
611     if (array != null) {
612       for (rank = 0; rank < array.length; rank++) {
613         final Element task = new DefaultElement(XTASK);
614         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
615         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
616         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
617         if (array[rank].length > 3) {
618           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
619         }
620         if (array[rank].length > 4) {
621           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
622         }
623         roottasks.add(task);
624       }
625     }
626     tasks.add(roottasks);
627     element.add(tasks);
628     tasks = new DefaultElement(XSPRETASKS);
629     roottasks = new DefaultElement(XTASKS);
630     array = rule.getSpreTasksArray();
631     if (array != null) {
632       for (rank = 0; rank < array.length; rank++) {
633         final Element task = new DefaultElement(XTASK);
634         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
635         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
636         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
637         if (array[rank].length > 3) {
638           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
639         }
640         if (array[rank].length > 4) {
641           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
642         }
643         roottasks.add(task);
644       }
645     }
646     tasks.add(roottasks);
647     element.add(tasks);
648     tasks = new DefaultElement(XSPOSTTASKS);
649     roottasks = new DefaultElement(XTASKS);
650     array = rule.getSpostTasksArray();
651     if (array != null) {
652       for (rank = 0; rank < array.length; rank++) {
653         final Element task = new DefaultElement(XTASK);
654         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
655         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
656         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
657         if (array[rank].length > 3) {
658           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
659         }
660         if (array[rank].length > 4) {
661           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
662         }
663         roottasks.add(task);
664       }
665     }
666     tasks.add(roottasks);
667     element.add(tasks);
668     tasks = new DefaultElement(XSERRORTASKS);
669     roottasks = new DefaultElement(XTASKS);
670     array = rule.getSerrorTasksArray();
671     if (array != null) {
672       for (rank = 0; rank < array.length; rank++) {
673         final Element task = new DefaultElement(XTASK);
674         task.add(newElement(DbRule.TASK_TYPE, array[rank][0]));
675         task.add(newElement(DbRule.TASK_PATH, array[rank][1]));
676         task.add(newElement(DbRule.TASK_DELAY, array[rank][2]));
677         if (array[rank].length > 3) {
678           task.add(newElement(DbRule.TASK_COMMENT, array[rank][3]));
679         }
680         if (array[rank].length > 4) {
681           task.add(newElement(DbRule.TASK_RANK, array[rank][4]));
682         }
683         roottasks.add(task);
684       }
685     }
686     tasks.add(roottasks);
687     element.add(tasks);
688   }
689 
690   /**
691    * Write the rule to a file from filename
692    *
693    * @param filename
694    * @param rule
695    *
696    * @throws OpenR66ProtocolSystemException
697    */
698   private static void writeXMLInternal(final String filename, final DbRule rule)
699       throws OpenR66ProtocolSystemException {
700     final Document document = DocumentHelper.createDocument();
701     final Element root = document.addElement(ROOT);
702     addToElement(root, rule);
703     try {
704       XmlUtil.writeXML(filename, null, document);
705     } catch (final IOException e) {
706       throw new OpenR66ProtocolSystemException("Cannot write file: " + filename,
707                                                e);
708     }
709   }
710 
711   /**
712    * Write to directory files prefixed by hostname all Rules from database
713    *
714    * @param directory
715    * @param hostname
716    *
717    * @throws WaarpDatabaseNoConnectionException
718    * @throws OpenR66ProtocolSystemException
719    */
720   public static void writeXml(final String directory, final String hostname)
721       throws WaarpDatabaseNoConnectionException,
722              OpenR66ProtocolSystemException {
723     final File dir = new File(directory);
724     if (!dir.isDirectory()) {
725       dir.mkdirs();//NOSONAR
726     }
727     final DbRule[] rules = DbRule.getAllRules();
728     for (final DbRule rule : rules) {
729       final String filename =
730           dir.getAbsolutePath() + File.separator + hostname + '_' +
731           rule.getIdRule() + EXT_RULE;
732       logger.debug("Will write Rule: {} in {}", rule.getIdRule(), filename);
733       writeXMLInternal(filename, rule);
734     }
735   }
736 
737   /**
738    * Write to directory 1 file prefixed by hostname all Rules from database
739    *
740    * @param directory
741    * @param hostname
742    *
743    * @return the filename
744    *
745    * @throws WaarpDatabaseNoConnectionException
746    * @throws OpenR66ProtocolSystemException
747    */
748   public static String writeOneXml(final String directory,
749                                    final String hostname)
750       throws WaarpDatabaseNoConnectionException,
751              OpenR66ProtocolSystemException {
752     final File dir = new File(directory);
753     if (!dir.isDirectory()) {
754       dir.mkdirs();//NOSONAR
755     }
756     final DbRule[] rules = DbRule.getAllRules();
757     final String filename =
758         dir.getAbsolutePath() + File.separator + hostname + EXT_RULES;
759     final Document document = DocumentHelper.createDocument();
760     final Element root = document.addElement(MULTIPLEROOT);
761     for (final DbRule rule : rules) {
762       final Element element = root.addElement(ROOT);
763       addToElement(element, rule);
764     }
765     try {
766       XmlUtil.writeXML(filename, null, document);
767     } catch (final IOException e) {
768       throw new OpenR66ProtocolSystemException("Cannot write file: " + filename,
769                                                e);
770     }
771     return filename;
772   }
773 }