| %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. |