View Javadoc

1   package org.apache.torque.dsfactory;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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                 // use reflection to set properties
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                     // do not log value of password
137                     // for this, ConvertUtils.convert cannot be used
138                     // as it also logs the value of the converted property
139                     // so it is assumed here that the password is a String
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 }