update DR logging to log under one system
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / NodeConfig.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * * ===========================================================================
7  * * Licensed under the Apache License, Version 2.0 (the "License");
8  * * you may not use this file except in compliance with the License.
9  * * You may obtain a copy of the License at
10  * *
11  *  *      http://www.apache.org/licenses/LICENSE-2.0
12  * *
13  *  * Unless required by applicable law or agreed to in writing, software
14  * * distributed under the License is distributed on an "AS IS" BASIS,
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * * See the License for the specific language governing permissions and
17  * * limitations under the License.
18  * * ============LICENSE_END====================================================
19  * *
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.node;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29
30 import java.io.File;
31 import java.util.Arrays;
32 import java.util.HashSet;
33 import java.util.Hashtable;
34 import java.util.Vector;
35
36 /**
37  * Processed configuration for this node.
38  * <p>
39  * The NodeConfig represents a processed configuration from the Data Router provisioning server.  Each time
40  * configuration data is received from the provisioning server, a new NodeConfig is created and the previous one
41  * discarded.
42  */
43 public class NodeConfig {
44     private static EELFLogger logger = EELFManager.getInstance().getLogger(NodeConfig.class);
45     /**
46      * Raw configuration entry for a data router node
47      */
48     public static class ProvNode {
49
50         private String cname;
51
52         /**
53          * Construct a node configuration entry.
54          *
55          * @param cname The cname of the node.
56          */
57         public ProvNode(String cname) {
58             this.cname = cname;
59         }
60
61         /**
62          * Get the cname of the node
63          */
64         public String getCName() {
65             return (cname);
66         }
67     }
68
69     /**
70      * Raw configuration entry for a provisioning parameter
71      */
72     public static class ProvParam {
73
74         private String name;
75         private String value;
76
77         /**
78          * Construct a provisioning parameter configuration entry.
79          *
80          * @param name The name of the parameter.
81          * @param value The value of the parameter.
82          */
83         public ProvParam(String name, String value) {
84             this.name = name;
85             this.value = value;
86         }
87
88         /**
89          * Get the name of the parameter.
90          */
91         public String getName() {
92             return (name);
93         }
94
95         /**
96          * Get the value of the parameter.
97          */
98         public String getValue() {
99             return (value);
100         }
101     }
102
103     /**
104      * Raw configuration entry for a data feed.
105      */
106     public static class ProvFeed {
107
108         private String id;
109         private String logdata;
110         private String status;
111         private String createdDate;
112         /*
113          * AAF changes: TDP EPIC US# 307413
114          * Passing aafInstance from to identify legacy/AAF feeds
115          */
116         private String aafInstance;
117
118         /**
119          * Construct a feed configuration entry.
120          *
121          * @param id The feed ID of the entry.
122          * @param logdata String for log entries about the entry.
123          * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or
124          * null if it is valid.
125          */
126         public ProvFeed(String id, String logdata, String status, String createdDate, String aafInstance) {
127             this.id = id;
128             this.logdata = logdata;
129             this.status = status;
130             this.createdDate = createdDate;
131             this.aafInstance = aafInstance;
132         }
133
134         /**
135          * Get the created date of the data feed.
136          */
137         public String getCreatedDate()
138         {
139             return(createdDate);
140         }
141
142         /**
143          * Get the aafInstance of the data feed.
144          */
145         public String getAafInstance() {
146             return aafInstance;
147         }
148
149         /**
150          * Get the feed id of the data feed.
151          */
152         public String getId() {
153             return (id);
154         }
155
156         /**
157          * Get the log data of the data feed.
158          */
159         public String getLogData() {
160             return (logdata);
161         }
162
163         /**
164          * Get the status of the data feed.
165          */
166         public String getStatus() {
167             return (status);
168         }
169     }
170
171     /**
172      * Raw configuration entry for a feed user.
173      */
174     public static class ProvFeedUser {
175
176         private String feedid;
177         private String user;
178         private String credentials;
179
180         /**
181          * Construct a feed user configuration entry
182          *
183          * @param feedid The feed id.
184          * @param user The user that will publish to the feed.
185          * @param credentials The Authorization header the user will use to publish.
186          */
187         public ProvFeedUser(String feedid, String user, String credentials) {
188             this.feedid = feedid;
189             this.user = user;
190             this.credentials = credentials;
191         }
192
193         /**
194          * Get the feed id of the feed user.
195          */
196         public String getFeedId() {
197             return (feedid);
198         }
199
200         /**
201          * Get the user for the feed user.
202          */
203         public String getUser() {
204             return (user);
205         }
206
207         /**
208          * Get the credentials for the feed user.
209          */
210         public String getCredentials() {
211             return (credentials);
212         }
213     }
214
215     /**
216      * Raw configuration entry for a feed subnet
217      */
218     public static class ProvFeedSubnet {
219
220         private String feedid;
221         private String cidr;
222
223         /**
224          * Construct a feed subnet configuration entry
225          *
226          * @param feedid The feed ID
227          * @param cidr The CIDR allowed to publish to the feed.
228          */
229         public ProvFeedSubnet(String feedid, String cidr) {
230             this.feedid = feedid;
231             this.cidr = cidr;
232         }
233
234         /**
235          * Get the feed id of the feed subnet.
236          */
237         public String getFeedId() {
238             return (feedid);
239         }
240
241         /**
242          * Get the CIDR of the feed subnet.
243          */
244         public String getCidr() {
245             return (cidr);
246         }
247     }
248
249     /**
250      * Raw configuration entry for a subscription
251      */
252     public static class ProvSubscription {
253
254         private String subid;
255         private String feedid;
256         private String url;
257         private String authuser;
258         private String credentials;
259         private boolean metaonly;
260         private boolean use100;
261         private boolean privilegedSubscriber;
262         private boolean followRedirect;
263         private boolean decompress;
264
265         /**
266          * Construct a subscription configuration entry
267          *
268          * @param subid The subscription ID
269          * @param feedid The feed ID
270          * @param url The base delivery URL (not including the fileid)
271          * @param authuser The user in the credentials used to deliver
272          * @param credentials The credentials used to authenticate to the delivery URL exactly as they go in the
273          * Authorization header.
274          * @param metaonly Is this a meta data only subscription?
275          * @param use100 Should we send Expect: 100-continue?
276          * @param privilegedSubscriber Can we wait to receive a delete file call before deleting file
277          * @param followRedirect Is follow redirect of destination enabled?
278          * @param decompress To see if they want their information compressed or decompressed
279          */
280         public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean followRedirect, boolean decompress) {
281             this.subid = subid;
282             this.feedid = feedid;
283             this.url = url;
284             this.authuser = authuser;
285             this.credentials = credentials;
286             this.metaonly = metaonly;
287             this.use100 = use100;
288             this.privilegedSubscriber = privilegedSubscriber;
289             this.followRedirect = followRedirect;
290             this.decompress = decompress;
291         }
292
293         /**
294          * Get the subscription ID
295          */
296         public String getSubId() {
297             return (subid);
298         }
299
300         /**
301          * Get the feed ID
302          */
303         public String getFeedId() {
304             return (feedid);
305         }
306
307         /**
308          * Get the delivery URL
309          */
310         public String getURL() {
311             return (url);
312         }
313
314         /**
315          * Get the user
316          */
317         public String getAuthUser() {
318             return (authuser);
319         }
320
321         /**
322          * Get the delivery credentials
323          */
324         public String getCredentials() {
325             return (credentials);
326         }
327
328         /**
329          * Is this a meta data only subscription?
330          */
331         public boolean isMetaDataOnly() {
332             return (metaonly);
333         }
334
335         /**
336          * Should we send Expect: 100-continue?
337          */
338         public boolean isUsing100() {
339             return (use100);
340         }
341
342         /**
343          * Can we wait to receive a delete file call before deleting file
344          */
345         public boolean isPrivilegedSubscriber() {
346             return (privilegedSubscriber);
347         }
348
349         /**
350          * Should i decompress the file before sending it on
351         */
352         public boolean isDecompress() {
353             return (decompress);
354         }
355
356         /**
357          *  New field is added - FOLLOW_REDIRECTS feature iTrack:DATARTR-17 - 1706
358          *      Get the followRedirect of this destination
359          */
360         boolean getFollowRedirect() {
361             return(followRedirect);
362         }
363     }
364
365     /**
366      * Raw configuration entry for controlled ingress to the data router node
367      */
368     public static class ProvForceIngress {
369
370         private String feedid;
371         private String subnet;
372         private String user;
373         private String[] nodes;
374
375         /**
376          * Construct a forced ingress configuration entry
377          *
378          * @param feedid The feed ID that this entry applies to
379          * @param subnet The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all
380          * publisher IP addresses
381          * @param user The publishing user this entry applies to or "" if it applies to all publishing users.
382          * @param nodes The array of FQDNs of the data router nodes to redirect publication attempts to.
383          */
384         public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) {
385             this.feedid = feedid;
386             this.subnet = subnet;
387             this.user = user;
388             //Sonar fix
389             if(nodes == null) {
390                 this.nodes = new String[0];
391             } else {
392                 this.nodes = Arrays.copyOf(nodes, nodes.length);
393             }
394         }
395
396         /**
397          * Get the feed ID
398          */
399         public String getFeedId() {
400             return (feedid);
401         }
402
403         /**
404          * Get the subnet
405          */
406         public String getSubnet() {
407             return (subnet);
408         }
409
410         /**
411          * Get the user
412          */
413         public String getUser() {
414             return (user);
415         }
416
417         /**
418          * Get the node
419          */
420         public String[] getNodes() {
421             return (nodes);
422         }
423     }
424
425     /**
426      * Raw configuration entry for controlled egress from the data router
427      */
428     public static class ProvForceEgress {
429
430         private String subid;
431         private String node;
432
433         /**
434          * Construct a forced egress configuration entry
435          *
436          * @param subid The subscription ID the subscription with forced egress
437          * @param node The node handling deliveries for this subscription
438          */
439         public ProvForceEgress(String subid, String node) {
440             this.subid = subid;
441             this.node = node;
442         }
443
444         /**
445          * Get the subscription ID
446          */
447         public String getSubId() {
448             return (subid);
449         }
450
451         /**
452          * Get the node
453          */
454         public String getNode() {
455             return (node);
456         }
457     }
458
459     /**
460      * Raw configuration entry for routing within the data router network
461      */
462     public static class ProvHop {
463
464         private String from;
465         private String to;
466         private String via;
467
468         /**
469          * A human readable description of this entry
470          */
471         public String toString() {
472             return ("Hop " + from + "->" + to + " via " + via);
473         }
474
475         /**
476          * Construct a hop entry
477          *
478          * @param from The FQDN of the node with the data to be delivered
479          * @param to The FQDN of the node that will deliver to the subscriber
480          * @param via The FQDN of the node where the from node should send the data
481          */
482         public ProvHop(String from, String to, String via) {
483             this.from = from;
484             this.to = to;
485             this.via = via;
486         }
487
488         /**
489          * Get the from node
490          */
491         public String getFrom() {
492             return (from);
493         }
494
495         /**
496          * Get the to node
497          */
498         public String getTo() {
499             return (to);
500         }
501
502         /**
503          * Get the next intermediate node
504          */
505         public String getVia() {
506             return (via);
507         }
508     }
509
510     private static class Redirection {
511
512         SubnetMatcher snm;
513         String user;
514         String[] nodes;
515     }
516
517     private static class Feed {
518
519         String loginfo;
520         String status;
521         SubnetMatcher[] subnets;
522         Hashtable<String, String> authusers = new Hashtable<String, String>();
523         Redirection[] redirections;
524         Target[] targets;
525         String createdDate;
526         String aafInstance;
527     }
528
529     private Hashtable<String, String> params = new Hashtable<>();
530     private Hashtable<String, Feed> feeds = new Hashtable<>();
531     private Hashtable<String, DestInfo> nodeinfo = new Hashtable<>();
532     private Hashtable<String, DestInfo> subinfo = new Hashtable<>();
533     private Hashtable<String, IsFrom> nodes = new Hashtable<>();
534     private Hashtable<String, ProvSubscription> provSubscriptions = new Hashtable<>();
535     private String myname;
536     private String myauth;
537     private DestInfo[] alldests;
538     private int rrcntr;
539
540     /**
541      * Process the raw provisioning data to configure this node
542      *
543      * @param pd The parsed provisioning data
544      * @param myname My name as seen by external systems
545      * @param spooldir The directory where temporary files live
546      * @param port The port number for URLs
547      * @param nodeauthkey The keying string used to generate node authentication credentials
548      */
549     public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) {
550         this.myname = myname;
551         for (ProvParam p : pd.getParams()) {
552             params.put(p.getName(), p.getValue());
553         }
554         Vector<DestInfo> destInfos = new Vector<>();
555         myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey);
556         for (ProvNode pn : pd.getNodes()) {
557             String cName = pn.getCName();
558             if (nodeinfo.get(cName) != null) {
559                 continue;
560             }
561             String auth = NodeUtils.getNodeAuthHdr(cName, nodeauthkey);
562             DestInfo di = new DestInfo("n:" + cName, spooldir + "/n/" + cName, null, "n2n-" + cName,
563                     "https://" + cName + ":" + port + "/internal/publish", cName, myauth, false, true, false, false, false);
564             (new File(di.getSpool())).mkdirs();
565             destInfos.add(di);
566             nodeinfo.put(cName, di);
567             nodes.put(auth, new IsFrom(cName));
568         }
569         PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[0]), pd.getHops());
570         Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<>();
571         for (ProvForceIngress pfi : pd.getForceIngress()) {
572             Vector<Redirection> v = rdtab.get(pfi.getFeedId());
573             if (v == null) {
574                 v = new Vector<>();
575                 rdtab.put(pfi.getFeedId(), v);
576             }
577             Redirection r = new Redirection();
578             if (pfi.getSubnet() != null) {
579                 r.snm = new SubnetMatcher(pfi.getSubnet());
580             }
581             r.user = pfi.getUser();
582             r.nodes = pfi.getNodes();
583             v.add(r);
584         }
585         Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<>();
586         for (ProvFeedUser pfu : pd.getFeedUsers()) {
587             Hashtable<String, String> t = pfutab.get(pfu.getFeedId());
588             if (t == null) {
589                 t = new Hashtable<>();
590                 pfutab.put(pfu.getFeedId(), t);
591             }
592             t.put(pfu.getCredentials(), pfu.getUser());
593         }
594         Hashtable<String, String> egrtab = new Hashtable<>();
595         for (ProvForceEgress pfe : pd.getForceEgress()) {
596             if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) {
597                 continue;
598             }
599             egrtab.put(pfe.getSubId(), pfe.getNode());
600         }
601         Hashtable<String, Vector<SubnetMatcher>> pfstab = new Hashtable<>();
602         for (ProvFeedSubnet pfs : pd.getFeedSubnets()) {
603             Vector<SubnetMatcher> v = pfstab.get(pfs.getFeedId());
604             if (v == null) {
605                 v = new Vector<>();
606                 pfstab.put(pfs.getFeedId(), v);
607             }
608             v.add(new SubnetMatcher(pfs.getCidr()));
609         }
610         Hashtable<String, StringBuffer> feedTargets = new Hashtable<>();
611         HashSet<String> allfeeds = new HashSet<>();
612         for (ProvFeed pfx : pd.getFeeds()) {
613             if (pfx.getStatus() == null) {
614                 allfeeds.add(pfx.getId());
615             }
616         }
617         for (ProvSubscription provSubscription : pd.getSubscriptions()) {
618             String subId = provSubscription.getSubId();
619             String feedId = provSubscription.getFeedId();
620             if (!allfeeds.contains(feedId)) {
621                 continue;
622             }
623             if (subinfo.get(subId) != null) {
624                 continue;
625             }
626             int sididx = 999;
627             try {
628                 sididx = Integer.parseInt(subId);
629                 sididx -= sididx % 100;
630             } catch (Exception e) {
631                 logger.error("NODE0517 Exception NodeConfig: "+e);
632             }
633             String subscriptionDirectory = sididx + "/" + subId;
634             DestInfo destinationInfo = new DestInfo("s:" + subId,
635                     spooldir + "/s/" + subscriptionDirectory, provSubscription);
636             (new File(destinationInfo.getSpool())).mkdirs();
637             destInfos.add(destinationInfo);
638             provSubscriptions.put(subId, provSubscription);
639             subinfo.put(subId, destinationInfo);
640             String egr = egrtab.get(subId);
641             if (egr != null) {
642                 subId = pf.getPath(egr) + subId;
643             }
644             StringBuffer sb = feedTargets.get(feedId);
645             if (sb == null) {
646                 sb = new StringBuffer();
647                 feedTargets.put(feedId, sb);
648             }
649             sb.append(' ').append(subId);
650         }
651         alldests = destInfos.toArray(new DestInfo[0]);
652         for (ProvFeed pfx : pd.getFeeds()) {
653             String fid = pfx.getId();
654             Feed f = feeds.get(fid);
655             if (f != null) {
656                 continue;
657             }
658             f = new Feed();
659             feeds.put(fid, f);
660             f.createdDate = pfx.getCreatedDate();
661             f.loginfo = pfx.getLogData();
662             f.status = pfx.getStatus();
663             /*
664              * AAF changes: TDP EPIC US# 307413
665              * Passing aafInstance from ProvFeed to identify legacy/AAF feeds
666              */
667             f.aafInstance = pfx.getAafInstance();
668             Vector<SubnetMatcher> v1 = pfstab.get(fid);
669             if (v1 == null) {
670                 f.subnets = new SubnetMatcher[0];
671             } else {
672                 f.subnets = v1.toArray(new SubnetMatcher[0]);
673             }
674             Hashtable<String, String> h1 = pfutab.get(fid);
675             if (h1 == null) {
676                 h1 = new Hashtable<String, String>();
677             }
678             f.authusers = h1;
679             Vector<Redirection> v2 = rdtab.get(fid);
680             if (v2 == null) {
681                 f.redirections = new Redirection[0];
682             } else {
683                 f.redirections = v2.toArray(new Redirection[0]);
684             }
685             StringBuffer sb = feedTargets.get(fid);
686             if (sb == null) {
687                 f.targets = new Target[0];
688             } else {
689                 f.targets = parseRouting(sb.toString());
690             }
691         }
692     }
693
694     /**
695      * Parse a target string into an array of targets
696      *
697      * @param routing Target string
698      * @return Array of targets.
699      */
700     public Target[] parseRouting(String routing) {
701         routing = routing.trim();
702         if ("".equals(routing)) {
703             return (new Target[0]);
704         }
705         String[] xx = routing.split("\\s+");
706         Hashtable<String, Target> tmap = new Hashtable<String, Target>();
707         HashSet<String> subset = new HashSet<String>();
708         Vector<Target> tv = new Vector<Target>();
709         Target[] ret = new Target[xx.length];
710         for (int i = 0; i < xx.length; i++) {
711             String t = xx[i];
712             int j = t.indexOf('/');
713             if (j == -1) {
714                 DestInfo di = subinfo.get(t);
715                 if (di == null) {
716                     tv.add(new Target(null, t));
717                 } else {
718                     if (!subset.contains(t)) {
719                         subset.add(t);
720                         tv.add(new Target(di, null));
721                     }
722                 }
723             } else {
724                 String node = t.substring(0, j);
725                 String rtg = t.substring(j + 1);
726                 DestInfo di = nodeinfo.get(node);
727                 if (di == null) {
728                     tv.add(new Target(null, t));
729                 } else {
730                     Target tt = tmap.get(node);
731                     if (tt == null) {
732                         tt = new Target(di, rtg);
733                         tmap.put(node, tt);
734                         tv.add(tt);
735                     } else {
736                         tt.addRouting(rtg);
737                     }
738                 }
739             }
740         }
741         return (tv.toArray(new Target[0]));
742     }
743
744     /**
745      * Check whether this is a valid node-to-node transfer
746      *
747      * @param credentials Credentials offered by the supposed node
748      * @param ip IP address the request came from
749      */
750     public boolean isAnotherNode(String credentials, String ip) {
751         IsFrom n = nodes.get(credentials);
752         return (n != null && n.isFrom(ip));
753     }
754
755     /**
756      * Check whether publication is allowed.
757      *
758      * @param feedid The ID of the feed being requested.
759      * @param credentials The offered credentials
760      * @param ip The requesting IP address
761      */
762     public String isPublishPermitted(String feedid, String credentials, String ip) {
763         Feed f = feeds.get(feedid);
764         String nf = "Feed does not exist";
765         if (f != null) {
766             nf = f.status;
767         }
768         if (nf != null) {
769             return (nf);
770         }
771         String user = f.authusers.get(credentials);
772         if (user == null) {
773             return ("Publisher not permitted for this feed");
774         }
775         if (f.subnets.length == 0) {
776             return (null);
777         }
778         byte[] addr = NodeUtils.getInetAddress(ip);
779         for (SubnetMatcher snm : f.subnets) {
780             if (snm.matches(addr)) {
781                 return (null);
782             }
783         }
784         return ("Publisher not permitted for this feed");
785     }
786
787     /**
788      * Check whether delete file is allowed.
789      *
790      * @param subId The ID of the subscription being requested.
791      */
792     public boolean isDeletePermitted(String subId) {
793         ProvSubscription provSubscription = provSubscriptions.get(subId);
794         return provSubscription.isPrivilegedSubscriber();
795     }
796
797     /**
798      * Check whether publication is allowed for AAF Feed.
799      * @param feedid The ID of the feed being requested.
800      * @param ip The requesting IP address
801      */
802     public String isPublishPermitted(String feedid, String ip) {
803         Feed f = feeds.get(feedid);
804         String nf = "Feed does not exist";
805         if (f != null) {
806             nf = f.status;
807         }
808         if (nf != null) {
809             return(nf);
810         }
811         if (f.subnets.length == 0) {
812             return(null);
813         }
814         byte[] addr = NodeUtils.getInetAddress(ip);
815         for (SubnetMatcher snm: f.subnets) {
816             if (snm.matches(addr)) {
817                 return(null);
818             }
819         }
820         return("Publisher not permitted for this feed");
821     }
822
823     /**
824      * Get authenticated user
825      */
826     public String getAuthUser(String feedid, String credentials) {
827         return (feeds.get(feedid).authusers.get(credentials));
828     }
829
830     /**
831      * AAF changes: TDP EPIC US# 307413
832      * Check AAF_instance for feed ID
833      * @param feedid    The ID of the feed specified
834      */
835     public String getAafInstance(String feedid) {
836         Feed f = feeds.get(feedid);
837         return f.aafInstance;
838     }
839
840     /**
841      * Check if the request should be redirected to a different ingress node
842      */
843     public String getIngressNode(String feedid, String user, String ip) {
844         Feed f = feeds.get(feedid);
845         if (f.redirections.length == 0) {
846             return (null);
847         }
848         byte[] addr = NodeUtils.getInetAddress(ip);
849         for (Redirection r : f.redirections) {
850             if (r.user != null && !user.equals(r.user)) {
851                 continue;
852             }
853             if (r.snm != null && !r.snm.matches(addr)) {
854                 continue;
855             }
856             for (String n : r.nodes) {
857                 if (myname.equals(n)) {
858                     return (null);
859                 }
860             }
861             if (r.nodes.length == 0) {
862                 return (null);
863             }
864             return (r.nodes[rrcntr++ % r.nodes.length]);
865         }
866         return (null);
867     }
868
869     /**
870      * Get a provisioned configuration parameter
871      */
872     public String getProvParam(String name) {
873         return (params.get(name));
874     }
875
876     /**
877      * Get all the DestInfos
878      */
879     public DestInfo[] getAllDests() {
880         return (alldests);
881     }
882
883     /**
884      * Get the targets for a feed
885      *
886      * @param feedid The feed ID
887      * @return The targets this feed should be delivered to
888      */
889     public Target[] getTargets(String feedid) {
890         if (feedid == null) {
891             return (new Target[0]);
892         }
893         Feed f = feeds.get(feedid);
894         if (f == null) {
895             return (new Target[0]);
896         }
897         return (f.targets);
898     }
899
900     /**
901      * Get the creation date for a feed
902      * @param feedid The feed ID
903      * @return the timestamp of creation date of feed id passed
904      */
905     public String getCreatedDate(String feedid) {
906         Feed f = feeds.get(feedid);
907         return(f.createdDate);
908     }
909
910     /**
911      * Get the feed ID for a subscription
912      *
913      * @param subid The subscription ID
914      * @return The feed ID
915      */
916     public String getFeedId(String subid) {
917         DestInfo di = subinfo.get(subid);
918         if (di == null) {
919             return (null);
920         }
921         return (di.getLogData());
922     }
923
924     /**
925      * Get the spool directory for a subscription
926      *
927      * @param subid The subscription ID
928      * @return The spool directory
929      */
930     public String getSpoolDir(String subid) {
931         DestInfo di = subinfo.get(subid);
932         if (di == null) {
933             return (null);
934         }
935         return (di.getSpool());
936     }
937
938     /**
939      * Get the Authorization value this node uses
940      *
941      * @return The Authorization header value for this node
942      */
943     public String getMyAuth() {
944         return (myauth);
945     }
946
947 }