1
2
3
4 package net.sourceforge.pmd.util.database;
5
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.FileNotFoundException;
9 import java.io.IOException;
10 import java.util.Properties;
11 import java.util.PropertyResourceBundle;
12 import java.util.ResourceBundle;
13 import java.util.logging.Level;
14 import java.util.logging.Logger;
15
16
17
18
19
20
21
22 public class DBType {
23 private final static String CLASS_NAME = DBType.class.getCanonicalName();
24
25 private final static Logger LOGGER = Logger.getLogger(DBType.class.getPackage().getName());
26
27 private final static String INTERNAL_SETTINGS = "[Internal Settings]";
28
29
30
31
32 public enum property {
33 USER("user", "Name of the connecting database user"), PASSWORD("password",
34 "The connecting database user's password"), DRIVER("driver", "JDBC driver classname"), CHARACTERSET(
35 "characterset", "Reader character set"), LANGUAGES("languages",
36 "Comma-separated list of PMD-supported languages"), SCHEMAS("schemas",
37 "SchemaSpy compatible regular expression for schemas to be processed"), SOURCE_TYPES("sourcecodetypes",
38 "Comma-separated list of supported source types"), SOURCE_NAMES("sourcecodenames",
39 "Default comma-separated list of source code names to validate"), GET_SOURCE_CODE_STATEMENT(
40 "getSourceCodeStatement",
41 "SQL92 or Oracle embedded SQL statement to retrieve code source from the database catalogue"), RETURN_TYPE(
42 "returnType", "int equivalent of java.sql.Types return type of getSourceCodeStatement");
43
44 private String name;
45 private String description;
46
47 private property(String name, String description) {
48 this.name = name;
49 this.description = description;
50 }
51
52 public String getPropertyName() {
53 return name;
54 }
55
56 public String getDescription() {
57 return description;
58 }
59 }
60
61
62
63
64 private String propertiesSource;
65
66
67
68
69 private Properties properties;
70
71
72 private String driverClass;
73
74
75 private String characterSet;
76
77
78 private String sourceCodeTypes;
79
80
81 private String languages;
82
83
84 private int sourceCodeReturnType;
85
86
87
88
89
90 public DBType(String dbType) throws Exception {
91 properties = loadDBProperties(dbType);
92 }
93
94
95
96
97
98
99
100
101 public DBType(String subProtocol, String subnamePrefix) throws IOException {
102
103 if (LOGGER.isLoggable(Level.FINE)) {
104 LOGGER.fine("subProtocol=" + subProtocol + ", subnamePrefix=" + subnamePrefix);
105 }
106
107 if (null == subProtocol && null == subnamePrefix) {
108 throw new RuntimeException("subProtocol and subnamePrefix cannot both be null");
109 } else {
110
111 properties = null;
112
113
114 if (subnamePrefix != null) {
115 properties = loadDBProperties(subnamePrefix);
116 }
117 if (properties == null && subProtocol != null) {
118 properties = loadDBProperties(subProtocol);
119 }
120
121 if (subnamePrefix != null && properties != null) {
122 LOGGER.log(Level.FINE, "DBType found using subnamePrefix={0}", subnamePrefix);
123 } else if (subProtocol != null && properties != null) {
124 LOGGER.log(Level.FINE, "DBType found using subProtocol={0}", subProtocol);
125 } else {
126 throw new RuntimeException(String.format(
127 "Could not locate DBType properties using subProtocol=%s and subnamePrefix=%s", subProtocol,
128 subnamePrefix));
129 }
130
131 }
132 }
133
134 public Properties getProperties() {
135
136 return properties;
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 private Properties loadDBProperties(String matchString) throws IOException {
155 LOGGER.entering(CLASS_NAME, matchString);
156
157 ResourceBundle resourceBundle = null;
158
159 if (LOGGER.isLoggable(Level.FINEST)) {
160 LOGGER.finest("class_path+" + System.getProperty("java.class.path"));
161 }
162
163
164
165
166
167
168 try {
169 File propertiesFile = new File(matchString);
170 if (LOGGER.isLoggable(Level.FINEST)) {
171 LOGGER.finest("Attempting File no file suffix: " + matchString);
172 }
173 resourceBundle = new PropertyResourceBundle(new FileInputStream(propertiesFile));
174 propertiesSource = propertiesFile.getAbsolutePath();
175 LOGGER.finest("FileSystemWithoutExtension");
176 } catch (FileNotFoundException notFoundOnFilesystemWithoutExtension) {
177 if (LOGGER.isLoggable(Level.FINEST)) {
178 LOGGER.finest("notFoundOnFilesystemWithoutExtension");
179 LOGGER.finest("Attempting File with added file suffix: " + matchString + ".properties");
180 }
181 try {
182 File propertiesFile = new File(matchString + ".properties");
183 resourceBundle = new PropertyResourceBundle(new FileInputStream(propertiesFile));
184 propertiesSource = propertiesFile.getAbsolutePath();
185 LOGGER.finest("FileSystemWithExtension");
186 } catch (FileNotFoundException notFoundOnFilesystemWithExtensionTackedOn) {
187 if (LOGGER.isLoggable(Level.FINEST)) {
188 LOGGER.finest("Attempting JARWithoutClassPrefix: " + matchString);
189 }
190 try {
191 resourceBundle = ResourceBundle.getBundle(matchString);
192 propertiesSource = "[" + INTERNAL_SETTINGS + "]" + File.separator + matchString + ".properties";
193 LOGGER.finest("InJarWithoutPath");
194 } catch (Exception notInJarWithoutPath) {
195 if (LOGGER.isLoggable(Level.FINEST)) {
196 LOGGER.finest("Attempting JARWithClass prefix: " + DBType.CLASS_NAME + "." + matchString);
197 }
198 try {
199 resourceBundle = ResourceBundle.getBundle(DBType.CLASS_NAME + "." + matchString);
200 propertiesSource = "[" + INTERNAL_SETTINGS + "]" + File.separator + matchString + ".properties";
201 LOGGER.finest("found InJarWithPath");
202 } catch (Exception notInJarWithPath) {
203 notInJarWithPath.printStackTrace();
204 notFoundOnFilesystemWithExtensionTackedOn.printStackTrace();
205 throw new RuntimeException(" Could not locate DBTYpe settings : " + matchString,
206 notInJarWithPath);
207 }
208 }
209 }
210 }
211
212
213 Properties matchedProperties = getResourceBundleAsProperties(resourceBundle);
214 resourceBundle = null;
215 String saveLoadedFrom = getPropertiesSource();
216
217
218
219
220
221
222 String extendedPropertyFile = (String) matchedProperties.remove("extends");
223 if (null != extendedPropertyFile && !"".equals(extendedPropertyFile.trim())) {
224 Properties extendedProperties = loadDBProperties(extendedPropertyFile.trim());
225
226
227
228 extendedProperties.putAll(matchedProperties);
229 matchedProperties = extendedProperties;
230 }
231
232
233
234
235
236 propertiesSource = saveLoadedFrom;
237 setProperties(matchedProperties);
238
239 return matchedProperties;
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 public static Properties getResourceBundleAsProperties(ResourceBundle resourceBundle) {
257 Properties properties = new Properties();
258 for (String key : resourceBundle.keySet()) {
259 properties.put(key, resourceBundle.getObject(key));
260 }
261
262 return properties;
263 }
264
265 @Override
266 public int hashCode() {
267 final int prime = 31;
268 int result = 1;
269 result = prime * result + ((characterSet == null) ? 0 : characterSet.hashCode());
270 result = prime * result + ((driverClass == null) ? 0 : driverClass.hashCode());
271 result = prime * result + ((languages == null) ? 0 : languages.hashCode());
272 result = prime * result + ((properties == null) ? 0 : properties.hashCode());
273 result = prime * result + ((propertiesSource == null) ? 0 : propertiesSource.hashCode());
274 result = prime * result + sourceCodeReturnType;
275 result = prime * result + ((sourceCodeTypes == null) ? 0 : sourceCodeTypes.hashCode());
276 return result;
277 }
278
279 @Override
280 public boolean equals(Object obj) {
281 if (this == obj) {
282 return true;
283 }
284 if (obj == null) {
285 return false;
286 }
287 if (getClass() != obj.getClass()) {
288 return false;
289 }
290 DBType other = (DBType) obj;
291 if (characterSet == null) {
292 if (other.characterSet != null) {
293 return false;
294 }
295 } else if (!characterSet.equals(other.characterSet)) {
296 return false;
297 }
298 if (driverClass == null) {
299 if (other.driverClass != null) {
300 return false;
301 }
302 } else if (!driverClass.equals(other.driverClass)) {
303 return false;
304 }
305 if (languages == null) {
306 if (other.languages != null) {
307 return false;
308 }
309 } else if (!languages.equals(other.languages)) {
310 return false;
311 }
312 if (properties == null) {
313 if (other.properties != null) {
314 return false;
315 }
316 } else if (!properties.equals(other.properties)) {
317 return false;
318 }
319 if (propertiesSource == null) {
320 if (other.propertiesSource != null) {
321 return false;
322 }
323 } else if (!propertiesSource.equals(other.propertiesSource)) {
324 return false;
325 }
326 if (sourceCodeReturnType != other.sourceCodeReturnType) {
327 return false;
328 }
329 if (sourceCodeTypes == null) {
330 if (other.sourceCodeTypes != null) {
331 return false;
332 }
333 } else if (!sourceCodeTypes.equals(other.sourceCodeTypes)) {
334 return false;
335 }
336 return true;
337 }
338
339
340
341
342 public String getDriverClass() {
343 return driverClass;
344 }
345
346
347
348
349 public String getCharacterSet() {
350 return characterSet;
351 }
352
353
354
355
356 public String getSourceCodeTypes() {
357 return sourceCodeTypes;
358 }
359
360
361
362
363 public String getLanguages() {
364 return languages;
365 }
366
367
368
369
370 public int getSourceCodeReturnType() {
371 return sourceCodeReturnType;
372 }
373
374
375
376
377 public String getPropertiesSource() {
378 return propertiesSource;
379 }
380
381
382
383
384 public void setProperties(Properties properties) {
385 this.properties = properties;
386
387
388 if (null != this.properties.getProperty("driver")) {
389 this.driverClass = this.properties.getProperty("driver");
390 }
391
392
393 if (null != this.properties.getProperty("characterset")) {
394 this.characterSet = this.properties.getProperty("characterset");
395 }
396
397
398 if (null != this.properties.getProperty("sourcecodetypes")) {
399 this.sourceCodeTypes = this.properties.getProperty("sourcecodetypes");
400 }
401
402
403 if (null != this.properties.getProperty("languages")) {
404 this.languages = this.properties.getProperty("languages");
405 }
406
407
408 if (null != this.properties.getProperty("returnType")) {
409 if (LOGGER.isLoggable(Level.FINEST)) {
410 LOGGER.finest("returnType" + this.properties.getProperty("returnType"));
411 }
412 this.sourceCodeReturnType = Integer.parseInt(this.properties.getProperty("returnType"));
413 }
414
415 }
416
417 public String toString() {
418 return CLASS_NAME + "@" + propertiesSource;
419 }
420 }