Beginnings of a Dependency Statement Creator for the JDBC Connector.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / attrresolv / provider / JDBCDataConnector.java
1 /*
2  * Copyright (c) 2003 National Research Council of Canada
3  *
4  * Permission is hereby granted, free of charge, to any person 
5  * obtaining a copy of this software and associated documentation 
6  * files (the "Software"), to deal in the Software without 
7  * restriction, including without limitation the rights to use, 
8  * copy, modify, merge, publish, distribute, sublicense, and/or 
9  * sell copies of the Software, and to permit persons to whom the 
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be 
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
17  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */
25
26 package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
27
28 import java.io.PrintWriter;
29 import java.lang.reflect.Constructor;
30 import java.security.Principal;
31 import java.sql.Blob;
32 import java.sql.Clob;
33 import java.sql.Connection;
34 import java.sql.PreparedStatement;
35 import java.sql.ResultSet;
36 import java.sql.ResultSetMetaData;
37 import java.sql.SQLException;
38 import java.text.SimpleDateFormat;
39 import java.util.ArrayList;
40 import java.util.Iterator;
41
42 import javax.naming.directory.Attributes;
43 import javax.naming.directory.BasicAttribute;
44 import javax.naming.directory.BasicAttributes;
45 import javax.sql.DataSource;
46
47 import org.apache.commons.dbcp.ConnectionFactory;
48 import org.apache.commons.dbcp.DriverManagerConnectionFactory;
49 import org.apache.commons.dbcp.PoolableConnectionFactory;
50 import org.apache.commons.dbcp.PoolingDataSource;
51 import org.apache.commons.pool.impl.GenericObjectPool;
52 import org.apache.commons.pool.impl.StackKeyedObjectPoolFactory;
53 import org.apache.log4j.Logger;
54 import org.apache.log4j.Priority;
55 import org.w3c.dom.Element;
56 import org.w3c.dom.Node;
57 import org.w3c.dom.NodeList;
58
59 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
60 import edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn;
61 import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
62 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
63 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
64
65 /*
66  * Built at the Canada Institute for Scientific and Technical Information (CISTI 
67  * <ahref="http://www.cisti-icist.nrc-cnrc.gc.ca/">http://www.cisti-icist.nrc-cnrc.gc.ca/</a>, 
68  * the National Research Council Canada 
69  * (NRC <a href="http://www.nrc-cnrc.gc.ca/">http://www.nrc-cnrc.gc.ca/</a>)
70  * by David Dearman, COOP student from Dalhousie University,
71  * under the direction of Glen Newton, Head research (IT)
72  * <ahref="mailto:glen.newton@nrc-cnrc.gc.ca">glen.newton@nrc-cnrc.gc.ca</a>. 
73  */
74
75 /**
76  * Data Connector that uses JDBC to access user attributes stored in databases.
77  *
78  * @author David Dearman (dearman@cs.dal.ca)
79  * @author Walter Hoehn (wassa@columbia.edu)
80  * @author Scott Cantor
81  */
82
83 public class JDBCDataConnector extends BaseResolutionPlugIn implements DataConnectorPlugIn {
84
85         private static Logger log = Logger.getLogger(JDBCDataConnector.class.getName());
86         protected String searchVal;
87         protected DataSource dataSource;
88         protected JDBCAttributeExtractor extractor;
89         protected JDBCStatementCreator statementCreator;
90
91         public JDBCDataConnector(Element element) throws ResolutionPlugInException {
92
93                 super(element);
94
95                 //Get the query string
96                 NodeList queryNodes = element.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "Query");
97                 Node tnode = queryNodes.item(0).getFirstChild();
98                 if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
99                         searchVal = tnode.getNodeValue();
100                 }
101                 if (searchVal == null || searchVal.equals("")) {
102                         log.error("Database query must be specified.");
103                         throw new ResolutionPlugInException("Database query must be specified.");
104                 }
105
106                 //Load the supplied JDBC driver
107                 String dbDriverName = element.getAttribute("dbDriver");
108                 if (dbDriverName != null && (!dbDriverName.equals(""))) {
109                         loadDriver(dbDriverName);
110                 }
111
112                 //Load site-specific implementation classes     
113                 setupAttributeExtractor(
114                         (Element) element.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "AttributeExtractor").item(
115                                 0));
116                 setupStatementCreator(
117                         (Element) element.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "StatementCreator").item(0));
118
119                 //Initialize a pooling Data Source
120                 int maxActive = 0;
121                 int maxIdle = 0;
122                 try {
123                         if (element.getAttribute("maxActive") != null) {
124                                 maxActive = Integer.parseInt(element.getAttribute("maxActive"));
125                         }
126                         if (element.getAttribute("maxIdle") != null) {
127                                 maxIdle = Integer.parseInt(element.getAttribute("maxIdle"));
128                         }
129                 } catch (NumberFormatException e) {
130                         log.error("Malformed pooling limits: using defaults.");
131                 }
132                 if (element.getAttribute("dbURL") == null || element.getAttribute("dbURL").equals("")) {
133                         log.error("JDBC connection requires a dbURL property");
134                         throw new ResolutionPlugInException("JDBCDataConnection requires a \"dbURL\" property");
135                 }
136                 setupDataSource(element.getAttribute("dbURL"), maxActive, maxIdle);
137         }
138
139         /**
140          * Initialize a Pooling Data Source
141          */
142         private void setupDataSource(String dbURL, int maxActive, int maxIdle) throws ResolutionPlugInException {
143
144                 GenericObjectPool objectPool = new GenericObjectPool(null);
145
146                 if (maxActive > 0) {
147                         objectPool.setMaxActive(maxActive);
148                 }
149                 if (maxIdle > 0) {
150                         objectPool.setMaxIdle(maxIdle);
151                 }
152
153                 objectPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
154
155                 ConnectionFactory connFactory = null;
156                 PoolableConnectionFactory poolConnFactory = null;
157
158                 try {
159                         connFactory = new DriverManagerConnectionFactory(dbURL, null);
160                         log.debug("Connection factory initialized.");
161                 } catch (Exception ex) {
162                         log.error(
163                                 "Connection factory couldn't be initialized, ensure database URL, username and password are correct.");
164                         throw new ResolutionPlugInException("Connection facotry couldn't be initialized: " + ex.getMessage());
165                 }
166
167                 try {
168                         new StackKeyedObjectPoolFactory();
169                         poolConnFactory =
170                                 new PoolableConnectionFactory(
171                                         connFactory,
172                                         objectPool,
173                                         new StackKeyedObjectPoolFactory(),
174                                         null,
175                                         false,
176                                         true);
177                 } catch (Exception ex) {
178                         log.debug("Poolable connection factory error");
179                 }
180
181                 dataSource = new PoolingDataSource(objectPool);
182                 log.info("Data Source initialized.");
183                 try {
184                         dataSource.setLogWriter(
185                                 new Log4jPrintWriter(Logger.getLogger(JDBCDataConnector.class.getName() + ".Pool"), Priority.DEBUG));
186                 } catch (SQLException e) {
187                         log.error("Coudn't setup logger for database connection pool.");
188                 }
189         }
190
191         /**
192          * Instantiate an Attribute Extractor, using the default if none was configured
193          */
194         private void setupAttributeExtractor(Element config) throws ResolutionPlugInException {
195
196                 String className = null;
197                 if (config != null) {
198                         className = config.getAttribute("class");
199                 }
200                 if (className == null || className.equals("")) {
201                         log.debug("Using default Attribute Extractor.");
202                         className = DefaultAE.class.getName();
203                 }
204                 try {
205                         Class aeClass = Class.forName(className);
206                         extractor = (JDBCAttributeExtractor) aeClass.newInstance();
207                         log.debug("Attribute Extractor implementation loaded.");
208
209                 } catch (ClassNotFoundException e) {
210                         log.error("The supplied Attribute Extractor class could not be found: " + e);
211                         throw new ResolutionPlugInException(
212                                 "The supplied Attribute Extractor class could not be found: " + e.getMessage());
213                 } catch (Exception e) {
214                         log.error("Unable to instantiate Attribute Extractor implementation: " + e);
215                         throw new ResolutionPlugInException(
216                                 "Unable to instantiate Attribute Extractor implementation: " + e.getMessage());
217                 }
218         }
219
220         /**
221          * Instantiate a Statement Creator, using the default if none was configured
222          */
223         private void setupStatementCreator(Element config) throws ResolutionPlugInException {
224
225                 String scClassName = null;
226                 if (config != null) {
227                         scClassName = config.getAttribute("class");
228                 }
229                 if (scClassName == null || scClassName.equals("")) {
230                         log.debug("Using default Statement Creator.");
231                         scClassName = DefaultStatementCreator.class.getName();
232                 }
233                 try {
234                         Class scClass = Class.forName(scClassName);
235
236                         Class[] params = new Class[1];
237                         params[0] = Class.forName("org.w3c.dom.Element");
238                         try {
239                                 Constructor implementorConstructor = scClass.getConstructor(params);
240                                 Object[] args = new Object[1];
241                                 args[0] = config;
242                                 log.debug("Initializing Statement Creator of type (" + scClass.getName() + ").");
243                                 statementCreator = (JDBCStatementCreator) implementorConstructor.newInstance(args);
244                         } catch (NoSuchMethodException nsme) {
245                                 log.debug(
246                                         "Implementation constructor does have a parameterized constructor, attempting to load default.");
247                                 statementCreator = (JDBCStatementCreator) scClass.newInstance();
248                         }
249                         log.debug("Statement Creator implementation loaded.");
250
251                 } catch (ClassNotFoundException e) {
252                         log.error("The supplied Statement Creator class could not be found: " + e);
253                         throw new ResolutionPlugInException(
254                                 "The supplied Statement Creator class could not be found: " + e.getMessage());
255                 } catch (Exception e) {
256                         log.error("Unable to instantiate Statement Creator implementation: " + e);
257                         throw new ResolutionPlugInException(
258                                 "Unable to instantiate Statement Creator implementation: " + e.getMessage());
259                 }
260         }
261
262         public Attributes resolve(Principal principal, String requester, Dependencies depends)
263                 throws ResolutionPlugInException {
264
265                 log.debug("Resolving connector: (" + getId() + ")");
266
267                 //Retrieve a connection from the connection pool
268                 Connection conn = null;
269                 try {
270                         conn = dataSource.getConnection();
271                         log.debug("Connection retrieved from pool");
272                 } catch (Exception e) {
273                         log.error("Unable to fetch a connection from the pool");
274                         throw new ResolutionPlugInException("Unable to fetch a connection from the pool: " + e.getMessage());
275                 }
276                 if (conn == null) {
277                         log.error("Pool didn't return a propertly initialized connection.");
278                         throw new ResolutionPlugInException("Pool didn't return a propertly initialized connection.");
279                 }
280
281                 //Setup and execute a (pooled) prepared statement
282                 ResultSet rs = null;
283                 PreparedStatement preparedStatement;
284                 try {
285                         preparedStatement = conn.prepareStatement(searchVal);
286                         statementCreator.create(preparedStatement, principal, requester, depends);
287                         rs = preparedStatement.executeQuery();
288                         if (!rs.next()) {
289                                 return new BasicAttributes();
290                         }
291
292                 } catch (JDBCStatementCreatorException e) {
293                         log.error("An ERROR occured while constructing the query");
294                         throw new ResolutionPlugInException("An ERROR occured while constructing the query: " + e.getMessage());
295                 } catch (SQLException e) {
296                         log.error("An ERROR occured while executing the query");
297                         throw new ResolutionPlugInException("An ERROR occured while executing the query: " + e.getMessage());
298                 }
299
300                 //Extract attributes from the ResultSet
301                 try {
302                         return extractor.extractAttributes(rs);
303
304                 } catch (JDBCAttributeExtractorException e) {
305                         log.error("An ERROR occured while extracting attributes from result set");
306                         throw new ResolutionPlugInException(
307                                 "An ERROR occured while extracting attributes from result set: " + e.getMessage());
308                 } finally {
309                         try {
310                                 if (preparedStatement != null) {
311                                         preparedStatement.close();
312                                 }
313                         } catch (SQLException e) {
314                                 log.error("An error occured while closing the prepared statement: " + e);
315                                 throw new ResolutionPlugInException("An error occured while closing the prepared statemen: " + e);
316                         }
317                         try {
318                                 rs.close();
319                         } catch (SQLException e) {
320                                 log.error("An error occured while closing the result set: " + e);
321                                 throw new ResolutionPlugInException("An error occured while closing the result set: " + e);
322                         }
323
324                         try {
325                                 conn.close();
326                         } catch (SQLException e) {
327                                 log.error("An error occured while closing the database connection: " + e);
328                                 throw new ResolutionPlugInException("An error occured while closing the database connection: " + e);
329                         }
330                 }
331         }
332
333         /** 
334          * Loads the driver used to access the database
335          * @param driver The driver used to access the database
336          * @throws ResolutionPlugInException If there is a failure to load the driver
337          */
338         public void loadDriver(String driver) throws ResolutionPlugInException {
339                 try {
340                         Class.forName(driver).newInstance();
341                         log.debug("Loading JDBC driver: " + driver);
342                 } catch (Exception e) {
343                         log.error("An error loading database driver: " + e);
344                         throw new ResolutionPlugInException(
345                                 "An IllegalAccessException occured while loading database driver: " + e.getMessage());
346                 }
347                 log.debug("Driver loaded.");
348         }
349
350         private class Log4jPrintWriter extends PrintWriter {
351
352                 private Priority level;
353                 private Logger logger;
354                 private StringBuffer text = new StringBuffer("");
355
356                 private Log4jPrintWriter(Logger logger, org.apache.log4j.Priority level) {
357                         super(System.err);
358                         this.level = level;
359                         this.logger = logger;
360                 }
361
362                 public void close() {
363                         flush();
364                 }
365
366                 public void flush() {
367                         if (!text.toString().equals("")) {
368                                 logger.log(level, text.toString());
369                                 text.setLength(0);
370                         }
371                 }
372
373                 public void print(boolean b) {
374                         text.append(b);
375                 }
376
377                 public void print(char c) {
378                         text.append(c);
379                 }
380
381                 public void print(char[] s) {
382                         text.append(s);
383                 }
384
385                 public void print(double d) {
386                         text.append(d);
387                 }
388
389                 public void print(float f) {
390                         text.append(f);
391                 }
392
393                 public void print(int i) {
394                         text.append(i);
395                 }
396
397                 public void print(long l) {
398                         text.append(l);
399                 }
400
401                 public void print(Object obj) {
402                         text.append(obj);
403                 }
404
405                 public void print(String s) {
406                         text.append(s);
407                 }
408
409                 public void println() {
410                         if (!text.toString().equals("")) {
411                                 logger.log(level, text.toString());
412                                 text.setLength(0);
413                         }
414                 }
415
416                 public void println(boolean x) {
417                         text.append(x);
418                         logger.log(level, text.toString());
419                         text.setLength(0);
420                 }
421
422                 public void println(char x) {
423                         text.append(x);
424                         logger.log(level, text.toString());
425                         text.setLength(0);
426                 }
427
428                 public void println(char[] x) {
429                         text.append(x);
430                         logger.log(level, text.toString());
431                         text.setLength(0);
432                 }
433
434                 public void println(double x) {
435                         text.append(x);
436                         logger.log(level, text.toString());
437                         text.setLength(0);
438                 }
439
440                 public void println(float x) {
441                         text.append(x);
442                         logger.log(level, text.toString());
443                         text.setLength(0);
444                 }
445
446                 public void println(int x) {
447                         text.append(x);
448                         logger.log(level, text.toString());
449                         text.setLength(0);
450                 }
451
452                 public void println(long x) {
453                         text.append(x);
454                         logger.log(level, text.toString());
455                         text.setLength(0);
456                 }
457
458                 public void println(Object x) {
459                         text.append(x);
460                         logger.log(level, text.toString());
461                         text.setLength(0);
462                 }
463
464                 public void println(String x) {
465                         text.append(x);
466                         logger.log(level, text.toString());
467                         text.setLength(0);
468                 }
469         }
470 }
471
472 /**
473  * The default attribute extractor. 
474  */
475 class DefaultAE implements JDBCAttributeExtractor {
476
477         private static Logger log = Logger.getLogger(DefaultAE.class.getName());
478
479         /**
480          * Method of extracting the attributes from the supplied result set.
481          *
482          * @param ResultSet The result set from the query which contains the attributes
483          * @return BasicAttributes as objects containing all the attributes
484          * @throws JDBCAttributeExtractorException If there is a complication in retrieving the attributes
485          */
486         public BasicAttributes extractAttributes(ResultSet rs) throws JDBCAttributeExtractorException {
487                 BasicAttributes attributes = new BasicAttributes();
488
489                 try {
490                         ResultSetMetaData rsmd = rs.getMetaData();
491                         int numColumns = rsmd.getColumnCount();
492                         log.debug("Number of returned columns: " + numColumns);
493
494                         for (int i = 1; i <= numColumns; i++) {
495                                 String columnName = rsmd.getColumnName(i);
496                                 String columnType = rsmd.getColumnTypeName(i);
497                                 Object columnValue = rs.getObject(columnName);
498                                 log.debug(
499                                         "("
500                                                 + i
501                                                 + ". ColumnType = "
502                                                 + columnType
503                                                 + ") "
504                                                 + columnName
505                                                 + " -> "
506                                                 + (columnValue != null ? columnValue.toString() : "(null)"));
507                                 attributes.put(new BasicAttribute(columnName, columnValue));
508                         }
509                 } catch (SQLException e) {
510                         log.error("An ERROR occured while retrieving result set meta data");
511                         throw new JDBCAttributeExtractorException(
512                                 "An ERROR occured while retrieving result set meta data: " + e.getMessage());
513                 }
514
515                 // Check for multiple rows.
516                 try {
517                         if (rs.next())
518                                 throw new JDBCAttributeExtractorException("Query returned more than one row.");
519                 } catch (SQLException e) {
520                         //TODO don't squelch this error!!!
521                 }
522
523                 return attributes;
524         }
525 }
526
527 class DefaultStatementCreator implements JDBCStatementCreator {
528
529         private static Logger log = Logger.getLogger(DefaultStatementCreator.class.getName());
530
531         public void create(
532                 PreparedStatement preparedStatement,
533                 Principal principal,
534                 String requester,
535                 Dependencies depends)
536                 throws JDBCStatementCreatorException {
537
538                 try {
539                         log.debug("Creating prepared statement.  Substituting principal: (" + principal.getName() + ")");
540                         preparedStatement.setString(1, principal.getName());
541                 } catch (SQLException e) {
542                         log.error("Encountered an error while creating prepared statement: " + e);
543                         throw new JDBCStatementCreatorException(
544                                 "Encountered an error while creating prepared statement: " + e.getMessage());
545                 }
546         }
547 }
548
549 class DependencyStatementCreator implements JDBCStatementCreator {
550
551         private static Logger log = Logger.getLogger(DependencyStatementCreator.class.getName());
552         private ArrayList parameters = new ArrayList();
553
554         public DependencyStatementCreator(Element conf) throws JDBCStatementCreatorException {
555
556                 NodeList nodes = conf.getElementsByTagName("Parameter");
557                 for (int i = 0; i < nodes.getLength(); i++) {
558                         Element parameter = (Element) nodes.item(i);
559                         String type = "String";
560                         if (parameter.getAttribute("type") != null && (!parameter.getAttribute("type").equals(""))) {
561                                 type = parameter.getAttribute("type");
562                         }
563
564                         if (parameter.getAttribute("attributeName") == null
565                                 || parameter.getAttribute("attributeName").equals("")) {
566                                 log.error("Statement Creator Parameter must reference an attribute by name.");
567                                 throw new JDBCStatementCreatorException("Statement Creator Parameter must reference an attribute by name.");
568                         }
569
570                         if (parameter.getAttribute("connectorId") != null && (!parameter.getAttribute("connectorId").equals(""))) {
571                                 parameters.add(
572                                         new Parameter(
573                                                 type,
574                                                 parameter.getAttribute("attributeName"),
575                                                 parameter.getAttribute("connectorId")));
576                         } else {
577                                 parameters.add(new Parameter(type, parameter.getAttribute("attributeName")));
578
579                         }
580                 }
581                 log.debug("Parameters configured: " + parameters.size());
582         }
583
584         public void create(
585                 PreparedStatement preparedStatement,
586                 Principal principal,
587                 String requester,
588                 Dependencies depends)
589                 throws JDBCStatementCreatorException {
590
591                 try {
592                         log.debug("Creating prepared statement.  Substituting values from dependencies.");
593                         for (int i = 0; i < parameters.size(); i++) {
594                                 ((Parameter) parameters.get(i)).setParameterValue(preparedStatement, i + 1, depends);
595                         }
596
597                 } catch (Exception e) {
598                         log.error("Encountered an error while creating prepared statement: " + e);
599                         throw new JDBCStatementCreatorException(
600                                 "Encountered an error while creating prepared statement: " + e.getMessage());
601                 }
602         }
603
604         private class Parameter {
605                 private String type;
606                 private String attributeName;
607                 private boolean referencesConnector = false;
608                 private String connectorId;
609
610                 private Parameter(String type, String attributeName) throws JDBCStatementCreatorException {
611                         if ((!type.equalsIgnoreCase("String"))
612                                 && (!type.equalsIgnoreCase("Integer"))
613                                 && (!type.equalsIgnoreCase("Byte"))
614                                 && (!type.equalsIgnoreCase("Double"))
615                                 && (!type.equalsIgnoreCase("Float"))
616                                 && (!type.equalsIgnoreCase("Long"))
617                                 && (!type.equalsIgnoreCase("Short"))
618                                 && (!type.equalsIgnoreCase("Boolean"))
619                                 && (!type.equalsIgnoreCase("Date"))
620                                 && (!type.equalsIgnoreCase("Blob"))
621                                 && (!type.equalsIgnoreCase("Clob"))) {
622                                 log.error("Unsupported type configured for Statement Creator Parameter.");
623                                 throw new JDBCStatementCreatorException("Unsupported type on Statement Creator Parameter.");
624                         }
625                         this.type = type;
626                         this.attributeName = attributeName;
627                 }
628
629                 private Parameter(String type, String attributeName, String connectorId) throws JDBCStatementCreatorException {
630                         this(type, attributeName);
631                         referencesConnector = true;
632                         this.connectorId = connectorId;
633
634                 }
635
636                 private Object setParameterValue(PreparedStatement preparedStatement, int valueIndex, Dependencies depends)
637                         throws JDBCStatementCreatorException {
638
639                         //TODO handle connector attributes
640                         ResolverAttribute attribute = depends.getAttributeResolution(attributeName);
641                         if (attribute != null) {
642                                 Object object = null;
643                                 Iterator iterator = attribute.getValues();
644                                 if (iterator.hasNext()) {
645                                         setSpecificParameter(preparedStatement, valueIndex, iterator.next());
646                                 } else {
647                                         //TODO make configurable (same as below)
648                                 }
649                                 if (iterator.hasNext()) {
650                                         log.error("Statement Creator encountered a multivalued dependent attribute.");
651                                         throw new JDBCStatementCreatorException("Statement Creator encountered a multivalued dependent attribute.");
652                                 }
653                                 return object;
654                         } else {
655                                 //TODO make configurable
656                                 throw new JDBCStatementCreatorException("foo");
657                         }
658                 }
659
660                 private void setSpecificParameter(PreparedStatement preparedStatement, int valueIndex, Object object)
661                         throws JDBCStatementCreatorException {
662
663                         if (type.equalsIgnoreCase("String")) {
664                                 setString(preparedStatement, valueIndex, object);
665                         } else if (type.equalsIgnoreCase("Integer")) {
666                                 setInteger(preparedStatement, valueIndex, object);
667                         } else if (type.equalsIgnoreCase("Byte")) {
668                                 setByte(preparedStatement, valueIndex, object);
669                         } else if (type.equalsIgnoreCase("Double")) {
670                                 setDouble(preparedStatement, valueIndex, object);
671                         } else if (type.equalsIgnoreCase("Float")) {
672                                 setFloat(preparedStatement, valueIndex, object);
673                         } else if (type.equalsIgnoreCase("Long")) {
674                                 setLong(preparedStatement, valueIndex, object);
675                         } else if (type.equalsIgnoreCase("Short")) {
676                                 setShort(preparedStatement, valueIndex, object);
677                         } else if (type.equalsIgnoreCase("Boolean")) {
678                                 setBoolean(preparedStatement, valueIndex, object);
679                         } else if (type.equalsIgnoreCase("Date")) {
680                                 setDate(preparedStatement, valueIndex, object);
681                         } else if (type.equalsIgnoreCase("Blob")) {
682                                 setBlob(preparedStatement, valueIndex, object);
683                         } else if (type.equalsIgnoreCase("Clob")) {
684                                 setClob(preparedStatement, valueIndex, object);
685                         } else {
686                                 setString(preparedStatement, valueIndex, object);
687                         }
688                 }
689
690                 private void setClob(PreparedStatement preparedStatement, int valueIndex, Object object)
691                         throws JDBCStatementCreatorException {
692                         if (object instanceof Clob) {
693                                 try {
694                                         preparedStatement.setClob(valueIndex, (Clob) object);
695                                         return;
696                                 } catch (SQLException e) {
697                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
698                                         throw new JDBCStatementCreatorException(
699                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
700                                 }
701                         }
702                         log.error("Encountered a dependency with an invalid java type.");
703                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
704
705                 }
706
707                 private void setBlob(PreparedStatement preparedStatement, int valueIndex, Object object)
708                         throws JDBCStatementCreatorException {
709                         if (object instanceof Blob) {
710                                 try {
711                                         preparedStatement.setBlob(valueIndex, (Blob) object);
712                                         return;
713                                 } catch (SQLException e) {
714                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
715                                         throw new JDBCStatementCreatorException(
716                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
717                                 }
718                         }
719                         log.error("Encountered a dependency with an invalid java type.");
720                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
721
722                 }
723
724                 private void setDate(PreparedStatement preparedStatement, int valueIndex, Object object)
725                         throws JDBCStatementCreatorException {
726
727                         if (object instanceof java.sql.Date) {
728                                 try {
729                                         preparedStatement.setDate(valueIndex, (java.sql.Date) object);
730                                         return;
731                                 } catch (SQLException e) {
732                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
733                                         throw new JDBCStatementCreatorException(
734                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
735                                 }
736                         } else if (object instanceof java.util.Date) {
737                                 try {
738                                         //If you want to be frustrated by the java class library, look no further...
739                                         preparedStatement.setDate(valueIndex, new java.sql.Date(((java.util.Date) object).getTime()));
740                                         return;
741                                 } catch (SQLException e) {
742                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
743                                         throw new JDBCStatementCreatorException(
744                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
745                                 }
746                         } else if (object instanceof Long) {
747                                 try {
748                                         preparedStatement.setDate(valueIndex, new java.sql.Date(((Long) object).longValue()));
749                                         return;
750                                 } catch (SQLException e) {
751                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
752                                         throw new JDBCStatementCreatorException(
753                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
754                                 }
755                         } else if (object instanceof String) {
756                                 try {
757                                         preparedStatement.setDate(
758                                                 valueIndex,
759                                                 new java.sql.Date(new SimpleDateFormat().parse((String) object).getTime()));
760                                         return;
761                                 } catch (Exception e) {
762                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
763                                         throw new JDBCStatementCreatorException(
764                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
765                                 }
766                         }
767                         log.error("Encountered a dependency with an invalid java type.");
768                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
769
770                 }
771
772                 private void setBoolean(PreparedStatement preparedStatement, int valueIndex, Object object)
773                         throws JDBCStatementCreatorException {
774                         // TODO Auto-generated method stub
775
776                 }
777
778                 private void setShort(PreparedStatement preparedStatement, int valueIndex, Object object)
779                         throws JDBCStatementCreatorException {
780                         // TODO Auto-generated method stub
781
782                 }
783
784                 private void setLong(PreparedStatement preparedStatement, int valueIndex, Object object)
785                         throws JDBCStatementCreatorException {
786                         // TODO Auto-generated method stub
787
788                 }
789
790                 private void setFloat(PreparedStatement preparedStatement, int valueIndex, Object object)
791                         throws JDBCStatementCreatorException {
792                         // TODO Auto-generated method stub
793
794                 }
795
796                 private void setDouble(PreparedStatement preparedStatement, int valueIndex, Object object)
797                         throws JDBCStatementCreatorException {
798                         // TODO Auto-generated method stub
799
800                 }
801
802                 private void setByte(PreparedStatement preparedStatement, int valueIndex, Object object)
803                         throws JDBCStatementCreatorException {
804                         // TODO Auto-generated method stub
805
806                 }
807
808                 private void setInteger(PreparedStatement preparedStatement, int valueIndex, Object object)
809                         throws JDBCStatementCreatorException {
810                         // TODO Auto-generated method stub
811
812                 }
813
814                 private void setString(PreparedStatement preparedStatement, int valueIndex, Object object)
815                         throws JDBCStatementCreatorException {
816                         if (object instanceof String) {
817                                 try {
818                                         preparedStatement.setString(valueIndex, (String) object);
819                                         return;
820                                 } catch (SQLException e) {
821                                         log.error("Encountered an error while adding parameter to prepared statement: " + e);
822                                         throw new JDBCStatementCreatorException(
823                                                 "Encountered an error while adding parameter to prepared statement: " + e.getMessage());
824                                 }
825                         }
826                         log.error("Encountered a dependency with an invalid java type.");
827                         throw new JDBCStatementCreatorException("Encountered a dependency with an invalid java type.");
828
829                 }
830         }
831 }
832
833
834
835
836