Removing unused code
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / beans / IngressRoute.java
1 /*******************************************************************************\r
2  * ============LICENSE_START==================================================\r
3  * * org.onap.dmaap\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * *\r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * *\r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 \r
24 \r
25 package org.onap.dmaap.datarouter.provisioning.beans;\r
26 \r
27 import java.net.InetAddress;\r
28 import java.net.UnknownHostException;\r
29 import java.sql.Connection;\r
30 import java.sql.PreparedStatement;\r
31 import java.sql.ResultSet;\r
32 import java.sql.SQLException;\r
33 import java.sql.Statement;\r
34 import java.util.ArrayList;\r
35 import java.util.Collection;\r
36 import java.util.Set;\r
37 import java.util.SortedSet;\r
38 import java.util.TreeSet;\r
39 \r
40 import javax.servlet.http.HttpServletRequest;\r
41 \r
42 import com.att.eelf.configuration.EELFLogger;\r
43 import com.att.eelf.configuration.EELFManager;\r
44 import org.apache.commons.codec.binary.Base64;\r
45 import org.json.JSONArray;\r
46 import org.json.JSONObject;\r
47 import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
48 \r
49 /**\r
50  * The representation of one route in the Ingress Route Table.\r
51  *\r
52  * @author Robert P. Eby\r
53  * @version $Id: IngressRoute.java,v 1.3 2013/12/16 20:30:23 eby Exp $\r
54  */\r
55 public class IngressRoute extends NodeClass implements Comparable<IngressRoute> {\r
56 \r
57     private static EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog");\r
58     private static final String SQLEXCEPTION = "SQLException: ";\r
59     private final int seq;\r
60     private final int feedid;\r
61     private final String userid;\r
62     private final String subnet;\r
63     private int nodelist;\r
64     private SortedSet<String> nodes;\r
65 \r
66     /**\r
67      * Get all IngressRoutes in the database, sorted in order according to their sequence field.\r
68      *\r
69      * @return a sorted set of IngressRoutes\r
70      */\r
71     public static SortedSet<IngressRoute> getAllIngressRoutes() {\r
72         return getAllIngressRoutesForSQL("select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES");\r
73     }\r
74 \r
75     /**\r
76      * Get all IngressRoutes in the database with a particular sequence number.\r
77      *\r
78      * @param seq the sequence number\r
79      * @return a set of IngressRoutes\r
80      */\r
81     public static Set<IngressRoute> getIngressRoutesForSeq(int seq) {\r
82         return getAllIngressRoutesForSQL(\r
83                 "select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES where SEQUENCE = " + seq);\r
84     }\r
85 \r
86     private static SortedSet<IngressRoute> getAllIngressRoutesForSQL(String sql) {\r
87         SortedSet<IngressRoute> set = new TreeSet<IngressRoute>();\r
88         try {\r
89             DB db = new DB();\r
90             @SuppressWarnings("resource")\r
91             Connection conn = db.getConnection();\r
92             try (Statement stmt = conn.createStatement()) {\r
93                 try (ResultSet rs = stmt.executeQuery(sql)) {\r
94                     while (rs.next()) {\r
95                         int seq = rs.getInt("SEQUENCE");\r
96                         int feedid = rs.getInt("FEEDID");\r
97                         String user = rs.getString("USERID");\r
98                         String subnet = rs.getString("SUBNET");\r
99                         int nodeset = rs.getInt("NODESET");\r
100                         set.add(new IngressRoute(seq, feedid, user, subnet, nodeset));\r
101                     }\r
102                 }\r
103             }\r
104             db.release(conn);\r
105         } catch (SQLException e) {\r
106             intlogger.error("PROV0001 getAllIngressRoutesForSQL: " + e.getMessage(), e);\r
107         }\r
108         return set;\r
109     }\r
110 \r
111     /**\r
112      * Get the maximum node set ID in use in the DB.\r
113      *\r
114      * @return the integer value of the maximum\r
115      */\r
116     public static int getMaxNodeSetID() {\r
117         return getMax("select max(SETID) as MAX from NODESETS");\r
118     }\r
119 \r
120     /**\r
121      * Get the maximum node sequence number in use in the DB.\r
122      *\r
123      * @return the integer value of the maximum\r
124      */\r
125     public static int getMaxSequence() {\r
126         return getMax("select max(SEQUENCE) as MAX from INGRESS_ROUTES");\r
127     }\r
128 \r
129     private static int getMax(String sql) {\r
130         int rv = 0;\r
131         try {\r
132             DB db = new DB();\r
133             @SuppressWarnings("resource")\r
134             Connection conn = db.getConnection();\r
135             try (Statement stmt = conn.createStatement()) {\r
136                 try (ResultSet rs = stmt.executeQuery(sql)) {\r
137                     if (rs.next()) {\r
138                         rv = rs.getInt("MAX");\r
139                     }\r
140                 }\r
141             }\r
142             db.release(conn);\r
143         } catch (SQLException e) {\r
144             intlogger.error("PROV0002 getMax: " + e.getMessage(), e);\r
145         }\r
146         return rv;\r
147     }\r
148 \r
149     /**\r
150      * Get an Ingress Route for a particular feed ID, user, and subnet\r
151      *\r
152      * @param feedid the Feed ID to look for\r
153      * @param user the user name to look for\r
154      * @param subnet the subnet to look for\r
155      * @return the Ingress Route, or null of there is none\r
156      */\r
157     public static IngressRoute getIngressRoute(int feedid, String user, String subnet) {\r
158         IngressRoute v = null;\r
159         PreparedStatement ps = null;\r
160         try {\r
161             DB db = new DB();\r
162             @SuppressWarnings("resource")\r
163             Connection conn = db.getConnection();\r
164             String sql = "select SEQUENCE, NODESET from INGRESS_ROUTES where FEEDID = ? AND USERID = ? and SUBNET = ?";\r
165             ps = conn.prepareStatement(sql);\r
166             ps.setInt(1, feedid);\r
167             ps.setString(2, user);\r
168             ps.setString(3, subnet);\r
169             try (ResultSet rs = ps.executeQuery()) {\r
170                 if (rs.next()) {\r
171                     int seq = rs.getInt("SEQUENCE");\r
172                     int nodeset = rs.getInt("NODESET");\r
173                     v = new IngressRoute(seq, feedid, user, subnet, nodeset);\r
174                 }\r
175             }\r
176             ps.close();\r
177             db.release(conn);\r
178         } catch (SQLException e) {\r
179             intlogger.error("PROV0003 getIngressRoute: " + e.getMessage(), e);\r
180         } finally {\r
181             try {\r
182                 if (ps != null) {\r
183                     ps.close();\r
184                 }\r
185             } catch (SQLException e) {\r
186                 intlogger.error(SQLEXCEPTION + e.getMessage(), e);\r
187             }\r
188         }\r
189         return v;\r
190     }\r
191 \r
192     public IngressRoute(int seq, int feedid, String user, String subnet, Collection<String> nodes)\r
193             throws IllegalArgumentException {\r
194         this(seq, feedid, user, subnet);\r
195         this.nodelist = -1;\r
196         this.nodes = new TreeSet<String>(nodes);\r
197     }\r
198 \r
199     public IngressRoute(int seq, int feedid, String user, String subnet, int nodeset)\r
200             throws IllegalArgumentException {\r
201         this(seq, feedid, user, subnet);\r
202         this.nodelist = nodeset;\r
203         this.nodes = new TreeSet<String>(readNodes());\r
204     }\r
205 \r
206     private IngressRoute(int seq, int feedid, String user, String subnet)\r
207             throws IllegalArgumentException {\r
208         this.seq = seq;\r
209         this.feedid = feedid;\r
210         this.userid = (user == null) ? "-" : user;\r
211         this.subnet = (subnet == null) ? "-" : subnet;\r
212         this.nodelist = -1;\r
213         this.nodes = null;\r
214         if (Feed.getFeedById(feedid) == null) {\r
215             throw new IllegalArgumentException("No such feed: " + feedid);\r
216         }\r
217         if (!this.subnet.equals("-")) {\r
218             SubnetMatcher sm = new SubnetMatcher(subnet);\r
219             if (!sm.isValid()) {\r
220                 throw new IllegalArgumentException("Invalid subnet: " + subnet);\r
221             }\r
222         }\r
223     }\r
224 \r
225     public IngressRoute(JSONObject jo) {\r
226         this.seq = jo.optInt("seq");\r
227         this.feedid = jo.optInt("feedid");\r
228         String t = jo.optString("user");\r
229         this.userid = t.equals("") ? "-" : t;\r
230         t = jo.optString("subnet");\r
231         this.subnet = t.equals("") ? "-" : t;\r
232         this.nodelist = -1;\r
233         this.nodes = new TreeSet<String>();\r
234         JSONArray ja = jo.getJSONArray("node");\r
235         for (int i = 0; i < ja.length(); i++) {\r
236             this.nodes.add(ja.getString(i));\r
237         }\r
238     }\r
239 \r
240     /**\r
241      * Does this particular IngressRoute match a request, represented by feedid and req? To match, <i>feedid</i> must\r
242      * match the feed ID in the route, the user in the route (if specified) must match the user in the request, and the\r
243      * subnet in the route (if specified) must match the subnet from the request.\r
244      *\r
245      * @param feedid the feedid for this request\r
246      * @param req the remainder of the request\r
247      * @return true if a match, false otherwise\r
248      */\r
249     public boolean matches(int feedid, HttpServletRequest req) {\r
250         // Check feedid\r
251         if (this.feedid != feedid) {\r
252             return false;\r
253         }\r
254 \r
255         // Get user from request and compare\r
256         // Note: we don't check the password; the node will do that\r
257         if (userid.length() > 0 && !userid.equals("-")) {\r
258             String credentials = req.getHeader("Authorization");\r
259             if (credentials == null || !credentials.startsWith("Basic ")) {\r
260                 return false;\r
261             }\r
262             String t = new String(Base64.decodeBase64(credentials.substring(6)));\r
263             int ix = t.indexOf(':');\r
264             if (ix >= 0) {\r
265                 t = t.substring(0, ix);\r
266             }\r
267             if (!t.equals(this.userid)) {\r
268                 return false;\r
269             }\r
270         }\r
271 \r
272         // If this route has a subnet, match it against the requester's IP addr\r
273         if (subnet.length() > 0 && !subnet.equals("-")) {\r
274             try {\r
275                 InetAddress inet = InetAddress.getByName(req.getRemoteAddr());\r
276                 SubnetMatcher sm = new SubnetMatcher(subnet);\r
277                 return sm.matches(inet.getAddress());\r
278             } catch (UnknownHostException e) {\r
279                 intlogger.error("PROV0008 matches: " + e.getMessage(), e);\r
280                 return false;\r
281             }\r
282         }\r
283         return true;\r
284     }\r
285 \r
286     /**\r
287      * Compare IP addresses as byte arrays to a subnet specified as a CIDR. Taken from\r
288      * org.onap.dmaap.datarouter.node.SubnetMatcher and modified somewhat.\r
289      */\r
290     public class SubnetMatcher {\r
291 \r
292         private byte[] sn;\r
293         private int len;\r
294         private int mask;\r
295         private boolean valid;\r
296 \r
297         /**\r
298          * Construct a subnet matcher given a CIDR\r
299          *\r
300          * @param subnet The CIDR to match\r
301          */\r
302         public SubnetMatcher(String subnet) {\r
303             int i = subnet.lastIndexOf('/');\r
304             if (i == -1) {\r
305                 try {\r
306                     sn = InetAddress.getByName(subnet).getAddress();\r
307                     len = sn.length;\r
308                     valid = true;\r
309                 } catch (UnknownHostException e) {\r
310                     intlogger.error("PROV0008 SubnetMatcher: " + e.getMessage(), e);\r
311                     len = 0;\r
312                     valid = false;\r
313                 }\r
314                 mask = 0;\r
315             } else {\r
316                 int n = Integer.parseInt(subnet.substring(i + 1));\r
317                 try {\r
318                     sn = InetAddress.getByName(subnet.substring(0, i)).getAddress();\r
319                     valid = true;\r
320                 } catch (UnknownHostException e) {\r
321                     intlogger.error("PROV0008 SubnetMatcher: " + e.getMessage(), e);\r
322                     valid = false;\r
323                 }\r
324                 len = n / 8;\r
325                 mask = ((0xff00) >> (n % 8)) & 0xff;\r
326             }\r
327         }\r
328 \r
329         public boolean isValid() {\r
330             return valid;\r
331         }\r
332 \r
333         /**\r
334          * Is the IP address in the CIDR?\r
335          *\r
336          * @param addr the IP address as bytes in network byte order\r
337          * @return true if the IP address matches.\r
338          */\r
339         public boolean matches(byte[] addr) {\r
340             if (!valid || addr.length != sn.length) {\r
341                 return false;\r
342             }\r
343             for (int i = 0; i < len; i++) {\r
344                 if (addr[i] != sn[i]) {\r
345                     return false;\r
346                 }\r
347             }\r
348             if (mask != 0 && ((addr[len] ^ sn[len]) & mask) != 0) {\r
349                 return false;\r
350             }\r
351             return true;\r
352         }\r
353     }\r
354 \r
355     /**\r
356      * Get the list of node names for this route.\r
357      *\r
358      * @return the list\r
359      */\r
360     public SortedSet<String> getNodes() {\r
361         return this.nodes;\r
362     }\r
363 \r
364     private Collection<String> readNodes() {\r
365         Collection<String> set = new TreeSet<>();\r
366         try {\r
367             DB db = new DB();\r
368             @SuppressWarnings("resource")\r
369             Connection conn = db.getConnection();\r
370             String sql = "select NODEID from NODESETS where SETID = ?";\r
371             try (PreparedStatement ps = conn.prepareStatement(sql)) {\r
372                 ps.setInt(1, nodelist);\r
373                 try (ResultSet rs = ps.executeQuery()) {\r
374                     while (rs.next()) {\r
375                         int id = rs.getInt("NODEID");\r
376                         set.add(lookupNodeID(id));\r
377                     }\r
378                 }\r
379             }\r
380             db.release(conn);\r
381         } catch (SQLException e) {\r
382             intlogger.error(SQLEXCEPTION + e.getMessage(), e);\r
383         }\r
384         return set;\r
385     }\r
386 \r
387     /**\r
388      * Delete the IRT route having this IngressRoutes feed ID, user ID, and subnet from the database.\r
389      *\r
390      * @return true if the delete succeeded\r
391      */\r
392     @Override\r
393     public boolean doDelete(Connection c) {\r
394         boolean rv = true;\r
395         PreparedStatement ps = null;\r
396         try {\r
397             ps = c.prepareStatement("delete from INGRESS_ROUTES where FEEDID = ? and USERID = ? and SUBNET = ?");\r
398             ps.setInt(1, feedid);\r
399             ps.setString(2, userid);\r
400             ps.setString(3, subnet);\r
401             ps.execute();\r
402             ps.close();\r
403 \r
404             ps = c.prepareStatement("delete from NODESETS where SETID = ?");\r
405             ps.setInt(1, nodelist);\r
406             ps.execute();\r
407         } catch (SQLException e) {\r
408             rv = false;\r
409             intlogger.warn("PROV0007 doDelete: " + e.getMessage(), e);\r
410         } finally {\r
411             try {\r
412                 if (ps != null) {\r
413                     ps.close();\r
414                 }\r
415             } catch (SQLException e) {\r
416                 intlogger.error(SQLEXCEPTION + e.getMessage(), e);\r
417             }\r
418         }\r
419         return rv;\r
420     }\r
421 \r
422     @SuppressWarnings("resource")\r
423     @Override\r
424     public boolean doInsert(Connection c) {\r
425         boolean rv = false;\r
426         PreparedStatement ps = null;\r
427         try {\r
428             // Create the NODESETS rows & set nodelist\r
429             int set = getMaxNodeSetID() + 1;\r
430             this.nodelist = set;\r
431             for (String node : nodes) {\r
432                 int id = lookupNodeName(node);\r
433                 ps = c.prepareStatement("insert into NODESETS (SETID, NODEID) values (?,?)");\r
434                 ps.setInt(1, this.nodelist);\r
435                 ps.setInt(2, id);\r
436                 ps.execute();\r
437                 ps.close();\r
438             }\r
439 \r
440             // Create the INGRESS_ROUTES row\r
441             ps = c.prepareStatement(\r
442                     "insert into INGRESS_ROUTES (SEQUENCE, FEEDID, USERID, SUBNET, NODESET) values (?, ?, ?, ?, ?)");\r
443             ps.setInt(1, this.seq);\r
444             ps.setInt(2, this.feedid);\r
445             ps.setString(3, this.userid);\r
446             ps.setString(4, this.subnet);\r
447             ps.setInt(5, this.nodelist);\r
448             ps.execute();\r
449             ps.close();\r
450             rv = true;\r
451         } catch (SQLException e) {\r
452             intlogger.warn("PROV0005 doInsert: " + e.getMessage(), e);\r
453         } finally {\r
454             try {\r
455                 if (ps != null) {\r
456                     ps.close();\r
457                 }\r
458             } catch (SQLException e) {\r
459                 intlogger.error(SQLEXCEPTION + e.getMessage(), e);\r
460             }\r
461         }\r
462         return rv;\r
463     }\r
464 \r
465     @Override\r
466     public boolean doUpdate(Connection c) {\r
467         return doDelete(c) && doInsert(c);\r
468     }\r
469 \r
470     @Override\r
471     public JSONObject asJSONObject() {\r
472         JSONObject jo = new JSONObject();\r
473         jo.put("feedid", feedid);\r
474         // Note: for user and subnet, null, "", and "-" are equivalent\r
475         if (userid != null && !userid.equals("-") && !userid.equals("")) {\r
476             jo.put("user", userid);\r
477         }\r
478         if (subnet != null && !subnet.equals("-") && !subnet.equals("")) {\r
479             jo.put("subnet", subnet);\r
480         }\r
481         jo.put("seq", seq);\r
482         jo.put("node", nodes);\r
483         return jo;\r
484     }\r
485 \r
486     @Override\r
487     public String getKey() {\r
488         return String\r
489                 .format("%d/%s/%s/%d", feedid, (userid == null) ? "" : userid, (subnet == null) ? "" : subnet, seq);\r
490     }\r
491 \r
492     @Override\r
493     public int hashCode() {\r
494         return toString().hashCode();\r
495     }\r
496 \r
497     @Override\r
498     public boolean equals(Object obj) {\r
499         if (!(obj instanceof IngressRoute)) {\r
500             return false;\r
501         }\r
502         return this.compareTo((IngressRoute) obj) == 0;\r
503     }\r
504 \r
505     @Override\r
506     public int compareTo(IngressRoute in) {\r
507         if (in == null) {\r
508             throw new NullPointerException();\r
509         }\r
510         int n = this.feedid - in.feedid;\r
511         if (n != 0) {\r
512             return n;\r
513         }\r
514         n = this.seq - in.seq;\r
515         if (n != 0) {\r
516             return n;\r
517         }\r
518         n = this.userid.compareTo(in.userid);\r
519         if (n != 0) {\r
520             return n;\r
521         }\r
522         n = this.subnet.compareTo(in.subnet);\r
523         if (n != 0) {\r
524             return n;\r
525         }\r
526         return this.nodes.equals(in.nodes) ? 0 : 1;\r
527     }\r
528 \r
529     @Override\r
530     public String toString() {\r
531         return String.format("INGRESS: feed=%d, userid=%s, subnet=%s, seq=%d", feedid, (userid == null) ? "" : userid,\r
532                 (subnet == null) ? "" : subnet, seq);\r
533     }\r
534 }\r