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