DR AAF CADI integration

Change-Id: I01548882f813e4029dddf7ddee2af12472163761
Issue-ID: DMAAP-1016
Signed-off-by: efiacor <fiachra.corcoran@est.tech>
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/BaseServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/BaseServlet.java
index 2d4f85f..50ec1b4 100755
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/BaseServlet.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/BaseServlet.java
@@ -24,68 +24,42 @@
 
 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 org.apache.commons.lang3.StringUtils;
 import org.apache.log4j.Logger;
+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.Deleteable;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
-import org.onap.dmaap.datarouter.provisioning.beans.Group;
-import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
-import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;
-import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
-import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
-import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
+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.json.JSONException;
 import org.slf4j.MDC;
-import org.slf4j.Marker;
-import org.slf4j.MarkerFactory;
 
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.UUID;
-import java.util.regex.Pattern;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.AddressException;
+import javax.mail.*;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.security.cert.X509Certificate;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+import static com.att.eelf.configuration.Configuration.*;
 
 /**
  * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
@@ -98,6 +72,24 @@
 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";
@@ -110,7 +102,9 @@
 
     //Adding groups functionality, ...1610
     static final String GROUP_BASECONTENT_TYPE = "application/vnd.dmaap-dr.group";
-    static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
+    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";
@@ -173,6 +167,10 @@
      */
     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];
@@ -196,10 +194,12 @@
      * 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
      */
@@ -210,7 +210,8 @@
      */
     private static String activeProvName = "feeds-drtr.web.att.com";
 
-    private static String staticRoutingNodes = STATIC_ROUTING_NODES; //Adding new param for static Routing - Rally:US664862-1610
+    //Adding new param for static Routing - Rally:US664862-1610
+    private static String staticRoutingNodes = STATIC_ROUTING_NODES;
 
     /**
      * This logger is used to log provisioning events
@@ -239,7 +240,10 @@
 
     //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");
+            .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.
@@ -277,7 +281,7 @@
         }
     }
 
-    int getIdFromPath(HttpServletRequest req) {
+    public static int getIdFromPath(HttpServletRequest req) {
         String path = req.getPathInfo();
         if (path == null || path.length() < 2) {
             return -1;
@@ -309,6 +313,36 @@
     }
 
     /**
+     * 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)?
@@ -324,7 +358,6 @@
         if (requireSecure && !request.isSecure()) {
             return "Request must be made over an HTTPS connection.";
         }
-
         // Is remote IP authorized?
         String remote = request.getRemoteAddr();
         try {
@@ -337,12 +370,12 @@
                 return "Unauthorized address: " + remote;
             }
         } catch (UnknownHostException e) {
+            intlogger.error("PROV0051 BaseServlet.isAuthorizedForProvisioning: ", e);
             return "Unauthorized address: " + remote;
         }
-
         // Does remote have a valid certificate?
         if (requireCert) {
-            X509Certificate certs[] = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
+            X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
             if (certs == null || certs.length == 0) {
                 return "Client certificate is missing.";
             }
@@ -353,7 +386,6 @@
                 return "No authorized certificate found.";
             }
         }
-
         // No problems!
         return null;
     }
@@ -365,7 +397,6 @@
      * @return true iff authorized
      */
     boolean isAuthorizedForInternal(HttpServletRequest request) {
-
         try {
             if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
                 return true;
@@ -388,7 +419,7 @@
                 return true;
             }
         } catch (UnknownHostException e) {
-            // ignore
+            intlogger.error("PROV0052 BaseServlet.isAuthorizedForInternal: ", e);
         }
         return false;
     }
@@ -397,7 +428,7 @@
      * 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
+     * @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) {
@@ -416,8 +447,8 @@
             }
             if (mlen > 0) {
                 byte[] masks = {
-                    (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
-                    (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
+                        (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++) {
@@ -432,6 +463,7 @@
                 }
             }
         } catch (UnknownHostException e) {
+            intlogger.error("PROV0053 BaseServlet.addressMatchesNetwork: ", e);
             return false;
         }
         return true;
@@ -441,7 +473,7 @@
      * 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.
      */
-    public static void provisioningDataChanged() {
+    static void provisioningDataChanged() {
         long now = System.currentTimeMillis();
         Poker p = Poker.getPoker();
         p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
@@ -450,7 +482,7 @@
     /**
      * Something in the parameters has changed, reload all parameters from the DB.
      */
-    public static void provisioningParametersChanged() {
+    static void provisioningParametersChanged() {
         Map<String, String> map = Parameters.getParameters();
         requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
         requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
@@ -461,15 +493,16 @@
         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);
-        staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
-            ""); //Adding new param for static Routing - Rally:US664862-1610
         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
+                ""); //Adding new param for static Routing - Rally:US664862-1610
         activeFeeds = Feed.countActiveFeeds();
         activeSubs = Subscription.countActiveSubscriptions();
         try {
@@ -491,6 +524,9 @@
             }
         }
 
+        //[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) {
@@ -498,7 +534,7 @@
                 filterNodes.add(node);
             }
         }
-        nodes = filterNodes.toArray(new String[filterNodes.size()]);
+        nodes = filterNodes.toArray(new String[0]);
 
         nodeAddresses = na;
         NodeClass.setNodes(nodes);        // update NODES table
@@ -535,17 +571,11 @@
     private void loadMailProperties() {
         if (mailprops == null) {
             mailprops = new Properties();
-            InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE);
-            try {
+            try (InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE)) {
                 mailprops.load(inStream);
             } catch (IOException e) {
                 intlogger.fatal("PROV9003 Opening properties: " + e.getMessage());
                 System.exit(1);
-            } finally {
-                try {
-                    inStream.close();
-                } catch (IOException e) {
-                }
             }
         }
     }
@@ -602,18 +632,16 @@
             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");
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
             mp.addBodyPart(htmlPart);
             msg.setContent(mp);
 
             System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
-                .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
 
             Transport.send(msg);
             intlogger.info("HTTPS relaxation mail is sent to - : " + email);
 
-        } catch (AddressException e) {
-            intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
         } catch (MessagingException e) {
             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
         }
