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.proxy.configuration;
21  
22  import org.dom4j.Document;
23  import org.dom4j.DocumentException;
24  import org.waarp.common.database.DbAdmin;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  import org.waarp.common.xml.XmlDecl;
28  import org.waarp.common.xml.XmlHash;
29  import org.waarp.common.xml.XmlRootHash;
30  import org.waarp.common.xml.XmlType;
31  import org.waarp.common.xml.XmlUtil;
32  import org.waarp.common.xml.XmlValue;
33  import org.waarp.openr66.protocol.configuration.Configuration;
34  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
35  import org.waarp.openr66.proxy.network.ProxyEntry;
36  
37  import java.net.InetSocketAddress;
38  
39  import static org.waarp.common.database.DbConstant.*;
40  import static org.waarp.openr66.configuration.FileBasedConfiguration.*;
41  import static org.waarp.openr66.configuration.FileBasedElements.*;
42  
43  /**
44   * File Based ConfigurationProxyR66
45   */
46  public class FileBasedConfiguration {
47    /**
48     * Internal Logger
49     */
50    private static final WaarpLogger logger =
51        WaarpLoggerFactory.getLogger(FileBasedConfiguration.class);
52  
53    /**
54     * SERVER Association entry
55     */
56    private static final String XML_SERVER_PROXY = "serverproxy";
57    /**
58     * SERVER Listening address
59     */
60    private static final String XML_SERVER_LISTENADDR = "serverlistenaddr";
61    /**
62     * SERVER Listening port
63     */
64    private static final String XML_SERVER_LISTENPORT = "serverlistenport";
65    /**
66     * SERVER Listening ssl mode
67     */
68    private static final String XML_SERVER_LISTENSSL = "serverlistenssl";
69    /**
70     * SERVER Remote address
71     */
72    private static final String XML_SERVER_REMOTEADDR = "serverremoteaddr";
73    /**
74     * SERVER Remote PORT
75     */
76    private static final String XML_SERVER_REMOTEPORT = "serverremoteport";
77    /**
78     * SERVER Remote ssl mode
79     */
80    private static final String XML_SERVER_REMOTESSL = "serverremotessl";
81  
82    /**
83     * Structure of the ConfigurationProxyR66 file
84     */
85    private static final XmlDecl[] configServerParamDecls = {
86        // server
87        new XmlDecl(XmlType.BOOLEAN, XML_USESSL),
88        new XmlDecl(XmlType.BOOLEAN, XML_USENOSSL),
89        new XmlDecl(XmlType.BOOLEAN, XML_USEHTTPCOMP),
90        new XmlDecl(XmlType.STRING, XML_SERVER_ADMIN),
91        new XmlDecl(XmlType.STRING, XML_SERVER_PASSWD),
92        new XmlDecl(XmlType.STRING, XML_SERVER_PASSWD_FILE),
93        new XmlDecl(XmlType.STRING, XML_HTTPADMINPATH),
94        new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPATH),
95        new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYSTOREPASS),
96        new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPASS),
97        new XmlDecl(XmlType.LONG, XML_MONITOR_PASTLIMIT),
98        new XmlDecl(XmlType.LONG, XML_MONITOR_MINIMALDELAY),
99        new XmlDecl(XmlType.STRING, XML_MONITOR_SNMP_CONFIG)
100   };
101   /**
102    * Structure of the ConfigurationProxyR66 file
103    */
104   private static final XmlDecl[] configNetworkProxyDecls = {
105       // proxy
106       new XmlDecl(XmlType.STRING, XML_SERVER_LISTENADDR),
107       new XmlDecl(XmlType.INTEGER, XML_SERVER_LISTENPORT),
108       new XmlDecl(XmlType.BOOLEAN, XML_SERVER_LISTENSSL),
109       new XmlDecl(XmlType.STRING, XML_SERVER_REMOTEADDR),
110       new XmlDecl(XmlType.INTEGER, XML_SERVER_REMOTEPORT),
111       new XmlDecl(XmlType.BOOLEAN, XML_SERVER_REMOTESSL)
112   };
113   /**
114    * Structure of the ConfigurationProxyR66 file
115    */
116   private static final XmlDecl[] configNetworkServerDecls = {
117       // network
118       new XmlDecl(XML_SERVER_PROXY, XmlType.XVAL, XML_SERVER_PROXY,
119                   configNetworkProxyDecls, true),
120       new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTPPORT),
121       new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTPSPORT)
122   };
123 
124   /**
125    * Structure of the ConfigurationProxyR66 file
126    */
127   private static final XmlDecl[] configDirectoryDecls = {
128       // directory
129       new XmlDecl(XmlType.STRING, XML_SERVER_HOME),
130       new XmlDecl(XmlType.STRING, XML_ARCHIVEPATH),
131       new XmlDecl(XmlType.STRING, XML_CONFIGPATH)
132   };
133 
134   /**
135    * Structure of the ConfigurationProxyR66 file
136    */
137   private static final XmlDecl[] configLimitDecls = {
138       // limit
139       new XmlDecl(XmlType.LONG, XML_LIMITSESSION),
140       new XmlDecl(XmlType.LONG, XML_LIMITGLOBAL),
141       new XmlDecl(XmlType.LONG, XML_LIMITDELAY),
142       new XmlDecl(XmlType.LONG, XML_DELAYRETRY),
143       new XmlDecl(XmlType.INTEGER, XML_SERVER_THREAD),
144       new XmlDecl(XmlType.INTEGER, XML_CLIENT_THREAD),
145       new XmlDecl(XmlType.LONG, XML_MEMORY_LIMIT),
146       new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPULIMIT),
147       new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPUJDKLIMIT),
148       new XmlDecl(XmlType.DOUBLE, XML_CSTRT_CPULIMIT),
149       new XmlDecl(XmlType.INTEGER, XML_CSTRT_CONNLIMIT),
150       new XmlDecl(XmlType.DOUBLE, XML_CSTRT_LOWCPULIMIT),
151       new XmlDecl(XmlType.DOUBLE, XML_CSTRT_HIGHCPULIMIT),
152       new XmlDecl(XmlType.DOUBLE, XML_CSTRT_PERCENTDECREASE),
153       new XmlDecl(XmlType.LONG, XML_CSTRT_LIMITLOWBANDWIDTH),
154       new XmlDecl(XmlType.LONG, XML_CSTRT_DELAYTHROTTLE),
155       new XmlDecl(XmlType.LONG, XML_TIMEOUTCON),
156       new XmlDecl(XmlType.BOOLEAN, XML_CHECKVERSION)
157   };
158 
159   /**
160    * Global Structure for Server ConfigurationProxyR66
161    */
162   private static final XmlDecl[] configServer = {
163       new XmlDecl(XML_IDENTITY, XmlType.XVAL, XML_ROOT + XML_IDENTITY,
164                   configIdentityDecls, false),
165       new XmlDecl(XML_SERVER, XmlType.XVAL, XML_ROOT + XML_SERVER,
166                   configServerParamDecls, false),
167       new XmlDecl(XML_NETWORK, XmlType.XVAL, XML_ROOT + XML_NETWORK,
168                   configNetworkServerDecls, false),
169       new XmlDecl(XML_SSL, XmlType.XVAL, XML_ROOT + XML_SSL, configSslDecls,
170                   false),
171       new XmlDecl(XML_DIRECTORY, XmlType.XVAL, XML_ROOT + XML_DIRECTORY,
172                   configDirectoryDecls, false),
173       new XmlDecl(XML_LIMIT, XmlType.XVAL, XML_ROOT + XML_LIMIT,
174                   configLimitDecls, false)
175   };
176 
177   private static XmlHash hashConfig;
178 
179   private FileBasedConfiguration() {
180   }
181 
182   private static boolean loadServerParam(final Configuration config) {
183     XmlHash hashConfigSub = new XmlHash(hashConfig.get(XML_SERVER));
184     try {
185       return org.waarp.openr66.configuration.FileBasedConfiguration.loadServerConfig(
186           config, hashConfigSub);
187     } finally {
188       hashConfigSub.clear();
189       hashConfigSub = null;
190     }
191   }
192 
193   private static boolean loadDirectory(final Configuration config) {
194     XmlHash hashConfigSub = new XmlHash(hashConfig.get(XML_DIRECTORY));
195     try {
196       if (loadMinimalDirectory(config, hashConfigSub)) {
197         return false;
198       }
199     } finally {
200       hashConfigSub.clear();
201       hashConfigSub = null;
202     }
203     return true;
204   }
205 
206   private static boolean alreadySetLimit;
207 
208   private static void loadLimit(final Configuration config,
209                                 final boolean updateLimit) {
210     if (alreadySetLimit) {
211       return;
212     }
213     final XmlHash hashConfigSub = new XmlHash(hashConfig.get(XML_LIMIT));
214     try {
215       loadCommonLimit(config, hashConfigSub, updateLimit);
216       if (config.getRunnerThread() < 10) {
217         config.setRunnerThread(10);
218       }
219       logger.info("Limit of Runner: {}", config.getRunnerThread());
220       alreadySetLimit = true;
221     } finally {
222       hashConfigSub.clear();
223     }
224   }
225 
226   @SuppressWarnings("unchecked")
227   private static boolean loadNetworkServer(final Configuration config) {
228     config.setServerPort(0);
229     config.setServerSslPort(0);
230     XmlValue value = hashConfig.get(XML_SERVER_HTTPPORT);
231     int httpport = 8066;
232     if (value != null && !value.isEmpty()) {
233       httpport = value.getInteger();
234     }
235     config.setServerHttpport(httpport);
236     value = hashConfig.get(XML_SERVER_HTTPSPORT);
237     int httpsport = 8067;
238     if (value != null && !value.isEmpty()) {
239       httpsport = value.getInteger();
240     }
241     config.setServerHttpsPort(httpsport);
242     // XXX FIXME to change to accept multiple port according to relation local-proxy
243     value = hashConfig.get(XML_SERVER_PROXY);
244     if (value != null && value.getList() != null) {
245       for (final XmlValue[] xml : (Iterable<XmlValue[]>) value.getList()) {
246         final XmlHash subHash = new XmlHash(xml);
247         value = subHash.get(XML_SERVER_LISTENADDR);
248         if (value == null || value.isEmpty()) {
249           continue;
250         }
251         final String listenaddr = value.getString();
252         value = subHash.get(XML_SERVER_LISTENPORT);
253         if (value == null || value.isEmpty()) {
254           continue;
255         }
256         final int listenport = value.getInteger();
257         value = subHash.get(XML_SERVER_LISTENSSL);
258         if (value == null || value.isEmpty()) {
259           continue;
260         }
261         final boolean listenssl = value.getBoolean();
262         value = subHash.get(XML_SERVER_REMOTEADDR);
263         if (value == null || value.isEmpty()) {
264           continue;
265         }
266         final String remoteaddr = value.getString();
267         value = subHash.get(XML_SERVER_REMOTEPORT);
268         if (value == null || value.isEmpty()) {
269           continue;
270         }
271         final int remoteport = value.getInteger();
272         value = subHash.get(XML_SERVER_REMOTESSL);
273         if (value == null || value.isEmpty()) {
274           continue;
275         }
276         final boolean remotessl = value.getBoolean();
277         final InetSocketAddress local =
278             new InetSocketAddress(listenaddr, listenport);
279         final InetSocketAddress remote =
280             new InetSocketAddress(remoteaddr, remoteport);
281         try {
282           ProxyEntry.add(local, listenssl, remote, remotessl);
283         } catch (final OpenR66ProtocolSystemException e) {
284           logger.error("Issue on configuration: {}", e.getMessage());
285           return false;
286         }
287       }
288       if (ProxyEntry.proxyEntries.isEmpty()) {
289         logger.error("No proxy configuration found");
290         return false;
291       }
292     } else {
293       logger.error("No proxy configuration found");
294       return false;
295     }
296     return true;
297   }
298 
299   /**
300    * Load database parameter
301    *
302    * @param config
303    *
304    * @return True if OK
305    */
306   private static boolean loadDatabase(final Configuration config) {
307     logger.info("No DBDriver in Config file for Proxy");
308     config.setSaveTaskRunnerWithNoDb(true);
309     admin = new DbAdmin(); // no database support
310     noCommitAdmin = admin;
311     return true;
312   }
313 
314   /**
315    * Initiate the configuration from the xml file for server
316    *
317    * @param config
318    * @param filename
319    *
320    * @return True if OK
321    */
322   public static boolean setConfigurationProxyFromXml(final Configuration config,
323                                                      final String filename) {
324     final Document document;
325     // Open config file
326     try {
327       document = XmlUtil.getNewSaxReader().read(filename);
328     } catch (final DocumentException e) {
329       logger.error("Unable to read the XML Config file: " + filename + ": {}",
330                    e.getMessage());
331       return false;
332     }
333     if (document == null) {
334       logger.error("Unable to read the XML Config file: " + filename);
335       return false;
336     }
337     XmlValue[] configuration = XmlUtil.read(document, configServer);
338     hashConfig = new XmlHash(configuration);
339     final XmlRootHash xmlRootHash = new XmlRootHash(configuration);
340     setXmlRootHash(xmlRootHash);
341     // Now read the configuration
342     if (!loadIdentity(config, xmlRootHash)) {
343       logger.error("Cannot load Identity");
344       return false;
345     }
346     if (!loadDatabase(config)) {
347       logger.error("Cannot load Database configuration");
348       return false;
349     }
350     if (!loadServerParam(config)) {
351       logger.error("Cannot load Server Parameters");
352       return false;
353     }
354     if (!loadDirectory(config)) {
355       logger.error("Cannot load Directory configuration");
356       return false;
357     }
358     loadLimit(config, false);
359     if (config.isUseSSL() && !loadSsl(config, xmlRootHash)) {
360       logger.error("Cannot load SSL configuration");
361       return false;
362     }
363     if (!loadNetworkServer(config)) {
364       logger.error("Cannot load Network configuration");
365       return false;
366     }
367     hashConfig.clear();
368     hashConfig = null;
369     xmlRootHash.clear();
370     configuration = null;
371     return true;
372   }
373 
374 }