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