KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > mapper > rdb > JDBCMapper


1 /**
2  * Copyright (C) 2001-2004 France Telecom R&D
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package org.objectweb.speedo.mapper.rdb;
19
20 import org.objectweb.jorm.api.PException;
21 import org.objectweb.jorm.api.PExceptionIO;
22 import org.objectweb.jorm.api.JormConfigurator;
23 import org.objectweb.jorm.mapper.rdb.lib.MapperJDBC;
24 import org.objectweb.jorm.mapper.rdb.lib.ConnectionSpecJDBC;
25 import org.objectweb.fractal.api.control.LifeCycleController;
26 import org.objectweb.fractal.api.control.BindingController;
27 import org.objectweb.util.monolog.api.LoggerFactory;
28 import org.objectweb.util.monolog.api.BasicLevel;
29 import org.objectweb.util.monolog.api.Logger;
30 import org.objectweb.util.monolog.wrapper.p6spy.P6SpyLogger;
31 import org.objectweb.speedo.api.ExceptionHelper;
32 import org.objectweb.speedo.mapper.rdb.JDBCConnectionHolder;
33 import org.objectweb.medor.eval.prefetch.lib.PrefetchCacheImpl;
34 import org.objectweb.perseus.pool.api.PoolMatchFactory;
35 import org.objectweb.perseus.pool.api.Pool;
36 import org.objectweb.perseus.pool.api.PoolException;
37 import org.objectweb.perseus.persistence.api.ConnectionHolderFactory;
38 import org.objectweb.perseus.persistence.api.ConnectionHolder;
39 import org.objectweb.perseus.persistence.api.PersistenceException;
40
41 import java.sql.DriverManager JavaDoc;
42 import java.sql.Driver JavaDoc;
43 import java.util.ArrayList JavaDoc;
44
45 /**
46  * A JDBC mapper component able to pool the JDBC connection in non managed
47  * environnement.
48  *
49  * @author S.Chassande-Barrioz
50  */

51 public class JDBCMapper
52         extends MapperJDBC
53         implements BindingController, LifeCycleController,
54         JDBCMapperAttributes, PoolMatchFactory, ConnectionHolderFactory {
55
56     public final static String JavaDoc POOL_BINDING = "pool";
57
58
59     /**
60      * The pool of JDBC connection.
61      */

62     protected Pool connectionPool;
63
64     /**
65      * The database url. This field is null when a Datasource is used.
66      */

67     private String JavaDoc url;
68
69     /**
70      * The user name to access the database. This field is null when a
71      * Datasource is used.
72      */

73     private String JavaDoc userName;
74
75     /**
76      * The user passwor to access the database. This field is null when a
77      * Datasource is used.
78      */

79     private String JavaDoc password;
80
81     /**
82      * The class name of the JDBC driver. This field is null when a
83      * Datasource is used.
84      */

85     private String JavaDoc driverCN = null;
86
87     /**
88      * Indicates if the component is started;
89      */

90     private boolean started = false;
91
92     /**
93      * Indicates if JDBC connection must be pool or not.
94      */

95     private boolean poolConnection = false;
96
97     /**
98      * Contains the connection allocated for a particular user, in a pooled mode
99      */

100     private ArrayList JavaDoc unpooledConnection;
101
102     private boolean checkConnectivityAtStartup = true;
103
104     public JDBCMapper() throws PException {
105     }
106
107     // IMPLEMENTATION OF THE ConnectionHolderFactory INTERFACE //
108
//---------------------------------------------------------//
109

110     public ConnectionHolder createConnectionHolder() throws PersistenceException {
111         return new JDBCConnectionHolder(this, logger);
112     }
113
114     // IMPLEMENTATION OF THE PoolMatchFactory INTERFACE //
115
//--------------------------------------------------//
116

117     /**
118      * <b>createResource</b> creates a new PoolResource.
119      * @param hints The "properties" that the created PoolResource should
120      * conform to.
121      * @return The created PoolResource.
122      */

123     public Object JavaDoc createResource(Object JavaDoc hints) throws PoolException {
124         if (!started) {
125             startFc();
126         }
127         Object JavaDoc connection = null;
128         try {
129             if (hints == null) {
130                 connection = super.getConnection();
131             } else {
132                 connection = super.getConnection(hints);
133             }
134         } catch (PException e) {
135             throw new PoolException("Error during the allocation a new JDBC connection", e);
136         }
137         if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
138             logger.log(BasicLevel.DEBUG,
139                     "New JDBC connection allocated for the pool:" + connection);
140         }
141         return connection;
142     }
143
144     /**
145      * <b>matchResource</b> tests if a given resource of a Pool matches with
146      * the hints passed with the Pool getResource method.
147      * @param pr The PoolResource to test its matching with some
148      * "properties" specified by hints.
149      * @param hints The "properties" that the PoolResource specified by pr
150      * should match.
151      * @return <b>true</b> if the pr PoolResource matches the hints
152      * "properties".
153      */