@@ -637,6 +665,16 @@
     }
 
     /**
+     * [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
@@ -981,7 +1019,7 @@
         setMDC(req, "X-InvocationID", "InvocationId");
     }
 
-    void setMDC(HttpServletRequest req, String headerName, String keyName) {
+    private void setMDC(HttpServletRequest req, String headerName, String keyName) {
         String mdcId = req.getHeader(headerName);
         if (StringUtils.isBlank(mdcId)) {
             mdcId = UUID.randomUUID().toString();
@@ -1004,4 +1042,95 @@
         }
 
     }
+
+    /*
+     * 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 || aafInstance.equals("")) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getFeedPermission: ", 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 || aafInstance.equals("")) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getSubscriberPermission: ", e);
+        }
+        return null;
+    }
 }
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServlet.java
index 895eba0..9bc9162 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServlet.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServlet.java
@@ -24,13 +24,8 @@
 
 package org.onap.dmaap.datarouter.provisioning;
 
-import java.io.IOException;
-import java.io.InvalidObjectException;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
 import org.json.JSONObject;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
@@ -38,8 +33,11 @@
 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;
 
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.util.List;
 
 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
 
@@ -55,7 +53,7 @@
 
     //Adding EELF Logger Rally:US664892
     private static EELFLogger eelflogger = EELFManager.getInstance()
-        .getLogger(DRFeedsServlet.class);
+            .getLogger(DRFeedsServlet.class);
 
     /**
      * DELETE on the &lt;drFeedsURL&gt; -- not supported.
@@ -109,8 +107,8 @@
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            String path = req
-                    .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            String path = req.getRequestURI();
             if (path != null && !path.equals("/")) {
                 message = "Bad URL.";
                 elr.setMessage(message);
@@ -236,8 +234,8 @@
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            String path = req
-                    .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            String path = req.getRequestURI();
             if (path != null && !path.equals("/")) {
                 message = "Bad URL.";
                 elr.setMessage(message);
@@ -257,16 +255,6 @@
                 sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
             JSONObject jo = getJSONfromInput(req);
             if (jo == null) {
                 message = "Badly formed JSON";
@@ -288,7 +276,7 @@
                 sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
                 return;
             }
-            Feed feed = null;
+            Feed feed;
             try {
                 feed = new Feed(jo);
             } catch (InvalidObjectException e) {
@@ -299,6 +287,60 @@
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
+
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - No legacy user check as all new users will be AAF users
+             */
+            String aafInstance = feed.getAafInstance();
+            if (Boolean.parseBoolean(isCadiEnabled)) {
+                if ((aafInstance == null || aafInstance.equals("") || (aafInstance.equalsIgnoreCase("legacy")) && req.getHeader(EXCLUDE_AAF_HEADER).equalsIgnoreCase("true"))) {
+                    // Check with the Authorizer
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access.";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    if (req.getHeader(EXCLUDE_AAF_HEADER).equalsIgnoreCase("true")) {
+                        message = "DRFeedsServlet.doPost() -Invalid request exclude_AAF should not be true if passing AAF_Instance value= " + aafInstance;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                    String permission = getFeedPermission(aafInstance, BaseServlet.CREATE_PERMISSION);
+                    eventlogger.info("DRFeedsServlet.doPost().. Permission String - " + permission);
+                    if (!req.isUserInRole(permission)) {
+                        message = "AAF disallows access to permission - " + permission;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                }
+            } else {
+                AuthorizationResponse aresp = authz.decide(req);
+                if (!aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            }
+            /*
+             * END - AAF changes
+             */
+
             feed.setPublisher(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header
 
             // Check if this feed already exists
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/FeedServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/FeedServlet.java
index e64f2c6..4ab3ef4 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/FeedServlet.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/FeedServlet.java
@@ -107,17 +107,37 @@
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (! aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove feed
+             */
+            String aafInstance = feed.getAafInstance();
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {
+                AuthorizationResponse aresp = authz.decide(req);
+                if (! aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                String permission = getFeedPermission(aafInstance, BaseServlet.DELETE_PERMISSION);
+                eventlogger.info("FeedServlet.doDelete().. Permission String - " + permission);
+                if (!req.isUserInRole(permission)) {
+                    message = "AAF disallows access to permission - " + permission;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
             }
-
+            /*
+             * END - AAF changes
+             */
             // Delete FEED table entry (set DELETED flag)
             feed.setDeleted(true);
             if (doUpdate(feed)) {
@@ -286,7 +306,7 @@
             }
             if (intlogger.isDebugEnabled())
                 intlogger.debug(jo.toString());
-            Feed feed = null;
+            Feed feed;
             try {
                 feed = new Feed(jo);
             } catch (InvalidObjectException e) {
@@ -317,24 +337,50 @@
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            if (!oldFeed.getVersion().equals(feed.getVersion())) {
-                message = "The version of the feed may not be updated.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
-                return;
+            //  US DSCDR-19 for DCAE if version is not null, version can't be changed
+            if ((oldFeed.getVersion() != null) && (feed.getVersion() != null)) {
+                if (!oldFeed.getVersion().equals(feed.getVersion())) {
+                    message = "The version of the feed may not be updated.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
+                    return;
+                }
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (! aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
+
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow feed edit/update/modify
+             */
+            String aafInstance = feed.getAafInstance();
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {
+                // Check with the Authorizer
+                AuthorizationResponse aresp = authz.decide(req);
+                if (!aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                String permission = getFeedPermission(aafInstance, BaseServlet.EDIT_PERMISSION);
+                eventlogger.info("FeedServlet.doPut().. Permission String - " + permission);
+                if (!req.isUserInRole(permission)) {
+                    message = "AAF disallows access to permission - " + permission;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
             }
+            /*
+             * END - AAF changes
+             */
 
             // Update FEEDS table entries
             if (doUpdate(feed)) {
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java
index 651d731..1bd3cbf 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java
@@ -24,34 +24,28 @@
 
 package org.onap.dmaap.datarouter.provisioning;
 
-import java.security.*;
-import java.util.*;
-
 import org.apache.log4j.Logger;
 import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.NCSARequestLog;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.*;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.handler.DefaultHandler;
 import org.eclipse.jetty.server.handler.HandlerCollection;
 import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.onap.dmaap.datarouter.provisioning.utils.DB;
-import org.onap.dmaap.datarouter.provisioning.utils.LogfileLoader;
-import org.onap.dmaap.datarouter.provisioning.utils.PurgeLogDirTask;
-import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.dmaap.datarouter.provisioning.utils.*;
 
 import javax.servlet.DispatcherType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Security;
+import java.util.EnumSet;
+import java.util.Properties;
+import java.util.Timer;
 
 /**
  * <p>
@@ -87,18 +81,31 @@
     /**
      * The truststore to use if none is specified
      */
-    public static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
-    public static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
-    public static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
-    public static final String KEYSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
-    public static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
-    public static final String TRUSTSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
+    static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
+    static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
+    static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
+    static final String KEYSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
+    static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
+    static final String TRUSTSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
+    public static final Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
 
     /**
      * The one and only {@link Server} instance in this JVM
      */
     private static Server server;
 
+    class Inner {
+        InputStream getCadiProps() {
+            InputStream in = null;
+            try {
+                in = getClass().getClassLoader().getResourceAsStream("drProvCadi.properties");
+            } catch (Exception e) {
+                intlogger.error("Exception in Main.getCadiProps() method ", e);
+            }
+            return in;
+        }
+    }
+
     /**
      * Starts the Data Router Provisioning server.
      *
@@ -106,29 +113,19 @@
      * @throws Exception if Jetty has a problem starting
      */
     public static void main(String[] args) throws Exception {
-        Security.setProperty("networkaddress.cache.ttl", "4");
-        Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
+        // Get prov properties
+        Properties provProperties = (new DB()).getProperties();
 
         // Check DB is accessible and contains the expected tables
         if (!checkDatabase()) {
             System.exit(1);
         }
 
-        logger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
+        intlogger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
 
-        // Get properties
-        Properties p = (new DB()).getProperties();
-        int httpPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
-        int httpsPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
-
-        // HTTP configuration
-        HttpConfiguration httpConfiguration = new HttpConfiguration();
-        httpConfiguration.setSecureScheme("https");
-        httpConfiguration.setSecurePort(httpsPort);
-        httpConfiguration.setOutputBufferSize(32768);
-        httpConfiguration.setRequestHeaderSize(2048);
-        httpConfiguration.setSendServerVersion(true);
-        httpConfiguration.setSendDateHeader(false);
+        Security.setProperty("networkaddress.cache.ttl", "4");
+        int httpPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
+        int httpsPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
 
         // Server's thread pool
         QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
@@ -138,121 +135,155 @@
 
         // The server itself
         server = new Server(queuedThreadPool);
+        server.setStopAtShutdown(true);
+        server.setStopTimeout(5000);
+        server.setDumpAfterStart(false);
+        server.setDumpBeforeStop(false);
 
-        // HTTP connector
-        HandlerCollection hc;
-        try (ServerConnector httpServerConnector = new ServerConnector(server,
-            new HttpConnectionFactory(httpConfiguration))) {
+        // Request log configuration
+        NCSARequestLog ncsaRequestLog = new NCSARequestLog();
+        ncsaRequestLog.setFilename(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
+        ncsaRequestLog.setFilenameDateFormat("yyyyMMdd");
+        ncsaRequestLog.setRetainDays(90);
+        ncsaRequestLog.setAppend(true);
+        ncsaRequestLog.setExtended(false);
+        ncsaRequestLog.setLogCookies(false);
+        ncsaRequestLog.setLogTimeZone("GMT");
+
+        RequestLogHandler requestLogHandler = new RequestLogHandler();
+        requestLogHandler.setRequestLog(ncsaRequestLog);
+        server.setRequestLog(ncsaRequestLog);
+
+        // HTTP configuration
+        HttpConfiguration httpConfiguration = new HttpConfiguration();
+        httpConfiguration.setSecureScheme("https");
+        httpConfiguration.setSecurePort(httpsPort);
+        httpConfiguration.setOutputBufferSize(32768);
+        httpConfiguration.setRequestHeaderSize(8192);
+        httpConfiguration.setResponseHeaderSize(8192);
+        httpConfiguration.setSendServerVersion(true);
+        httpConfiguration.setSendDateHeader(false);
+
+        //HTTP Connector
+        HandlerCollection handlerCollection;
+        try (ServerConnector httpServerConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration))) {
             httpServerConnector.setPort(httpPort);
             httpServerConnector.setAcceptQueueSize(2);
             httpServerConnector.setIdleTimeout(300000);
 
+            // SSL Context
+            SslContextFactory sslContextFactory = new SslContextFactory();
+            sslContextFactory.setKeyStoreType(provProperties.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
+            sslContextFactory.setKeyStorePath(provProperties.getProperty(KEYSTORE_PATH_PROPERTY));
+            sslContextFactory.setKeyStorePassword(provProperties.getProperty(KEYSTORE_PASS_PROPERTY));
+            sslContextFactory.setKeyManagerPassword(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
+
+            String ts = provProperties.getProperty(TRUSTSTORE_PATH_PROPERTY);
+            if (ts != null && ts.length() > 0) {
+                intlogger.info("@@ TS -> " + ts);
+                sslContextFactory.setTrustStorePath(ts);
+                sslContextFactory.setTrustStorePassword(provProperties.getProperty(TRUSTSTORE_PASS_PROPERTY));
+            } else {
+                sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
+                sslContextFactory.setTrustStorePassword("changeit");
+            }
+
+            sslContextFactory.setWantClientAuth(true);
+            sslContextFactory.setExcludeCipherSuites(
+                    "SSL_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+                    "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                    "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
+            );
+            sslContextFactory.addExcludeProtocols("SSLv3");
+            sslContextFactory.setIncludeProtocols(provProperties.getProperty(
+                    "org.onap.dmaap.datarouter.provserver.https.include.protocols", "TLSv1.1|TLSv1.2").trim().split("\\|"));
+
+            intlogger.info("Not supported protocols prov server:-" + String.join(",", sslContextFactory.getExcludeProtocols()));
+            intlogger.info("Supported protocols prov server:-" + String.join(",", sslContextFactory.getIncludeProtocols()));
+            intlogger.info("Not supported ciphers prov server:-" + String.join(",", sslContextFactory.getExcludeCipherSuites()));
+            intlogger.info("Supported ciphers prov server:-" + String.join(",", sslContextFactory.getIncludeCipherSuites()));
+
             // HTTPS configuration
             HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration);
             httpsConfiguration.setRequestHeaderSize(8192);
 
             // HTTPS connector
-            SslContextFactory sslContextFactory = new SslContextFactory();
-            sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
-            sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASS_PROPERTY));
-            sslContextFactory
-                    .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
-            // SSL stuff
-            /* Skip SSLv3 Fixes */
-            sslContextFactory.addExcludeProtocols("SSLv3");
-            logger.info("Excluded protocols prov-" + Arrays.toString(sslContextFactory.getExcludeProtocols()));
-            /* End of SSLv3 Fixes */
-
             try (ServerConnector httpsServerConnector = new ServerConnector(server,
                     new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                     new HttpConnectionFactory(httpsConfiguration))) {
+
                 httpsServerConnector.setPort(httpsPort);
                 httpsServerConnector.setIdleTimeout(30000);
                 httpsServerConnector.setAcceptQueueSize(2);
 
-                sslContextFactory.setKeyStoreType(p.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
-                sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
-                sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASS_PROPERTY));
-                sslContextFactory
-                        .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
-
-                String ts = p.getProperty(TRUSTSTORE_PATH_PROPERTY);
-                if (ts != null && ts.length() > 0) {
-                    logger.info("@@ TS -> " + ts);
-                    sslContextFactory.setTrustStorePath(ts);
-                    sslContextFactory.setTrustStorePassword(p.getProperty(TRUSTSTORE_PASS_PROPERTY));
-                } else {
-                    sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
-                    sslContextFactory.setTrustStorePassword("changeit");
-                }
-                sslContextFactory.setWantClientAuth(true);
-
                 // Servlet and Filter configuration
-                ServletContextHandler ctxt = new ServletContextHandler(0);
-                ctxt.setContextPath("/");
-                ctxt.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
-                ctxt.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
-                ctxt.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
-                ctxt.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
-                ctxt.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
-                ctxt.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
-                ctxt.addServlet(new ServletHolder(new GroupServlet()),
-                        "/group/*"); //Provision groups - Rally US708115 -1610
-                ctxt.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
-                ctxt.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
-                ctxt.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
-                ctxt.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
-                ctxt.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
+                ServletContextHandler servletContextHandler = new ServletContextHandler(0);
+                servletContextHandler.setContextPath("/");
+                servletContextHandler.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
+                servletContextHandler.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
+                servletContextHandler.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
+                servletContextHandler.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
+                servletContextHandler.addServlet(new ServletHolder(new GroupServlet()), "/group/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
+                servletContextHandler.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
+                servletContextHandler.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
+                servletContextHandler.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
+                servletContextHandler.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
 
-                ContextHandlerCollection contexts = new ContextHandlerCollection();
-                contexts.addHandler(ctxt);
+                //CADI Filter activation check
+                if (Boolean.parseBoolean(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false"))) {
+                    //Get cadi properties
+                    Properties cadiProperties = null;
+                    try {
+                        intlogger.info("PROV0001 Prov - Loading CADI properties");
+                        cadiProperties = new Properties();
+                        Inner obj = new Main().new Inner();
+                        InputStream in = obj.getCadiProps();
+                        cadiProperties.load(in);
+                    } catch (IOException e1) {
+                        intlogger.error("PROV0001 Exception loading CADI properties", e1);
+                    }
+                    cadiProperties.setProperty("aaf_locate_url", provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.aaf.url", "https://aaf-onap-test.osaaf.org:8095"));
+                    intlogger.info("PROV0001  aaf_url set to - " + cadiProperties.getProperty("aaf_url"));
 
-                // Request log configuration
-                NCSARequestLog nrl = new NCSARequestLog();
-                nrl.setFilename(
-                        p.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
-                nrl.setFilenameDateFormat("yyyyMMdd");
-                nrl.setRetainDays(90);
-                nrl.setAppend(true);
-                nrl.setExtended(false);
-                nrl.setLogCookies(false);
-                nrl.setLogTimeZone("GMT");
+                    PropAccess access = new PropAccess(cadiProperties);
+                    servletContextHandler.addFilter(new FilterHolder(new DRProvCadiFilter(true, access)), "/*", EnumSet.of(DispatcherType.REQUEST));
+                }
 
-                RequestLogHandler reqlog = new RequestLogHandler();
-                reqlog.setRequestLog(nrl);
+                ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
+                contextHandlerCollection.addHandler(servletContextHandler);
 
                 // Server's Handler collection
-                hc = new HandlerCollection();
-                hc.setHandlers(new Handler[]{contexts, new DefaultHandler()});
-                hc.addHandler(reqlog);
-
-                // Daemon to clean up the log directory on a daily basis
-                Timer rolex = new Timer();
-                rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
-
-                // Start LogfileLoader
-                LogfileLoader.getLoader();
-
-                try (ServerConnector serverConnector = new ServerConnector(server,
-                        new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
-                        new HttpConnectionFactory(httpsConfiguration))) {
-                    serverConnector.setPort(httpsPort);
-                    serverConnector.setIdleTimeout(500000);
-                }
+                handlerCollection = new HandlerCollection();
+                handlerCollection.setHandlers(new Handler[]{contextHandlerCollection, new DefaultHandler()});
+                handlerCollection.addHandler(requestLogHandler);
 
                 server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector});
             }
         }
-        server.setHandler(hc);
-        server.setStopAtShutdown(true);
-        server.setStopTimeout(5000);
+        server.setHandler(handlerCollection);
 
-        server.setDumpAfterStart(false);
-        server.setDumpBeforeStop(false);
+        // Daemon to clean up the log directory on a daily basis
+        Timer rolex = new Timer();
+        rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
 
-        server.start();
+        // Start LogfileLoader
+        LogfileLoader.getLoader();
+
+        try {
+            server.start();
+            intlogger.info("Prov Server started-" + server.getState());
+        } catch (Exception e) {
+            intlogger.info("Jetty failed to start. Reporting will we unavailable", e);
+        }
         server.join();
-        logger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
+        intlogger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
     }
 
     private static boolean checkDatabase() {
@@ -270,7 +301,7 @@
                 Thread.sleep(5000L);
                 System.exit(0);
             } catch (Exception e) {
-                // ignore
+                intlogger.error("Exception in Main.shutdown() method " + e);
             }
         });
     }
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscribeServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscribeServlet.java
index 2127f00..35ce062 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscribeServlet.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscribeServlet.java
@@ -128,17 +128,6 @@
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
-
             // Display a list of URLs
             Collection<String> list = Subscription.getSubscriptionUrlList(feedid);
             String t = JSONUtilities.createJSONArray(list);
@@ -228,17 +217,6 @@
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
-
             // check content type is SUB_CONTENT_TYPE, version 1.0
             ContentHeader ch = getContentHeader(req);
             String ver = ch.getAttribute("version");
@@ -272,7 +250,7 @@
                 sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
                 return;
             }
-            Subscription sub = null;
+            Subscription sub;
             try {
                 sub = new Subscription(jo);
             } catch (InvalidObjectException e) {
@@ -286,13 +264,70 @@
             }
             sub.setFeedid(feedid);
             sub.setSubscriber(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow to create/add subscription
+             */
+            String feedAafInstance = feed.getAafInstance();
+            String subAafInstance = sub.getAafInstance();
+            boolean subAafLegacyEmptyOrNull = (subAafInstance == null || subAafInstance.equals("") || subAafInstance.equalsIgnoreCase("legacy"));
 
+            // This extra check added to verify AAF feed with AAF subscriber having empty aaf instance check
+            if (feedAafInstance == null || feedAafInstance.equals("") || feedAafInstance.equalsIgnoreCase("legacy")) {
+                if (subAafLegacyEmptyOrNull) {
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    //If Legacy Feed and AAF instance provided in Subscriber JSON
+                    message = "AAF Subscriber can not be added to legacy Feed- " + feedid;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                //New AAF Requirement to add legacy subscriber to AAF Feed
+                if (subAafLegacyEmptyOrNull) {
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access.";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    //New AAF Requirement to add subscriber by publisher on publisher approval only
+                    String permission = getSubscriberPermission(subAafInstance, BaseServlet.APPROVE_SUB_PERMISSION);
+                    eventlogger.info("SubscribeServlet.doPost().. Permission String - " + permission);
+                    if (!req.isUserInRole(permission)) {
+                        message = "AAF disallows access to permission - " + permission;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                }
+            }
+            /*
+             * END - AAF changes
+             */
             // Check if this subscription already exists; not an error (yet), just warn
             Subscription sub2 = Subscription.getSubscriptionMatching(sub);
             if (sub2 != null) {
                 intlogger.warn(
-                    "PROV0011 Creating a duplicate subscription: new subid=" + sub.getSubid() + ", old subid=" + sub2
-                        .getSubid());
+                    "PROV0011 Creating a duplicate subscription: new subid=" + sub.getSubid() + ", old subid=" + sub2.getSubid());
             }
 
             // Create SUBSCRIPTIONS table entries
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServlet.java
index ec4d33a..d7c4657 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServlet.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServlet.java
@@ -58,7 +58,7 @@
 @SuppressWarnings("serial")

 public class SubscriptionServlet extends ProxyServlet {

 

-    public static final String SUBCNTRL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-control";

+    private static final String SUBCNTRL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-control";

     //Adding EELF Logger Rally:US664892

     private static EELFLogger eelflogger = EELFManager.getInstance()

         .getLogger(SubscriptionServlet.class);

@@ -113,17 +113,37 @@
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);

                 return;

             }

-            // Check with the Authorizer

-            AuthorizationResponse aresp = authz.decide(req);

-            if (!aresp.isAuthorized()) {

-                message = "Policy Engine disallows access.";

-                elr.setMessage(message);

-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);

-                eventlogger.info(elr);

-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

-                return;

+            /*

+             * START - AAF changes

+             * TDP EPIC US# 307413

+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove subscription

+             */

+            String aafInstance = sub.getAafInstance();

+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {

+                AuthorizationResponse aresp = authz.decide(req);

+                if (!aresp.isAuthorized()) {

+                    message = "Policy Engine disallows access.";

+                    elr.setMessage(message);

+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);

+                    eventlogger.info(elr);

+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

+                    return;

+                }

+            } else {

+                String permission = getSubscriberPermission(aafInstance, BaseServlet.DELETE_PERMISSION);

+                eventlogger.info("SubscriptionServlet.doDelete().. Permission String - " + permission);

+                if (!req.isUserInRole(permission)) {

+                    message = "AAF disallows access to permission - " + permission;

+                    elr.setMessage(message);

+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);

+                    eventlogger.info(elr);

+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

+                    return;

+                }

             }

-

+            /*

+             * END - AAF changes

+             */

             // Delete Subscription

             if (doDelete(sub)) {

                 activeSubs--;

@@ -270,16 +290,6 @@
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);

                 return;

             }

-            // Check with the Authorizer

-            AuthorizationResponse aresp = authz.decide(req);

-            if (!aresp.isAuthorized()) {

-                message = "Policy Engine disallows access.";

-                elr.setMessage(message);

-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);

-                eventlogger.info(elr);

-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

-                return;

-            }

             // check content type is SUB_CONTENT_TYPE, version 1.0

             ContentHeader ch = getContentHeader(req);

             String ver = ch.getAttribute("version");

@@ -314,6 +324,38 @@
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);

                 return;

             }

+

+            /*

+             * START - AAF changes

+             * TDP EPIC US# 307413

+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove subscription

+             */

+            String aafInstance = sub.getAafInstance();

+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {

+                AuthorizationResponse aresp = authz.decide(req);

+                if (!aresp.isAuthorized()) {

+                    message = "Policy Engine disallows access.";

+                    elr.setMessage(message);

+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);

+                    eventlogger.info(elr);

+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

+                    return;

+                }

+            } else {

+                String permission = getSubscriberPermission(aafInstance, BaseServlet.EDIT_PERMISSION);

+                eventlogger.info("SubscriptionServlet.doDelete().. Permission String - " + permission);

+                if (!req.isUserInRole(permission)) {

+                    message = "AAF disallows access to permission - " + permission;

+                    elr.setMessage(message);

+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);

+                    eventlogger.info(elr);

+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);

+                    return;

+                }

+            }

+            /*

+             * END - AAF changes

+             */

             sub.setSubid(oldsub.getSubid());

             sub.setFeedid(oldsub.getFeedid());

             sub.setSubscriber(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header

@@ -373,13 +415,6 @@
      */

     @Override

     public void doPost(HttpServletRequest req, HttpServletResponse resp) {

-// OLD pre-3.0 code

-//        String message = "POST not allowed for the subscriptionURL.";

-//        EventLogRecord elr = new EventLogRecord(req);

-//        elr.setMessage(message);

-//        elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);

-//        eventlogger.info(elr);

-//        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);

 

         setIpFqdnRequestIDandInvocationIDForEelf("doPost", req);

         eelflogger.info(EelfMsgs.ENTRY);

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Feed.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Feed.java
index a2076b0..502dbbd 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Feed.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Feed.java
@@ -24,17 +24,21 @@
 

 package org.onap.dmaap.datarouter.provisioning.beans;

 

+import org.apache.log4j.Level;

 import org.apache.log4j.Logger;

 import org.json.JSONArray;

+import org.json.JSONException;

 import org.json.JSONObject;

 import org.onap.dmaap.datarouter.provisioning.utils.DB;

 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;

+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;

 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;

 

 import java.io.InvalidObjectException;

+import java.security.GeneralSecurityException;

 import java.sql.*;

-import java.util.*;

 import java.util.Date;

+import java.util.*;

 

 /**

  * The representation of a Feed.  Feeds can be retrieved from the DB, or stored/updated in the DB.

@@ -59,6 +63,7 @@
     private boolean suspended;

     private Date last_mod;

     private Date created_date;

+    private String aaf_instance;

 

     /**

      * Check if a feed ID is valid.

@@ -82,7 +87,7 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0024 Feed.isFeedValid: ", e);

         }

         return count != 0;

     }

@@ -132,8 +137,8 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.info("countActiveFeeds: " + e.getMessage());

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.info("PROV0025 Feed.countActiveFeeds: " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0025 Feed.countActiveFeeds: ", e);

         }

         return count;

     }

@@ -153,8 +158,8 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.info("getMaxFeedID: " + e.getMessage());

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.info("PROV0026 Feed.getMaxFeedID: "+e.getMessage());

+            intlogger.log(Level.WARN, "PROV0026 Feed.getMaxFeedID: ", e);

         }

         return max;

     }

@@ -200,7 +205,7 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0027 Feed.getAllFeeds: ", e);

         }

         return map.values();

     }

@@ -234,7 +239,7 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0028 Feed.getFilteredFeedUrlList: ", e);

         }

         return list;

     }

@@ -271,7 +276,7 @@
             }

             db.release(conn);

         } catch (SQLException e) {

-            intlogger.error("SQLException " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0029 Feed.getFeedBySQL: ", e);

         }

         return feed;

     }

@@ -294,6 +299,7 @@
         this.suspended = false;

         this.last_mod = new Date();

         this.created_date = new Date();

+        this.aaf_instance = "";

     }

 

     public Feed(ResultSet rs) throws SQLException {

@@ -315,6 +321,7 @@
         this.suspended = rs.getBoolean("SUSPENDED");

         this.last_mod = rs.getDate("LAST_MOD");

         this.created_date = rs.getTimestamp("CREATED_DATE");

+        this.aaf_instance = rs.getString("AAF_INSTANCE");

     }

 

     public Feed(JSONObject jo) throws InvalidObjectException {

@@ -322,41 +329,49 @@
         try {

             // The JSONObject is assumed to contain a vnd.dmaap-dr.feed representation

             this.feedid = jo.optInt("feedid", -1);

-            this.groupid = jo.optInt("groupid"); //New field is added - Groups feature Rally:US708115 - 1610

+            this.groupid = jo.optInt("groupid");

             this.name = jo.getString("name");

+            this.aaf_instance = jo.optString("aaf_instance", "legacy");

+            if(!(aaf_instance.equalsIgnoreCase("legacy"))){

+                if (aaf_instance.length() > 255){

+                    throw new InvalidObjectException("aaf_instance field is too long");

+                }

+            }

             if (name.length() > 255)

                 throw new InvalidObjectException("name field is too long");

-            this.version = jo.getString("version");

-            if (version.length() > 20)

+            try {

+                this.version = jo.getString("version");

+            } catch (JSONException e) {

+                this.version = null;

+            }

+            if(version != null && version.length() > 20)

                 throw new InvalidObjectException("version field is too long");

             this.description = jo.optString("description");

-            this.business_description = jo.optString("business_description"); // New field is added - Groups feature Rally:US708102 - 1610

+            this.business_description = jo.optString("business_description");

             if (description.length() > 1000)

                 throw new InvalidObjectException("technical description field is too long");

-

-            if (business_description.length() > 1000) // New field is added - Groups feature Rally:US708102 - 1610

+            if (business_description.length() > 1000)

                 throw new InvalidObjectException("business description field is too long");

-

             this.authorization = new FeedAuthorization();

             JSONObject jauth = jo.getJSONObject("authorization");

             this.authorization.setClassification(jauth.getString("classification"));

             if (this.authorization.getClassification().length() > 32)

                 throw new InvalidObjectException("classification field is too long");

-            JSONArray ja = jauth.getJSONArray("endpoint_ids");

-            for (int i = 0; i < ja.length(); i++) {

-                JSONObject id = ja.getJSONObject(i);

+            JSONArray endPointIds = jauth.getJSONArray("endpoint_ids");

+            for (int i = 0; i < endPointIds.length(); i++) {

+                JSONObject id = endPointIds.getJSONObject(i);

                 FeedEndpointID fid = new FeedEndpointID(id.getString("id"), id.getString("password"));

-                if (fid.getId().length() > 20)

+                if (fid.getId().length() > 60)

                     throw new InvalidObjectException("id field is too long (" + fid.getId() + ")");

                 if (fid.getPassword().length() > 32)

-                    throw new InvalidObjectException("password field is too long (" + fid.getPassword() + ")");

+                    throw new InvalidObjectException("password field is too long ("+ fid.getPassword()+")");  //Fortify scan fixes - Privacy Violation

                 this.authorization.getEndpoint_ids().add(fid);

             }

             if (this.authorization.getEndpoint_ids().size() < 1)

                 throw new InvalidObjectException("need to specify at least one endpoint_id");

-            ja = jauth.getJSONArray("endpoint_addrs");

-            for (int i = 0; i < ja.length(); i++) {

-                String addr = ja.getString(i);

+            endPointIds = jauth.getJSONArray("endpoint_addrs");

+            for (int i = 0; i < endPointIds.length(); i++) {

+                String addr = endPointIds.getString(i);

                 if (!JSONUtilities.validIPAddrOrSubnet(addr))

                     throw new InvalidObjectException("bad IP addr or subnet mask: " + addr);

                 this.authorization.getEndpoint_addrs().add(addr);

@@ -368,8 +383,10 @@
             JSONObject jol = jo.optJSONObject("links");

             this.links = (jol == null) ? (new FeedLinks()) : (new FeedLinks(jol));

         } catch (InvalidObjectException e) {

+            intlogger.log(Level.WARN, "PROV0030 Feed.Feed: ", e);

             throw e;

         } catch (Exception e) {

+            intlogger.error("PROV0031 Feed.Feed: invalid JSON: "+e);

             throw new InvalidObjectException("invalid JSON: " + e.getMessage());

         }

     }

@@ -389,6 +406,14 @@
         fl.setLog(URLUtilities.generateFeedLogURL(feedid));

     }

 

+    public String getAafInstance() {

+        return aaf_instance;

+    }

+

+    public void setAaf_instance(String aaf_instance) {

+        this.aaf_instance = aaf_instance;

+    }

+

     //new getter setters for groups- Rally:US708115 - 1610

     public int getGroupid() {

         return groupid;

@@ -499,6 +524,7 @@
         jo.put("suspend", suspended);

         jo.put("last_mod", last_mod.getTime());

         jo.put("created_date", created_date.getTime());

+        jo.put("aaf_instance", aaf_instance);

         return jo;

     }

 

@@ -581,7 +607,7 @@
             }

 

             // Finally, create the FEEDS row

-            sql = "insert into FEEDS (FEEDID, NAME, VERSION, DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, DELETED, SUSPENDED,BUSINESS_DESCRIPTION, GROUPID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?)";

+            sql = "insert into FEEDS (FEEDID, NAME, VERSION, DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, DELETED, SUSPENDED,BUSINESS_DESCRIPTION, GROUPID, AAF_INSTANCE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

             try(PreparedStatement ps2 = c.prepareStatement(sql)) {

                 ps2.setInt(1, feedid);

                 ps2.setString(2, getName());

@@ -595,8 +621,9 @@
                 ps2.setString(10, getLinks().getLog());

                 ps2.setBoolean(11, isDeleted());

                 ps2.setBoolean(12, isSuspended());

-                ps2.setString(13, getBusiness_description()); // New field is added - Groups feature Rally:US708102 - 1610

-                ps2.setInt(14, groupid); //New field is added - Groups feature Rally:US708115 - 1610

+                ps2.setString(13, getBusiness_description());

+                ps2.setInt(14, groupid);

+                ps2.setString(15, getAafInstance());

                 ps2.executeUpdate();

             }

         } catch (SQLException e) {

@@ -675,8 +702,8 @@
             ps.setString(2, getAuthorization().getClassification());

             ps.setInt(3, deleted ? 1 : 0);

             ps.setInt(4, suspended ? 1 : 0);

-            ps.setString(5, getBusiness_description()); // New field is added - Groups feature Rally:US708102 - 1610

-            ps.setInt(6, groupid); //New field is added - Groups feature Rally:US708115 - 1610

+            ps.setString(5, getBusiness_description());

+            ps.setInt(6, groupid);

             ps.setInt(7, feedid);

             ps.executeUpdate();

             ps.close();

@@ -760,6 +787,8 @@
             return false;

         if (suspended != of.suspended)

             return false;

+        if (!aaf_instance.equals(of.aaf_instance))

+            return false;

         return true;

     }

 

@@ -770,6 +799,6 @@
 

     @Override

     public int hashCode() {

-        return Objects.hash(feedid, groupid, name, version, description, business_description, authorization, publisher, links, deleted, suspended, last_mod, created_date);

+        return super.hashCode();

     }

-}

+}
\ No newline at end of file
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Subscription.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Subscription.java
index 0c0c546..bdc062f 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Subscription.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Subscription.java
@@ -23,23 +23,19 @@
 

 package org.onap.dmaap.datarouter.provisioning.beans;

 

-import java.io.InvalidObjectException;

-import java.sql.Connection;

-import java.sql.PreparedStatement;

-import java.sql.ResultSet;

-import java.sql.SQLException;

-import java.sql.Statement;

-import java.util.ArrayList;

-import java.util.Collection;

-import java.util.Date;

-import java.util.List;

-import java.util.Objects;

-import java.util.Properties;

+import org.apache.log4j.Level;

 import org.apache.log4j.Logger;

 import org.json.JSONObject;

 import org.onap.dmaap.datarouter.provisioning.utils.DB;

+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;

 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;

 

+import java.io.InvalidObjectException;

+import java.security.GeneralSecurityException;

+import java.sql.*;

+import java.util.Date;

+import java.util.*;

+

 /**

  * The representation of a Subscription.  Subscriptions can be retrieved from the DB, or stored/updated in the DB.

  *

@@ -62,6 +58,7 @@
     private int feedid;

     private int groupid; //New field is added - Groups feature Rally:US708115 - 1610

     private SubDelivery delivery;

+    private boolean followRedirect;

     private boolean metadataOnly;

     private String subscriber;

     private SubLinks links;

@@ -69,18 +66,20 @@
     private Date lastMod;

     private Date createdDate;

     private boolean privilegedSubscriber;

+    private String aafInstance;

     private boolean decompress;

 

     public static Subscription getSubscriptionMatching(Subscription sub) {

         SubDelivery deli = sub.getDelivery();

         String sql = String.format(

-                "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d",

+                "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d and FOLLOW_REDIRECTS = %d",

                 sub.getFeedid(),

                 deli.getUrl(),

                 deli.getUser(),

                 deli.getPassword(),

                 deli.isUse100() ? 1 : 0,

-                sub.isMetadataOnly() ? 1 : 0

+                sub.isMetadataOnly() ? 1 : 0,

+                sub.isFollowRedirect() ? 1 :0

         );

         List<Subscription> list = getSubscriptionsForSQL(sql);

         return !list.isEmpty() ? list.get(0) : null;

@@ -145,7 +144,6 @@
             DB db = new DB();

             @SuppressWarnings("resource")

             Connection conn = db.getConnection();

-

             try (PreparedStatement stmt = conn.prepareStatement(sql)) {

                 stmt.setString(1, String.valueOf(feedid));

                 try (ResultSet rs = stmt.executeQuery()) {

@@ -197,12 +195,14 @@
         this.groupid = -1; //New field is added - Groups feature Rally:US708115 - 1610

         this.delivery = new SubDelivery(url, user, password, false);

         this.metadataOnly = false;

+        this.followRedirect = false;

         this.subscriber = "";

         this.links = new SubLinks();

         this.suspended = false;

         this.lastMod = new Date();

         this.createdDate = new Date();

         this.privilegedSubscriber = false;

+        this.aafInstance = "";

         this.decompress = false;

     }

 

@@ -212,13 +212,14 @@
         this.groupid = rs.getInt("GROUPID"); //New field is added - Groups feature Rally:US708115 - 1610

         this.delivery = new SubDelivery(rs);

         this.metadataOnly = rs.getBoolean("METADATA_ONLY");

+        this.followRedirect = rs.getBoolean("FOLLOW_REDIRECTS");

         this.subscriber = rs.getString("SUBSCRIBER");

-        this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid),

-                rs.getString("LOG_LINK"));

+        this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid), rs.getString("LOG_LINK"));

         this.suspended = rs.getBoolean("SUSPENDED");

         this.lastMod = rs.getDate("LAST_MOD");

         this.createdDate = rs.getDate("CREATED_DATE");

         this.privilegedSubscriber = rs.getBoolean("PRIVILEGED_SUBSCRIBER");

+        this.aafInstance = rs.getString("AAF_INSTANCE");

         this.decompress  = rs.getBoolean("DECOMPRESS");

     }

 

@@ -229,7 +230,11 @@
             this.subid = jo.optInt(SUBID_KEY, -1);

             this.feedid = jo.optInt(FEEDID_KEY, -1);

             this.groupid = jo.optInt(GROUPID_KEY, -1); //New field is added - Groups feature Rally:US708115 - 1610

-

+            this.aafInstance = jo.optString("aaf_instance", "legacy");

+            if(!(aafInstance.equalsIgnoreCase("legacy"))){

+                if (aafInstance.length() > 255)

+                    throw new InvalidObjectException("aaf_instance field is too long");

+            }

             JSONObject jdeli = jo.getJSONObject("delivery");

             String url = jdeli.getString("url");

             String user = jdeli.getString("user");

@@ -245,15 +250,15 @@
             if (url.length() > 256) {

                 throw new InvalidObjectException("delivery url field is too long");

             }

-            if (user.length() > 20) {

+            if (user.length() > 60) {

                 throw new InvalidObjectException("delivery user field is too long");

             }

             if (password.length() > 32) {

                 throw new InvalidObjectException("delivery password field is too long");

             }

             this.delivery = new SubDelivery(url, user, password, use100);

-

             this.metadataOnly = jo.getBoolean("metadataOnly");

+            this.followRedirect = jo.optBoolean("follow_redirect", false);

             this.suspended = jo.optBoolean("suspend", false);

             this.privilegedSubscriber = jo.optBoolean("privilegedSubscriber", false);

             this.decompress = jo.optBoolean("decompress", false);

@@ -296,6 +301,13 @@
         SubLinks sl = getLinks();

         sl.setFeed(URLUtilities.generateFeedURL(feedid));

     }

+    public String getAafInstance() {

+        return aafInstance;

+    }

+

+    public void setAafInstance(String aafInstance) {

+        this.aafInstance = aafInstance;

+    }

 

     //New getter setters for Groups feature Rally:US708115 - 1610

     public int getGroupid() {

@@ -322,7 +334,14 @@
         this.metadataOnly = metadataOnly;

     }

 

-    public boolean isSuspended() {

+    private boolean isFollowRedirect() {

+        return followRedirect;

+    }

+    public void setFollowRedirect(boolean followRedirect) {

+        this.followRedirect = followRedirect;

+    }

+

+    boolean isSuspended() {

         return suspended;

     }

 

@@ -355,7 +374,7 @@
         return links;

     }

 

-    public void setLinks(SubLinks links) {

+    void setLinks(SubLinks links) {

         this.links = links;

     }

 

@@ -375,12 +394,14 @@
         jo.put(GROUPID_KEY, groupid); //New field is added - Groups feature Rally:US708115 - 1610

         jo.put("delivery", delivery.asJSONObject());

         jo.put("metadataOnly", metadataOnly);

+        jo.put("follow_redirect", followRedirect);

         jo.put("subscriber", subscriber);

         jo.put("links", links.asJSONObject());

         jo.put("suspend", suspended);

         jo.put(LAST_MOD_KEY, lastMod.getTime());

         jo.put(CREATED_DATE, createdDate.getTime());

         jo.put("privilegedSubscriber", privilegedSubscriber);

+        jo.put("aaf_instance", aafInstance);

         jo.put("decompress", decompress);

         return jo;

     }

@@ -419,7 +440,7 @@
             }

 

             // Create the SUBSCRIPTIONS row

-            String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, DECOMPRESS) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

+            String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, FOLLOW_REDIRECTS, DECOMPRESS, AAF_INSTANCE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

             ps = c.prepareStatement(sql, new String[]{SUBID_COL});

             ps.setInt(1, subid);

             ps.setInt(2, feedid);

@@ -432,7 +453,9 @@
             ps.setBoolean(9, isSuspended());

             ps.setInt(10, groupid); //New field is added - Groups feature Rally:US708115 - 1610

             ps.setBoolean(11, isPrivilegedSubscriber());

-            ps.setBoolean(12, isDecompress());

+            ps.setInt(12, isFollowRedirect() ? 1 : 0);

+            ps.setBoolean(13, isDecompress());

+            ps.setString(14, getAafInstance());

             ps.execute();

             ps.close();

             // Update the row to set the URLs

@@ -446,6 +469,7 @@
         } catch (SQLException e) {

             rv = false;

             intlogger.warn("PROV0005 doInsert: " + e.getMessage());

+            intlogger.log(Level.WARN, "PROV0005 Subscription.doInsert(1): ", e);

         } finally {

             try {

                 if (ps != null) {

@@ -463,7 +487,7 @@
         boolean rv = true;

         PreparedStatement ps = null;

         try {

-            String sql = "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ?, DECOMPRESS = ? where SUBID = ?";

+            String sql = "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ?, FOLLOW_REDIRECTS = ?, DECOMPRESS = ? where SUBID = ?";

             ps = c.prepareStatement(sql);

             ps.setString(1, delivery.getUrl());

             ps.setString(2, delivery.getUser());

@@ -473,8 +497,9 @@
             ps.setInt(6, suspended ? 1 : 0);

             ps.setInt(7, groupid); //New field is added - Groups feature Rally:US708115 - 1610

             ps.setInt(8, privilegedSubscriber ? 1 : 0);

-            ps.setInt(9, decompress ? 1 : 0);

-            ps.setInt(10, subid);

+            ps.setInt(9, isFollowRedirect() ? 1 : 0);

+            ps.setInt(10, isDecompress() ? 1 : 0);

+            ps.setInt(11, subid);

             ps.executeUpdate();

         } catch (SQLException e) {

             rv = false;

@@ -576,19 +601,27 @@
         if (metadataOnly != os.metadataOnly) {

             return false;

         }

+        if (followRedirect != os.followRedirect) {

+            return false;

+        }

         if (!subscriber.equals(os.subscriber)) {

             return false;

         }

         if (!links.equals(os.links)) {

             return false;

         }

-        return suspended == os.suspended;

+        if (suspended != os.suspended) {

+            return false;

+        }

+        if (!aafInstance.equals(os.aafInstance)) {

+            return false;

+        }

+        return true;

     }

 

     @Override

     public int hashCode() {

-        return Objects.hash(subid, feedid, groupid, delivery, metadataOnly, subscriber, links, suspended, lastMod,

-                createdDate);

+        return super.hashCode();

     }

 

     @Override

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DB.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DB.java
index 3e2436f..8ca7118 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DB.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DB.java
@@ -185,8 +185,8 @@
             connection = getConnection();

             Set<String> actualTables = getTableSet(connection);

             boolean initialize = false;

-            for (String table : expectedTables) {

-                initialize |= !actualTables.contains(table.toLowerCase());

+            for (String tableName : expectedTables) {

+                initialize |= !actualTables.contains(tableName);

             }

             if (initialize) {

                 intlogger.info("PROV9001: First time startup; The database is being initialized.");

@@ -211,13 +211,13 @@
      * @return the set of table names

      */

     private Set<String> getTableSet(Connection connection) {

-        Set<String> tables = new HashSet<String>();

+        Set<String> tables = new HashSet<>();

         try {

             DatabaseMetaData md = connection.getMetaData();

             ResultSet rs = md.getTables(null, null, "%", null);

             if (rs != null) {

                 while (rs.next()) {

-                    tables.add(rs.getString("TABLE_NAME"));

+                    tables.add(rs.getString("TABLE_NAME").toUpperCase());

                 }

                 rs.close();

             }

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java
new file mode 100644
index 0000000..fb8b072
--- /dev/null
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java
@@ -0,0 +1,259 @@
+/**
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ * <p>
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.datarouter.provisioning.utils;
+
+import org.apache.log4j.Logger;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.filter.CadiFilter;
+import org.onap.dmaap.datarouter.provisioning.BaseServlet;
+import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
+import org.onap.dmaap.datarouter.provisioning.beans.Feed;
+import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+public class DRProvCadiFilter extends CadiFilter {
+    private static Logger eventlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.events");
+    private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
+    private String aafInstance = "";
+
+    public DRProvCadiFilter(boolean init, PropAccess access) throws ServletException {
+        super(init, access);
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletRequest httpRequest = null;
+        HttpServletResponse httpResponse = null;
+        //cadi code
+        try {
+            httpRequest = (HttpServletRequest) request;
+            httpResponse = (HttpServletResponse) response;
+        } catch (ClassCastException e) {
+            try {
+                throw new ServletException("Only serving HTTP today", e);
+            } catch (ServletException e1) {
+                intlogger.error("PROV7001 DRProvCadiFilter.doFilter: ", e1);
+            }
+        }
+        EventLogRecord elr = new EventLogRecord(httpRequest);
+        String excludeAAF = httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);//send this param value as true, if want to add legacy feed/subscriber in AAF env
+
+        String pathUrl = httpRequest.getServletPath();
+        if (!(pathUrl.contains("internal") ||
+                pathUrl.contains("sublog") ||
+                pathUrl.contains("feedlog") ||
+                pathUrl.contains("statistics") ||
+                pathUrl.contains("publish") ||
+                pathUrl.contains("group"))) {
+
+            String method = httpRequest.getMethod().toUpperCase();
+            if (!(method.equals("POST"))) { // if request method is PUT method (publish or Feed update) Needs to check for DELETE
+                if (method.equals("PUT") || method.equals("DELETE")) {
+                    if ((pathUrl.contains("subs"))) {//edit subscriber
+                        int subId = BaseServlet.getIdFromPath(httpRequest);
+                        if (subId <= 0) {
+                            String message = String.format("Invalid request URI - %s", httpRequest.getPathInfo());
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                            return;
+                        }
+                        if (isAAFSubscriber(subId)) {//edit AAF Subscriber
+                            String message = String.format("DRProvCadiFilter - Edit AAF Subscriber : %d : AAF Instance - %s", subId, aafInstance);
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            //request.setAttribute("aafInstance", aafInstance);// no need to set it in request since it is taken care in respective servlets
+                            super.doFilter(request, response, chain);
+
+                        } else {//Edit or publish legacy Subscriber
+                            String message = "DRProvCadiFilter - Edit/Publish Legacy Subscriber :" + subId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        }
+
+                    } else {//edit or publish Feed
+                        int feedId = BaseServlet.getIdFromPath(httpRequest);
+                        if (feedId <= 0) {
+                            String message = "Invalid request URI - " + httpRequest.getPathInfo();
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                            return;
+                        }
+
+                        if (isAAFFeed(feedId)) {//edit AAF Feed
+                            String message = "DRProvCadiFilter - Edit AAF Feed:" + feedId + ":" + "AAF Instance -" + aafInstance;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            super.doFilter(request, response, chain);
+
+                        } else {//Edit or publish legacy Feed
+                            String message = "DRProvCadiFilter - Edit/Publish Legacy Feed:" + feedId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        }
+                    }
+                } else {// in all other cases defaults to legacy behavior
+                    String message = "DRProvCadiFilter - Default Legacy Feed/Subscriber URI -:" + httpRequest.getPathInfo();
+                    elr.setMessage(message);
+                    eventlogger.info(elr);
+                    chain.doFilter(request, response);
+                }
+            } else {
+                //check to add legacy/AAF subscriber
+                if ((pathUrl.contains("subscribe"))) {//add subscriber
+                    int feedId = BaseServlet.getIdFromPath(httpRequest);
+                    if (feedId <= 0) {
+                        String message = "Invalid request URI - " + httpRequest.getPathInfo();
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                        eventlogger.info(elr);
+                        httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                        return;
+                    }
+                    if (isAAFFeed(feedId)) {//check if AAF Feed or legacy to add new subscriber
+                        if (excludeAAF == null) {
+                            String message = "DRProvCadiFilter -Invalid request Header Parmeter " + BaseServlet.EXCLUDE_AAF_HEADER + " = " + httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+                            return;
+                        }
+                        if (excludeAAF.equalsIgnoreCase("true")) {//Check to add legacy subscriber to AAF Feed
+                            String message = "DRProvCadiFilter - add legacy subscriber to AAF Feed, FeedID:" + feedId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        } else {
+                            String message = "DRProvCadiFilter - Add AAF subscriber to AAF Feed, FeedID:" + feedId + ":" + "AAF Instance -" + aafInstance;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            super.doFilter(request, response, chain);
+                        }
+                    } else {//Add legacy susbcriber to legacy Feed
+                        String message = "DRProvCadiFilter - add legacy subscriber to legacy Feed:" + feedId;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        chain.doFilter(request, response);
+                    }
+                } else {//add AAF feed
+                    if (excludeAAF == null) {
+                        String message = "DRProvCadiFilter -Invalid request Header Parmeter " + BaseServlet.EXCLUDE_AAF_HEADER + " = " + httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                        eventlogger.info(elr);
+                        httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+                        return;
+                    }
+                    if (excludeAAF.equalsIgnoreCase("true")) {//add legacy feed
+                        String message = "DRProvCadiFilter - Create new legacy Feed : EXCLUDE_AAF = " + excludeAAF;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        chain.doFilter(request, response);
+                    } else {//add AAF Feed
+                        String message = "DRProvCadiFilter - Create new AAF Feed : EXCLUDE_AAF = " + excludeAAF;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        super.doFilter(request, response, chain);
+                    }
+                }
+            }
+        } else {
+            //All other requests default to (Non CADI) legacy
+            chain.doFilter(request, response);
+        }
+    }
+
+    /**
+     * Check if it is AAF feed OR existing feed.
+     *
+     * @param feedId the Feed ID
+     * @return true if it is valid
+     */
+    @SuppressWarnings("resource")
+    private boolean isAAFFeed(int feedId) {
+        try {
+            Feed feed = Feed.getFeedById(feedId);
+            if (feed != null) {
+                if (!((feed.getAafInstance().equalsIgnoreCase("legacy")) || feed.getAafInstance() == null || feed.getAafInstance().equals(""))) { //also apply null check and empty check too
+                    aafInstance = feed.getAafInstance();
+                    String message = "DRProvCadiFilter.isAAFFeed: aafInstance-:" + aafInstance + "; feedId:- " + feedId;
+                    intlogger.debug(message);
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                String message = "DRProvCadiFilter.isAAFFeed; Feed does not exist FeedID:-" + feedId;
+                intlogger.debug(message);
+            }
+
+        } catch (Exception e) {
+            intlogger.error("PROV0073 DRProvCadiFilter.isAAFFeed: ", e);
+            return false;
+        }
+        return false;
+    }
+
+    /**
+     * Check if it is AAF sub OR existing sub.
+     *
+     * @param subId the Sub ID
+     * @return true if it is valid
+     */
+    @SuppressWarnings("resource")
+    private boolean isAAFSubscriber(int subId) {
+        try {
+            Subscription subscriber = Subscription.getSubscriptionById(subId);
+            if (subscriber != null) {
+                if (!((subscriber.getAafInstance().equalsIgnoreCase("legacy")) || subscriber.getAafInstance() == null || subscriber.getAafInstance().equals(""))) { //also apply null check and empty check too
+                    aafInstance = subscriber.getAafInstance();
+                    String message = "DRProvCadiFilter.isAAFSubscriber: aafInstance-:" + aafInstance + "; subId:- " + subId;
+                    intlogger.debug(message);
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                String message = "DRProvCadiFilter.isAAFSubscriber; Subscriber does not exist subId:-" + subId;
+                intlogger.debug(message);
+            }
+        } catch (Exception e) {
+            intlogger.error("PROV0073 DRProvCadiFilter.isAAFSubscriber: ", e);
+            return false;
+        }
+        return false;
+    }
+
+}
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/LogfileLoader.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/LogfileLoader.java
index af9f829..6c5a13f 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/LogfileLoader.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/LogfileLoader.java
@@ -82,7 +82,7 @@
     /**

      * This is a singleton -- there is only one LogfileLoader object in the server

      */

-    private static LogfileLoader p;

+    private static LogfileLoader logfileLoader;

 

     /**

      * Get the singleton LogfileLoader object, and start it if it is not running.

@@ -90,11 +90,11 @@
      * @return the LogfileLoader

      */

     public static synchronized LogfileLoader getLoader() {

-        if (p == null)

-            p = new LogfileLoader();

-        if (!p.isAlive())

-            p.start();

-        return p;

+        if (logfileLoader == null)

+            logfileLoader = new LogfileLoader();

+        if (!logfileLoader.isAlive())

+            logfileLoader.start();

+        return logfileLoader;

     }

 

     /**

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java
new file mode 100644
index 0000000..4414203
--- /dev/null
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java
@@ -0,0 +1,73 @@
+/**

+ * -

+ * ============LICENSE_START=======================================================

+ * Copyright (C) 2019 Nordix Foundation.

+ * ================================================================================

+ * 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

+ * <p>

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * <p>

+ * 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.

+ * <p>

+ * SPDX-License-Identifier: Apache-2.0

+ * ============LICENSE_END=========================================================

+ */

+

+package org.onap.dmaap.datarouter.provisioning.utils;

+

+import javax.crypto.Cipher;

+import javax.crypto.SecretKey;

+import javax.crypto.SecretKeyFactory;

+import javax.crypto.spec.PBEKeySpec;

+import javax.crypto.spec.PBEParameterSpec;

+import java.nio.charset.StandardCharsets;

+import java.security.GeneralSecurityException;

+import java.util.Base64;

+

+/**

+ * The Processing of a Password.  Password can be encrypted and decrypted.

+ * @author Vikram Singh

+ * @version $Id: PasswordProcessor.java,v 1.0 2016/12/14 10:16:52 EST

+ */

+public class PasswordProcessor {

+

+    private PasswordProcessor(){}

+

+    private static final String SECRET_KEY_FACTORY_TYPE = "PBEWithMD5AndDES";

+    private static final String PASSWORD_ENCRYPTION_STRING = (new DB()).getProperties().getProperty("org.onap.dmaap.datarouter.provserver.passwordencryption");

+    private static final char[] PASSWORD = PASSWORD_ENCRYPTION_STRING.toCharArray();

+    private static final byte[] SALT = {(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,};

+

+    /**

+     * Encrypt password.

+     * @param property the Password

+     * @return Encrypted password.

+     */

+    public static String encrypt(String property) throws GeneralSecurityException {

+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_TYPE);

+        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));

+        Cipher pbeCipher = Cipher.getInstance(SECRET_KEY_FACTORY_TYPE);

+        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 32));

+        return Base64.getEncoder().encodeToString(pbeCipher.doFinal(property.getBytes(StandardCharsets.UTF_8)));

+    }

+

+    /**

+     * Decrypt password.

+     * @param property the Password

+     * @return Decrypt password.

+     */

+    public static String decrypt(String property) throws GeneralSecurityException {

+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_TYPE);

+        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));

+        Cipher pbeCipher = Cipher.getInstance(SECRET_KEY_FACTORY_TYPE);

+        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 32));

