KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > providers > jdbc > JdbcConnector


1 /*
2  * $Id: JdbcConnector.java 3937 2006-11-20 16:04:25Z lajos $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 package org.mule.providers.jdbc;
12
13 import org.apache.commons.dbutils.QueryRunner;
14 import org.apache.commons.dbutils.ResultSetHandler;
15 import org.apache.commons.lang.exception.ExceptionUtils;
16 import org.mule.config.ExceptionHelper;
17 import org.mule.config.i18n.Message;
18 import org.mule.config.i18n.Messages;
19 import org.mule.util.properties.BeanPropertyExtractor;
20 import org.mule.util.properties.MapPropertyExtractor;
21 import org.mule.util.properties.MessagePropertyExtractor;
22 import org.mule.util.properties.PayloadPropertyExtractor;
23 import org.mule.util.properties.PropertyExtractor;
24 import org.mule.providers.AbstractServiceEnabledConnector;
25 import org.mule.transaction.TransactionCoordination;
26 import org.mule.umo.TransactionException;
27 import org.mule.umo.UMOComponent;
28 import org.mule.umo.UMOTransaction;
29 import org.mule.umo.endpoint.UMOEndpoint;
30 import org.mule.umo.endpoint.UMOImmutableEndpoint;
31 import org.mule.umo.lifecycle.InitialisationException;
32 import org.mule.umo.provider.UMOMessageReceiver;
33 import org.mule.util.ClassUtils;
34 import org.mule.util.StringUtils;
35
36 import javax.naming.Context JavaDoc;
37 import javax.naming.InitialContext JavaDoc;
38 import javax.naming.NamingException JavaDoc;
39 import javax.sql.DataSource JavaDoc;
40 import java.sql.Connection JavaDoc;
41 import java.util.Hashtable JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.Set JavaDoc;
46 import java.util.HashSet JavaDoc;
47 import java.util.regex.Matcher JavaDoc;
48 import java.util.regex.Pattern JavaDoc;
49
50 public class JdbcConnector extends AbstractServiceEnabledConnector
51 {
52     // These are properties that can be overridden on the Receiver by the endpoint
53
// declaration
54
public static final String JavaDoc PROPERTY_POLLING_FREQUENCY = "pollingFrequency";
55     public static final long DEFAULT_POLLING_FREQUENCY = 1000;
56
57     private static final String JavaDoc DEFAULT_QUERY_RUNNER = "org.apache.commons.dbutils.QueryRunner";
58     private static final String JavaDoc DEFAULT_RESULTSET_HANDLER = "org.apache.commons.dbutils.handlers.MapListHandler";
59
60     private static final Pattern JavaDoc STATEMENT_ARGS = Pattern.compile("\\$\\{[^\\}]*\\}");
61
62     /* Register the SQL Exception reader if this class gets loaded */
63     static
64     {
65         ExceptionHelper.registerExceptionReader(new SQLExceptionReader());
66     }
67
68     protected long pollingFrequency = 0;
69     protected DataSource JavaDoc dataSource;
70     protected String JavaDoc dataSourceJndiName;
71     protected Context JavaDoc jndiContext;
72     protected String JavaDoc jndiInitialFactory;
73     protected String JavaDoc jndiProviderUrl;
74     protected Map JavaDoc providerProperties;
75     protected Map JavaDoc queries;
76     protected String JavaDoc resultSetHandler = DEFAULT_RESULTSET_HANDLER;
77     protected String JavaDoc queryRunner = DEFAULT_QUERY_RUNNER;
78     protected Set JavaDoc queryValueExtractors;
79     protected Set JavaDoc propertyExtractors;
80
81     /*
82      * (non-Javadoc)
83      *
84      * @see org.mule.umo.provider.UMOConnector#getProtocol()
85      */

