3ce59a2bd70a4df4a851315bad66e9e9ba230efc
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / attrresolv / provider / JDBCDataConnector.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
18
19 import java.io.PrintWriter;
20 import java.lang.reflect.Constructor;
21 import java.security.Principal;
22 import java.sql.Blob;
23 import java.sql.Clob;
24 import java.sql.Connection;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.ResultSetMetaData;
28 import java.sql.SQLException;
29 import java.sql.Types;
30 import java.text.SimpleDateFormat;
31 import java.util.ArrayList;
32 import java.util.Iterator;
33 import java.util.Properties;
34
35 import javax.naming.NamingException;
36 import javax.naming.directory.Attribute;
37 import javax.naming.directory.Attributes;
38 import javax.naming.directory.BasicAttribute;
39 import javax.naming.directory.BasicAttributes;
40 import javax.sql.DataSource;
41
42 import org.apache.commons.dbcp.ConnectionFactory;
43 import org.apache.commons.dbcp.DriverManagerConnectionFactory;
44 import org.apache.commons.dbcp.PoolableConnectionFactory;
45 import org.apache.commons.dbcp.PoolingDataSource;
46 import org.apache.commons.pool.impl.GenericObjectPool;
47 import org.apache.commons.pool.impl.StackKeyedObjectPoolFactory;
48 import org.apache.log4j.Logger;
49 import org.apache.log4j.Priority;
50 import org.w3c.dom.Element;
51 import org.w3c.dom.Node;
52 import org.w3c.dom.NodeList;
53
54 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
55 import edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn;
56 import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
57 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
58 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
59
60 /*
61  * Built at the Canada Institute for Scientific and Technical Information (CISTI
62  * <ahref="http://www.cisti-icist.nrc-cnrc.gc.ca/">http://www.cisti-icist.nrc-cnrc.gc.ca/ </a>, the National Research
63  * Council Canada (NRC <a href="http://www.nrc-cnrc.gc.ca/">http://www.nrc-cnrc.gc.ca/ </a>) by David Dearman, COOP
64  * student from Dalhousie University, under the direction of Glen Newton, Head research (IT)
65  * <ahref="mailto:glen.newton@nrc-cnrc.gc.ca">glen.newton@nrc-cnrc.gc.ca </a>.
66  */
67
68 /**
69  * Data Connector that uses JDBC to access user attributes stored in databases.
70  * 
71  * @author David Dearman (dearman@cs.dal.ca)
72  * @author Walter Hoehn (wassa@columbia.edu)
73  * @author Scott Cantor
74  */
75
76 public class JDBCDataConnector extends BaseDataConnector implements DataConnectorPlugIn {
77
78         private static Logger log = Logger.getLogger(JDBCDataConnector.class.getName());
79         protected String searchVal;
80         protected int minResultSet = 0, maxResultSet = 0, retryInterval = 300;
81         protected long deadSince = 0;
82         protected DataSource dataSource;
83         protected JDBCAttributeExtractor extractor;
84         protected JDBCStatementCreator statementCreator;
85
86         public JDBCDataConnector(Element e) throws ResolutionPlugInException {
87
88                 super(e);
89
90                 // Get the query string
91                 NodeList queryNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "Query");
92                 Node tnode = queryNodes.item(0).getFirstChild();
93                 if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
94                         searchVal = tnode.getNodeValue();
95                 }
96                 if (searchVal == null || searchVal.equals("")) {
97                         log.error("Database query must be specified.");
98                         throw new ResolutionPlugInException("Database query must be specified.");
99                 }
100
101                 // Load the supplied JDBC driver
102                 String dbDriverName = e.getAttribute("dbDriver");
103                 if (dbDriverName != null && (!dbDriverName.equals(""))) {
104                         loadDriver(dbDriverName);
105                 }
106
107                 String validationQuery = e.getAttribute("validationQuery");
108                 if (validationQuery == null || validationQuery.equals("")) {
109                         validationQuery = "select 1";
110                 }
111
112                 try {
113                         if (e.getAttributeNode("minResultSet") != null) {
114                                 minResultSet = Integer.parseInt(e.getAttribute("minResultSet"));
115                         }
116                         if (e.getAttributeNode("maxResultSet") != null) {
117                                 maxResultSet = Integer.parseInt(e.getAttribute("maxResultSet"));
118                         }
119                         if (e.getAttributeNode("retryInterval") != null) {
120                                 retryInterval = Integer.parseInt(e.getAttribute("retryInterval"));
121                         }
122                 } catch (NumberFormatException ex) {
123                         log.error("Malformed result set and retry limits: using defaults.");
124                 }
125
126                 // Load site-specific implementation classes
127                 setupAttributeExtractor((Element) e.getElementsByTagNameNS(AttributeResolver.resolverNamespace,
128                                 "AttributeExtractor").item(0));
129                 setupStatementCreator((Element) e.getElementsByTagNameNS(AttributeResolver.resolverNamespace,
130                                 "StatementCreator").item(0));
131
132                 // Load driver properties
133                 Properties props = new Properties();
134                 NodeList propertiesNode = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "Property");
135                 for (int i = 0; propertiesNode.getLength() > i; i++) {
136                         Element property = (Element) propertiesNode.item(i);
137                         String propertiesName = property.getAttribute("name");
138                         String propertiesValue = property.getAttribute("value");
139
140                         if (propertiesName != null && !propertiesName.equals("") && propertiesValue != null
141                                         && !propertiesValue.equals("")) {
142                                 props.setProperty(propertiesName, propertiesValue);
143                                 log.debug("Property: (" + propertiesName + ")");
144                                 log.debug("   Value: (" + propertiesValue + ")");
145                         } else {
146                                 log.error("Property is malformed.");
147                                 throw new ResolutionPlugInException("Property is malformed.");
148                         }
149                 }
150
151                 // Initialize a pooling Data Source
152                 int maxActive = 5;
153                 int maxIdle = 5;
154                 int maxWait = 15;
155                 try {
156                         if (e.getAttributeNode("maxActive") != null) {
157                                 maxActive = Integer.parseInt(e.getAttribute("maxActive"));
158                         }
159                         if (e.getAttributeNode("maxIdle") != null) {
160                                 maxIdle = Integer.parseInt(e.getAttribute("maxIdle"));
161                         }
162                         if (e.getAttributeNode("maxWait") != null) {
163                                 maxWait = Integer.parseInt(e.getAttribute("maxWait"));
164                         }
165                 } catch (NumberFormatException ex) {
166                         log.error("Malformed pooling limits: using defaults.");
167                 }
168                 if (e.getAttribute("dbURL") == null || e.getAttribute("dbURL").equals("")) {
169                         log.error("JDBC connection requires a dbURL property");
170                         throw new ResolutionPlugInException("JDBCDataConnection requires a \"dbURL\" property");
171                 }
172                 setupDataSource(e.getAttribute("dbURL"), props, maxActive, maxIdle, maxWait, validationQuery);
173         }
174
175         /**
176          * Initialize a Pooling Data Source
177          */
178         private void setupDataSource(String dbURL, Properties props, int maxActive, int maxIdle, int maxWait,
179                         String validationQuery) throws ResolutionPlugInException {
180
181                 GenericObjectPool objectPool = new GenericObjectPool(null);
182
183                 objectPool.setMaxActive(maxActive);
184                 objectPool.setMaxIdle(maxIdle);
185                 if (maxWait > 0) objectPool.setMaxWait(1000 * maxWait);
186                 else objectPool.setMaxWait(maxWait);
187
188                 objectPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
189                 objectPool.setTestOnBorrow(true);
190
191                 ConnectionFactory connFactory = null;
192                 PoolableConnectionFactory poolConnFactory = null;
193
194                 try {
195                         connFactory = new DriverManagerConnectionFactory(dbURL, props);
196                         log.debug("Connection factory initialized.");
197                 } catch (Exception ex) {
198                         log
199                                         .error("Connection factory couldn't be initialized, ensure database URL, username and password are correct.");
200                         throw new ResolutionPlugInException("Connection factory couldn't be initialized: " + ex.getMessage());
201                 }
202
203                 try {
204                         poolConnFactory = new PoolableConnectionFactory(connFactory, objectPool, new StackKeyedObjectPoolFactory(),
205                                         validationQuery, true, true);
206                 } catch (Exception ex) {
207                         log.debug("Poolable connection factory error");
208                 }
209
210                 dataSource = new PoolingDataSource(objectPool);
211                 log.info("Data Source initialized.");
212                 try {
213                         dataSource.setLogWriter(new Log4jPrintWriter(Logger.getLogger(JDBCDataConnector.class.getName() + ".Pool"),
214                                         Priority.DEBUG));
215                 } catch (SQLException e) {
216                         log.error("Coudn't setup logger for database connection pool.");
217                 }
218         }
219
220         /**
221          * Instantiate an Attribute Extractor, using the default if none was configured
222          */
223         private void setupAttributeExtractor(Element config) throws ResolutionPlugInException {
224
225                 String className = null;
226                 if (config != null) {
227                         className = config.getAttribute("class");
228                 }
229                 if (className == null || className.equals("")) {
230                         log.debug("Using default Attribute Extractor.");
231                         className = DefaultAE.class.getName();
232                 }
233                 try {
234                         Class aeClass = Class.forName(className);
235                         extractor = (JDBCAttributeExtractor) aeClass.newInstance();
236                         log.debug("Attribute Extractor implementation loaded.");
237
238                 } catch (ClassNotFoundException e) {
239                         log.error("The supplied Attribute Extractor class could not be found: " + e);
240                         throw new ResolutionPlugInException("The supplied Attribute Extractor class could not be found: "
241                                         + e.getMessage());
242                 } catch (Exception e) {
243                         log.error("Unable to instantiate Attribute Extractor implementation: " + e);
244                         throw new ResolutionPlugInException("Unable to instantiate Attribute Extractor implementation: "
245                                         + e.getMessage());
246                 }
247         }
248
249         /**
250          * Instantiate a Statement Creator, using the default if none was configured
251          */
252         private void setupStatementCreator(Element config) throws ResolutionPlugInException {
253
254                 String scClassName = null;
255                 if (config != null) {
256                         scClassName = config.getAttribute("class");
257                 }
258                 if (scClassName == null || scClassName.equals("")) {
259                         log.debug("Using default Statement Creator.");
260                         scClassName = DefaultStatementCreator.class.getName();
261                 }
262                 try {
263                         Class scClass = Class.forName(scClassName);
264
265                         Class[] params = new Class[1];
266                         params[0] = Class.forName("org.w3c.dom.Element");
267                         try {
268                                 Constructor implementorConstructor = scClass.getConstructor(params);
269                                 Object[] args = new Object[1];
270                                 args[0] = config;
271                                 log.debug("Initializing Statement Creator of type (" + scClass.getName() + ").");
272                                 statementCreator = (JDBCStatementCreator) implementorConstructor.newInstance(args);
273                         } catch (NoSuchMethodException nsme) {
274                                 log
275                                                 .debug("Implementation constructor does have a parameterized constructor, attempting to load default.");
276                                 statementCreator = (JDBCStatementCreator) scClass.newInstance();
277                         }
278                         log.debug("Statement Creator implementation loaded.");
279
280                 } catch (ClassNotFoundException e) {
281                         log.error("The supplied Statement Creator class could not be found: " + e);
282                         throw new ResolutionPlugInException("The supplied Statement Creator class could not be found: "
283                                         + e.getMessage());
284                 } catch (Exception e) {
285                         log.error("Unable to instantiate Statement Creator implementation: " + e);
286                         throw new ResolutionPlugInException("Unable to instantiate Statement Creator implementation: "
287                                         + e.getMessage());
288                 }
289         }
290
291         /**
292          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#resolve(java.security.Principal,
293          *      java.lang.String, java.lang.String, edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies)
294          */
295         public Attributes resolve(Principal principal, String requester, String responder, Dependencies depends)
296                         throws ResolutionPlugInException {
297
298                 log.debug("Resolving connector: (" + getId() + ")");
299
300                 // Are we alive?
301                 boolean alive = true;
302                 long now = System.currentTimeMillis();
303                 synchronized (this) {
304                         if (deadSince > 0 && now - deadSince < (1000 * retryInterval)) {
305                                 alive = false;
306                         } else {
307                                 deadSince = 0;
308                         }
309                 }
310
311                 if (!alive) {
312                         log.info("JDBC Connector (" + getId() + ") is dead, returning immediately");
313                         throw new ResolutionPlugInException("Connection is dead");
314                 }
315
316                 // Retrieve a connection from the connection pool
317                 Connection conn = null;
318                 try {
319                         conn = dataSource.getConnection();
320                         log.debug("Connection retrieved from pool");
321                 } catch (Exception e) {
322                         synchronized (this) {
323                                 deadSince = now;
324                         }
325                         log.error("JDBC Connector (" + getId() + ") unable to fetch a connection from the pool, marking it dead");
326                         throw new ResolutionPlugInException("Unable to fetch a connection from the pool, marking it dead: "
327                                         + e.getMessage());
328                 }
329                 if (conn == null) {
330                         log.error("Pool didn't return a properly initialized connection.");
331                         throw new ResolutionPlugInException("Pool didn't return a properly initialized connection.");
332                 }
333
334                 // Setup and execute a (pooled) prepared statement
335                 ResultSet rs = null;
336                 PreparedStatement preparedStatement = null;
337                 try {
338                         preparedStatement = conn.prepareStatement(searchVal);
339                         preparedStatement.clearParameters();
340                         statementCreator.create(preparedStatement, principal, requester, responder, depends);
341                         rs = preparedStatement.executeQuery();
342                         if (!rs.next()) {
343                                 if (minResultSet == 0) return new BasicAttributes();
344                                 else {
345                                         log.error("Statement returned no rows, violating minResultSet of " + minResultSet);
346                                         throw new ResolutionPlugInException("Statement didn't return any rows, violating minResultSet of "
347                                                         + minResultSet);
348                                 }
349                         }
350                         return extractor.extractAttributes(rs, minResultSet, maxResultSet);
351                 } catch (JDBCStatementCreatorException e) {
352                         log.error("An ERROR occured while constructing the query");
353                         throw new ResolutionPlugInException("An ERROR occured while constructing the query: " + e.getMessage());
354                 } catch (JDBCAttributeExtractorException e) {
355                         log.error("An ERROR occured while extracting attributes from result set");
356                         throw new ResolutionPlugInException("An ERROR occured while extracting attributes from result set: "
357                                         + e.getMessage());
358                 } catch (SQLException e) {
359                         synchronized (this) {
360                                 deadSince = now;
361                         }
362                         log.error("An ERROR occured while executing the query, marking connector dead");
363                         throw new ResolutionPlugInException("An ERROR occured while executing the query, marking connector dead: "
364                                         + e.getMessage());
365                 } finally {
366                         Exception e_save = null;
367                         try {
368                                 if (preparedStatement != null) {
369                                         preparedStatement.close();
370                                 }
371                         } catch (SQLException e) {
372                                 log.error("An error occured while closing the prepared statement: " + e.getMessage());
373                                 e_save = e;
374                         }
375                         try {
376                                 if (rs != null) {
377                                         rs.close();
378                                 }
379                         } catch (SQLException e) {
380                                 log.error("An error occured while closing the result set: " + e.getMessage());
381                                 e_save = e;
382                         }
383                         try {
384                                 conn.close();
385                         } catch (SQLException e) {
386                                 log.error("An error occured while closing the database connection: " + e.getMessage());
387                                 e_save = e;
388                         }
389                         if (e_save != null) { throw new ResolutionPlugInException(
390                                         "An error occured while closing database objects:" + e_save.getMessage()); }
391                 }
392         }
393
394         /**
395          * Loads the driver used to access the database
396          * 
397          * @param driver
398          *            The driver used to access the database
399          * @throws ResolutionPlugInException
400          *             If there is a failure to load the driver
401          */
402         public void loadDriver(String driver) throws ResolutionPlugInException {
403
404                 try {
405                         Class.forName(driver).newInstance();
406                         log.debug("Loading JDBC driver: " + driver);
407                 } catch (Exception e) {
408                         log.error("An error loading database driver: " + e);
409                         throw new ResolutionPlugInException("An IllegalAccessException occured while loading database driver: "
410                                         + e.getMessage());
411                 }
412                 log.debug("Driver loaded.");
413         }
414
415         private class Log4jPrintWriter extends PrintWriter {
416
417                 private Priority level;
418                 private Logger logger;
419                 private StringBuffer text = new StringBuffer("");
420
421                 private Log4jPrintWriter(Logger logger, org.apache.log4j.Priority level) {
422
423                         super(System.err);
424                         this.level = level;
425                         this.logger = logger;
426                 }
427
428                 public void close() {
429
430                         flush();
431                 }
432
433                 public void flush() {
434
435                         if (!text.toString().equals("")) {
436                                 logger.log(level, text.toString());
437                                 text.setLength(0);
438                         }
439                 }
440
441                 public void print(boolean b) {
442
443                         text.append(b);
444                 }
445
446                 public void print(char c) {
447
448                         text.append(c);
449                 }
450
451                 public void print(char[] s) {
452
453                         text.append(s);
454                 }
455
456                 public void print(double d) {
457
458                         text.append(d);
459                 }
460
461                 public void print(float f) {
462
463                         text.append(f);
464                 }
465
466                 public void print(int i) {
467
468                         text.append(i);
469                 }
470
471                 public void print(long l) {
472
473                         text.append(l);
474                 }
475
476                 public void print(Object obj) {
477
478                         text.append(obj);
479                 }
480
481                 public void print(String s) {
482
483                         text.append(s);
484                 }
485
486                 public void println() {
487
488                         if (!text.toString().equals("")) {
489                                 logger.log(level, text.toString());
490                                 text.setLength(0);
491                         }
492                 }
493
494                 public void println(boolean x) {
495
496                         text.append(x);
497                         logger.log(level, text.toString());
498                         text.setLength(0);
499                 }
500
501                 public void println(char x) {
502
503                         text.append(x);
504                         logger.log(level, text.toString());
505                         text.setLength(0);
506                 }
507
508                 public void println(char[] x) {
509
510                         text.append(x);
511                         logger.log(level, text.toString());
512                         text.setLength(0);
513                 }
514
515                 public void println(double x) {
516
517                         text.append(x);
518                         logger.log(level, text.toString());
519                         text.setLength(0);
520                 }
521
522                 public void println(float x) {
523
524                         text.append(x);
525                         logger.log(level, text.toString());
526                         text.setLength(0);
527                 }
528
529                 public void println(int x) {
530
531                         text.append(x);
532                         logger.log(level, text.toString());
533                         text.setLength(0);
534                 }
535
536                 public void println(long x) {
537
538                         text.append(x);
539                         logger.log(level, text.toString());
540                         text.setLength(0);
541                 }
542
543                 public void println(Object x) {
544
545                         text.append(x);
546                         logger.log(level, text.toString());
547                         text.setLength(0);
548                 }
549
550                 public void println(String x) {
551
552                         text.append(x);
553                         logger.log(level, text.toString());
554                         text.setLength(0);
555                 }
556         }
557 }
558
559 /**
560  * The default attribute extractor.
561  */
562
563 class DefaultAE implements JDBCAttributeExtractor {
564
565         private static Logger log = Logger.getLogger(DefaultAE.class.getName());
566
567         public Attributes extractAttributes(ResultSet rs, int minResultSet, int maxResultSet)
568                         throws JDBCAttributeExtractorException {
569
570                 BasicAttributes attributes = new BasicAttributes(true);
571                 int row = 0;
572
573                 try {
574                         // Get metadata about result set.
575                         ResultSetMetaData rsmd = rs.getMetaData();
576                         int numColumns = rsmd.getColumnCount();
577                         log.debug("Number of returned columns: " + numColumns);
578
579                         do {
580                                 if (maxResultSet > 0 && row + 1 > maxResultSet) {
581                                         log.error("Statement returned too many rows, violating maxResultSet of " + maxResultSet);
582                                         throw new JDBCAttributeExtractorException(
583                                                         "Statement returned too many rows, violating maxResultSet of " + maxResultSet);
584                                 }
585
586                                 for (int i = 1; i <= numColumns; i++) {
587                                         String columnName = rsmd.getColumnName(i);
588                                         Object columnValue = rs.getObject(columnName);
589                                         if (log.isDebugEnabled()) {
590                                                 log.debug("(" + i + ". ColumnType = " + rsmd.getColumnTypeName(i) + ") " + columnName + " -> "
591                                                                 + (columnValue != null ? columnValue.toString() : "(null)"));
592                                         }
593                                         if (row == 0) {
594                                                 BasicAttribute ba = new BasicAttribute(columnName, true);
595                                                 ba.add(row, columnValue);
596                                                 attributes.put(ba);
597                                         } else {
598                                                 attributes.get(columnName).add(row, columnValue);
599                                         }
600                                 }
601                                 row++;
602                         } while (rs.next());
603                 } catch (SQLException e) {
604                         log.error("An ERROR occured while processing result set");
605                         throw new JDBCAttributeExtractorException("An ERROR occured while processing result set: " + e.getMessage());
606                 }
607
608                 if (row < minResultSet) {
609                         log.error("Statement returned " + row + " rows, violating minResultSet of " + minResultSet);
610                         throw new JDBCAttributeExtractorException("Statement returned " + row + " rows, violating minResultSet of "
611                                         + minResultSet);
612                 }
613                 return attributes;
614         }
615 }
616
617 class DefaultStatementCreator implements JDBCStatementCreator {
618
619         private static Logger log = Logger.getLogger(DefaultStatementCreator.class.getName());
620         private int numberOfParams = 1;
621
622         public DefaultStatementCreator(Element conf) throws JDBCStatementCreatorException {
623
624                 if (conf != null && conf.getAttribute("numberOfParams") != null
625                                 && !(conf.getAttribute("numberOfParams").equals(""))) {
626                         try {
627                                 numberOfParams = Integer.parseInt(conf.getAttribute("numberOfParams"));
628                                 if (numberOfParams < 0) { throw new NumberFormatException(
629                                                 "The number of parameters cannot be less than 0."); }
630                         } catch (NumberFormatException nfe) {
631                                 log.error("Statement Creator () attribute must be a positive integer: " + nfe);
632                                 throw new JDBCStatementCreatorException("Statement Creator () attribute must be a positive integer.");
633                         }
634                 }
635
636                 log.debug("Parameters configured: " + numberOfParams);
637         }
638
639         public void create(PreparedStatement preparedStatement, Principal principal, String requester, String responder,
640                         Dependencies depends) throws JDBCStatementCreatorException {
641
642                 log.debug("Creating prepared statement.  Substituting principal: (" + principal.getName() + ")");
643                 // Tried using ParameterMetaData to determine param count, but it fails, so...
644                 try {
645                         for (int i = 1; i <= numberOfParams; i++) {
646                                 preparedStatement.setString(i++, principal.getName());
647                         }
648                 } catch (SQLException e) {
649                         // Ignore any additional exceptions, assume parameters simply don't exist.
650                 }
651         }
652 }
653
654 class DependencyStatementCreator implements JDBCStatementCreator {
655
656         private static Logger log = Logger.getLogger(DependencyStatementCreator.class.getName());
657         private ArrayList parameters = new ArrayList();
658
659         public DependencyStatementCreator(Element conf) throws JDBCStatementCreatorException {
660
661                 NodeList nodes = conf.getElementsByTagName("Parameter");
662                 for (int i = 0; i < nodes.getLength(); i++) {
663                         Element parameter = (Element) nodes.item(i);
664                         String type = "String";
665                         if (parameter.getAttribute("type") != null && (!parameter.getAttribute("type").equals(""))) {
666                                 type = parameter.getAttribute("type");
667                         }
668
669                         if (parameter.getAttribute("attributeName") == null || parameter.getAttribute("attributeName").equals("")) {
670                                 log.error("Statement Creator Parameter must reference an attribute by name.");
671                                 throw new JDBCStatementCreatorException(
672                                                 "Statement Creator Parameter must reference an attribute by name.");
673                         }
674
675                         if (parameter.getAttribute("connectorId") != null && (!parameter.getAttribute("connectorId").equals(""))) {
676                                 parameters.add(new Parameter(type, parameter.getAttribute("attributeName"), parameter
677                                                 .getAttribute("connectorId")));
678                         } else {
679                                 parameters.add(new Parameter(type, parameter.getAttribute("attributeName")));
680
681                         }
682
683                         if (parameter.getAttribute("nullMissing") != null && (!parameter.getAttribute("nullMissing").equals(""))) {
684                                 if (parameter.getAttribute("nullMissing").equalsIgnoreCase("FALSE")) {
685                                         ((Parameter) parameters.get(i)).setNullMissing(false);
686                                 }
687                         }
688                 }
689                 log.debug("Parameters configured: " + parameters.size());
690         }
691
692         public void create(PreparedStatement preparedStatement, Principal principal, String requester, String responder,
693                         Dependencies depends) throws JDBCStatementCreatorException {
694
695                 try {
696                         log.debug("Creating prepared statement.  Substituting values from dependencies.");
697                         for (int i = 0; i < parameters.size(); i++) {
698                                 ((Parameter) parameters.get(i)).setParameterValue(preparedStatement, i + 1, depends, principal,
699                                                 requester);
700                         }
701
702                 } catch (Exception e) {
703                         log.error("Encountered an error while creating prepared statement (principal=" + principal.getName()
704                                         + "): " + e);
705                         throw new JDBCStatementCreatorException("Encountered an error while creating prepared statement: "
706                                         + e.getMessage());
707                 }
708         }
709
710         protected class Parameter {
711
712                 private String type;
713                 private String attributeName;
714                 private boolean referencesConnector = false;
715                 private String connectorId;
716                 private boolean nullMissing = true;
717
718                 protected Parameter(String type, String attributeName) throws JDBCStatementCreatorException {
719
720                         if ((!type.equalsIgnoreCase("String")) && (!type.equalsIgnoreCase("Integer"))
721                                         && (!type.equalsIgnoreCase("Byte")) && (!type.equalsIgnoreCase("Double"))
722                                         && (!type.equalsIgnoreCase("Float")) && (!type.equalsIgnoreCase("Long"))
723                                         && (!type.equalsIgnoreCase("Short")) && (!type.equalsIgnoreCase("Boolean"))
724                                         && (!type.equalsIgnoreCase("Date")) && (!type.equalsIgnoreCase("Blob"))
725                                         && (!type.equalsIgnoreCase("Clob"))) {
726                                 log.error("Unsupported type configured for Statement Creator Parameter.");
727                                 throw new JDBCStatementCreatorException("Unable to load Statement Creator Parameter.");
728                         }
729                         this.type = type;
730                         this.attributeName = attributeName;
731
732                         if (attributeName == null) {
733                                 log.error("No (attributeName) attribute specified for Statement Creator Parameter.");
734                                 throw new JDBCStatementCreatorException("Unable to load Statement Creator Parameter.");
735                         } else if ((attributeName.equals("%PRINCIPAL%") || attributeName.equals("%REQUESTER%"))
736                                         && !type.equalsIgnoreCase("String")) {
737                                 log.error("The (type) attribute must be set to \"String\" when \"%PRINCIPAL%\" or \"%REQUESTER%\" is "
738                                                 + "used as the (attributeName) for a Statement Creator Parameter.");
739                                 throw new JDBCStatementCreatorException("Unable to load Statement Creator Parameter.");
740                         }
741                 }
742
743                 protected Parameter(String type, String attributeName, String connectorId) throws JDBCStatementCreatorException {
744
745                         this(type, attributeName);
746                         referencesConnector = true;
747                         this.connectorId = connectorId;
748
749                 }
750
751                 protected int getSQLType() {
752
753                         if (type.equalsIgnoreCase("String")) {
754                                 return Types.VARCHAR;
755                         } else if (type.equalsIgnoreCase("Integer")) {
756                                 return Types.INTEGER;
757                         } else if (type.equalsIgnoreCase("Byte")) {
758                                 return Types.TINYINT;
759                         } else if (type.equalsIgnoreCase("Double")) {
760                                 return Types.DOUBLE;
761                         } else if (type.equalsIgnoreCase("Float")) {
762                                 return Types.FLOAT;
763                         } else if (type.equalsIgnoreCase("Long")) {
764                                 return Types.INTEGER;
765                         } else if (type.equalsIgnoreCase("Short")) {
766                                 return Types.SMALLINT;
767                         } else if (type.equalsIgnoreCase("Boolean")) {
768                                 return Types.BOOLEAN;
769                         } else if (type.equalsIgnoreCase("Date")) {
770                                 return Types.DATE;
771                         } else if (type.equalsIgnoreCase("Blob")) {
772                                 return Types.BLOB;
773                         } else if (type.equalsIgnoreCase("Clob")) {
774                                 return Types.CLOB;
775                         } else {
776                                 return Types.VARCHAR;
777                         }
778                 }
779
780                 protected void setParameterValue(PreparedStatement preparedStatement, int valueIndex, Dependencies depends,
781                                 Principal principal, String requester) throws JDBCStatementCreatorException {
782
783                         // handle values from DataConnectors
784                         if (referencesConnector) {
785                                 Attributes attributes = depends.getConnectorResolution(connectorId);
786                                 if (attributes == null) {
787                                         log.error("Statement Creator misconfiguration: Connector (" + connectorId
788                                                         + ") is not a dependency of this JDBCDataConnector.");
789                                         throw new JDBCStatementCreatorException("Statement Creator misconfiguration: Connector ("
790                                                         + connectorId + ") is not a dependency of this JDBCDataConnector.");
791                                 }
792
793                                 Attribute attribute = attributes.get(attributeName);
794                                 if (attribute == null || attribute.size() < 1) {
795                                         if (attributeName.equalsIgnoreCase("%REQUESTER%")) {
796                                                 try {
797                                                         setSpecificParameter(preparedStatement, valueIndex, requester);
798                                                         return;
799                                                 } catch (Exception e) {
800                                                         log.error("Statement Creator encountered an error while adding the parameter 'Requester': "
801                                                                         + e);
802                                                         throw new JDBCStatementCreatorException(
803                                                                         "Statement Creator encountered an error while parameter 'Requester': "
804                                                                                         + e.getMessage());
805                                                 }
806                                         } else if (attributeName.equalsIgnoreCase("%PRINCIPAL%")) {
807                                                 try {
808                                                         setSpecificParameter(preparedStatement, valueIndex, principal.toString());
809                                                         return;
810                                                 } catch (Exception e) {
811                                                         log.error("Statement Creator encountered an error while adding the parameter 'Requester': "
812                                                                         + e);
813                                                         throw new JDBCStatementCreatorException(
814                                                                         "Statement Creator encountered an error while parameter 'Requester': "
815                                                                                         + e.getMessage());
816                                                 }
817                                         } else if (nullMissing) {
818                                                 try {
819                                                         preparedStatement.setNull(valueIndex, getSQLType());
820                                                         return;
821                                                 } catch (SQLException e) {
822                                                         log
823                                                                         .error("Encountered a problem while attempting to convert missing attribute value to null parameter.");
824                                                 }
825                                         }
826                                         log.error("Cannot parameterize prepared statement: missing dependency value.");
827                                         throw new JDBCStatementCreatorException(
828                                                         "Cannot parameterize prepared statement: missing dependency value.");
829                                 }
830
831                                 if (attribute.size() > 1) {
832                                         log.error("Statement Creator encountered a multivalued dependent attribute.");
833                                         throw new JDBCStatementCreatorException(
834                                                         "Statement Creator encountered a multivalued dependent attribute.");
835                                 }
836
837                                 try {
838                                         setSpecificParameter(preparedStatement, valueIndex, attribute.get());
839                                         return;
840                                 } catch (NamingException e) {
841                                         log.error("Statement Creator encountered an error while extracting attributes "
842                                                         + "from a Data Conector: " + e);
843                                         throw new JDBCStatementCreatorException(
844                                                         "Statement Creator encountered an error while extracting attributes from a Data Conector: "
845                                                                         + e.getMessage());
846                                 }
847                         }
848
849                         // handle values from AttributeDefinitons
850                         ResolverAttribute attribute = depends.getAttributeResolution(attributeName);
851                         if (attribute != null) {
852                                 Iterator iterator = attribute.getValues();
853                                 if (iterator.hasNext()) {
854                                         setSpecificParameter(preparedStatement, valueIndex, iterator.next());
855                                         if (iterator.hasNext()) {
856                                                 log.error("Statement Creator encountered a multivalued dependent attribute.");
857                                                 throw new JDBCStatementCreatorException(
858                                                                 "Statement Creator encountered a multivalued dependent attribute.");
859                                         }
860                                         return;
861                                 }
862                         }
863                         if (nullMissing) {
864                                 try {
865                                         preparedStatement.setNull(valueIndex, getSQLType());
866                                         return;
867                                 } catch (SQLException e) {
868                                         log.error("Encountered a problem while attempting to convert missing attribute "
869                                                         + "value to null parameter.");
870                                 }
871                         }
872                         log.error("Cannot parameterize prepared statement: missing dependency value.");
873                         throw new JDBCStatementCreatorException("Cannot parameterize prepared statement: missing dependency value.");
874                 }
875
876                 protected void setNullMissing(boolean nullMissing) {
877
878                         this.nullMissing = nullMissing;
879                 }
880
881                 private void setSpecificParameter(PreparedStatement preparedStatement, int valueIndex, Object object)
882                                 throws JDBCStatementCreatorException {
883
884                         if (object == null) {
885                                 try {
886                                         preparedStatement.setNull(valueIndex, getSQLType());
887                                         return;
888                                 } catch (SQLException e) {
889                                         log
890                                                         .error("Encountered a problem while attempting to convert missing attribute value to null parameter.");
891                                         throw new JDBCStatementCreatorException(
892                                                         "Encountered a problem while attempting to convert missing attribute value to null parameter.");
893                                 }
894                         } else if (type.equalsIgnoreCase("String")) {
895                                 setString(preparedStatement, valueIndex, object);
896                         } else if (type.equalsIgnoreCase("Integer")) {
897                                 setInteger(preparedStatement, valueIndex, object);
898                         } else if (type.equalsIgnoreCase("Byte")) {
899                                 setByte(preparedStatement, valueIndex, object);
900                         } else if (type.equalsIgnoreCase("Double")) {
901                                 setDouble(preparedStatement, valueIndex, object);
902                         } else if (type.equalsIgnoreCase("Float")) {
903                                 setFloat(preparedStatement, valueIndex, object);
904                         } else if (type.equalsIgnoreCase("Long")) {
905                                 setLong(preparedStatement, valueIndex, object);
906                         } else if (type.equalsIgnoreCase("Short")) {
907                                 setShort(preparedStatement, valueIndex, object);
908                         } else if (type.equalsIgnoreCase("Boolean")) {
909                                 setBoolean(preparedStatement, valueIndex, object);
910                         } else if (type.equalsIgnoreCase("Date")) {
911                                 setDate(preparedStatement, valueIndex, object);
912                         } else if (type.equalsIgnoreCase("Blob")) {
913                                 setBlob(preparedStatement, valueIndex, object);
914                         } else if (type.equalsIgnoreCase("Clob")) {
915                                 setClob(preparedStatement, valueIndex, object);
916                         } else {
917                                 setString(preparedStatement, valueIndex, object);
918                         }
919                 }
920
921                 private void setClob(PreparedStatement preparedStatement, int valueIndex, Object object)
922                                 throws JDBCStatementCreatorException {
923
924                         if (object instanceof Clob) {
925                                 try {
926                                         preparedStatement.setClob(valueIndex, (Clob) object);
927                                         return;
928                                 } catch (SQLException e) {
929                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
930                                         throw new JDBCStatementCreatorException(
931                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
932                                 }
933                         }
934                         log.error("Encountered a dependency with an invalid java type.");
935                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
936                 }
937
938                 private void setBlob(PreparedStatement preparedStatement, int valueIndex, Object object)
939                                 throws JDBCStatementCreatorException {
940
941                         if (object instanceof Blob) {
942                                 try {
943                                         preparedStatement.setBlob(valueIndex, (Blob) object);
944                                         return;
945                                 } catch (SQLException e) {
946                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
947                                         throw new JDBCStatementCreatorException(
948                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
949                                 }
950                         }
951                         log.error("Encountered a dependency with an invalid java type.");
952                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
953                 }
954
955                 private void setDate(PreparedStatement preparedStatement, int valueIndex, Object object)
956                                 throws JDBCStatementCreatorException {
957
958                         if (object instanceof java.sql.Date) {
959                                 try {
960                                         preparedStatement.setDate(valueIndex, (java.sql.Date) object);
961                                         return;
962                                 } catch (SQLException e) {
963                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
964                                         throw new JDBCStatementCreatorException(
965                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
966                                 }
967                         } else if (object instanceof java.util.Date) {
968                                 try {
969                                         // If you want to be frustrated by the java class library, look no further...
970                                         preparedStatement.setDate(valueIndex, new java.sql.Date(((java.util.Date) object).getTime()));
971                                         return;
972                                 } catch (SQLException e) {
973                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
974                                         throw new JDBCStatementCreatorException(
975                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
976                                 }
977                         } else if (object instanceof Long) {
978                                 try {
979                                         preparedStatement.setDate(valueIndex, new java.sql.Date(((Long) object).longValue()));
980                                         return;
981                                 } catch (SQLException e) {
982                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
983                                         throw new JDBCStatementCreatorException(
984                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
985                                 }
986                         } else if (object instanceof String) {
987                                 try {
988                                         preparedStatement.setDate(valueIndex, new java.sql.Date(new SimpleDateFormat().parse(
989                                                         (String) object).getTime()));
990                                         return;
991                                 } catch (Exception e) {
992                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
993                                         throw new JDBCStatementCreatorException(
994                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
995                                 }
996                         }
997                         log.error("Encountered a dependency with an invalid java type.");
998                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
999                 }
1000
1001                 private void setBoolean(PreparedStatement preparedStatement, int valueIndex, Object object)
1002                                 throws JDBCStatementCreatorException {
1003
1004                         if (object instanceof Boolean) {
1005                                 try {
1006                                         preparedStatement.setBoolean(valueIndex, ((Boolean) object).booleanValue());
1007                                         return;
1008                                 } catch (SQLException e) {
1009                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1010                                         throw new JDBCStatementCreatorException(
1011                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1012                                 }
1013                         } else if (object instanceof String) {
1014                                 try {
1015                                         preparedStatement.setBoolean(valueIndex, new Boolean((String) object).booleanValue());
1016                                         return;
1017                                 } catch (Exception e) {
1018                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1019                                         throw new JDBCStatementCreatorException(
1020                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1021                                 }
1022                         }
1023                         log.error("Encountered a dependency with an invalid java type.");
1024                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1025                 }
1026
1027                 private void setShort(PreparedStatement preparedStatement, int valueIndex, Object object)
1028                                 throws JDBCStatementCreatorException {
1029
1030                         if (object instanceof Boolean) {
1031                                 try {
1032                                         preparedStatement.setShort(valueIndex, ((Short) object).shortValue());
1033                                         return;
1034                                 } catch (SQLException e) {
1035                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1036                                         throw new JDBCStatementCreatorException(
1037                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1038                                 }
1039                         } else if (object instanceof String) {
1040                                 try {
1041                                         preparedStatement.setShort(valueIndex, new Short((String) object).shortValue());
1042                                         return;
1043                                 } catch (Exception e) {
1044                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1045                                         throw new JDBCStatementCreatorException(
1046                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1047                                 }
1048                         }
1049                         log.error("Encountered a dependency with an invalid java type.");
1050                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1051                 }
1052
1053                 private void setLong(PreparedStatement preparedStatement, int valueIndex, Object object)
1054                                 throws JDBCStatementCreatorException {
1055
1056                         if (object instanceof Long || object instanceof Integer || object instanceof Short) {
1057                                 try {
1058                                         preparedStatement.setLong(valueIndex, ((Number) object).longValue());
1059                                         return;
1060                                 } catch (SQLException e) {
1061                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1062                                         throw new JDBCStatementCreatorException(
1063                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1064                                 }
1065                         } else if (object instanceof String) {
1066                                 try {
1067                                         preparedStatement.setLong(valueIndex, new Long((String) object).longValue());
1068                                         return;
1069                                 } catch (Exception e) {
1070                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1071                                         throw new JDBCStatementCreatorException(
1072                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1073                                 }
1074                         }
1075                         log.error("Encountered a dependency with an invalid java type.");
1076                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1077                 }
1078
1079                 private void setFloat(PreparedStatement preparedStatement, int valueIndex, Object object)
1080                                 throws JDBCStatementCreatorException {
1081
1082                         if (object instanceof Float) {
1083                                 try {
1084                                         preparedStatement.setFloat(valueIndex, ((Float) object).floatValue());
1085                                         return;
1086                                 } catch (SQLException e) {
1087                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1088                                         throw new JDBCStatementCreatorException(
1089                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1090                                 }
1091                         } else if (object instanceof String) {
1092                                 try {
1093                                         preparedStatement.setFloat(valueIndex, new Float((String) object).floatValue());
1094                                         return;
1095                                 } catch (Exception e) {
1096                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1097                                         throw new JDBCStatementCreatorException(
1098                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1099                                 }
1100                         }
1101                         log.error("Encountered a dependency with an invalid java type.");
1102                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1103                 }
1104
1105                 private void setDouble(PreparedStatement preparedStatement, int valueIndex, Object object)
1106                                 throws JDBCStatementCreatorException {
1107
1108                         if (object instanceof Double || object instanceof Float) {
1109                                 try {
1110                                         preparedStatement.setDouble(valueIndex, ((Number) object).doubleValue());
1111                                         return;
1112                                 } catch (SQLException e) {
1113                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1114                                         throw new JDBCStatementCreatorException(
1115                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1116                                 }
1117                         } else if (object instanceof String) {
1118                                 try {
1119                                         preparedStatement.setDouble(valueIndex, new Double((String) object).doubleValue());
1120                                         return;
1121                                 } catch (Exception e) {
1122                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1123                                         throw new JDBCStatementCreatorException(
1124                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1125                                 }
1126                         }
1127                         log.error("Encountered a dependency with an invalid java type.");
1128                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1129                 }
1130
1131                 private void setByte(PreparedStatement preparedStatement, int valueIndex, Object object)
1132                                 throws JDBCStatementCreatorException {
1133
1134                         if (object instanceof Byte) {
1135                                 try {
1136                                         preparedStatement.setByte(valueIndex, ((Byte) object).byteValue());
1137                                         return;
1138                                 } catch (SQLException e) {
1139                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1140                                         throw new JDBCStatementCreatorException(
1141                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1142                                 }
1143                         } else if (object instanceof String) {
1144                                 try {
1145                                         preparedStatement.setByte(valueIndex, new Byte((String) object).byteValue());
1146                                         return;
1147                                 } catch (Exception e) {
1148                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1149                                         throw new JDBCStatementCreatorException(
1150                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1151                                 }
1152                         }
1153                         log.error("Encountered a dependency with an invalid java type.");
1154                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1155                 }
1156
1157                 private void setInteger(PreparedStatement preparedStatement, int valueIndex, Object object)
1158                                 throws JDBCStatementCreatorException {
1159
1160                         if (object instanceof Integer || object instanceof Short) {
1161                                 try {
1162                                         preparedStatement.setInt(valueIndex, ((Number) object).intValue());
1163                                         return;
1164                                 } catch (SQLException e) {
1165                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1166                                         throw new JDBCStatementCreatorException(
1167                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1168                                 }
1169                         } else if (object instanceof String) {
1170                                 try {
1171                                         preparedStatement.setInt(valueIndex, new Integer((String) object).intValue());
1172                                         return;
1173                                 } catch (Exception e) {
1174                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1175                                         throw new JDBCStatementCreatorException(
1176                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1177                                 }
1178                         }
1179                         log.error("Encountered a dependency with an invalid java type.");
1180                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1181                 }
1182
1183                 private void setString(PreparedStatement preparedStatement, int valueIndex, Object object)
1184                                 throws JDBCStatementCreatorException {
1185
1186                         if (object instanceof String) {
1187                                 try {
1188                                         preparedStatement.setString(valueIndex, (String) object);
1189                                         return;
1190                                 } catch (SQLException e) {
1191                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
1192                                         throw new JDBCStatementCreatorException(
1193                                                         "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
1194                                 }
1195                         }
1196                         log.error("Encountered a dependency with an invalid java type.");
1197                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
1198                 }
1199         }
1200 }