Add optional API for PM Mapper
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / beans / Subscription.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 package org.onap.dmaap.datarouter.provisioning.beans;\r
25 \r
26 import java.io.InvalidObjectException;\r
27 import java.sql.Connection;\r
28 import java.sql.PreparedStatement;\r
29 import java.sql.ResultSet;\r
30 import java.sql.SQLException;\r
31 import java.sql.Statement;\r
32 import java.util.ArrayList;\r
33 import java.util.Collection;\r
34 import java.util.Date;\r
35 import java.util.List;\r
36 import java.util.Objects;\r
37 import java.util.Properties;\r
38 import org.apache.log4j.Logger;\r
39 import org.json.JSONObject;\r
40 import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
41 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;\r
42 \r
43 /**\r
44  * The representation of a Subscription.  Subscriptions can be retrieved from the DB, or stored/updated in the DB.\r
45  *\r
46  * @author Robert Eby\r
47  * @version $Id: Subscription.java,v 1.9 2013/10/28 18:06:53 eby Exp $\r
48  */\r
49 public class Subscription extends Syncable {\r
50 \r
51     private static final String SQLEXCEPTION = "SQLException: ";\r
52     private static final String SUBID_KEY = "subid";\r
53     private static final String SUBID_COL = "SUBID";\r
54     private static final String FEEDID_KEY = "feedid";\r
55     private static final String GROUPID_KEY = "groupid";\r
56     private static final String LAST_MOD_KEY = "last_mod";\r
57     private static final String CREATED_DATE = "created_date";\r
58     private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");\r
59     private static int nextSubid = getMaxSubID() + 1;\r
60 \r
61     private int subid;\r
62     private int feedid;\r
63     private int groupid; //New field is added - Groups feature Rally:US708115 - 1610\r
64     private SubDelivery delivery;\r
65     private boolean metadataOnly;\r
66     private String subscriber;\r
67     private SubLinks links;\r
68     private boolean suspended;\r
69     private Date lastMod;\r
70     private Date createdDate;\r
71     private boolean privilegedSubscriber;\r
72 \r
73     public static Subscription getSubscriptionMatching(Subscription sub) {\r
74         SubDelivery deli = sub.getDelivery();\r
75         String sql = String.format(\r
76                 "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d",\r
77                 sub.getFeedid(),\r
78                 deli.getUrl(),\r
79                 deli.getUser(),\r
80                 deli.getPassword(),\r
81                 deli.isUse100() ? 1 : 0,\r
82                 sub.isMetadataOnly() ? 1 : 0\r
83         );\r
84         List<Subscription> list = getSubscriptionsForSQL(sql);\r
85         return !list.isEmpty() ? list.get(0) : null;\r
86     }\r
87 \r
88     public static Subscription getSubscriptionById(int id) {\r
89         String sql = "select * from SUBSCRIPTIONS where SUBID = " + id;\r
90         List<Subscription> list = getSubscriptionsForSQL(sql);\r
91         return !list.isEmpty() ? list.get(0) : null;\r
92     }\r
93 \r
94     public static Collection<Subscription> getAllSubscriptions() {\r
95         return getSubscriptionsForSQL("select * from SUBSCRIPTIONS");\r
96     }\r
97 \r
98     private static List<Subscription> getSubscriptionsForSQL(String sql) {\r
99         List<Subscription> list = new ArrayList<>();\r
100         try {\r
101             DB db = new DB();\r
102             @SuppressWarnings("resource")\r
103             Connection conn = db.getConnection();\r
104             try (Statement stmt = conn.createStatement()) {\r
105                 try (ResultSet rs = stmt.executeQuery(sql)) {\r
106                     while (rs.next()) {\r
107                         Subscription sub = new Subscription(rs);\r
108                         list.add(sub);\r
109                     }\r
110                 }\r
111             }\r
112             db.release(conn);\r
113         } catch (SQLException e) {\r
114             intlogger.error(e);\r
115         }\r
116         return list;\r
117     }\r
118 \r
119     public static int getMaxSubID() {\r
120         int max = 0;\r
121         try {\r
122             DB db = new DB();\r
123             @SuppressWarnings("resource")\r
124             Connection conn = db.getConnection();\r
125             try (Statement stmt = conn.createStatement()) {\r
126                 try (ResultSet rs = stmt.executeQuery("select MAX(subid) from SUBSCRIPTIONS")) {\r
127                     if (rs.next()) {\r
128                         max = rs.getInt(1);\r
129                     }\r
130                 }\r
131             }\r
132             db.release(conn);\r
133         } catch (SQLException e) {\r
134             intlogger.info("getMaxSubID: " + e.getMessage());\r
135         }\r
136         return max;\r
137     }\r
138 \r
139     public static Collection<String> getSubscriptionUrlList(int feedid) {\r
140         List<String> list = new ArrayList<>();\r
141         String sql = "select SUBID from SUBSCRIPTIONS where FEEDID = ?";\r
142 \r
143         try {\r
144             DB db = new DB();\r
145             @SuppressWarnings("resource")\r
146             Connection conn = db.getConnection();\r
147 \r
148             try (PreparedStatement stmt = conn.prepareStatement(sql)) {\r
149                 stmt.setString(1, String.valueOf(feedid));\r
150                 try (ResultSet rs = stmt.executeQuery()) {\r
151                     while (rs.next()) {\r
152                         int subid = rs.getInt(SUBID_COL);\r
153                         list.add(URLUtilities.generateSubscriptionURL(subid));\r
154                     }\r
155                 }\r
156             }\r
157             db.release(conn);\r
158         } catch (SQLException e) {\r
159             intlogger.error(SQLEXCEPTION + e.getMessage());\r
160         }\r
161         return list;\r
162     }\r
163 \r
164     /**\r
165      * Return a count of the number of active subscriptions in the DB.\r
166      *\r
167      * @return the count\r
168      */\r
169     public static int countActiveSubscriptions() {\r
170         int count = 0;\r
171         try {\r
172             DB db = new DB();\r
173             @SuppressWarnings("resource")\r
174             Connection conn = db.getConnection();\r
175             try (Statement stmt = conn.createStatement()) {\r
176                 try (ResultSet rs = stmt.executeQuery("select count(*) from SUBSCRIPTIONS")) {\r
177                     if (rs.next()) {\r
178                         count = rs.getInt(1);\r
179                     }\r
180                 }\r
181             }\r
182             db.release(conn);\r
183         } catch (SQLException e) {\r
184             intlogger.warn("PROV0008 countActiveSubscriptions: " + e.getMessage());\r
185         }\r
186         return count;\r
187     }\r
188 \r
189     public Subscription() {\r
190         this("", "", "");\r
191     }\r
192 \r
193     public Subscription(String url, String user, String password) {\r
194         this.subid = -1;\r
195         this.feedid = -1;\r
196         this.groupid = -1; //New field is added - Groups feature Rally:US708115 - 1610\r
197         this.delivery = new SubDelivery(url, user, password, false);\r
198         this.metadataOnly = false;\r
199         this.subscriber = "";\r
200         this.links = new SubLinks();\r
201         this.suspended = false;\r
202         this.lastMod = new Date();\r
203         this.createdDate = new Date();\r
204         this.privilegedSubscriber = false;\r
205     }\r
206 \r
207     public Subscription(ResultSet rs) throws SQLException {\r
208         this.subid = rs.getInt(SUBID_COL);\r
209         this.feedid = rs.getInt("FEEDID");\r
210         this.groupid = rs.getInt("GROUPID"); //New field is added - Groups feature Rally:US708115 - 1610\r
211         this.delivery = new SubDelivery(rs);\r
212         this.metadataOnly = rs.getBoolean("METADATA_ONLY");\r
213         this.subscriber = rs.getString("SUBSCRIBER");\r
214         this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid),\r
215                 rs.getString("LOG_LINK"));\r
216         this.suspended = rs.getBoolean("SUSPENDED");\r
217         this.lastMod = rs.getDate("LAST_MOD");\r
218         this.createdDate = rs.getDate("CREATED_DATE");\r
219         this.privilegedSubscriber = rs.getBoolean("PRIVILEGED_SUBSCRIBER");\r
220     }\r
221 \r
222     public Subscription(JSONObject jo) throws InvalidObjectException {\r
223         this("", "", "");\r
224         try {\r
225             // The JSONObject is assumed to contain a vnd.dmaap-dr.subscription representation\r
226             this.subid = jo.optInt(SUBID_KEY, -1);\r
227             this.feedid = jo.optInt(FEEDID_KEY, -1);\r
228             this.groupid = jo.optInt(GROUPID_KEY, -1); //New field is added - Groups feature Rally:US708115 - 1610\r
229 \r
230             JSONObject jdeli = jo.getJSONObject("delivery");\r
231             String url = jdeli.getString("url");\r
232             String user = jdeli.getString("user");\r
233             String password = jdeli.getString("password");\r
234             boolean use100 = jdeli.getBoolean("use100");\r
235 \r
236             //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.\r
237             Properties p = (new DB()).getProperties();\r
238             if (!url.startsWith("https://") && isHttpsRelaxationFalseAndHasSyncKey(jo, p)) {\r
239                 throw new InvalidObjectException("delivery URL is not HTTPS");\r
240             }\r
241 \r
242             if (url.length() > 256) {\r
243                 throw new InvalidObjectException("delivery url field is too long");\r
244             }\r
245             if (user.length() > 20) {\r
246                 throw new InvalidObjectException("delivery user field is too long");\r
247             }\r
248             if (password.length() > 32) {\r
249                 throw new InvalidObjectException("delivery password field is too long");\r
250             }\r
251             this.delivery = new SubDelivery(url, user, password, use100);\r
252 \r
253             this.metadataOnly = jo.getBoolean("metadataOnly");\r
254             this.suspended = jo.optBoolean("suspend", false);\r
255             this.privilegedSubscriber = jo.optBoolean("privilegedSubscriber", false);\r
256             this.subscriber = jo.optString("subscriber", "");\r
257             JSONObject jol = jo.optJSONObject("links");\r
258             this.links = (jol == null) ? (new SubLinks()) : (new SubLinks(jol));\r
259         } catch (InvalidObjectException e) {\r
260             throw e;\r
261         } catch (Exception e) {\r
262             throw new InvalidObjectException("invalid JSON: " + e.getMessage());\r
263         }\r
264     }\r
265 \r
266     private boolean isHttpsRelaxationFalseAndHasSyncKey(JSONObject jo, Properties p) {\r
267         return p.get("org.onap.dmaap.datarouter.provserver.https.relaxation").toString().equals("false") && !jo\r
268                 .has("sync");\r
269     }\r
270 \r
271     public int getSubid() {\r
272         return subid;\r
273     }\r
274 \r
275     public void setSubid(int subid) {\r
276         this.subid = subid;\r
277 \r
278         // Create link URLs\r
279         SubLinks sl = getLinks();\r
280         sl.setSelf(URLUtilities.generateSubscriptionURL(subid));\r
281         sl.setLog(URLUtilities.generateSubLogURL(subid));\r
282     }\r
283 \r
284     public int getFeedid() {\r
285         return feedid;\r
286     }\r
287 \r
288     public void setFeedid(int feedid) {\r
289         this.feedid = feedid;\r
290 \r
291         // Create link URLs\r
292         SubLinks sl = getLinks();\r
293         sl.setFeed(URLUtilities.generateFeedURL(feedid));\r
294     }\r
295 \r
296     //New getter setters for Groups feature Rally:US708115 - 1610\r
297     public int getGroupid() {\r
298         return groupid;\r
299     }\r
300 \r
301     public void setGroupid(int groupid) {\r
302         this.groupid = groupid;\r
303     }\r
304 \r
305     public SubDelivery getDelivery() {\r
306         return delivery;\r
307     }\r
308 \r
309     public void setDelivery(SubDelivery delivery) {\r
310         this.delivery = delivery;\r
311     }\r
312 \r
313     public boolean isMetadataOnly() {\r
314         return metadataOnly;\r
315     }\r
316 \r
317     public void setMetadataOnly(boolean metadataOnly) {\r
318         this.metadataOnly = metadataOnly;\r
319     }\r
320 \r
321     public boolean isSuspended() {\r
322         return suspended;\r
323     }\r
324 \r
325     public void setSuspended(boolean suspended) {\r
326         this.suspended = suspended;\r
327     }\r
328 \r
329     public boolean isPrivilegedSubscriber() {\r
330         return privilegedSubscriber;\r
331     }\r
332 \r
333     public void setPrivilegedSubscriber(boolean privilegedSubscriber) {\r
334         this.privilegedSubscriber = privilegedSubscriber;\r
335     }\r
336 \r
337     public String getSubscriber() {\r
338         return subscriber;\r
339     }\r
340 \r
341     public void setSubscriber(String subscriber) {\r
342         if (subscriber != null) {\r
343             if (subscriber.length() > 8) {\r
344                 subscriber = subscriber.substring(0, 8);\r
345             }\r
346             this.subscriber = subscriber;\r
347         }\r
348     }\r
349 \r
350     public SubLinks getLinks() {\r
351         return links;\r
352     }\r
353 \r
354     public void setLinks(SubLinks links) {\r
355         this.links = links;\r
356     }\r
357 \r
358     @Override\r
359     public JSONObject asJSONObject() {\r
360         JSONObject jo = new JSONObject();\r
361         jo.put(SUBID_KEY, subid);\r
362         jo.put(FEEDID_KEY, feedid);\r
363         jo.put(GROUPID_KEY, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
364         jo.put("delivery", delivery.asJSONObject());\r
365         jo.put("metadataOnly", metadataOnly);\r
366         jo.put("subscriber", subscriber);\r
367         jo.put("links", links.asJSONObject());\r
368         jo.put("suspend", suspended);\r
369         jo.put(LAST_MOD_KEY, lastMod.getTime());\r
370         jo.put(CREATED_DATE, createdDate.getTime());\r
371         jo.put("privilegedSubscriber", privilegedSubscriber);\r
372         return jo;\r
373     }\r
374 \r
375     public JSONObject asLimitedJSONObject() {\r
376         JSONObject jo = asJSONObject();\r
377         jo.remove(SUBID_KEY);\r
378         jo.remove(FEEDID_KEY);\r
379         jo.remove(LAST_MOD_KEY);\r
380         return jo;\r
381     }\r
382 \r
383     public JSONObject asJSONObject(boolean hidepasswords) {\r
384         JSONObject jo = asJSONObject();\r
385         if (hidepasswords) {\r
386             jo.remove(SUBID_KEY);    // we no longer hide passwords, however we do hide these\r
387             jo.remove(FEEDID_KEY);\r
388             jo.remove(LAST_MOD_KEY);\r
389             jo.remove(CREATED_DATE);\r
390         }\r
391         return jo;\r
392     }\r
393 \r
394     @Override\r
395     public boolean doInsert(Connection c) {\r
396         boolean rv = true;\r
397         PreparedStatement ps = null;\r
398         try {\r
399             if (subid == -1) {\r
400                 // No feed ID assigned yet, so assign the next available one\r
401                 setSubid(nextSubid++);\r
402             }\r
403             // In case we insert a feed from synchronization\r
404             if (subid > nextSubid) {\r
405                 nextSubid = subid + 1;\r
406             }\r
407 \r
408             // Create the SUBSCRIPTIONS row\r
409             String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";\r
410             ps = c.prepareStatement(sql, new String[]{SUBID_COL});\r
411             ps.setInt(1, subid);\r
412             ps.setInt(2, feedid);\r
413             ps.setString(3, getDelivery().getUrl());\r
414             ps.setString(4, getDelivery().getUser());\r
415             ps.setString(5, getDelivery().getPassword());\r
416             ps.setInt(6, getDelivery().isUse100() ? 1 : 0);\r
417             ps.setInt(7, isMetadataOnly() ? 1 : 0);\r
418             ps.setString(8, getSubscriber());\r
419             ps.setBoolean(9, isSuspended());\r
420             ps.setInt(10, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
421             ps.setBoolean(11, isPrivilegedSubscriber());\r
422             ps.execute();\r
423             ps.close();\r
424             // Update the row to set the URLs\r
425             sql = "update SUBSCRIPTIONS set SELF_LINK = ?, LOG_LINK = ? where SUBID = ?";\r
426             ps = c.prepareStatement(sql);\r
427             ps.setString(1, getLinks().getSelf());\r
428             ps.setString(2, getLinks().getLog());\r
429             ps.setInt(3, subid);\r
430             ps.execute();\r
431             ps.close();\r
432         } catch (SQLException e) {\r
433             rv = false;\r
434             intlogger.warn("PROV0005 doInsert: " + e.getMessage());\r
435         } finally {\r
436             try {\r
437                 if (ps != null) {\r
438                     ps.close();\r
439                 }\r
440             } catch (SQLException e) {\r
441                 intlogger.error(SQLEXCEPTION + e.getMessage());\r
442             }\r
443         }\r
444         return rv;\r
445     }\r
446 \r
447     @Override\r
448     public boolean doUpdate(Connection c) {\r
449         boolean rv = true;\r
450         PreparedStatement ps = null;\r
451         try {\r
452             String sql = "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ? where SUBID = ?";\r
453             ps = c.prepareStatement(sql);\r
454             ps.setString(1, delivery.getUrl());\r
455             ps.setString(2, delivery.getUser());\r
456             ps.setString(3, delivery.getPassword());\r
457             ps.setInt(4, delivery.isUse100() ? 1 : 0);\r
458             ps.setInt(5, isMetadataOnly() ? 1 : 0);\r
459             ps.setInt(6, suspended ? 1 : 0);\r
460             ps.setInt(7, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
461             ps.setInt(8, privilegedSubscriber ? 1 : 0);\r
462             ps.setInt(9, subid);\r
463             ps.executeUpdate();\r
464         } catch (SQLException e) {\r
465             rv = false;\r
466             intlogger.warn("PROV0006 doUpdate: " + e.getMessage());\r
467         } finally {\r
468             try {\r
469                 if (ps != null) {\r
470                     ps.close();\r
471                 }\r
472             } catch (SQLException e) {\r
473                 intlogger.error(SQLEXCEPTION + e.getMessage());\r
474             }\r
475         }\r
476         return rv;\r
477     }\r
478 \r
479 \r
480     /**\r
481      * Rally US708115 Change Ownership of Subscription - 1610\r
482      */\r
483     public boolean changeOwnerShip() {\r
484         boolean rv = true;\r
485         PreparedStatement ps = null;\r
486         try {\r
487 \r
488             DB db = new DB();\r
489             @SuppressWarnings("resource")\r
490             Connection c = db.getConnection();\r
491             String sql = "update SUBSCRIPTIONS set SUBSCRIBER = ? where SUBID = ?";\r
492             ps = c.prepareStatement(sql);\r
493             ps.setString(1, this.subscriber);\r
494             ps.setInt(2, subid);\r
495             ps.execute();\r
496             ps.close();\r
497         } catch (SQLException e) {\r
498             rv = false;\r
499             intlogger.warn("PROV0006 doUpdate: " + e.getMessage());\r
500         } finally {\r
501             try {\r
502                 if (ps != null) {\r
503                     ps.close();\r
504                 }\r
505             } catch (SQLException e) {\r
506                 intlogger.error(SQLEXCEPTION + e.getMessage());\r
507             }\r
508         }\r
509         return rv;\r
510     }\r
511 \r
512 \r
513     @Override\r
514     public boolean doDelete(Connection c) {\r
515         boolean rv = true;\r
516         PreparedStatement ps = null;\r
517         try {\r
518             String sql = "delete from SUBSCRIPTIONS where SUBID = ?";\r
519             ps = c.prepareStatement(sql);\r
520             ps.setInt(1, subid);\r
521             ps.execute();\r
522         } catch (SQLException e) {\r
523             rv = false;\r
524             intlogger.warn("PROV0007 doDelete: " + e.getMessage());\r
525         } finally {\r
526             try {\r
527                 if (ps != null) {\r
528                     ps.close();\r
529                 }\r
530             } catch (SQLException e) {\r
531                 intlogger.error(SQLEXCEPTION + e.getMessage());\r
532             }\r
533         }\r
534         return rv;\r
535     }\r
536 \r
537     @Override\r
538     public String getKey() {\r
539         return "" + getSubid();\r
540     }\r
541 \r
542     @Override\r
543     public boolean equals(Object obj) {\r
544         if (!(obj instanceof Subscription)) {\r
545             return false;\r
546         }\r
547         Subscription os = (Subscription) obj;\r
548         if (subid != os.subid) {\r
549             return false;\r
550         }\r
551         if (feedid != os.feedid) {\r
552             return false;\r
553         }\r
554         if (groupid != os.groupid) //New field is added - Groups feature Rally:US708115 - 1610\r
555         {\r
556             return false;\r
557         }\r
558         if (!delivery.equals(os.delivery)) {\r
559             return false;\r
560         }\r
561         if (metadataOnly != os.metadataOnly) {\r
562             return false;\r
563         }\r
564         if (!subscriber.equals(os.subscriber)) {\r
565             return false;\r
566         }\r
567         if (!links.equals(os.links)) {\r
568             return false;\r
569         }\r
570         return suspended == os.suspended;\r
571     }\r
572 \r
573     @Override\r
574     public int hashCode() {\r
575         return Objects.hash(subid, feedid, groupid, delivery, metadataOnly, subscriber, links, suspended, lastMod,\r
576                 createdDate);\r
577     }\r
578 \r
579     @Override\r
580     public String toString() {\r
581         return "SUB: subid=" + subid + ", feedid=" + feedid;\r
582     }\r
583 }\r