Update project structure to org.onap
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / NodeConfig.java
diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java
new file mode 100644 (file)
index 0000000..c196d46
--- /dev/null
@@ -0,0 +1,722 @@
+/*******************************************************************************\r
+ * ============LICENSE_START==================================================\r
+ * * org.onap.dmaap\r
+ * * ===========================================================================\r
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * * ===========================================================================\r
+ * * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * * you may not use this file except in compliance with the License.\r
+ * * You may obtain a copy of the License at\r
+ * * \r
+ *  *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * * \r
+ *  * Unless required by applicable law or agreed to in writing, software\r
+ * * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * * See the License for the specific language governing permissions and\r
+ * * limitations under the License.\r
+ * * ============LICENSE_END====================================================\r
+ * *\r
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
+ * *\r
+ ******************************************************************************/\r
+\r
+\r
+package org.onap.dmaap.datarouter.node;\r
+\r
+import java.util.*;\r
+import java.io.*;\r
+\r
+/**\r
+ *     Processed configuration for this node.\r
+ *     <p>\r
+ *     The NodeConfig represents a processed configuration from the Data Router\r
+ *     provisioning server.  Each time configuration data is received from the\r
+ *     provisioning server, a new NodeConfig is created and the previous one\r
+ *     discarded.\r
+ */\r
+public class NodeConfig        {\r
+       /**\r
+        *      Raw configuration entry for a data router node\r
+        */\r
+       public static class ProvNode {\r
+               private String cname;\r
+               /**\r
+                *      Construct a node configuration entry.\r
+                *      @param cname    The cname of the node.\r
+                */\r
+               public ProvNode(String cname) {\r
+                       this.cname = cname;\r
+               }\r
+               /**\r
+                *      Get the cname of the node\r
+                */\r
+               public String getCName() {\r
+                       return(cname);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for a provisioning parameter\r
+        */\r
+       public static class ProvParam {\r
+               private String name;\r
+               private String value;\r
+               /**\r
+                *      Construct a provisioning parameter configuration entry.\r
+                *      @param  name The name of the parameter.\r
+                *      @param  value The value of the parameter.\r
+                */\r
+               public ProvParam(String name, String value) {\r
+                       this.name = name;\r
+                       this.value = value;\r
+               }\r
+               /**\r
+                *      Get the name of the parameter.\r
+                */\r
+               public String getName() {\r
+                       return(name);\r
+               }\r
+               /**\r
+                *      Get the value of the parameter.\r
+                */\r
+               public String getValue() {\r
+                       return(value);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for a data feed.\r
+        */\r
+       public static class ProvFeed {\r
+               private String id;\r
+               private String logdata;\r
+               private String status;\r
+               /**\r
+                *      Construct a feed configuration entry.\r
+                *      @param id       The feed ID of the entry.\r
+                *      @param logdata  String for log entries about the entry.\r
+                *      @param status   The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or null if it is valid.\r
+                */\r
+               public ProvFeed(String id, String logdata, String status) {\r
+                       this.id = id;\r
+                       this.logdata = logdata;\r
+                       this.status = status;\r
+               }\r
+               /**\r
+                *      Get the feed id of the data feed.\r
+                */\r
+               public String getId() {\r
+                       return(id);\r
+               }\r
+               /**\r
+                *      Get the log data of the data feed.\r
+                */\r
+               public String getLogData() {\r
+                       return(logdata);\r
+               }\r
+               /**\r
+                *      Get the status of the data feed.\r
+                */\r
+               public String getStatus() {\r
+                       return(status);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for a feed user.\r
+        */\r
+       public static class ProvFeedUser        {\r
+               private String feedid;\r
+               private String user;\r
+               private String credentials;\r
+               /**\r
+                *      Construct a feed user configuration entry\r
+                *      @param feedid   The feed id.\r
+                *      @param user     The user that will publish to the feed.\r
+                *      @param credentials      The Authorization header the user will use to publish.\r
+                */\r
+               public ProvFeedUser(String feedid, String user, String credentials) {\r
+                       this.feedid = feedid;\r
+                       this.user = user;\r
+                       this.credentials = credentials;\r
+               }\r
+               /**\r
+                *      Get the feed id of the feed user.\r
+                */\r
+               public String getFeedId() {\r
+                       return(feedid);\r
+               }\r
+               /**\r
+                *      Get the user for the feed user.\r
+                */\r
+               public String getUser() {\r
+                       return(user);\r
+               }\r
+               /**\r
+                *      Get the credentials for the feed user.\r
+                */\r
+               public String getCredentials() {\r
+                       return(credentials);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for a feed subnet\r
+        */\r
+       public static class ProvFeedSubnet      {\r
+               private String feedid;\r
+               private String cidr;\r
+               /**\r
+                *      Construct a feed subnet configuration entry\r
+                *      @param feedid   The feed ID\r
+                *      @param cidr     The CIDR allowed to publish to the feed.\r
+                */\r
+               public ProvFeedSubnet(String feedid, String cidr) {\r
+                       this.feedid = feedid;\r
+                       this.cidr = cidr;\r
+               }\r
+               /**\r
+                *      Get the feed id of the feed subnet.\r
+                */\r
+               public String getFeedId() {\r
+                       return(feedid);\r
+               }\r
+               /**\r
+                *      Get the CIDR of the feed subnet.\r
+                */\r
+               public String getCidr() {\r
+                       return(cidr);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for a subscription\r
+        */\r
+       public static class ProvSubscription    {\r
+               private String  subid;\r
+               private String  feedid;\r
+               private String  url;\r
+               private String  authuser;\r
+               private String  credentials;\r
+               private boolean metaonly;\r
+               private boolean use100;\r
+               /**\r
+                *      Construct a subscription configuration entry\r
+                *      @param subid    The subscription ID\r
+                *      @param feedid   The feed ID\r
+                *      @param url      The base delivery URL (not including the fileid)\r
+                *      @param authuser The user in the credentials used to deliver\r
+                *      @param credentials      The credentials used to authenticate to the delivery URL exactly as they go in the Authorization header.\r
+                *      @param metaonly Is this a meta data only subscription?\r
+                *      @param use100   Should we send Expect: 100-continue?\r
+                */\r
+               public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, boolean metaonly, boolean use100) {\r
+                       this.subid = subid;\r
+                       this.feedid = feedid;\r
+                       this.url = url;\r
+                       this.authuser = authuser;\r
+                       this.credentials = credentials;\r
+                       this.metaonly = metaonly;\r
+                       this.use100 = use100;\r
+               }\r
+               /**\r
+                *      Get the subscription ID\r
+                */\r
+               public String getSubId() {\r
+                       return(subid);\r
+               }\r
+               /**\r
+                *      Get the feed ID\r
+                */\r
+               public String getFeedId() {\r
+                       return(feedid);\r
+               }\r
+               /**\r
+                *      Get the delivery URL\r
+                */\r
+               public String getURL() {\r
+                       return(url);\r
+               }\r
+               /**\r
+                *      Get the user\r
+                */\r
+               public String getAuthUser() {\r
+                       return(authuser);\r
+               }\r
+               /**\r
+                *      Get the delivery credentials\r
+                */\r
+               public String getCredentials() {\r
+                       return(credentials);\r
+               }\r
+               /**\r
+                *      Is this a meta data only subscription?\r
+                */\r
+               public boolean isMetaDataOnly() {\r
+                       return(metaonly);\r
+               }\r
+               /**\r
+                *      Should we send Expect: 100-continue?\r
+                */\r
+               public boolean isUsing100() {\r
+                       return(use100);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for controlled ingress to the data router node\r
+        */\r
+       public static class ProvForceIngress    {\r
+               private String feedid;\r
+               private String subnet;\r
+               private String user;\r
+               private String[] nodes;\r
+               /**\r
+                *      Construct a forced ingress configuration entry\r
+                *      @param feedid   The feed ID that this entry applies to\r
+                *      @param subnet   The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all publisher IP addresses\r
+                *      @param user     The publishing user this entry applies to or "" if it applies to all publishing users.\r
+                *      @param nodes    The array of FQDNs of the data router nodes to redirect publication attempts to.\r
+                */\r
+               public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) {\r
+                       this.feedid = feedid;\r
+                       this.subnet = subnet;\r
+                       this.user = user;\r
+                       this.nodes = nodes;\r
+               }\r
+               /**\r
+                *      Get the feed ID\r
+                */\r
+               public String getFeedId() {\r
+                       return(feedid);\r
+               }\r
+               /**\r
+                *      Get the subnet\r
+                */\r
+               public String getSubnet() {\r
+                       return(subnet);\r
+               }\r
+               /**\r
+                *      Get the user\r
+                */\r
+               public String getUser() {\r
+                       return(user);\r
+               }\r
+               /**\r
+                *      Get the node\r
+                */\r
+               public String[] getNodes() {\r
+                       return(nodes);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for controlled egress from the data router\r
+        */\r
+       public static class ProvForceEgress     {\r
+               private String subid;\r
+               private String node;\r
+               /**\r
+                *      Construct a forced egress configuration entry\r
+                *      @param subid    The subscription ID the subscription with forced egress\r
+                *      @param node     The node handling deliveries for this subscription\r
+                */\r
+               public ProvForceEgress(String subid, String node) {\r
+                       this.subid = subid;\r
+                       this.node = node;\r
+               }\r
+               /**\r
+                *      Get the subscription ID\r
+                */\r
+               public String getSubId() {\r
+                       return(subid);\r
+               }\r
+               /**\r
+                *      Get the node\r
+                */\r
+               public String getNode() {\r
+                       return(node);\r
+               }\r
+       }\r
+       /**\r
+        *      Raw configuration entry for routing within the data router network\r
+        */\r
+       public static class ProvHop     {\r
+               private String  from;\r
+               private String  to;\r
+               private String  via;\r
+               /**\r
+                *      A human readable description of this entry\r
+                */\r
+               public String toString() {\r
+                       return("Hop " + from + "->" + to + " via " + via);\r
+               }\r
+               /**\r
+                *      Construct a hop entry\r
+                *      @param from     The FQDN of the node with the data to be delivered\r
+                *      @param to       The FQDN of the node that will deliver to the subscriber\r
+                *      @param via      The FQDN of the node where the from node should send the data\r
+                */\r
+               public ProvHop(String from, String to, String via) {\r
+                       this.from = from;\r
+                       this.to = to;\r
+                       this.via = via;\r
+               }\r
+               /**\r
+                *      Get the from node\r
+                */\r
+               public String getFrom() {\r
+                       return(from);\r
+               }\r
+               /**\r
+                *      Get the to node\r
+                */\r
+               public String getTo() {\r
+                       return(to);\r
+               }\r
+               /**\r
+                *      Get the next intermediate node\r
+                */\r
+               public String getVia() {\r
+                       return(via);\r
+               }\r
+       }\r
+       private static class Redirection        {\r
+               public SubnetMatcher snm;\r
+               public String user;\r
+               public String[] nodes;\r
+       }\r
+       private static class Feed       {\r
+               public String   loginfo;\r
+               public String   status;\r
+               public SubnetMatcher[] subnets;\r
+               public Hashtable<String, String> authusers = new Hashtable<String, String>();\r
+               public Redirection[]    redirections;\r
+               public Target[] targets;\r
+       }\r
+       private Hashtable<String, String> params = new Hashtable<String, String>();\r
+       private Hashtable<String, Feed> feeds = new Hashtable<String, Feed>();\r
+       private Hashtable<String, DestInfo> nodeinfo = new Hashtable<String, DestInfo>();\r
+       private Hashtable<String, DestInfo> subinfo = new Hashtable<String, DestInfo>();\r
+       private Hashtable<String, IsFrom> nodes = new Hashtable<String, IsFrom>();\r
+       private String  myname;\r
+       private String  myauth;\r
+       private DestInfo[]      alldests;\r
+       private int     rrcntr;\r
+       /**\r
+        *      Process the raw provisioning data to configure this node\r
+        *      @param pd       The parsed provisioning data\r
+        *      @param myname   My name as seen by external systems\r
+        *      @param spooldir The directory where temporary files live\r
+        *      @param port     The port number for URLs\r
+        *      @param nodeauthkey      The keying string used to generate node authentication credentials\r
+        */\r
+       public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) {\r
+               this.myname = myname;\r
+               for (ProvParam p: pd.getParams()) {\r
+                       params.put(p.getName(), p.getValue());\r
+               }\r
+               Vector<DestInfo>        div = new Vector<DestInfo>();\r
+               myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey);\r
+               for (ProvNode pn: pd.getNodes()) {\r
+                       String cn = pn.getCName();\r
+                       if (nodeinfo.get(cn) != null) {\r
+                               continue;\r
+                       }\r
+                       String auth = NodeUtils.getNodeAuthHdr(cn, nodeauthkey);\r
+                       DestInfo di = new DestInfo("n:" + cn, spooldir + "/n/" + cn, null, "n2n-" + cn, "https://" + cn + ":" + port + "/internal/publish", cn, myauth, false, true);\r
+                       (new File(di.getSpool())).mkdirs();\r
+                       div.add(di);\r
+                       nodeinfo.put(cn, di);\r
+                       nodes.put(auth, new IsFrom(cn));\r
+               }\r
+               PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[nodeinfo.size()]), pd.getHops());\r
+               Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<String, Vector<Redirection>>();\r
+               for (ProvForceIngress pfi: pd.getForceIngress()) {\r
+                       Vector<Redirection> v = rdtab.get(pfi.getFeedId());\r
+                       if (v == null) {\r
+                               v = new Vector<Redirection>();\r
+                               rdtab.put(pfi.getFeedId(), v);\r
+                       }\r
+                       Redirection r = new Redirection();\r
+                       if (pfi.getSubnet() != null) {\r
+                               r.snm = new SubnetMatcher(pfi.getSubnet());\r
+                       }\r
+                       r.user = pfi.getUser();\r
+                       r.nodes = pfi.getNodes();\r
+                       v.add(r);\r
+               }\r
+               Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<String, Hashtable<String, String>>();\r
+               for (ProvFeedUser pfu: pd.getFeedUsers()) {\r
+                       Hashtable<String, String> t = pfutab.get(pfu.getFeedId());\r
+                       if (t == null) {\r
+                               t = new Hashtable<String, String>();\r
+                               pfutab.put(pfu.getFeedId(), t);\r
+                       }\r
+                       t.put(pfu.getCredentials(), pfu.getUser());\r
+               }\r
+               Hashtable<String, String> egrtab = new Hashtable<String, String>();\r
+               for (ProvForceEgress pfe: pd.getForceEgress()) {\r
+                       if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) {\r
+                               continue;\r
+                       }\r
+                       egrtab.put(pfe.getSubId(), pfe.getNode());\r
+               }\r
+               Hashtable<String, Vector<SubnetMatcher>> pfstab = new Hashtable<String, Vector<SubnetMatcher>>();\r
+               for (ProvFeedSubnet pfs: pd.getFeedSubnets()) {\r
+                       Vector<SubnetMatcher> v = pfstab.get(pfs.getFeedId());\r
+                       if (v == null) {\r
+                               v = new Vector<SubnetMatcher>();\r
+                               pfstab.put(pfs.getFeedId(), v);\r
+                       }\r
+                       v.add(new SubnetMatcher(pfs.getCidr()));\r
+               }\r
+               Hashtable<String, StringBuffer> ttab = new Hashtable<String, StringBuffer>();\r
+               HashSet<String> allfeeds = new HashSet<String>();\r
+               for (ProvFeed pfx: pd.getFeeds()) {\r
+                       if (pfx.getStatus() == null) {\r
+                               allfeeds.add(pfx.getId());\r
+                       }\r
+               }\r
+               for (ProvSubscription ps: pd.getSubscriptions()) {\r
+                       String sid = ps.getSubId();\r
+                       String fid = ps.getFeedId();\r
+                       if (!allfeeds.contains(fid)) {\r
+                               continue;\r
+                       }\r
+                       if (subinfo.get(sid) != null) {\r
+                               continue;\r
+                       }\r
+                       int sididx = 999;\r
+                       try {\r
+                               sididx = Integer.parseInt(sid);\r
+                               sididx -= sididx % 100;\r
+                       } catch (Exception e) {\r
+                       }\r
+                       String siddir = sididx + "/" + sid;\r
+                       DestInfo di = new DestInfo("s:" + sid, spooldir + "/s/" + siddir, sid, fid, ps.getURL(), ps.getAuthUser(), ps.getCredentials(), ps.isMetaDataOnly(), ps.isUsing100());\r
+                       (new File(di.getSpool())).mkdirs();\r
+                       div.add(di);\r
+                       subinfo.put(sid, di);\r
+                       String egr = egrtab.get(sid);\r
+                       if (egr != null) {\r
+                               sid = pf.getPath(egr) + sid;\r
+                       }\r
+                       StringBuffer sb = ttab.get(fid);\r
+                       if (sb == null) {\r
+                               sb = new StringBuffer();\r
+                               ttab.put(fid, sb);\r
+                       }\r
+                       sb.append(' ').append(sid);\r
+               }\r
+               alldests = div.toArray(new DestInfo[div.size()]);\r
+               for (ProvFeed pfx: pd.getFeeds()) {\r
+                       String fid = pfx.getId();\r
+                       Feed f = feeds.get(fid);\r
+                       if (f != null) {\r
+                               continue;\r
+                       }\r
+                       f = new Feed();\r
+                       feeds.put(fid, f);\r
+                       f.loginfo = pfx.getLogData();\r
+                       f.status = pfx.getStatus();\r
+                       Vector<SubnetMatcher> v1 = pfstab.get(fid);\r
+                       if (v1 == null) {\r
+                               f.subnets = new SubnetMatcher[0];\r
+                       } else {\r
+                               f.subnets = v1.toArray(new SubnetMatcher[v1.size()]);\r
+                       }\r
+                       Hashtable<String, String> h1 = pfutab.get(fid);\r
+                       if (h1 == null) {\r
+                               h1 = new Hashtable<String, String>();\r
+                       }\r
+                       f.authusers = h1;\r
+                       Vector<Redirection> v2 = rdtab.get(fid);\r
+                       if (v2 == null) {\r
+                               f.redirections = new Redirection[0];\r
+                       } else {\r
+                               f.redirections = v2.toArray(new Redirection[v2.size()]);\r
+                       }\r
+                       StringBuffer sb = ttab.get(fid);\r
+                       if (sb == null) {\r
+                               f.targets = new Target[0];\r
+                       } else {\r
+                               f.targets = parseRouting(sb.toString());\r
+                       }\r
+               }\r
+       }\r
+       /**\r
+        *      Parse a target string into an array of targets\r
+        *      @param routing Target string\r
+        *      @return Array of targets.\r
+        */\r
+       public Target[] parseRouting(String routing) {\r
+               routing = routing.trim();\r
+               if ("".equals(routing)) {\r
+                       return(new Target[0]);\r
+               }\r
+               String[] xx = routing.split("\\s+");\r
+               Hashtable<String, Target> tmap = new Hashtable<String, Target>();\r
+               HashSet<String> subset = new HashSet<String>();\r
+               Vector<Target> tv = new Vector<Target>();\r
+               Target[] ret = new Target[xx.length];\r
+               for (int i = 0; i < xx.length; i++) {\r
+                       String t = xx[i];\r
+                       int j = t.indexOf('/');\r
+                       if (j == -1) {\r
+                               DestInfo di = subinfo.get(t);\r
+                               if (di == null) {\r
+                                       tv.add(new Target(null, t));\r
+                               } else {\r
+                                       if (!subset.contains(t)) {\r
+                                               subset.add(t);\r
+                                               tv.add(new Target(di, null));\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               String node = t.substring(0, j);\r
+                               String rtg = t.substring(j + 1);\r
+                               DestInfo di = nodeinfo.get(node);\r
+                               if (di == null) {\r
+                                       tv.add(new Target(null, t));\r
+                               } else {\r
+                                       Target tt = tmap.get(node);\r
+                                       if (tt == null) {\r
+                                               tt = new Target(di, rtg);\r
+                                               tmap.put(node, tt);\r
+                                               tv.add(tt);\r
+                                       } else {\r
+                                               tt.addRouting(rtg);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               return(tv.toArray(new Target[tv.size()]));\r
+       }\r
+       /**\r
+        *      Check whether this is a valid node-to-node transfer\r
+        *      @param credentials      Credentials offered by the supposed node\r
+        *      @param ip       IP address the request came from\r
+        */\r
+       public boolean isAnotherNode(String credentials, String ip) {\r
+               IsFrom n = nodes.get(credentials);\r
+               return (n != null && n.isFrom(ip));\r
+       }\r
+       /**\r
+        *      Check whether publication is allowed.\r
+        *      @param feedid   The ID of the feed being requested.\r
+        *      @param credentials      The offered credentials\r
+        *      @param ip       The requesting IP address\r
+        */\r
+       public String isPublishPermitted(String feedid, String credentials, String ip) {\r
+               Feed f = feeds.get(feedid);\r
+               String nf = "Feed does not exist";\r
+               if (f != null) {\r
+                       nf = f.status;\r
+               }\r
+               if (nf != null) {\r
+                       return(nf);\r
+               }\r
+               String user = f.authusers.get(credentials);\r
+               if (user == null) {\r
+                       return("Publisher not permitted for this feed");\r
+               }\r
+               if (f.subnets.length == 0) {\r
+                       return(null);\r
+               }\r
+               byte[] addr = NodeUtils.getInetAddress(ip);\r
+               for (SubnetMatcher snm: f.subnets) {\r
+                       if (snm.matches(addr)) {\r
+                               return(null);\r
+                       }\r
+               }\r
+               return("Publisher not permitted for this feed");\r
+       }\r
+       /**\r
+        *      Get authenticated user\r
+        */\r
+       public String getAuthUser(String feedid, String credentials) {\r
+               return(feeds.get(feedid).authusers.get(credentials));\r
+       }\r
+       /**\r
+        *      Check if the request should be redirected to a different ingress node\r
+        */\r
+       public String getIngressNode(String feedid, String user, String ip) {\r
+               Feed f = feeds.get(feedid);\r
+               if (f.redirections.length == 0) {\r
+                       return(null);\r
+               }\r
+               byte[] addr = NodeUtils.getInetAddress(ip);\r
+               for (Redirection r: f.redirections) {\r
+                       if (r.user != null && !user.equals(r.user)) {\r
+                               continue;\r
+                       }\r
+                       if (r.snm != null && !r.snm.matches(addr)) {\r
+                               continue;\r
+                       }\r
+                       for (String n: r.nodes) {\r
+                               if (myname.equals(n)) {\r
+                                       return(null);\r
+                               }\r
+                       }\r
+                       if (r.nodes.length == 0) {\r
+                               return(null);\r
+                       }\r
+                       return(r.nodes[rrcntr++ % r.nodes.length]);\r
+               }\r
+               return(null);\r
+       }\r
+       /**\r
+        *      Get a provisioned configuration parameter\r
+        */\r
+       public String getProvParam(String name) {\r
+               return(params.get(name));\r
+       }\r
+       /**\r
+        *      Get all the DestInfos\r
+        */\r
+       public DestInfo[]       getAllDests() {\r
+               return(alldests);\r
+       }\r
+       /**\r
+        *      Get the targets for a feed\r
+        *      @param feedid   The feed ID\r
+        *      @return The targets this feed should be delivered to\r
+        */\r
+       public Target[] getTargets(String feedid) {\r
+               if (feedid == null) {\r
+                       return(new Target[0]);\r
+               }\r
+               Feed f = feeds.get(feedid);\r
+               if (f == null) {\r
+                       return(new Target[0]);\r
+               }\r
+               return(f.targets);\r
+       }\r
+       /**\r
+        *      Get the feed ID for a subscription\r
+        *      @param subid    The subscription ID\r
+        *      @return The feed ID\r
+        */\r
+       public String getFeedId(String subid) {\r
+               DestInfo di = subinfo.get(subid);\r
+               if (di == null) {\r
+                       return(null);\r
+               }\r
+               return(di.getLogData());\r
+       }\r
+       /**\r
+        *      Get the spool directory for a subscription\r
+        *      @param subid    The subscription ID\r
+        *      @return The spool directory\r
+        */\r
+       public String getSpoolDir(String subid) {\r
+               DestInfo di = subinfo.get(subid);\r
+               if (di == null) {\r
+                       return(null);\r
+               }\r
+               return(di.getSpool());\r
+       }\r
+       /**\r
+        *      Get the Authorization value this node uses\r
+        *      @return The Authorization header value for this node\r
+        */\r
+       public String getMyAuth() {\r
+               return(myauth);\r
+       }\r
+\r
+}\r