%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
ca.spaz.cron.datasource.sql.ConnectionManager |
|
|
1 | /* |
|
2 | ******************************************************************************* |
|
3 | * Copyright (c) 2005 Chris Rose and AIMedia |
|
4 | * All rights reserved. ConnectionManager and the accompanying materials |
|
5 | * are made available under the terms of the Common Public License v1.0 |
|
6 | * which accompanies this distribution, and is available at |
|
7 | * http://www.eclipse.org/legal/cpl-v10.html |
|
8 | * |
|
9 | * Contributors: |
|
10 | * Chris Rose |
|
11 | *******************************************************************************/ |
|
12 | package ca.spaz.cron.datasource.sql; |
|
13 | ||
14 | import java.sql.*; |
|
15 | import java.util.*; |
|
16 | ||
17 | import org.apache.log4j.Logger; |
|
18 | ||
19 | import ca.spaz.cron.CRONConfiguration; |
|
20 | import ca.spaz.util.ToolBox; |
|
21 | ||
22 | /** |
|
23 | * Class for JDBC connection management. Provides information about available |
|
24 | * datasources, and provides Connection objects to calling classes that are |
|
25 | * guaranteed to be working. |
|
26 | * |
|
27 | * @author Chris Rose |
|
28 | */ |
|
29 | 14 | public class ConnectionManager { |
30 | ||
31 | /** |
|
32 | * Implementation of the DatabaseID interface for DB name and DB ID |
|
33 | * |
|
34 | * @author Chris Rose |
|
35 | */ |
|
36 | private static class DatabaseIDImpl implements DatabaseID { |
|
37 | ||
38 | private String id; |
|
39 | ||
40 | private String name; |
|
41 | ||
42 | /** |
|
43 | * Create a new instance, with the supplied DB ID and name. |
|
44 | * |
|
45 | * @param dbID |
|
46 | * the ID of the database in the properties file |
|
47 | * @param dbName |
|
48 | * the human-readable name of the database. |
|
49 | */ |
|
50 | public DatabaseIDImpl(String dbID, String dbName) { |
|
51 | this.id = dbID; |
|
52 | this.name = dbName; |
|
53 | } |
|
54 | ||
55 | /* |
|
56 | * (non-Javadoc) |
|
57 | * |
|
58 | * @see ca.spaz.cron.database.DatabaseID#getID() |
|
59 | */ |
|
60 | public String getID() { |
|
61 | return id; |
|
62 | } |
|
63 | ||
64 | /* |
|
65 | * (non-Javadoc) |
|
66 | * |
|
67 | * @see ca.spaz.cron.database.DatabaseID#getName() |
|
68 | */ |
|
69 | public String getName() { |
|
70 | return name; |
|
71 | } |
|
72 | ||
73 | /* |
|
74 | * (non-Javadoc) |
|
75 | * |
|
76 | * @see java.lang.Object#toString() |
|
77 | */ |
|
78 | public String toString() { |
|
79 | return name; |
|
80 | } |
|
81 | ||
82 | } |
|
83 | ||
84 | private static List dbIDList; |
|
85 | ||
86 | private static Map instanceMap; |
|
87 | ||
88 | 20 | private static final Logger logger = Logger |
89 | 20 | .getLogger(ConnectionManager.class); |
90 | ||
91 | /** |
|
92 | * Get the human-friendly name for a connection ID |
|
93 | * |
|
94 | * @param connectionID |
|
95 | * the ID to get the name for |
|
96 | * @return the name of the Connection, or an error message. |
|
97 | */ |
|
98 | static String getConnectionName(String connectionID) { |
|
99 | 884 | return getProperties().getProperty("db." + connectionID + ".name", |
100 | 364 | "Missing DB Name"); |
101 | } |
|
102 | ||
103 | /** |
|
104 | * Retrieve a list of available database IDs. |
|
105 | * |
|
106 | * @return a <code>List</code> containing <code>DatabaseID</code> |
|
107 | * implementations for every available user datasource. |
|
108 | */ |
|
109 | public static List getDatabaseIDs() { |
|
110 | 0 | if (null == dbIDList) { |
111 | 0 | dbIDList = new ArrayList(); |
112 | 0 | String[] ids = getProperties().getProperty("db.dblist", "").split(","); |
113 | 0 | for (int i = 0; i < ids.length; i++) { |
114 | 0 | dbIDList.add(new DatabaseIDImpl(ids[i], getConnectionName(ids[i]))); |
115 | } |
|
116 | } |
|
117 | 0 | return dbIDList; |
118 | } |
|
119 | ||
120 | /** |
|
121 | * Get an instance of a ConnectionManager for a particular dbID. |
|
122 | * |
|
123 | * @param dbID |
|
124 | * the ID of the connection |
|
125 | * @return a <code>ConnectionManager</code> for the ID |
|
126 | */ |
|
127 | public static ConnectionManager getInstance(String dbID) { |
|
128 | 1054 | ConnectionManager dbInstance = (ConnectionManager) getInstanceMap().get( |
129 | 434 | dbID); |
130 | 620 | if (null == dbInstance) { |
131 | 30 | dbInstance = new ConnectionManager(dbID); |
132 | 30 | getInstanceMap().put(dbID, dbInstance); |
133 | } |
|
134 | 620 | return dbInstance; |
135 | } |
|
136 | ||
137 | private static Map getInstanceMap() { |
|
138 | 680 | if (null == instanceMap) { |
139 | 20 | instanceMap = new HashMap(); |
140 | } |
|
141 | 680 | return instanceMap; |
142 | } |
|
143 | ||
144 | /** |
|
145 | * @return |
|
146 | */ |
|
147 | private static CRONConfiguration getProperties() { |
|
148 | 1140 | return CRONConfiguration.getInstance(); |
149 | } |
|
150 | ||
151 | /** |
|
152 | * @param foodDB |
|
153 | */ |
|
154 | private static void registerInstance(ConnectionManager foodDB) { |
|
155 | 30 | getInstanceMap().put(foodDB.dbID, foodDB); |
156 | 30 | } |
157 | ||
158 | private Connection dbc; |
|
159 | ||
160 | private String dbID; |
|
161 | ||
162 | private List listeners; |
|
163 | ||
164 | 30 | private ConnectionManager(String dbID) { |
165 | 30 | this.dbID = dbID; |
166 | 30 | registerInstance(this); |
167 | 30 | } |
168 | ||
169 | /** |
|
170 | * Add an observer for notification when the database connection is made. If |
|
171 | * the database is already connected, fires a notification immediately. |
|
172 | * |
|
173 | * @param observer |
|
174 | * the Observer. |
|
175 | */ |
|
176 | public void addConnectionStatusListener(IConnectionStatusObserver observer) { |
|
177 | 0 | getListeners().add(observer); |
178 | 0 | if (getInstanceMap().containsKey(dbID)) { |
179 | 0 | observer.connectionMade(dbID); |
180 | } |
|
181 | 0 | } |
182 | ||
183 | /** |
|
184 | * Get the database connection. Lazy initializer. |
|
185 | * |
|
186 | * @return the connection to the food database or null if there is no |
|
187 | * connection possible. |
|
188 | */ |
|
189 | public Connection getConnection() { |
|
190 | try { |
|
191 | /* |
|
192 | * This is a test to determine if the connection is 'live' -- if it is |
|
193 | * not, we'll be replacing it with a new one. |
|
194 | */ |
|
195 | 620 | if (dbc != null) { |
196 | 590 | dbc.createStatement().execute( |
197 | "CREATE TABLE _garbage___(id char(1))"); |
|
198 | 0 | dbc.createStatement().execute("DROP TABLE _garbage___"); |
199 | } |
|
200 | 590 | } catch (SQLException e) { |
201 | 590 | if (logger.isDebugEnabled()) { |
202 | 0 | logger.debug("getConnection() - lost working connection to DB [" |
203 | + dbID + "]", e); |
|
204 | } |
|
205 | 590 | dbc = null; |
206 | 9 | } |
207 | 620 | if (dbc == null) { |
208 | /* |
|
209 | * Acquire a connection based on values set in db.properties |
|
210 | */ |
|
211 | 620 | CRONConfiguration p = getProperties(); |
212 | /* |
|
213 | * Load the db properties. Defaults are specified for server mode |
|
214 | * operation. |
|
215 | */ |
|
216 | 620 | String serverMode = ""; |
217 | 620 | serverMode = p.getProperty("db." + dbID); |
218 | 620 | if (null == serverMode) { |
219 | 0 | logger.error("Incomplete properties -- missing datasource for " |
220 | + dbID); |
|
221 | } |
|
222 | 620 | String classname = p.getProperty("db." + serverMode + ".driverclass"); |
223 | 620 | String url = p.getProperty("db." + serverMode + ".url"); |
224 | 620 | int idx = url.indexOf("${APP_HOME}"); |
225 | 620 | if (idx >= 0) { |
226 | 0 | String oldURL = url; |
227 | 0 | url = oldURL.substring(0, idx) + ToolBox.getUserAppDirectory("cronometer").getAbsolutePath() + oldURL.substring(idx + "${APP_HOME}".length()); |
228 | } |
|
229 | 620 | String username = p.getProperty("db." + serverMode + ".username"); |
230 | 620 | String password = p.getProperty("db." + serverMode + ".password"); |
231 | 620 | if (null == url || class="keyword">null == classname || class="keyword">null == username |
232 | 434 | || null == password) { |
233 | 0 | logger.error("Incomplete properties for [" + dbID + "] source " |
234 | + serverMode); |
|
235 | 0 | return null; |
236 | } |
|
237 | try { |
|
238 | 620 | if (logger.isInfoEnabled()) { |
239 | 0 | logger |
240 | .info("getConnection() - Acquiring db connection to : url = " |
|
241 | + url); |
|
242 | } |
|
243 | ||
244 | 620 | Class.forName(classname).newInstance(); |
245 | 620 | dbc = DriverManager.getConnection(url, username, password); |
246 | 620 | notifyObservers(); |
247 | 0 | } catch (Exception e) { |
248 | 0 | logger.error("getConnection()", e); |
249 | 186 | } |
250 | } |
|
251 | 620 | return dbc; |
252 | } |
|
253 | ||
254 | private List getListeners() { |
|
255 | 620 | if (null == listeners) { |
256 | 30 | listeners = new ArrayList(); |
257 | } |
|
258 | 620 | return listeners; |
259 | } |
|
260 | ||
261 | private void notifyObservers() { |
|
262 | 1054 | for (Iterator iter = getListeners().iterator(); iter.hasNext();) { |
263 | 0 | IConnectionStatusObserver element = (IConnectionStatusObserver) iter |
264 | .next(); |
|
265 | 0 | element.connectionMade(dbID); |
266 | 0 | } |
267 | 620 | } |
268 | ||
269 | /** |
|
270 | * Remove an observer from this ConnectionManager |
|
271 | * |
|
272 | * @param observer |
|
273 | * the Observer to remove. |
|
274 | */ |
|
275 | public void removeConnectionStatusListener(IConnectionStatusObserver observer) { |
|
276 | 0 | getListeners().remove(observer); |
277 | 0 | } |
278 | ||
279 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |