KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > lib > sql > XConnection


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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  * $Id: XConnection.java,v 1.29 2004/02/11 17:56:36 minchau Exp $
18  */

19 package org.apache.xalan.lib.sql;
20
21 import java.math.BigDecimal JavaDoc;
22 import java.sql.Connection JavaDoc;
23 import java.sql.Date JavaDoc;
24 import java.sql.PreparedStatement JavaDoc;
25 import java.sql.ResultSet JavaDoc;
26 import java.sql.SQLException JavaDoc;
27 import java.sql.SQLWarning JavaDoc;
28 import java.sql.Statement JavaDoc;
29 import java.sql.Time JavaDoc;
30 import java.sql.Timestamp JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.util.Properties JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34 import java.util.Vector JavaDoc;
35
36 import org.apache.xalan.extensions.ExpressionContext;
37 import org.apache.xml.dtm.DTM;
38 import org.apache.xml.dtm.DTMManager;
39 import org.apache.xml.dtm.ref.DTMManagerDefault;
40 import org.apache.xpath.XPathContext;
41 import org.apache.xpath.objects.XBooleanStatic;
42
43 import org.w3c.dom.Element JavaDoc;
44 import org.w3c.dom.NamedNodeMap JavaDoc;
45 import org.w3c.dom.Node JavaDoc;
46 import org.w3c.dom.NodeList JavaDoc;
47
48 import javax.xml.transform.ErrorListener JavaDoc;
49 import javax.xml.transform.TransformerException JavaDoc;
50
51 /**
52  * An XSLT extension that allows a stylesheet to
53  * access JDBC data.
54  *
55  * It is accessed by specifying a namespace URI as follows:
56  * <pre>
57  * xmlns:sql="http://xml.apache.org/xalan/sql"
58  * </pre>
59  *
60  * From the stylesheet perspective,
61  * XConnection provides 3 extension functions: new(),
62  * query(), and close().
63  * Use new() to call one of XConnection constructors, which
64  * establishes a JDBC driver connection to a data source and
65  * returns an XConnection object.
66  * Then use the XConnection object query() method to return a
67  * result set in the form of a row-set element.
68  * When you have finished working with the row-set, call the
69  * XConnection object close() method to terminate the connection.
70  */

