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.kernel;
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.exception.InvalidArgumentException;
28  import org.waarp.common.logging.WaarpLogger;
29  import org.waarp.common.logging.WaarpLoggerFactory;
30  import org.waarp.common.xml.XmlDecl;
31  import org.waarp.common.xml.XmlHash;
32  import org.waarp.common.xml.XmlType;
33  import org.waarp.common.xml.XmlUtil;
34  import org.waarp.common.xml.XmlValue;
35  import org.waarp.gateway.kernel.AbstractHttpField.FieldPosition;
36  import org.waarp.gateway.kernel.AbstractHttpField.FieldRole;
37  import org.waarp.gateway.kernel.HttpPage.PageRole;
38  import org.waarp.gateway.kernel.exception.HttpIncorrectRequestException;
39  
40  import java.io.IOException;
41  import java.util.ArrayList;
42  import java.util.HashMap;
43  import java.util.LinkedHashMap;
44  import java.util.List;
45  
46  /**
47   *
48   */
49  public final class HttpXmlDefinition {
50    private static final String UNABLE_TO_LINK_VALUE_OF_FIELD =
51        "Unable to link value of field: ";
52  
53    private static final String UNABLE_TO_FIND_FIELD = "Unable to find field: ";
54  
55    /**
56     * Internal Logger
57     */
58    private static final WaarpLogger logger =
59        WaarpLoggerFactory.getLogger(HttpXmlDefinition.class);
60  
61    /*
62     * pagename, fileform, header, footer, beginform, endform, nextinform, uri, pagerole, errorpage, classname,
63     * <br> <fieldname, fieldtype, fieldinfo, fieldvalue, fieldvisibility, fieldmandatory, fieldcookieset,
64     * fieldtovalidate, fieldposition, fieldrank>*
65     */
66    /**
67     * HTTP global root
68     */
69    private static final String XML_ROOT_NAME = "root";
70    /**
71     * HTTP global root
72     */
73    private static final String XML_HTTP_ROOT = '/' + XML_ROOT_NAME + '/';
74    /**
75     * HTTP Pages
76     */
77    private static final String XML_HTTP_PAGES = "pages";
78    /**
79     * HTTP Page root
80     */
81    private static final String XML_HTTP_PAGE = "page";
82    /**
83     * HTTP Pagename
84     */
85    private static final String XML_HTTP_PAGENAME = "pagename";
86    /**
87     * HTTP Pagename
88     */
89    private static final String XML_HTTP_FILEFORM = "fileform";
90    /**
91     * HTTP Header
92     */
93    private static final String XML_HTTP_HEADER = "header";
94    /**
95     * HTTP Footer
96     */
97    private static final String XML_HTTP_FOOTER = "footer";
98    /**
99     * HTTP begin form
100    */
101   private static final String XML_HTTP_BEGINFORM = "beginform";
102   /**
103    * HTTP end form
104    */
105   private static final String XML_HTTP_ENDFORM = "endform";
106   /**
107    * HTTP next in form
108    */
109   private static final String XML_HTTP_NEXTINFORM = "nextinform";
110   /**
111    * HTTP uri
112    */
113   private static final String XML_HTTP_URI = "uri";
114   /**
115    * HTTP Page role
116    */
117   private static final String XML_HTTP_PAGEROLE = "pagerole";
118   /**
119    * HTTP error page (uri as reference to access to HttpPage Object)
120    */
121   private static final String XML_HTTP_ERRORPAGE = "errorpage";
122   /**
123    * HTTP Class name
124    */
125   private static final String XML_HTTP_CLASSNAME = "classname";
126   /*
127    * fieldname, fieldtype, fieldinfo, fieldvalue, fieldvisibility, fieldmandatory, fieldcookieset,
128    * fieldtovalidate, fieldposition, fieldrank
129    */
130   /**
131    * HTTP fields list
132    */
133   private static final String XML_HTTP_FIELDS = "fields";
134   /**
135    * HTTP field definition
136    */
137   private static final String XML_HTTP_FIELD = "field";
138   /**
139    * HTTP fieldname
140    */
141   private static final String XML_HTTP_FIELDNAME = "fieldname";
142   /**
143    * HTTP fieldtype
144    */
145   private static final String XML_HTTP_FIELDTYPE = "fieldtype";
146   /**
147    * HTTP fieldinfo
148    */
149   private static final String XML_HTTP_FIELDINFO = "fieldinfo";
150   /**
151    * HTTP fieldvalue
152    */
153   private static final String XML_HTTP_FIELDVALUE = "fieldvalue";
154   /**
155    * HTTP fieldvisibility
156    */
157   private static final String XML_HTTP_FIELDVISIBILITY = "fieldvisibility";
158   /**
159    * HTTP fieldmandatory
160    */
161   private static final String XML_HTTP_FIELDMANDATORY = "fieldmandatory";
162   /**
163    * HTTP fieldcookieset
164    */
165   private static final String XML_HTTP_FIELDCOOKIESET = "fieldcookieset";
166   /**
167    * HTTP fieldtovalidate
168    */
169   private static final String XML_HTTP_FIELDTOVALIDATE = "fieldtovalidate";
170   /**
171    * HTTP fieldposition
172    */
173   private static final String XML_HTTP_FIELDPOSITION = "fieldposition";
174   /**
175    * HTTP fieldrank
176    */
177   private static final String XML_HTTP_FIELDRANK = "fieldrank";
178 
179   /**
180    * Structure of the Configuration: Field
181    */
182   private static final XmlDecl[] configHttpField = {
183       // 1 Field
184       new XmlDecl(XmlType.STRING, XML_HTTP_FIELDNAME),
185       new XmlDecl(XmlType.STRING, XML_HTTP_FIELDTYPE),
186       new XmlDecl(XmlType.STRING, XML_HTTP_FIELDINFO),
187       new XmlDecl(XmlType.STRING, XML_HTTP_FIELDVALUE),
188       new XmlDecl(XmlType.BOOLEAN, XML_HTTP_FIELDVISIBILITY),
189       new XmlDecl(XmlType.BOOLEAN, XML_HTTP_FIELDMANDATORY),
190       new XmlDecl(XmlType.BOOLEAN, XML_HTTP_FIELDCOOKIESET),
191       new XmlDecl(XmlType.BOOLEAN, XML_HTTP_FIELDTOVALIDATE),
192       new XmlDecl(XmlType.STRING, XML_HTTP_FIELDPOSITION),
193       new XmlDecl(XmlType.INTEGER, XML_HTTP_FIELDRANK)
194   };
195 
196   /**
197    * Structure of the Configuration: Page
198    */
199   private static final XmlDecl[] configHttpPage = {
200       // 1 Page
201       new XmlDecl(XmlType.STRING, XML_HTTP_PAGENAME),
202       new XmlDecl(XmlType.STRING, XML_HTTP_FILEFORM),
203       new XmlDecl(XmlType.STRING, XML_HTTP_HEADER),
204       new XmlDecl(XmlType.STRING, XML_HTTP_FOOTER),
205       new XmlDecl(XmlType.STRING, XML_HTTP_BEGINFORM),
206       new XmlDecl(XmlType.STRING, XML_HTTP_ENDFORM),
207       new XmlDecl(XmlType.STRING, XML_HTTP_NEXTINFORM),
208       new XmlDecl(XmlType.STRING, XML_HTTP_URI),
209       new XmlDecl(XmlType.STRING, XML_HTTP_PAGEROLE),
210       new XmlDecl(XmlType.STRING, XML_HTTP_ERRORPAGE),
211       new XmlDecl(XmlType.STRING, XML_HTTP_CLASSNAME),
212       // all fields
213       new XmlDecl(XML_HTTP_FIELD, XmlType.XVAL,
214                   XML_HTTP_FIELDS + '/' + XML_HTTP_FIELD, configHttpField, true)
215   };
216 
217   /**
218    * Structure of the Configuration: Pages
219    * <p>
220    * from root => Pages.Page
221    */
222   private static final XmlDecl[] configHttpPages = {
223       // all pages
224       new XmlDecl(XML_HTTP_PAGE, XmlType.XVAL,
225                   XML_HTTP_ROOT + XML_HTTP_PAGES + '/' + XML_HTTP_PAGE,
226                   configHttpPage, true)
227   };
228 
229   private HttpXmlDefinition() {
230   }
231 
232   static AbstractHttpField loadHttpPage(final XmlValue[] xmlValue)
233       throws InvalidArgumentException {
234     final XmlHash hash = new XmlHash(xmlValue);
235     XmlValue value = hash.get(XML_HTTP_FIELDNAME);
236     if (value == null || value.isEmpty() || value.getString().length() == 0) {
237       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDNAME);
238       throw new InvalidArgumentException(
239           UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDNAME);
240     }
241     final String fieldname = value.getString();
242     value = hash.get(XML_HTTP_FIELDTYPE);
243     if (value == null || value.isEmpty() || value.getString().length() == 0) {
244       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDTYPE);
245       throw new InvalidArgumentException(
246           UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDTYPE);
247     }
248     final String fieldtype = value.getString();
249     final FieldRole fieldRole;
250     try {
251       fieldRole = FieldRole.valueOf(fieldtype);
252     } catch (final IllegalArgumentException e) {
253       logger.error(UNABLE_TO_LINK_VALUE_OF_FIELD + XML_HTTP_FIELDTYPE);
254       throw new InvalidArgumentException(
255           UNABLE_TO_LINK_VALUE_OF_FIELD + XML_HTTP_FIELDTYPE);
256     }
257     value = hash.get(XML_HTTP_FIELDINFO);
258     String fieldinfo = fieldname;
259     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
260       fieldinfo = value.getString();
261     }
262     value = hash.get(XML_HTTP_FIELDVALUE);
263     String fieldvalue = null;
264     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
265       fieldvalue = value.getString();
266     }
267     value = hash.get(XML_HTTP_FIELDVISIBILITY);
268     boolean fieldvisibility = true;
269     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
270       fieldvisibility = value.getBoolean();
271     }
272     value = hash.get(XML_HTTP_FIELDMANDATORY);
273     boolean fieldmandatory = true;
274     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
275       fieldmandatory = value.getBoolean();
276     }
277     value = hash.get(XML_HTTP_FIELDCOOKIESET);
278     boolean fieldcookieset = false;
279     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
280       fieldcookieset = value.getBoolean();
281     }
282     value = hash.get(XML_HTTP_FIELDTOVALIDATE);
283     boolean fieldtovalidate = false;
284     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
285       fieldtovalidate = value.getBoolean();
286     }
287     value = hash.get(XML_HTTP_FIELDPOSITION);
288     FieldPosition fieldposition = FieldPosition.ANY;
289     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
290       fieldposition = FieldPosition.valueOf(value.getString());
291     }
292     value = hash.get(XML_HTTP_FIELDRANK);
293     if (value == null || value.isEmpty() || value.getString().length() == 0) {
294       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDRANK);
295       throw new InvalidArgumentException(
296           UNABLE_TO_FIND_FIELD + XML_HTTP_FIELDRANK);
297     }
298     final int fieldrank = value.getInteger();
299     return new DefaultHttpField(fieldname, fieldRole, fieldinfo, fieldvalue,
300                                 fieldvisibility, fieldmandatory, fieldcookieset,
301                                 fieldtovalidate, fieldposition, fieldrank);
302   }
303 
304   static HttpPage loadHttpConfiguration(final XmlValue[] xmlValue)
305       throws InvalidArgumentException, ClassNotFoundException,
306              InstantiationException, IllegalAccessException {
307     final XmlHash hash = new XmlHash(xmlValue);
308     XmlValue value = hash.get(XML_HTTP_PAGENAME);
309     if (value == null || value.isEmpty() || value.getString().length() == 0) {
310       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_PAGENAME);
311       throw new InvalidArgumentException(
312           UNABLE_TO_FIND_FIELD + XML_HTTP_PAGENAME);
313     }
314     final String pagename = value.getString();
315     value = hash.get(XML_HTTP_FILEFORM);
316     String fileform = null;
317     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
318       fileform = value.getString();
319     }
320     value = hash.get(XML_HTTP_HEADER);
321     String header = null;
322     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
323       header = value.getString();
324     }
325     value = hash.get(XML_HTTP_FOOTER);
326     String footer = null;
327     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
328       footer = value.getString();
329     }
330     value = hash.get(XML_HTTP_BEGINFORM);
331     String beginform = null;
332     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
333       beginform = value.getString();
334     }
335     value = hash.get(XML_HTTP_ENDFORM);
336     String endform = null;
337     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
338       endform = value.getString();
339     }
340     value = hash.get(XML_HTTP_NEXTINFORM);
341     String nextinform = null;
342     if (value != null && !value.isEmpty() && value.getString().length() != 0) {
343       nextinform = value.getString();
344     }
345     value = hash.get(XML_HTTP_URI);
346     if (value == null || value.isEmpty() || value.getString().length() == 0) {
347       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_URI);
348       throw new InvalidArgumentException(UNABLE_TO_FIND_FIELD + XML_HTTP_URI);
349     }
350     final String uri = value.getString();
351     value = hash.get(XML_HTTP_PAGEROLE);
352     if (value == null || value.isEmpty() || value.getString().length() == 0) {
353       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_PAGEROLE);
354       throw new InvalidArgumentException(
355           UNABLE_TO_FIND_FIELD + XML_HTTP_PAGEROLE);
356     }
357     final String pagerole = value.getString();
358     final PageRole pageRole;
359     try {
360       pageRole = PageRole.valueOf(pagerole);
361     } catch (final IllegalArgumentException e) {
362       logger.error(UNABLE_TO_LINK_VALUE_OF_FIELD + XML_HTTP_PAGEROLE);
363       throw new InvalidArgumentException(
364           UNABLE_TO_LINK_VALUE_OF_FIELD + XML_HTTP_PAGEROLE);
365     }
366     value = hash.get(XML_HTTP_ERRORPAGE);
367     if (value == null || value.isEmpty() || value.getString().length() == 0) {
368       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_ERRORPAGE);
369       throw new InvalidArgumentException(
370           UNABLE_TO_FIND_FIELD + XML_HTTP_ERRORPAGE);
371     }
372     final String errorpage = value.getString();
373     value = hash.get(XML_HTTP_CLASSNAME);
374     if (value == null || value.isEmpty() || value.getString().length() == 0) {
375       logger.error(UNABLE_TO_FIND_FIELD + XML_HTTP_CLASSNAME);
376       throw new InvalidArgumentException(
377           UNABLE_TO_FIND_FIELD + XML_HTTP_CLASSNAME);
378     }
379     final String classname = value.getString();
380     // now getting Fields
381     value = hash.get(XML_HTTP_FIELD);
382     @SuppressWarnings("unchecked")
383     final List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
384     final List<AbstractHttpField> listFields =
385         new ArrayList<AbstractHttpField>(list.size());
386     // Now read the configuration
387     for (final XmlValue[] fieldValue : list) {
388       final AbstractHttpField field = loadHttpPage(fieldValue);
389       listFields.add(field.getFieldrank(), field);
390     }
391     list.clear();
392     final LinkedHashMap<String, AbstractHttpField> linkedHashMap =
393         new LinkedHashMap<String, AbstractHttpField>(listFields.size());
394     for (final AbstractHttpField abstractHttpField : listFields) {
395       linkedHashMap.put(abstractHttpField.getFieldname(), abstractHttpField);
396     }
397     listFields.clear();
398     return new HttpPage(pagename, fileform, header, footer, beginform, endform,
399                         nextinform, uri, pageRole, errorpage, classname,
400                         linkedHashMap);
401   }
402 
403   /**
404    * Initiate the configuration from the xml file for Http server
405    *
406    * @param filename
407    *
408    * @return the List<HttpPage> if OK
409    *
410    * @throws InvalidArgumentException
411    * @throws ClassNotFoundException
412    * @throws IllegalAccessException
413    * @throws InstantiationException
414    */
415   public static HttpPageHandler setConfigurationHttpServerFromXml(
416       final String filename)
417       throws InvalidArgumentException, ClassNotFoundException,
418              InstantiationException, IllegalAccessException {
419     final Document document;
420     // Open config file
421     try {
422       document = XmlUtil.getNewSaxReader().read(filename);
423     } catch (final DocumentException e) {
424       logger.error("Unable to read the XML Config file: " + filename + ": {}",
425                    e.getMessage());
426       throw new InvalidArgumentException(
427           "Unable to read XML file: " + filename);
428     }
429     if (document == null) {
430       logger.error("Unable to read the XML Config file: " + filename);
431       throw new InvalidArgumentException(
432           "Unable to parse XML file: " + filename);
433     }
434     final XmlValue[] values = XmlUtil.read(document, configHttpPages);
435     if (values.length <= 0) {
436       throw new InvalidArgumentException("XML file is empty");
437     }
438     final XmlValue value = values[0];
439     @SuppressWarnings("unchecked")
440     final List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
441     final HashMap<String, HttpPage> pages =
442         new HashMap<String, HttpPage>(list.size());
443     // Now read the configuration
444     for (final XmlValue[] xmlValue : list) {
445       final HttpPage page = loadHttpConfiguration(xmlValue);
446       pages.put(page.getUri(), page);
447     }
448     list.clear();
449     return new HttpPageHandler(pages);
450   }
451 
452   /**
453    * Construct a new Element with value
454    *
455    * @param name
456    * @param value
457    *
458    * @return the new Element
459    */
460   private static Element newElement(final String name, final String value) {
461     final Element node = new DefaultElement(name);
462     if (value != null && value.length() > 0) {
463       node.addText(value);
464     }
465     return node;
466   }
467 
468   static void addToField(final Element root, final AbstractHttpField field) {
469     root.add(newElement(XML_HTTP_FIELDNAME, field.getFieldname()));
470     root.add(newElement(XML_HTTP_FIELDTYPE, field.getFieldtype().name()));
471     root.add(newElement(XML_HTTP_FIELDINFO, field.getFieldinfo()));
472     root.add(newElement(XML_HTTP_FIELDVALUE, field.fieldvalue));
473     root.add(newElement(XML_HTTP_FIELDVISIBILITY,
474                         Boolean.toString(field.isFieldvisibility())));
475     root.add(newElement(XML_HTTP_FIELDMANDATORY,
476                         Boolean.toString(field.isFieldmandatory())));
477     root.add(newElement(XML_HTTP_FIELDCOOKIESET,
478                         Boolean.toString(field.isFieldcookieset())));
479     root.add(newElement(XML_HTTP_FIELDTOVALIDATE,
480                         Boolean.toString(field.isFieldtovalidate())));
481     root.add(
482         newElement(XML_HTTP_FIELDPOSITION, field.getFieldposition().name()));
483     root.add(
484         newElement(XML_HTTP_FIELDRANK, Integer.toString(field.getFieldrank())));
485   }
486 
487   static void addToElement(final Element root, final HttpPage page) {
488     root.add(newElement(XML_HTTP_PAGENAME, page.getPagename()));
489     root.add(newElement(XML_HTTP_FILEFORM, page.getFileform()));
490     root.add(newElement(XML_HTTP_HEADER, page.getHeader()));
491     root.add(newElement(XML_HTTP_FOOTER, page.getFooter()));
492     root.add(newElement(XML_HTTP_BEGINFORM, page.getBeginform()));
493     root.add(newElement(XML_HTTP_ENDFORM, page.getEndform()));
494     root.add(newElement(XML_HTTP_NEXTINFORM, page.getNextinform()));
495     root.add(newElement(XML_HTTP_URI, page.getUri()));
496     root.add(newElement(XML_HTTP_PAGEROLE, page.getPagerole().name()));
497     root.add(newElement(XML_HTTP_ERRORPAGE, page.getErrorpage()));
498     root.add(newElement(XML_HTTP_CLASSNAME, page.getClassname()));
499     final Element element = root.addElement(XML_HTTP_FIELDS);
500     for (final AbstractHttpField field : page.getFields().values()) {
501       final Element subroot = element.addElement(XML_HTTP_FIELD);
502       addToField(subroot, field);
503     }
504   }
505 
506   public static void exportConfiguration(final HttpPageHandler httpPageHandler,
507                                          final String filename)
508       throws HttpIncorrectRequestException {
509     final Document document = DocumentHelper.createDocument();
510     final Element root = document.addElement(XML_ROOT_NAME);
511     final Element subroot = root.addElement(XML_HTTP_PAGES);
512     for (final HttpPage page : httpPageHandler.getHashmap().values()) {
513       final Element element = subroot.addElement(XML_HTTP_PAGE);
514       addToElement(element, page);
515     }
516     try {
517       XmlUtil.writeXML(filename, null, document);
518     } catch (final IOException e) {
519       throw new HttpIncorrectRequestException("Cannot write file: " + filename,
520                                               e);
521     }
522   }
523 }