1
2
3
4 package net.sourceforge.pmd.util.database;
5
6 import java.net.MalformedURLException;
7 import java.sql.CallableStatement;
8 import java.sql.Clob;
9 import java.sql.Connection;
10 import java.sql.DatabaseMetaData;
11 import java.sql.DriverManager;
12 import java.sql.PreparedStatement;
13 import java.sql.ResultSet;
14 import java.sql.SQLException;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Properties;
20 import java.util.logging.Level;
21 import java.util.logging.Logger;
22
23
24
25
26
27
28
29 public class DBMSMetadata
30 {
31
32
33
34
35 private final static String CLASS_NAME = DBMSMetadata.class.getCanonicalName();
36
37
38
39
40 private final static Logger LOGGER = Logger.getLogger(CLASS_NAME);
41
42
43
44
45
46
47
48 private final static String GET_SOURCE_OBJECTS_STATEMENT = "getSourceObjectsStatement" ;
49
50
51
52
53
54
55
56 private final static String GET_SOURCE_CODE_STATEMENT = "getSourceCodeStatement" ;
57
58
59
60
61 protected DBURI dburi = null;
62
63
64
65
66 protected Connection connection = null;
67
68
69
70
71 protected String returnSourceCodeObjectsStatement = null ;
72
73
74
75
76 protected String returnSourceCodeStatement = null ;
77
78
79
80
81 protected CallableStatement callableStatement = null;
82
83
84
85
86
87
88 protected int returnType = java.sql.Types.CLOB ;
89
90
91
92
93
94
95
96 public Connection getConnection() throws SQLException
97 { return connection; }
98
99
100
101
102
103
104
105 public DBMSMetadata(Connection c) throws SQLException
106 { connection = c; }
107
108
109
110
111
112
113
114
115
116
117
118 public DBMSMetadata(String user, String password, DBURI dbURI) throws SQLException, MalformedURLException, ClassNotFoundException
119 {
120 String urlString = init(dbURI);
121
122 Properties mergedProperties = dbURI.getDbType().getProperties() ;
123 Map<String,String> dbURIParameters = dbURI.getParameters();
124 mergedProperties.putAll(dbURIParameters) ;
125 mergedProperties.put("user", user) ;
126 mergedProperties.put("password", password) ;
127
128 connection = DriverManager.getConnection(urlString, mergedProperties );
129 if (LOGGER.isLoggable(Level.FINE)) {
130 LOGGER.fine("we have a connection="+connection);
131 }
132 }
133
134
135
136
137
138
139
140
141
142
143
144 public DBMSMetadata(Properties properties, DBURI dbURI) throws SQLException, MalformedURLException, ClassNotFoundException
145 {
146 String urlString = init(dbURI);
147
148 Properties mergedProperties = dbURI.getDbType().getProperties();
149 Map<String,String> dbURIParameters = dbURI.getParameters();
150 mergedProperties.putAll(dbURIParameters) ;
151 mergedProperties.putAll(properties) ;
152
153 if (LOGGER.isLoggable(Level.FINE)) {
154 LOGGER.fine("Retrieving connection for urlString"+urlString);
155 }
156 connection = DriverManager.getConnection(urlString ,mergedProperties);
157 if (LOGGER.isLoggable(Level.FINE)) {
158 LOGGER.fine("Secured Connection for DBURI"+dbURI);
159 }
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public DBMSMetadata(DBURI dbURI) throws SQLException, ClassNotFoundException
175 {
176 String urlString = init(dbURI);
177
178 Properties dbURIProperties = dbURI.getDbType().getProperties();
179 Map<String,String> dbURIParameters = dbURI.getParameters();
180
181
182
183
184
185 dbURIProperties.putAll(dbURIParameters) ;
186
187 connection = DriverManager.getConnection(urlString, dbURIProperties);
188 }
189
190 private String init(DBURI dbURI) throws ClassNotFoundException {
191 this.dburi = dbURI;
192 this.returnSourceCodeObjectsStatement = dbURI.getDbType().getProperties().getProperty(GET_SOURCE_OBJECTS_STATEMENT);
193 this.returnSourceCodeStatement = dbURI.getDbType().getProperties().getProperty(GET_SOURCE_CODE_STATEMENT);
194 this.returnType = dbURI.getSourceCodeType();
195 if (LOGGER.isLoggable(Level.FINE)) {
196 LOGGER.fine("returnSourceCodeStatement="+returnSourceCodeStatement +", returnType="+returnType);
197 }
198
199 String driverClass = dbURI.getDriverClass();
200 String urlString = dbURI.getURL().toString();
201 if (LOGGER.isLoggable(Level.FINE)) {
202 LOGGER.fine("driverClass="+driverClass+", urlString="+urlString);
203 }
204 Class.forName(driverClass);
205 if (LOGGER.isLoggable(Level.FINE)) {
206 LOGGER.fine("Located class for driverClass="+driverClass);
207 }
208 return urlString;
209 }
210
211
212
213
214
215
216
217
218 public java.io.Reader getSourceCode (SourceObject sourceObject )
219 throws SQLException
220 {
221 return getSourceCode(
222 sourceObject.getType(), sourceObject.getName(), sourceObject.getSchema());
223
224 }
225
226
227
228
229
230
231
232
233
234
235 public java.io.Reader getSourceCode (
236 String objectType,
237 String name,
238 String schema
239 )
240 throws SQLException
241 {
242 Object result;
243
244
245 if (null == callableStatement)
246 {
247 if (LOGGER.isLoggable(Level.FINEST)) {
248 LOGGER.finest("getSourceCode: returnSourceCodeStatement=\""+returnSourceCodeStatement+"\"");
249 LOGGER.finest("getSourceCode: returnType=\""+returnType+"\"");
250 }
251 callableStatement = getConnection().prepareCall(returnSourceCodeStatement);
252 callableStatement.registerOutParameter(1, returnType);
253 }
254
255
256 callableStatement.setString(2, objectType);
257 callableStatement.setString(3, name);
258 callableStatement.setString(4, schema);
259
260
261 callableStatement.executeUpdate();
262
263 result = callableStatement.getObject(1);
264
265 return (java.sql.Types.CLOB == returnType)
266 ? ((Clob) result).getCharacterStream()
267 : new java.io.StringReader( result.toString() )
268 ;
269 }
270
271
272
273
274
275 public List<SourceObject> getSourceObjectList ()
276 {
277
278 if (null == dburi)
279 {
280 LOGGER.warning("No dbUri defined - no further action possible");
281 return null;
282 }
283 else
284 {
285 return getSourceObjectList(
286 dburi.getLanguagesList()
287 ,dburi.getSchemasList()
288 ,dburi.getSourceCodeTypesList()
289 ,dburi.getSourceCodeNamesList()
290 );
291 }
292
293 }
294
295
296
297
298
299
300
301
302
303
304
305 public List<SourceObject> getSourceObjectList (List<String> languages, List<String> schemas, List<String> sourceCodeTypes, List<String> sourceCodeNames )
306 {
307
308 ResultSet sourceCodeObjects = null ;
309 List<SourceObject> sourceObjectsList = new ArrayList<SourceObject>() ;
310
311 List<String> searchLanguages = languages ;
312 List<String> searchSchemas = schemas ;
313 List<String> searchSourceCodeTypes = sourceCodeTypes ;
314 List<String> searchSourceCodeNames = sourceCodeNames ;
315 List<String> wildcardList = Arrays.asList(new String[] {"%"} );
316
317
318
319
320
321
322
323
324
325 if( null == searchLanguages )
326 {
327 List dbURIList = (null == dburi) ? null : dburi.getLanguagesList() ;
328 if (null == dbURIList || dbURIList.isEmpty())
329 {
330 searchLanguages = wildcardList;
331 }
332 else
333 {
334 searchLanguages = dbURIList;
335 }
336 }
337
338 if( null == searchSchemas )
339 {
340 List dbURIList = (null == dburi) ? null : dburi.getSchemasList() ;
341 if (null == dbURIList || dbURIList.isEmpty())
342 {
343 searchSchemas = wildcardList;
344 }
345 else
346 {
347 searchSchemas = dbURIList;
348 }
349 }
350
351 if( null == searchSourceCodeTypes )
352 {
353 List dbURIList = (null == dburi) ? null : dburi.getSourceCodeTypesList() ;
354 if (null == dbURIList || dbURIList.isEmpty())
355 {
356 searchSourceCodeTypes = wildcardList;
357 }
358 else
359 {
360 searchSourceCodeTypes = dbURIList;
361 }
362 }
363
364 if( null == searchSourceCodeNames )
365 {
366 List dbURIList = (null == dburi) ? null : dburi.getSourceCodeNamesList() ;
367 if (null == dbURIList || dbURIList.isEmpty())
368 {
369 searchSourceCodeNames = wildcardList;
370 }
371 else
372 {
373 searchSourceCodeNames = dbURIList;
374 }
375 }
376
377 try
378 {
379
380 if (null != returnSourceCodeObjectsStatement)
381 {
382 LOGGER.log(Level.FINE, "Have bespoke returnSourceCodeObjectsStatement from DBURI: \"{0}\""
383 , returnSourceCodeObjectsStatement
384 );
385 PreparedStatement sourceCodeObjectsStatement = getConnection().prepareStatement(returnSourceCodeObjectsStatement);
386
387 for (String language : searchLanguages )
388 {
389 for (String schema : searchSchemas )
390 {
391 for (String sourceCodeType : searchSourceCodeTypes )
392 {
393 for (String sourceCodeName : searchSourceCodeNames )
394 {
395 sourceCodeObjectsStatement.setString(1, language );
396 sourceCodeObjectsStatement.setString(2, schema );
397 sourceCodeObjectsStatement.setString(3, sourceCodeType );
398 sourceCodeObjectsStatement.setString(4, sourceCodeName );
399 LOGGER.finer(String.format("searching for language=\"%s\", schema=\"%s\", sourceCodeType=\"%s\", sourceCodeNames=\"%s\" "
400 ,language
401 ,schema
402 ,sourceCodeType
403 ,sourceCodeName
404 )
405 );
406
407
408
409
410
411
412
413 sourceCodeObjects = sourceCodeObjectsStatement.executeQuery();
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 while( sourceCodeObjects.next() )
431 {
432 LOGGER.finest(String.format("Found schema=%s,object_type=%s,object_name=%s"
433 ,sourceCodeObjects.getString("PROCEDURE_SCHEM")
434 ,sourceCodeObjects.getString("PROCEDURE_TYPE")
435 ,sourceCodeObjects.getString("PROCEDURE_NAME")
436 )
437 );
438
439
440 sourceObjectsList.add(new SourceObject(
441 sourceCodeObjects.getString("PROCEDURE_SCHEM")
442 ,sourceCodeObjects.getString("PROCEDURE_TYPE")
443 ,sourceCodeObjects.getString("PROCEDURE_NAME")
444 ,null
445 )
446 );
447 }
448 }
449 }
450 }
451 }
452 }
453 else
454 {
455 LOGGER.fine("Have dbUri - no returnSourceCodeObjectsStatement, reverting to DatabaseMetaData.getProcedures(...)");
456
457 DatabaseMetaData metadata = connection.getMetaData() ;
458 List<String> schemasList = dburi.getSchemasList() ;
459 for (String schema : schemasList )
460 {
461 for (String sourceCodeName : dburi.getSourceCodeNamesList() )
462 {
463
464
465
466
467
468 sourceCodeObjects = metadata.getProcedures(null
469 ,schema
470 ,sourceCodeName
471 );
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508 while( sourceCodeObjects.next() )
509 {
510 LOGGER.finest(String.format("Located schema=%s,object_type=%s,object_name=%s\n"
511 ,sourceCodeObjects.getString("PROCEDURE_SCHEM")
512 ,sourceCodeObjects.getString("PROCEDURE_TYPE")
513 ,sourceCodeObjects.getString("PROCEDURE_NAME")
514 ));
515
516
517 sourceObjectsList.add(new SourceObject(
518 sourceCodeObjects.getString("PROCEDURE_SCHEM")
519 ,sourceCodeObjects.getString("PROCEDURE_TYPE")
520 ,sourceCodeObjects.getString("PROCEDURE_NAME")
521 ,null
522 )
523 );
524 }
525 }
526 }
527 }
528
529 LOGGER.finer(String.format("Identfied=%d sourceObjects", sourceObjectsList.size()));
530
531 return sourceObjectsList ;
532 }
533 catch (SQLException sqle)
534 {
535 throw new RuntimeException ("Problem collecting list of source code objects",sqle);
536 }
537 }
538 }