154     public boolean matchResource(Object JavaDoc pr, Object JavaDoc hints) {
155         return true;
156     }
157
158     public void destroyResource(Object JavaDoc resource) {
159         if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
160             logger.log(BasicLevel.DEBUG,
161                     "Destroy the JDBC connection of the pool:" + resource);
162         }
163         try {
164             super.closeConnection(resource);
165         } catch (PException e) {
166             if (logger != null) {
167                 logger.log(BasicLevel.ERROR,
168                         "ERROR during the closing of a connection of the pool:"
169                         + resource, e);
170             }
171         }
172     }
173
174     // IMPLEMENTATION OF THE JDBCMapperAttributes INTERFACE //
175
//------------------------------------------------------//
176

177     public String JavaDoc getDriverClassName() {
178         return driverCN;
179     }
180
181     public void setDriverClassName(String JavaDoc dcn) {
182         driverCN = dcn;
183     }
184
185     public String JavaDoc getURL() {
186         return url;
187     }
188
189     public void setURL(String JavaDoc url) {
190         this.url = url;
191     }
192
193     public String JavaDoc getUserName() {
194         return userName;
195     }
196
197     public void setUserName(String JavaDoc userName) {
198         this.userName = userName;
199     }
200
201     public String JavaDoc getPassword() {
202         return password;
203     }
204
205     public void setPassword(String JavaDoc password) {
206         this.password = password;
207     }
208
209     public void setPoolConnection(boolean pc) {
210         poolConnection = pc;
211         if (poolConnection) {
212             unpooledConnection = new ArrayList JavaDoc(5);
213         }
214     }
215
216     public boolean getPoolConnection() {
217         return poolConnection;
218     }
219
220
221     // IMPLEMENTATION OF THE UserBindingController INTERFACE //
222
//-------------------------------------------------------//
223

224     public String JavaDoc[] listFc() {
225         return new String JavaDoc[] {
226             POOL_BINDING
227         };
228     }
229
230     public Object JavaDoc lookupFc(String JavaDoc s) {
231         if (POOL_BINDING.equals(s)) {
232             return connectionPool;
233         } else {
234             return null;
235         }
236     }
237
238     public void bindFc(String JavaDoc s, Object JavaDoc o) {
239         if ("logger".equals(s)) {
240             logger = (Logger) o;
241             if (P6SpyLogger.logger == null) {
242                 P6SpyLogger.logger = logger;
243             }
244         } else if ("monolog-factory".equals(s)) {
245             Logger l = logger;
246             setLoggerFactory((LoggerFactory) o);
247             if (l != null) {
248                 logger = l;
249             }
250             P6SpyLogger.logger = getLoggerFactory()
251                     .getLogger(logger.getName() + ".sql");
252         } else if (POOL_BINDING.equals(s)) {
253             connectionPool = (Pool) o;
254         }
255     }
256
257     public void unbindFc(String JavaDoc s) {
258         if (POOL_BINDING.equals(s)) {
259             connectionPool = null;
260         }
261     }
262
263     // IMPLEMENTATION OF THE LifeCycleController INTERFACE //
264
//-----------------------------------------------------//
265

266     public String JavaDoc getFcState() {
267         return started ? STARTED : STOPPED;
268     }
269
270     public void startFc() {
271         if (!started) {
272             if (logger == null) {
273                 String JavaDoc msg = "No logger assigned on the component before the start.";
274                 System.err.println(msg);
275                 throw new RuntimeException JavaDoc(msg);
276             }
277             started = true;
278             P6SpyLogger.level = BasicLevel.DEBUG;
279             Object JavaDoc cf = getConnectionFactory();
280             if (cf == null) {
281                 try {
282                     DriverManager.registerDriver((Driver JavaDoc)
283                                 Class.forName(driverCN).newInstance());
284                     setConnectionFactory(
285                             new ConnectionSpecJDBC(url, driverCN, userName, password));
286                 } catch (Exception JavaDoc e) {
287                     logger.log(BasicLevel.ERROR,
288                             "Impossible to configure the jdbc access: ", e);
289                     throw new RuntimeException JavaDoc(
290                             "Impossible to configure the jdbc access: "
291                             + ExceptionHelper.getNested(e).getMessage());
292                 }
293             }
294             if (checkConnectivityAtStartup) {
295                 Object JavaDoc o = null;
296                 try {
297                     logger.log(BasicLevel.DEBUG, "try to fetch a connection");
298                     o = getConnection();
299                 } catch (Exception JavaDoc e) {
300                     Exception JavaDoc ie = ExceptionHelper.getNested(e);
301                     logger.log(BasicLevel.ERROR,
302                             "Impossible to fetch a connection", ie);
303                     throw new RuntimeException JavaDoc(
304                             "Impossible to fetch a connection: "
305                             + ie.getMessage());
306                 } finally {
307                     if (o != null) {
308                         try {
309                             closeConnection(o);
310                         } catch (PException e) {
311                         }
312                     }
313                 }
314             }
315
316             try {
317                 JormConfigurator jc = getJormConfigurator();
318                 jc.setLoggerFactory(getLoggerFactory());
319                 PrefetchCacheImpl pc = new PrefetchCacheImpl(
320                         getLoggerFactory().getLogger(
321                                 "org.objectweb.speedo.rt.query.prefetch"));
322                 setPrefetchCache(pc);
323                 start();
324             } catch (PException e) {
325                 throw new RuntimeException JavaDoc(
326                         "Impossible to configure the mapper: "
327                         + ExceptionHelper.getNested(e).getMessage());
328             }
329         }
330     }
331
332     public void stopFc() {
333         started = false;
334     }
335
336
337     // IMPLEMENTATION OF THE PMapper INTERFACE //
338
//-----------------------------------------//
339

