1 package org.apache.torque.dsfactory;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Iterator;
23
24 import javax.sql.ConnectionPoolDataSource;
25 import javax.sql.DataSource;
26
27 import org.apache.commons.beanutils.ConvertUtils;
28 import org.apache.commons.beanutils.MappedPropertyDescriptor;
29 import org.apache.commons.beanutils.PropertyUtils;
30 import org.apache.commons.configuration.Configuration;
31 import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS;
32 import org.apache.commons.lang.StringUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.torque.Torque;
36 import org.apache.torque.TorqueException;
37 import org.apache.torque.TorqueRuntimeException;
38
39 /***
40 * A class that contains common functionality of the factories in this
41 * package.
42 *
43 * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
44 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
45 * @version $Id: AbstractDataSourceFactory.java 473821 2006-11-11 22:37:25Z tv $
46 */
47 public abstract class AbstractDataSourceFactory
48 implements DataSourceFactory
49 {
50 /*** "pool" Key for the configuration */
51 public static final String POOL_KEY = "pool";
52
53 /*** "connection" Key for the configuration */
54 public static final String CONNECTION_KEY = "connection";
55
56 /*** "schema" Key for the configuration */
57 public static final String SCHEMA_KEY = "schema";
58
59 /*** "defaults" Key for the configuration */
60 public static final String DEFAULTS_KEY = "defaults";
61
62 /*** "defaults.pool" Key for the configuration */
63 public static final String DEFAULT_POOL_KEY
64 = DEFAULTS_KEY + "." + POOL_KEY;
65
66 /*** "defaults.connection" Key for the configuration */
67 public static final String DEFAULT_CONNECTION_KEY
68 = DEFAULTS_KEY + "." + CONNECTION_KEY;
69
70 /*** default schema name for the configuration */
71 public static final String DEFAULT_SCHEMA_KEY
72 = DEFAULTS_KEY + "." + SCHEMA_KEY;
73
74
75 /*** The log */
76 private static Log log = LogFactory.getLog(AbstractDataSourceFactory.class);
77
78 /*** Internal Marker for the Schema name of this database connection */
79 private String schema = null;
80
81 /***
82 * Encapsulates setting configuration properties on
83 * <code>DataSource</code> objects.
84 *
85 * @param property the property to read from the configuration
86 * @param c the configuration to read the property from
87 * @param ds the <code>DataSource</code> instance to write the property to
88 * @throws Exception if anything goes wrong
89 */
90 protected void setProperty(String property, Configuration c, Object ds)
91 throws Exception
92 {
93 if (c == null || c.isEmpty())
94 {
95 return;
96 }
97
98 String key = property;
99 Class dsClass = ds.getClass();
100 int dot = property.indexOf('.');
101 try
102 {
103 if (dot > 0)
104 {
105 property = property.substring(0, dot);
106
107 MappedPropertyDescriptor mappedPD =
108 new MappedPropertyDescriptor(property, dsClass);
109 Class propertyType = mappedPD.getMappedPropertyType();
110 Configuration subProps = c.subset(property);
111
112 Iterator j = subProps.getKeys();
113 while (j.hasNext())
114 {
115 String subProp = (String) j.next();
116 String propVal = subProps.getString(subProp);
117 Object value = ConvertUtils.convert(propVal, propertyType);
118 PropertyUtils
119 .setMappedProperty(ds, property, subProp, value);
120
121 if (log.isDebugEnabled())
122 {
123 log.debug("setMappedProperty("
124 + ds + ", "
125 + property + ", "
126 + subProp + ", "
127 + value
128 + ")");
129 }
130 }
131 }
132 else
133 {
134 if ("password".equals(key))
135 {
136
137
138
139
140 String value = c.getString(property);
141 PropertyUtils.setSimpleProperty(ds, property, value);
142 if (log.isDebugEnabled())
143 {
144 log.debug("setSimpleProperty("
145 + ds + ", "
146 + property + ", "
147 + " (value not logged)"
148 + ")");
149 }
150 }
151 else
152 {
153 Class propertyType =
154 PropertyUtils.getPropertyType(ds, property);
155 Object value =
156 ConvertUtils.convert(c.getString(property), propertyType);
157 PropertyUtils.setSimpleProperty(ds, property, value);
158
159 if (log.isDebugEnabled())
160 {
161 log.debug("setSimpleProperty("
162 + ds + ", "
163 + property + ", "
164 + value
165 + ")");
166 }
167 }
168 }
169 }
170 catch (RuntimeException e)
171 {
172 throw new TorqueRuntimeException(
173 "Runtime error setting property " + property, e);
174 }
175 catch (Exception e)
176 {
177 log.error(
178 "Property: "
179 + property
180 + " value: "
181 + c.getString(key)
182 + " is not supported by DataSource: "
183 + ds.getClass().getName());
184 }
185 }
186
187 /***
188 * Iterate over a Configuration subset and apply all
189 * properties to a passed object which must contain Bean
190 * setter and getter
191 *
192 * @param c The configuration subset
193 * @param o The object to apply the properties to
194 * @throws TorqueException if a property set fails
195 */
196 protected void applyConfiguration(Configuration c, Object o)
197 throws TorqueException
198 {
199 log.debug("applyConfiguration(" + c + ", " + o + ")");
200
201 if (c != null)
202 {
203 try
204 {
205 for (Iterator i = c.getKeys(); i.hasNext();)
206 {
207 String key = (String) i.next();
208 setProperty(key, c, o);
209 }
210 }
211 catch (Exception e)
212 {
213 log.error(e);
214 throw new TorqueException(e);
215 }
216 }
217 }
218
219 /***
220 * Initializes the ConnectionPoolDataSource.
221 *
222 * @param configuration where to read the settings from
223 * @throws TorqueException if a property set fails
224 * @return a configured <code>ConnectionPoolDataSource</code>
225 */
226 protected ConnectionPoolDataSource initCPDS(Configuration configuration)
227 throws TorqueException
228 {
229 log.debug("Starting initCPDS");
230 ConnectionPoolDataSource cpds = new DriverAdapterCPDS();
231 Configuration c = Torque.getConfiguration();
232
233 if (c == null || c.isEmpty())
234 {
235 log.warn("Global Configuration not set,"
236 + " no Default connection pool data source configured!");
237 }
238 else
239 {
240 Configuration conf = c.subset(DEFAULT_CONNECTION_KEY);
241 applyConfiguration(conf, cpds);
242 }
243
244 Configuration conf = configuration.subset(CONNECTION_KEY);
245 applyConfiguration(conf, cpds);
246
247 return cpds;
248 }
249
250 /***
251 * Sets the current schema for the database connection
252 *
253 * @param schema The current schema name
254 */
255 public void setSchema(String schema)
256 {
257 this.schema = schema;
258 }
259
260 /***
261 * This method returns the current schema for the database connection
262 *
263 * @return The current schema name. Null means, no schema has been set.
264 * @throws TorqueException Any exceptions caught during processing will be
265 * rethrown wrapped into a TorqueException.
266 * @deprecated use DatabaseInfo.setSchema() instead. Will be removed
267 * in a future version of Torque.
268 */
269 public String getSchema()
270 {
271 return schema;
272 }
273
274 /***
275 * @return the <code>DataSource</code> configured by the factory.
276 * @throws TorqueException if the source can't be returned
277 */
278 public abstract DataSource getDataSource()
279 throws TorqueException;
280
281 /***
282 * Initialize the factory.
283 *
284 * @param configuration where to load the factory settings from
285 * @throws TorqueException Any exceptions caught during processing will be
286 * rethrown wrapped into a TorqueException.
287 */
288 public void initialize(Configuration configuration)
289 throws TorqueException
290 {
291 if (configuration == null)
292 {
293 throw new TorqueException(
294 "Torque cannot be initialized without "
295 + "a valid configuration. Please check the log files "
296 + "for further details.");
297 }
298
299 schema = configuration.getString(SCHEMA_KEY, null);
300
301 if (StringUtils.isEmpty(schema))
302 {
303 Configuration conf = Torque.getConfiguration();
304 schema = conf.getString(DEFAULT_SCHEMA_KEY, null);
305 }
306 }
307 }