86     public String JavaDoc getProtocol()
87     {
88         return "jdbc";
89     }
90
91     public UMOMessageReceiver createReceiver(UMOComponent component, UMOEndpoint endpoint) throws Exception JavaDoc
92     {
93         Map JavaDoc props = endpoint.getProperties();
94         if (props != null)
95         {
96             String JavaDoc tempPolling = (String JavaDoc) props.get(PROPERTY_POLLING_FREQUENCY);
97             if (tempPolling != null)
98             {
99                 pollingFrequency = Long.parseLong(tempPolling);
100             }
101         }
102
103         if (pollingFrequency <= 0)
104         {
105             pollingFrequency = DEFAULT_POLLING_FREQUENCY;
106         }
107
108         String JavaDoc[] params = getReadAndAckStatements(endpoint);
109         return getServiceDescriptor().createMessageReceiver(this, component, endpoint, params);
110     }
111
112     protected void initJndiContext() throws NamingException JavaDoc
113     {
114         if (this.jndiContext == null)
115         {
116             Hashtable JavaDoc props = new Hashtable JavaDoc();
117             if (this.jndiInitialFactory != null)
118             {
119                 props.put(Context.INITIAL_CONTEXT_FACTORY, this.jndiInitialFactory);
120             }
121             if (this.jndiProviderUrl != null)
122             {
123                 props.put(Context.PROVIDER_URL, jndiProviderUrl);
124             }
125             if (this.providerProperties != null)
126             {
127                 props.putAll(this.providerProperties);
128             }
129             this.jndiContext = new InitialContext JavaDoc(props);
130         }
131
132     }
133
134     protected void createDataSource() throws InitialisationException, NamingException JavaDoc
135     {
136         Object JavaDoc temp = this.jndiContext.lookup(this.dataSourceJndiName);
137         if (temp instanceof DataSource JavaDoc)
138         {
139             dataSource = (DataSource JavaDoc)temp;
140         }
141         else
142         {
143             throw new InitialisationException(new Message(Messages.JNDI_RESOURCE_X_NOT_FOUND,
144                 this.dataSourceJndiName), this);
145         }
146     }
147
148     /*
149      * (non-Javadoc)
150      *
151      * @see org.mule.providers.UMOConnector#create(java.util.HashMap)
152      */