71 public class XConnection
72 {
73
74   /**
75    * Flag for DEBUG mode
76    */

77   private static final boolean DEBUG = false;
78
79   /**
80    * The Current Connection Pool in Use. An XConnection can only
81    * represent one query at a time, prior to doing some type of query.
82    */

83   private ConnectionPool m_ConnectionPool = null;
84
85   /**
86    * The DBMS Connection used to produce this SQL Document.
87    * Will be used to clear free up the database resources on
88    * close.
89    */

90   private Connection JavaDoc m_Connection = null;
91
92   /**
93    * If a default Connection Pool is used. i.e. A connection Pool
94    * that is created internally, then do we actually allow pools
95    * to be created. Due to the archititure of the Xalan Extensions,
96    * there is no notification of when the Extension is being unloaded and
97    * as such, there is a good chance that JDBC COnnections are not closed.
98    * A finalized is provided to try and catch this situation but since
99    * support of finalizers is inconsistant across JVM's this may cause
100    * a problem. The robustness of the JDBC Driver is also at issue here.
101    * if a controlled shutdown is provided by the driver then default
102    * conntectiom pools are OK.
103    */

104   private boolean m_DefaultPoolingEnabled = false;
105
106
107   /**
108    * As we do queries, we will produce SQL Documents. Any ony may produce
109    * one or more SQL Documents so that the current connection information
110    * may be easilly reused. This collection will hold a collection of all
111    * the documents created. As Documents are closed, they will be removed
112    * from the collection and told to free all the used resources.
113    */

114   private Vector JavaDoc m_OpenSQLDocuments = new Vector JavaDoc();
115
116
117   /**
118    * Let's keep a copy of the ConnectionPoolMgr in
119    * alive here so we are keeping the static pool alive
120    * We will also use this Pool Manager to register our default pools.
121    */

122   private ConnectionPoolManager m_PoolMgr = new ConnectionPoolManager();
123
124   /**
125    * For PreparedStatements, we need a place to
126    * to store the parameters in a vector.
127    */

128   private Vector JavaDoc m_ParameterList = new Vector JavaDoc();
129
130   /**
131    * Allow the SQL Extensions to return null on error. The Error information will
132    * be stored in a seperate Error Document that can easily be retrived using the
133    * getError() method.
134    * %REVIEW% This functionality will probably be buried inside the SQLDocument.
135    */

136   private Exception JavaDoc m_Error = null;
137
138   /**
139    * When the Stylesheet wants to review the errors from a paticular
140    * document, it asks the XConnection. We need to track what document
141    * in the list of managed documents caused the last error. As SetError
142    * is called, it will record the document that had the error.
143    */

144   private SQLDocument m_LastSQLDocumentWithError = null;
145
146   /**
147    * If true then full information should be returned about errors and warnings
148    * in getError(). This includes chained errors and warnings.
149    * If false (the default) then getError() returns just the first SQLException.
150    */

151   private boolean m_FullErrors = false;
152
153
154
155   /**
156    * One a per XConnection basis there is a master QueryParser that is responsible
157    * for generating Query Parsers. This will allow us to cache previous instances
158    * so the inline parser execution time is minimized.
159    */

160   private SQLQueryParser m_QueryParser = new SQLQueryParser();
161
162   /**
163    */

164   private boolean m_IsDefaultPool = false;
165
166   /**
167    * This flag will be used to indicate to the SQLDocument to use
168    * Streaming mode. Streeaming Mode will reduce the memory footprint
169    * to a fixed amount but will not let you traverse the tree more than
170    * once since the Row data will be reused for every Row in the Query.
171    */

172   private boolean m_IsStreamingEnabled = true;
173
174   /**
175    *
176    */

177    private boolean m_InlineVariables = false;
178
179   /**
180    * This flag will be used to indicate if multiple result sets are
181    * supported from the database. If they are, then the metadata element is
182    * moved to insude the row-set element and multiple row-set elements may
183    * be included under the sql root element.
184    */

185   private boolean m_IsMultipleResultsEnabled = false;
186
187   /**
188    * This flag will be used to indicate if database preparedstatements
189    * should be cached. This also controls if the Java statement object
190    * should be cached.
191    */

192   private boolean m_IsStatementCachingEnabled = false;
193
194   /**
195    */

196   public XConnection( )
197   {
198   }
199
200   // The original constructors will be kept around for backwards
201
// compatibility. Future Stylesheets should use the approaite
202
// connect method to receive full error information.
203
//
204
/**
205    * @param exprContext
206    * @param ConnPoolName
207    */

208   public XConnection( ExpressionContext exprContext, String JavaDoc ConnPoolName )
209   {
210     connect(exprContext, ConnPoolName);
211   }
212
213   /**
214    * @param exprContext
215    * @param driver
216    * @param dbURL
217    */

218   public XConnection( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL )
219   {
220     connect(exprContext, driver, dbURL);
221   }
222
223   /**
224    * @param exprContext
225    * @param list
226    */

227   public XConnection( ExpressionContext exprContext, NodeList JavaDoc list )
228   {
229     connect(exprContext, list);
230   }
231
232   /**
233    * @param exprContext
234    * @param driver
235    * @param dbURL
236    * @param user
237    * @param password
238    */

239   public XConnection( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL, String JavaDoc user, String JavaDoc password )
240   {
241     connect(exprContext, driver, dbURL, user, password);
242   }
243
244   /**
245    * @param exprContext
246    * @param driver
247    * @param dbURL
248    * @param protocolElem
249    */

250   public XConnection( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL, Element JavaDoc protocolElem )
251   {
252     connect(exprContext, driver, dbURL, protocolElem);
253   }
254
255
256   /**
257    * Create an XConnection using the name of an existing Connection Pool
258    * @param exprContext
259    * @param ConnPoolName
260    *
261    */

262   public XBooleanStatic connect( ExpressionContext exprContext, String JavaDoc ConnPoolName )
263   {
264     try
265     {
266       m_ConnectionPool = m_PoolMgr.getPool(ConnPoolName);
267
268       if (m_ConnectionPool == null)
269         throw new java.lang.IllegalArgumentException JavaDoc("Invalid Pool Name");
270
271       m_IsDefaultPool = false;
272       return new XBooleanStatic(true);
273     }
274     catch (Exception JavaDoc e)
275     {
276       setError(e, exprContext);
277       return new XBooleanStatic(false);
278     }
279
280   }
281
282   /**
283    * Create an XConnection object with just a driver and database URL.
284    * @param exprContext
285    * @param driver JDBC driver of the form foo.bar.Driver.
286    * @param dbURL database URL of the form jdbc:subprotocol:subname.
287    *
288    */

289   public XBooleanStatic connect( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL )
290   {
291     try
292     {
293       init(driver, dbURL, new Properties JavaDoc());
294       return new XBooleanStatic(true);
295     }
296     catch(SQLException JavaDoc e)
297     {
298       setError(e,exprContext);
299       return new XBooleanStatic(false);
300     }
301     catch (Exception JavaDoc e)
302     {
303       setError(e,exprContext);
304       return new XBooleanStatic(false);
305     }
306   }
307
308   /**
309    * @param exprContext
310    * @param protocolElem
311    *
312    */

313   public XBooleanStatic connect( ExpressionContext exprContext, Element JavaDoc protocolElem )
314   {
315     try
316     {
317       initFromElement(protocolElem);
318       return new XBooleanStatic(true);
319     }
320     catch(SQLException JavaDoc e)
321     {
322       setError(e,exprContext);
323       return new XBooleanStatic(false);
324     }
325     catch (Exception JavaDoc e)
326     {
327       setError(e,exprContext);
328       return new XBooleanStatic(false);
329     }
330   }
331
332   /**
333    * @param exprContext
334    * @param list
335    *
336    */

337   public XBooleanStatic connect( ExpressionContext exprContext, NodeList JavaDoc list )
338   {
339     try
340     {
341       initFromElement( (Element JavaDoc) list.item(0) );
342       return new XBooleanStatic(true);
343     }
344     catch(SQLException JavaDoc e)
345     {
346       setError(e, exprContext);
347       return new XBooleanStatic(false);
348     }
349     catch (Exception JavaDoc e)
350     {
351       setError(e,exprContext);
352       return new XBooleanStatic(false);
353     }
354   }
355
356   /**
357    * Create an XConnection object with user ID and password.
358    * @param exprContext
359    * @param driver JDBC driver of the form foo.bar.Driver.
360    * @param dbURL database URL of the form jdbc:subprotocol:subname.
361    * @param user user ID.
362    * @param password connection password.
363    *
364    */

365   public XBooleanStatic connect( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL, String JavaDoc user, String JavaDoc password )
366   {
367     try
368     {
369       Properties JavaDoc prop = new Properties JavaDoc();
370       prop.put("user", user);
371       prop.put("password", password);
372
373       init(driver, dbURL, prop);
374
375       return new XBooleanStatic(true);
376     }
377     catch(SQLException JavaDoc e)
378     {
379       setError(e,exprContext);
380       return new XBooleanStatic(false);
381     }
382     catch (Exception JavaDoc e)
383     {
384       setError(e,exprContext);
385       return new XBooleanStatic(false);
386     }
387   }
388
389
390   /**
391    * Create an XConnection object with a connection protocol
392    * @param exprContext
393    * @param driver JDBC driver of the form foo.bar.Driver.
394    * @param dbURL database URL of the form jdbc:subprotocol:subname.
395    * @param protocolElem list of string tag/value connection arguments,
396    * normally including at least "user" and "password".
397    *
398    */

399   public XBooleanStatic connect( ExpressionContext exprContext, String JavaDoc driver, String JavaDoc dbURL, Element JavaDoc protocolElem )
400   {
401     try
402     {
403       Properties JavaDoc prop = new Properties JavaDoc();
404
405       NamedNodeMap JavaDoc atts = protocolElem.getAttributes();
406
407       for (int i = 0; i < atts.getLength(); i++)
408       {
409         prop.put(atts.item(i).getNodeName(), atts.item(i).getNodeValue());
410       }
411
412       init(driver, dbURL, prop);
413
414       return new XBooleanStatic(true);
415     }
416     catch(SQLException JavaDoc e)
417     {
418       setError(e,exprContext);
419       return new XBooleanStatic(false);
420     }
421     catch (Exception JavaDoc e)
422     {
423       setError(e, exprContext);
424       return new XBooleanStatic(false);
425     }
426   }
427
428
429   /**
430    * Allow the database connection information to be sepcified in
431    * the XML tree. The connection information could also be
432    * externally originated and passed in as an XSL Parameter.
433    * The required XML Format is as follows.
434    * A document fragment is needed to specify the connection information
435    * the top tag name is not specific for this code, we are only interested
436    * in the tags inside.
437    * <DBINFO-TAG>
438    * Specify the driver name for this connection pool
439    * <dbdriver>drivername</dbdriver>
440    * Specify the URL for the driver in this connection pool
441    * <dburl>url</dburl>
442    * Specify the password for this connection pool
443    * <password>password</password>
444    * Specify the username for this connection pool
445    * <user>username</user>
446    * You can add extra protocol items including the User Name & Password
447    * with the protocol tag. For each extra protocol item, add a new element
448    * where the name of the item is specified as the name attribute and
449    * and its value as the elements value.
450    * <protocol name="name of value">value</protocol>
451    * </DBINFO-TAG>
452    * @param e
453    *
454    * @throws SQLException
455    */

456   private void initFromElement( Element JavaDoc e )throws SQLException JavaDoc
457   {
458
459     Properties JavaDoc prop = new Properties JavaDoc();
460     String JavaDoc driver = "";
461     String JavaDoc dbURL = "";
462     Node JavaDoc n = e.getFirstChild();
463
464     if (null == n) return; // really need to throw an error
465

466     do
467     {
468       String JavaDoc nName = n.getNodeName();
469
470       if (nName.equalsIgnoreCase("dbdriver"))
471       {
472         driver = "";
473         Node JavaDoc n1 = n.getFirstChild();
474         if (null != n1)
475         {
476           driver = n1.getNodeValue();
477         }
478       }
479
480       if (nName.equalsIgnoreCase("dburl"))
481       {
482         dbURL = "";
483         Node JavaDoc n1 = n.getFirstChild();
484         if (null != n1)
485         {
486           dbURL = n1.getNodeValue();
487         }
488       }
489
490       if (nName.equalsIgnoreCase("password"))
491       {
492         String JavaDoc s = "";
493         Node JavaDoc n1 = n.getFirstChild();
494         if (null != n1)
495         {
496           s = n1.getNodeValue();
497         }
498         prop.put("password", s);
499       }
500
501       if (nName.equalsIgnoreCase("user"))
502       {
503         String JavaDoc s = "";
504         Node JavaDoc n1 = n.getFirstChild();
505         if (null != n1)
506         {
507           s = n1.getNodeValue();
508         }
509         prop.put("user", s);
510       }
511
512       if (nName.equalsIgnoreCase("protocol"))
513       {
514         String JavaDoc Name = "";
515
516         NamedNodeMap JavaDoc attrs = n.getAttributes();
517         Node JavaDoc n1 = attrs.getNamedItem("name");
518         if (null != n1)
519         {
520           String JavaDoc s = "";
521           Name = n1.getNodeValue();
522
523           Node JavaDoc n2 = n.getFirstChild();
524           if (null != n2) s = n2.getNodeValue();
525
526           prop.put(Name, s);
527         }
528       }
529
530     } while ( (n = n.getNextSibling()) != null);
531
532     init(driver, dbURL, prop);
533   }
534
535
536
537   /**
538    * Initilize is being called because we did not have an
539    * existing Connection Pool, so let's see if we created one
540    * already or lets create one ourselves.
541    * @param driver
542    * @param dbURL
543    * @param prop
544    *
545    * @throws SQLException
546    */

547   private void init( String JavaDoc driver, String JavaDoc dbURL, Properties JavaDoc prop )throws SQLException JavaDoc
548   {
549     Connection JavaDoc con = null;
550
551     if (DEBUG)
552       System.out.println("XConnection, Connection Init");
553
554     String JavaDoc user = prop.getProperty("user");
555     if (user == null) user = "";
556
557     String JavaDoc passwd = prop.getProperty("password");
558     if (passwd == null) passwd = "";
559
560
561     String JavaDoc poolName = driver + dbURL + user + passwd;
562     ConnectionPool cpool = m_PoolMgr.getPool(poolName);
563
564     if (cpool == null)
565     {
566
567       if (DEBUG)
568       {
569         System.out.println("XConnection, Creating Connection");
570         System.out.println(" Driver :" + driver);
571         System.out.println(" URL :" + dbURL);
572         System.out.println(" user :" + user);
573         System.out.println(" passwd :" + passwd);
574       }
575
576
577       DefaultConnectionPool defpool = new DefaultConnectionPool();
578
579       if ((DEBUG) && (defpool == null))
580         System.out.println("Failed to Create a Default Connection Pool");
581
582       defpool.setDriver(driver);
583       defpool.setURL(dbURL);
584       defpool.setProtocol(prop);
585
586       // Only enable pooling in the default pool if we are explicatly
587
// told too.
588
if (m_DefaultPoolingEnabled) defpool.setPoolEnabled(true);
589
590       m_PoolMgr.registerPool(poolName, defpool);
591       m_ConnectionPool = defpool;
592     }
593     else
594     {
595       m_ConnectionPool = cpool;
596     }
597
598     m_IsDefaultPool = true;
599
600     //
601
// Let's test to see if we really can connect
602
// Just remember to give it back after the test.
603
//
604
try
605     {
606       con = m_ConnectionPool.getConnection();
607     }
608     catch(SQLException JavaDoc e)
609     {
610       if (con != null)
611       {
612         m_ConnectionPool.releaseConnectionOnError(con);
613         con = null;
614       }
615       throw e;
616     }
617     finally
618     {
619       if ( con != null ) m_ConnectionPool.releaseConnection(con);
620     }
621   }
622
623   /**
624    * Allow the SQL Document to retrive a connection to be used
625    * to build the SQL Statement.
626    */

627   public ConnectionPool getConnectionPool()
628   {
629     return m_ConnectionPool;
630   }
631
632
633   /**
634    * Execute a query statement by instantiating an
635    * @param exprContext
636    * @param queryString the SQL query.
637    * @return XStatement implements NodeIterator.
638    * @throws SQLException
639    * @link org.apache.xalan.lib.sql.XStatement XStatement}
640    * object. The XStatement executes the query, and uses the result set
641    * to create a
642    * @link org.apache.xalan.lib.sql.RowSet RowSet},
643    * a row-set element.
644    */

645   public DTM query( ExpressionContext exprContext, String JavaDoc queryString )
646   {
647     SQLDocument doc = null;
648
649     try
650     {
651       if (DEBUG) System.out.println("pquery()");
652
653       // Build an Error Document, NOT Connected.
654
if ( null == m_ConnectionPool ) return null;
655
656       SQLQueryParser query =
657           m_QueryParser.parse
658             (this, queryString, SQLQueryParser.NO_INLINE_PARSER);
659
660       doc = SQLDocument.getNewDocument(exprContext);
661       doc.execute(this, query);
662
663       // also keep a local reference
664
m_OpenSQLDocuments.addElement(doc);
665     }
666     catch (Exception JavaDoc e)
667     {
668       // OK We had an error building the document, let try and grab the
669
// error information and clean up our connections.
670

671       if (DEBUG) System.out.println("exception in query()");
672
673       if (doc != null)
674       {
675         if (doc.hasErrors())
676         {
677           setError(e, doc, doc.checkWarnings());
678         }
679
680         doc.close();
681         doc = null;
682       }
683     }
684     finally
685     {
686       if (DEBUG) System.out.println("leaving query()");
687     }
688
689     // Doc will be null if there was an error
690
return doc;
691   }
692
693   /**
694    * Execute a parameterized query statement by instantiating an
695    * @param exprContext
696    * @param queryString the SQL query.
697    * @return XStatement implements NodeIterator.
698    * @throws SQLException
699    * @link org.apache.xalan.lib.sql.XStatement XStatement}
700    * object. The XStatement executes the query, and uses the result set
701    * to create a
702    * @link org.apache.xalan.lib.sql.RowSet RowSet},
703    * a row-set element.
704    */

705   public DTM pquery( ExpressionContext exprContext, String JavaDoc queryString )
706   {
707     return(pquery(exprContext, queryString, null));
708   }
709
710   /**
711    * Execute a parameterized query statement by instantiating an
712    * @param exprContext
713    * @param queryString the SQL query.
714    * @param typeInfo
715    * @return XStatement implements NodeIterator.
716    * @throws SQLException
717    * @link org.apache.xalan.lib.sql.XStatement XStatement}
718    * object. The XStatement executes the query, and uses the result set
719    * to create a
720    * @link org.apache.xalan.lib.sql.RowSet RowSet},
721    * a row-set element.
722    * This method allows for the user to pass in a comma seperated
723    * String that represents a list of parameter types. If supplied
724    * the parameter types will be used to overload the current types
725    * in the current parameter list.
726    */

727   public DTM pquery( ExpressionContext exprContext, String JavaDoc queryString, String JavaDoc typeInfo)
728   {
729     SQLDocument doc = null;
730
731     try
732     {
733       if (DEBUG) System.out.println("pquery()");
734
735       // Build an Error Document, NOT Connected.
736
if ( null == m_ConnectionPool ) return null;
737
738       SQLQueryParser query =
739           m_QueryParser.parse
740             (this, queryString, SQLQueryParser.NO_OVERRIDE);
741
742       // If we are not using the inline parser, then let add the data
743
// to the parser so it can populate the SQL Statement.
744
if ( !m_InlineVariables )
745       {
746         addTypeToData(typeInfo);
747         query.setParameters(m_ParameterList);
748       }
749
750       doc = SQLDocument.getNewDocument(exprContext);
751       doc.execute(this, query);
752
753       // also keep a local reference
754
m_OpenSQLDocuments.addElement(doc);
755     }
756     catch (Exception JavaDoc e)
757     {
758       // OK We had an error building the document, let try and grab the
759
// error information and clean up our connections.
760

761       if (DEBUG) System.out.println("exception in query()");
762
763       if (doc != null)
764       {
765         if (doc.hasErrors())
766         {
767           setError(e, doc, doc.checkWarnings());
768         }
769
770         doc.close();
771         doc = null;
772       }
773     }
774     finally
775     {
776       if (DEBUG) System.out.println("leaving query()");
777     }
778
779     // Doc will be null if there was an error
780
return doc;
781   }
782
783   private void addTypeToData(String JavaDoc typeInfo)
784   {
785       int indx;
786
787       if ( typeInfo != null && m_ParameterList != null )
788       {
789           // Parse up the parameter types that were defined
790
// with the query
791
StringTokenizer JavaDoc plist = new StringTokenizer JavaDoc(typeInfo);
792
793           // Override the existing type that is stored in the
794
// parameter list. If there are more types than parameters
795
// ignore for now, a more meaningfull error should occur
796
// when the actual query is executed.
797
indx = 0;
798           while (plist.hasMoreTokens())
799           {
800             String JavaDoc value = plist.nextToken();
801             QueryParameter qp = (QueryParameter) m_ParameterList.elementAt(indx);
802             if ( null != qp )
803             {
804               qp.setTypeName(value);
805             }
806
807             indx++;
808           }
809       }
810   }
811
812   /**
813    * Add an untyped value to the parameter list.
814    * @param value
815    *
816    */

817   public void addParameter( String JavaDoc value )
818   {
819     addParameterWithType(value, null);
820   }
821
822   /**
823    * Add a typed parameter to the parameter list.
824    * @param value
825    * @param Type
826    *
827    */

828   public void addParameterWithType( String JavaDoc value, String JavaDoc Type )
829   {
830     m_ParameterList.addElement( new QueryParameter(value, Type) );
831   }
832
833
834   /**
835    * Add a single parameter to the parameter list
836    * formatted as an Element
837    * @param e
838    *
839    */

840   public void addParameterFromElement( Element JavaDoc e )
841   {
842     NamedNodeMap JavaDoc attrs = e.getAttributes();
843     Node JavaDoc Type = attrs.getNamedItem("type");
844     Node JavaDoc n1 = e.getFirstChild();
845     if (null != n1)
846     {
847       String JavaDoc value = n1.getNodeValue();
848       if (value == null) value = "";
849       m_ParameterList.addElement( new QueryParameter(value, Type.getNodeValue()) );
850     }
851   }
852
853
854   /**
855    * Add a section of parameters to the Parameter List
856    * Do each element from the list
857    * @param nl
858    *
859    */

860   public void addParameterFromElement( NodeList JavaDoc nl )
861   {
862     //
863
// Each child of the NodeList represents a node
864
// match from the select= statment. Process each
865
// of them as a seperate list.
866
// The XML Format is as follows
867
//
868
// <START-TAG>
869
// <TAG1 type="int">value</TAG1>
870
// <TAGA type="int">value</TAGA>
871
// <TAG2 type="string">value</TAG2>
872
// </START-TAG>
873
//
874
// The XSL to process this is formatted as follows
875
// <xsl:param name="plist" select="//START-TAG" />
876
// <sql:addParameter( $plist );
877
//
878
int count = nl.getLength();
879     for (int x=0; x<count; x++)
880     {
881       addParameters( (Element JavaDoc) nl.item(x));
882     }
883   }
884
885   /**
886    * @param elem
887    *
888    */

889   private void addParameters( Element JavaDoc elem )
890   {
891     //
892
// Process all of the Child Elements
893
// The format is as follows
894
//
895
//<TAG type ="typeid">value</TAG>
896
//<TAG1 type ="typeid">value</TAG1>
897
//<TAGA type ="typeid">value</TAGA>
898
//
899
// The name of the Node is not important just is value
900
// and if it contains a type attribute
901

902     Node JavaDoc n = elem.getFirstChild();
903
904     if (null == n) return;
905
906     do
907     {
908       if (n.getNodeType() == Node.ELEMENT_NODE)
909       {
910         NamedNodeMap JavaDoc attrs = n.getAttributes();
911         Node JavaDoc Type = attrs.getNamedItem("type");
912         String JavaDoc TypeStr;
913
914         if (Type == null) TypeStr = "string";
915         else TypeStr = Type.getNodeValue();
916
917         Node JavaDoc n1 = n.getFirstChild();
918         if (null != n1)
919         {
920           String JavaDoc value = n1.getNodeValue();
921           if (value == null) value = "";
922
923
924           m_ParameterList.addElement(
925             new QueryParameter(value, TypeStr) );
926         }
927       }
928     } while ( (n = n.getNextSibling()) != null);
929   }
930
931   /**
932    *
933    */

934   public void clearParameters( )
935   {
936     m_ParameterList.removeAllElements();
937   }
938
939   /**
940    * There is a problem with some JDBC drivers when a Connection
941    * is open and the JVM shutsdown. If there is a problem, there
942    * is no way to control the currently open connections in the
943    * pool. So for the default connection pool, the actuall pooling
944    * mechinsm is disabled by default. The Stylesheet designer can
945    * re-enabled pooling to take advantage of connection pools.
946    * The connection pool can even be disabled which will close all
947    * outstanding connections.
948    *
949    * @deprecated Use setFeature("default-pool-enabled", "true");
950    */

951   public void enableDefaultConnectionPool( )
952   {
953
954     if (DEBUG)
955       System.out.println("Enabling Default Connection Pool");
956
957     m_DefaultPoolingEnabled = true;
958
959     if (m_ConnectionPool == null) return;
960     if (m_IsDefaultPool) return;
961
962     m_ConnectionPool.setPoolEnabled(true);
963
964   }
965
966   /**
967    * See enableDefaultConnectionPool
968    *
969    * @deprecated Use setFeature("default-pool-enabled", "false");
970    */

971   public void disableDefaultConnectionPool( )
972   {
973     if (DEBUG)
974       System.out.println("Disabling Default Connection Pool");
975
976     m_DefaultPoolingEnabled = false;
977
978     if (m_ConnectionPool == null) return;
979     if (!m_IsDefaultPool) return;
980
981     m_ConnectionPool.setPoolEnabled(false);
982   }
983
984
985   /**
986    * Control how the SQL Document uses memory. In Streaming Mode,
987    * memory consumption is greatly reduces so you can have queries
988    * of unlimited size but it will not let you traverse the data
989    * more than once.
990    *
991    * @deprecated Use setFeature("streaming", "true");
992    */

993   public void enableStreamingMode( )
994   {
995
996     if (DEBUG)
997       System.out.println("Enabling Streaming Mode");
998
999     m_IsStreamingEnabled = true;
1000  }
1001
1002  /**
1003   * Control how the SQL Document uses memory. In Streaming Mode,
1004   * memory consumption is greatly reduces so you can have queries
1005   * of unlimited size but it will not let you traverse the data
1006   * more than once.
1007   *
1008   * @deprecated Use setFeature("streaming", "false");
1009   */

1010  public void disableStreamingMode( )
1011  {
1012
1013    if (DEBUG)
1014      System.out.println("Disable Streaming Mode");
1015
1016    m_IsStreamingEnabled = false;
1017  }
1018
1019  /**
1020   * Provide access to the last error that occued. This error
1021   * may be over written when the next operation occurs.
1022   *
1023   */

1024  public DTM getError( )
1025  {
1026    if ( m_FullErrors )
1027    {
1028      for ( int idx = 0 ; idx < m_OpenSQLDocuments.size() ; idx++ )
1029      {
1030        SQLDocument doc = (SQLDocument)m_OpenSQLDocuments.elementAt(idx);
1031        SQLWarning JavaDoc warn = doc.checkWarnings();
1032        if ( warn != null ) setError(null, doc, warn);
1033      }
1034    }
1035
1036    return(buildErrorDocument());
1037  }
1038
1039  /**
1040   * Close the connection to the data source.
1041   *
1042   * @throws SQLException
1043   */

1044  public void close( )throws SQLException JavaDoc
1045  {
1046    if (DEBUG)
1047      System.out.println("Entering XConnection.close()");
1048
1049    //
1050
// This function is included just for Legacy support
1051
// If it is really called then we must me using a single
1052
// document interface, so close all open documents.
1053

1054    while(m_OpenSQLDocuments.size() != 0)
1055    {
1056      SQLDocument d = (SQLDocument) m_OpenSQLDocuments.elementAt(0);
1057      try
1058      {
1059        d.close();
1060      }
1061      catch (Exception JavaDoc se ) {}
1062
1063      m_OpenSQLDocuments.removeElementAt(0);
1064    }
1065
1066    if ( null != m_Connection )
1067    {
1068      m_ConnectionPool.releaseConnection(m_Connection);
1069      m_Connection = null;
1070    }
1071
1072    if (DEBUG)
1073      System.out.println("Exiting XConnection.close");
1074  }
1075
1076  /**
1077   * Close the connection to the data source. Only close the connections
1078   * for a single document.
1079   * @param sqldoc
1080   *
1081   * @throws SQLException
1082   */

1083  public void close( SQLDocument sqldoc )throws SQLException JavaDoc
1084  {
1085    if (DEBUG)
1086      System.out.println("Entering XConnection.close(" + sqldoc + ")");
1087
1088    int size = m_OpenSQLDocuments.size();
1089
1090    for(int x=0; x<size; x++)
1091    {
1092      SQLDocument d = (SQLDocument) m_OpenSQLDocuments.elementAt(x);
1093      if (d == sqldoc)
1094      {
1095        d.close();
1096        m_OpenSQLDocuments.removeElementAt(x);
1097      }
1098    }
1099  }
1100
1101
1102  /**
1103   * @param exprContext
1104   * @param excp
1105   *
1106   */

1107  private SQLErrorDocument buildErrorDocument()
1108  {
1109    SQLErrorDocument eDoc = null;
1110
1111    if ( m_LastSQLDocumentWithError != null)
1112    {
1113      // @todo
1114
// Do we need to do something with this ??
1115
// m_Error != null || (m_FullErrors && m_Warning != null) )
1116

1117      ExpressionContext ctx = m_LastSQLDocumentWithError.getExpressionContext();
1118      SQLWarning JavaDoc warn = m_LastSQLDocumentWithError.checkWarnings();
1119
1120
1121      try
1122      {
1123        DTMManager mgr =
1124          ((XPathContext.XPathExpressionContext)ctx).getDTMManager();
1125        DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr;
1126        int dtmIdent = mgrDefault.getFirstFreeDTMID();
1127
1128        eDoc = new SQLErrorDocument(
1129            mgr, dtmIdent<<DTMManager.IDENT_DTM_NODE_BITS,
1130            m_Error, warn, m_FullErrors);
1131
1132        // Register our document
1133
mgrDefault.addDTM(eDoc, dtmIdent);
1134
1135        // Clear the error and warning.
1136
m_Error = null;
1137        m_LastSQLDocumentWithError = null;
1138      }
1139      catch(Exception JavaDoc e)
1140      {
1141        eDoc = null;
1142      }
1143    }
1144
1145    return(eDoc);
1146  }
1147
1148
1149  /**
1150   * This is an internal version of Set Error that is called withen
1151   * XConnection where there is no SQLDocument created yet. As in the
1152   * Connect statement or creation of the ConnectionPool.
1153   */

1154  public void setError(Exception JavaDoc excp,ExpressionContext expr)
1155  {
1156    try
1157    {
1158      ErrorListener JavaDoc listen = expr.getErrorListener();
1159      if ( listen != null && excp != null )
1160      {
1161        listen.warning(
1162          new TransformerException JavaDoc(excp.toString(),
1163          expr.getXPathContext().getSAXLocator(), excp));
1164      }
1165    }
1166    catch(Exception JavaDoc e) {}
1167  }
1168
1169  /**
1170   * Set an error and/or warning on this connection.
1171   * @param feature The name of the feature being set, currently supports (streaming, inline-variables, multiple-results, cache-statements, default-pool-enabled).
1172   * @param setting The new setting for the specified feature, currently "true" is true and anything else is false.
1173   *
1174   */

1175  public void setError(Exception JavaDoc excp, SQLDocument doc, SQLWarning JavaDoc warn)
1176  {
1177
1178    ExpressionContext cont = doc.getExpressionContext();
1179    m_LastSQLDocumentWithError = doc;
1180
1181    try
1182    {
1183      ErrorListener JavaDoc listen = cont.getErrorListener();
1184      if ( listen != null && excp != null )
1185      listen.warning(
1186        new TransformerException JavaDoc(excp.toString(),
1187        cont.getXPathContext().getSAXLocator(), excp));
1188
1189      if ( listen != null && warn != null )
1190      {
1191        listen.warning(new TransformerException JavaDoc(
1192          warn.toString(), cont.getXPathContext().getSAXLocator(), warn));
1193      }
1194
1195      // Assume there will be just one error, but perhaps multiple warnings.
1196
if ( excp != null ) m_Error = excp;
1197
1198      if ( warn != null )
1199      {
1200        // Because the log may not have processed the previous warning yet
1201
// we need to make a new one.
1202
SQLWarning JavaDoc tw =
1203          new SQLWarning JavaDoc(warn.getMessage(), warn.getSQLState(),
1204            warn.getErrorCode());
1205        SQLWarning JavaDoc nw = warn.getNextWarning();
1206        while ( nw != null )
1207        {
1208          tw.setNextWarning(new SQLWarning JavaDoc(nw.getMessage(),
1209            nw.getSQLState(), nw.getErrorCode()));
1210
1211          nw = nw.getNextWarning();
1212        }
1213
1214        tw.setNextWarning(
1215          new SQLWarning JavaDoc(warn.getMessage(), warn.getSQLState(),
1216            warn.getErrorCode()));
1217
1218// m_Warning = tw;
1219

1220      }
1221    }
1222    catch(Exception JavaDoc e)
1223    {
1224      //m_Error = null;
1225
}
1226  }
1227
1228  /**
1229   * Set feature options for this XConnection.
1230   * @param feature The name of the feature being set, currently supports (streaming, inline-variables, multiple-results, cache-statements, default-pool-enabled).
1231   * @param setting The new setting for the specified feature, currently "true" is true and anything else is false.
1232   *
1233   */

1234  public void setFeature(String JavaDoc feature, String JavaDoc setting)
1235  {
1236    boolean value = false;
1237
1238    if ( "true".equalsIgnoreCase(setting) ) value = true;
1239
1240    if ( "streaming".equalsIgnoreCase(feature) )
1241    {
1242      m_IsStreamingEnabled = value;
1243    }
1244    else if ( "inline-variables".equalsIgnoreCase(feature) )
1245    {
1246      m_InlineVariables = value;
1247    }
1248    else if ( "multiple-results".equalsIgnoreCase(feature) )
1249    {
1250      m_IsMultipleResultsEnabled = value;
1251    }
1252    else if ( "cache-statements".equalsIgnoreCase(feature) )
1253    {
1254      m_IsStatementCachingEnabled = value;
1255    }
1256    else if ( "default-pool-enabled".equalsIgnoreCase(feature) )
1257    {
1258      m_DefaultPoolingEnabled = value;
1259
1260      if (m_ConnectionPool == null) return;
1261      if (m_IsDefaultPool) return;
1262
1263      m_ConnectionPool.setPoolEnabled(value);
1264    }
1265    else if ( "full-errors".equalsIgnoreCase(feature) )
1266    {
1267      m_FullErrors = value;
1268    }
1269  }
1270
1271  /**
1272   * Get feature options for this XConnection.
1273   * @param feature The name of the feature to get the setting for.
1274   * @return The setting of the specified feature. Will be "true" or "false" (null if the feature is not known)
1275   */

1276  public String JavaDoc getFeature(String JavaDoc feature)
1277  {
1278    String JavaDoc value = null;
1279
1280    if ( "streaming".equalsIgnoreCase(feature) )
1281      value = m_IsStreamingEnabled ? "true" : "false";
1282    else if ( "inline-variables".equalsIgnoreCase(feature) )
1283      value = m_InlineVariables ? "true" : "false";
1284    else if ( "multiple-results".equalsIgnoreCase(feature) )
1285      value = m_IsMultipleResultsEnabled ? "true" : "false";
1286    else if ( "cache-statements".equalsIgnoreCase(feature) )
1287      value = m_IsStatementCachingEnabled ? "true" : "false";
1288    else if ( "default-pool-enabled".equalsIgnoreCase(feature) )
1289      value = m_DefaultPoolingEnabled ? "true" : "false";
1290    else if ( "full-errors".equalsIgnoreCase(feature) )
1291      value = m_FullErrors ? "true" : "false";
1292
1293    return(value);
1294  }
1295
1296
1297
1298  /**
1299   *
1300   */

1301  protected void finalize( )
1302  {
1303    if (DEBUG) System.out.println("In XConnection, finalize");
1304    try
1305    {
1306      close();
1307    }
1308    catch(Exception JavaDoc e)
1309    {
1310      // Empty We are final Anyway
1311
}
1312  }
1313
1314}
1315
Popular Tags