+        return new String(pbeCipher.doFinal(Base64.getDecoder().decode(property)), StandardCharsets.UTF_8);

+    }

+

+}

diff --git a/datarouter-prov/src/main/resources/drProvCadi.properties b/datarouter-prov/src/main/resources/drProvCadi.properties
new file mode 100644
index 0000000..56f2e5c
--- /dev/null
+++ b/datarouter-prov/src/main/resources/drProvCadi.properties
@@ -0,0 +1,23 @@
+cadi_x509_issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US
+cadi_keyfile=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.keyfile
+cadi_keystore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
+cadi_keystore_password=AT{];bvaDiytVD&oWhMZj0N5
+cadi_key_password=AT{];bvaDiytVD&oWhMZj0N5
+cadi_alias=dmaap-dr-prov@dmaap-dr.onap.org
+cadi_truststore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
+cadi_truststore_password=ljlS@Y}0]{UO(TnwvEWkgJ%]
+
+aaf_env=DEV
+aaf_locate_url=https://aaf-onap-test.osaaf.org:8095
+aaf_oauth2_introspect_url=https://AAF_LOCATE_URL/AAF_NS.introspect:2.1/introspect
+aaf_oauth2_token_url=https://AAF_LOCATE_URL/AAF_NS.token:2.1/token
+aaf_url=https://AAF_LOCATE_URL/AAF_NS.service:2.1
+cadi_protocols=TLSv1.1,TLSv1.2
+cm_url=https://AAF_LOCATE_URL/AAF_NS.cm:2.1
+fs_url=https://AAF_LOCATE_URL/AAF_NS.fs.2.1
+gui_url=https://AAF_LOCATE_URL/AAF_NS.gui.2.1
+
+cadi_latitude=53.423
+cadi_longitude=7.940
+
+cadi_loglevel=DEBUG
\ No newline at end of file
diff --git a/datarouter-prov/src/main/resources/misc/sql_init_01.sql b/datarouter-prov/src/main/resources/misc/sql_init_01.sql
index 14c59a6..55f0aee 100755
--- a/datarouter-prov/src/main/resources/misc/sql_init_01.sql
+++ b/datarouter-prov/src/main/resources/misc/sql_init_01.sql
@@ -1,10 +1,8 @@
-use datarouter;
-
 CREATE TABLE FEEDS (
     FEEDID         INT UNSIGNED NOT NULL PRIMARY KEY,
     GROUPID        INT(10) UNSIGNED NOT NULL DEFAULT 0,
     NAME           VARCHAR(255) NOT NULL,
-    VERSION        VARCHAR(20) NOT NULL,
+    VERSION        VARCHAR(20) NULL,
     DESCRIPTION    VARCHAR(1000),
     BUSINESS_DESCRIPTION VARCHAR(1000) DEFAULT NULL,
     AUTH_CLASS     VARCHAR(32) NOT NULL,
@@ -16,13 +14,14 @@
     DELETED        BOOLEAN DEFAULT FALSE,
     LAST_MOD       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED      BOOLEAN DEFAULT FALSE,
-    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    AAF_INSTANCE   VARCHAR(256)
 );
 
 CREATE TABLE FEED_ENDPOINT_IDS (
     FEEDID        INT UNSIGNED NOT NULL,
-    USERID        VARCHAR(20) NOT NULL,
-    PASSWORD      VARCHAR(32) NOT NULL
+    USERID        VARCHAR(60) NOT NULL,
+    PASSWORD      VARCHAR(100) NOT NULL
 );
 
 CREATE TABLE FEED_ENDPOINT_ADDRS (
@@ -35,8 +34,9 @@
     FEEDID                      INT UNSIGNED NOT NULL,
     GROUPID                     INT(10) UNSIGNED NOT NULL DEFAULT 0,
     DELIVERY_URL                VARCHAR(256),
-    DELIVERY_USER               VARCHAR(20),
-    DELIVERY_PASSWORD           VARCHAR(32),
+    FOLLOW_REDIRECTS            TINYINT(1) NOT NULL DEFAULT 0,
+    DELIVERY_USER               VARCHAR(60),
+    DELIVERY_PASSWORD           VARCHAR(100),
     DELIVERY_USE100             BOOLEAN DEFAULT FALSE,
     METADATA_ONLY               BOOLEAN DEFAULT FALSE,
     SUBSCRIBER                  VARCHAR(8) NOT NULL,
@@ -45,8 +45,9 @@
     LAST_MOD                    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED                   BOOLEAN DEFAULT FALSE,
     PRIVILEGED_SUBSCRIBER       BOOLEAN DEFAULT FALSE,
+    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     DECOMPRESS                  BOOLEAN DEFAULT FALSE,
-    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    AAF_INSTANCE                VARCHAR(256)
 
 );
 
@@ -89,7 +90,7 @@
 CREATE TABLE INGRESS_ROUTES (
     SEQUENCE  INT UNSIGNED NOT NULL,
     FEEDID    INT UNSIGNED NOT NULL,
-    USERID    VARCHAR(20),
+    USERID    VARCHAR(50),
     SUBNET    VARCHAR(44),
     NODESET   INT UNSIGNED NOT NULL
 );
@@ -144,6 +145,6 @@
     ('PROV_MAXFEED_COUNT',  '10000'),
     ('PROV_MAXSUB_COUNT',   '100000'),
     ('PROV_REQUIRE_CERT', 'false'),
-    ('PROV_REQUIRE_SECURE', 'false'),
+    ('PROV_REQUIRE_SECURE', 'true'),
     ('_INT_VALUES', 'LOGROLL_INTERVAL|PROV_MAXFEED_COUNT|PROV_MAXSUB_COUNT|DELIVERY_INIT_RETRY_INTERVAL|DELIVERY_MAX_RETRY_INTERVAL|DELIVERY_RETRY_RATIO|DELIVERY_MAX_AGE|DELIVERY_FILE_PROCESS_INTERVAL')
-    ;
+    ;
\ No newline at end of file
diff --git a/datarouter-prov/src/main/resources/provserver.properties b/datarouter-prov/src/main/resources/provserver.properties
index 4dcdee5..4539346 100755
--- a/datarouter-prov/src/main/resources/provserver.properties
+++ b/datarouter-prov/src/main/resources/provserver.properties
@@ -47,6 +47,22 @@
 
 # Database access
 org.onap.dmaap.datarouter.db.driver   = org.mariadb.jdbc.Driver
-org.onap.dmaap.datarouter.db.url      = jdbc:mariadb://172.100.0.2:3306/datarouter
+org.onap.dmaap.datarouter.db.url      = jdbc:mariadb://datarouter-mariadb:3306/datarouter
 org.onap.dmaap.datarouter.db.login    = datarouter
 org.onap.dmaap.datarouter.db.password = datarouter
+
+# PROV - DEFAULT ENABLED TLS PROTOCOLS
+org.onap.dmaap.datarouter.provserver.https.include.protocols = TLSv1.1|TLSv1.2
+
+# AAF config
+org.onap.dmaap.datarouter.provserver.cadi.enabled = false
+
+org.onap.dmaap.datarouter.provserver.passwordencryption   = PasswordEncryptionKey#@$%^&1234#
+org.onap.dmaap.datarouter.provserver.aaf.feed.type        = org.onap.dmaap-dr.feed
+org.onap.dmaap.datarouter.provserver.aaf.sub.type         = org.onap.dmaap-dr.sub
+org.onap.dmaap.datarouter.provserver.aaf.instance         = legacy
+org.onap.dmaap.datarouter.provserver.aaf.action.publish   = publish
+org.onap.dmaap.datarouter.provserver.aaf.action.subscribe = subscribe
+
+# AAF URL to connect to AAF server
+org.onap.dmaap.datarouter.provserver.cadi.aaf.url = https://aaf-onap-test.osaaf.org:8095
\ No newline at end of file
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServletTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServletTest.java
index a8f9c56..e2a2bc2 100755
--- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServletTest.java
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServletTest.java
@@ -22,59 +22,75 @@
  ******************************************************************************/
 package org.onap.dmaap.datarouter.provisioning;
 
-import static org.hamcrest.Matchers.notNullValue;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.argThat;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONArray;
 import org.json.JSONObject;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.authz.Authorizer;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.Mockito.*;
+import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
+
 
 @RunWith(PowerMockRunner.class)
-@SuppressStaticInitializationFor("org.onap.dmaap.datarouter.provisioning.beans.Feed")
 public class DRFeedsServletTest extends DrServletTestBase {
 
     private static DRFeedsServlet drfeedsServlet;
+    private static EntityManagerFactory emf;
+    private static EntityManager em;
+    private DB db;
 
     @Mock
     private HttpServletRequest request;
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
+
+    @BeforeClass
+    public static void init() {
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");
+        em = emf.createEntityManager();
+        System.setProperty(
+                "org.onap.dmaap.datarouter.provserver.properties",
+                "src/test/resources/h2Database.properties");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        em.clear();
+        em.close();
+        emf.close();
+    }
 
     @Before
     public void setUp() throws Exception {
-        super.setUp();
         listAppender = setTestLogger(DRFeedsServlet.class);
         drfeedsServlet = new DRFeedsServlet();
+        db = new DB();
         setAuthoriserToReturnRequestIsAuthorized();
         setPokerToNotCreateTimersWhenDeleteFeedIsCalled();
         setupValidAuthorisedRequest();
@@ -137,14 +153,11 @@
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds_With_Valid_Name_And_Version() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
-        when(request.getParameter("name")).thenReturn("stub_name");
-        when(request.getParameter("version")).thenReturn("stub_version");
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(feed);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
+        when(request.getParameter("name")).thenReturn("Feed1");
+        when(request.getParameter("version")).thenReturn("v0.1");
         drfeedsServlet.doGet(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        verify(response).setContentType(BaseServlet.FEEDFULL_CONTENT_TYPE);
         verifyEnteringExitCalled(listAppender);
     }
 
@@ -205,14 +218,114 @@
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
+    public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_True_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
         throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
+                return jo;
+            }
+        };
         drfeedsServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
     @Test
+    public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_False_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
+            throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "false", true);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
+                return jo;
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_True_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
+                return jo;
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Invalid request exclude_AAF"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
+                return jo;
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_With_Permissions_Then_Created_OK_Response_Is_Generated() throws Exception {
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
+        JSONObject JSObject = buildRequestJsonObject();
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
+                return jo;
+            }
+
+            @Override
+            protected boolean doInsert(Insertable bean) {
+                return true;
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
+        verifyEnteringExitCalled(listAppender);
+    }
+
+    @Test
     public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
         throws Exception {
         drfeedsServlet.doPost(request, response);
@@ -235,13 +348,9 @@
     @Test
     public void Given_Request_Is_HTTP_POST_And_Feed_Is_Not_Valid_Object_Bad_Request_Response_Is_Generated()
         throws Exception {
-        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
-        JSONObject JSObject = buildRequestJsonObject();
-
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
-                JSONObject jo = new JSONObject();
-                return jo;
+                return new JSONObject();
             }
         };
 