153     public void doInitialise() throws InitialisationException
154     {
155         super.doInitialise();
156         try
157         {
158             // If we have a dataSource, there is no need to initialise
159
// the JndiContext
160
if (dataSource == null)
161             {
162                 initJndiContext();
163                 createDataSource();
164             }
165             // setup property Extractors for queries
166
if (queryValueExtractors == null)
167             {
168                 // Add defaults
169
queryValueExtractors = new HashSet JavaDoc();
170                 queryValueExtractors.add(MessagePropertyExtractor.class.getName());
171                 queryValueExtractors.add(NowPropertyExtractor.class.getName());
172                 queryValueExtractors.add(PayloadPropertyExtractor.class.getName());
173                 queryValueExtractors.add(MapPropertyExtractor.class.getName());
174                 queryValueExtractors.add(BeanPropertyExtractor.class.getName());
175                 if (ClassUtils.isClassOnPath("org.mule.util.properties.Dom4jPropertyExtractor", getClass()))
176                 {
177                     queryValueExtractors.add("org.mule.util.properties.Dom4jPropertyExtractor");
178                 }
179                 if (ClassUtils.isClassOnPath("org.mule.util.properties.JDomPropertyExtractor", getClass()))
180                 {
181                     queryValueExtractors.add("org.mule.util.properties.JDomPropertyExtractor");
182                 }
183             }
184             propertyExtractors = new HashSet JavaDoc();
185             for (Iterator JavaDoc iterator = queryValueExtractors.iterator(); iterator.hasNext();)
186             {
187                 String JavaDoc s = (String JavaDoc)iterator.next();
188                 propertyExtractors.add(ClassUtils.instanciateClass(s, ClassUtils.NO_ARGS));
189             }
190         }
191         catch (Exception JavaDoc e)
192         {
193             throw new InitialisationException(new Message(Messages.FAILED_TO_CREATE_X, "Jdbc Connector"), e,
194                 this);
195         }
196     }
197
198     public String JavaDoc[] getReadAndAckStatements(UMOImmutableEndpoint endpoint)
199     {
200         String JavaDoc str;
201         // Find read statement
202
String JavaDoc readStmt;
203         if ((str = (String JavaDoc)endpoint.getProperty("sql")) != null)
204         {
205             readStmt = str;
206         }
207         else
208         {
209             readStmt = endpoint.getEndpointURI().getAddress();
210         }
211         // Find ack statement
212
String JavaDoc ackStmt;
213         if ((str = (String JavaDoc)endpoint.getProperty("ack")) != null)
214         {
215             ackStmt = str;
216             if ((str = getQuery(endpoint, ackStmt)) != null)
217             {
218                 ackStmt = str;
219             }
220         }
221         else
222         {
223             ackStmt = readStmt + ".ack";
224             if ((str = getQuery(endpoint, ackStmt)) != null)
225             {
226                 ackStmt = str;
227             }
228             else
229             {
230                 ackStmt = null;
231             }
232         }
233         // Translate both using queries map
234
if ((str = getQuery(endpoint, readStmt)) != null)
235         {
236             readStmt = str;
237         }
238         if (readStmt == null)
239         {
240             throw new IllegalArgumentException JavaDoc("Read statement should not be null");
241         }
242         if (!"select".equalsIgnoreCase(readStmt.substring(0, 6)))
243         {
244             throw new IllegalArgumentException JavaDoc("Read statement should be a select sql statement");
245         }
246         if (ackStmt != null)
247         {
248             if (!"insert".equalsIgnoreCase(ackStmt.substring(0, 6))
249                 && !"update".equalsIgnoreCase(ackStmt.substring(0, 6))
250                 && !"delete".equalsIgnoreCase(ackStmt.substring(0, 6)))
251             {
252                 throw new IllegalArgumentException JavaDoc(
253                     "Ack statement should be an insert / update / delete sql statement");
254             }
255         }
256         return new String JavaDoc[]{readStmt, ackStmt};
257     }
258
259     public String JavaDoc getQuery(UMOImmutableEndpoint endpoint, String JavaDoc stmt)
260     {
261         Object JavaDoc query = null;
262         if (endpoint != null && endpoint.getProperties() != null)
263         {
264             Object JavaDoc queries = endpoint.getProperties().get("queries");
265             if (queries instanceof Map JavaDoc)
266             {
267                 query = ((Map JavaDoc)queries).get(stmt);
268             }
269         }
270         if (query == null)
271         {
272             if (this.queries != null)
273             {
274                 query = this.queries.get(stmt);
275             }
276         }
277         return query == null ? null : query.toString();
278     }
279
280     /**
281      * @return Returns the dataSource.
282      */

283     public DataSource JavaDoc getDataSource()
284     {
285         return dataSource;
286     }
287
288     /**
289      * @param dataSource The dataSource to set.
290      */

291     public void setDataSource(DataSource JavaDoc dataSource)
292     {
293         this.dataSource = dataSource;
294     }
295
296     /**
297      * @return Returns the pollingFrequency.
298      */

299     public long getPollingFrequency()
300     {
301         return pollingFrequency;
302     }
303
304     /**
305      * @param pollingFrequency The pollingFrequency to set.
306      */

307     public void setPollingFrequency(long pollingFrequency)
308     {
309         this.pollingFrequency = pollingFrequency;
310     }
311
312     /**
313      * @return Returns the queries.
314      */

315     public Map JavaDoc getQueries()
316     {
317         return queries;
318     }
319
320     /**
321      * @param queries The queries to set.
322      */

323     public void setQueries(Map JavaDoc queries)
324     {
325         this.queries = queries;
326     }
327
328     /**
329      * @return Returns the dataSourceJndiName.
330      */

