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 io.netty.handler.codec.http.multipart.FileUpload;
23  import org.waarp.common.exception.FileTransferException;
24  import org.waarp.common.exception.InvalidArgumentException;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  import org.waarp.common.utility.ParametersChecker;
28  import org.waarp.common.utility.SingletonUtils;
29  import org.waarp.common.utility.WaarpStringUtils;
30  import org.waarp.common.utility.WaarpSystemUtil;
31  import org.waarp.gateway.kernel.AbstractHttpField.FieldPosition;
32  import org.waarp.gateway.kernel.exception.HttpIncorrectRequestException;
33  
34  import java.lang.reflect.InvocationTargetException;
35  import java.net.SocketAddress;
36  import java.util.LinkedHashMap;
37  import java.util.Map;
38  
39  /**
40   *
41   */
42  public class HttpPage {
43    /**
44     * Internal Logger
45     */
46    private static final WaarpLogger logger =
47        WaarpLoggerFactory.getLogger(HttpPage.class);
48  
49    public enum PageRole {
50      HTML, MENU, GETDOWNLOAD, POST, PUT, POSTUPLOAD, DELETE, ERROR
51    }
52  
53    /*
54     * pagename, fileform, header, footer, beginform, endform, nextinform, uri, pagerole, errorpage, classname,
55     * fields
56     */
57    private String pagename;
58    private String fileform;
59    private String header;
60    private String footer;
61    private String beginform;
62    private String endform;
63    private String nextinform;
64    private String uri;
65    private PageRole pagerole;
66    private String errorpage;
67    private String classname;
68    private Map<String, AbstractHttpField> fields;
69    private HttpBusinessFactory httpBusinessFactory;
70  
71    /**
72     * @param pagename
73     * @param fileform
74     * @param header
75     * @param footer
76     * @param beginform
77     * @param endform
78     * @param nextinform
79     * @param uri
80     * @param pagerole
81     * @param errorpage
82     * @param classname
83     * @param fields
84     *
85     * @throws ClassNotFoundException
86     * @throws IllegalAccessException
87     * @throws InstantiationException
88     */
89    public HttpPage(final String pagename, final String fileform,
90                    final String header, final String footer,
91                    final String beginform, final String endform,
92                    final String nextinform, final String uri,
93                    final PageRole pagerole, final String errorpage,
94                    final String classname,
95                    final Map<String, AbstractHttpField> fields)
96        throws ClassNotFoundException, InstantiationException,
97               IllegalAccessException {
98      setPagename(pagename);
99      setFileform(fileform);
100     if (getFileform() != null && getFileform().length() == 0) {
101       setFileform(null);
102     }
103     setHeader(header);
104     setFooter(footer);
105     setBeginform(beginform);
106     setEndform(endform);
107     setNextinform(nextinform);
108     setUri(uri);
109     setPagerole(pagerole);
110     setErrorpage(errorpage);
111     setClassname(classname);
112     setFields(fields);
113     try {
114       ParametersChecker.checkSanityString(classname);
115     } catch (final InvalidArgumentException e) {
116       throw new IllegalArgumentException(e.getMessage());
117     }
118     @SuppressWarnings("unchecked")
119     final HttpBusinessFactory factory;
120     try {
121       factory =
122           (HttpBusinessFactory) WaarpSystemUtil.newInstance(classname);//NOSONAR
123     } catch (final InvocationTargetException e) {
124       throw new InstantiationException(e.getMessage());
125     }
126     setHttpBusinessFactory(factory);//NOSONAR
127   }
128 
129   /**
130    * Called at the beginning of every request to get the current
131    * HttpBusinessFactory to use.
132    *
133    * @param remoteAddress the remote socket address in use
134    *
135    * @return AbstractHttpBusinessRequest to use during the request
136    */
137   public AbstractHttpBusinessRequest newRequest(
138       final SocketAddress remoteAddress) {
139     final LinkedHashMap<String, AbstractHttpField> linkedHashMap =
140         new LinkedHashMap<String, AbstractHttpField>(getFields().size());
141     for (final AbstractHttpField field : getFields().values()) {
142       final AbstractHttpField newfield = field.clone();
143       if (getPagerole() != PageRole.MENU) {
144         newfield.fieldvalue = null;
145       }
146       linkedHashMap.put(field.getFieldname(), newfield);
147     }
148     return getHttpBusinessFactory().getNewHttpBusinessRequest(remoteAddress,
149                                                               linkedHashMap,
150                                                               this);
151   }
152 
153   public final String getPageValue(final String value) {
154     if (getFileform() != null && value != null) {
155       try {
156         return WaarpStringUtils.readFileException(getFileform() + value);
157       } catch (final FileTransferException ignored) {
158         // nothing
159       }
160     }
161     return value;
162   }
163 
164   /**
165    * @param reference
166    *
167    * @return the Html results for all pages except Get (result of a download)
168    *
169    * @throws HttpIncorrectRequestException
170    */
171   public final String getHtmlPage(final AbstractHttpBusinessRequest reference)
172       throws HttpIncorrectRequestException {
173     if (reference == null) {
174       return "<HTML><HEADER/>ERROR</HTML>";
175     }
176     if (getPagerole() == PageRole.HTML) {
177       return getSimpleHtml(reference);
178     }
179     final boolean isForm = reference.isForm();
180     String value = reference.getHeader();
181     if (value == null || value.length() == 0) {
182       value = getPageValue(getHeader());
183     }
184     final StringBuilder builder;
185     if (value == null) {
186       builder = new StringBuilder();
187     } else {
188       builder = new StringBuilder(value);
189     }
190     final Map<String, AbstractHttpField> requestFields =
191         reference.getMapHttpFields();
192     setFromPossibleForm(reference, isForm, builder, requestFields);
193     setFields(reference, isForm, builder, requestFields);
194     finalizePage(reference, isForm, builder);
195     return builder.toString();
196   }
197 
198   private void finalizePage(final AbstractHttpBusinessRequest reference,
199                             final boolean isForm, final StringBuilder builder) {
200     String value;
201     if (!isForm) {
202       value = reference.getEndForm();
203       if (value == null || value.length() == 0) {
204         value = getPageValue(getEndform());
205       }
206       if (value != null) {
207         builder.append(value);
208       } else {
209         builder.append("</TABLE><BR>");
210       }
211     } else {
212       value = reference.getEndForm();
213       if (value == null || value.length() == 0) {
214         value = getPageValue(getEndform());
215       }
216       if (value != null) {
217         builder.append(value);
218       }
219     }
220     value = reference.getFooter();
221     if (value == null || value.length() == 0) {
222       value = getPageValue(getFooter());
223     }
224     if (value != null) {
225       builder.append(value);
226     }
227   }
228 
229   private void setFields(final AbstractHttpBusinessRequest reference,
230                          final boolean isForm, final StringBuilder builder,
231                          final Map<String, AbstractHttpField> requestFields)
232       throws HttpIncorrectRequestException {
233     String value;
234     boolean first = true;
235     for (final AbstractHttpField field : requestFields.values()) {
236       if (field.isFieldvisibility()) {
237         // to prevent that last will have a next field form
238         if (first) {
239           first = false;
240         } else {
241           value = reference.getNextFieldInForm();
242           if (value == null || value.length() == 0) {
243             value = getPageValue(getNextinform());
244           }
245           if (value != null) {
246             builder.append(value);
247           }
248         }
249         value = reference.getFieldForm(field);
250         if (value == null || value.length() == 0) {
251           if (isForm) {
252             value = field.getHtmlFormField(this);
253           } else {
254             value = field.getHtmlTabField(this);
255           }
256         }
257         if (value != null) {
258           builder.append(value);
259         }
260       }
261     }
262   }
263 
264   private void setFromPossibleForm(final AbstractHttpBusinessRequest reference,
265                                    final boolean isForm,
266                                    final StringBuilder builder,
267                                    final Map<String, AbstractHttpField> requestFields) {
268     String value;
269     if (!isForm) {
270       value = reference.getBeginForm();
271       if (value == null || value.length() == 0) {
272         value = getPageValue(getBeginform());
273       }
274       if (value != null) {
275         builder.append(value);
276       } else {
277         builder.append("<BR><TABLE border=1><TR>");
278         for (final AbstractHttpField field : requestFields.values()) {
279           if (field.isFieldvisibility()) {
280             builder.append("<TH>").append(field.getFieldinfo()).append("</TH>");
281           }
282         }
283         builder.append("<TR>");
284       }
285     } else {
286       value = reference.getBeginForm();
287       if (value == null || value.length() == 0) {
288         value = getPageValue(getBeginform());
289       }
290       if (value != null) {
291         builder.append(value);
292       }
293     }
294   }
295 
296   private String getSimpleHtml(final AbstractHttpBusinessRequest reference) {
297     // No handling of variable management, use MENU instead
298     String value = reference.getHeader();
299     logger.debug("Debug: {}", value != null);
300     if (value == null || value.length() == 0) {
301       value = getPageValue(getHeader());
302     }
303     final StringBuilder builder;
304     if (value == null) {
305       builder = new StringBuilder();
306     } else {
307       builder = new StringBuilder(value);
308     }
309     value = reference.getBeginForm();
310     if (value == null || value.length() == 0) {
311       value = getPageValue(getBeginform());
312     }
313     if (value != null) {
314       builder.append(value);
315     }
316     value = reference.getEndForm();
317     if (value == null || value.length() == 0) {
318       value = getPageValue(getEndform());
319     }
320     if (value != null) {
321       builder.append(value);
322     }
323     value = reference.getFooter();
324     if (value == null || value.length() == 0) {
325       value = getPageValue(getFooter());
326     }
327     if (value != null) {
328       builder.append(value);
329     }
330     return builder.toString();
331   }
332 
333   /**
334    * Set the value to the field according to fieldname.
335    * <p>
336    * If the field is not registered, the field is ignored.
337    *
338    * @param reference
339    * @param fieldname
340    * @param value
341    * @param position
342    *
343    * @throws HttpIncorrectRequestException
344    */
345   public final void setValue(final AbstractHttpBusinessRequest reference,
346                              final String fieldname, final String value,
347                              final FieldPosition position)
348       throws HttpIncorrectRequestException {
349     if (reference == null) {
350       return;
351     }
352     final Map<String, AbstractHttpField> requestFields =
353         reference.getMapHttpFields();
354     final AbstractHttpField field = requestFields.get(fieldname);
355     if (field != null) {
356       if (field.getFieldposition() == FieldPosition.ANY ||
357           field.getFieldposition() == position) {
358         field.setStringValue(value);
359         if (field.isFieldtovalidate() && !reference.isFieldValid(field)) {
360           throw new HttpIncorrectRequestException(
361               "Field unvalid: " + fieldname);
362         }
363       } else {
364         throw new HttpIncorrectRequestException(
365             "Invalid position: " + position +
366             " while field is supposed to be in " + field.getFieldposition());
367       }
368     }
369   }
370 
371   /**
372    * Set the value to the field according to fieldname.
373    * <p>
374    * If the field is not registered, the field is ignored.
375    *
376    * @param reference
377    * @param fieldname
378    *
379    * @throws HttpIncorrectRequestException
380    */
381   public final void setValue(final AbstractHttpBusinessRequest reference,
382                              final String fieldname,
383                              final FileUpload fileUpload)
384       throws HttpIncorrectRequestException {
385     final Map<String, AbstractHttpField> requestFields =
386         reference.getMapHttpFields();
387     final AbstractHttpField field = requestFields.get(fieldname);
388     if (field != null) {
389       field.setFileUpload(fileUpload);
390       if (field.isFieldtovalidate() && !reference.isFieldValid(field)) {
391         throw new HttpIncorrectRequestException("Field unvalid: " + fieldname);
392       }
393     }
394   }
395 
396   /**
397    * @param reference
398    *
399    * @return True if the request is fully valid
400    */
401   public final boolean isRequestValid(
402       final AbstractHttpBusinessRequest reference) {
403     if (reference == null) {
404       return true;
405     }
406     final Map<String, AbstractHttpField> requestFields =
407         reference.getMapHttpFields();
408     for (final AbstractHttpField field : requestFields.values()) {
409       if (field.isFieldmandatory() && !field.isPresent()) {
410         logger.warn("Request invalid since the following field is absent: " +
411                     field.getFieldname());
412         return false;
413       }
414     }
415     return reference.isRequestValid();
416   }
417 
418   /**
419    * Convenient method to get the fields list
420    *
421    * @param reference
422    *
423    * @return the fields list from the current AbstractHttpBusinessRequest
424    */
425   public final Map<String, AbstractHttpField> getFieldsForRequest(
426       final AbstractHttpBusinessRequest reference) {
427     if (reference == null) {
428       return SingletonUtils.singletonMap();
429     }
430     return reference.getMapHttpFields();
431   }
432 
433   /**
434    * Convenient method to get the value of one field
435    *
436    * @param reference
437    * @param fieldname
438    *
439    * @return the String value
440    */
441   public final String getValue(final AbstractHttpBusinessRequest reference,
442                                final String fieldname) {
443     final AbstractHttpField field = reference.getMapHttpFields().get(fieldname);
444     if (field != null) {
445       return field.fieldvalue;
446     }
447     return null;
448   }
449 
450   /**
451    * Convenient method to get the value of one field
452    *
453    * @param reference
454    * @param fieldname
455    *
456    * @return the FileUpload value
457    */
458   public final FileUpload getFileUpload(
459       final AbstractHttpBusinessRequest reference, final String fieldname) {
460     final AbstractHttpField field = reference.getMapHttpFields().get(fieldname);
461     if (field != null) {
462       return field.fileUpload;
463     }
464     return null;
465   }
466 
467   /**
468    * Convenient method to get one field
469    *
470    * @param reference
471    * @param fieldname
472    *
473    * @return the AbstractHttpField value
474    */
475   public final AbstractHttpField getField(
476       final AbstractHttpBusinessRequest reference, final String fieldname) {
477     return reference.getMapHttpFields().get(fieldname);
478   }
479 
480   /**
481    * @return the pagename
482    */
483   public final String getPagename() {
484     return pagename;
485   }
486 
487   /**
488    * @param pagename the pagename to set
489    */
490   private void setPagename(final String pagename) {
491     this.pagename = pagename;
492   }
493 
494   /**
495    * @return the fileform
496    */
497   public final String getFileform() {
498     return fileform;
499   }
500 
501   /**
502    * @param fileform the fileform to set
503    */
504   private void setFileform(final String fileform) {
505     this.fileform = fileform;
506   }
507 
508   /**
509    * @return the header
510    */
511   public final String getHeader() {
512     return header;
513   }
514 
515   /**
516    * @param header the header to set
517    */
518   private void setHeader(final String header) {
519     this.header = header;
520   }
521 
522   /**
523    * @return the footer
524    */
525   public final String getFooter() {
526     return footer;
527   }
528 
529   /**
530    * @param footer the footer to set
531    */
532   private void setFooter(final String footer) {
533     this.footer = footer;
534   }
535 
536   /**
537    * @return the beginform
538    */
539   public final String getBeginform() {
540     return beginform;
541   }
542 
543   /**
544    * @param beginform the beginform to set
545    */
546   private void setBeginform(final String beginform) {
547     this.beginform = beginform;
548   }
549 
550   /**
551    * @return the endform
552    */
553   public final String getEndform() {
554     return endform;
555   }
556 
557   /**
558    * @param endform the endform to set
559    */
560   private void setEndform(final String endform) {
561     this.endform = endform;
562   }
563 
564   /**
565    * @return the nextinform
566    */
567   public final String getNextinform() {
568     return nextinform;
569   }
570 
571   /**
572    * @param nextinform the nextinform to set
573    */
574   private void setNextinform(final String nextinform) {
575     this.nextinform = nextinform;
576   }
577 
578   /**
579    * @return the uri
580    */
581   public final String getUri() {
582     return uri;
583   }
584 
585   /**
586    * @param uri the uri to set
587    */
588   private void setUri(final String uri) {
589     this.uri = uri;
590   }
591 
592   /**
593    * @return the pagerole
594    */
595   public final PageRole getPagerole() {
596     return pagerole;
597   }
598 
599   /**
600    * @param pagerole the pagerole to set
601    */
602   private void setPagerole(final PageRole pagerole) {
603     this.pagerole = pagerole;
604   }
605 
606   /**
607    * @return the errorpage
608    */
609   public final String getErrorpage() {
610     return errorpage;
611   }
612 
613   /**
614    * @param errorpage the errorpage to set
615    */
616   private void setErrorpage(final String errorpage) {
617     this.errorpage = errorpage;
618   }
619 
620   /**
621    * @return the classname
622    */
623   public final String getClassname() {
624     return classname;
625   }
626 
627   /**
628    * @param classname the classname to set
629    */
630   private void setClassname(final String classname) {
631     this.classname = classname;
632   }
633 
634   /**
635    * @return the fields
636    */
637   public final Map<String, AbstractHttpField> getFields() {
638     return fields;
639   }
640 
641   /**
642    * @param fields the fields to set
643    */
644   private void setFields(final Map<String, AbstractHttpField> fields) {
645     this.fields = fields;
646   }
647 
648   /**
649    * @return the httpBusinessFactory
650    */
651   public final HttpBusinessFactory getHttpBusinessFactory() {
652     return httpBusinessFactory;
653   }
654 
655   /**
656    * @param httpBusinessFactory the httpBusinessFactory to set
657    */
658   private void setHttpBusinessFactory(
659       final HttpBusinessFactory httpBusinessFactory) {
660     this.httpBusinessFactory = httpBusinessFactory;
661   }
662 }