1 package org.apache.torque.dsfactory;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.Iterator;
20
21 import javax.sql.ConnectionPoolDataSource;
22 import javax.sql.DataSource;
23
24 import org.apache.commons.beanutils.ConvertUtils;
25 import org.apache.commons.beanutils.MappedPropertyDescriptor;
26 import org.apache.commons.beanutils.PropertyUtils;
27
28 import org.apache.commons.configuration.Configuration;
29 import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS;
30
31 import org.apache.commons.lang.StringUtils;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36 import org.apache.torque.Torque;
37 import org.apache.torque.TorqueException;
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 239636 2005-08-24 12:38:09Z henning $
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 (Exception e)
171 {
172 log.error(
173 "Property: "
174 + property
175 + " value: "
176 + c.getString(key)
177 + " is not supported by DataSource: "
178 + ds.getClass().getName());
179 }
180 }
181
182 /***
183 * Iterate over a Configuration subset and apply all
184 * properties to a passed object which must contain Bean
185 * setter and getter
186 *
187 * @param c The configuration subset
188 * @param o The object to apply the properties to
189 * @throws TorqueException if a property set fails
190 */
191 protected void applyConfiguration(Configuration c, Object o)
192 throws TorqueException
193 {
194 log.debug("applyConfiguration(" + c + ", " + o + ")");
195
196 if (c != null)
197 {
198 try
199 {
200 for (Iterator i = c.getKeys(); i.hasNext();)
201 {
202 String key = (String) i.next();
203 setProperty(key, c, o);
204 }
205 }
206 catch (Exception e)
207 {
208 log.error(e);
209 throw new TorqueException(e);
210 }
211 }
212 }
213
214 /***
215 * Initializes the ConnectionPoolDataSource.
216 *
217 * @param configuration where to read the settings from
218 * @throws TorqueException if a property set fails
219 * @return a configured <code>ConnectionPoolDataSource</code>
220 */
221 protected ConnectionPoolDataSource initCPDS(Configuration configuration)
222 throws TorqueException
223 {
224 log.debug("Starting initCPDS");
225 ConnectionPoolDataSource cpds = new DriverAdapterCPDS();
226 Configuration c = Torque.getConfiguration();
227
228 if (c == null || c.isEmpty())
229 {
230 log.warn("Global Configuration not set,"
231 + " no Default connection pool data source configured!");
232 }
233 else
234 {
235 Configuration conf = c.subset(DEFAULT_CONNECTION_KEY);
236 applyConfiguration(conf, cpds);
237 }
238
239 Configuration conf = configuration.subset(CONNECTION_KEY);
240 applyConfiguration(conf, cpds);
241
242 return cpds;
243 }
244
245 /***
246 * Sets the current schema for the database connection
247 *
248 * @param schema The current schema name
249 */
250 public void setSchema(String schema)
251 {
252 this.schema = schema;
253 }
254
255 /***
256 * This method returns the current schema for the database connection
257 *
258 * @return The current schema name. Null means, no schema has been set.
259 * @throws TorqueException Any exceptions caught during processing will be
260 * rethrown wrapped into a TorqueException.
261 */
262 public String getSchema()
263 {
264 return schema;
265 }
266
267 /***
268 * @return the <code>DataSource</code> configured by the factory.
269 * @throws TorqueException if the source can't be returned
270 */
271 public abstract DataSource getDataSource()
272 throws TorqueException;
273
274 /***
275 * Initialize the factory.
276 *
277 * @param configuration where to load the factory settings from
278 * @throws TorqueException Any exceptions caught during processing will be
279 * rethrown wrapped into a TorqueException.
280 */
281 public void initialize(Configuration configuration)
282 throws TorqueException
283 {
284 if (configuration == null)
285 {
286 throw new TorqueException(
287 "Torque cannot be initialized without "
288 + "a valid configuration. Please check the log files "
289 + "for further details.");
290 }
291
292 schema = configuration.getString(SCHEMA_KEY, null);
293
294 if (StringUtils.isEmpty(schema))
295 {
296 Configuration conf = Torque.getConfiguration();
297 schema = conf.getString(DEFAULT_SCHEMA_KEY, null);
298 }
299 }
300 }