331     public String JavaDoc getDataSourceJndiName()
332     {
333         return dataSourceJndiName;
334     }
335
336     /**
337      * @param dataSourceJndiName The dataSourceJndiName to set.
338      */

339     public void setDataSourceJndiName(String JavaDoc dataSourceJndiName)
340     {
341         this.dataSourceJndiName = dataSourceJndiName;
342     }
343
344     /**
345      * @return Returns the jndiContext.
346      */

347     public Context JavaDoc getJndiContext()
348     {
349         return jndiContext;
350     }
351
352     /**
353      * @param jndiContext The jndiContext to set.
354      */

355     public void setJndiContext(Context JavaDoc jndiContext)
356     {
357         this.jndiContext = jndiContext;
358     }
359
360     /**
361      * @return Returns the jndiInitialFactory.
362      */

363     public String JavaDoc getJndiInitialFactory()
364     {
365         return jndiInitialFactory;
366     }
367
368     /**
369      * @param jndiInitialFactory The jndiInitialFactory to set.
370      */

371     public void setJndiInitialFactory(String JavaDoc jndiInitialFactory)
372     {
373         this.jndiInitialFactory = jndiInitialFactory;
374     }
375
376     /**
377      * @return Returns the jndiProviderUrl.
378      */

379     public String JavaDoc getJndiProviderUrl()
380     {
381         return jndiProviderUrl;
382     }
383
384     /**
385      * @param jndiProviderUrl The jndiProviderUrl to set.
386      */

387     public void setJndiProviderUrl(String JavaDoc jndiProviderUrl)
388     {
389         this.jndiProviderUrl = jndiProviderUrl;
390     }
391
392     /**
393      * @return Returns the providerProperties.
394      */

395     public Map JavaDoc getProviderProperties()
396     {
397         return providerProperties;
398     }
399
400     /**
401      * @param providerProperties The providerProperties to set.
402      */

403     public void setProviderProperties(Map JavaDoc providerProperties)
404     {
405         this.providerProperties = providerProperties;
406     }
407
408     /*
409      * (non-Javadoc)
410      *
411      * @see org.mule.providers.TransactionEnabledConnector#getSessionFactory(org.mule.umo.endpoint.UMOEndpoint)
412      */

413     public Object JavaDoc getSessionFactory(UMOEndpoint endpoint) throws Exception JavaDoc
414     {
415         return dataSource;
416     }
417
418     public Connection JavaDoc getConnection() throws Exception JavaDoc
419     {
420         UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
421         if (tx != null)
422         {
423             if (tx.hasResource(dataSource))
424             {
425                 logger.debug("Retrieving connection from current transaction");
426                 return (Connection JavaDoc)tx.getResource(dataSource);
427             }
428         }
429         logger.debug("Retrieving new connection from data source");
430         Connection JavaDoc con = dataSource.getConnection();
431
432         if (tx != null)
433         {
434             logger.debug("Binding connection to current transaction");
435             try
436             {
437                 tx.bindResource(dataSource, con);
438             }
439             catch (TransactionException e)
440             {
441                 throw new RuntimeException JavaDoc("Could not bind connection to current transaction", e);
442             }
443         }
444         return con;
445     }
446
447     /**
448      * @return Returns the resultSetHandler.
449      */

450     public String JavaDoc getResultSetHandler()
451     {
452         return this.resultSetHandler;
453     }
454
455     /**
456      * @param resultSetHandler The resultSetHandler class name to set.
457      */

458     public void setResultSetHandler(String JavaDoc resultSetHandler)
459     {
460         this.resultSetHandler = resultSetHandler;
461     }
462
463     /**
464      * @return a new instance of the ResultSetHandler class as defined in the
465      * JdbcConnector
466      */

