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