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 public class DBType
22 {
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"),
34 PASSWORD("password", "The connecting database user's password"),
35 DRIVER("driver", "JDBC driver classname"),
36 CHARACTERSET("characterset","Reader character set"),
37 LANGUAGES("languages", "Comma-separated list of PMD-supported languages"),
38 SCHEMAS("schemas","SchemaSpy compatible regular expression for schemas to be processed"),
39 SOURCE_TYPES("sourcecodetypes","Comma-separated list of supported source types"),
40 SOURCE_NAMES("sourcecodenames", "Default comma-separated list of source code names to validate"),
41 GET_SOURCE_CODE_STATEMENT("getSourceCodeStatement","SQL92 or Oracle embedded SQL statement to retrieve code source from the database catalogue"),
42 RETURN_TYPE("returnType", "int equivalent of java.sql.Types return type of getSourceCodeStatement");
43
44 private String name;
45
46 private property(String name, String description)
47 {
48 this.name = name;
49 }
50 }
51
52
53
54
55
56 private String propertiesSource;
57
58
59
60
61 private Properties properties ;
62
63
64 private String driverClass ;
65
66
67 private String characterSet;
68
69
70 private String sourceCodeTypes;
71
72
73 private String languages;
74
75
76 private int sourceCodeReturnType;
77
78
79
80
81
82 public DBType(String dbType) throws Exception
83 {
84 properties = loadDBProperties(dbType);
85 }
86
87
88
89
90
91
92
93 public DBType(String subProtocol, String subnamePrefix) throws IOException
94 {
95
96 LOGGER.fine("subProtocol="+subProtocol+", subnamePrefix="+subnamePrefix);
97
98 if (null == subProtocol && null == subnamePrefix)
99 {
100 throw new RuntimeException("subProtocol and subnamePrefix cannot both be null");
101 }
102 else
103 {
104
105 properties = null;
106
107
108 if (null != subnamePrefix
109 && null != (properties = loadDBProperties(subnamePrefix))
110 )
111 {
112 LOGGER.log(Level.FINE, "DBType found using subnamePrefix={0}", subnamePrefix);
113 }
114 else if (null != (properties = loadDBProperties(subProtocol) ) )
115 {
116 LOGGER.log(Level.FINE, "DBType found using subProtocol={0}", subProtocol);
117 }
118 else
119 {
120 throw new RuntimeException(String.format("Could not locate DBType properties using subProtocol=%s and subnamePrefix=%s"
121 ,subProtocol
122 ,subnamePrefix
123 )
124 );
125 }
126
127 }
128 }
129
130 public Properties getProperties () {
131
132 return properties;
133 }
134
135
136
137
138
139
140
141
142
143
144 private Properties loadDBProperties(String matchString) throws IOException {
145 LOGGER.entering(CLASS_NAME, matchString);
146
147 ResourceBundle resourceBundle = null;
148
149 LOGGER.finest("class_path+"+System.getProperty("java.class.path"));
150
151
152
153
154
155
156
157
158
159 try {
160 File propertiesFile = new File(matchString);
161 LOGGER.finest("Attempting File no file suffix: " + matchString);
162 resourceBundle = new PropertyResourceBundle(new FileInputStream(propertiesFile));
163 propertiesSource = propertiesFile.getAbsolutePath();
164 LOGGER.finest("FileSystemWithoutExtension");
165 } catch (FileNotFoundException notFoundOnFilesystemWithoutExtension) {
166 LOGGER.finest("notFoundOnFilesystemWithoutExtension");
167 LOGGER.finest("Attempting File with added file suffix: "
168 + matchString + ".properties");
169 try {
170 File propertiesFile = new File(matchString + ".properties");
171 resourceBundle = new PropertyResourceBundle(new FileInputStream(propertiesFile));
172 propertiesSource = propertiesFile.getAbsolutePath();
173 LOGGER.finest("FileSystemWithExtension");
174 } catch (FileNotFoundException notFoundOnFilesystemWithExtensionTackedOn) {
175 LOGGER.finest("Attempting JARWithoutClassPrefix: " + matchString);
176 try {
177 resourceBundle = ResourceBundle.getBundle(matchString);
178 propertiesSource = "[" + INTERNAL_SETTINGS + "]" + File.separator
179 + matchString + ".properties";
180 LOGGER.finest("InJarWithoutPath");
181 } catch (Exception notInJarWithoutPath) {
182 LOGGER.finest("Attempting JARWithClass prefix: " + DBType.CLASS_NAME + "." + matchString);
183 try {
184 resourceBundle = ResourceBundle.getBundle(DBType.CLASS_NAME + "." + matchString);
185 propertiesSource = "[" + INTERNAL_SETTINGS + "]" + File.separator
186 + matchString + ".properties";
187 LOGGER.finest("found InJarWithPath");
188 } catch (Exception notInJarWithPath) {
189 notInJarWithPath.printStackTrace();
190 notFoundOnFilesystemWithExtensionTackedOn.printStackTrace();
191 throw new RuntimeException (" Could not locate DBTYpe settings : "+matchString,notInJarWithPath);
192 }
193 }
194 }
195 }
196
197
198 Properties matchedProperties = getResourceBundleAsProperties(resourceBundle);
199 resourceBundle = null;
200 String saveLoadedFrom = getPropertiesSource();
201
202
203
204
205
206
207
208 String extendedPropertyFile = (String)matchedProperties.remove("extends");
209 if (null != extendedPropertyFile && !"".equals(extendedPropertyFile.trim()) ) {
210 Properties extendedProperties = loadDBProperties(extendedPropertyFile.trim());
211
212
213 extendedProperties.putAll(matchedProperties);
214 matchedProperties = extendedProperties;
215 }
216
217
218
219
220
221 propertiesSource = saveLoadedFrom;
222 setProperties(matchedProperties);
223
224 return matchedProperties;
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 public static Properties getResourceBundleAsProperties(ResourceBundle resourceBundle) {
241 Properties properties = new Properties();
242 for (String key : resourceBundle.keySet() )
243 {
244 properties.put(key, resourceBundle.getObject(key));
245 }
246
247 return properties;
248 }
249
250 public boolean equals(DBType other)
251 {
252
253 return
254 this.getPropertiesSource().equals(other.getPropertiesSource()) &&
255 this.getProperties().equals(other.getProperties()) &&
256 this.getDriverClass().equals(other.getDriverClass()) &&
257 this.getCharacterSet().equals(other.getCharacterSet()) &&
258 this.getSourceCodeTypes().equals(other.getSourceCodeTypes()) &&
259 this.getLanguages().equals(other.getLanguages()) &&
260 this.getSourceCodeReturnType() == other.getSourceCodeReturnType()
261 ;
262 }
263
264
265
266
267 public String getDriverClass() {
268 return driverClass;
269 }
270
271
272
273
274 public String getCharacterSet() {
275 return characterSet;
276 }
277
278
279
280
281 public String getSourceCodeTypes() {
282 return sourceCodeTypes;
283 }
284
285
286
287
288 public String getLanguages() {
289 return languages;
290 }
291
292
293
294
295 public int getSourceCodeReturnType() {
296 return sourceCodeReturnType;
297 }
298
299
300
301
302 public String getPropertiesSource() {
303 return propertiesSource;
304 }
305
306
307
308
309 public void setProperties(Properties properties) {
310 this.properties = properties;
311
312
313 if (null != this.properties.getProperty("driver"))
314 {
315 this.driverClass = this.properties.getProperty("driver");
316 }
317
318
319 if (null != this.properties.getProperty("characterset"))
320 {
321 this.characterSet = this.properties.getProperty("characterset");
322 }
323
324
325 if (null != this.properties.getProperty("sourcecodetypes"))
326 {
327 this.sourceCodeTypes = this.properties.getProperty("sourcecodetypes");
328 }
329
330
331 if (null != this.properties.getProperty("languages"))
332 {
333 this.languages = this.properties.getProperty("languages");
334 }
335
336
337 if (null != this.properties.getProperty("returnType"))
338 {
339 LOGGER.finest("returnType" + this.properties.getProperty("returnType") );
340 this.sourceCodeReturnType = Integer.parseInt(this.properties.getProperty("returnType"));
341 }
342
343 }
344
345 public String toString()
346 {
347 return CLASS_NAME+"@"+propertiesSource;
348 }
349 }