Update project structure to org.onap
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / beans / IngressRoute.java
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/IngressRoute.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/IngressRoute.java
new file mode 100644 (file)
index 0000000..056c769
--- /dev/null
@@ -0,0 +1,541 @@
+/*******************************************************************************\r
+ * ============LICENSE_START==================================================\r
+ * * org.onap.dmaap\r
+ * * ===========================================================================\r
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * * ===========================================================================\r
+ * * 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
+ *  *      http://www.apache.org/licenses/LICENSE-2.0\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
+ * * See the License for the specific language governing permissions and\r
+ * * limitations under the License.\r
+ * * ============LICENSE_END====================================================\r
+ * *\r
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
+ * *\r
+ ******************************************************************************/\r
+\r
+\r
+package org.onap.dmaap.datarouter.provisioning.beans;\r
+\r
+import java.net.InetAddress;\r
+import java.net.UnknownHostException;\r
+import java.sql.Connection;\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.sql.Statement;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Set;\r
+import java.util.SortedSet;\r
+import java.util.TreeSet;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+\r
+import org.apache.commons.codec.binary.Base64;\r
+import org.apache.log4j.Logger;\r
+import org.json.JSONArray;\r
+import org.json.JSONObject;\r
+import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
+\r
+/**\r
+ * The representation of one route in the Ingress Route Table.\r
+ *\r
+ * @author Robert P. Eby\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