KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > ConnectionFactoryAbstractImpl


1 package org.apache.ojb.broker.accesslayer;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
19 import org.apache.ojb.broker.platforms.PlatformException;
20 import org.apache.ojb.broker.platforms.PlatformFactory;
21 import org.apache.ojb.broker.util.ClassHelper;
22 import org.apache.ojb.broker.util.logging.Logger;
23 import org.apache.ojb.broker.util.logging.LoggerFactory;
24
25 import javax.naming.InitialContext JavaDoc;
26 import javax.naming.NamingException JavaDoc;
27 import javax.sql.DataSource JavaDoc;
28 import java.sql.Connection JavaDoc;
29 import java.sql.DriverManager JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Properties JavaDoc;
34
35 /**
36  * Abstract base class to simplify implementation of {@link ConnectionFactory}'s.
37  *
38  * @author <a HREF="mailto:armin@codeAuLait.de">Armin Waibel</a>
39  * @version $Id: ConnectionFactoryAbstractImpl.java,v 1.10.2.5 2005/04/30 20:55:15 mkalen Exp $
40  */

41 public abstract class ConnectionFactoryAbstractImpl implements ConnectionFactory
42 {
43     private Logger log = LoggerFactory.getLogger(ConnectionFactoryAbstractImpl.class);
44
45     /**
46      * holds the datasource looked up from JNDI in a map, keyed
47      * by the JNDI name.
48      */

49     private Map JavaDoc dataSourceCache = new HashMap JavaDoc();
50
51     /**
52      * Returns a valid JDBC Connection. Implement this method in concrete subclasses.
53      * Concrete implementations using Connection pooling are responsible for any validation
54      * and pool removal management.
55      * <p>
56      * Note: This method is never called for a jdbc-connection-descriptor that uses datasources,
57      * OJB only manages connections from DriverManager.
58      * <p>
59      * Note: If the concrete implementation does not callback to
60      * {@link #newConnectionFromDriverManager(org.apache.ojb.broker.metadata.JdbcConnectionDescriptor)}
61      * when creating a new Connection, it <em>must</em> call
62      * {@link #initializeJdbcConnection(java.sql.Connection, org.apache.ojb.broker.metadata.JdbcConnectionDescriptor)}
63      * so that the platform implementation can peform any RDBMS-specific init tasks for newly
64      * created Connection objetcs.
65      *
66      * @param jcd the connection descriptor for which to return a validated Connection
67      * @return a valid Connection, never null.
68      * Specific implementations <em>must</em> guarantee that the connection is not null and
69      * that it is valid.
70      * @throws LookupException if a valid Connection could not be obtained
71      */

72     public abstract Connection JavaDoc checkOutJdbcConnection(JdbcConnectionDescriptor jcd)
73             throws LookupException;
74
75     /**
76      * Releases a Connection after use. Implement this method in concrete subclasses.
77      * Concrete implementations using Connection pooling are responsible for any validation
78      * and pool removal management.
79      * <p>
80      * Note: This method is never called for a jdbc-connection-descriptor that uses datasources,
81      * OJB only manages connections from DriverManager.
82      *
83      * @param jcd the connection descriptor for which the connection was created
84      * @param con the connection to release.
85      * Callers <em>must</em> guarantee that the passed connection was obtained by calling
86      * {@link #checkOutJdbcConnection(org.apache.ojb.broker.metadata.JdbcConnectionDescriptor)}.
87      * @throws LookupException if errors occured during release of object. Typically happens
88      * if return of object to pool fails in a pooled implementation.
89      */

90     public abstract void releaseJdbcConnection(JdbcConnectionDescriptor jcd, Connection JavaDoc con)
91             throws LookupException;
92
93     public void releaseConnection(JdbcConnectionDescriptor jcd, Connection JavaDoc con)
94     {
95         if (con == null) return;
96         if (jcd.isDataSource())
97         {
98             try
99             {
100                 con.close();
101             }
102             catch (SQLException JavaDoc e)
103             {
104                 log.error("Closing connection failed", e);
105             }
106         }
107         else
108         {
109             try
110             {
111                 releaseJdbcConnection(jcd, con);
112             }
113             catch (LookupException e)
114             {
115                 log.error("Unexpected exception when return connection " + con +
116                         " to pool using " + jcd, e);
117             }
118         }
119     }
120
121     public Connection JavaDoc lookupConnection(JdbcConnectionDescriptor jcd) throws LookupException
122     {
123         Connection JavaDoc conn;
124         /*
125         use JNDI datasourcelookup or ordinary jdbc DriverManager
126         to obtain connection ?
127         */

128         if (jcd.isDataSource())
129         {
130             if (log.isDebugEnabled())
131             {
132                 log.debug("do datasource lookup, name: " + jcd.getDatasourceName() +
133                         ", user: " + jcd.getUserName());
134             }
135             conn = newConnectionFromDataSource(jcd);
136         }
137         else
138         {
139             conn = checkOutJdbcConnection(jcd);
140             // connection is now guaranteed to be valid by API contract (else exception is thrown)
141
}
142         return conn;
143     }
144
145     /**
146      * Initialize the connection with the specified properties in OJB
147      * configuration files and platform depended properties.
148      * Invoke this method after a NEW connection is created, not if re-using from pool.
149      *
150      * @see org.apache.ojb.broker.platforms.PlatformFactory
151      * @see org.apache.ojb.broker.platforms.Platform
152      */

153     protected void initializeJdbcConnection(Connection JavaDoc con, JdbcConnectionDescriptor jcd)
154             throws LookupException
155     {
156         try
157         {
158             PlatformFactory.getPlatformFor(jcd).initializeJdbcConnection(jcd, con);
159         }
160         catch (PlatformException e)
161         {
162             throw new LookupException("Platform dependent initialization of connection failed", e);
163         }
164     }
165
166     /**
167      * Override this method to do cleanup in your implementation.
168      * Do a <tt>super.releaseAllResources()</tt> in your method implementation
169      * to free resources used by this class.
170      */

171     public synchronized void releaseAllResources()
172     {
173         this.dataSourceCache.clear();
174     }
175
176     /**
177      * Creates a new connection from the data source that the connection descriptor
178      * represents. If the connection descriptor does not directly contain the data source
179      * then a JNDI lookup is performed to retrieve the data source.
180      *
181      * @param jcd The connection descriptor
182      * @return A connection instance
183      * @throws LookupException if we can't get a connection from the datasource either due to a
184      * naming exception, a failed sanity check, or a SQLException.
185      */

186     protected Connection JavaDoc newConnectionFromDataSource(JdbcConnectionDescriptor jcd)
187             throws LookupException
188     {
189         Connection JavaDoc retval = null;
190         // use JNDI lookup
191
DataSource JavaDoc ds = jcd.getDataSource();
192
193         if (ds == null)
194         {
195             // [tomdz] Would it suffice to store the datasources only at the JCDs ?
196
// Only possible problem would be serialization of the JCD because
197
// the data source object in the JCD does not 'survive' this
198
ds = (DataSource JavaDoc) dataSourceCache.get(jcd.getDatasourceName());
199         }
200         try
201         {
202             if (ds == null)
203             {
204                 /**
205                  * this synchronization block won't be a big deal as we only look up
206                  * new datasources not found in the map.
207                  */

208                 synchronized (dataSourceCache)
209                 {
210                     InitialContext JavaDoc ic = new InitialContext JavaDoc();
211                     ds = (DataSource JavaDoc) ic.lookup(jcd.getDatasourceName());
212                     /**
213                      * cache the datasource lookup.
214                      */

215                     dataSourceCache.put(jcd.getDatasourceName(), ds);
216                 }
217             }
218             if (jcd.getUserName() == null)
219             {
220                 retval = ds.getConnection();
221             }
222             else
223             {
224                 retval = ds.getConnection(jcd.getUserName(), jcd.getPassWord());
225             }
226         }
227         catch (SQLException JavaDoc sqlEx)
228         {
229             log.error("SQLException thrown while trying to get Connection from Datasource (" +
230                     jcd.getDatasourceName() + ")", sqlEx);
231             throw new LookupException("SQLException thrown while trying to get Connection from Datasource (" +
232                     jcd.getDatasourceName() + ")", sqlEx);
233         }
234         catch (NamingException JavaDoc namingEx)
235         {
236             log.error("Naming Exception while looking up DataSource (" + jcd.getDatasourceName() + ")", namingEx);
237             throw new LookupException("Naming Exception while looking up DataSource (" + jcd.getDatasourceName() +
238                     ")", namingEx);
239         }
240         // initialize connection
241
initializeJdbcConnection(retval, jcd);
242         if(log.isDebugEnabled()) log.debug("Create new connection using DataSource: "+retval);
243         return retval;
244     }
245
246     /**
247      * Returns a new created connection
248      *
249      * @param jcd the connection descriptor
250      * @return an instance of Connection from the drivermanager
251      */

252     protected Connection JavaDoc newConnectionFromDriverManager(JdbcConnectionDescriptor jcd)
253             throws LookupException
254     {
255         Connection JavaDoc retval = null;
256         // use JDBC DriverManager
257
final String JavaDoc driver = jcd.getDriver();
258         final String JavaDoc url = getDbURL(jcd);
259         try
260         {
261             // loads the driver - NB call to newInstance() added to force initialisation
262
ClassHelper.getClass(driver, true);
263             final String JavaDoc user = jcd.getUserName();
264             final String JavaDoc password = jcd.getPassWord();
265             final Properties JavaDoc properties = getJdbcProperties(jcd, user, password);
266             if (properties.isEmpty())
267             {
268                 if (user == null)
269                 {
270                     retval = DriverManager.getConnection(url);
271                 }
272                 else
273                 {
274                     retval = DriverManager.getConnection(url, user, password);
275                 }
276             }
277             else
278             {
279                 retval = DriverManager.getConnection(url, properties);
280             }
281         }
282         catch (SQLException JavaDoc sqlEx)
283         {
284             log.error("Error getting Connection from DriverManager with url (" + url + ") and driver (" + driver + ")", sqlEx);
285             throw new LookupException("Error getting Connection from DriverManager with url (" + url + ") and driver (" + driver + ")", sqlEx);
286         }
287         catch (ClassNotFoundException JavaDoc cnfEx)
288         {
289             log.error(cnfEx);
290             throw new LookupException("A class was not found", cnfEx);
291         }
292         catch (Exception JavaDoc e)
293         {
294             log.error("Instantiation of jdbc driver failed", e);
295             throw new LookupException("Instantiation of jdbc driver failed", e);
296         }
297         // initialize connection
298
initializeJdbcConnection(retval, jcd);
299         if(log.isDebugEnabled()) log.debug("Create new connection using DriverManager: "+retval);
300         return retval;
301     }
302
303     /**
304      * Returns connection properties for passing to DriverManager, after merging
305      * JDBC driver-specific configuration settings with name/password from connection
306      * descriptor.
307      * @param jcd the connection descriptor with driver-specific settings
308      * @param user the jcd username (or null if not using authenticated login)
309      * @param password the jcd password (only used when user != null)
310      * @return merged properties object to pass to DriverManager
311      */

312     protected Properties JavaDoc getJdbcProperties(JdbcConnectionDescriptor jcd,
313                                            String JavaDoc user, String JavaDoc password)
314     {
315         final Properties JavaDoc jdbcProperties;
316         jdbcProperties = jcd.getConnectionPoolDescriptor().getJdbcProperties();
317         if (user != null)
318         {
319             jdbcProperties.put("user", user);
320             jdbcProperties.put("password", password);
321         }
322         return jdbcProperties;
323     }
324
325     protected Properties JavaDoc getJdbcProperties(JdbcConnectionDescriptor jcd)
326     {
327         final String JavaDoc user = jcd.getUserName();
328         final String JavaDoc password = jcd.getPassWord();
329         return getJdbcProperties(jcd, user, password);
330     }
331
332     protected String JavaDoc getDbURL(JdbcConnectionDescriptor jcd)
333     {
334         return jcd.isDataSource() ? jcd.getDatasourceName() :
335                 jcd.getProtocol() + ":" + jcd.getSubProtocol() + ":" + jcd.getDbAlias();
336     }
337
338     protected String JavaDoc getJcdDescription(JdbcConnectionDescriptor jcd)
339     {
340         return "Connection for JdbcConnectionDescriptor (" +
341                (jcd.getDatasourceName() != null ? "datasource: " + jcd.getDatasourceName() :
342                 "db-url: " + getDbURL(jcd) + ", user: " + jcd.getUserName()) +
343                ")";
344     }
345
346 }
347
Popular Tags