467     protected ResultSetHandler createResultSetHandler()
468     {
469         try
470         {
471             return (ResultSetHandler) ClassUtils.instanciateClass(getResultSetHandler(),
472                                                                   ClassUtils.NO_ARGS);
473         }
474         catch (Exception JavaDoc e)
475         {
476             throw new IllegalArgumentException JavaDoc("Error creating instance of the resultSetHandler class :"
477                                                + getResultSetHandler() + System.getProperty("line.separator")
478                                                + ExceptionUtils.getFullStackTrace(e));
479         }
480     }
481
482     public Set JavaDoc getQueryValueExtractors()
483     {
484         return queryValueExtractors;
485     }
486
487     public void setQueryValueExtractors(Set JavaDoc queryValueExtractors)
488     {
489         this.queryValueExtractors = queryValueExtractors;
490     }
491
492     /**
493      * @return Returns the queryRunner.
494      */

495     public String JavaDoc getQueryRunner()
496     {
497         return this.queryRunner;
498     }
499
500     /**
501      * @param queryRunner The QueryRunner class name to set.
502      */

503     public void setQueryRunner(String JavaDoc queryRunner)
504     {
505         this.queryRunner = queryRunner;
506     }
507
508     /**
509      * @return a new instance of the QueryRunner class as defined in the
510      * JdbcConnector
511      */

512     protected QueryRunner createQueryRunner()
513     {
514         try
515         {
516             return (QueryRunner) ClassUtils.instanciateClass(getQueryRunner(),
517                                                              ClassUtils.NO_ARGS);
518         }
519         catch (Exception JavaDoc e)
520         {
521             throw new IllegalArgumentException JavaDoc("Error creating instance of the queryRunner class :"
522                                                + getQueryRunner() + System.getProperty("line.separator")
523                                                + ExceptionUtils.getFullStackTrace(e));
524         }
525     }
526
527     /**
528      * Parse the given statement filling the parameter list and return the ready to
529      * use statement.
530      *
531      * @param stmt
532      * @param params
533      * @return
534      */

535     public String JavaDoc parseStatement(String JavaDoc stmt, List JavaDoc params)
536     {
537         if (stmt == null)
538         {
539             return stmt;
540         }
541         Matcher JavaDoc m = STATEMENT_ARGS.matcher(stmt);
542         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(200);
543         while (m.find())
544         {
545             String JavaDoc key = m.group();
546             m.appendReplacement(sb, "?");
547             params.add(key);
548         }
549         m.appendTail(sb);
550         return sb.toString();
551     }
552
553     public Object JavaDoc[] getParams(UMOImmutableEndpoint endpoint, List JavaDoc paramNames, Object JavaDoc message)
554         throws Exception JavaDoc
555     {
556         Object JavaDoc[] params = new Object JavaDoc[paramNames.size()];
557         for (int i = 0; i < paramNames.size(); i++)
558         {
559             String JavaDoc param = (String JavaDoc)paramNames.get(i);
560             String JavaDoc name = param.substring(2, param.length() - 1);
561             Object JavaDoc value = null;
562             // If we find a value and it happens to be null, thats acceptable
563
boolean foundValue = false;
564             if (message != null)
565             {
566                 for (Iterator JavaDoc iterator = propertyExtractors.iterator(); iterator.hasNext();)
567                 {
568                     PropertyExtractor pe = (PropertyExtractor)iterator.next();
569                     value = pe.getProperty(name, message);
570                     if (value != null)
571                     {
572                         if (value.equals(StringUtils.EMPTY) && pe instanceof BeanPropertyExtractor)
573                         {
574                             value = null;
575                         }
576                         foundValue = true;
577                         break;
578                     }
579                 }
580             }
581             if (!foundValue)
582             {
583                 value = endpoint.getProperty(name);
584             }
585
586             // Allow null values which may be acceptable to the user
587
// Why shouldn't nulls be allowed? Otherwise every null parameter has to
588
// be defined
589
// if (value == null && !foundValue)
590
// {
591
// throw new IllegalArgumentException("Can not retrieve argument " +
592
// name);
593
// }
594
params[i] = value;
595         }
596         return params;
597     }
598 }
599
Popular Tags