Remove major and minor code smells in dr-prov
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / BaseServlet.java
old mode 100644 (file)
new mode 100755 (executable)
index 45d9748..7475b6b
-/*******************************************************************************\r
- * ============LICENSE_START==================================================\r
- * * org.onap.dmaap\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * * \r
- *  *      http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
- *  * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-\r
-\r
-package org.onap.dmaap.datarouter.provisioning;\r
-\r
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;\r
-\r
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;\r
-import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.InetAddress;\r
-import java.net.UnknownHostException;\r
-import java.security.cert.X509Certificate;\r
-import java.sql.Connection;\r
-import java.sql.SQLException;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.List;\r
-import java.util.ArrayList;\r
-\r
-import javax.servlet.ServletConfig;\r
-import javax.servlet.ServletException;\r
-import javax.servlet.http.HttpServlet;\r
-import javax.servlet.http.HttpServletRequest;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.json.JSONObject;\r
-import org.json.JSONTokener;\r
-import org.onap.dmaap.datarouter.authz.Authorizer;\r
-import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;\r
-import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Deleteable;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Group;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Insertable;\r
-import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Parameters;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Subscription;\r
-import org.onap.dmaap.datarouter.provisioning.beans.Updateable;\r
-import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
-import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;\r
-import org.json.JSONException; \r
-import org.slf4j.MDC;\r
-\r
-import java.util.Properties;\r
-import java.util.regex.Pattern;\r
-import javax.mail.Message;\r
-import javax.mail.MessagingException;\r
-import javax.mail.Multipart;\r
-import javax.mail.Session;\r
-import javax.mail.Transport;\r
-import javax.mail.internet.AddressException;\r
-import javax.mail.internet.InternetAddress;\r
-import javax.mail.internet.MimeBodyPart;\r
-import javax.mail.internet.MimeMessage;\r
-import javax.mail.internet.MimeMultipart;\r
-/**\r
- * This is the base class for all Servlets in the provisioning code.\r
- * It provides standard constants and some common methods.\r
- *\r
- * @author Robert Eby\r
- * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $\r
- */\r
-@SuppressWarnings("serial")\r
-public class BaseServlet extends HttpServlet implements ProvDataProvider {\r
-       public static final String BEHALF_HEADER         = "X-ATT-DR-ON-BEHALF-OF";\r
-       public static final String FEED_BASECONTENT_TYPE = "application/vnd.att-dr.feed";\r
-       public static final String FEED_CONTENT_TYPE     = "application/vnd.att-dr.feed; version=2.0";\r
-       public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.att-dr.feed-full; version=2.0";\r
-       public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.att-dr.feed-list; version=1.0";\r
-       public static final String SUB_BASECONTENT_TYPE  = "application/vnd.att-dr.subscription";\r
-       public static final String SUB_CONTENT_TYPE      = "application/vnd.att-dr.subscription; version=2.0";\r
-       public static final String SUBFULL_CONTENT_TYPE  = "application/vnd.att-dr.subscription-full; version=2.0";\r
-       public static final String SUBLIST_CONTENT_TYPE  = "application/vnd.att-dr.subscription-list; version=1.0";\r
-\r
-       \r
-       //Adding groups functionality, ...1610\r
-       public static final String GROUP_BASECONTENT_TYPE = "application/vnd.att-dr.group";\r
-       public static final String GROUP_CONTENT_TYPE     = "application/vnd.att-dr.group; version=2.0";\r
-       public static final String GROUPFULL_CONTENT_TYPE = "application/vnd.att-dr.group-full; version=2.0";\r
-       public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.att-dr.fegrouped-list; version=1.0";\r
-\r
-\r
-       public static final String LOGLIST_CONTENT_TYPE  = "application/vnd.att-dr.log-list; version=1.0";\r
-       public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.att-dr.provfeed-full; version=1.0";\r
-       public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.att-dr.provfeed-full; version=2.0";\r
-       public static final String CERT_ATTRIBUTE        = "javax.servlet.request.X509Certificate";\r
-\r
-       public static final String DB_PROBLEM_MSG = "There has been a problem with the DB.  It is suggested you try the operation again.";\r
-\r
-       public static final int    DEFAULT_MAX_FEEDS     = 10000;\r
-       public static final int    DEFAULT_MAX_SUBS      = 100000;\r
-       public static final int    DEFAULT_POKETIMER1    = 5;\r
-       public static final int    DEFAULT_POKETIMER2    = 30;\r
-       public static final String DEFAULT_DOMAIN        = "web.att.com";\r
-       public static final String DEFAULT_PROVSRVR_NAME = "feeds-drtr.web.att.com";\r
-       public static final String RESEARCH_SUBNET       = "135.207.136.128/25";\r
-       public static final String STATIC_ROUTING_NODES       = ""; //Adding new param for static Routing - Rally:US664862-1610\r
-\r
-       /** A boolean to trigger one time "provisioning changed" event on startup */\r
-       private static boolean startmsg_flag  = true;\r
-       /** This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE) */\r
-       private static boolean require_secure = true;\r
-       /** This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT) */\r
-       private static boolean require_cert   = true;\r
-       /** The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES) */\r
-       private static Set<String> authorizedAddressesAndNetworks = new HashSet<String>();\r
-       /** The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS) */\r
-       private static Set<String> authorizedNames = new HashSet<String>();\r
-       /** The FQDN of the initially "active" provisioning server in this Data Router ecosystem */\r
-       private static String initial_active_pod;\r
-       /** The FQDN of the initially "standby" provisioning server in this Data Router ecosystem */\r
-       private static String initial_standby_pod;\r
-       /** The FQDN of this provisioning server in this Data Router ecosystem */\r
-       private static String this_pod;\r
-       /** "Timer 1" - used to determine when to notify nodes of provisioning changes */\r
-       private static long poke_timer1;\r
-       /** "Timer 2" - used to determine when to notify nodes of provisioning changes */\r
-       private static long poke_timer2;\r
-       /** Array of nodes names and/or FQDNs */\r
-       private static String[] nodes = new String[0];\r
-       /** Array of node IP addresses */\r
-       private static InetAddress[] nodeAddresses = new InetAddress[0];\r
-       /** Array of POD IP addresses */\r
-       private static InetAddress[] podAddresses = new InetAddress[0];\r
-       /** The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT) */\r
-       protected static int max_feeds    = 0;\r
-       /** The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT) */\r
-       protected static int max_subs     = 0;\r
-       /** The current number of feeds in the system */\r
-       protected static int active_feeds = 0;\r
-       /** The current number of subscriptions in the system */\r
-       protected static int active_subs  = 0;\r
-       /** The domain used to generate a FQDN from the "bare" node names */\r
-       public static String prov_domain = "web.att.com";\r
-       /** The standard FQDN of the provisioning server in this Data Router ecosystem */\r
-       public static String prov_name   = "feeds-drtr.web.att.com";\r
-       /** The standard FQDN of the ACTIVE provisioning server in this Data Router ecosystem */\r
-       public static String active_prov_name   = "feeds-drtr.web.att.com";\r
-       /** Special subnet that is allowed access to /internal */\r
-       protected static String special_subnet = RESEARCH_SUBNET;\r
-\r
-       /** Special subnet that is allowed access to /internal to Lab Machine */\r
-       protected static String special_subnet_secondary = RESEARCH_SUBNET;\r
-       protected static String static_routing_nodes = STATIC_ROUTING_NODES; //Adding new param for static Routing - Rally:US664862-1610\r
-\r
-       /** This logger is used to log provisioning events */\r
-       protected static Logger eventlogger;\r
-       /** This logger is used to log internal events (errors, etc.) */\r
-       protected static Logger intlogger;\r
-       /** Authorizer - interface to the Policy Engine */\r
-       protected static Authorizer authz;\r
-       /** The Synchronizer used to sync active DB to standby one */\r
-       protected static SynchronizerTask synctask = null;\r
-    \r
-       //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
-       private InetAddress thishost;\r
-       private InetAddress loopback;\r
-    private static Boolean mailSendFlag = false;\r
-\r
-       public static final String MAILCONFIG_FILE = "mail.properties";\r
-       private static Properties mailprops;\r
-       /**\r
-        * Initialize data common to all the provisioning server servlets.\r
-        */\r
-       protected BaseServlet() {\r
-               if (eventlogger == null)\r
-                       eventlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.events");\r
-               if (intlogger == null)\r
-                       intlogger   = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");\r
-               if (authz == null)\r
-                       authz = new ProvAuthorizer(this);\r
-               if (startmsg_flag) {\r
-                       startmsg_flag = false;\r
-                       provisioningParametersChanged();\r
-               }\r
-               if (synctask == null) {\r
-                       synctask = SynchronizerTask.getSynchronizer();\r
-               }\r
-               String name = this.getClass().getName();\r
-               intlogger.info("PROV0002 Servlet "+name+" started.");\r
-       }\r
-       @Override\r
-       public void init(ServletConfig config) throws ServletException {\r
-               super.init(config);\r
-               try {\r
-                       thishost = InetAddress.getLocalHost();\r
-                       loopback = InetAddress.getLoopbackAddress();\r
-                       checkHttpsRelaxation(); //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
-               } catch (UnknownHostException e) {\r
-                       // ignore\r
-               }\r
-       }\r
-       protected int getIdFromPath(HttpServletRequest req) {\r
-               String path = req.getPathInfo();\r
-               if (path == null || path.length() < 2)\r
-                       return -1;\r
-               try {\r
-                       return Integer.parseInt(path.substring(1));\r
-               } catch (NumberFormatException e) {\r
-                       return -1;\r
-               }\r
-       }\r
-       /**\r
-        * Read the request's input stream and return a JSONObject from it\r
-        * @param req the HTTP request\r
-        * @return the JSONObject, or null if the stream cannot be parsed\r
-        */\r
-       protected JSONObject getJSONfromInput(HttpServletRequest req) {\r
-               JSONObject jo = null;\r
-               try {\r
-                       jo = new JSONObject(new JSONTokener(req.getInputStream()));\r
-                       if (intlogger.isDebugEnabled())\r
-                               intlogger.debug("JSON: "+jo.toString());\r
-               } catch (Exception e) {\r
-                       intlogger.info("Error reading JSON: "+e);\r
-               }\r
-               return jo;\r
-       }\r
-       /**\r
-        * Check if the remote host is authorized to perform provisioning.\r
-        * Is the request secure?\r
-        * Is it coming from an authorized IP address or network (configured via PROV_AUTH_ADDRESSES)?\r
-        * Does it have a valid client certificate (configured via PROV_AUTH_SUBJECTS)?\r
-        * @param request the request\r
-        * @return an error string, or null if all is OK\r
-        */\r
-       protected String isAuthorizedForProvisioning(HttpServletRequest request) {\r
-               // Is the request https?\r
-               if (require_secure && !request.isSecure()) {\r
-                       return "Request must be made over an HTTPS connection.";\r
-               }\r
-\r
-               // Is remote IP authorized?\r
-               String remote = request.getRemoteAddr();\r
-               try {\r
-                       boolean found = false;\r
-                       InetAddress ip = InetAddress.getByName(remote);\r
-                       for (String addrnet : authorizedAddressesAndNetworks) {\r
-                               found |= addressMatchesNetwork(ip, addrnet);\r
-                       }\r
-                       if (!found) {\r
-                               return "Unauthorized address: "+remote;\r
-                       }\r
-               } catch (UnknownHostException e) {\r
-                       return "Unauthorized address: "+remote;\r
-               }\r
-\r
-               // Does remote have a valid certificate?\r
-               if (require_cert) {\r
-                       X509Certificate certs[] = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);\r
-                       if (certs == null || certs.length == 0) {\r
-                               return "Client certificate is missing.";\r
-                       }\r
-                       // cert[0] is the client cert\r
-                       // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()\r
-                       String name = certs[0].getSubjectX500Principal().getName();\r
-                       if (!authorizedNames.contains(name)) {\r
-                               return "No authorized certificate found.";\r
-                       }\r
-               }\r
-\r
-               // No problems!\r
-               return null;\r
-       }\r
-       /**\r
-        * Check if the remote IP address is authorized to see the /internal URL tree.\r
-        * @param request the HTTP request\r
-        * @return true iff authorized\r
-        */\r
-       protected boolean isAuthorizedForInternal(HttpServletRequest request) {\r
-               try {\r
-                       InetAddress ip = InetAddress.getByName(request.getRemoteAddr());\r
-                       for (InetAddress node : getNodeAddresses()) {\r
-                               if (node != null && ip.equals(node))\r
-                                       return true;\r
-                       }\r
-                       for (InetAddress pod : getPodAddresses()) {\r
-                               if (pod != null && ip.equals(pod))\r
-                                       return true;\r
-                       }\r
-                       if (thishost != null && ip.equals(thishost))\r
-                               return true;\r
-                       if (loopback != null && ip.equals(loopback))\r
-                               return true;\r
-                       // Also allow the "special subnet" access\r
-                       if (addressMatchesNetwork(ip, special_subnet_secondary))\r
-                               return true;\r
-                       if (addressMatchesNetwork(ip, special_subnet))\r
-                               return true;\r
-               } catch (UnknownHostException e) {\r
-                       // ignore\r
-               }\r
-               return false;\r
-       }\r
-       /**\r
-        * Check if an IP address matches a network address.\r
-        * @param ip the IP address\r
-        * @param s the network address; a bare IP address may be matched also\r
-        * @return true if they intersect\r
-        */\r
-       protected static boolean addressMatchesNetwork(InetAddress ip, String s) {\r
-               int mlen = -1;\r
-               int n = s.indexOf("/");\r
-               if (n >= 0) {\r
-                       mlen = Integer.parseInt(s.substring(n+1));\r
-                       s = s.substring(0, n);\r
-               }\r
-               try {\r
-                       InetAddress i2 = InetAddress.getByName(s);\r
-                       byte[] b1 = ip.getAddress();\r
-                       byte[] b2 = i2.getAddress();\r
-                       if (b1.length != b2.length)\r
-                               return false;\r
-                       if (mlen > 0) {\r
-                               byte[] masks = {\r
-                                       (byte)0x00, (byte)0x80, (byte)0xC0, (byte)0xE0,\r
-                                       (byte)0xF0, (byte)0xF8, (byte)0xFC, (byte)0xFE\r
-                               };\r
-                               byte mask = masks[mlen%8];\r
-                               for (n = mlen/8; n < b1.length; n++) {\r
-                                       b1[n] &= mask;\r
-                                       b2[n] &= mask;\r
-                                       mask = 0;\r
-                               }\r
-                       }\r
-                       for (n = 0; n < b1.length; n++)\r
-                               if (b1[n] != b2[n])\r
-                                       return false;\r
-               } catch (UnknownHostException e) {\r
-                       return false;\r
-               }\r
-               return true;\r
-       }\r
-       /**\r
-        * Something has changed in the provisioning data.\r
-        * Start the timers that will cause the pre-packaged JSON string to be regenerated,\r
-        * and cause nodes and the other provisioning server to be notified.\r
-        */\r
-       public static void provisioningDataChanged() {\r
-               long now = System.currentTimeMillis();\r
-               Poker p = Poker.getPoker();\r
-               p.setTimers(now + (poke_timer1 * 1000L), now + (poke_timer2 * 1000L));\r
-       }\r
-       /**\r
-        * Something in the parameters has changed, reload all parameters from the DB.\r
-        */\r
-       public static void provisioningParametersChanged() {\r
-               Map<String,String> map         = Parameters.getParameters();\r
-               require_secure   = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);\r
-               require_cert     = getBoolean(map, Parameters.PROV_REQUIRE_CERT);\r
-               authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);\r
-               authorizedNames  = getSet    (map, Parameters.PROV_AUTH_SUBJECTS);\r
-               nodes            = getSet    (map, Parameters.NODES).toArray(new String[0]);\r
-               max_feeds        = getInt    (map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);\r
-               max_subs         = getInt    (map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);\r
-               poke_timer1      = getInt    (map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);\r
-               poke_timer2      = getInt    (map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);\r
-               prov_domain      = getString (map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);\r
-               prov_name        = getString (map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);\r
-               active_prov_name = getString (map, Parameters.PROV_ACTIVE_NAME, prov_name);\r
-               special_subnet   = getString (map, Parameters.PROV_SPECIAL_SUBNET, RESEARCH_SUBNET);\r
-               static_routing_nodes = getString (map, Parameters.STATIC_ROUTING_NODES, ""); //Adding new param for static Routing - Rally:US664862-1610\r
-               initial_active_pod  = getString (map, Parameters.ACTIVE_POD, "");\r
-               initial_standby_pod = getString (map, Parameters.STANDBY_POD, "");\r
-               static_routing_nodes = getString (map, Parameters.STATIC_ROUTING_NODES, ""); //Adding new param for static Routing - Rally:US664862-1610\r
-               active_feeds     = Feed.countActiveFeeds();\r
-               active_subs      = Subscription.countActiveSubscriptions();\r
-               try {\r
-                       this_pod = InetAddress.getLocalHost().getHostName();\r
-               } catch (UnknownHostException e) {\r
-                       this_pod = "";\r
-                       intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.");\r
-               }\r
-\r
-               // Normalize the nodes, and fill in nodeAddresses\r
-               InetAddress[] na = new InetAddress[nodes.length];\r
-               for (int i = 0; i < nodes.length; i++) {\r
-                       if (nodes[i].indexOf('.') < 0)\r
-                               nodes[i] += "." + prov_domain;\r
-                       try {\r
-                               na[i] = InetAddress.getByName(nodes[i]);\r
-                               intlogger.debug("PROV0003 DNS lookup: "+nodes[i]+" => "+na[i].toString());\r
-                       } catch (UnknownHostException e) {\r
-                               na[i] = null;\r
-                               intlogger.warn("PROV0004 Cannot lookup "+nodes[i]+": "+e);\r
-                       }\r
-               }\r
-\r
-               //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .   \r
-               List<String> filterNodes = new ArrayList<>();           \r
-               for (int i = 0; i < nodes.length; i++) {                \r
-                       if(!static_routing_nodes.contains(nodes[i])){           \r
-                               filterNodes.add(nodes[i]);              \r
-                       }               \r
-               }               \r
-               String [] filteredNodes = filterNodes.toArray(new String[filterNodes.size()]);                          \r
-               nodes = filteredNodes;\r
-\r
-               nodeAddresses = na;\r
-               NodeClass.setNodes(nodes);              // update NODES table\r
-\r
-               // Normalize the PODs, and fill in podAddresses\r
-               String[] pods = getPods();\r
-               na = new InetAddress[pods.length];\r
-               for (int i = 0; i < pods.length; i++) {\r
-                       if (pods[i].indexOf('.') < 0)\r
-                               pods[i] += "." + prov_domain;\r
-                       try {\r
-                               na[i] = InetAddress.getByName(pods[i]);\r
-                               intlogger.debug("PROV0003 DNS lookup: "+pods[i]+" => "+na[i].toString());\r
-                       } catch (UnknownHostException e) {\r
-                               na[i] = null;\r
-                               intlogger.warn("PROV0004 Cannot lookup "+pods[i]+": "+e);\r
-                       }\r
-               }\r
-               podAddresses = na;\r
-\r
-               // Update ThrottleFilter\r
-               ThrottleFilter.configure();\r
-\r
-               // Check if we are active or standby POD\r
-               if (!isInitialActivePOD() && !isInitialStandbyPOD())\r
-                       intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");\r
-       }\r
-\r
-\r
-       /**Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
-        * Load mail properties.\r
-        * @author vs215k\r
-        *  \r
-       **/\r
-       private void loadMailProperties() {\r
-               if (mailprops == null) {\r
-                       mailprops = new Properties();\r
-                       InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE);\r
-                       try {\r
-                               mailprops.load(inStream);\r
-                       } catch (IOException e) {\r
-                               intlogger.fatal("PROV9003 Opening properties: "+e.getMessage());\r
-                               e.printStackTrace();\r
-                               System.exit(1);\r
-                       }\r
-                       finally {\r
-                               try {\r
-                                       inStream.close();\r
-                               } \r
-                               catch (IOException e) {\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       \r
-       /**Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
-        * Check if HTTPS Relexaction is enabled \r
-        * @author vs215k\r
-        *  \r
-       **/\r
-       private void checkHttpsRelaxation() {\r
-               if(mailSendFlag == false) {\r
-                       Properties p = (new DB()).getProperties();\r
-                       intlogger.info("HTTPS relaxatio: "+p.get("com.att.research.datarouter.provserver.https.relaxation"));\r
-                       \r
-                       if(p.get("com.att.research.datarouter.provserver.https.relaxation").equals("true")) {\r
-                           try {\r
-                                 notifyPSTeam(p.get("com.att.research.datarouter.provserver.https.relax.notify").toString());\r
-                           } \r
-                               catch (Exception e) {\r
-                                   e.printStackTrace();\r
-                           }\r
-                        }\r
-                       mailSendFlag = true;\r
-               }\r
-       }\r
-       \r
-       /**Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
-        * @author vs215k\r
-        * @param email - list of email ids to notify if HTTP relexcation is enabled. \r
-       **/\r
-       private void notifyPSTeam(String email) throws Exception {\r
-               loadMailProperties(); //Load HTTPS Relex mail properties.\r
-               String[] emails = email.split(Pattern.quote("|"));\r
-       \r
-       Properties mailproperties = new Properties();\r
-               mailproperties.put("mail.smtp.host", mailprops.get("com.att.dmaap.datarouter.mail.server"));\r
-               mailproperties.put("mail.transport.protocol", mailprops.get("com.att.dmaap.datarouter.mail.protocol"));\r
-               \r
-       Session session = Session.getDefaultInstance(mailproperties, null);\r
-       Multipart mp = new MimeMultipart();\r
-       MimeBodyPart htmlPart = new MimeBodyPart();\r
-       \r
-       try {\r
-               \r
-         Message msg = new MimeMessage(session);\r
-         msg.setFrom(new InternetAddress(mailprops.get("com.att.dmaap.datarouter.mail.from").toString()));\r
-         \r
-         InternetAddress[] addressTo = new InternetAddress[emails.length];\r
-         for ( int x =0 ; x < emails.length; x++) {\r
-              addressTo[x] = new InternetAddress(emails[x]);\r
-         }\r
-         \r
-         msg.addRecipients(Message.RecipientType.TO, addressTo);\r
-         msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());\r
-         htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString().replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");\r
-         mp.addBodyPart(htmlPart);\r
-         msg.setContent(mp);\r
-         \r
-         System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString().replace("[SERVER]", InetAddress.getLocalHost().getHostName()));\r
-       \r
-         Transport.send(msg);\r
-         intlogger.info("HTTPS relaxation mail is sent to - : "+email);\r
-         \r
-       } catch (AddressException e) {\r
-                 intlogger.error("Invalid email address, unable to send https relaxation mail to - : "+email);\r
-       } catch (MessagingException e) {\r
-               intlogger.error("Invalid email address, unable to send https relaxation mail to - : "+email);\r
-       } \r
-       }\r
-\r
-\r
-       /**\r
-        * Get an array of all node names in the DR network.\r
-        * @return an array of Strings\r
-        */\r
-       public static String[] getNodes() {\r
-               return nodes;\r
-       }\r
-       /**\r
-        * Get an array of all node InetAddresses in the DR network.\r
-        * @return an array of InetAddresses\r
-        */\r
-       public static InetAddress[] getNodeAddresses() {\r
-               return nodeAddresses;\r
-       }\r
-       /**\r
-        * Get an array of all POD names in the DR network.\r
-        * @return an array of Strings\r
-        */\r
-       public static String[] getPods() {\r
-               return new String[] { initial_active_pod, initial_standby_pod };\r
-       }\r
-       /**\r
-        * Get an array of all POD InetAddresses in the DR network.\r
-        * @return an array of InetAddresses\r
-        */\r
-       public static InetAddress[] getPodAddresses() {\r
-               return podAddresses;\r
-       }\r
-       /**\r
-        * Gets the FQDN of the initially ACTIVE provisioning server (POD).\r
-        * Note: this used to be called isActivePOD(), however, that is a misnomer, as the active status\r
-        * could shift to the standby POD without these parameters changing.  Hence, the function names\r
-        * have been changed to more accurately reflect their purpose.\r
-        * @return the FQDN\r
-        */\r
-       public static boolean isInitialActivePOD() {\r
-               return this_pod.equals(initial_active_pod);\r
-       }\r
-       /**\r
-        * Gets the FQDN of the initially STANDBY provisioning server (POD).\r
-        * Note: this used to be called isStandbyPOD(), however, that is a misnomer, as the standby status\r
-        * could shift to the active POD without these parameters changing.  Hence, the function names\r
-        * have been changed to more accurately reflect their purpose.\r
-        * @return the FQDN\r
-        */\r
-       public static boolean isInitialStandbyPOD() {\r
-               return this_pod.equals(initial_standby_pod);\r
-       }\r
-       /**\r
-        * INSERT an {@link Insertable} bean into the database.\r
-        * @param bean the bean representing a row to insert\r
-        * @return true if the INSERT was successful\r
-        */\r
-       protected boolean doInsert(Insertable bean) {\r
-               boolean rv = false;\r
-               DB db = new DB();\r
-               Connection conn = null;\r
-               try {\r
-                       conn = db.getConnection();\r
-                       rv = bean.doInsert(conn);\r
-               } catch (SQLException e) {\r
-                       rv = false;\r
-                       intlogger.warn("PROV0005 doInsert: "+e.getMessage());\r
-                       e.printStackTrace();\r
-               } finally {\r
-                       if (conn != null)\r
-                               db.release(conn);\r
-               }\r
-               return rv;\r
-       }\r
-       /**\r
-        * UPDATE an {@link Updateable} bean in the database.\r
-        * @param bean the bean representing a row to update\r
-        * @return true if the UPDATE was successful\r
-        */\r
-       protected boolean doUpdate(Updateable bean) {\r
-               boolean rv = false;\r
-               DB db = new DB();\r
-               Connection conn = null;\r
-               try {\r
-                       conn = db.getConnection();\r
-                       rv = bean.doUpdate(conn);\r
-               } catch (SQLException e) {\r
-                       rv = false;\r
-                       intlogger.warn("PROV0006 doUpdate: "+e.getMessage());\r
-                       e.printStackTrace();\r
-               } finally {\r
-                       if (conn != null)\r
-                               db.release(conn);\r
-               }\r
-               return rv;\r
-       }\r
-       /**\r
-        * DELETE an {@link Deleteable} bean from the database.\r
-        * @param bean the bean representing a row to delete\r
-        * @return true if the DELETE was successful\r
-        */\r
-       protected boolean doDelete(Deleteable bean) {\r
-               boolean rv = false;\r
-               DB db = new DB();\r
-               Connection conn = null;\r
-               try {\r
-                       conn = db.getConnection();\r
-                       rv = bean.doDelete(conn);\r
-               } catch (SQLException e) {\r
-                       rv = false;\r
-                       intlogger.warn("PROV0007 doDelete: "+e.getMessage());\r
-                       e.printStackTrace();\r
-               } finally {\r
-                       if (conn != null)\r
-                               db.release(conn);\r
-               }\r
-               return rv;\r
-       }\r
-       private static boolean getBoolean(Map<String,String> map, String name) {\r
-               String s = map.get(name);\r
-               return (s != null) && s.equalsIgnoreCase("true");\r
-       }\r
-       private static String getString(Map<String,String> map, String name, String dflt) {\r
-               String s = map.get(name);\r
-               return (s != null) ? s : dflt;\r
-       }\r
-       private static int getInt(Map<String,String> map, String name, int dflt) {\r
-               try {\r
-                       String s = map.get(name);\r
-                       return Integer.parseInt(s);\r
-               } catch (NumberFormatException e) {\r
-                       return dflt;\r
-               }\r
-       }\r
-       private static Set<String> getSet(Map<String,String> map, String name) {\r
-               Set<String> set = new HashSet<String>();\r
-               String s = map.get(name);\r
-               if (s != null) {\r
-                       String[] pp = s.split("\\|");\r
-                       if (pp != null) {\r
-                               for (String t : pp) {\r
-                                       String t2 = t.trim();\r
-                                       if (t2.length() > 0)\r
-                                               set.add(t2);\r
-                               }\r
-                       }\r
-               }\r
-               return set;\r
-       }\r
-\r
-       /**\r
-        * A class used to encapsulate a Content-type header, separating out the "version" attribute\r
-        * (which defaults to "1.0" if missing).\r
-        */\r
-       public class ContentHeader {\r
-               private String type = "";\r
-               private Map<String, String> map = new HashMap<String, String>();\r
-               public ContentHeader() {\r
-                       this("", "1.0");\r
-               }\r
-               public ContentHeader(String t, String v) {\r
-                       type = t.trim();\r
-                       map.put("version", v);\r
-               }\r
-               public String getType() {\r
-                       return type;\r
-               }\r
-               public String getAttribute(String key) {\r
-                       String s = map.get(key);\r
-                       if (s == null)\r
-                               s = "";\r
-                       return s;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Get the ContentHeader from an HTTP request.\r
-        * @param req the request\r
-        * @return the header, encapsulated in a ContentHeader object\r
-        */\r
-       public ContentHeader getContentHeader(HttpServletRequest req) {\r
-               ContentHeader ch = new ContentHeader();\r
-               String s = req.getHeader("Content-Type");\r
-               if (s != null) {\r
-                       String[] pp = s.split(";");\r
-                       ch.type = pp[0].trim();\r
-                       for (int i = 1; i < pp.length; i++) {\r
-                               int ix = pp[i].indexOf('=');\r
-                               if (ix > 0) {\r
-                                       String k = pp[i].substring(0, ix).trim();\r
-                                       String v = pp[i].substring(ix+1).trim();\r
-                                       ch.map.put(k,  v);\r
-                               } else {\r
-                                       ch.map.put(pp[i].trim(), "");\r
-                               }\r
-                       }\r
-               }\r
-               return ch;\r
-       }\r
-       // Methods for the Policy Engine classes - ProvDataProvider interface\r
-       @Override\r
-       public String getFeedOwner(String feedId) {\r
-               try {\r
-                       int n = Integer.parseInt(feedId);\r
-                       Feed f = Feed.getFeedById(n);\r
-                       if (f != null)\r
-                               return f.getPublisher();\r
-               } catch (NumberFormatException e) {\r
-                       // ignore\r
-               }\r
-               return null;\r
-       }\r
-       @Override\r
-       public String getFeedClassification(String feedId) {\r
-               try {\r
-                       int n = Integer.parseInt(feedId);\r
-                       Feed f = Feed.getFeedById(n);\r
-                       if (f != null)\r
-                               return f.getAuthorization().getClassification();\r
-               } catch (NumberFormatException e) {\r
-                       // ignore\r
-               }\r
-               return null;\r
-       }\r
-       @Override\r
-       public String getSubscriptionOwner(String subId) {\r
-               try {\r
-                       int n = Integer.parseInt(subId);\r
-                       Subscription s = Subscription.getSubscriptionById(n);\r
-                       if (s != null)\r
-                               return s.getSubscriber();\r
-               } catch (NumberFormatException e) {\r
-                       // ignore\r
-               }\r
-               return null;\r
-       }\r
-\r
-       /*\r
-        * @Method - isUserMemberOfGroup - Rally:US708115 \r
-        * @Params - group object and user to check if exists in given group\r
-        * @return - boolean value /true/false\r
-        */\r
-       private boolean isUserMemberOfGroup(Group group, String user) {\r
-                        \r
-               String groupdetails = group.getMembers().replace("]", "").replace("[", "");\r
-           String s[] =        groupdetails.split("},");\r
-               \r
-               for(int i=0; i < s.length; i++) {\r
-                               JSONObject jsonObj = null;\r
-                               try {\r
-                           jsonObj = new JSONObject(s[i]+"}");\r
-                           if(jsonObj.get("id").equals(user))\r
-                               return true;\r
-                       } catch (JSONException e) {\r
-                           e.printStackTrace();\r
-                       }\r
-               }\r
-               return false;\r
-               \r
-       }\r
-       \r
-       /*\r
-        * @Method - getGroupByFeedGroupId- Rally:US708115 \r
-        * @Params - User to check in group and feedid which is assigned the group.\r
-        * @return - string value grupid/null\r
-        */\r
-       @Override\r
-       public String getGroupByFeedGroupId(String owner, String feedId) {\r
-               try {\r
-                       int n = Integer.parseInt(feedId);\r
-                       Feed f = Feed.getFeedById(n);\r
-                       if (f != null) {\r
-                               int groupid = f.getGroupid();\r
-                               if(groupid > 0) {\r
-                                       Group group = Group.getGroupById(groupid);\r
-                                       if(isUserMemberOfGroup(group, owner)) {\r
-                                               return group.getAuthid();\r
-                                       }\r
-                               }\r
-                       }\r
-               } catch (NumberFormatException e) {\r
-                       // ignore\r
-               }\r
-               return null;\r
-       }\r
-       \r
-       /*\r
-        * @Method - getGroupBySubGroupId - Rally:US708115  \r
-        * @Params - User to check in group and subid which is assigned the group.\r
-        * @return - string value grupid/null\r
-        */\r
-       @Override\r
-       public String getGroupBySubGroupId(String owner, String subId) {\r
-               try {\r
-                       int n = Integer.parseInt(subId);\r
-                       Subscription s = Subscription.getSubscriptionById(n);\r
-                       if (s != null) {\r
-                               int groupid = s.getGroupid();\r
-                               if(groupid > 0) {\r
-                                       Group group = Group.getGroupById(groupid);\r
-                                       if(isUserMemberOfGroup(group, owner)) {\r
-                                               return group.getAuthid();\r
-                                       }\r
-                               }\r
-                       }\r
-               } catch (NumberFormatException e) {\r
-                       // ignore\r
-               }\r
-               return null;\r
-       }\r
-       \r
-       /*\r
-        * @Method - setIpAndFqdnForEelf - Rally:US664892  \r
-        * @Params - method, prints method name in EELF log.\r
-        */     \r
-       protected void setIpAndFqdnForEelf(String method) {\r
-               MDC.clear();\r
-        MDC.put(MDC_SERVICE_NAME, method);\r
-        try {\r
-            MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());\r
-            MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());\r
-        } catch (Exception e) {\r
-            e.printStackTrace();\r
-        }\r
-\r
-       }\r
-}\r
+/*******************************************************************************
+ * ============LICENSE_START==================================================
+ * * org.onap.dmaap
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+
+
+package org.onap.dmaap.datarouter.provisioning;
+
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
+import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
+
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.cert.X509Certificate;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONTokener;
+import org.onap.dmaap.datarouter.authz.Authorizer;
+import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
+import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
+import org.onap.dmaap.datarouter.provisioning.beans.*;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
+import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
+import org.slf4j.MDC;
+
+import javax.mail.*;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import java.security.GeneralSecurityException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+
+/**
+ * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
+ * methods.
+ *
+ * @author Robert Eby
+ * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $
+ */
+@SuppressWarnings("serial")
+public class BaseServlet extends HttpServlet implements ProvDataProvider {
+
+    public static final String BEHALF_HEADER = "X-DMAAP-DR-ON-BEHALF-OF";
+
+    public static final String EXCLUDE_AAF_HEADER = "X-EXCLUDE-AAF";
+
+    private static final String AAF_CADI_FEED_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.feed.type";
+    private static final String AAF_CADI_SUB_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.sub.type";
+    private static final String AAF_INSTANCE = "org.onap.dmaap.datarouter.provserver.aaf.instance";
+    private static final String AAF_CADI_FEED = "org.onap.dmaap-dr.feed";
+    private static final String AAF_CADI_SUB = "org.onap.dmaap-dr.sub";
+
+    static final String CREATE_PERMISSION = "create";
+    static final String EDIT_PERMISSION = "edit";
+    static final String DELETE_PERMISSION = "delete";
+    static final String PUBLISH_PERMISSION = "publish";
+    static final String SUSPEND_PERMISSION = "suspend";
+    static final String RESTORE_PERMISSION = "restore";
+    static final String SUBSCRIBE_PERMISSION = "subscribe";
+    static final String APPROVE_SUB_PERMISSION = "approveSub";
+
+    static final String FEED_BASECONTENT_TYPE = "application/vnd.dmaap-dr.feed";
+    public static final String FEED_CONTENT_TYPE = "application/vnd.dmaap-dr.feed; version=2.0";
+    public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-full; version=2.0";
+    public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-list; version=1.0";
+    static final String SUB_BASECONTENT_TYPE = "application/vnd.dmaap-dr.subscription";
+    public static final String SUB_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription; version=2.0";
+    public static final String SUBFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-full; version=2.0";
+    static final String SUBLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-list; version=1.0";
+
+
+    //Adding groups functionality, ...1610
+    static final String GROUP_BASECONTENT_TYPE = "application/vnd.dmaap-dr.group";
+    static final String GROUP_CONTENT_TYPE = "application/vnd.dmaap-dr.group; version=2.0";
+    public static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
+    public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.fegrouped-list; version=1.0";
+
+
+    public static final String LOGLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.log-list; version=1.0";
+    public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.dmaap-dr.provfeed-full; version=1.0";
+    public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.dmaap-dr.provfeed-full; version=2.0";
+    public static final String CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";
+
+    static final String DB_PROBLEM_MSG = "There has been a problem with the DB.  It is suggested you try the operation again.";
+
+    private static final int DEFAULT_MAX_FEEDS = 10000;
+    private static final int DEFAULT_MAX_SUBS = 100000;
+    private static final int DEFAULT_POKETIMER1 = 5;
+    private static final int DEFAULT_POKETIMER2 = 30;
+    private static final String DEFAULT_DOMAIN = "onap";
+    private static final String DEFAULT_PROVSRVR_NAME = "dmaap-dr-prov";
+    private static final String STATIC_ROUTING_NODES = ""; //Adding new param for static Routing - Rally:US664862-1610
+
+    //Common Errors
+    public static final String MISSING_ON_BEHALF = "Missing X-DMAAP-DR-ON-BEHALF-OF header.";
+    public static final String MISSING_FEED = "Missing or bad feed number.";
+    public static final String POLICY_ENGINE = "Policy Engine disallows access.";
+    public static final String UNAUTHORIZED = "Unauthorized.";
+    public static final String BAD_SUB = "Missing or bad subscription number.";
+    public static final String BAD_JSON = "Badly formed JSON";
+    public static final String BAD_URL = "Bad URL.";
+
+    public static final String API = "/api/";
+    public static final String LOGS = "/logs/";
+    public static final String TEXT_CT = "text/plain";
+    public static final String INGRESS = "/ingress/";
+    public static final String EGRESS = "/egress/";
+    public static final String NETWORK = "/network/";
+    public static final String GROUPID = "groupid";
+    public static final String FEEDID = "feedid";
+    public static final String FEEDIDS = "feedids";
+    public static final String SUBID = "subid";
+    public static final String EVENT_TYPE = "eventType";
+    public static final String OUTPUT_TYPE = "output_type";
+    public static final String START_TIME = "start_time";
+    public static final String END_TIME = "end_time";
+    public static final String REASON_SQL = "reasonSQL";
+
+
+    /**
+     * A boolean to trigger one time "provisioning changed" event on startup
+     */
+    private static boolean startmsgFlag = true;
+    /**
+     * This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE)
+     */
+    private static boolean requireSecure = true;
+    /**
+     * This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT)
+     */
+    private static boolean requireCert = true;
+    /**
+     * The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES)
+     */
+    private static Set<String> authorizedAddressesAndNetworks = new HashSet<>();
+    /**
+     * The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS)
+     */
+    private static Set<String> authorizedNames = new HashSet<>();
+    /**
+     * The FQDN of the initially "active" provisioning server in this Data Router ecosystem
+     */
+    private static String initialActivePod;
+    /**
+     * The FQDN of the initially "standby" provisioning server in this Data Router ecosystem
+     */
+    private static String initialStandbyPod;
+    /**
+     * The FQDN of this provisioning server in this Data Router ecosystem
+     */
+    private static String thisPod;
+    /**
+     * "Timer 1" - used to determine when to notify nodes of provisioning changes
+     */
+    private static long pokeTimer1;
+    /**
+     * "Timer 2" - used to determine when to notify nodes of provisioning changes
+     */
+    private static long pokeTimer2;
+    /**
+     * Array of nodes names and/or FQDNs
+     */
+    private static String[] nodes = new String[0];
+    /**
+     * [DATARTR-27] Poke all the DR nodes : Array of nodes names and/or FQDNs
+     */
+    private static String[] drnodes = new String[0];
+    /**
+     * Array of node IP addresses
+     */
+    private static InetAddress[] nodeAddresses = new InetAddress[0];
+    /**
+     * Array of POD IP addresses
+     */
+    private static InetAddress[] podAddresses = new InetAddress[0];
+    /**
+     * The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT)
+     */
+    static int maxFeeds = 0;
+    /**
+     * The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT)
+     */
+    static int maxSubs = 0;
+    /**
+     * The current number of feeds in the system
+     */
+    static int activeFeeds = 0;
+    /**
+     * The current number of subscriptions in the system
+     */
+    static int activeSubs = 0;
+
+    /**
+     * The domain used to generate a FQDN from the "bare" node names
+     */
+    private static String provDomain = "web.att.com";
+
+    /**
+     * The standard FQDN of the provisioning server in this Data Router ecosystem
+     */
+    private static String provName = "feeds-drtr.web.att.com";
+
+    /**
+     * The standard FQDN of the ACTIVE provisioning server in this Data Router ecosystem
+     */
+    private static String activeProvName = "feeds-drtr.web.att.com";
+
+    //Adding new param for static Routing - Rally:US664862-1610
+    private static String staticRoutingNodes = STATIC_ROUTING_NODES;
+
+    /**
+     * This logger is used to log provisioning events
+     */
+    protected static EELFLogger eventlogger;
+    /**
+     * This logger is used to log internal events (errors, etc.)
+     */
+    protected static EELFLogger intlogger;
+    /**
+     * Authorizer - interface to the Policy Engine
+     */
+    protected static Authorizer authz;
+    /**
+     * The Synchronizer used to sync active DB to standby one
+     */
+    private static SynchronizerTask synctask = null;
+
+    //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
+    private InetAddress thishost;
+    private InetAddress loopback;
+    private static Boolean mailSendFlag = false;
+
+    private static final String MAILCONFIG_FILE = "mail.properties";
+    private static Properties mailprops;
+
+    //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
+    private static String isAddressAuthEnabled = (new DB()).getProperties()
+            .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
+
+    static String isCadiEnabled = (new DB()).getProperties()
+            .getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false");
+
+    /**
+     * Initialize data common to all the provisioning server servlets.
+     */
+    protected BaseServlet() {
+        if(eventlogger == null) {
+            this.eventlogger = EELFManager.getInstance().getLogger("EventLog");
+        }
+        if(intlogger == null) {
+            this.intlogger = EELFManager.getInstance().getLogger("InternalLog");
+        }
+        if (authz == null) {
+            authz = new ProvAuthorizer(this);
+        }
+        if (startmsgFlag) {
+            startmsgFlag = false;
+            provisioningParametersChanged();
+        }
+        if (synctask == null) {
+            synctask = SynchronizerTask.getSynchronizer();
+        }
+        String name = this.getClass().getName();
+        intlogger.info("PROV0002 Servlet " + name + " started.");
+    }
+
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        try {
+            thishost = InetAddress.getLocalHost();
+            loopback = InetAddress.getLoopbackAddress();
+        } catch (UnknownHostException e) {
+            intlogger.info("BaseServlet.init: " + e.getMessage(), e);
+        }
+    }
+
+    public static int getIdFromPath(HttpServletRequest req) {
+        String path = req.getPathInfo();
+        if (path == null || path.length() < 2) {
+            return -1;
+        }
+        try {
+            return Integer.parseInt(path.substring(1));
+        } catch (NumberFormatException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Read the request's input stream and return a JSONObject from it
+     *
+     * @param req the HTTP request
+     * @return the JSONObject, or null if the stream cannot be parsed
+     */
+    JSONObject getJSONfromInput(HttpServletRequest req) {
+        JSONObject jo = null;
+        try {
+            jo = new JSONObject(new JSONTokener(req.getInputStream()));
+            if (intlogger.isDebugEnabled()) {
+                intlogger.debug("JSON: " + jo.toString());
+            }
+        } catch (Exception e) {
+            intlogger.info("Error reading JSON: " + e);
+        }
+        return jo;
+    }
+
+    /**
+     * This method encrypt/decrypt the key in the JSON passed by user request inside the authorisation header object in request before logging the JSON.
+     *
+     * @param jo-      the JSON passed in http request.
+     * @param maskKey- the key to be masked in the JSON passed.
+     * @param action-  whether to mask the key or unmask it in a JSON passed.
+     * @return the JSONObject, or null if the stream cannot be parsed.
+     */
+    public static JSONObject maskJSON(JSONObject jo, String maskKey, boolean action) {
+        if (!jo.isNull("authorization")) {
+            JSONObject j2 = jo.getJSONObject("authorization");
+            JSONArray ja = j2.getJSONArray("endpoint_ids");
+            for (int i = 0; i < ja.length(); i++) {
+                if ((!ja.getJSONObject(i).isNull(maskKey))) {
+                    String password = ja.getJSONObject(i).get(maskKey).toString();
+                    try {
+                        if (action) {
+                            ja.getJSONObject(i).put(maskKey, PasswordProcessor.encrypt(password));
+                        } else {
+                            ja.getJSONObject(i).put(maskKey, PasswordProcessor.decrypt(password));
+                        }
+                    } catch (JSONException | GeneralSecurityException e) {
+                        intlogger.info("Error reading JSON while masking: " + e);
+                    }
+                }
+            }
+        }
+        return jo;
+    }
+
+    /**
+     * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
+     * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
+     * (configured via PROV_AUTH_SUBJECTS)?
+     *
+     * @param request the request
+     * @return an error string, or null if all is OK
+     */
+    String isAuthorizedForProvisioning(HttpServletRequest request) {
+        if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
+            return null;
+        }
+        // Is the request https?
+        if (requireSecure && !request.isSecure()) {
+            return "Request must be made over an HTTPS connection.";
+        }
+        // Is remote IP authorized?
+        String remote = request.getRemoteAddr();
+        try {
+            boolean found = false;
+            InetAddress ip = InetAddress.getByName(remote);
+            for (String addrnet : authorizedAddressesAndNetworks) {
+                found |= addressMatchesNetwork(ip, addrnet);
+            }
+            if (!found) {
+                return "Unauthorized address: " + remote;
+            }
+        } catch (UnknownHostException e) {
+            intlogger.error("PROV0051 BaseServlet.isAuthorizedForProvisioning: " + e.getMessage(), e);
+            return "Unauthorized address: " + remote;
+        }
+        // Does remote have a valid certificate?
+        if (requireCert) {
+            X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
+            if (certs == null || certs.length == 0) {
+                return "Client certificate is missing.";
+            }
+            // cert[0] is the client cert
+            // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
+            String name = certs[0].getSubjectX500Principal().getName();
+            if (!authorizedNames.contains(name)) {
+                return "No authorized certificate found.";
+            }
+        }
+        // No problems!
+        return null;
+    }
+
+    /**
+     * Check if the remote IP address is authorized to see the /internal URL tree.
+     *
+     * @param request the HTTP request
+     * @return true iff authorized
+     */
+    boolean isAuthorizedForInternal(HttpServletRequest request) {
+        try {
+            if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
+                return true;
+            }
+            InetAddress ip = InetAddress.getByName(request.getRemoteAddr());
+            for (InetAddress node : getNodeAddresses()) {
+                if (node != null && ip.equals(node)) {
+                    return true;
+                }
+            }
+            for (InetAddress pod : getPodAddresses()) {
+                if (pod != null && ip.equals(pod)) {
+                    return true;
+                }
+            }
+            if (thishost != null && ip.equals(thishost)) {
+                return true;
+            }
+            if (loopback != null && ip.equals(loopback)) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            intlogger.error("PROV0052 BaseServlet.isAuthorizedForInternal: " + e.getMessage(), e);
+        }
+        return false;
+    }
+
+    /**
+     * Check if an IP address matches a network address.
+     *
+     * @param ip the IP address
+     * @param s  the network address; a bare IP address may be matched also
+     * @return true if they intersect
+     */
+    private static boolean addressMatchesNetwork(InetAddress ip, String s) {
+        int mlen = -1;
+        int n = s.indexOf("/");
+        if (n >= 0) {
+            mlen = Integer.parseInt(s.substring(n + 1));
+            s = s.substring(0, n);
+        }
+        try {
+            InetAddress i2 = InetAddress.getByName(s);
+            byte[] b1 = ip.getAddress();
+            byte[] b2 = i2.getAddress();
+            if (b1.length != b2.length) {
+                return false;
+            }
+            if (mlen > 0) {
+                byte[] masks = {
+                        (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
+                        (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
+                };
+                byte mask = masks[mlen % 8];
+                for (n = mlen / 8; n < b1.length; n++) {
+                    b1[n] &= mask;
+                    b2[n] &= mask;
+                    mask = 0;
+                }
+            }
+            for (n = 0; n < b1.length; n++) {
+                if (b1[n] != b2[n]) {
+                    return false;
+                }
+            }
+        } catch (UnknownHostException e) {
+            intlogger.error("PROV0053 BaseServlet.addressMatchesNetwork: " + e.getMessage(), e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
+     * be regenerated, and cause nodes and the other provisioning server to be notified.
+     */
+    static void provisioningDataChanged() {
+        long now = System.currentTimeMillis();
+        Poker p = Poker.getPoker();
+        p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
+    }
+
+    /**
+     * Something in the parameters has changed, reload all parameters from the DB.
+     */
+    static void provisioningParametersChanged() {
+        Map<String, String> map = Parameters.getParameters();
+        requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
+        requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
+        authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);
+        authorizedNames = getSet(map, Parameters.PROV_AUTH_SUBJECTS);
+        nodes = getSet(map, Parameters.NODES).toArray(new String[0]);
+        maxFeeds = getInt(map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);
+        maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
+        pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
+        pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
+        /**
+         * The domain used to generate a FQDN from the "bare" node names
+         */
+        provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
+        provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
+        activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
+        initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
+        initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
+        staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
+                ""); //Adding new param for static Routing - Rally:US664862-1610
+        activeFeeds = Feed.countActiveFeeds();
+        activeSubs = Subscription.countActiveSubscriptions();
+        try {
+            thisPod = InetAddress.getLocalHost().getHostName();
+        } catch (UnknownHostException e) {
+            thisPod = "";
+            intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.", e);
+        }
+
+        // Normalize the nodes, and fill in nodeAddresses
+        InetAddress[] na = new InetAddress[nodes.length];
+        for (int i = 0; i < nodes.length; i++) {
+            try {
+                na[i] = InetAddress.getByName(nodes[i]);
+                intlogger.debug("PROV0003 DNS lookup: " + nodes[i] + " => " + na[i].toString());
+            } catch (UnknownHostException e) {
+                na[i] = null;
+                intlogger.warn("PROV0004 Cannot lookup " + nodes[i] + ": " + e.getMessage(), e);
+            }
+        }
+
+        //[DATARTR-27] Poke all the DR nodes: assigning DR Nodes
+        drnodes = nodes.clone();
+
+        //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
+        List<String> filterNodes = new ArrayList<>();
+        for (String node : nodes) {
+            if (!staticRoutingNodes.contains(node)) {
+                filterNodes.add(node);
+            }
+        }
+        nodes = filterNodes.toArray(new String[0]);
+
+        nodeAddresses = na;
+        NodeClass.setNodes(nodes);        // update NODES table
+
+        // Normalize the PODs, and fill in podAddresses
+        String[] pods = getPods();
+        na = new InetAddress[pods.length];
+        for (int i = 0; i < pods.length; i++) {
+            try {
+                na[i] = InetAddress.getByName(pods[i]);
+                intlogger.debug("PROV0003 DNS lookup: " + pods[i] + " => " + na[i].toString());
+            } catch (UnknownHostException e) {
+                na[i] = null;
+                intlogger.warn("PROV0004 Cannot lookup " + pods[i] + ": " + e.getMessage(), e);
+            }
+        }
+        podAddresses = na;
+
+        // Update ThrottleFilter
+        ThrottleFilter.configure();
+
+        // Check if we are active or standby POD
+        if (!isInitialActivePOD() && !isInitialStandbyPOD()) {
+            intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");
+        }
+    }
+
+
+    /**
+     * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Load mail properties.
+     *
+     * @author vs215k
+     **/
+    private void loadMailProperties() {
+        if (mailprops == null) {
+            mailprops = new Properties();
+            try (InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE)) {
+                mailprops.load(inStream);
+            } catch (IOException e) {
+                intlogger.error("PROV9003 Opening properties: " + e.getMessage(), e);
+                System.exit(1);
+            }
+        }
+    }
+
+
+    /**
+     * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
+     *
+     * @param email - list of email ids to notify if HTTP relexcation is enabled.
+     * @author vs215k
+     **/
+    private void notifyPSTeam(String email) {
+        loadMailProperties(); //Load HTTPS Relex mail properties.
+        String[] emails = email.split(Pattern.quote("|"));
+
+        Properties mailproperties = new Properties();
+        mailproperties.put("mail.smtp.host", mailprops.get("com.att.dmaap.datarouter.mail.server"));
+        mailproperties.put("mail.transport.protocol", mailprops.get("com.att.dmaap.datarouter.mail.protocol"));
+
+        Session session = Session.getDefaultInstance(mailproperties, null);
+        Multipart mp = new MimeMultipart();
+        MimeBodyPart htmlPart = new MimeBodyPart();
+
+        try {
+
+            Message msg = new MimeMessage(session);
+            msg.setFrom(new InternetAddress(mailprops.get("com.att.dmaap.datarouter.mail.from").toString()));
+
+            InternetAddress[] addressTo = new InternetAddress[emails.length];
+            for (int x = 0; x < emails.length; x++) {
+                addressTo[x] = new InternetAddress(emails[x]);
+            }
+
+            msg.addRecipients(Message.RecipientType.TO, addressTo);
+            msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());
+            htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
+            mp.addBodyPart(htmlPart);
+            msg.setContent(mp);
+
+            intlogger.info(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
+
+            Transport.send(msg);
+            intlogger.info("HTTPS relaxation mail is sent to - : " + email);
+
+        } catch (MessagingException e) {
+            intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email, e);
+        } catch (UnknownHostException uhe) {
+            intlogger.error("UnknownHostException", uhe);
+        }
+    }
+
+    public static String getProvName() {
+        return provName;
+    }
+
+    public static String getActiveProvName() {
+        return activeProvName;
+    }
+
+    /**
+     * Get an array of all node names in the DR network.
+     *
+     * @return an array of Strings
+     */
+    public static String[] getNodes() {
+        return nodes;
+    }
+
+    /**
+     * [DATARTR-27] Poke all the DR nodes
+     * Get an array of all node names in the DR network.
+     *
+     * @return an array of Strings
+     */
+    public static String[] getDRNodes() {
+        return drnodes;
+    }
+
+    /**
+     * Get an array of all node InetAddresses in the DR network.
+     *
+     * @return an array of InetAddresses
+     */
+    public static InetAddress[] getNodeAddresses() {
+        return nodeAddresses;
+    }
+
+    /**
+     * Get an array of all POD names in the DR network.
+     *
+     * @return an array of Strings
+     */
+    public static String[] getPods() {
+        return new String[]{initialActivePod, initialStandbyPod};
+    }
+
+    /**
+     * Get an array of all POD InetAddresses in the DR network.
+     *
+     * @return an array of InetAddresses
+     */
+    private static InetAddress[] getPodAddresses() {
+        return podAddresses;
+    }
+
+    /**
+     * Gets the FQDN of the initially ACTIVE provisioning server (POD). Note: this used to be called isActivePOD(),
+     * however, that is a misnomer, as the active status could shift to the standby POD without these parameters
+     * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
+     *
+     * @return the FQDN
+     */
+    public static boolean isInitialActivePOD() {
+        return thisPod.equals(initialActivePod);
+    }
+
+    /**
+     * Gets the FQDN of the initially STANDBY provisioning server (POD). Note: this used to be called isStandbyPOD(),
+     * however, that is a misnomer, as the standby status could shift to the active POD without these parameters
+     * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
+     *
+     * @return the FQDN
+     */
+    public static boolean isInitialStandbyPOD() {
+        return thisPod.equals(initialStandbyPod);
+    }
+
+    /**
+     * INSERT an {@link Insertable} bean into the database.
+     *
+     * @param bean the bean representing a row to insert
+     * @return true if the INSERT was successful
+     */
+    protected boolean doInsert(Insertable bean) {
+        boolean rv;
+        DB db = new DB();
+        Connection conn = null;
+        try {
+            conn = db.getConnection();
+            rv = bean.doInsert(conn);
+        } catch (SQLException e) {
+            rv = false;
+            intlogger.warn("PROV0005 doInsert: " + e.getMessage(), e);
+        } finally {
+            if (conn != null) {
+                db.release(conn);
+            }
+        }
+        return rv;
+    }
+
+    /**
+     * UPDATE an {@link Updateable} bean in the database.
+     *
+     * @param bean the bean representing a row to update
+     * @return true if the UPDATE was successful
+     */
+    protected boolean doUpdate(Updateable bean) {
+        boolean rv;
+        DB db = new DB();
+        Connection conn = null;
+        try {
+            conn = db.getConnection();
+            rv = bean.doUpdate(conn);
+        } catch (SQLException e) {
+            rv = false;
+            intlogger.warn("PROV0006 doUpdate: " + e.getMessage(), e);
+        } finally {
+            if (conn != null) {
+                db.release(conn);
+            }
+        }
+        return rv;
+    }
+
+    /**
+     * DELETE an {@link Deleteable} bean from the database.
+     *
+     * @param bean the bean representing a row to delete
+     * @return true if the DELETE was successful
+     */
+    protected boolean doDelete(Deleteable bean) {
+        boolean rv;
+        DB db = new DB();
+        Connection conn = null;
+        try {
+            conn = db.getConnection();
+            rv = bean.doDelete(conn);
+        } catch (SQLException e) {
+            rv = false;
+            intlogger.warn("PROV0007 doDelete: " + e.getMessage(), e);
+        } finally {
+            if (conn != null) {
+                db.release(conn);
+            }
+        }
+        return rv;
+    }
+
+    private static boolean getBoolean(Map<String, String> map, String name) {
+        String s = map.get(name);
+        return (s != null) && "true".equalsIgnoreCase(s);
+    }
+
+    private static String getString(Map<String, String> map, String name, String dflt) {
+        String s = map.get(name);
+        return (s != null) ? s : dflt;
+    }
+
+    private static int getInt(Map<String, String> map, String name, int dflt) {
+        try {
+            String s = map.get(name);
+            return Integer.parseInt(s);
+        } catch (NumberFormatException e) {
+            return dflt;
+        }
+    }
+
+    private static Set<String> getSet(Map<String, String> map, String name) {
+        Set<String> set = new HashSet<>();
+        String s = map.get(name);
+        if (s != null) {
+            String[] pp = s.split("\\|");
+            if (pp != null) {
+                for (String t : pp) {
+                    String t2 = t.trim();
+                    if (t2.length() > 0) {
+                        set.add(t2);
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * A class used to encapsulate a Content-type header, separating out the "version" attribute (which defaults to
+     * "1.0" if missing).
+     */
+    public class ContentHeader {
+
+        private String type = "";
+        private Map<String, String> map = new HashMap<>();
+
+        ContentHeader() {
+            this("", "1.0");
+        }
+
+        ContentHeader(String t, String v) {
+            type = t.trim();
+            map.put("version", v);
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public String getAttribute(String key) {
+            String s = map.get(key);
+            if (s == null) {
+                s = "";
+            }
+            return s;
+        }
+    }
+
+    /**
+     * Get the ContentHeader from an HTTP request.
+     *
+     * @param req the request
+     * @return the header, encapsulated in a ContentHeader object
+     */
+    ContentHeader getContentHeader(HttpServletRequest req) {
+        ContentHeader ch = new ContentHeader();
+        String s = req.getHeader("Content-Type");
+        if (s != null) {
+            String[] pp = s.split(";");
+            ch.type = pp[0].trim();
+            for (int i = 1; i < pp.length; i++) {
+                int ix = pp[i].indexOf('=');
+                if (ix > 0) {
+                    String k = pp[i].substring(0, ix).trim();
+                    String v = pp[i].substring(ix + 1).trim();
+                    ch.map.put(k, v);
+                } else {
+                    ch.map.put(pp[i].trim(), "");
+                }
+            }
+        }
+        return ch;
+    }
+
+    // Methods for the Policy Engine classes - ProvDataProvider interface
+    @Override
+    public String getFeedOwner(String feedId) {
+        try {
+            int n = Integer.parseInt(feedId);
+            Feed f = Feed.getFeedById(n);
+            if (f != null) {
+                return f.getPublisher();
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    @Override
+    public String getFeedClassification(String feedId) {
+        try {
+            int n = Integer.parseInt(feedId);
+            Feed f = Feed.getFeedById(n);
+            if (f != null) {
+                return f.getAuthorization().getClassification();
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    @Override
+    public String getSubscriptionOwner(String subId) {
+        try {
+            int n = Integer.parseInt(subId);
+            Subscription s = Subscription.getSubscriptionById(n);
+            if (s != null) {
+                return s.getSubscriber();
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    /*
+     * @Method - isUserMemberOfGroup - Rally:US708115
+     * @Params - group object and user to check if exists in given group
+     * @return - boolean value /true/false
+     */
+    private boolean isUserMemberOfGroup(Group group, String user) {
+
+        String groupDetails = group.getMembers().replace("]", "").replace("[", "");
+        String[] s = groupDetails.split("},");
+
+        for (String value : s) {
+            JSONObject jsonObj;
+            try {
+                jsonObj = new JSONObject(value + "}");
+                if (jsonObj.get("id").equals(user)) {
+                    return true;
+                }
+            } catch (JSONException e) {
+                intlogger.error("JSONException: " + e.getMessage(), e);
+            }
+        }
+        return false;
+
+    }
+
+    /*
+     * @Method - getGroupByFeedGroupId- Rally:US708115
+     * @Params - User to check in group and feedid which is assigned the group.
+     * @return - string value grupid/null
+     */
+    @Override
+    public String getGroupByFeedGroupId(String owner, String feedId) {
+        try {
+            int n = Integer.parseInt(feedId);
+            Feed f = Feed.getFeedById(n);
+            if (f != null) {
+                int groupid = f.getGroupid();
+                if (groupid > 0) {
+                    Group group = Group.getGroupById(groupid);
+                    assert group != null;
+                    if (isUserMemberOfGroup(group, owner)) {
+                        return group.getAuthid();
+                    }
+                }
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    /*
+     * @Method - getGroupBySubGroupId - Rally:US708115
+     * @Params - User to check in group and subid which is assigned the group.
+     * @return - string value grupid/null
+     */
+    @Override
+    public String getGroupBySubGroupId(String owner, String subId) {
+        try {
+            int n = Integer.parseInt(subId);
+            Subscription s = Subscription.getSubscriptionById(n);
+            if (s != null) {
+                int groupid = s.getGroupid();
+                if (groupid > 0) {
+                    Group group = Group.getGroupById(groupid);
+                    assert group != null;
+                    if (isUserMemberOfGroup(group, owner)) {
+                        return group.getAuthid();
+                    }
+                }
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    /*
+     * @Method - setIpFqdnRequestIDandInvocationIDForEelf
+     * @Params - method, prints method name in EELF log.
+     * @Params- Req, Request used to get RequestId and InvocationId
+     */
+    void setIpFqdnRequestIDandInvocationIDForEelf(String method, HttpServletRequest req) {
+        setIpFqdnForEelf(method);
+        setMDC(req, "X-ONAP-RequestID", MDC_KEY_REQUEST_ID);
+        setMDC(req, "X-InvocationID", "InvocationId");
+    }
+
+    private void setMDC(HttpServletRequest req, String headerName, String keyName) {
+        String mdcId = req.getHeader(headerName);
+        if (StringUtils.isBlank(mdcId)) {
+            mdcId = UUID.randomUUID().toString();
+        }
+        MDC.put(keyName, mdcId);
+    }
+
+    /*
+     * @Method - setIpFqdnRequestIdForEelf - Rally:US664892
+     * @Params - method, prints method name in EELF log.
+     */
+    void setIpFqdnForEelf(String method) {
+        MDC.clear();
+        MDC.put(MDC_SERVICE_NAME, method);
+        try {
+            MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
+            MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
+        } catch (Exception e) {
+            intlogger.error("Exception: " + e.getMessage(), e);
+        }
+
+    }
+
+    /*
+     * AAF changes: TDP EPIC US# 307413
+     * @Method - getFeedPermission - Forming permission string for feed part to check AAF access in CADI Framework
+     * @Params - aafInstance Passing aafInstance as it's used in permission string
+     * @Params - userAction Passing CONST values to set different actions in permission string
+     */
+    String getFeedPermission(String aafInstance, String userAction) {
+        try {
+            Properties props = (new DB()).getProperties();
+            String type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+            String action;
+            switch (userAction) {
+                case CREATE_PERMISSION:
+                    action = CREATE_PERMISSION;
+                    break;
+                case EDIT_PERMISSION:
+                    action = EDIT_PERMISSION;
+                    break;
+                case DELETE_PERMISSION:
+                    action = DELETE_PERMISSION;
+                    break;
+                case PUBLISH_PERMISSION:
+                    action = PUBLISH_PERMISSION;
+                    break;
+                case SUSPEND_PERMISSION:
+                    action = SUSPEND_PERMISSION;
+                    break;
+                case RESTORE_PERMISSION:
+                    action = RESTORE_PERMISSION;
+                    break;
+                default:
+                    action = "*";
+            }
+            if (aafInstance == null || "".equals(aafInstance)) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getFeedPermission: " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /*
+     * AAF changes: TDP EPIC US# 307413
+     * @Method - getSubscriberPermission - Forming permission string for subscription part to check AAF access in CADI Framework
+     * @Params - aafInstance Passing aafInstance as it's used in permission string
+     * @Params - userAction Passing CONST values to set different actions in permission string
+     */
+    String getSubscriberPermission(String aafInstance, String userAction) {
+        try {
+            Properties props = (new DB()).getProperties();
+            String type = props.getProperty(AAF_CADI_SUB_TYPE, AAF_CADI_SUB);
+            String action;
+            switch (userAction) {
+                case SUBSCRIBE_PERMISSION:
+                    action = SUBSCRIBE_PERMISSION;
+                    type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+                    break;
+                case EDIT_PERMISSION:
+                    action = EDIT_PERMISSION;
+                    break;
+                case DELETE_PERMISSION:
+                    action = DELETE_PERMISSION;
+                    break;
+                case RESTORE_PERMISSION:
+                    action = RESTORE_PERMISSION;
+                    break;
+                case SUSPEND_PERMISSION:
+                    action = SUSPEND_PERMISSION;
+                    break;
+                case PUBLISH_PERMISSION:
+                    action = PUBLISH_PERMISSION;
+                    break;
+                case APPROVE_SUB_PERMISSION:
+                    action = APPROVE_SUB_PERMISSION;
+                    type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+                    break;
+                default:
+                    action = "*";
+            }
+            if (aafInstance == null || "".equals(aafInstance)) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getSubscriberPermission: " + e.getMessage(), e);
+        }
+        return null;
+    }
+}