@@ -252,30 +361,36 @@
     @Test
     public void Given_Request_Is_HTTP_POST_And_Feed_Already_Exists_Bad_Request_Response_Is_Generated()
         throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+        when(request.getParameter("name")).thenReturn("AafFeed");
+        when(request.getParameter("version")).thenReturn("v0.1");
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
         JSONObject JSObject = buildRequestJsonObject();
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "not_stub_name");
-                jo.put("version", "1.0");
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
                 return jo;
             }
         };
         drfeedsServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("This feed already exists in the database"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
         JSONObject JSObject = buildRequestJsonObject();
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
                 jo.put("name", "stub_name");
                 jo.put("version", "2.0");
                 jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
                 return jo;
             }
 
@@ -289,32 +404,6 @@
             .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
     }
 
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_Change_On_Feeds_Succeeds_A_STATUS_OK_Response_Is_Generated()
-        throws Exception {
-        ServletOutputStream outStream = mock(ServletOutputStream.class);
-        when(response.getOutputStream()).thenReturn(outStream);
-        JSONObject JSObject = buildRequestJsonObject();
-        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
-            protected JSONObject getJSONfromInput(HttpServletRequest req) {
-                JSONObject jo = new JSONObject();
-                jo.put("name", "stub_name");
-                jo.put("version", "1.0");
-                jo.put("authorization", JSObject);
-                return jo;
-            }
-
-            @Override
-            protected boolean doInsert(Insertable bean) {
-                return true;
-            }
-        };
-        drfeedsServlet.doPost(request, response);
-        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
-        verifyEnteringExitCalled(listAppender);
-    }
-
     @NotNull
     private JSONObject buildRequestJsonObject() {
         JSONObject JSObject = new JSONObject();
@@ -335,7 +424,7 @@
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
         FieldUtils
             .writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,
@@ -348,29 +437,6 @@
         when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
     }
 
