1 package com.explosion.expfmodules.rdbmsconn;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Properties;
30 import java.util.StringTokenizer;
31 import java.util.Vector;
32 import java.util.prefs.Preferences;
33
34 import org.apache.log4j.LogManager;
35 import org.apache.log4j.Logger;
36
37 import com.explosion.utilities.GeneralConstants;
38 import com.explosion.utilities.GeneralUtils;
39 import com.explosion.utilities.PropertiesUtils;
40 import com.explosion.utilities.exception.ExceptionManagerFactory;
41 import com.explosion.utilities.preferences.Preference;
42 import com.explosion.utilities.preferences.groups.PreferenceGroup;
43 import com.explosion.utilities.preferences.groups.PreferenceGroupManager;
44
45 /***
46 * @author Stephen Cowx Date created:@25-Jan-2003
47 * This class holds information about a set of drivers.
48 *
49 * I guess you should only normally need one of these per application
50 */
51 public class DriverDescriptorManager extends PreferenceGroupManager
52 {
53
54 private static Logger log = LogManager.getLogger(DriverDescriptorManager.class);
55 private Properties driverProperties;
56 protected String driverFileName;
57 private Map driverDetails = new HashMap();
58 private List embeddedList = new ArrayList();
59
60
61 public DriverDescriptorManager(Object referenceToStore) throws Exception
62 {
63 super(referenceToStore);
64 loadUsing(referenceToStore);
65 }
66
67 /***
68 * Loads the preferences from storage and initialises them. It will
69 * reconcile the loaded entries with those it finds in the properties file
70 * "driver.properties".
71 */
72 public void loadUsing(Object referenceToStore) throws Exception
73 {
74 loadUsing(referenceToStore, RdbmsConnConstants.EMBEDDED_PROPERTIES_FILE);
75 }
76
77 /***
78 * This method is used mainly for testing. It allows an override of the
79 * default properties file "driver.properties".
80 */
81 public void loadUsing(Object referenceToStore, String driverFileName) throws Exception
82 {
83 if (referenceToStore instanceof Preferences)
84 {
85 this.driverFileName = driverFileName;
86
87
88 loadDriverDetails();
89
90
91 Preferences root = (Preferences) referenceToStore;
92 String[] names = root.childrenNames();
93 for (int i = 0; i < names.length; i++)
94 {
95
96 this.addGroup(names[i], createGroup(names[i]));
97 }
98
99
100 for (Iterator it = embeddedList.iterator(); it.hasNext();)
101 {
102 createOrUpdateEmbeddedDriver((String)it.next());
103 }
104 }
105 else
106 {
107
108 }
109 }
110
111 /***
112 * Return the correct node for the group with the given identifier
113 * @param identifier
114 * @return
115 */
116 public Object getReferenceForGroup(String identifier)
117 {
118 if (getReferenceToStore() instanceof Preferences)
119 {
120 Preferences pref = (Preferences) getReferenceToStore();
121 return pref.node(identifier);
122 }
123 else
124 {
125 return new HashMap();
126 }
127
128 }
129
130 /***
131 * This method creates a new ConnectionPersistentObject
132 */
133 public PreferenceGroup createGroup(String driverLabel) throws Exception
134 {
135 Object correctReferenceForThisGroup = getReferenceForGroup(driverLabel);
136
137 DriverDetails drvr = (DriverDetails) driverDetails.get(driverLabel);
138
139 Preference embedded = new Preference(RdbmsConnConstants.DRVR_EMBEDDED, Preference.PROPERTY_TYPE_BOOLEAN, drvr == null ? new Boolean(false) : new Boolean(drvr.isEmbedded()) , correctReferenceForThisGroup);
140 embedded.setLongName("Embedded");
141 embedded.setDescription("This indicates whether the driver is to be found on the classpath of the program or on an independantly specified path.");
142 embedded.setEditable(false);
143 embedded.setVisible(false);
144
145 Preference supportsNamespaces = new Preference(RdbmsConnConstants.DRVR_DB_SUPPORTS_NAMESPACES, Preference.PROPERTY_TYPE_BOOLEAN, drvr == null ? new Boolean(true) : new Boolean(drvr.isDbSupportsNamespaces()) , correctReferenceForThisGroup);
146 supportsNamespaces.setLongName("Supports namespaces");
147 supportsNamespaces.setDescription("Indicates whether or not this database/driver schema supports namespaces such as Schemas and Catalogs.");
148
149 Preference useQuotes = new Preference(RdbmsConnConstants.DRVR_USE_QUOTES_WITH_IDENTIFERS, Preference.PROPERTY_TYPE_BOOLEAN, new Boolean(false) , correctReferenceForThisGroup);
150 useQuotes.setLongName("Use quotes around identifiers");
151 useQuotes.setDescription("Indicates whether or not this database/driver should surround identifiers with quotes when creating SQL queries. This is relevant in databases where the identiers are case-sensitive.");
152
153 Preference rememberedPossibleValues = new Preference(RdbmsConnConstants.DRVR_POSSIBLE_VALUES, Preference.PROPERTY_TYPE_TEXT, drvr == null ? "" : drvr.getClassNamesString(), correctReferenceForThisGroup);
154 rememberedPossibleValues.setLongName("Remembered possible driver names");
155 rememberedPossibleValues.setDescription("This is a list of the driver names which are in the path of this driver file.");
156 rememberedPossibleValues.setEditable(false);
157 rememberedPossibleValues.setVisible(false);
158
159 Preference location = new Preference(RdbmsConnConstants.DRVR_LOCATION, Preference.PROPERTY_TYPE_COLLECTION, Preference.PROPERTY_TYPE_FILE, new File(GeneralConstants.DEFAULT_FILE), correctReferenceForThisGroup);
160 location.setLongName("Driver libraries");
161 location.setDescription("This is the location of the library or libraries containing the actual JDBC driver. It should point to at least one jar file on the local drive or the network. It may point to more than one if the driver requires supporting jar files.");
162
163 DriverDescriptorPreference driver = new DriverDescriptorPreference(RdbmsConnConstants.DRVR_NAME, Preference.PROPERTY_TYPE_STRING_CHOICE, "", correctReferenceForThisGroup);
164 driver.setLongName("Driver name");
165 driver.setDescription("The name given to the driver by the driver authors. Be aware that there might be more than one driver in your driver file, be sure to select the correct one.");
166
167
168
169 PreferenceGroup driverGroup = new PreferenceGroup(correctReferenceForThisGroup, driverLabel);
170 driverGroup.addPreference(RdbmsConnConstants.DRVR_LOCATION, location);
171 driverGroup.addPreference(RdbmsConnConstants.DRVR_DB_SUPPORTS_NAMESPACES, supportsNamespaces);
172 driverGroup.addPreference(RdbmsConnConstants.DRVR_EMBEDDED, embedded);
173 driverGroup.addPreference(RdbmsConnConstants.DRVR_POSSIBLE_VALUES, rememberedPossibleValues);
174 driverGroup.addPreference(RdbmsConnConstants.DRVR_USE_QUOTES_WITH_IDENTIFERS, useQuotes);
175
176
177 if (drvr != null && drvr.isEmbedded())
178 {
179 driver.setChoiceValues(drvr.getClassNames());
180 driver.setValue(drvr.getClassNames().get(0));
181 driverGroup.addPreference(RdbmsConnConstants.DRVR_NAME, driver);
182 driverGroup.setEditable(false);
183 }
184 else
185 {
186 driver.initialiseNonEmbeddedDriver(location, rememberedPossibleValues);
187 location.addPreferenceChangeListener(driver);
188 driverGroup.addPreference(RdbmsConnConstants.DRVR_NAME, driver);
189 }
190
191 return driverGroup;
192 }
193
194
195 /***
196 * If an embedded driver exists it will be updated, if it does not, it will be created
197 *
198 * @throws Exception
199 */
200 private void createOrUpdateEmbeddedDriver(String driverLabel) throws Exception
201 {
202
203 PreferenceGroup driver = this.getGroup(driverLabel);
204 if (driver == null)
205 {
206
207 this.addGroup(driverLabel, createGroup(driverLabel));
208 }
209 else
210 {
211
212 PreferenceGroup newDesc = createGroup(driverLabel);
213 this.setGroup(driverLabel, newDesc);
214 }
215 }
216
217 /***
218 * This method loads the driver details from the list of drivers in the
219 * driver.properties file.
220 *
221 * @throws Exception
222 */
223 private void loadDriverDetails() throws Exception
224 {
225 driverProperties = PropertiesUtils.loadPropertiesFromClasspath(driverFileName, this.getClass().getClassLoader());
226 if (driverProperties != null)
227 {
228
229 Map embeddedDrivers = findEmbeddedDrivers();
230
231
232 getDriverDetails(embeddedDrivers);
233
234 }
235 else
236 {
237 log.warn("No embedded driver information available as file " + driverFileName + " cannot be found.");
238 }
239 }
240
241 /***
242 * Loads information about all of the drivers
243 * @param embeddedDrivers
244 * @throws Exception
245 */
246 private void getDriverDetails(Map embeddedDrivers) throws Exception
247 {
248 driverDetails = new HashMap();
249 int itemCount = 0;
250 try
251 {
252 String itemString = driverProperties.getProperty(RdbmsConnConstants.EMBEDDED_PROPERTIES_ITEMS_DRIVERS);
253 if (itemString == null )
254 throw new Exception("Mandatory property " + RdbmsConnConstants.EMBEDDED_PROPERTIES_ITEMS_DRIVERS + " was missing from the properties file.");
255
256 itemCount = Integer.parseInt(itemString);
257 if (itemCount < 1)
258 log.warn("No driver information found in driver properties file " + driverFileName);
259 }
260 catch (NumberFormatException e)
261 {
262 ExceptionManagerFactory.getExceptionManager().manageException(e,"Property "+RdbmsConnConstants.EMBEDDED_PROPERTIES_ITEMS_DRIVERS+" specified in properties file " + driverFileName + " is not a valid integer.");
263 }
264
265 for (int i=1;i<=itemCount;i++)
266 {
267 String driverLabel = (String) driverProperties.getProperty(i + "." + RdbmsConnConstants.EMBEDDED_PROP_LABEL);
268 String driverClassNames = (String) driverProperties.getProperty(i + "." + RdbmsConnConstants.EMBEDDED_PROP_CLASSNAMES);
269 String driverSupportsNamespaces = (String) driverProperties.getProperty(i + "." + RdbmsConnConstants.EMBEDDED_PROP_SUPPORTS_NAMESPACES);
270
271 DriverDetails drvr = new DriverDetails();
272
273 if (embeddedDrivers.get(Integer.toString(i)) != null)
274 {
275 if (embeddedList == null)
276 embeddedList = new ArrayList();
277
278 embeddedList.add(driverLabel);
279
280 drvr.setEmbedded(true);
281
282 if (driverLabel == null)
283 throw new Exception("Mandatory property " + i + "." + RdbmsConnConstants.EMBEDDED_PROP_LABEL + " was missing from the properties file.");
284
285 if (driverClassNames == null)
286 throw new Exception("Mandatory property " + i + "." + RdbmsConnConstants.EMBEDDED_PROP_CLASSNAMES + " was missing from the properties file.");
287 }
288
289 if (driverSupportsNamespaces != null)
290 {
291 drvr.setDbSupportsNamespaces(GeneralUtils.getLenientBoolean(driverSupportsNamespaces));
292 }
293
294
295 if (driverClassNames != null)
296 {
297 StringTokenizer classNamesTokenizer = new StringTokenizer(driverClassNames, ",");
298 Vector classNames = new Vector();
299 while (classNamesTokenizer.hasMoreTokens())
300 {
301 classNames.add(classNamesTokenizer.nextToken().trim());
302 }
303 drvr.setClassNames(classNames);
304 drvr.setClassNamesString(driverClassNames);
305 }
306
307 drvr.setLabel(driverLabel);
308
309 driverDetails.put(driverLabel,drvr);
310 }
311 }
312
313 /***
314 * Makes a map of keys which are embedded drivers
315 * @param embeddedDrivers
316 */
317 private Map findEmbeddedDrivers()
318 {
319 /***
320 * Look for and mark embedded drivers
321 */
322 Map embeddedDrivers = new HashMap();
323 String embeddedDriversString = (String) driverProperties.getProperty(RdbmsConnConstants.EMBEDDED_PROPERTIES_EMBEDDED_DRIVERS);
324 if (embeddedDriversString != null)
325 {
326 StringTokenizer tokenizer = new StringTokenizer(embeddedDriversString, ",");
327 while (tokenizer.hasMoreTokens())
328 {
329 embeddedDrivers.put(tokenizer.nextToken(), "");
330 }
331 }
332 else
333 {
334 log.warn("No embedded drivers found in driver properties file " + driverFileName);
335 }
336
337 return embeddedDrivers;
338 }
339 }
340
341 /***
342 * Small helper class to store temporary information about an embedded driver
343 * once it has been read from a properties file
344 *
345 * @author Stephen Cowx Created on 18-Oct-2004
346 */
347
348 class DriverDetails
349 {
350 private String label;
351 private Vector classNames;
352 private String classNamesString;
353 private boolean isEmbedded;
354 private boolean dbSupportsNamespaces = true;
355
356 public Vector getClassNames()
357 {
358 return classNames;
359 }
360
361 public void setClassNames(Vector classNames)
362 {
363 this.classNames = classNames;
364 }
365
366 public String getLabel()
367 {
368 return label;
369 }
370
371 public void setLabel(String label)
372 {
373 this.label = label;
374 }
375
376 public boolean isEmbedded()
377 {
378 return isEmbedded;
379 }
380
381 public void setEmbedded(boolean isEmbedded)
382 {
383 this.isEmbedded = isEmbedded;
384 }
385
386 public String getClassNamesString()
387 {
388 return classNamesString;
389 }
390
391 public void setClassNamesString(String classNamesString)
392 {
393 this.classNamesString = classNamesString;
394 }
395
396 public boolean isDbSupportsNamespaces() {
397 return dbSupportsNamespaces;
398 }
399
400 public void setDbSupportsNamespaces(boolean dbSupportsNamespaces) {
401 this.dbSupportsNamespaces = dbSupportsNamespaces;
402 }
403 }
404