Fix NPE in toJsonString()
[ccsdk/sli/core.git] / sli / common / src / main / java / org / onap / ccsdk / sli / core / sli / SvcLogicJdbcStore.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                              reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.core.sli;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.sql.Blob;
29 import java.sql.Connection;
30 import java.sql.DatabaseMetaData;
31 import java.sql.Driver;
32 import java.sql.DriverManager;
33 import java.sql.PreparedStatement;
34 import java.sql.ResultSet;
35 import java.sql.SQLException;
36 import java.sql.Statement;
37 import java.util.Properties;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class SvcLogicJdbcStore implements SvcLogicStore {
42     private static final Logger LOG = LoggerFactory.getLogger(SvcLogicJdbcStore.class);
43
44     private String dbUrl = null;
45     private String dbName = null;
46     private String dbUser = null;
47     private String dbPasswd = null;
48     private String dbDriver = null;
49
50     private Connection dbConn;
51     private PreparedStatement hasActiveGraphStmt = null;
52     private PreparedStatement hasVersionGraphStmt = null;
53     private PreparedStatement fetchActiveGraphStmt = null;
54     private PreparedStatement fetchVersionGraphStmt = null;
55     private PreparedStatement storeGraphStmt = null;
56     private PreparedStatement deleteGraphStmt = null;
57
58     private PreparedStatement deactivateStmt = null;
59     private PreparedStatement activateStmt = null;
60
61     private void getConnection() throws ConfigurationException {
62
63         Properties jdbcProps = new Properties();
64
65         jdbcProps.setProperty("user", dbUser);
66         jdbcProps.setProperty("password", dbPasswd);
67
68         try {
69             Driver dvr = new org.mariadb.jdbc.Driver();
70             if (dvr.acceptsURL(dbUrl)) {
71                 LOG.debug("Driver com.mysql.jdbc.Driver accepts {}", dbUrl);
72             } else {
73                 LOG.warn("Driver com.mysql.jdbc.Driver does not accept {}", dbUrl);
74             }
75         } catch (SQLException e1) {
76             LOG.error("Caught exception trying to load com.mysql.jdbc.Driver", e1);
77         }
78
79         try {
80             this.dbConn = DriverManager.getConnection(dbUrl, jdbcProps);
81         } catch (Exception e) {
82             throw new ConfigurationException("failed to get database connection [" + dbUrl + "]", e);
83         }
84
85     }
86
87     private void createTable() throws ConfigurationException {
88
89         DatabaseMetaData dbm;
90
91         try {
92             dbm = dbConn.getMetaData();
93         } catch (SQLException e) {
94
95             throw new ConfigurationException("could not get databse metadata", e);
96         }
97
98         // See if table SVC_LOGIC exists. If not, create it.
99         Statement stmt = null;
100         try {
101
102             ResultSet tables = dbm.getTables(null, null, "SVC_LOGIC", null);
103             if (tables.next()) {
104                 LOG.debug("SVC_LOGIC table already exists");
105             } else {
106                 String crTableCmd = "CREATE TABLE " + dbName + ".SVC_LOGIC (" + "module varchar(80) NOT NULL,"
107                         + "rpc varchar(80) NOT NULL," + "version varchar(40) NOT NULL," + "mode varchar(5) NOT NULL,"
108                         + "active varchar(1) NOT NULL,graph BLOB,"
109                         + "modified_timestamp timestamp ,"
110                         + "md5sum varchar(128) DEFAULT NULL,"
111                         + "CONSTRAINT P_SVC_LOGIC PRIMARY KEY(module, rpc, version, mode))";
112
113                 stmt = dbConn.createStatement();
114                 stmt.executeUpdate(crTableCmd);
115             }
116         } catch (Exception e) {
117             throw new ConfigurationException("could not create SVC_LOGIC table", e);
118         } finally {
119             if (stmt != null) {
120                 try {
121                     stmt.close();
122                 } catch (SQLException e) {
123                     LOG.error("Statement close error ", e);
124                 }
125             }
126         }
127
128         // See if NODE_TYPES table exists and, if not, create it
129         stmt = null;
130         try {
131
132             ResultSet tables = dbm.getTables(null, null, "NODE_TYPES", null);
133             if (tables.next()) {
134                 LOG.debug("NODE_TYPES table already exists");
135             } else {
136                 String crTableCmd = "CREATE TABLE " + dbName + ".NODE_TYPES (" + "nodetype varchar(80) NOT NULL,"
137                         + "CONSTRAINT P_NODE_TYPES PRIMARY KEY(nodetype))";
138
139                 stmt = dbConn.createStatement();
140
141                 stmt.executeUpdate(crTableCmd);
142             }
143         } catch (Exception e) {
144             throw new ConfigurationException("could not create SVC_LOGIC table", e);
145         } finally {
146             if (stmt != null) {
147                 try {
148                     stmt.close();
149                 } catch (SQLException e) {
150                     LOG.error("Statement close error ", e);
151                 }
152             }
153         }
154     }
155
156     private void prepStatements() throws ConfigurationException {
157
158         // Prepare statements
159         String hasVersionGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE
160                 + CommonConstants.JDBC_GRAPH_QUERY;
161
162         try {
163             hasVersionGraphStmt = dbConn.prepareStatement(hasVersionGraphSql);
164         } catch (Exception e) {
165             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e);
166
167         }
168
169         String hasActiveGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE
170                 + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY;
171
172         try {
173             hasActiveGraphStmt = dbConn.prepareStatement(hasActiveGraphSql);
174         } catch (Exception e) {
175             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e);
176
177         }
178
179         String fetchVersionGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE
180                 + CommonConstants.JDBC_GRAPH_QUERY;
181
182         try {
183             fetchVersionGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql);
184         } catch (Exception e) {
185             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e);
186
187         }
188
189         String fetchActiveGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE
190                 + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY;
191
192         try {
193             fetchActiveGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql);
194         } catch (Exception e) {
195             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e);
196
197         }
198
199         String storeGraphSql = CommonConstants.JDBC_INSERT + dbName
200                 + ".SVC_LOGIC (module, rpc, version, mode, active, graph, md5sum) VALUES(?, ?, ?, ?, ?, ?, ?)";
201
202         try {
203             storeGraphStmt = dbConn.prepareStatement(storeGraphSql);
204         } catch (Exception e) {
205             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + storeGraphSql, e);
206         }
207
208         String deleteGraphSql = CommonConstants.JDBC_DELETE + dbName
209                 + ".SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?";
210
211         try {
212             deleteGraphStmt = dbConn.prepareStatement(deleteGraphSql);
213         } catch (Exception e) {
214             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deleteGraphSql, e);
215         }
216
217         String deactivateSql = CommonConstants.JDBC_UPDATE + dbName
218                 + ".SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?";
219
220         try {
221             deactivateStmt = dbConn.prepareStatement(deactivateSql);
222         } catch (Exception e) {
223             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deactivateSql, e);
224         }
225
226         String activateSql = CommonConstants.JDBC_UPDATE + dbName
227                 + ".SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND version = ? AND mode = ?";
228
229         try {
230             activateStmt = dbConn.prepareStatement(activateSql);
231         } catch (Exception e) {
232             throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + activateSql, e);
233         }
234     }
235
236     private void initDbResources() throws ConfigurationException {
237         if ((dbDriver != null) && (dbDriver.length() > 0)) {
238
239             try {
240                 Class.forName(dbDriver);
241             } catch (Exception e) {
242                 throw new ConfigurationException("could not load driver class " + dbDriver, e);
243             }
244         }
245         getConnection();
246         createTable();
247         prepStatements();
248     }
249
250
251     @Override
252     public void init(Properties props) throws ConfigurationException {
253
254
255         dbUrl = props.getProperty("org.onap.ccsdk.sli.jdbc.url");
256         if ((dbUrl == null) || (dbUrl.length() == 0)) {
257             throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.url unset");
258         }
259
260         dbName = props.getProperty("org.onap.ccsdk.sli.jdbc.database");
261         if ((dbName == null) || (dbName.length() == 0)) {
262             throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.database unset");
263         }
264
265         dbUser = props.getProperty("org.onap.ccsdk.sli.jdbc.user");
266         if ((dbUser == null) || (dbUser.length() == 0)) {
267             throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.user unset");
268         }
269
270
271         dbPasswd = props.getProperty("org.onap.ccsdk.sli.jdbc.password");
272         if ((dbPasswd == null) || (dbPasswd.length() == 0)) {
273             throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.password unset");
274         }
275
276         dbDriver = props.getProperty("org.onap.ccsdk.sli.jdbc.driver");
277
278
279         initDbResources();
280
281     }
282
283     private boolean isDbConnValid() {
284
285         boolean isValid = false;
286
287         try {
288             if (dbConn != null) {
289                 isValid = dbConn.isValid(1);
290             }
291         } catch (SQLException e) {
292             LOG.error("Not a valid db connection: ", e);
293         }
294
295         return isValid;
296     }
297
298     @Override
299     public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException {
300
301         if (!isDbConnValid()) {
302
303             // Try reinitializing
304             initDbResources();
305
306             if (!isDbConnValid()) {
307                 throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
308             }
309         }
310
311         boolean retval = false;
312         ResultSet results = null;
313
314         PreparedStatement hasGraphStmt;
315         if (version == null) {
316             hasGraphStmt = hasActiveGraphStmt;
317         } else {
318             hasGraphStmt = hasVersionGraphStmt;
319         }
320
321         try {
322             hasGraphStmt.setString(1, module);
323             hasGraphStmt.setString(2, rpc);
324             hasGraphStmt.setString(3, mode);
325
326
327             if (version != null) {
328                 hasGraphStmt.setString(4, version);
329             }
330             boolean oldAutoCommit = dbConn.getAutoCommit();
331             dbConn.setAutoCommit(false);
332             results = hasGraphStmt.executeQuery();
333             dbConn.commit();
334             dbConn.setAutoCommit(oldAutoCommit);
335
336             if (results.next()) {
337                 int cnt = results.getInt(1);
338
339                 if (cnt > 0) {
340                     retval = true;
341                 }
342
343             }
344         } catch (Exception e) {
345             throw new ConfigurationException("SQL query failed", e);
346         } finally {
347             if (results != null) {
348                 try {
349                     results.close();
350                 } catch (SQLException x) {
351                     LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x);
352                 }
353             }
354
355         }
356
357         return retval;
358
359     }
360
361     @Override
362     public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException {
363
364
365         if (!isDbConnValid()) {
366
367             // Try reinitializing
368             initDbResources();
369
370             if (!isDbConnValid()) {
371                 throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
372             }
373         }
374
375         SvcLogicGraph retval = null;
376         ResultSet results = null;
377
378         PreparedStatement fetchGraphStmt;
379         if (version == null) {
380             fetchGraphStmt = fetchActiveGraphStmt;
381         } else {
382             fetchGraphStmt = fetchVersionGraphStmt;
383         }
384         try {
385             fetchGraphStmt.setString(1, module);
386             fetchGraphStmt.setString(2, rpc);
387             fetchGraphStmt.setString(3, mode);
388
389
390             if (version != null) {
391                 fetchGraphStmt.setString(4, version);
392             }
393             boolean oldAutoCommit = dbConn.getAutoCommit();
394             dbConn.setAutoCommit(false);
395             results = fetchGraphStmt.executeQuery();
396             dbConn.commit();
397             dbConn.setAutoCommit(oldAutoCommit);
398
399             if (results.next()) {
400                 Blob graphBlob = results.getBlob("graph");
401
402                 ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream());
403
404                 Object graphObj = gStream.readObject();
405                 gStream.close();
406
407                 if (graphObj instanceof SvcLogicGraph) {
408                     retval = (SvcLogicGraph) graphObj;
409                 } else {
410                     throw new ConfigurationException("invalid type for graph (" + graphObj.getClass().getName());
411
412                 }
413             }
414
415         } catch (Exception e) {
416             throw new ConfigurationException("SQL query failed", e);
417         } finally {
418             if (results != null) {
419                 try {
420                     results.close();
421                 } catch (SQLException x) {
422                     LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x);
423                 }
424             }
425
426         }
427
428         return retval;
429     }
430
431     public void store(SvcLogicGraph graph) throws SvcLogicException {
432
433
434         if (!isDbConnValid()) {
435
436             // Try reinitializing
437             initDbResources();
438
439             if (!isDbConnValid()) {
440                 throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
441             }
442         }
443
444         if (graph == null) {
445             throw new SvcLogicException("graph cannot be null");
446         }
447
448         byte[] graphBytes;
449
450         try (ByteArrayOutputStream byteStr = new ByteArrayOutputStream();
451                 ObjectOutputStream goutStr = new ObjectOutputStream(byteStr)) {
452
453             goutStr.writeObject(graph);
454
455             graphBytes = byteStr.toByteArray();
456
457         } catch (Exception e) {
458             throw new SvcLogicException("could not serialize graph", e);
459         }
460
461         // If object already stored in database, delete it
462         if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode())) {
463             delete(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode());
464         }
465
466         try {
467             boolean oldAutoCommit = dbConn.getAutoCommit();
468             dbConn.setAutoCommit(false);
469             storeGraphStmt.setString(1,  graph.getModule());
470             storeGraphStmt.setString(2,  graph.getRpc());
471             storeGraphStmt.setString(3, graph.getVersion());
472             storeGraphStmt.setString(4, graph.getMode());
473             storeGraphStmt.setString(5, "N");
474             storeGraphStmt.setBlob(6,  new ByteArrayInputStream(graphBytes));
475              storeGraphStmt.setString(7, graph.getMd5sum());
476
477             storeGraphStmt.executeUpdate();
478             dbConn.commit();
479             
480             dbConn.setAutoCommit(oldAutoCommit);
481         } catch (Exception e) {
482             throw new SvcLogicException("Could not write object to database", e);
483         }
484     }
485
486     @Override
487     public void delete(String module, String rpc, String version, String mode) throws SvcLogicException {
488         if (!isDbConnValid()) {
489
490             // Try reinitializing
491             initDbResources();
492
493             if (!isDbConnValid()) {
494                 throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
495             }
496         }
497
498         try {
499             boolean oldAutoCommit = dbConn.getAutoCommit();
500             dbConn.setAutoCommit(false);
501             deleteGraphStmt.setString(1, module);
502             deleteGraphStmt.setString(2, rpc);
503             deleteGraphStmt.setString(3, version);
504             deleteGraphStmt.setString(4, mode);
505
506
507             deleteGraphStmt.executeUpdate();
508             dbConn.commit();
509             dbConn.setAutoCommit(oldAutoCommit);
510         } catch (Exception e) {
511             throw new SvcLogicException("Could not delete object from database", e);
512         }
513     }
514
515     @Override
516     public void activate(SvcLogicGraph graph) throws SvcLogicException {
517         try {
518             boolean oldAutoCommit = dbConn.getAutoCommit();
519
520             dbConn.setAutoCommit(false);
521
522             // Deactivate any current active version
523             deactivateStmt.setString(1, graph.getModule());
524             deactivateStmt.setString(2, graph.getRpc());
525             deactivateStmt.setString(3, graph.getMode());
526             deactivateStmt.executeUpdate();
527
528             // Activate this version
529             activateStmt.setString(1, graph.getModule());
530             activateStmt.setString(2, graph.getRpc());
531             activateStmt.setString(3, graph.getVersion());
532             activateStmt.setString(4, graph.getMode());
533             activateStmt.executeUpdate();
534
535             dbConn.commit();
536
537             dbConn.setAutoCommit(oldAutoCommit);
538
539         } catch (Exception e) {
540             throw new SvcLogicException("Could not activate graph", e);
541         }
542     }
543
544     @Override
545     public void activate(String module, String rpc, String version, String mode) throws SvcLogicException {
546         try {
547             boolean oldAutoCommit = dbConn.getAutoCommit();
548
549             dbConn.setAutoCommit(false);
550
551             // Deactivate any current active version
552             deactivateStmt.setString(1, module);
553             deactivateStmt.setString(2, rpc);
554             deactivateStmt.setString(3, mode);
555             deactivateStmt.executeUpdate();
556
557             // Activate this version
558             activateStmt.setString(1, module);
559             activateStmt.setString(2, rpc);
560             activateStmt.setString(3, version);
561             activateStmt.setString(4, mode);
562             activateStmt.executeUpdate();
563
564             dbConn.commit();
565
566             dbConn.setAutoCommit(oldAutoCommit);
567
568         } catch (Exception e) {
569             throw new SvcLogicException("Could not activate graph", e);
570         }
571     }
572
573
574 }