-    private void setValidPathInfoInHttpHeader() {
-        when(request.getPathInfo()).thenReturn("/123");
-    }
-
-    private void setFeedToReturnInvalidFeedIdSupplied() {
-        PowerMockito.mockStatic(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(null);
-        when(Feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(mock(Feed.class));
-    }
-
-    private void setFeedToReturnValidFeedForSuppliedId() {
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(feed);
-        when(feed.isDeleted()).thenReturn(false);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
-        when(feed.getPublisher()).thenReturn("Stub_Value");
-        when(feed.getName()).thenReturn("stub_name");
-        when(feed.getVersion()).thenReturn("1.0");
-        when(feed.asLimitedJSONObject()).thenReturn(mock(JSONObject.class));
-        PowerMockito.when(feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(null);
-    }
-
     private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
         Authorizer authorizer = mock(Authorizer.class);
@@ -395,13 +461,10 @@
     private void setupValidAuthorisedRequest() throws Exception {
         setUpValidSecurityOnHttpRequest();
         setBehalfHeader("Stub_Value");
-        setValidPathInfoInHttpHeader();
-        setFeedToReturnValidFeedForSuppliedId();
     }
 
-    private void setUpValidContentHeadersAndJSONOnHttpRequest() {
+    private void setUpValidContentHeadersAndJSONOnHttpRequest() throws IllegalAccessException {
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
-
     }
 }
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DrServletTestBase.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DrServletTestBase.java
index 265a2ee..bad6e2c 100644
--- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DrServletTestBase.java
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DrServletTestBase.java
@@ -28,17 +28,11 @@
 import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.Before;
 import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
 import java.util.Properties;
-import java.util.Scanner;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
@@ -46,7 +40,6 @@
 
 public class DrServletTestBase {
 
-
     @Before
     public void setUp() throws Exception {
         Properties props = new Properties();
@@ -61,7 +54,7 @@
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "synctask", synchronizerTask, true);
     }
 
-    public ListAppender<ILoggingEvent> setTestLogger(Class c) {
+    ListAppender<ILoggingEvent> setTestLogger(Class c) {
         Logger logger = (Logger) LoggerFactory.getLogger(c);
         ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
         listAppender.start();
@@ -69,7 +62,7 @@
         return listAppender;
     }
 
-    public void verifyEnteringExitCalled(ListAppender<ILoggingEvent> listAppender) {
+    void verifyEnteringExitCalled(ListAppender<ILoggingEvent> listAppender) {
         assertEquals("EELF0004I  Entering data router provisioning component with RequestId and InvocationId", listAppender.list.get(0).getMessage());
         assertEquals("EELF0005I  Exiting data router provisioning component with RequestId and InvocationId", listAppender.list.get(2).getMessage());
         assertEquals(3, listAppender.list.size());
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/FeedServletTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/FeedServletTest.java
index f042e11..f4eac05 100755
--- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/FeedServletTest.java
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/FeedServletTest.java
@@ -71,7 +71,7 @@
     private static EntityManager em;
     private DB db;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
 
     @BeforeClass
     public static void init() {
@@ -120,8 +120,7 @@
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
         when(request.getPathInfo()).thenReturn(null);
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
@@ -129,8 +128,7 @@
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
         when(request.getPathInfo()).thenReturn("/123");
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
@@ -138,13 +136,28 @@
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        feedServlet.doDelete(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() {
+        when(request.getPathInfo()).thenReturn("/3");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|delete")).thenReturn(true);
+        feedServlet.doDelete(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
+        verifyEnteringExitCalled(listAppender);
+    }
+
 
     @Test
     public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Fails_An_Internal_Server_Error_Is_Reported()
@@ -161,8 +174,7 @@
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
         feedServlet.doDelete(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
         reinsertFeedIntoDb();
@@ -209,6 +221,7 @@
     public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
         throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
@@ -218,6 +231,7 @@
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doGet(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
         verifyEnteringExitCalled(listAppender);
@@ -264,9 +278,9 @@
         throws Exception {
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed-fail; version=2.0");
         when(request.getContentType()).thenReturn("stub_contentType");
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doPut(request, response);
-        verify(response)
-            .sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
     }
 
     @Test
@@ -274,12 +288,19 @@
         throws Exception {
         ServletInputStream inStream = mock(ServletInputStream.class);
         when(request.getInputStream()).thenReturn(inStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return null;
+            }
+        };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("Badly formed JSON"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Invalid_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 return new JSONObject();
@@ -292,6 +313,7 @@
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Change_Is_Not_Publisher_Who_Requested_Feed_Bad_Request_Response_Is_Generated() throws Exception {
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -302,13 +324,13 @@
                 return jo;
             }
         };
-
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("must be modified by the same publisher"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Name_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -320,52 +342,99 @@
             }
         };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("name of the feed may not be updated"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Version_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "stub_name");
-                jo.put("version", "2.0");
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.2");
                 jo.put("authorization", JSObject);
                 return jo;
             }
         };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("version of the feed may not be updated"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
             }
         };
-        setAuthoriserToReturnRequestNotAuthorized();
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
+                return jo;
+            }
+        };
+        feedServlet.doPut(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_With_Permissions_Then_STATUS_OK__Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|edit")).thenReturn(true);
+        JSONObject JSObject = buildRequestJsonObject();
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
+                return jo;
+            }
+            @Override
+            protected boolean doUpdate(Updateable bean) {
+                return true;
+            }
+
+        };
+        feedServlet.doPut(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        verifyEnteringExitCalled(listAppender);
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
-
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
@@ -384,15 +453,20 @@
     public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Suceeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
             }
+            @Override
+            protected boolean doUpdate(Updateable bean) {
+                return true;
+            }
 
         };
         feedServlet.doPut(request, response);
@@ -427,11 +501,9 @@
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
-        FieldUtils
-            .writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,
-                true);
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,true);
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
     }
 
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscribeServletTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscribeServletTest.java
index 0b5c23f..b867c67 100755
--- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscribeServletTest.java
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscribeServletTest.java
@@ -27,19 +27,24 @@
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONObject;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.authz.Authorizer;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -54,20 +59,39 @@
 
 
 @RunWith(PowerMockRunner.class)