340     /**
341      * The pool is used to fetch a connection.
342      */

343     public Object JavaDoc getConnection() throws PException {
344         if (poolConnection) {
345             try {
346                 Object JavaDoc connection = connectionPool.getResource(null);
347                 if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
348                     logger.log(BasicLevel.DEBUG, "Get a JDBC connection from the pool: " + connection);
349                 }
350                 return connection;
351             } catch (Exception JavaDoc e) {
352                 throw new PExceptionIO(ExceptionHelper.getNested(e),
353                         "Impossible to fetch a jdbc connection on driver");
354             }
355         } else {
356             Object JavaDoc connection = super.getConnection();
357             if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
358                 logger.log(BasicLevel.DEBUG, "JDBC connection allocated: " + connection);
359             }
360             return connection;
361         }
362     }
363
364     public Object JavaDoc getConnection(Object JavaDoc connectionContext, Object JavaDoc user) throws PException {
365         if (poolConnection) {
366             if (connectionContext == null) {
367                 try {
368                     Object JavaDoc connection = connectionPool.getResource(null, user);
369                     if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
370                         logger.log(BasicLevel.DEBUG, "Get a JDBC connection from the pool: " + connection);
371                     }
372                     return connection;
373                 } catch (Exception JavaDoc e) {
374                     throw new PExceptionIO(ExceptionHelper.getNested(e),
375                             "Impossible to fetch a jdbc connection on driver");
376                 }
377             } else {
378                 Object JavaDoc connection = super.getConnection(connectionContext, user);
379                 synchronized(unpooledConnection) {
380                     unpooledConnection.add(connection);
381                 }
382                 if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
383                     logger.log(BasicLevel.DEBUG,
384                         "JDBC connection allocated with context, context= "
385                         + connectionContext + ", connection=" + connection);
386                 }
387                 return connection;
388             }
389         } else {
390             Object JavaDoc connection = super.getConnection(connectionContext, user);
391             if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
392                 logger.log(BasicLevel.DEBUG, "JDBC connection allocated: " + connection);
393             }
394             return connection;
395         }
396     }
397
398     /**
399      * The connection is release into the pool
400      * @param conn
401      * @throws org.objectweb.jorm.api.PException
402      */

403     public void closeConnection(Object JavaDoc conn) throws PException {
404         if (conn == null) {
405             return;
406         }
407         if (poolConnection) {
408             if (unpooledConnection != null) {
409                 synchronized(unpooledConnection) {
410                     if (unpooledConnection.remove(unpooledConnection)) {
411                         if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
412                             logger.log(BasicLevel.DEBUG, "Closing the JDBC connection (context): " + conn);
413                         }
414                         return;
415                     } //else the connection has not been found
416
}
417             }
418             try {
419                 connectionPool.releaseResource(conn);
420             } catch (Exception JavaDoc e) {
421                 throw new PExceptionIO(ExceptionHelper.getNested(e),
422                         "Impossible to release a jdbc connection");
423             }
424         } else {
425             if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
426                 logger.log(BasicLevel.DEBUG, "Closing the JDBC connection: " + conn);
427             }
428             super.closeConnection(conn);
429         }
430     }
431     public boolean getCheckConnectivityAtStartup() {
432         return this.checkConnectivityAtStartup;
433     }
434     public void setCheckConnectivityAtStartup(boolean b) {
435         checkConnectivityAtStartup = b;
436
437     }
438 }
439
Popular Tags