Merge "Add Unit Tests for GroupServlet"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / Main.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * * ===========================================================================
7  * * Licensed under the Apache License, Version 2.0 (the "License");
8  * * you may not use this file except in compliance with the License.
9  * * You may obtain a copy of the License at
10  * *
11  *  *      http://www.apache.org/licenses/LICENSE-2.0
12  * *
13  *  * Unless required by applicable law or agreed to in writing, software
14  * * distributed under the License is distributed on an "AS IS" BASIS,
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * * See the License for the specific language governing permissions and
17  * * limitations under the License.
18  * * ============LICENSE_END====================================================
19  * *
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.provisioning;
26
27 import java.security.*;
28 import java.util.*;
29
30 import org.apache.log4j.Logger;
31 import org.eclipse.jetty.http.HttpVersion;
32 import org.eclipse.jetty.server.Connector;
33 import org.eclipse.jetty.server.Handler;
34 import org.eclipse.jetty.server.HttpConfiguration;
35 import org.eclipse.jetty.server.HttpConnectionFactory;
36 import org.eclipse.jetty.server.NCSARequestLog;
37 import org.eclipse.jetty.server.Server;
38 import org.eclipse.jetty.server.ServerConnector;
39 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
40 import org.eclipse.jetty.server.handler.DefaultHandler;
41 import org.eclipse.jetty.server.handler.HandlerCollection;
42 import org.eclipse.jetty.server.handler.RequestLogHandler;
43 import org.eclipse.jetty.server.SslConnectionFactory;
44 import org.eclipse.jetty.util.ssl.SslContextFactory;
45 import org.eclipse.jetty.servlet.FilterHolder;
46 import org.eclipse.jetty.servlet.ServletContextHandler;
47 import org.eclipse.jetty.servlet.ServletHolder;
48 import org.eclipse.jetty.util.thread.QueuedThreadPool;
49 import org.onap.dmaap.datarouter.provisioning.utils.DB;
50 import org.onap.dmaap.datarouter.provisioning.utils.LogfileLoader;
51 import org.onap.dmaap.datarouter.provisioning.utils.PurgeLogDirTask;
52 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
53
54 import javax.servlet.DispatcherType;
55
56 /**
57  * <p>
58  * A main class which may be used to start the provisioning server with an "embedded" Jetty server. Configuration is
59  * done via the properties file <i>provserver.properties</i>, which should be in the CLASSPATH. The provisioning server
60  * may also be packaged with a web.xml and started as a traditional webapp.
61  * </p>
62  * <p>
63  * Most of the work of the provisioning server is carried out within the eight servlets (configured below) that are used
64  * to handle each of the eight types of requests the server may receive. In addition, there are background threads
65  * started to perform other tasks:
66  * </p>
67  * <ul>
68  * <li>One background Thread runs the {@link LogfileLoader} in order to process incoming logfiles.
69  * This Thread is created as a side effect of the first successful POST to the /internal/logs/ servlet.</li>
70  * <li>One background Thread runs the {@link SynchronizerTask} which is used to periodically
71  * synchronize the database between active and standby servers.</li>
72  * <li>One background Thread runs the {@link Poker} which is used to notify the nodes whenever
73  * provisioning data changes.</li>
74  * <li>One task is run once a day to run {@link PurgeLogDirTask} which purges older logs from the
75  * /opt/app/datartr/logs directory.</li>
76  * </ul>
77  * <p>
78  * The provisioning server is stopped by issuing a GET to the URL http://127.0.0.1/internal/halt using <i>curl</i> or
79  * some other such tool.
80  * </p>
81  *
82  * @author Robert Eby
83  * @version $Id: Main.java,v 1.12 2014/03/12 19:45:41 eby Exp $
84  */
85 public class Main {
86
87     /**
88      * The truststore to use if none is specified
89      */
90     public static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
91     public static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
92     public static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
93     public static final String KEYSTORE_PASSWORD_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
94     public static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
95     public static final String TRUSTSTORE_PASSWORD_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
96
97     /**
98      * The one and only {@link Server} instance in this JVM
99      */
100     private static Server server;
101
102     /**
103      * Starts the Data Router Provisioning server.
104      *
105      * @param args not used
106      * @throws Exception if Jetty has a problem starting
107      */
108     public static void main(String[] args) throws Exception {
109         Security.setProperty("networkaddress.cache.ttl", "4");
110         Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
111
112         // Check DB is accessible and contains the expected tables
113         if (!checkDatabase(logger)) {
114             System.exit(1);
115         }
116
117         logger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
118
119         // Get properties
120         Properties p = (new DB()).getProperties();
121         int httpPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
122         int httpsPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
123
124         // HTTP configuration
125         HttpConfiguration httpConfiguration = new HttpConfiguration();
126         httpConfiguration.setSecureScheme("https");
127         httpConfiguration.setSecurePort(httpsPort);
128         httpConfiguration.setOutputBufferSize(32768);
129         httpConfiguration.setRequestHeaderSize(2048);
130         httpConfiguration.setIdleTimeout(300000);
131         httpConfiguration.setSendServerVersion(true);
132         httpConfiguration.setSendDateHeader(false);
133
134         // Server's thread pool
135         QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
136         queuedThreadPool.setMinThreads(10);
137         queuedThreadPool.setMaxThreads(200);
138         queuedThreadPool.setDetailedDump(false);
139
140         // The server itself
141         server = new Server(queuedThreadPool);
142
143         // HTTP connector
144         HandlerCollection hc;
145         try (ServerConnector httpServerConnector = new ServerConnector(server,
146             new HttpConnectionFactory(httpConfiguration))) {
147             httpServerConnector.setPort(httpPort);
148             httpServerConnector.setAcceptQueueSize(2);
149
150             // HTTPS configuration
151             HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration);
152             httpsConfiguration.setRequestHeaderSize(8192);
153
154             // HTTPS connector
155             SslContextFactory sslContextFactory = new SslContextFactory();
156             sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
157             sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASSWORD_PROPERTY));
158             sslContextFactory
159                 .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
160             // SSL stuff
161             /* Skip SSLv3 Fixes */
162             sslContextFactory.addExcludeProtocols("SSLv3");
163             logger.info("Excluded protocols prov-" + Arrays.toString(sslContextFactory.getExcludeProtocols()));
164             /* End of SSLv3 Fixes */
165
166             ServerConnector httpsServerConnector = new ServerConnector(server,
167                 new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
168                 new HttpConnectionFactory(httpsConfiguration));
169             httpsServerConnector.setPort(httpsPort);
170             httpsServerConnector.setIdleTimeout(30000);
171             httpsServerConnector.setAcceptQueueSize(2);
172
173             sslContextFactory.setKeyStoreType(p.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
174             sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
175             sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASSWORD_PROPERTY));
176             sslContextFactory
177                 .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
178
179             String ts = p.getProperty(TRUSTSTORE_PATH_PROPERTY);
180             if (ts != null && ts.length() > 0) {
181                 System.out.println("@@ TS -> " + ts);
182                 sslContextFactory.setTrustStorePath(ts);
183                 sslContextFactory.setTrustStorePassword(p.getProperty(TRUSTSTORE_PASSWORD_PROPERTY));
184             } else {
185                 sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
186                 sslContextFactory.setTrustStorePassword("changeit");
187             }
188             sslContextFactory.setTrustStorePath("/opt/app/datartr/self_signed/cacerts.jks");
189             sslContextFactory.setTrustStorePassword("changeit");
190             sslContextFactory.setWantClientAuth(true);
191
192             // Servlet and Filter configuration
193             ServletContextHandler ctxt = new ServletContextHandler(0);
194             ctxt.setContextPath("/");
195             ctxt.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
196             ctxt.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
197             ctxt.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
198             ctxt.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
199             ctxt.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
200             ctxt.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
201             ctxt.addServlet(new ServletHolder(new GroupServlet()),
202                 "/group/*"); //Provision groups - Rally US708115 -1610
203             ctxt.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
204             ctxt.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
205             ctxt.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
206             ctxt.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
207             ctxt.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
208
209             ContextHandlerCollection contexts = new ContextHandlerCollection();
210             contexts.addHandler(ctxt);
211
212             // Request log configuration
213             NCSARequestLog nrl = new NCSARequestLog();
214             nrl.setFilename(
215                 p.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
216             nrl.setFilenameDateFormat("yyyyMMdd");
217             nrl.setRetainDays(90);
218             nrl.setAppend(true);
219             nrl.setExtended(false);
220             nrl.setLogCookies(false);
221             nrl.setLogTimeZone("GMT");
222
223             RequestLogHandler reqlog = new RequestLogHandler();
224             reqlog.setRequestLog(nrl);
225
226             // Server's Handler collection
227             hc = new HandlerCollection();
228             hc.setHandlers(new Handler[]{contexts, new DefaultHandler()});
229             hc.addHandler(reqlog);
230
231             // Daemon to clean up the log directory on a daily basis
232             Timer rolex = new Timer();
233             rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
234
235             // Start LogfileLoader
236             LogfileLoader.getLoader();
237
238             try (ServerConnector serverConnector = new ServerConnector(server,
239                 new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
240                 new HttpConnectionFactory(httpsConfiguration))) {
241                 serverConnector.setPort(httpsPort);
242                 serverConnector.setIdleTimeout(500000);
243             }
244
245             server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector});
246         }
247         server.setHandler(hc);
248         server.setStopAtShutdown(true);
249         server.setStopTimeout(5000);
250
251         server.setDumpAfterStart(false);
252         server.setDumpBeforeStop(false);
253
254         server.start();
255         server.join();
256         logger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
257     }
258
259     private static boolean checkDatabase(Logger logger) {
260         DB db = new DB();
261         return db.runRetroFits();
262     }
263
264     /**
265      * Stop the Jetty server.
266      */
267     static void shutdown() {
268         new Thread(() -> {
269             try {
270                 server.stop();
271                 Thread.sleep(5000L);
272                 System.exit(0);
273             } catch (Exception e) {
274                 // ignore
275             }
276         });
277     }
278 }