View Javadoc

1   /*
2    * Copyright (C) 2017-2019 Centre National d'Etudes Spatiales (CNES).
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 3.0 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17   * MA 02110-1301  USA
18   */
19  package fr.cnes.doi.settings;
20  
21  import fr.cnes.doi.utils.spec.Requirement;
22  import org.apache.logging.log4j.LogManager;
23  import org.apache.logging.log4j.Logger;
24  import org.restlet.Server;
25  import org.restlet.data.Parameter;
26  import org.restlet.ext.jetty.JettyServerHelper;
27  
28  /**
29   * Fills Jetty configuration file based on DoiSettings and registers it in
30   * Jetty.
31   *
32   * @author Jean-Christophe Malapert
33   */
34  @Requirement(reqId = Requirement.DOI_CONFIG_010, reqName = Requirement.DOI_CONFIG_010_NAME)
35  public final class JettySettings extends JettyServerHelper {
36  
37      /**
38       * Logger.
39       */
40      private static final Logger LOG = LogManager.getLogger(JettySettings.class.getName());
41  
42      /**
43       * DOI settings.
44       */
45      private final DoiSettings settings;
46  
47      /**
48       * Server.
49       */
50      private final Server server;
51  
52      /**
53       * Constructs settings for Jetty.
54       *
55       * @param server Jetty server
56       * @param settings DOI settings
57       */
58      public JettySettings(final Server server,
59              final DoiSettings settings) {
60          super(server);
61          LOG.trace("Entering in Constructor");
62          this.server = server;
63          this.settings = settings;
64          LOG.trace("Exiting from Constructor");
65      }
66  
67      /**
68       * HTTP request header size in bytes. Defaults to 8*1024. Larger headers
69       * will allow for more and/or larger cookies plus larger form content
70       * encoded in a URL. However, larger headers consume more memory and can
71       * make a server more vulnerable to denial of service attacks.
72       *
73       * @return HTTP request header size.
74       */
75      @Override
76      public int getHttpRequestHeaderSize() {
77          LOG.traceEntry();
78          int result;
79          try {
80              result = settings.getInt(Consts.JETTY_REQUEST_HEADER_SIZE);
81              LOG.debug("getHttpRequestHeaderSize : default value from configuration file loaded");
82          } catch (NumberFormatException e) {
83              result = super.getHttpRequestHeaderSize();
84              LOG.debug("getHttpRequestHeaderSize : default value loaded");
85          }
86          LOG.info("getHttpRequestHeaderSize : {}", result);
87          return LOG.traceExit(result);
88      }
89  
90      /**
91       * HTTP response header size in bytes. Defaults to 8*1024. Larger headers
92       * will allow for more and/or larger cookies and longer HTTP headers (e.g.
93       * for redirection). However, larger headers will also consume more memory.
94       *
95       * @return HTTP response header size.
96       */
97      @Override
98      public int getHttpResponseHeaderSize() {
99          LOG.traceEntry();
100         int result;
101         try {
102             result = settings.getInt(Consts.JETTY_RESPONSE_HEADER_SIZE);
103             LOG.debug("getHttpResponseHeaderSize : default value from configuration file loaded");
104         } catch (NumberFormatException e) {
105             result = super.getHttpResponseHeaderSize();
106             LOG.debug("getHttpResponseHeaderSize : default value loaded");
107         }
108         LOG.info("getHttpResponseHeaderSize : {}", result);
109         LOG.trace("Exiting from getHttpResponseHeaderSize with result {}", result);
110         return result;
111     }
112 
113     /**
114      * Thread pool minimum threads. Defaults to 8.
115      *
116      * @return Thread pool minimum threads.
117      */
118     @Override
119     public int getThreadPoolMinThreads() {
120         LOG.traceEntry();
121         int result;
122         try {
123             result = settings.getInt(Consts.JETTY_MIN_THREADS);
124             LOG.debug("getThreadPoolMinThreads : default value from configuration file loaded");
125         } catch (NumberFormatException e) {
126             result = super.getThreadPoolMinThreads();
127             LOG.debug("getThreadPoolMinThreads : default value loaded");
128         }
129         LOG.info("getThreadPoolMinThreads : {}", result);
130         return LOG.traceExit(result);
131     }
132 
133     /**
134      * Thread pool maximum threads. Defaults to 200.
135      *
136      * @return Thread pool maximum threads.
137      */
138     @Override
139     public int getThreadPoolMaxThreads() {
140         LOG.traceEntry();
141         int result;
142         try {
143             result = settings.getInt(Consts.JETTY_MAX_THREADS);
144             LOG.debug("getThreadPoolMaxThreads : default value from configuration file loaded");
145         } catch (NumberFormatException e) {
146             result = super.getThreadPoolMaxThreads();
147             LOG.debug("getThreadPoolMaxThreads : default value loaded");
148         }
149         LOG.info("getThreadPoolMaxThreads : {}", result);
150         return LOG.traceExit(result);
151     }
152 
153     /**
154      * Thread pool threads priority. Defaults to Thread.NORM_PRIORITY.
155      *
156      * @return Thread pool maximum threads.
157      */
158     @Override
159     public int getThreadPoolThreadsPriority() {
160         LOG.traceEntry();
161         int result;
162         try {
163             result = settings.getInt(Consts.JETTY_THREADS_PRIORITY);
164             LOG.debug("getThreadPoolThreadsPriority : default value from configuration file loaded");
165         } catch (NumberFormatException e) {
166             result = super.getThreadPoolThreadsPriority();
167             LOG.debug("getThreadPoolThreadsPriority : default value loaded");
168         }
169         LOG.info("getThreadPoolThreadsPriority : {}", result);
170         return LOG.traceExit(result);
171     }
172 
173     /**
174      * Thread pool idle timeout in milliseconds. Defaults to 60000. Threads that
175      * are idle for longer than this period may be stopped.
176      *
177      * @return Thread pool idle timeout.
178      */
179     @Override
180     public int getThreadPoolIdleTimeout() {
181         LOG.traceEntry();
182         int result;
183         try {
184             result = settings.getInt(Consts.JETTY_THREAD_MAX_IDLE_TIME_MS);
185             LOG.debug("getThreadPoolIdleTimeout : default value from configuration file loaded");
186         } catch (NumberFormatException e) {
187             result = super.getThreadPoolIdleTimeout();
188             LOG.debug("getThreadPoolIdleTimeout : default value loaded");
189         }
190         LOG.info("getThreadPoolIdleTimeout : {}", result);
191         return LOG.traceExit(result);
192     }
193 
194     /**
195      * Thread pool stop timeout in milliseconds. Defaults to 5000. The maximum
196      * time allowed for the service to shutdown.
197      *
198      * @return Thread pool stop timeout.
199      */
200     @Override
201     public long getThreadPoolStopTimeout() {
202         LOG.traceEntry();
203         long result;
204         try {
205             result = settings.getLong(Consts.JETTY_THREAD_STOP_TIME_MS);
206             LOG.debug("getThreadPoolStopTimeout : default value from configuration file loaded");
207         } catch (NumberFormatException e) {
208             result = super.getThreadPoolStopTimeout();
209             LOG.debug("getThreadPoolStopTimeout : default value loaded");
210         }
211         LOG.info("getThreadPoolStopTimeout : {}", result);
212         return LOG.traceExit(result);
213     }
214 
215     /**
216      * Connector acceptor thread count. Defaults to -1. When -1, Jetty will
217      * default to Runtime.availableProcessors() / 2, with a minimum of 1.
218      *
219      * @return Connector acceptor thread count.
220      */
221     @Override
222     public int getConnectorAcceptors() {
223         LOG.traceEntry();
224         int result;
225         try {
226             result = settings.getInt(Consts.JETTY_ACCEPTOR_THREADS);
227             LOG.debug("getConnectorAcceptors : default value from configuration file loaded");
228         } catch (NumberFormatException e) {
229             result = super.getConnectorAcceptors();
230             LOG.debug("getConnectorAcceptors : default value loaded");
231         }
232         LOG.info("getConnectorAcceptors : {}", result);
233         return LOG.traceExit(result);
234     }
235 
236     /**
237      * Connector selector thread count. Defaults to -1. When 0, Jetty will
238      * default to Runtime.availableProcessors().
239      *
240      * @return Connector acceptor thread count.
241      */
242     @Override
243     public int getConnectorSelectors() {
244         LOG.traceEntry();
245         int result;
246         try {
247             result = settings.getInt(Consts.JETTY_SELECTOR_THREADS);
248             LOG.debug("getConnectorSelectors : default value from configuration file loaded");
249         } catch (NumberFormatException e) {
250             result = super.getConnectorSelectors();
251             LOG.debug("getConnectorSelectors : default value loaded");
252         }
253         LOG.info("getConnectorSelectors : {}", result);
254         return LOG.traceExit(result);
255     }
256 
257     /**
258      * Low resource monitor idle timeout in milliseconds. Defaults to 1000.
259      * Applied to EndPoints when in the low resources state.
260      *
261      * @return Low resource monitor idle timeout.
262      */
263     @Override
264     public int getLowResourceMonitorIdleTimeout() {
265         LOG.traceEntry();
266         int result;
267         try {
268             result = settings.getInt(Consts.JETTY_LOW_RESOURCES_MAX_IDLE_TIME_MS);
269             LOG.debug(
270                     "getLowResourceMonitorIdleTimeout : default value from configuration file loaded");
271         } catch (NumberFormatException e) {
272             result = super.getLowResourceMonitorIdleTimeout();
273             LOG.debug("getLowResourceMonitorIdleTimeout : default value loaded");
274         }
275         LOG.info("getLowResourceMonitorIdleTimeout : {}", result);
276         return LOG.traceExit(result);
277     }
278 
279     /**
280      * Low resource monitor period in milliseconds. Defaults to 1000. When 0,
281      * low resource monitoring is disabled.
282      *
283      * @return Low resource monitor period.
284      */
285     @Override
286     public int getLowResourceMonitorPeriod() {
287         LOG.traceEntry();
288         int result;
289         try {
290             result = settings.getInt(Consts.JETTY_LOW_RESOURCES_PERIOD);
291             LOG.debug("getLowResourceMonitorPeriod : default value from configuration file loaded");
292         } catch (NumberFormatException e) {
293             result = super.getLowResourceMonitorPeriod();
294             LOG.debug("getLowResourceMonitorPeriod : default value loaded");
295         }
296         LOG.info("getLowResourceMonitorPeriod : {}", result);
297         return LOG.traceExit(result);
298     }
299 
300     /**
301      * Low resource monitor max memory in bytes. Defaults to 0. When 0, the
302      * check disabled. Memory used is calculated as (totalMemory-freeMemory).
303      *
304      * @return Low resource monitor max memory.
305      */
306     @Override
307     public long getLowResourceMonitorMaxMemory() {
308         LOG.traceEntry();
309         long result;
310         try {
311             result = settings.getLong(Consts.JETTY_LOW_RESOURCES_MAX_MEMORY);
312             LOG.debug(
313                     "getLowResourceMonitorMaxMemory : default value from configuration file loaded");
314         } catch (NumberFormatException e) {
315             result = super.getLowResourceMonitorMaxMemory();
316             LOG.debug("getLowResourceMonitorMaxMemory : default value loaded");
317         }
318         LOG.info("getLowResourceMonitorMaxMemory : {}", result);
319         return LOG.traceExit(result);
320     }
321 
322     /**
323      * Low resource monitor max connections. Defaults to 0. When 0, the check is
324      * disabled.
325      *
326      * @return Low resource monitor max connections.
327      */
328     @Override
329     public int getLowResourceMonitorMaxConnections() {
330         LOG.traceEntry();
331         int result;
332         try {
333             result = settings.getInt(Consts.JETTY_LOW_RESOURCES_MAX_MEMORY);
334             LOG.debug(
335                     "getLowResourceMonitorMaxConnections : default value from configuration file loaded");
336         } catch (NumberFormatException e) {
337             result = super.getLowResourceMonitorMaxConnections();
338             LOG.debug("getLowResourceMonitorMaxConnections : default value loaded");
339         }
340         LOG.info("getLowResourceMonitorMaxConnections : {}", result);
341         return LOG.traceExit(result);
342     }
343 
344     /**
345      * Low resource monitor, whether to check if we're low on threads. Defaults
346      * to true.
347      *
348      * @return Low resource monitor threads.
349      */
350     @Override
351     public boolean getLowResourceMonitorThreads() {
352         LOG.traceEntry();
353         boolean result;
354         try {
355             result = settings.getBoolean(Consts.JETTY_LOW_RESOURCES_THREADS);
356             LOG.debug("getLowResourceMonitorThreads : default value from configuration file loaded");
357         } catch (IllegalArgumentException e) {
358             result = super.getLowResourceMonitorThreads();
359             LOG.debug("getLowResourceMonitorThreads : default value loaded");
360         }
361         LOG.info("getLowResourceMonitorThreads : {}", result);
362         return LOG.traceExit(result);
363     }
364 
365     /**
366      * Connector accept queue size. Defaults to 0. Also known as accept backlog.
367      *
368      * @return Connector accept queue size.
369      */
370     @Override
371     public int getConnectorAcceptQueueSize() {
372         LOG.traceEntry();
373         int result;
374         try {
375             result = settings.getInt(Consts.JETTY_ACCEPT_QUEUE_SIZE);
376             LOG.debug("getConnectorAcceptQueueSize : default value from configuration file loaded");
377         } catch (NumberFormatException e) {
378             result = super.getConnectorAcceptQueueSize();
379             LOG.debug("getConnectorAcceptQueueSize : default value loaded");
380         }
381         LOG.info("getConnectorAcceptQueueSize : {}", result);
382         return LOG.traceExit(result);
383     }
384 
385     /**
386      * Connector TCP/IP SO linger time in milliseconds. Defaults to -1
387      * (disabled).
388      *
389      * @return Connector TCP/IP SO linger time.
390      */
391     @Override
392     public int getConnectorSoLingerTime() {
393         LOG.traceEntry();
394         int result;
395         try {
396             result = settings.getInt(Consts.JETTY_SO_LINGER_TIME);
397             LOG.debug("getConnectorSoLingerTime : default value from configuration file loaded");
398         } catch (NumberFormatException e) {
399             result = super.getConnectorSoLingerTime();
400             LOG.debug("getConnectorSoLingerTime : default value loaded");
401         }
402         LOG.info("getConnectorSoLingerTime : {}", result);
403         return LOG.traceExit(result);
404     }
405 
406     /**
407      * Connector idle timeout in milliseconds. Defaults to 30000. This value is
408      * interpreted as the maximum time between some progress being made on the
409      * connection. So if a single byte is read or written, then the timeout is
410      * reset.
411      *
412      * @return Connector idle timeout.
413      */
414     @Override
415     public int getConnectorIdleTimeout() {
416         LOG.traceEntry();
417         int result;
418         try {
419             result = settings.getInt(Consts.JETTY_IO_MAX_IDLE_TIME_MS);
420             LOG.debug("getConnectorIdleTimeout : default value from configuration file loaded");
421         } catch (NumberFormatException e) {
422             result = super.getConnectorIdleTimeout();
423             LOG.debug("getConnectorIdleTimeout : default value loaded");
424         }
425         LOG.info("getConnectorIdleTimeout : {}", result);
426         return LOG.traceExit(result);
427     }
428 
429     /**
430      * HTTP output buffer size in bytes. Defaults to 32*1024. A larger buffer
431      * can improve performance by allowing a content producer to run without
432      * blocking, however larger buffers consume more memory and may induce some
433      * latency before a client starts processing the content.
434      *
435      * @return HTTP output buffer size.
436      */
437     @Override
438     public int getHttpOutputBufferSize() {
439         LOG.traceEntry();
440         int result;
441         try {
442             result = settings.getInt(Consts.JETTY_RESPONSE_BUFFER_SIZE);
443             LOG.debug("getHttpOutputBufferSize : default value from configuration file loaded");
444         } catch (NumberFormatException e) {
445             result = super.getHttpOutputBufferSize();
446             LOG.debug("getHttpOutputBufferSize : default value loaded");
447         }
448         LOG.info("getHttpOutputBufferSize : {}", result);
449         return LOG.traceExit(result);
450     }
451 
452     /**
453      * HTTP header cache size in bytes. Defaults to 512.
454      *
455      * @return HTTP header cache size.
456      */
457     @Override
458     public int getHttpHeaderCacheSize() {
459         LOG.traceEntry();
460         int result;
461         try {
462             result = settings.getInt(Consts.JETTY_REQUEST_BUFFER_SIZE);
463             LOG.debug("getHttpHeaderCacheSize : default value from configuration file loaded");
464         } catch (NumberFormatException e) {
465             result = super.getHttpHeaderCacheSize();
466             LOG.debug("getHttpHeaderCacheSize : default value loaded");
467         }
468         LOG.info("getHttpHeaderCacheSize : {}", result);
469         return LOG.traceExit(result);
470     }
471 
472     /**
473      * Connector stop timeout in milliseconds. Defaults to 30000. The maximum
474      * time allowed for the service to shutdown.
475      *
476      * @return Connector stop timeout.
477      */
478     @Override
479     public int getConnectorStopTimeout() {
480         LOG.traceEntry();
481         int result;
482         try {
483             result = settings.getInt(Consts.JETTY_GRACEFUL_SHUTDOWN);
484             LOG.debug("getConnectorStopTimeout : default value from configuration file loaded");
485         } catch (NumberFormatException e) {
486             result = super.getConnectorStopTimeout();
487             LOG.debug("getConnectorStopTimeout : default value loaded");
488         }
489         LOG.info("getConnectorStopTimeout : {}", result);
490         return LOG.traceExit(result);
491     }
492 
493     /**
494      * Low resource monitor stop timeout in milliseconds. Defaults to 30000. The
495      * maximum time allowed for the service to shutdown.
496      *
497      * @return Low resource monitor stop timeout.
498      */
499     @Override
500     public long getLowResourceMonitorStopTimeout() {
501         LOG.traceEntry();
502         long result;
503         try {
504             result = settings.getLong(Consts.JETTY_GRACEFUL_SHUTDOWN);
505             LOG.debug(
506                     "getLowResourceMonitorStopTimeout : default value from configuration file loaded");
507         } catch (NumberFormatException e) {
508             result = super.getLowResourceMonitorStopTimeout();
509             LOG.debug("getLowResourceMonitorStopTimeout : default value loaded");
510         }
511         LOG.info("getLowResourceMonitorStopTimeout : {}", result);
512         return LOG.traceExit(result);
513     }
514 
515     /**
516      * addParamsToServerContext.
517      */
518     public void addParamsToServerContext() {
519         LOG.traceEntry();
520         LOG.info("---- Jetty parameters ----");
521         addParam("threadPool.minThreads", getThreadPoolMinThreads());
522         addParam("threadPool.maxThreads", getThreadPoolMaxThreads());
523         addParam("threadPool.threadsPriority", getThreadPoolThreadsPriority());
524         addParam("threadPool.idleTimeout", getThreadPoolIdleTimeout());
525         addParam("threadPool.stopTimeout", getThreadPoolStopTimeout());
526         addParam("connector.acceptors", getConnectorAcceptors());
527         addParam("connector.selectors", getConnectorSelectors());
528         addParam("connector.acceptQueueSize", getConnectorAcceptQueueSize());
529         addParam("connector.idleTimeout", getConnectorIdleTimeout());
530         addParam("connector.soLingerTime", getConnectorSoLingerTime());
531         addParam("connector.stopTimeout", getConnectorStopTimeout());
532         addParam("http.headerCacheSize", getHttpHeaderCacheSize());
533         addParam("http.requestHeaderSize", getHttpRequestHeaderSize());
534         addParam("http.responseHeaderSize", getHttpResponseHeaderSize());
535         addParam("http.outputBufferSize", getHttpOutputBufferSize());
536         addParam("lowResource.period", getLowResourceMonitorPeriod());
537         addParam("lowResource.threads", getLowResourceMonitorThreads());
538         addParam("lowResource.maxMemory", getLowResourceMonitorMaxMemory());
539         addParam("lowResource.maxConnections", getLowResourceMonitorMaxConnections());
540         addParam("lowResource.idleTimeout", getLowResourceMonitorIdleTimeout());
541         addParam("lowResource.stopTimeout", getLowResourceMonitorStopTimeout());
542         LOG.info("Jetty settings have been loaded");
543         LOG.info("---------------------------");
544         LOG.traceExit();
545     }
546 
547     /**
548      * Add a parameter to a Jetty server.
549      *
550      * @param propName the name of the property to add
551      * @param propValue the value to set
552      * @throws IllegalArgumentException - if propValue is null
553      */
554     private void addParam(final String propName,
555             final Object propValue) {
556         LOG.traceEntry("Parameters : {} and {}", propName, propValue);
557         if (propValue == null) {
558             throw new IllegalArgumentException("propValue for " + propName + " is not defined");
559         }
560         final Parameter param = this.server.getContext().getParameters().getFirst(propName);
561         if (param == null) {
562             this.server.getContext().getParameters().add(propName, String.valueOf(propValue));
563             LOG.info("add to a new param {} : {}", propName, propValue);
564         } else {
565             param.setValue(String.valueOf(propValue));
566             LOG.info("add to an existant param {} : {}", propName, propValue);
567         }
568         LOG.traceExit();
569     }
570 }