-@SuppressStaticInitializationFor({"org.onap.dmaap.datarouter.provisioning.beans.Feed", "org.onap.dmaap.datarouter.provisioning.beans.Subscription"})
+@PrepareForTest(Subscription.class)
 public class SubscribeServletTest extends DrServletTestBase {
     private static SubscribeServlet subscribeServlet;
+    private static EntityManagerFactory emf;
+    private static EntityManager em;
+    private DB db;
 
     @Mock
     private HttpServletRequest request;
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
+
+    @BeforeClass
+    public static void init() {
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");
+        em = emf.createEntityManager();
+        System.setProperty(
+                "org.onap.dmaap.datarouter.provserver.properties",
+                "src/test/resources/h2Database.properties");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        em.clear();
+        em.close();
+        emf.close();
+    }
 
     @Before
     public void setUp() throws Exception {
-        super.setUp();
+        db = new DB();
         listAppender = setTestLogger(SubscribeServlet.class);
         subscribeServlet = new SubscribeServlet();
         setAuthoriserToReturnRequestIsAuthorized();
@@ -110,26 +134,18 @@
 
     @Test
     public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+        when(request.getPathInfo()).thenReturn("/123");
         subscribeServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
 
-
-    @Test
-    public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
-        setAuthoriserToReturnRequestNotAuthorized();
-        subscribeServlet.doGet(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
-    }
-
-
     @Test
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/1");
         PowerMockito.mockStatic(Subscription.class);
-        List<String> list = new ArrayList<String>();
+        List<String> list = new ArrayList<>();
         list.add("{}");
         PowerMockito.when(Subscription.getSubscriptionUrlList(anyInt())).thenReturn(list);
         subscribeServlet.doGet(request, response);
@@ -171,7 +187,7 @@
 
     @Test
     public void Given_Request_Is_HTTP_POST_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+        when(request.getPathInfo()).thenReturn("/123");
         subscribeServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -179,41 +195,7 @@
     @Test
     public void Given_Request_Is_HTTP_POST_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
-        subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
-    }
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
-        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
-        when(request.getContentType()).thenReturn("stub_contentType");
-        subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
-    }
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
-        subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
-    }
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated() throws Exception {
-        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 0, true);
-        SubscribeServlet subscribeServlet = new SubscribeServlet() {
-            protected JSONObject getJSONfromInput(HttpServletRequest req) {
-                return new JSONObject();
-            }
-        };
-        subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
-    }
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
-        PowerMockito.mockStatic(Subscription.class);
-        PowerMockito.when(Subscription.getSubscriptionMatching(mock(Subscription.class))).thenReturn(null);
-        PowerMockito.when(Subscription.countActiveSubscriptions()).thenReturn(0);
+        when(request.getPathInfo()).thenReturn("/1");
         JSONObject JSObject = buildRequestJsonObject();
         SubscribeServlet subscribeServlet = new SubscribeServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -226,23 +208,18 @@
                 jo.put("sync", false);
                 return jo;
             }
