1 /*******************************************************************************
\r
2 * ============LICENSE_START==================================================
\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
11 * * http://www.apache.org/licenses/LICENSE-2.0
\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
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
24 package org.onap.dmaap.datarouter.provisioning.beans;
\r
26 import com.att.eelf.configuration.EELFLogger;
\r
27 import com.att.eelf.configuration.EELFManager;
\r
28 import java.io.InvalidObjectException;
\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.util.ArrayList;
\r
34 import java.util.Collection;
\r
35 import java.util.Date;
\r
36 import java.util.List;
\r
37 import java.util.Properties;
\r
38 import org.json.JSONObject;
\r
39 import org.onap.dmaap.datarouter.provisioning.ProvRunner;
\r
40 import org.onap.dmaap.datarouter.provisioning.utils.ProvDbUtils;
\r
41 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;
\r
45 * The representation of a Subscription. Subscriptions can be retrieved from the DB, or stored/updated in the DB.
\r
47 * @author Robert Eby
\r
48 * @version $Id: Subscription.java,v 1.9 2013/10/28 18:06:53 eby Exp $
\r
51 public class Subscription extends Syncable {
\r
53 private static final String SQLEXCEPTION = "SQLException: ";
\r
54 private static final String SUBID_KEY = "subid";
\r
55 private static final String SUBID_COL = "SUBID";
\r
56 private static final String FEEDID_KEY = "feedid";
\r
57 private static final String GROUPID_KEY = "groupid";
\r
58 private static final String LAST_MOD_KEY = "last_mod";
\r
59 private static final String CREATED_DATE = "created_date";
\r
60 private static EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog");
\r
61 private static int nextSubid = getMaxSubID() + 1;
\r
65 private int groupid; //New field is added - Groups feature Rally:US708115 - 1610
\r
66 private SubDelivery delivery;
\r
67 private boolean followRedirect;
\r
68 private boolean metadataOnly;
\r
69 private String subscriber;
\r
70 private SubLinks links;
\r
71 private boolean suspended;
\r
72 private Date lastMod;
\r
73 private Date createdDate;
\r
74 private boolean privilegedSubscriber;
\r
75 private String aafInstance;
\r
76 private boolean decompress;
\r
78 public Subscription() {
\r
83 * Subscription constructor.
\r
84 * @param url url string
\r
85 * @param user user string
\r
86 * @param password password string
\r
88 public Subscription(String url, String user, String password) {
\r
91 this.groupid = -1; //New field is added - Groups feature Rally:US708115 - 1610
\r
92 this.delivery = new SubDelivery(url, user, password, false);
\r
93 this.metadataOnly = false;
\r
94 this.followRedirect = false;
\r
95 this.subscriber = "";
\r
96 this.links = new SubLinks();
\r
97 this.suspended = false;
\r
98 this.lastMod = new Date();
\r
99 this.createdDate = new Date();
\r
100 this.privilegedSubscriber = false;
\r
101 this.aafInstance = "";
\r
102 this.decompress = false;
\r
106 * Subscription constructor.
\r
107 * @param rs resultset from SQL
\r
108 * @throws SQLException in case of SQL error
\r
110 public Subscription(ResultSet rs) throws SQLException {
\r
111 this.subid = rs.getInt(SUBID_COL);
\r
112 this.feedid = rs.getInt("FEEDID");
\r
113 this.groupid = rs.getInt("GROUPID"); //New field is added - Groups feature Rally:US708115 - 1610
\r
114 this.delivery = new SubDelivery(rs);
\r
115 this.metadataOnly = rs.getBoolean("METADATA_ONLY");
\r
116 this.followRedirect = rs.getBoolean("FOLLOW_REDIRECTS");
\r
117 this.subscriber = rs.getString("SUBSCRIBER");
\r
118 this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid),
\r
119 rs.getString("LOG_LINK"));
\r
120 this.suspended = rs.getBoolean("SUSPENDED");
\r
121 this.lastMod = rs.getDate("LAST_MOD");
\r
122 this.createdDate = rs.getDate("CREATED_DATE");
\r
123 this.privilegedSubscriber = rs.getBoolean("PRIVILEGED_SUBSCRIBER");
\r
124 this.aafInstance = rs.getString("AAF_INSTANCE");
\r
125 this.decompress = rs.getBoolean("DECOMPRESS");
\r
129 * Subscription constructor.
\r
130 * @param jo JSONObject
\r
131 * @throws InvalidObjectException in case of object error
\r
133 public Subscription(JSONObject jo) throws InvalidObjectException {
\r
136 // The JSONObject is assumed to contain a vnd.dmaap-dr.subscription representation
\r
137 this.subid = jo.optInt(SUBID_KEY, -1);
\r
138 this.feedid = jo.optInt(FEEDID_KEY, -1);
\r
139 this.groupid = jo.optInt(GROUPID_KEY, -1); //New field is added - Groups feature Rally:US708115 - 1610
\r
140 this.aafInstance = jo.optString("aaf_instance", "legacy");
\r
141 if (!(aafInstance.equalsIgnoreCase("legacy")) && aafInstance.length() > 255) {
\r
142 throw new InvalidObjectException("aaf_instance field is too long");
\r
144 JSONObject jdeli = jo.getJSONObject("delivery");
\r
145 String url = jdeli.getString("url");
\r
146 String user = jdeli.getString("user");
\r
147 final String password = jdeli.getString("password");
\r
148 final boolean use100 = jdeli.getBoolean("use100");
\r
150 //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
\r
151 Properties prop = ProvRunner.getProvProperties();
\r
152 if (!url.startsWith("https://") && isHttpsRelaxationFalseAndHasSyncKey(jo, prop)) {
\r
153 throw new InvalidObjectException("delivery URL is not HTTPS");
\r
156 if (url.length() > 256) {
\r
157 throw new InvalidObjectException("delivery url field is too long");
\r
159 if (user.length() > 60) {
\r
160 throw new InvalidObjectException("delivery user field is too long");
\r
162 if (password.length() > 32) {
\r
163 throw new InvalidObjectException("delivery password field is too long");
\r
165 this.delivery = new SubDelivery(url, user, password, use100);
\r
166 this.metadataOnly = jo.getBoolean("metadataOnly");
\r
167 this.followRedirect = jo.optBoolean("follow_redirect", false);
\r
168 this.suspended = jo.optBoolean("suspend", false);
\r
169 this.privilegedSubscriber = jo.optBoolean("privilegedSubscriber", false);
\r
170 this.decompress = jo.optBoolean("decompress", false);
\r
171 this.subscriber = jo.optString("subscriber", "");
\r
172 JSONObject jol = jo.optJSONObject("links");
\r
173 this.links = (jol == null) ? (new SubLinks()) : (new SubLinks(jol));
\r
174 } catch (InvalidObjectException e) {
\r
176 } catch (Exception e) {
\r
177 intlogger.warn("Invalid JSON: " + e.getMessage(), e);
\r
178 throw new InvalidObjectException("Invalid JSON: " + e.getMessage());
\r
183 * Get specific subscription.
\r
184 * @param sub subscription object
\r
185 * @return subscription
\r
187 public static Subscription getSubscriptionMatching(Subscription sub) {
\r
188 SubDelivery deli = sub.getDelivery();
\r
189 String sql = String.format(
\r
190 "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" "
\r
191 + "and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d "
\r
192 + "and FOLLOW_REDIRECTS = %d",
\r
196 deli.getPassword(),
\r
197 deli.isUse100() ? 1 : 0,
\r
198 sub.isMetadataOnly() ? 1 : 0,
\r
199 sub.isFollowRedirect() ? 1 : 0
\r
201 List<Subscription> list = getSubscriptionsForSQL(sql);
\r
202 return !list.isEmpty() ? list.get(0) : null;
\r
206 * Get subscription by id.
\r
207 * @param id subscription id string
\r
208 * @return subscription
\r
210 public static Subscription getSubscriptionById(int id) {
\r
211 String sql = "select * from SUBSCRIPTIONS where SUBID = " + id;
\r
212 List<Subscription> list = getSubscriptionsForSQL(sql);
\r
213 return !list.isEmpty() ? list.get(0) : null;
\r
216 public static Collection<Subscription> getAllSubscriptions() {
\r
217 return getSubscriptionsForSQL("select * from SUBSCRIPTIONS");
\r
221 * Get subscriptions from SQL.
\r
222 * @param sql SQL statement
\r
223 * @return List of subscriptions
\r
225 private static List<Subscription> getSubscriptionsForSQL(String sql) {
\r
226 List<Subscription> list = new ArrayList<>();
\r
227 try (Connection conn = ProvDbUtils.getInstance().getConnection();
\r
228 PreparedStatement ps = conn.prepareStatement(sql);
\r
229 ResultSet rs = ps.executeQuery()) {
\r
230 while (rs.next()) {
\r
231 Subscription sub = new Subscription(rs);
\r
234 } catch (SQLException e) {
\r
235 intlogger.error("PROV0001 getSubscriptionsForSQL: " + e.toString(), e);
\r
242 * @return subid int
\r
244 public static int getMaxSubID() {
\r
246 try (Connection conn = ProvDbUtils.getInstance().getConnection();
\r
247 PreparedStatement ps = conn.prepareStatement("select MAX(subid) from SUBSCRIPTIONS");
\r
248 ResultSet rs = ps.executeQuery()) {
\r
250 max = rs.getInt(1);
\r
252 } catch (SQLException e) {
\r
253 intlogger.info("getMaxSubID: " + e.getMessage(), e);
\r
259 * Get subscription URL list.
\r
260 * @param feedid feedid int
\r
261 * @return collection of subscription URL
\r
263 public static Collection<String> getSubscriptionUrlList(int feedid) {
\r
264 List<String> list = new ArrayList<>();
\r
265 try (Connection conn = ProvDbUtils.getInstance().getConnection();
\r
266 PreparedStatement stmt = conn.prepareStatement("select SUBID from SUBSCRIPTIONS where FEEDID = ?")) {
\r
267 stmt.setString(1, String.valueOf(feedid));
\r
268 try (ResultSet rs = stmt.executeQuery()) {
\r
269 while (rs.next()) {
\r
270 int subid = rs.getInt(SUBID_COL);
\r
271 list.add(URLUtilities.generateSubscriptionURL(subid));
\r
274 } catch (SQLException e) {
\r
275 intlogger.error(SQLEXCEPTION + e.getMessage(), e);
\r
281 * Return a count of the number of active subscriptions in the DB.
\r
283 * @return the count
\r
285 public static int countActiveSubscriptions() {
\r
287 try (Connection conn = ProvDbUtils.getInstance().getConnection();
\r
288 PreparedStatement ps = conn.prepareStatement("select count(*) from SUBSCRIPTIONS");
\r
289 ResultSet rs = ps.executeQuery()) {
\r
291 count = rs.getInt(1);
\r
293 } catch (SQLException e) {
\r
294 intlogger.warn("PROV0008 countActiveSubscriptions: " + e.getMessage(), e);
\r
299 private boolean isHttpsRelaxationFalseAndHasSyncKey(JSONObject jo, Properties prop) {
\r
300 return prop.get("org.onap.dmaap.datarouter.provserver.https.relaxation").toString().equals("false") && !jo
\r
304 public int getSubid() {
\r
310 * @param subid subid string
\r
312 public void setSubid(int subid) {
\r
313 this.subid = subid;
\r
315 // Create link URLs
\r
316 SubLinks sl = getLinks();
\r
317 sl.setSelf(URLUtilities.generateSubscriptionURL(subid));
\r
318 sl.setLog(URLUtilities.generateSubLogURL(subid));
\r
321 public int getFeedid() {
\r
327 * @param feedid feedid string
\r
329 public void setFeedid(int feedid) {
\r
330 this.feedid = feedid;
\r
332 // Create link URLs
\r
333 SubLinks sl = getLinks();
\r
334 sl.setFeed(URLUtilities.generateFeedURL(feedid));
\r
337 public String getAafInstance() {
\r
338 return aafInstance;
\r
341 public void setAafInstance(String aafInstance) {
\r
342 this.aafInstance = aafInstance;
\r
345 //New getter setters for Groups feature Rally:US708115 - 1610
\r
346 public int getGroupid() {
\r
350 public void setGroupid(int groupid) {
\r
351 this.groupid = groupid;
\r
354 public SubDelivery getDelivery() {
\r
358 public void setDelivery(SubDelivery delivery) {
\r
359 this.delivery = delivery;
\r
362 public boolean isMetadataOnly() {
\r
363 return metadataOnly;
\r
366 public void setMetadataOnly(boolean metadataOnly) {
\r
367 this.metadataOnly = metadataOnly;
\r
370 private boolean isFollowRedirect() {
\r
371 return followRedirect;
\r
374 public void setFollowRedirect(boolean followRedirect) {
\r
375 this.followRedirect = followRedirect;
\r
378 boolean isSuspended() {
\r
382 public void setSuspended(boolean suspended) {
\r
383 this.suspended = suspended;
\r
386 public boolean isPrivilegedSubscriber() {
\r
387 return privilegedSubscriber;
\r
390 public void setPrivilegedSubscriber(boolean privilegedSubscriber) {
\r
391 this.privilegedSubscriber = privilegedSubscriber;
\r
394 public String getSubscriber() {
\r
399 * Subscriber setter.
\r
400 * @param subscriber subscriber string
\r
402 public void setSubscriber(String subscriber) {
\r
403 if (subscriber != null) {
\r
404 if (subscriber.length() > 8) {
\r
405 subscriber = subscriber.substring(0, 8);
\r
407 this.subscriber = subscriber;
\r
411 public SubLinks getLinks() {
\r
415 void setLinks(SubLinks links) {
\r
416 this.links = links;
\r
419 public boolean isDecompress() {
\r
423 public void setDecompress(boolean decompress) {
\r
424 this.decompress = decompress;
\r
428 public JSONObject asJSONObject() {
\r
429 JSONObject jo = new JSONObject();
\r
430 jo.put(SUBID_KEY, subid);
\r
431 jo.put(FEEDID_KEY, feedid);
\r
432 jo.put(GROUPID_KEY, groupid); //New field is added - Groups feature Rally:US708115 - 1610
\r
433 jo.put("delivery", delivery.asJSONObject());
\r
434 jo.put("metadataOnly", metadataOnly);
\r
435 jo.put("follow_redirect", followRedirect);
\r
436 jo.put("subscriber", subscriber);
\r
437 jo.put("links", links.asJSONObject());
\r
438 jo.put("suspend", suspended);
\r
439 jo.put(LAST_MOD_KEY, lastMod.getTime());
\r
440 jo.put(CREATED_DATE, createdDate.getTime());
\r
441 jo.put("privilegedSubscriber", privilegedSubscriber);
\r
442 jo.put("aaf_instance", aafInstance);
\r
443 jo.put("decompress", decompress);
\r
448 * Method to hide attributes.
\r
449 * @param hidepasswords true/false
\r
450 * @return JSONObject
\r
452 public JSONObject asJSONObject(boolean hidepasswords) {
\r
453 JSONObject jo = asJSONObject();
\r
454 if (hidepasswords) {
\r
455 jo.remove(SUBID_KEY); // we no longer hide passwords, however we do hide these
\r
456 jo.remove(FEEDID_KEY);
\r
457 jo.remove(LAST_MOD_KEY);
\r
458 jo.remove(CREATED_DATE);
\r
464 * Method to remove some attributes from JSON.
\r
467 public JSONObject asLimitedJSONObject() {
\r
468 JSONObject jo = asJSONObject();
\r
469 jo.remove(SUBID_KEY);
\r
470 jo.remove(FEEDID_KEY);
\r
471 jo.remove(LAST_MOD_KEY);
\r
477 public boolean doInsert(Connection conn) {
\r
479 PreparedStatement ps = null;
\r
482 // No feed ID assigned yet, so assign the next available one
\r
483 setSubid(nextSubid++);
\r
485 // In case we insert a feed from synchronization
\r
486 if (subid > nextSubid) {
\r
487 nextSubid = subid + 1;
\r
490 // Create the SUBSCRIPTIONS row
\r
491 String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, "
\r
492 + "DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, "
\r
493 + "PRIVILEGED_SUBSCRIBER, FOLLOW_REDIRECTS, DECOMPRESS, AAF_INSTANCE) "
\r
494 + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
\r
495 ps = conn.prepareStatement(sql, new String[]{SUBID_COL});
\r
496 ps.setInt(1, subid);
\r
497 ps.setInt(2, feedid);
\r
498 ps.setString(3, getDelivery().getUrl());
\r
499 ps.setString(4, getDelivery().getUser());
\r
500 ps.setString(5, getDelivery().getPassword());
\r
501 ps.setInt(6, getDelivery().isUse100() ? 1 : 0);
\r
502 ps.setInt(7, isMetadataOnly() ? 1 : 0);
\r
503 ps.setString(8, getSubscriber());
\r
504 ps.setBoolean(9, isSuspended());
\r
505 ps.setInt(10, groupid); //New field is added - Groups feature Rally:US708115 - 1610
\r
506 ps.setBoolean(11, isPrivilegedSubscriber());
\r
507 ps.setInt(12, isFollowRedirect() ? 1 : 0);
\r
508 ps.setBoolean(13, isDecompress());
\r
509 ps.setString(14, getAafInstance());
\r
512 // Update the row to set the URLs
\r
513 sql = "update SUBSCRIPTIONS set SELF_LINK = ?, LOG_LINK = ? where SUBID = ?";
\r
514 ps = conn.prepareStatement(sql);
\r
515 ps.setString(1, getLinks().getSelf());
\r
516 ps.setString(2, getLinks().getLog());
\r
517 ps.setInt(3, subid);
\r
520 } catch (SQLException e) {
\r
522 intlogger.warn("PROV0005 doInsert: " + e.getMessage(), e);
\r
528 } catch (SQLException e) {
\r
529 intlogger.error(SQLEXCEPTION + e.getMessage(), e);
\r
536 public boolean doUpdate(Connection conn) {
\r
538 try (PreparedStatement ps = conn.prepareStatement(
\r
539 "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, "
\r
540 + "DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ?, "
\r
541 + "FOLLOW_REDIRECTS = ?, DECOMPRESS = ? where SUBID = ?")) {
\r
542 ps.setString(1, delivery.getUrl());
\r
543 ps.setString(2, delivery.getUser());
\r
544 ps.setString(3, delivery.getPassword());
\r
545 ps.setInt(4, delivery.isUse100() ? 1 : 0);
\r
546 ps.setInt(5, isMetadataOnly() ? 1 : 0);
\r
547 ps.setInt(6, suspended ? 1 : 0);
\r
548 ps.setInt(7, groupid); //New field is added - Groups feature Rally:US708115 - 1610
\r
549 ps.setInt(8, privilegedSubscriber ? 1 : 0);
\r
550 ps.setInt(9, isFollowRedirect() ? 1 : 0);
\r
551 ps.setInt(10, isDecompress() ? 1 : 0);
\r
552 ps.setInt(11, subid);
\r
553 ps.executeUpdate();
\r
554 } catch (SQLException e) {
\r
556 intlogger.warn("PROV0006 doUpdate: " + e.getMessage(), e);
\r
563 * Rally US708115 Change Ownership of Subscription - 1610.
\r
565 public boolean changeOwnerShip() {
\r
567 try (Connection conn = ProvDbUtils.getInstance().getConnection();
\r
568 PreparedStatement ps = conn.prepareStatement(
\r
569 "update SUBSCRIPTIONS set SUBSCRIBER = ? where SUBID = ?")) {
\r
570 ps.setString(1, this.subscriber);
\r
571 ps.setInt(2, subid);
\r
573 } catch (SQLException e) {
\r
575 intlogger.warn("PROV0006 doUpdate: " + e.getMessage(), e);
\r
582 public boolean doDelete(Connection conn) {
\r
584 try (PreparedStatement ps = conn.prepareStatement("delete from SUBSCRIPTIONS where SUBID = ?")) {
\r
585 ps.setInt(1, subid);
\r
587 } catch (SQLException e) {
\r
589 intlogger.warn("PROV0007 doDelete: " + e.getMessage(), e);
\r
595 public String getKey() {
\r
596 return "" + getSubid();
\r
600 public boolean equals(Object obj) {
\r
601 if (!(obj instanceof Subscription)) {
\r
604 Subscription os = (Subscription) obj;
\r
605 if (subid != os.subid) {
\r
608 if (feedid != os.feedid) {
\r
611 if (groupid != os.groupid) {
\r
612 //New field is added - Groups feature Rally:US708115 - 1610
\r
615 if (!delivery.equals(os.delivery)) {
\r
618 if (metadataOnly != os.metadataOnly) {
\r
621 if (followRedirect != os.followRedirect) {
\r
624 if (!subscriber.equals(os.subscriber)) {
\r
627 if (!links.equals(os.links)) {
\r
630 if (suspended != os.suspended) {
\r
633 if (!aafInstance.equals(os.aafInstance)) {
\r
640 public int hashCode() {
\r
641 return super.hashCode();
\r
645 public String toString() {
\r
646 return "SUB: subid=" + subid + ", feedid=" + feedid;
\r