* * Licensed under the Apache License, Version 2.0 (the "License");\r
* * you may not use this file except in compliance with the License.\r
* * You may obtain a copy of the License at\r
- * * \r
+ * *\r
* * http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
+ * *\r
* * Unless required by applicable law or agreed to in writing, software\r
* * distributed under the License is distributed on an "AS IS" BASIS,\r
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
* @version $Id: IngressRoute.java,v 1.3 2013/12/16 20:30:23 eby Exp $\r
*/\r
public class IngressRoute extends NodeClass implements Comparable<IngressRoute> {\r
- private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");\r
- private final int seq;\r
- private final int feedid;\r
- private final String userid;\r
- private final String subnet;\r
- private int nodelist;\r
- private SortedSet<String> nodes;\r
-\r
- /**\r
- * Get all IngressRoutes in the database, sorted in order according to their sequence field.\r
- * @return a sorted set of IngressRoutes\r
- */\r
- public static SortedSet<IngressRoute> getAllIngressRoutes() {\r
- return getAllIngressRoutesForSQL("select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES");\r
- }\r
- /**\r
- * Get all IngressRoutes in the database with a particular sequence number.\r
- * @param seq the sequence number\r
- * @return a set of IngressRoutes\r
- */\r
- public static Set<IngressRoute> getIngressRoutesForSeq(int seq) {\r
- return getAllIngressRoutesForSQL("select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES where SEQUENCE = "+seq);\r
- }\r
- private static SortedSet<IngressRoute> getAllIngressRoutesForSQL(String sql) {\r
- SortedSet<IngressRoute> set = new TreeSet<IngressRoute>();\r
- try {\r
- DB db = new DB();\r
- @SuppressWarnings("resource")\r
- Connection conn = db.getConnection();\r
- Statement stmt = conn.createStatement();\r
- ResultSet rs = stmt.executeQuery(sql);\r
- while (rs.next()) {\r
- int seq = rs.getInt("SEQUENCE");\r
- int feedid = rs.getInt("FEEDID");\r
- String user = rs.getString("USERID");\r
- String subnet = rs.getString("SUBNET");\r
- int nodeset = rs.getInt("NODESET");\r
- set.add(new IngressRoute(seq, feedid, user, subnet, nodeset));\r
- }\r
- rs.close();\r
- stmt.close();\r
- db.release(conn);\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- return set;\r
- }\r
-\r
- /**\r
- * Get the maximum node set ID in use in the DB.\r
- * @return the integer value of the maximum\r
- */\r
- public static int getMaxNodeSetID() {\r
- return getMax("select max(SETID) as MAX from NODESETS");\r
- }\r
- /**\r
- * Get the maximum node sequence number in use in the DB.\r
- * @return the integer value of the maximum\r
- */\r
- public static int getMaxSequence() {\r
- return getMax("select max(SEQUENCE) as MAX from INGRESS_ROUTES");\r
- }\r
- private static int getMax(String sql) {\r
- int rv = 0;\r
- try {\r
- DB db = new DB();\r
- @SuppressWarnings("resource")\r
- Connection conn = db.getConnection();\r
- Statement stmt = conn.createStatement();\r
- ResultSet rs = stmt.executeQuery(sql);\r
- if (rs.next()) {\r
- rv = rs.getInt("MAX");\r
- }\r
- rs.close();\r
- stmt.close();\r
- db.release(conn);\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- return rv;\r
- }\r
-\r
- /**\r
- * Get an Ingress Route for a particular feed ID, user, and subnet\r
- * @param feedid the Feed ID to look for\r
- * @param user the user name to look for\r
- * @param subnet the subnet to look for\r
- * @return the Ingress Route, or null of there is none\r
- */\r
- public static IngressRoute getIngressRoute(int feedid, String user, String subnet) {\r
- IngressRoute v = null;\r
- PreparedStatement ps = null;\r
- try {\r
- DB db = new DB();\r
- @SuppressWarnings("resource")\r
- Connection conn = db.getConnection();\r
- String sql = "select SEQUENCE, NODESET from INGRESS_ROUTES where FEEDID = ? AND USERID = ? and SUBNET = ?";\r
- ps = conn.prepareStatement(sql);\r
- ps.setInt(1, feedid);\r
- ps.setString(2, user);\r
- ps.setString(3, subnet);\r
- ResultSet rs = ps.executeQuery();\r
- if (rs.next()) {\r
- int seq = rs.getInt("SEQUENCE");\r
- int nodeset = rs.getInt("NODESET");\r
- v = new IngressRoute(seq, feedid, user, subnet, nodeset);\r
- }\r
- rs.close();\r
- ps.close();\r
- db.release(conn);\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- } finally {\r
- try {\r
- ps.close();\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return v;\r
- }\r
-\r
- /**\r
- * Get a collection of all Ingress Routes with a particular sequence number.\r
- * @param seq the sequence number to look for\r
- * @return the collection (may be empty).\r
- */\r
- public static Collection<IngressRoute> getIngressRoute(int seq) {\r
- Collection<IngressRoute> rv = new ArrayList<IngressRoute>();\r
- PreparedStatement ps = null;\r
- try {\r
- DB db = new DB();\r
- @SuppressWarnings("resource")\r
- Connection conn = db.getConnection();\r
- String sql = "select FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES where SEQUENCE = ?";\r
- ps = conn.prepareStatement(sql);\r
- ps.setInt(1, seq);\r
- ResultSet rs = ps.executeQuery();\r
- while (rs.next()) {\r
- int feedid = rs.getInt("FEEDID");\r
- String user = rs.getString("USERID");\r
- String subnet = rs.getString("SUBNET");\r
- int nodeset = rs.getInt("NODESET");\r
- rv.add(new IngressRoute(seq, feedid, user, subnet, nodeset));\r
- }\r
- rs.close();\r
- ps.close();\r
- db.release(conn);\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- } finally {\r
- try {\r
- ps.close();\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return rv;\r
- }\r
-\r
- public IngressRoute(int seq, int feedid, String user, String subnet, Collection<String> nodes)\r
- throws IllegalArgumentException\r
- {\r
- this(seq, feedid, user, subnet);\r
- this.nodelist = -1;\r
- this.nodes = new TreeSet<String>(nodes);\r
- }\r
-\r
- public IngressRoute(int seq, int feedid, String user, String subnet, int nodeset)\r
- throws IllegalArgumentException\r
- {\r
- this(seq, feedid, user, subnet);\r
- this.nodelist = nodeset;\r
- this.nodes = new TreeSet<String>(readNodes());\r
- }\r
-\r
- private IngressRoute(int seq, int feedid, String user, String subnet)\r
- throws IllegalArgumentException\r
- {\r
- this.seq = seq;\r
- this.feedid = feedid;\r
- this.userid = (user == null) ? "-" : user;\r
- this.subnet = (subnet == null) ? "-" : subnet;\r
- this.nodelist = -1;\r
- this.nodes = null;\r
- if (Feed.getFeedById(feedid) == null)\r
- throw new IllegalArgumentException("No such feed: "+feedid);\r
- if (!this.subnet.equals("-")) {\r
- SubnetMatcher sm = new SubnetMatcher(subnet);\r
- if (!sm.isValid())\r
- throw new IllegalArgumentException("Invalid subnet: "+subnet);\r
- }\r
- }\r
-\r
- public IngressRoute(JSONObject jo) {\r
- this.seq = jo.optInt("seq");\r
- this.feedid = jo.optInt("feedid");\r
- String t = jo.optString("user");\r
- this.userid = t.equals("") ? "-" : t;\r
- t = jo.optString("subnet");\r
- this.subnet = t.equals("") ? "-" : t;\r
- this.nodelist = -1;\r
- this.nodes = new TreeSet<String>();\r
- JSONArray ja = jo.getJSONArray("node");\r
- for (int i = 0; i < ja.length(); i++)\r
- this.nodes.add(ja.getString(i));\r
- }\r
- /**\r
- * Does this particular IngressRoute match a request, represented by feedid and req?\r
- * To match, <i>feedid</i> must match the feed ID in the route, the user in the route\r
- * (if specified) must match the user in the request, and the subnet in the route (if specified)\r
- * must match the subnet from the request.\r
- * @param feedid the feedid for this request\r
- * @param req the remainder of the request\r
- * @return true if a match, false otherwise\r
- */\r
- public boolean matches(int feedid, HttpServletRequest req) {\r
- // Check feedid\r
- if (this.feedid != feedid)\r
- return false;\r
-\r
- // Get user from request and compare\r
- // Note: we don't check the password; the node will do that\r
- if (userid.length() > 0 && !userid.equals("-")) {\r
- String credentials = req.getHeader("Authorization");\r
- if (credentials == null || !credentials.startsWith("Basic "))\r
- return false;\r
- String t = new String(Base64.decodeBase64(credentials.substring(6)));\r
- int ix = t.indexOf(':');\r
- if (ix >= 0)\r
- t = t.substring(0, ix);\r
- if (!t.equals(this.userid))\r
- return false;\r
- }\r
-\r
- // If this route has a subnet, match it against the requester's IP addr\r
- if (subnet.length() > 0 && !subnet.equals("-")) {\r
- try {\r
- InetAddress inet = InetAddress.getByName(req.getRemoteAddr());\r
- SubnetMatcher sm = new SubnetMatcher(subnet);\r
- return sm.matches(inet.getAddress());\r
- } catch (UnknownHostException e) {\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- /**\r
- * Compare IP addresses as byte arrays to a subnet specified as a CIDR.\r
- * Taken from com.att.research.datarouter.node.SubnetMatcher and modified somewhat.\r
- */\r
- public class SubnetMatcher {\r
- private byte[] sn;\r
- private int len;\r
- private int mask;\r
- private boolean valid;\r
-\r
- /**\r
- * Construct a subnet matcher given a CIDR\r
- * @param subnet The CIDR to match\r
- */\r
- public SubnetMatcher(String subnet) {\r
- int i = subnet.lastIndexOf('/');\r
- if (i == -1) {\r
- try {\r
- sn = InetAddress.getByName(subnet).getAddress();\r
- len = sn.length;\r
- valid = true;\r
- } catch (UnknownHostException e) {\r
- len = 0;\r
- valid = false;\r
- }\r
- mask = 0;\r
- } else {\r
- int n = Integer.parseInt(subnet.substring(i + 1));\r
- try {\r
- sn = InetAddress.getByName(subnet.substring(0, i)).getAddress();\r
- valid = true;\r
- } catch (UnknownHostException e) {\r
- valid = false;\r
- }\r
- len = n / 8;\r
- mask = ((0xff00) >> (n % 8)) & 0xff;\r
- }\r
- }\r
- public boolean isValid() {\r
- return valid;\r
- }\r
- /**\r
- * Is the IP address in the CIDR?\r
- * @param addr the IP address as bytes in network byte order\r
- * @return true if the IP address matches.\r
- */\r
- public boolean matches(byte[] addr) {\r
- if (!valid || addr.length != sn.length) {\r
- return false;\r
- }\r
- for (int i = 0; i < len; i++) {\r
- if (addr[i] != sn[i]) {\r
- return false;\r
- }\r
- }\r
- if (mask != 0 && ((addr[len] ^ sn[len]) & mask) != 0) {\r
- return false;\r
- }\r
- return true;\r
- }\r
- }\r
-\r
- /**\r
- * Get the list of node names for this route.\r
- * @return the list\r
- */\r
- public SortedSet<String> getNodes() {\r
- return this.nodes;\r
- }\r
-\r
- private Collection<String> readNodes() {\r
- Collection<String> set = new TreeSet<String>();\r
- PreparedStatement ps = null;\r
- try {\r
- DB db = new DB();\r
- @SuppressWarnings("resource")\r
- Connection conn = db.getConnection();\r
- Statement stmt = conn.createStatement();\r
- String sql = "select NODEID from NODESETS where SETID = ?";\r
- ps = conn.prepareStatement(sql);\r
- ps.setInt(1, nodelist);\r
- ResultSet rs = ps.executeQuery();\r
- while (rs.next()) {\r
- int id = rs.getInt("NODEID");\r
- set.add(lookupNodeID(id));\r
- }\r
- rs.close();\r
- stmt.close();\r
- db.release(conn);\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- } finally {\r
- try {\r
- ps.close();\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return set;\r
- }\r
-\r
- /**\r
- * Delete the IRT route having this IngressRoutes feed ID, user ID, and subnet from the database.\r
- * @return true if the delete succeeded\r
- */\r
- @Override\r
- public boolean doDelete(Connection c) {\r
- boolean rv = true;\r
- PreparedStatement ps = null;\r
- try {\r
- ps = c.prepareStatement("delete from INGRESS_ROUTES where FEEDID = ? and USERID = ? and SUBNET = ?");\r
- ps.setInt(1, feedid);\r
- ps.setString(2, userid);\r
- ps.setString(3, subnet);\r
- ps.execute();\r
- ps.close();\r
-\r
- ps = c.prepareStatement("delete from NODESETS where SETID = ?");\r
- ps.setInt(1, nodelist);\r
- ps.execute();\r
- } catch (SQLException e) {\r
- rv = false;\r
- intlogger.warn("PROV0007 doDelete: "+e.getMessage());\r
- e.printStackTrace();\r
- } finally {\r
- try {\r
- ps.close();\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return rv;\r
- }\r
-\r
- @SuppressWarnings("resource")\r
- @Override\r
- public boolean doInsert(Connection c) {\r
- boolean rv = false;\r
- PreparedStatement ps = null;\r
- try {\r
- // Create the NODESETS rows & set nodelist\r
- int set = getMaxNodeSetID() + 1;\r
- this.nodelist = set;\r
- for (String node : nodes) {\r
- int id = lookupNodeName(node);\r
- ps = c.prepareStatement("insert into NODESETS (SETID, NODEID) values (?,?)");\r
- ps.setInt(1, this.nodelist);\r
- ps.setInt(2, id);\r
- ps.execute();\r
- ps.close();\r
- }\r
-\r
- // Create the INGRESS_ROUTES row\r
- ps = c.prepareStatement("insert into INGRESS_ROUTES (SEQUENCE, FEEDID, USERID, SUBNET, NODESET) values (?, ?, ?, ?, ?)");\r
- ps.setInt(1, this.seq);\r
- ps.setInt(2, this.feedid);\r
- ps.setString(3, this.userid);\r
- ps.setString(4, this.subnet);\r
- ps.setInt(5, this.nodelist);\r
- ps.execute();\r
- ps.close();\r
- rv = true;\r
- } catch (SQLException e) {\r
- intlogger.warn("PROV0005 doInsert: "+e.getMessage());\r
- e.printStackTrace();\r
- } finally {\r
- try {\r
- ps.close();\r
- } catch (SQLException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return rv;\r
- }\r
-\r
- @Override\r
- public boolean doUpdate(Connection c) {\r
- return doDelete(c) && doInsert(c);\r
- }\r
-\r
- @Override\r
- public JSONObject asJSONObject() {\r
- JSONObject jo = new JSONObject();\r
- jo.put("feedid", feedid);\r
- // Note: for user and subnet, null, "", and "-" are equivalent\r
- if (userid != null && !userid.equals("-") && !userid.equals(""))\r
- jo.put("user", userid);\r
- if (subnet != null && !subnet.equals("-") && !subnet.equals(""))\r
- jo.put("subnet", subnet);\r
- jo.put("seq", seq);\r
- jo.put("node", nodes);\r
- return jo;\r
- }\r
-\r
- @Override\r
- public String getKey() {\r
- return String.format("%d/%s/%s/%d", feedid, (userid == null)?"":userid, (subnet == null)?"":subnet, seq);\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- return toString().hashCode();\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- try {\r
- if (!(obj instanceof IngressRoute))\r
- return false;\r
- return this.compareTo((IngressRoute) obj) == 0;\r
- } catch (NullPointerException e) {\r
- return false;\r
- }\r
- }\r
-\r
- @Override\r
- public int compareTo(IngressRoute in) {\r
- if (in == null)\r
- throw new NullPointerException();\r
- int n = this.feedid - in.feedid;\r
- if (n != 0)\r
- return n;\r
- n = this.seq - in.seq;\r
- if (n != 0)\r
- return n;\r
- n = this.userid.compareTo(in.userid);\r
- if (n != 0)\r
- return n;\r
- n = this.subnet.compareTo(in.subnet);\r
- if (n != 0)\r
- return n;\r
- return this.nodes.equals(in.nodes) ? 0 : 1;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return String.format("INGRESS: feed=%d, userid=%s, subnet=%s, seq=%d", feedid, (userid == null)?"":userid, (subnet == null)?"":subnet, seq);\r
- }\r
+\r
+ private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");\r
+ private final int seq;\r
+ private final int feedid;\r
+ private final String userid;\r
+ private final String subnet;\r
+ private int nodelist;\r
+ private SortedSet<String> nodes;\r
+\r
+ /**\r
+ * Get all IngressRoutes in the database, sorted in order according to their sequence field.\r
+ *\r
+ * @return a sorted set of IngressRoutes\r
+ */\r
+ public static SortedSet<IngressRoute> getAllIngressRoutes() {\r
+ return getAllIngressRoutesForSQL("select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES");\r
+ }\r
+\r
+ /**\r
+ * Get all IngressRoutes in the database with a particular sequence number.\r
+ *\r
+ * @param seq the sequence number\r
+ * @return a set of IngressRoutes\r
+ */\r
+ public static Set<IngressRoute> getIngressRoutesForSeq(int seq) {\r
+ return getAllIngressRoutesForSQL(\r
+ "select SEQUENCE, FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES where SEQUENCE = " + seq);\r
+ }\r
+\r
+ private static SortedSet<IngressRoute> getAllIngressRoutesForSQL(String sql) {\r
+ SortedSet<IngressRoute> set = new TreeSet<IngressRoute>();\r
+ try {\r
+ DB db = new DB();\r
+ @SuppressWarnings("resource")\r
+ Connection conn = db.getConnection();\r
+ try (Statement stmt = conn.createStatement()) {\r
+ try (ResultSet rs = stmt.executeQuery(sql)) {\r
+ while (rs.next()) {\r
+ int seq = rs.getInt("SEQUENCE");\r
+ int feedid = rs.getInt("FEEDID");\r
+ String user = rs.getString("USERID");\r
+ String subnet = rs.getString("SUBNET");\r
+ int nodeset = rs.getInt("NODESET");\r
+ set.add(new IngressRoute(seq, feedid, user, subnet, nodeset));\r
+ }\r
+ }\r
+ }\r
+ db.release(conn);\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ return set;\r
+ }\r
+\r
+ /**\r
+ * Get the maximum node set ID in use in the DB.\r
+ *\r
+ * @return the integer value of the maximum\r
+ */\r
+ public static int getMaxNodeSetID() {\r
+ return getMax("select max(SETID) as MAX from NODESETS");\r
+ }\r
+\r
+ /**\r
+ * Get the maximum node sequence number in use in the DB.\r
+ *\r
+ * @return the integer value of the maximum\r
+ */\r
+ public static int getMaxSequence() {\r
+ return getMax("select max(SEQUENCE) as MAX from INGRESS_ROUTES");\r
+ }\r
+\r
+ private static int getMax(String sql) {\r
+ int rv = 0;\r
+ try {\r
+ DB db = new DB();\r
+ @SuppressWarnings("resource")\r
+ Connection conn = db.getConnection();\r
+ try (Statement stmt = conn.createStatement()) {\r
+ try (ResultSet rs = stmt.executeQuery(sql)) {\r
+ if (rs.next()) {\r
+ rv = rs.getInt("MAX");\r
+ }\r
+ }\r
+ }\r
+ db.release(conn);\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ /**\r
+ * Get an Ingress Route for a particular feed ID, user, and subnet\r
+ *\r
+ * @param feedid the Feed ID to look for\r
+ * @param user the user name to look for\r
+ * @param subnet the subnet to look for\r
+ * @return the Ingress Route, or null of there is none\r
+ */\r
+ public static IngressRoute getIngressRoute(int feedid, String user, String subnet) {\r
+ IngressRoute v = null;\r
+ PreparedStatement ps = null;\r
+ try {\r
+ DB db = new DB();\r
+ @SuppressWarnings("resource")\r
+ Connection conn = db.getConnection();\r
+ String sql = "select SEQUENCE, NODESET from INGRESS_ROUTES where FEEDID = ? AND USERID = ? and SUBNET = ?";\r
+ ps = conn.prepareStatement(sql);\r
+ ps.setInt(1, feedid);\r
+ ps.setString(2, user);\r
+ ps.setString(3, subnet);\r
+ try (ResultSet rs = ps.executeQuery()) {\r
+ if (rs.next()) {\r
+ int seq = rs.getInt("SEQUENCE");\r
+ int nodeset = rs.getInt("NODESET");\r
+ v = new IngressRoute(seq, feedid, user, subnet, nodeset);\r
+ }\r
+ }\r
+ ps.close();\r
+ db.release(conn);\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ } finally {\r
+ try {\r
+ if (ps != null) {\r
+ ps.close();\r
+ }\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ }\r
+ return v;\r
+ }\r
+\r
+ /**\r
+ * Get a collection of all Ingress Routes with a particular sequence number.\r
+ *\r
+ * @param seq the sequence number to look for\r
+ * @return the collection (may be empty).\r
+ */\r
+ public static Collection<IngressRoute> getIngressRoute(int seq) {\r
+ Collection<IngressRoute> rv = new ArrayList<IngressRoute>();\r
+ try {\r
+ DB db = new DB();\r
+ @SuppressWarnings("resource")\r
+ Connection conn = db.getConnection();\r
+ String sql = "select FEEDID, USERID, SUBNET, NODESET from INGRESS_ROUTES where SEQUENCE = ?";\r
+ try (PreparedStatement ps = conn.prepareStatement(sql)) {\r
+ ps.setInt(1, seq);\r
+ try (ResultSet rs = ps.executeQuery()) {\r
+ while (rs.next()) {\r
+ int feedid = rs.getInt("FEEDID");\r
+ String user = rs.getString("USERID");\r
+ String subnet = rs.getString("SUBNET");\r
+ int nodeset = rs.getInt("NODESET");\r
+ rv.add(new IngressRoute(seq, feedid, user, subnet, nodeset));\r
+ }\r
+ }\r
+ }\r
+ db.release(conn);\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ public IngressRoute(int seq, int feedid, String user, String subnet, Collection<String> nodes)\r
+ throws IllegalArgumentException {\r
+ this(seq, feedid, user, subnet);\r
+ this.nodelist = -1;\r
+ this.nodes = new TreeSet<String>(nodes);\r
+ }\r
+\r
+ public IngressRoute(int seq, int feedid, String user, String subnet, int nodeset)\r
+ throws IllegalArgumentException {\r
+ this(seq, feedid, user, subnet);\r
+ this.nodelist = nodeset;\r
+ this.nodes = new TreeSet<String>(readNodes());\r
+ }\r
+\r
+ private IngressRoute(int seq, int feedid, String user, String subnet)\r
+ throws IllegalArgumentException {\r
+ this.seq = seq;\r
+ this.feedid = feedid;\r
+ this.userid = (user == null) ? "-" : user;\r
+ this.subnet = (subnet == null) ? "-" : subnet;\r
+ this.nodelist = -1;\r
+ this.nodes = null;\r
+ if (Feed.getFeedById(feedid) == null) {\r
+ throw new IllegalArgumentException("No such feed: " + feedid);\r
+ }\r
+ if (!this.subnet.equals("-")) {\r
+ SubnetMatcher sm = new SubnetMatcher(subnet);\r
+ if (!sm.isValid()) {\r
+ throw new IllegalArgumentException("Invalid subnet: " + subnet);\r
+ }\r
+ }\r
+ }\r
+\r
+ public IngressRoute(JSONObject jo) {\r
+ this.seq = jo.optInt("seq");\r
+ this.feedid = jo.optInt("feedid");\r
+ String t = jo.optString("user");\r
+ this.userid = t.equals("") ? "-" : t;\r
+ t = jo.optString("subnet");\r
+ this.subnet = t.equals("") ? "-" : t;\r
+ this.nodelist = -1;\r
+ this.nodes = new TreeSet<String>();\r
+ JSONArray ja = jo.getJSONArray("node");\r
+ for (int i = 0; i < ja.length(); i++) {\r
+ this.nodes.add(ja.getString(i));\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Does this particular IngressRoute match a request, represented by feedid and req? To match, <i>feedid</i> must\r
+ * match the feed ID in the route, the user in the route (if specified) must match the user in the request, and the\r
+ * subnet in the route (if specified) must match the subnet from the request.\r
+ *\r
+ * @param feedid the feedid for this request\r
+ * @param req the remainder of the request\r
+ * @return true if a match, false otherwise\r
+ */\r
+ public boolean matches(int feedid, HttpServletRequest req) {\r
+ // Check feedid\r
+ if (this.feedid != feedid) {\r
+ return false;\r
+ }\r
+\r
+ // Get user from request and compare\r
+ // Note: we don't check the password; the node will do that\r
+ if (userid.length() > 0 && !userid.equals("-")) {\r
+ String credentials = req.getHeader("Authorization");\r
+ if (credentials == null || !credentials.startsWith("Basic ")) {\r
+ return false;\r
+ }\r
+ String t = new String(Base64.decodeBase64(credentials.substring(6)));\r
+ int ix = t.indexOf(':');\r
+ if (ix >= 0) {\r
+ t = t.substring(0, ix);\r
+ }\r
+ if (!t.equals(this.userid)) {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ // If this route has a subnet, match it against the requester's IP addr\r
+ if (subnet.length() > 0 && !subnet.equals("-")) {\r
+ try {\r
+ InetAddress inet = InetAddress.getByName(req.getRemoteAddr());\r
+ SubnetMatcher sm = new SubnetMatcher(subnet);\r
+ return sm.matches(inet.getAddress());\r
+ } catch (UnknownHostException e) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Compare IP addresses as byte arrays to a subnet specified as a CIDR. Taken from\r
+ * org.onap.dmaap.datarouter.node.SubnetMatcher and modified somewhat.\r
+ */\r
+ public class SubnetMatcher {\r
+\r
+ private byte[] sn;\r
+ private int len;\r
+ private int mask;\r
+ private boolean valid;\r
+\r
+ /**\r
+ * Construct a subnet matcher given a CIDR\r
+ *\r
+ * @param subnet The CIDR to match\r
+ */\r
+ public SubnetMatcher(String subnet) {\r
+ int i = subnet.lastIndexOf('/');\r
+ if (i == -1) {\r
+ try {\r
+ sn = InetAddress.getByName(subnet).getAddress();\r
+ len = sn.length;\r
+ valid = true;\r
+ } catch (UnknownHostException e) {\r
+ len = 0;\r
+ valid = false;\r
+ }\r
+ mask = 0;\r
+ } else {\r
+ int n = Integer.parseInt(subnet.substring(i + 1));\r
+ try {\r
+ sn = InetAddress.getByName(subnet.substring(0, i)).getAddress();\r
+ valid = true;\r
+ } catch (UnknownHostException e) {\r
+ valid = false;\r
+ }\r
+ len = n / 8;\r
+ mask = ((0xff00) >> (n % 8)) & 0xff;\r
+ }\r
+ }\r
+\r
+ public boolean isValid() {\r
+ return valid;\r
+ }\r
+\r
+ /**\r
+ * Is the IP address in the CIDR?\r
+ *\r
+ * @param addr the IP address as bytes in network byte order\r
+ * @return true if the IP address matches.\r
+ */\r
+ public boolean matches(byte[] addr) {\r
+ if (!valid || addr.length != sn.length) {\r
+ return false;\r
+ }\r
+ for (int i = 0; i < len; i++) {\r
+ if (addr[i] != sn[i]) {\r
+ return false;\r
+ }\r
+ }\r
+ if (mask != 0 && ((addr[len] ^ sn[len]) & mask) != 0) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the list of node names for this route.\r
+ *\r
+ * @return the list\r
+ */\r
+ public SortedSet<String> getNodes() {\r
+ return this.nodes;\r
+ }\r
+\r
+ private Collection<String> readNodes() {\r
+ Collection<String> set = new TreeSet<String>();\r
+ try {\r
+ DB db = new DB();\r
+ @SuppressWarnings("resource")\r
+ Connection conn = db.getConnection();\r
+ String sql = "select NODEID from NODESETS where SETID = ?";\r
+ try (PreparedStatement ps = conn.prepareStatement(sql)) {\r
+ ps.setInt(1, nodelist);\r
+ try (ResultSet rs = ps.executeQuery()) {\r
+ while (rs.next()) {\r
+ int id = rs.getInt("NODEID");\r
+ set.add(lookupNodeID(id));\r
+ }\r
+ }\r
+ }\r
+ db.release(conn);\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ return set;\r
+ }\r
+\r
+ /**\r
+ * Delete the IRT route having this IngressRoutes feed ID, user ID, and subnet from the database.\r
+ *\r
+ * @return true if the delete succeeded\r
+ */\r
+ @Override\r
+ public boolean doDelete(Connection c) {\r
+ boolean rv = true;\r
+ PreparedStatement ps = null;\r
+ try {\r
+ ps = c.prepareStatement("delete from INGRESS_ROUTES where FEEDID = ? and USERID = ? and SUBNET = ?");\r
+ ps.setInt(1, feedid);\r
+ ps.setString(2, userid);\r
+ ps.setString(3, subnet);\r
+ ps.execute();\r
+ ps.close();\r
+\r
+ ps = c.prepareStatement("delete from NODESETS where SETID = ?");\r
+ ps.setInt(1, nodelist);\r
+ ps.execute();\r
+ } catch (SQLException e) {\r
+ rv = false;\r
+ intlogger.warn("PROV0007 doDelete: " + e.getMessage());\r
+ } finally {\r
+ try {\r
+ if (ps != null) {\r
+ ps.close();\r
+ }\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ @SuppressWarnings("resource")\r
+ @Override\r
+ public boolean doInsert(Connection c) {\r
+ boolean rv = false;\r
+ PreparedStatement ps = null;\r
+ try {\r
+ // Create the NODESETS rows & set nodelist\r
+ int set = getMaxNodeSetID() + 1;\r
+ this.nodelist = set;\r
+ for (String node : nodes) {\r
+ int id = lookupNodeName(node);\r
+ ps = c.prepareStatement("insert into NODESETS (SETID, NODEID) values (?,?)");\r
+ ps.setInt(1, this.nodelist);\r
+ ps.setInt(2, id);\r
+ ps.execute();\r
+ ps.close();\r
+ }\r
+\r
+ // Create the INGRESS_ROUTES row\r
+ ps = c.prepareStatement(\r
+ "insert into INGRESS_ROUTES (SEQUENCE, FEEDID, USERID, SUBNET, NODESET) values (?, ?, ?, ?, ?)");\r
+ ps.setInt(1, this.seq);\r
+ ps.setInt(2, this.feedid);\r
+ ps.setString(3, this.userid);\r
+ ps.setString(4, this.subnet);\r
+ ps.setInt(5, this.nodelist);\r
+ ps.execute();\r
+ ps.close();\r
+ rv = true;\r
+ } catch (SQLException e) {\r
+ intlogger.warn("PROV0005 doInsert: " + e.getMessage());\r
+ } finally {\r
+ try {\r
+ if (ps != null) {\r
+ ps.close();\r
+ }\r
+ } catch (SQLException e) {\r
+ intlogger.error("SQLException " + e.getMessage());\r
+ }\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ @Override\r
+ public boolean doUpdate(Connection c) {\r
+ return doDelete(c) && doInsert(c);\r
+ }\r
+\r
+ @Override\r
+ public JSONObject asJSONObject() {\r
+ JSONObject jo = new JSONObject();\r
+ jo.put("feedid", feedid);\r
+ // Note: for user and subnet, null, "", and "-" are equivalent\r
+ if (userid != null && !userid.equals("-") && !userid.equals("")) {\r
+ jo.put("user", userid);\r
+ }\r
+ if (subnet != null && !subnet.equals("-") && !subnet.equals("")) {\r
+ jo.put("subnet", subnet);\r
+ }\r
+ jo.put("seq", seq);\r
+ jo.put("node", nodes);\r
+ return jo;\r
+ }\r
+\r
+ @Override\r
+ public String getKey() {\r
+ return String\r
+ .format("%d/%s/%s/%d", feedid, (userid == null) ? "" : userid, (subnet == null) ? "" : subnet, seq);\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return toString().hashCode();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ try {\r
+ if (!(obj instanceof IngressRoute)) {\r
+ return false;\r
+ }\r
+ return this.compareTo((IngressRoute) obj) == 0;\r
+ } catch (NullPointerException e) {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public int compareTo(IngressRoute in) {\r
+ if (in == null) {\r
+ throw new NullPointerException();\r
+ }\r
+ int n = this.feedid - in.feedid;\r
+ if (n != 0) {\r
+ return n;\r
+ }\r
+ n = this.seq - in.seq;\r
+ if (n != 0) {\r
+ return n;\r
+ }\r
+ n = this.userid.compareTo(in.userid);\r
+ if (n != 0) {\r
+ return n;\r
+ }\r
+ n = this.subnet.compareTo(in.subnet);\r
+ if (n != 0) {\r
+ return n;\r
+ }\r
+ return this.nodes.equals(in.nodes) ? 0 : 1;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return String.format("INGRESS: feed=%d, userid=%s, subnet=%s, seq=%d", feedid, (userid == null) ? "" : userid,\r
+ (subnet == null) ? "" : subnet, seq);\r
+ }\r
}\r