-
             @Override
             protected boolean doInsert(Insertable bean) {
                 return false;
             }
         };
         subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
-
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Change_On_Feeds_Succeeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
-        ServletOutputStream outStream = mock(ServletOutputStream.class);
-        when(response.getOutputStream()).thenReturn(outStream);
-        PowerMockito.mockStatic(Subscription.class);
-        PowerMockito.when(Subscription.getSubscriptionMatching(mock(Subscription.class))).thenReturn(null);
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_Legacy_Feed_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/1");
         JSONObject JSObject = buildRequestJsonObject();
         SubscribeServlet subscribeServlet = new SubscribeServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -252,7 +229,85 @@
                 jo.put("metadataOnly", true);
                 jo.put("suspend", true);
                 jo.put("delivery", JSObject);
-                jo.put("sync", true);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+            @Override
+            protected boolean doInsert(Insertable bean) {
+                return false;
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF Subscriber can not be added to legacy Feed"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Legacy_Subscriber_Added_To_AAF_Feed_And_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access."));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_With_Permissions_Then_OK_Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|approveSub")).thenReturn(true);
+        PowerMockito.mockStatic(Subscription.class);
+        PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
                 return jo;
             }
 
@@ -266,6 +321,63 @@
         verifyEnteringExitCalled(listAppender);
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
+        when(request.getContentType()).thenReturn("stub_contentType");
+        when(request.getPathInfo()).thenReturn("/1");
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/1");
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 0, true);
+        when(request.getPathInfo()).thenReturn("/1");
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return new JSONObject();
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        PowerMockito.mockStatic(Subscription.class);
+        PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+
+            @Override
+            protected boolean doInsert(Insertable bean) {
+                return false;
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
+    }
 
     @NotNull
     private JSONObject buildRequestJsonObject() {
@@ -279,7 +391,7 @@
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks, true);
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
@@ -290,27 +402,6 @@
         when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
     }
 
-    private void setValidPathInfoInHttpHeader() {
-        when(request.getPathInfo()).thenReturn("/123");
-    }
-
-    private void setFeedToReturnInvalidFeedIdSupplied() {
-        PowerMockito.mockStatic(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(null);
-    }
-
-    private void setFeedToReturnValidFeedForSuppliedId() {
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(feed);
-        when(feed.isDeleted()).thenReturn(false);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
-        when(feed.getPublisher()).thenReturn("Stub_Value");
-        when(feed.getName()).thenReturn("stub_name");
-        when(feed.getVersion()).thenReturn("1.0");
-        when(feed.asLimitedJSONObject()).thenReturn(mock(JSONObject.class));
-    }
-
     private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
         Authorizer authorizer = mock(Authorizer.class);
@@ -335,8 +426,6 @@
     private void setupValidAuthorisedRequest() throws Exception {
         setUpValidSecurityOnHttpRequest();
         setBehalfHeader("Stub_Value");
-        setValidPathInfoInHttpHeader();
-        setFeedToReturnValidFeedForSuppliedId();
     }
 
     private void setUpValidContentHeadersAndJSONOnHttpRequest() {
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServletTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServletTest.java
index aede69c..a17e23e 100755
--- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServletTest.java
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServletTest.java
@@ -27,7 +27,10 @@
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONObject;
-import org.junit.*;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
@@ -37,6 +40,9 @@
 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
 import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
 import javax.persistence.EntityManager;
@@ -46,7 +52,6 @@
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.FileNotFoundException;
 import java.sql.SQLException;
 import java.util.HashSet;
 import java.util.Set;
@@ -57,6 +62,7 @@
 
 
 @RunWith(PowerMockRunner.class)
+@PrepareForTest(PasswordProcessor.class)
 public class SubscriptionServletTest extends DrServletTestBase {
     private static EntityManagerFactory emf;
     private static EntityManager em;
@@ -72,7 +78,7 @@
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
 
     @BeforeClass
     public static void init() {
@@ -84,7 +90,7 @@
     }
 
     @AfterClass
-    public static void tearDownClass() throws FileNotFoundException {
+    public static void tearDownClass() {
         em.clear();
         em.close();
         emf.close();
@@ -125,7 +131,7 @@
 
     @Test
     public void Given_Request_Is_HTTP_DELETE_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -149,11 +155,22 @@
     }
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_CADI_Is_Enabled_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/2");
+        subscriptionServlet.doDelete(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_CADI_Is_Enabled_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.sub|*|delete")).thenReturn(true);
         subscriptionServlet.doDelete(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
         verifyEnteringExitCalled(listAppender);
-        insertSubscriptionIntoDb();
+        resetAafSubscriptionInDB();
     }
 
     @Test
@@ -180,7 +197,7 @@
 
     @Test
     public void Given_Request_Is_HTTP_GET_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -225,7 +242,7 @@
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doPut(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -233,11 +250,83 @@
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("decompress", true);
+                jo.put("sync", true);
+                jo.put("changeowner", true);
+                return jo;
+            }
+        };
         subscriptionServlet.doPut(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
     @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_CADI_Is_Enabled_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/3");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", true);
+                jo.put("changeowner", true);
+                return jo;
+            }
+        };
+        subscriptionServlet.doPut(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_CADI_Is_Enabled_With_Permissions_Then_OK_Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/3");
+        when(request.isUserInRole("org.onap.dmaap-dr.sub|*|edit")).thenReturn(true);
+        PowerMockito.mockStatic(PasswordProcessor.class);
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", true);
+                return jo;
+            }
+        };
+        subscriptionServlet.doPut(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        resetAafSubscriptionInDB();
+        verifyEnteringExitCalled(listAppender);
+    }
+
+    @Test
     public void Given_Request_Is_HTTP_PUT_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
         when(request.getContentType()).thenReturn("stub_ContentType");
         subscriptionServlet.doPut(request, response);
@@ -281,6 +370,8 @@
                 jo.put("privilegedSubscriber", true);
                 jo.put("decompress", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("subscriber", "differentSubscriber");
                 jo.put("sync", true);
                 return jo;
@@ -304,7 +395,9 @@
                 jo.put("suspend", true);
                 jo.put("privilegedSubscriber", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
                 jo.put("decompress", true);
+                jo.put("follow_redirect", false);
                 jo.put("sync", true);
                 return jo;
             }
@@ -324,6 +417,7 @@
         when(response.getOutputStream()).thenReturn(outStream);
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        PowerMockito.mockStatic(PasswordProcessor.class);
         JSONObject JSObject = buildRequestJsonObject();
         SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -335,6 +429,8 @@
                 jo.put("privilegedSubscriber", true);
                 jo.put("decompress", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("sync", true);
                 jo.put("changeowner", true);
                 return jo;
@@ -370,7 +466,7 @@
 
     @Test
     public void Given_Request_Is_HTTP_POST_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
     }
@@ -435,6 +531,8 @@
                 jo.put("suspend", true);
                 jo.put("delivery", JSObject);
                 jo.put("privilegedSubscriber", false);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("decompress", false);
                 jo.put("failed", false);
                 return jo;
@@ -498,21 +596,6 @@
         setValidPathInfoInHttpHeader();
     }
 
-    private void insertSubscriptionIntoDb() throws SQLException {
-        Subscription subscription = new Subscription(URL, USER, PASSWORD);
-        subscription.setSubid(1);
-        subscription.setSubscriber("user1");
-        subscription.setFeedid(1);
-        SubDelivery subDelivery = new SubDelivery(URL, USER, PASSWORD, true);
-        subscription.setDelivery(subDelivery);
-        subscription.setGroupid(1);
-        subscription.setMetadataOnly(false);
-        subscription.setSuspended(false);
-        subscription.setPrivilegedSubscriber(false);
-        subscription.setDecompress(false);
-        subscription.doInsert(db.getConnection());
-    }
-
     private void changeSubscriptionBackToNormal() throws SQLException {
         Subscription subscription = new Subscription("https://172.100.0.5", "user1", "password1");
         subscription.setSubid(1);
@@ -528,4 +611,20 @@
         subscription.changeOwnerShip();
         subscription.doUpdate(db.getConnection());
     }
+
+    private void resetAafSubscriptionInDB() throws SQLException {
+        Subscription subscription = new Subscription("https://172.100.0.5:8080", "user2", "password2");
+        subscription.setSubid(2);
+        subscription.setSubscriber("user2");
+        subscription.setFeedid(1);
+        SubDelivery subDelivery = new SubDelivery(URL, USER, PASSWORD, true);
+        subscription.setDelivery(subDelivery);
+        subscription.setGroupid(1);
+        subscription.setMetadataOnly(false);
+        subscription.setSuspended(false);
+        subscription.setAafInstance("https://aaf-onap-test.osaaf.org:8095");
+        subscription.setDecompress(false);
+        subscription.setPrivilegedSubscriber(false);
+        subscription.doUpdate(db.getConnection());
+    }
 }
\ No newline at end of file
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java
new file mode 100644
index 0000000..5e24c5a
--- /dev/null
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java
@@ -0,0 +1,269 @@
+/**-

+ * ============LICENSE_START=======================================================

+ *  Copyright (C) 2019 Nordix Foundation.

+ * ================================================================================

+ * 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.

+ *

+ * SPDX-License-Identifier: Apache-2.0

+ * ============LICENSE_END=========================================================

+ */

+

+package org.onap.dmaap.datarouter.provisioning.utils;

