Merge "Fixed Sonar issue"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / BaseServlet.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 static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
28
29 import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
30 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
31
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.net.InetAddress;
35 import java.net.UnknownHostException;
36 import java.security.cert.X509Certificate;
37 import java.sql.Connection;
38 import java.sql.SQLException;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.List;
44 import java.util.ArrayList;
45
46 import javax.servlet.ServletConfig;
47 import javax.servlet.ServletException;
48 import javax.servlet.http.HttpServlet;
49 import javax.servlet.http.HttpServletRequest;
50
51 import org.apache.log4j.Logger;
52 import org.json.JSONObject;
53 import org.json.JSONTokener;
54 import org.onap.dmaap.datarouter.authz.Authorizer;
55 import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
56 import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
57 import org.onap.dmaap.datarouter.provisioning.beans.Deleteable;
58 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
59 import org.onap.dmaap.datarouter.provisioning.beans.Group;
60 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
61 import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;
62 import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
63 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
64 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
65 import org.onap.dmaap.datarouter.provisioning.utils.DB;
66 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
67 import org.json.JSONException;
68 import org.slf4j.MDC;
69
70 import java.util.Properties;
71 import java.util.regex.Pattern;
72 import javax.mail.Message;
73 import javax.mail.MessagingException;
74 import javax.mail.Multipart;
75 import javax.mail.Session;
76 import javax.mail.Transport;
77 import javax.mail.internet.AddressException;
78 import javax.mail.internet.InternetAddress;
79 import javax.mail.internet.MimeBodyPart;
80 import javax.mail.internet.MimeMessage;
81 import javax.mail.internet.MimeMultipart;
82
83 /**
84  * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
85  * methods.
86  *
87  * @author Robert Eby
88  * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $
89  */
90 @SuppressWarnings("serial")
91 public class BaseServlet extends HttpServlet implements ProvDataProvider {
92
93     public static final String BEHALF_HEADER = "X-ATT-DR-ON-BEHALF-OF";
94     static final String FEED_BASECONTENT_TYPE = "application/vnd.att-dr.feed";
95     public static final String FEED_CONTENT_TYPE = "application/vnd.att-dr.feed; version=2.0";
96     public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.att-dr.feed-full; version=2.0";
97     public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.att-dr.feed-list; version=1.0";
98     static final String SUB_BASECONTENT_TYPE = "application/vnd.att-dr.subscription";
99     public static final String SUB_CONTENT_TYPE = "application/vnd.att-dr.subscription; version=2.0";
100     public static final String SUBFULL_CONTENT_TYPE = "application/vnd.att-dr.subscription-full; version=2.0";
101     static final String SUBLIST_CONTENT_TYPE = "application/vnd.att-dr.subscription-list; version=1.0";
102
103
104     //Adding groups functionality, ...1610
105     static final String GROUP_BASECONTENT_TYPE = "application/vnd.att-dr.group";
106     public static final String GROUP_CONTENT_TYPE = "application/vnd.att-dr.group; version=2.0";
107     static final String GROUPFULL_CONTENT_TYPE = "application/vnd.att-dr.group-full; version=2.0";
108     public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.att-dr.fegrouped-list; version=1.0";
109
110
111     public static final String LOGLIST_CONTENT_TYPE = "application/vnd.att-dr.log-list; version=1.0";
112     public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.att-dr.provfeed-full; version=1.0";
113     public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.att-dr.provfeed-full; version=2.0";
114     public static final String CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";
115
116     static final String DB_PROBLEM_MSG = "There has been a problem with the DB.  It is suggested you try the operation again.";
117
118     private static final int DEFAULT_MAX_FEEDS = 10000;
119     private static final int DEFAULT_MAX_SUBS = 100000;
120     private static final int DEFAULT_POKETIMER1 = 5;
121     private static final int DEFAULT_POKETIMER2 = 30;
122     private static final String DEFAULT_DOMAIN = "onap";
123     private static final String DEFAULT_PROVSRVR_NAME = "dmaap-dr-prov";
124     private static final String RESEARCH_SUBNET = "10.42.0.0/16";
125     private static final String STATIC_ROUTING_NODES = ""; //Adding new param for static Routing - Rally:US664862-1610
126
127     /**
128      * A boolean to trigger one time "provisioning changed" event on startup
129      */
130     private static boolean startmsgFlag = true;
131     /**
132      * This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE)
133      */
134     private static boolean requireSecure = true;
135     /**
136      * This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT)
137      */
138     private static boolean requireCert = true;
139     /**
140      * The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES)
141      */
142     private static Set<String> authorizedAddressesAndNetworks = new HashSet<String>();
143     /**
144      * The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS)
145      */
146     private static Set<String> authorizedNames = new HashSet<String>();
147     /**
148      * The FQDN of the initially "active" provisioning server in this Data Router ecosystem
149      */
150     private static String initialActivePod;
151     /**
152      * The FQDN of the initially "standby" provisioning server in this Data Router ecosystem
153      */
154     private static String initialStandbyPod;
155     /**
156      * The FQDN of this provisioning server in this Data Router ecosystem
157      */
158     private static String thisPod;
159     /**
160      * "Timer 1" - used to determine when to notify nodes of provisioning changes
161      */
162     private static long pokeTimer1;
163     /**
164      * "Timer 2" - used to determine when to notify nodes of provisioning changes
165      */
166     private static long pokeTimer2;
167     /**
168      * Array of nodes names and/or FQDNs
169      */
170     private static String[] nodes = new String[0];
171     /**
172      * Array of node IP addresses
173      */
174     private static InetAddress[] nodeAddresses = new InetAddress[0];
175     /**
176      * Array of POD IP addresses
177      */
178     private static InetAddress[] podAddresses = new InetAddress[0];
179     /**
180      * The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT)
181      */
182     static int maxFeeds = 0;
183     /**
184      * The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT)
185      */
186     static int maxSubs = 0;
187     /**
188      * The current number of feeds in the system
189      */
190     static int activeFeeds = 0;
191     /**
192      * The current number of subscriptions in the system
193      */
194     static int activeSubs = 0;
195     /**
196      * The domain used to generate a FQDN from the "bare" node names
197      */
198     private static String provDomain = "web.att.com";
199     /**
200      * The standard FQDN of the provisioning server in this Data Router ecosystem
201      */
202     public static String provName = "feeds-drtr.web.att.com";
203     /**
204      * The standard FQDN of the ACTIVE provisioning server in this Data Router ecosystem
205      */
206     public static String activeProvName = "feeds-drtr.web.att.com";
207     /**
208      * Special subnet that is allowed access to /internal
209      */
210     private static String researchSubnet = RESEARCH_SUBNET;
211     /**
212      * Special subnet that is allowed access to /internal to Lab Machine
213      */
214     private static String researchSubnet1 = RESEARCH_SUBNET;
215     private static String staticRoutingNodes = STATIC_ROUTING_NODES; //Adding new param for static Routing - Rally:US664862-1610
216
217     /**
218      * This logger is used to log provisioning events
219      */
220     protected static Logger eventlogger;
221     /**
222      * This logger is used to log internal events (errors, etc.)
223      */
224     protected static Logger intlogger;
225     /**
226      * Authorizer - interface to the Policy Engine
227      */
228     protected static Authorizer authz;
229     /**
230      * The Synchronizer used to sync active DB to standby one
231      */
232     private static SynchronizerTask synctask = null;
233
234     //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
235     private InetAddress thishost;
236     private InetAddress loopback;
237     private static Boolean mailSendFlag = false;
238
239     private static final String MAILCONFIG_FILE = "mail.properties";
240     private static Properties mailprops;
241
242     //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
243     private static String isAddressAuthEnabled = (new DB()).getProperties()
244         .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
245
246     /**
247      * Initialize data common to all the provisioning server servlets.
248      */
249     protected BaseServlet() {
250         if (eventlogger == null) {
251             eventlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.events");
252         }
253         if (intlogger == null) {
254             intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
255         }
256         if (authz == null) {
257             authz = new ProvAuthorizer(this);
258         }
259         if (startmsgFlag) {
260             startmsgFlag = false;
261             provisioningParametersChanged();
262         }
263         if (synctask == null) {
264             synctask = SynchronizerTask.getSynchronizer();
265         }
266         String name = this.getClass().getName();
267         intlogger.info("PROV0002 Servlet " + name + " started.");
268     }
269
270     @Override
271     public void init(ServletConfig config) throws ServletException {
272         super.init(config);
273         try {
274             thishost = InetAddress.getLocalHost();
275             loopback = InetAddress.getLoopbackAddress();
276             //checkHttpsRelaxation(); //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
277         } catch (UnknownHostException e) {
278             // ignore
279         }
280     }
281
282     int getIdFromPath(HttpServletRequest req) {
283         String path = req.getPathInfo();
284         if (path == null || path.length() < 2) {
285             return -1;
286         }
287         try {
288             return Integer.parseInt(path.substring(1));
289         } catch (NumberFormatException e) {
290             return -1;
291         }
292     }
293
294     /**
295      * Read the request's input stream and return a JSONObject from it
296      *
297      * @param req the HTTP request
298      * @return the JSONObject, or null if the stream cannot be parsed
299      */
300     JSONObject getJSONfromInput(HttpServletRequest req) {
301         JSONObject jo = null;
302         try {
303             jo = new JSONObject(new JSONTokener(req.getInputStream()));
304             if (intlogger.isDebugEnabled()) {
305                 intlogger.debug("JSON: " + jo.toString());
306             }
307         } catch (Exception e) {
308             intlogger.info("Error reading JSON: " + e);
309         }
310         return jo;
311     }
312
313     /**
314      * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
315      * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
316      * (configured via PROV_AUTH_SUBJECTS)?
317      *
318      * @param request the request
319      * @return an error string, or null if all is OK
320      */
321     String isAuthorizedForProvisioning(HttpServletRequest request) {
322         if (Boolean.parseBoolean(isAddressAuthEnabled)) {
323             return null;
324         }
325         // Is the request https?
326         if (requireSecure && !request.isSecure()) {
327             return "Request must be made over an HTTPS connection.";
328         }
329
330         // Is remote IP authorized?
331         String remote = request.getRemoteAddr();
332         try {
333             boolean found = false;
334             InetAddress ip = InetAddress.getByName(remote);
335             for (String addrnet : authorizedAddressesAndNetworks) {
336                 found |= addressMatchesNetwork(ip, addrnet);
337             }
338             if (!found) {
339                 return "Unauthorized address: " + remote;
340             }
341         } catch (UnknownHostException e) {
342             return "Unauthorized address: " + remote;
343         }
344
345         // Does remote have a valid certificate?
346         if (requireCert) {
347             X509Certificate certs[] = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
348             if (certs == null || certs.length == 0) {
349                 return "Client certificate is missing.";
350             }
351             // cert[0] is the client cert
352             // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
353             String name = certs[0].getSubjectX500Principal().getName();
354             if (!authorizedNames.contains(name)) {
355                 return "No authorized certificate found.";
356             }
357         }
358
359         // No problems!
360         return null;
361     }
362
363     /**
364      * Check if the remote IP address is authorized to see the /internal URL tree.
365      *
366      * @param request the HTTP request
367      * @return true iff authorized
368      */
369     boolean isAuthorizedForInternal(HttpServletRequest request) {
370
371         try {
372             if (Boolean.parseBoolean(isAddressAuthEnabled)) {
373                 return true;
374             }
375             InetAddress ip = InetAddress.getByName(request.getRemoteAddr());
376             for (InetAddress node : getNodeAddresses()) {
377                 if (node != null && ip.equals(node)) {
378                     return true;
379                 }
380             }
381             for (InetAddress pod : getPodAddresses()) {
382                 if (pod != null && ip.equals(pod)) {
383                     return true;
384                 }
385             }
386             if (thishost != null && ip.equals(thishost)) {
387                 return true;
388             }
389             if (loopback != null && ip.equals(loopback)) {
390                 return true;
391             }
392             // Also allow the "special subnet" access
393             if (addressMatchesNetwork(ip, researchSubnet1)) {
394                 return true;
395             }
396             if (addressMatchesNetwork(ip, researchSubnet)) {
397                 return true;
398             }
399         } catch (UnknownHostException e) {
400             // ignore
401         }
402         return false;
403     }
404
405     /**
406      * Check if an IP address matches a network address.
407      *
408      * @param ip the IP address
409      * @param s the network address; a bare IP address may be matched also
410      * @return true if they intersect
411      */
412     private static boolean addressMatchesNetwork(InetAddress ip, String s) {
413         int mlen = -1;
414         int n = s.indexOf("/");
415         if (n >= 0) {
416             mlen = Integer.parseInt(s.substring(n + 1));
417             s = s.substring(0, n);
418         }
419         try {
420             InetAddress i2 = InetAddress.getByName(s);
421             byte[] b1 = ip.getAddress();
422             byte[] b2 = i2.getAddress();
423             if (b1.length != b2.length) {
424                 return false;
425             }
426             if (mlen > 0) {
427                 byte[] masks = {
428                     (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
429                     (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
430                 };
431                 byte mask = masks[mlen % 8];
432                 for (n = mlen / 8; n < b1.length; n++) {
433                     b1[n] &= mask;
434                     b2[n] &= mask;
435                     mask = 0;
436                 }
437             }
438             for (n = 0; n < b1.length; n++) {
439                 if (b1[n] != b2[n]) {
440                     return false;
441                 }
442             }
443         } catch (UnknownHostException e) {
444             return false;
445         }
446         return true;
447     }
448
449     /**
450      * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
451      * be regenerated, and cause nodes and the other provisioning server to be notified.
452      */
453     public static void provisioningDataChanged() {
454         long now = System.currentTimeMillis();
455         Poker p = Poker.getPoker();
456         p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
457     }
458
459     /**
460      * Something in the parameters has changed, reload all parameters from the DB.
461      */
462     public static void provisioningParametersChanged() {
463         Map<String, String> map = Parameters.getParameters();
464         requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
465         requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
466         authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);
467         authorizedNames = getSet(map, Parameters.PROV_AUTH_SUBJECTS);
468         nodes = getSet(map, Parameters.NODES).toArray(new String[0]);
469         maxFeeds = getInt(map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);
470         maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
471         pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
472         pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
473         provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
474         provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
475         activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
476         researchSubnet = getString(map, Parameters.PROV_SPECIAL_SUBNET, RESEARCH_SUBNET);
477         staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
478             ""); //Adding new param for static Routing - Rally:US664862-1610
479         initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
480         initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
481         staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
482             ""); //Adding new param for static Routing - Rally:US664862-1610
483         activeFeeds = Feed.countActiveFeeds();
484         activeSubs = Subscription.countActiveSubscriptions();
485         try {
486             thisPod = InetAddress.getLocalHost().getHostName();
487         } catch (UnknownHostException e) {
488             thisPod = "";
489             intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.");
490         }
491
492         // Normalize the nodes, and fill in nodeAddresses
493         InetAddress[] na = new InetAddress[nodes.length];
494         for (int i = 0; i < nodes.length; i++) {
495             if (nodes[i].indexOf('.') < 0) {
496                 nodes[i] += "." + provDomain;
497             }
498             try {
499                 na[i] = InetAddress.getByName(nodes[i]);
500                 intlogger.debug("PROV0003 DNS lookup: " + nodes[i] + " => " + na[i].toString());
501             } catch (UnknownHostException e) {
502                 na[i] = null;
503                 intlogger.warn("PROV0004 Cannot lookup " + nodes[i] + ": " + e);
504             }
505         }
506
507         //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
508         List<String> filterNodes = new ArrayList<>();
509         for (String node : nodes) {
510             if (!staticRoutingNodes.contains(node)) {
511                 filterNodes.add(node);
512             }
513         }
514         nodes = filterNodes.toArray(new String[filterNodes.size()]);
515
516         nodeAddresses = na;
517         NodeClass.setNodes(nodes);        // update NODES table
518
519         // Normalize the PODs, and fill in podAddresses
520         String[] pods = getPods();
521         na = new InetAddress[pods.length];
522         for (int i = 0; i < pods.length; i++) {
523             if (pods[i].indexOf('.') < 0) {
524                 pods[i] += "." + provDomain;
525             }
526             try {
527                 na[i] = InetAddress.getByName(pods[i]);
528                 intlogger.debug("PROV0003 DNS lookup: " + pods[i] + " => " + na[i].toString());
529             } catch (UnknownHostException e) {
530                 na[i] = null;
531                 intlogger.warn("PROV0004 Cannot lookup " + pods[i] + ": " + e);
532             }
533         }
534         podAddresses = na;
535
536         // Update ThrottleFilter
537         ThrottleFilter.configure();
538
539         // Check if we are active or standby POD
540         if (!isInitialActivePOD() && !isInitialStandbyPOD()) {
541             intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");
542         }
543     }
544
545
546     /**
547      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Load mail properties.
548      *
549      * @author vs215k
550      **/
551     private void loadMailProperties() {
552         if (mailprops == null) {
553             mailprops = new Properties();
554             InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE);
555             try {
556                 mailprops.load(inStream);
557             } catch (IOException e) {
558                 intlogger.fatal("PROV9003 Opening properties: " + e.getMessage());
559                 e.printStackTrace();
560                 System.exit(1);
561             } finally {
562                 try {
563                     inStream.close();
564                 } catch (IOException e) {
565                 }
566             }
567         }
568     }
569
570     /**
571      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Check if HTTPS Relexaction is enabled
572      *
573      * @author vs215k
574      **/
575     private void checkHttpsRelaxation() {
576         if (!mailSendFlag) {
577             Properties p = (new DB()).getProperties();
578             intlogger.info("HTTPS relaxation: " + p.get("org.onap.dmaap.datarouter.provserver.https.relaxation"));
579
580             if (p.get("org.onap.dmaap.datarouter.provserver.https.relaxation").equals("true")) {
581                 try {
582                     notifyPSTeam(p.get("org.onap.dmaap.datarouter.provserver.https.relax.notify").toString());
583                 } catch (Exception e) {
584                     e.printStackTrace();
585                 }
586             }
587             mailSendFlag = true;
588         }
589     }
590
591     /**
592      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
593      *
594      * @param email - list of email ids to notify if HTTP relexcation is enabled.
595      * @author vs215k
596      **/
597     private void notifyPSTeam(String email) throws Exception {
598         loadMailProperties(); //Load HTTPS Relex mail properties.
599         String[] emails = email.split(Pattern.quote("|"));
600
601         Properties mailproperties = new Properties();
602         mailproperties.put("mail.smtp.host", mailprops.get("com.att.dmaap.datarouter.mail.server"));
603         mailproperties.put("mail.transport.protocol", mailprops.get("com.att.dmaap.datarouter.mail.protocol"));
604
605         Session session = Session.getDefaultInstance(mailproperties, null);
606         Multipart mp = new MimeMultipart();
607         MimeBodyPart htmlPart = new MimeBodyPart();
608
609         try {
610
611             Message msg = new MimeMessage(session);
612             msg.setFrom(new InternetAddress(mailprops.get("com.att.dmaap.datarouter.mail.from").toString()));
613
614             InternetAddress[] addressTo = new InternetAddress[emails.length];
615             for (int x = 0; x < emails.length; x++) {
616                 addressTo[x] = new InternetAddress(emails[x]);
617             }
618
619             msg.addRecipients(Message.RecipientType.TO, addressTo);
620             msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());
621             htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
622                 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
623             mp.addBodyPart(htmlPart);
624             msg.setContent(mp);
625
626             System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
627                 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
628
629             Transport.send(msg);
630             intlogger.info("HTTPS relaxation mail is sent to - : " + email);
631
632         } catch (AddressException e) {
633             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
634         } catch (MessagingException e) {
635             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
636         }
637     }
638
639
640     /**
641      * Get an array of all node names in the DR network.
642      *
643      * @return an array of Strings
644      */
645     public static String[] getNodes() {
646         return nodes;
647     }
648
649     /**
650      * Get an array of all node InetAddresses in the DR network.
651      *
652      * @return an array of InetAddresses
653      */
654     public static InetAddress[] getNodeAddresses() {
655         return nodeAddresses;
656     }
657
658     /**
659      * Get an array of all POD names in the DR network.
660      *
661      * @return an array of Strings
662      */
663     public static String[] getPods() {
664         return new String[]{initialActivePod, initialStandbyPod};
665     }
666
667     /**
668      * Get an array of all POD InetAddresses in the DR network.
669      *
670      * @return an array of InetAddresses
671      */
672     private static InetAddress[] getPodAddresses() {
673         return podAddresses;
674     }
675
676     /**
677      * Gets the FQDN of the initially ACTIVE provisioning server (POD). Note: this used to be called isActivePOD(),
678      * however, that is a misnomer, as the active status could shift to the standby POD without these parameters
679      * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
680      *
681      * @return the FQDN
682      */
683     public static boolean isInitialActivePOD() {
684         return thisPod.equals(initialActivePod);
685     }
686
687     /**
688      * Gets the FQDN of the initially STANDBY provisioning server (POD). Note: this used to be called isStandbyPOD(),
689      * however, that is a misnomer, as the standby status could shift to the active POD without these parameters
690      * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
691      *
692      * @return the FQDN
693      */
694     public static boolean isInitialStandbyPOD() {
695         return thisPod.equals(initialStandbyPod);
696     }
697
698     /**
699      * INSERT an {@link Insertable} bean into the database.
700      *
701      * @param bean the bean representing a row to insert
702      * @return true if the INSERT was successful
703      */
704     protected boolean doInsert(Insertable bean) {
705         boolean rv;
706         DB db = new DB();
707         Connection conn = null;
708         try {
709             conn = db.getConnection();
710             rv = bean.doInsert(conn);
711         } catch (SQLException e) {
712             rv = false;
713             intlogger.warn("PROV0005 doInsert: " + e.getMessage());
714             e.printStackTrace();
715         } finally {
716             if (conn != null) {
717                 db.release(conn);
718             }
719         }
720         return rv;
721     }
722
723     /**
724      * UPDATE an {@link Updateable} bean in the database.
725      *
726      * @param bean the bean representing a row to update
727      * @return true if the UPDATE was successful
728      */
729     protected boolean doUpdate(Updateable bean) {
730         boolean rv;
731         DB db = new DB();
732         Connection conn = null;
733         try {
734             conn = db.getConnection();
735             rv = bean.doUpdate(conn);
736         } catch (SQLException e) {
737             rv = false;
738             intlogger.warn("PROV0006 doUpdate: " + e.getMessage());
739             e.printStackTrace();
740         } finally {
741             if (conn != null) {
742                 db.release(conn);
743             }
744         }
745         return rv;
746     }
747
748     /**
749      * DELETE an {@link Deleteable} bean from the database.
750      *
751      * @param bean the bean representing a row to delete
752      * @return true if the DELETE was successful
753      */
754     protected boolean doDelete(Deleteable bean) {
755         boolean rv;
756         DB db = new DB();
757         Connection conn = null;
758         try {
759             conn = db.getConnection();
760             rv = bean.doDelete(conn);
761         } catch (SQLException e) {
762             rv = false;
763             intlogger.warn("PROV0007 doDelete: " + e.getMessage());
764             e.printStackTrace();
765         } finally {
766             if (conn != null) {
767                 db.release(conn);
768             }
769         }
770         return rv;
771     }
772
773     private static boolean getBoolean(Map<String, String> map, String name) {
774         String s = map.get(name);
775         return (s != null) && s.equalsIgnoreCase("true");
776     }
777
778     private static String getString(Map<String, String> map, String name, String dflt) {
779         String s = map.get(name);
780         return (s != null) ? s : dflt;
781     }
782
783     private static int getInt(Map<String, String> map, String name, int dflt) {
784         try {
785             String s = map.get(name);
786             return Integer.parseInt(s);
787         } catch (NumberFormatException e) {
788             return dflt;
789         }
790     }
791
792     private static Set<String> getSet(Map<String, String> map, String name) {
793         Set<String> set = new HashSet<String>();
794         String s = map.get(name);
795         if (s != null) {
796             String[] pp = s.split("\\|");
797             if (pp != null) {
798                 for (String t : pp) {
799                     String t2 = t.trim();
800                     if (t2.length() > 0) {
801                         set.add(t2);
802                     }
803                 }
804             }
805         }
806         return set;
807     }
808
809     /**
810      * A class used to encapsulate a Content-type header, separating out the "version" attribute (which defaults to
811      * "1.0" if missing).
812      */
813     public class ContentHeader {
814
815         private String type = "";
816         private Map<String, String> map = new HashMap<String, String>();
817
818         ContentHeader() {
819             this("", "1.0");
820         }
821
822         ContentHeader(String t, String v) {
823             type = t.trim();
824             map.put("version", v);
825         }
826
827         public String getType() {
828             return type;
829         }
830
831         public String getAttribute(String key) {
832             String s = map.get(key);
833             if (s == null) {
834                 s = "";
835             }
836             return s;
837         }
838     }
839
840     /**
841      * Get the ContentHeader from an HTTP request.
842      *
843      * @param req the request
844      * @return the header, encapsulated in a ContentHeader object
845      */
846     ContentHeader getContentHeader(HttpServletRequest req) {
847         ContentHeader ch = new ContentHeader();
848         String s = req.getHeader("Content-Type");
849         if (s != null) {
850             String[] pp = s.split(";");
851             ch.type = pp[0].trim();
852             for (int i = 1; i < pp.length; i++) {
853                 int ix = pp[i].indexOf('=');
854                 if (ix > 0) {
855                     String k = pp[i].substring(0, ix).trim();
856                     String v = pp[i].substring(ix + 1).trim();
857                     ch.map.put(k, v);
858                 } else {
859                     ch.map.put(pp[i].trim(), "");
860                 }
861             }
862         }
863         return ch;
864     }
865
866     // Methods for the Policy Engine classes - ProvDataProvider interface
867     @Override
868     public String getFeedOwner(String feedId) {
869         try {
870             int n = Integer.parseInt(feedId);
871             Feed f = Feed.getFeedById(n);
872             if (f != null) {
873                 return f.getPublisher();
874             }
875         } catch (NumberFormatException e) {
876             // ignore
877         }
878         return null;
879     }
880
881     @Override
882     public String getFeedClassification(String feedId) {
883         try {
884             int n = Integer.parseInt(feedId);
885             Feed f = Feed.getFeedById(n);
886             if (f != null) {
887                 return f.getAuthorization().getClassification();
888             }
889         } catch (NumberFormatException e) {
890             // ignore
891         }
892         return null;
893     }
894
895     @Override
896     public String getSubscriptionOwner(String subId) {
897         try {
898             int n = Integer.parseInt(subId);
899             Subscription s = Subscription.getSubscriptionById(n);
900             if (s != null) {
901                 return s.getSubscriber();
902             }
903         } catch (NumberFormatException e) {
904             // ignore
905         }
906         return null;
907     }
908
909     /*
910      * @Method - isUserMemberOfGroup - Rally:US708115
911      * @Params - group object and user to check if exists in given group
912      * @return - boolean value /true/false
913      */
914     private boolean isUserMemberOfGroup(Group group, String user) {
915
916         String groupDetails = group.getMembers().replace("]", "").replace("[", "");
917         String[] s = groupDetails.split("},");
918
919         for (String value : s) {
920             JSONObject jsonObj;
921             try {
922                 jsonObj = new JSONObject(value + "}");
923                 if (jsonObj.get("id").equals(user)) {
924                     return true;
925                 }
926             } catch (JSONException e) {
927                 e.printStackTrace();
928             }
929         }
930         return false;
931
932     }
933
934     /*
935      * @Method - getGroupByFeedGroupId- Rally:US708115
936      * @Params - User to check in group and feedid which is assigned the group.
937      * @return - string value grupid/null
938      */
939     @Override
940     public String getGroupByFeedGroupId(String owner, String feedId) {
941         try {
942             int n = Integer.parseInt(feedId);
943             Feed f = Feed.getFeedById(n);
944             if (f != null) {
945                 int groupid = f.getGroupid();
946                 if (groupid > 0) {
947                     Group group = Group.getGroupById(groupid);
948                     assert group != null;
949                     if (isUserMemberOfGroup(group, owner)) {
950                         return group.getAuthid();
951                     }
952                 }
953             }
954         } catch (NumberFormatException e) {
955             // ignore
956         }
957         return null;
958     }
959
960     /*
961      * @Method - getGroupBySubGroupId - Rally:US708115
962      * @Params - User to check in group and subid which is assigned the group.
963      * @return - string value grupid/null
964      */
965     @Override
966     public String getGroupBySubGroupId(String owner, String subId) {
967         try {
968             int n = Integer.parseInt(subId);
969             Subscription s = Subscription.getSubscriptionById(n);
970             if (s != null) {
971                 int groupid = s.getGroupid();
972                 if (groupid > 0) {
973                     Group group = Group.getGroupById(groupid);
974                     assert group != null;
975                     if (isUserMemberOfGroup(group, owner)) {
976                         return group.getAuthid();
977                     }
978                 }
979             }
980         } catch (NumberFormatException e) {
981             // ignore
982         }
983         return null;
984     }
985
986     /*
987      * @Method - setIpAndFqdnForEelf - Rally:US664892
988      * @Params - method, prints method name in EELF log.
989      */
990     void setIpAndFqdnForEelf(String method) {
991         MDC.clear();
992         MDC.put(MDC_SERVICE_NAME, method);
993         try {
994             MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
995             MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
996         } catch (Exception e) {
997             e.printStackTrace();
998         }
999
1000     }
1001 }