+

+import org.junit.Before;

+import org.junit.BeforeClass;

+import org.junit.Test;

+import org.junit.runner.RunWith;

+import org.mockito.Mock;

+import org.onap.aaf.cadi.PropAccess;

+import org.onap.aaf.cadi.filter.CadiFilter;

+import org.onap.dmaap.datarouter.provisioning.BaseServlet;

+import org.powermock.api.mockito.PowerMockito;

+import org.powermock.api.support.membermodification.MemberMatcher;

+import org.powermock.core.classloader.annotations.PrepareForTest;

+import org.powermock.modules.junit4.PowerMockRunner;

+

+import javax.persistence.EntityManager;

+import javax.persistence.EntityManagerFactory;

+import javax.persistence.Persistence;

+import javax.servlet.FilterChain;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import static org.hamcrest.Matchers.notNullValue;

+import static org.mockito.Matchers.argThat;

+import static org.mockito.Matchers.eq;

+import static org.mockito.Mockito.*;

+import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;

+

+@RunWith(PowerMockRunner.class)

+@PrepareForTest({CadiFilter.class})

+public class DRProvCadiFilterTest {

+

+    @Mock

+    private PropAccess access;

+

+    @Mock

+    private HttpServletRequest request;

+

+    @Mock

+    private HttpServletResponse response;

+

+    @Mock

+    private FilterChain chain;

+

+    private DRProvCadiFilter cadiFilter;

+

+

+    private static EntityManagerFactory emf;

+    private static EntityManager em;

+

+

+    @BeforeClass

+    public static void init() {

+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");

+        em = emf.createEntityManager();

+        System.setProperty(

+                "org.onap.dmaap.datarouter.provserver.properties",

+                "src/test/resources/h2Database.properties");

+    }

+

+    @Before

+    public void setUp() throws Exception {

+        cadiFilter = new DRProvCadiFilter(false, access);

+    }

+

+    @Test

+    public void Given_doFilter_Called_And_Path_Contains_subs_And_SubId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned() throws Exception{

+        setRequestMocking("PUT", "subs");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+    }

+

+    @Test

+    public void Given_doFilter_called_And_Path_Contains_subs_And_Is_AAF_Subscriber_then_call_Super_doFilter() throws Exception{

+        setRequestMocking("PUT", "subs");

+        when(request.getPathInfo()).thenReturn("/2");

+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(0)).doFilter(request, response);

+    }

+

+    @Test

+    public void Given_doFilter_called_And_Path_Contains_subs_And_Is_Not_AAF_Subscriber_then_call_chain_doFilter() throws Exception{

+        setRequestMocking("PUT", "subs");

+        when(request.getPathInfo()).thenReturn("/5");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+    }

+

+    @Test

+    public void Given_doFilter_called_And_FeedId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned () throws Exception{

+        setRequestMocking("PUT", "feeds");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+    }

+

+    @Test

+    public void Given_doFilter_called_And_FeedId_Is_Correctly_Set_And_Is_AAF_Feed_Then_Call_Super_doFilter() throws Exception{

+        setRequestMocking("PUT", "feeds");

+        when(request.getPathInfo()).thenReturn("/2");

+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(0)).doFilter(request, response);

+    }

+

+    @Test

+    public void Given_doFilter_called_And_FeedId_Is_Correctly_Set_And_Is_Not_AAF_Feed_then_call_chain_doFilter() throws Exception{

+        setRequestMocking("PUT", "feeds");

+        when(request.getPathInfo()).thenReturn("/1");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+    }

+

+    @Test

+    public void Given_doFilter_called_With_Get_Then_call_chain_doFilter() throws Exception{

+        setRequestMocking("GET", "feeds");

+        when(request.getPathInfo()).thenReturn("/5");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+    }

+

+

+    @Test

+    public void Given_doFilter_called_With_POST_Then_call_chain_doFilter() throws Exception{

+        setRequestMocking("POST", "subscribe");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_FeedId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned() throws Exception{

+        setRequestMocking("POST", "subscribe");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Is_NULL_Then_Bad_Request_Response_Returned() throws Exception{

+        setRequestMocking("POST", "subscribe");

+        when(request.getPathInfo()).thenReturn("/2");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Equals_True_Then_Call_Chain_doFilter() throws Exception{

+        setRequestMocking("POST", "subscribe");

+        when(request.getPathInfo()).thenReturn("/2");

+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("true");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Equals_False_Then_Call_Super_doFilter() throws Exception{

+        setRequestMocking("POST", "subscribe");

+        when(request.getPathInfo()).thenReturn("/2");

+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");

+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(0)).doFilter(request, response);

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Is_Not_AAF_Exclude_AAF_Equals_Then_Call_Chain_doFilter() throws Exception{

+        setRequestMocking("POST", "subscribe");

+        when(request.getPathInfo()).thenReturn("/5");

+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Is_NULL_Then_Bad_Request_Response_Returned() throws Exception{

+        setRequestMocking("POST", "other");

+        when(request.getPathInfo()).thenReturn("/5");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Equals_True_Then_Call_Chain_doFilter() throws Exception{

+        setRequestMocking("POST", "other");

+        when(request.getPathInfo()).thenReturn("/5");

+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("true");

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(1)).doFilter(request, response);

+

+    }

+

+    @Test

+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Equals_False_Then_Call_Super_doFilter() throws Exception{

+        setRequestMocking("POST", "other");

+        when(request.getPathInfo()).thenReturn("/5");

+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");

+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));

+

+        cadiFilter.doFilter(request, response, chain);

+        verify(chain, times(0)).doFilter(request, response);

+

+    }

+

+    @Test

+    public void Given_doFilter_Called_And_Path_Contains_subs_And_getSubId_Throws_NumberFormatException_then_Not_Found_response_returned() throws Exception{

+            setRequestMocking("PUT", "subs");

+            when(request.getPathInfo()).thenReturn("5/");

+            cadiFilter.doFilter(request, response, chain);

+            verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+

+    }

+

+    @Test

+    public void Given_doFilter_called_And_FeedId_Throws_Set_Then_Not_Found_Response_Returned () throws Exception{

+        setRequestMocking("PUT", "feeds");

+        when(request.getPathInfo()).thenReturn("//5");

+        cadiFilter.doFilter(request, response, chain);

+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));

+    }

+

+    private void setRequestMocking(String method, String servletPath)

+    {

+        when(request.getRemoteAddr()).thenReturn(null);

+        when(request.getHeader(BEHALF_HEADER)).thenReturn(null);

+        when(request.getAttribute(BaseServlet.CERT_ATTRIBUTE)).thenReturn(null);

+        when(request.getMethod()).thenReturn(method);

+        when(request.getServletPath()).thenReturn(servletPath);

+    }

+

+    }

diff --git a/datarouter-prov/src/test/resources/create.sql b/datarouter-prov/src/test/resources/create.sql
index 9412adf..1fb30c9 100755
--- a/datarouter-prov/src/test/resources/create.sql
+++ b/datarouter-prov/src/test/resources/create.sql
@@ -2,7 +2,7 @@
     FEEDID         INT UNSIGNED NOT NULL PRIMARY KEY,
     GROUPID        INT(10) UNSIGNED NOT NULL DEFAULT 0,
     NAME           VARCHAR(255) NOT NULL,
-    VERSION        VARCHAR(20) NOT NULL,
+    VERSION        VARCHAR(20) NULL,
     DESCRIPTION    VARCHAR(1000),
     BUSINESS_DESCRIPTION VARCHAR(1000) DEFAULT NULL,
     AUTH_CLASS     VARCHAR(32) NOT NULL,
@@ -14,13 +14,14 @@
     DELETED        BOOLEAN DEFAULT FALSE,
     LAST_MOD       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED      BOOLEAN DEFAULT FALSE,
-    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    AAF_INSTANCE   VARCHAR(256)
 );
 
 CREATE TABLE FEED_ENDPOINT_IDS (
     FEEDID        INT UNSIGNED NOT NULL,
-    USERID        VARCHAR(20) NOT NULL,
-    PASSWORD      VARCHAR(32) NOT NULL
+    USERID        VARCHAR(60) NOT NULL,
+    PASSWORD      VARCHAR(100) NOT NULL
 );
 
 CREATE TABLE FEED_ENDPOINT_ADDRS (
@@ -33,8 +34,9 @@
     FEEDID                      INT UNSIGNED NOT NULL,
     GROUPID                     INT(10) UNSIGNED NOT NULL DEFAULT 0,
     DELIVERY_URL                VARCHAR(256),
-    DELIVERY_USER               VARCHAR(20),
-    DELIVERY_PASSWORD           VARCHAR(32),
+    FOLLOW_REDIRECTS            TINYINT(1) NOT NULL DEFAULT 0,
+    DELIVERY_USER               VARCHAR(60),
+    DELIVERY_PASSWORD           VARCHAR(100),
     DELIVERY_USE100             BOOLEAN DEFAULT FALSE,
     METADATA_ONLY               BOOLEAN DEFAULT FALSE,
     SUBSCRIBER                  VARCHAR(8) NOT NULL,
@@ -43,8 +45,9 @@
     LAST_MOD                    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED                   BOOLEAN DEFAULT FALSE,
     PRIVILEGED_SUBSCRIBER       BOOLEAN DEFAULT FALSE,
+    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     DECOMPRESS                  BOOLEAN DEFAULT FALSE,
-    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    AAF_INSTANCE                VARCHAR(256)
 
 );
 
@@ -87,7 +90,7 @@
 CREATE TABLE INGRESS_ROUTES (
     SEQUENCE  INT UNSIGNED NOT NULL,
     FEEDID    INT UNSIGNED NOT NULL,
-    USERID    VARCHAR(20),
+    USERID    VARCHAR(50),
     SUBNET    VARCHAR(44),
     NODESET   INT UNSIGNED NOT NULL
 );
@@ -136,7 +139,7 @@
     ('DELIVERY_MAX_RETRY_INTERVAL', '3600'),
     ('DELIVERY_FILE_PROCESS_INTERVAL', '600'),
     ('DELIVERY_RETRY_RATIO', '2'),
-    ('LOGROLL_INTERVAL', '300'),
+    ('LOGROLL_INTERVAL', '30'),
     ('PROV_AUTH_ADDRESSES', 'dmaap-dr-prov|dmaap-dr-node'),
     ('PROV_AUTH_SUBJECTS', ''),
     ('PROV_MAXFEED_COUNT',  '10000'),
@@ -149,11 +152,17 @@
 INSERT INTO GROUPS(GROUPID, AUTHID, NAME, DESCRIPTION, CLASSIFICATION, MEMBERS)
 VALUES (1, 'Basic dXNlcjE6cGFzc3dvcmQx', 'Group1', 'First Group for testing', 'Class1', 'Member1');
 
-INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, DECOMPRESS)
-VALUES (1, 1, 'https://172.100.0.5:8080', 'user1', 'password1', true, false, 'user1', false, 1, false, false);
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, AAF_INSTANCE, DECOMPRESS)
+VALUES (1, 1, 'https://172.100.0.5:8080', 0, 'user1', 'password1', true, false, 'user1', false, 1, false, 'legacy', false);
 
-INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, SUBSCRIBER, SELF_LINK, LOG_LINK)
-VALUES (23, 1, 'http://delivery_url', 'user1', 'somepassword', 'sub123', 'selflink', 'loglink');
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, AAF_INSTANCE)
+VALUES (2, 1, 'https://172.100.0.5:8080', 0, 'user2', 'password2', true, true, 'subsc2', false, 1, '*');
+
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, AAF_INSTANCE)
+VALUES (3, 1, 'https://172.100.0.5:8080', 0, 'user3', 'password3', true, true, 'subsc3', false, 1, '*');
+
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, SUBSCRIBER, SELF_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (23, 1, 'http://delivery_url', 'user1', 'somepassword', 'sub123', 'selflink', 'loglink', 'legacy');
 
 INSERT INTO FEED_ENDPOINT_IDS(FEEDID, USERID, PASSWORD)
 VALUES (1, 'USER', 'PASSWORD');
@@ -164,6 +173,12 @@
 INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK)
 VALUES (1, 1,'Feed1','v0.1', 'First Feed for testing', 'First Feed for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link');
 
+INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (2, 1,'AafFeed','v0.1', 'AAF Feed for testing', 'AAF Feed for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link','*');
+
+INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (3, 1,'DeleteableAafFeed','v0.1', 'AAF Feed3 for testing', 'AAF Feed3 for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link','*');
+
 insert into INGRESS_ROUTES(SEQUENCE, FEEDID , USERID, SUBNET, NODESET)
 VALUES (1,1,'user',null,2);
 
diff --git a/datarouter-prov/src/test/resources/h2Database.properties b/datarouter-prov/src/test/resources/h2Database.properties
index a7ed3fa..fee9c68 100755
--- a/datarouter-prov/src/test/resources/h2Database.properties
+++ b/datarouter-prov/src/test/resources/h2Database.properties
@@ -28,4 +28,5 @@
 org.onap.dmaap.datarouter.provserver.https.relaxation      = false
 org.onap.dmaap.datarouter.provserver.accesslog.dir         = unit-test-logs
 org.onap.dmaap.datarouter.provserver.spooldir              = unit-test-logs/spool
-org.onap.dmaap.datarouter.provserver.localhost             = 127.0.0.1
\ No newline at end of file
+org.onap.dmaap.datarouter.provserver.localhost             = 127.0.0.1
+org.onap.dmaap.datarouter.provserver.passwordencryption    = PasswordEncryptionKey#@$%^&1234#
\ No newline at end of file