All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.xalan.lib.sql.XConnection Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: XConnection.java 468638 2006-10-28 06:52:06Z minchau $
 */
package org.apache.xalan.lib.sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.TransformerException;

import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMManagerDefault;
import org.apache.xml.dtm.ref.DTMNodeIterator;
import org.apache.xml.dtm.ref.DTMNodeProxy;
import org.apache.xpath.XPathContext;
import org.apache.xpath.objects.XBooleanStatic;
import org.apache.xpath.objects.XNodeSet;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * An XSLT extension that allows a stylesheet to
 * access JDBC data.
 *
 * It is accessed by specifying a namespace URI as follows:
 * 
 *    xmlns:sql="http://xml.apache.org/xalan/sql"
 * 
* * From the stylesheet perspective, * XConnection provides 3 extension functions: new(), * query(), and close(). * Use new() to call one of XConnection constructors, which * establishes a JDBC driver connection to a data source and * returns an XConnection object. * Then use the XConnection object query() method to return a * result set in the form of a row-set element. * When you have finished working with the row-set, call the * XConnection object close() method to terminate the connection. */ public class XConnection { /** * Flag for DEBUG mode */ private static final boolean DEBUG = false; /** * The Current Connection Pool in Use. An XConnection can only * represent one query at a time, prior to doing some type of query. */ private ConnectionPool m_ConnectionPool = null; /** * The DBMS Connection used to produce this SQL Document. * Will be used to clear free up the database resources on * close. */ private Connection m_Connection = null; /** * If a default Connection Pool is used. i.e. A connection Pool * that is created internally, then do we actually allow pools * to be created. Due to the archititure of the Xalan Extensions, * there is no notification of when the Extension is being unloaded and * as such, there is a good chance that JDBC COnnections are not closed. * A finalized is provided to try and catch this situation but since * support of finalizers is inconsistant across JVM's this may cause * a problem. The robustness of the JDBC Driver is also at issue here. * if a controlled shutdown is provided by the driver then default * conntectiom pools are OK. */ private boolean m_DefaultPoolingEnabled = false; /** * As we do queries, we will produce SQL Documents. Any ony may produce * one or more SQL Documents so that the current connection information * may be easilly reused. This collection will hold a collection of all * the documents created. As Documents are closed, they will be removed * from the collection and told to free all the used resources. */ private Vector m_OpenSQLDocuments = new Vector(); /** * Let's keep a copy of the ConnectionPoolMgr in * alive here so we are keeping the static pool alive * We will also use this Pool Manager to register our default pools. */ private ConnectionPoolManager m_PoolMgr = new ConnectionPoolManager(); /** * For PreparedStatements, we need a place to * to store the parameters in a vector. */ private Vector m_ParameterList = new Vector(); /** * Allow the SQL Extensions to return null on error. The Error information will * be stored in a seperate Error Document that can easily be retrived using the * getError() method. * %REVIEW% This functionality will probably be buried inside the SQLDocument. */ private Exception m_Error = null; /** * When the Stylesheet wants to review the errors from a paticular * document, it asks the XConnection. We need to track what document * in the list of managed documents caused the last error. As SetError * is called, it will record the document that had the error. */ private SQLDocument m_LastSQLDocumentWithError = null; /** * If true then full information should be returned about errors and warnings * in getError(). This includes chained errors and warnings. * If false (the default) then getError() returns just the first SQLException. */ private boolean m_FullErrors = false; /** * One a per XConnection basis there is a master QueryParser that is responsible * for generating Query Parsers. This will allow us to cache previous instances * so the inline parser execution time is minimized. */ private SQLQueryParser m_QueryParser = new SQLQueryParser(); /** */ private boolean m_IsDefaultPool = false; /** * This flag will be used to indicate to the SQLDocument to use * Streaming mode. Streeaming Mode will reduce the memory footprint * to a fixed amount but will not let you traverse the tree more than * once since the Row data will be reused for every Row in the Query. */ private boolean m_IsStreamingEnabled = true; /** * */ private boolean m_InlineVariables = false; /** * This flag will be used to indicate if multiple result sets are * supported from the database. If they are, then the metadata element is * moved to insude the row-set element and multiple row-set elements may * be included under the sql root element. */ private boolean m_IsMultipleResultsEnabled = false; /** * This flag will be used to indicate if database preparedstatements * should be cached. This also controls if the Java statement object * should be cached. */ private boolean m_IsStatementCachingEnabled = false; /** */ public XConnection( ) { } /** * Constructs a new XConnection and attempts to connect to a datasource as * defined in the * connect(ExpressionContext exprContext, String connPoolName) * method. * org.apache.xalan.lib.sql.ConnectionPool or a JNDI datasource. * * @param exprContext Context automatically passed from the XSLT sheet. * @param name The name of the ConnectionPool or the JNDI DataSource path. * */ public XConnection( ExpressionContext exprContext, String connPoolName ) { connect(exprContext, connPoolName); } /** * @param exprContext * @param driver * @param dbURL */ public XConnection( ExpressionContext exprContext, String driver, String dbURL ) { connect(exprContext, driver, dbURL); } /** * @param exprContext * @param list */ public XConnection( ExpressionContext exprContext, NodeList list ) { connect(exprContext, list); } /** * @param exprContext * @param driver * @param dbURL * @param user * @param password */ public XConnection( ExpressionContext exprContext, String driver, String dbURL, String user, String password ) { connect(exprContext, driver, dbURL, user, password); } /** * @param exprContext * @param driver * @param dbURL * @param protocolElem */ public XConnection( ExpressionContext exprContext, String driver, String dbURL, Element protocolElem ) { connect(exprContext, driver, dbURL, protocolElem); } /** * Returns an XConnection from either a user created * org.apache.xalan.lib.sql.ConnectionPool or a JNDI datasource. * * This method first tries to resolve the passed name against * ConnectionPools registered with * ConnectionPoolManager. * If that fails, it attempts to find the name as a JNDI DataSource path. * * @param exprContext Context automatically passed from the XSLT sheet. * @param name The name of the ConnectionPool or the JNDI DataSource path. * */ public XBooleanStatic connect( ExpressionContext exprContext, String name ) { try { m_ConnectionPool = m_PoolMgr.getPool(name); if (m_ConnectionPool == null) { //Try to create a jndi source with the passed name ConnectionPool pool = new JNDIConnectionPool(name); if (pool.testConnection()) { //JNDIConnectionPool seems good, so register it with the pool manager. //Once registered, it will show up like other named ConnectionPool's, //so the m_PoolMgr.getPool(name) method (above) will find it. m_PoolMgr.registerPool(name, pool); m_ConnectionPool = pool; m_IsDefaultPool = false; return new XBooleanStatic(true); } else { throw new IllegalArgumentException( "Invalid ConnectionPool name or JNDI Datasource path: " + name); } } else { m_IsDefaultPool = false; return new XBooleanStatic(true); } } catch (Exception e) { setError(e, exprContext); return new XBooleanStatic(false); } } /** * Create an XConnection object with just a driver and database URL. * @param exprContext * @param driver JDBC driver of the form foo.bar.Driver. * @param dbURL database URL of the form jdbc:subprotocol:subname. * */ public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL ) { try { init(driver, dbURL, new Properties()); return new XBooleanStatic(true); } catch(SQLException e) { setError(e,exprContext); return new XBooleanStatic(false); } catch (Exception e) { setError(e,exprContext); return new XBooleanStatic(false); } } /** * @param exprContext * @param protocolElem * */ public XBooleanStatic connect( ExpressionContext exprContext, Element protocolElem ) { try { initFromElement(protocolElem); return new XBooleanStatic(true); } catch(SQLException e) { setError(e,exprContext); return new XBooleanStatic(false); } catch (Exception e) { setError(e,exprContext); return new XBooleanStatic(false); } } /** * @param exprContext * @param list * */ public XBooleanStatic connect( ExpressionContext exprContext, NodeList list ) { try { initFromElement( (Element) list.item(0) ); return new XBooleanStatic(true); } catch(SQLException e) { setError(e, exprContext); return new XBooleanStatic(false); } catch (Exception e) { setError(e,exprContext); return new XBooleanStatic(false); } } /** * Create an XConnection object with user ID and password. * @param exprContext * @param driver JDBC driver of the form foo.bar.Driver. * @param dbURL database URL of the form jdbc:subprotocol:subname. * @param user user ID. * @param password connection password. * */ public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL, String user, String password ) { try { Properties prop = new Properties(); prop.put("user", user); prop.put("password", password); init(driver, dbURL, prop); return new XBooleanStatic(true); } catch(SQLException e) { setError(e,exprContext); return new XBooleanStatic(false); } catch (Exception e) { setError(e,exprContext); return new XBooleanStatic(false); } } /** * Create an XConnection object with a connection protocol * @param exprContext * @param driver JDBC driver of the form foo.bar.Driver. * @param dbURL database URL of the form jdbc:subprotocol:subname. * @param protocolElem list of string tag/value connection arguments, * normally including at least "user" and "password". * */ public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL, Element protocolElem ) { try { Properties prop = new Properties(); NamedNodeMap atts = protocolElem.getAttributes(); for (int i = 0; i < atts.getLength(); i++) { prop.put(atts.item(i).getNodeName(), atts.item(i).getNodeValue()); } init(driver, dbURL, prop); return new XBooleanStatic(true); } catch(SQLException e) { setError(e,exprContext); return new XBooleanStatic(false); } catch (Exception e) { setError(e, exprContext); return new XBooleanStatic(false); } } /** * Allow the database connection information to be sepcified in * the XML tree. The connection information could also be * externally originated and passed in as an XSL Parameter. * The required XML Format is as follows. * A document fragment is needed to specify the connection information * the top tag name is not specific for this code, we are only interested * in the tags inside. * * Specify the driver name for this connection pool * drivername * Specify the URL for the driver in this connection pool * url * Specify the password for this connection pool * password * Specify the username for this connection pool * username * You can add extra protocol items including the User Name & Password * with the protocol tag. For each extra protocol item, add a new element * where the name of the item is specified as the name attribute and * and its value as the elements value. * value * * @param e * * @throws SQLException */ private void initFromElement( Element e )throws SQLException { Properties prop = new Properties(); String driver = ""; String dbURL = ""; Node n = e.getFirstChild(); if (null == n) return; // really need to throw an error do { String nName = n.getNodeName(); if (nName.equalsIgnoreCase("dbdriver")) { driver = ""; Node n1 = n.getFirstChild(); if (null != n1) { driver = n1.getNodeValue(); } } if (nName.equalsIgnoreCase("dburl")) { dbURL = ""; Node n1 = n.getFirstChild(); if (null != n1) { dbURL = n1.getNodeValue(); } } if (nName.equalsIgnoreCase("password")) { String s = ""; Node n1 = n.getFirstChild(); if (null != n1) { s = n1.getNodeValue(); } prop.put("password", s); } if (nName.equalsIgnoreCase("user")) { String s = ""; Node n1 = n.getFirstChild(); if (null != n1) { s = n1.getNodeValue(); } prop.put("user", s); } if (nName.equalsIgnoreCase("protocol")) { String Name = ""; NamedNodeMap attrs = n.getAttributes(); Node n1 = attrs.getNamedItem("name"); if (null != n1) { String s = ""; Name = n1.getNodeValue(); Node n2 = n.getFirstChild(); if (null != n2) s = n2.getNodeValue(); prop.put(Name, s); } } } while ( (n = n.getNextSibling()) != null); init(driver, dbURL, prop); } /** * Initilize is being called because we did not have an * existing Connection Pool, so let's see if we created one * already or lets create one ourselves. * @param driver * @param dbURL * @param prop * * @throws SQLException */ private void init( String driver, String dbURL, Properties prop )throws SQLException { Connection con = null; if (DEBUG) System.out.println("XConnection, Connection Init"); String user = prop.getProperty("user"); if (user == null) user = ""; String passwd = prop.getProperty("password"); if (passwd == null) passwd = ""; String poolName = driver + dbURL + user + passwd; ConnectionPool cpool = m_PoolMgr.getPool(poolName); if (cpool == null) { if (DEBUG) { System.out.println("XConnection, Creating Connection"); System.out.println(" Driver :" + driver); System.out.println(" URL :" + dbURL); System.out.println(" user :" + user); System.out.println(" passwd :" + passwd); } DefaultConnectionPool defpool = new DefaultConnectionPool(); if ((DEBUG) && (defpool == null)) System.out.println("Failed to Create a Default Connection Pool"); defpool.setDriver(driver); defpool.setURL(dbURL); defpool.setProtocol(prop); // Only enable pooling in the default pool if we are explicatly // told too. if (m_DefaultPoolingEnabled) defpool.setPoolEnabled(true); m_PoolMgr.registerPool(poolName, defpool); m_ConnectionPool = defpool; } else { m_ConnectionPool = cpool; } m_IsDefaultPool = true; // // Let's test to see if we really can connect // Just remember to give it back after the test. // try { con = m_ConnectionPool.getConnection(); } catch(SQLException e) { if (con != null) { m_ConnectionPool.releaseConnectionOnError(con); con = null; } throw e; } finally { if ( con != null ) m_ConnectionPool.releaseConnection(con); } } /** * Allow the SQL Document to retrive a connection to be used * to build the SQL Statement. */ public ConnectionPool getConnectionPool() { return m_ConnectionPool; } /** * Execute a query statement by instantiating an * @param exprContext * @param queryString the SQL query. * @return XStatement implements NodeIterator. * @throws SQLException * @link org.apache.xalan.lib.sql.XStatement XStatement} * object. The XStatement executes the query, and uses the result set * to create a * @link org.apache.xalan.lib.sql.RowSet RowSet}, * a row-set element. */ public DTM query( ExpressionContext exprContext, String queryString ) { SQLDocument doc = null; try { if (DEBUG) System.out.println("pquery()"); // Build an Error Document, NOT Connected. if ( null == m_ConnectionPool ) return null; SQLQueryParser query = m_QueryParser.parse (this, queryString, SQLQueryParser.NO_INLINE_PARSER); doc = SQLDocument.getNewDocument(exprContext); doc.execute(this, query); // also keep a local reference m_OpenSQLDocuments.addElement(doc); } catch (Exception e) { // OK We had an error building the document, let try and grab the // error information and clean up our connections. if (DEBUG) System.out.println("exception in query()"); if (doc != null) { if (doc.hasErrors()) { setError(e, doc, doc.checkWarnings()); } doc.close(m_IsDefaultPool); doc = null; } } finally { if (DEBUG) System.out.println("leaving query()"); } // Doc will be null if there was an error return doc; } /** * Execute a parameterized query statement by instantiating an * @param exprContext * @param queryString the SQL query. * @return XStatement implements NodeIterator. * @throws SQLException * @link org.apache.xalan.lib.sql.XStatement XStatement} * object. The XStatement executes the query, and uses the result set * to create a * @link org.apache.xalan.lib.sql.RowSet RowSet}, * a row-set element. */ public DTM pquery( ExpressionContext exprContext, String queryString ) { return(pquery(exprContext, queryString, null)); } /** * Execute a parameterized query statement by instantiating an * @param exprContext * @param queryString the SQL query. * @param typeInfo * @return XStatement implements NodeIterator. * @throws SQLException * @link org.apache.xalan.lib.sql.XStatement XStatement} * object. The XStatement executes the query, and uses the result set * to create a * @link org.apache.xalan.lib.sql.RowSet RowSet}, * a row-set element. * This method allows for the user to pass in a comma seperated * String that represents a list of parameter types. If supplied * the parameter types will be used to overload the current types * in the current parameter list. */ public DTM pquery( ExpressionContext exprContext, String queryString, String typeInfo) { SQLDocument doc = null; try { if (DEBUG) System.out.println("pquery()"); // Build an Error Document, NOT Connected. if ( null == m_ConnectionPool ) return null; SQLQueryParser query = m_QueryParser.parse (this, queryString, SQLQueryParser.NO_OVERRIDE); // If we are not using the inline parser, then let add the data // to the parser so it can populate the SQL Statement. if ( !m_InlineVariables ) { addTypeToData(typeInfo); query.setParameters(m_ParameterList); } doc = SQLDocument.getNewDocument(exprContext); doc.execute(this, query); // also keep a local reference m_OpenSQLDocuments.addElement(doc); } catch (Exception e) { // OK We had an error building the document, let try and grab the // error information and clean up our connections. if (DEBUG) System.out.println("exception in query()"); if (doc != null) { if (doc.hasErrors()) { setError(e, doc, doc.checkWarnings()); } // If we are using the Default Connection Pool, then // force the connection pool to flush unused connections. doc.close(m_IsDefaultPool); doc = null; } } finally { if (DEBUG) System.out.println("leaving query()"); } // Doc will be null if there was an error return doc; } /** * The purpose of this routine is to force the DB cursor to skip forward * N records. You should call this function after [p]query to help with * pagination. i.e. Perfrom your select, then skip forward past the records * you read previously. * * @param exprContext * @param o * @param value */ public void skipRec( ExpressionContext exprContext, Object o, int value ) { SQLDocument sqldoc = null; DTMNodeIterator nodei = null; sqldoc = locateSQLDocument( exprContext, o); if (sqldoc != null) sqldoc.skip(value); } private void addTypeToData(String typeInfo) { int indx; if ( typeInfo != null && m_ParameterList != null ) { // Parse up the parameter types that were defined // with the query StringTokenizer plist = new StringTokenizer(typeInfo); // Override the existing type that is stored in the // parameter list. If there are more types than parameters // ignore for now, a more meaningfull error should occur // when the actual query is executed. indx = 0; while (plist.hasMoreTokens()) { String value = plist.nextToken(); QueryParameter qp = (QueryParameter) m_ParameterList.elementAt(indx); if ( null != qp ) { qp.setTypeName(value); } indx++; } } } /** * Add an untyped value to the parameter list. * @param value * */ public void addParameter( String value ) { addParameterWithType(value, null); } /** * Add a typed parameter to the parameter list. * @param value * @param Type * */ public void addParameterWithType( String value, String Type ) { m_ParameterList.addElement( new QueryParameter(value, Type) ); } /** * Add a single parameter to the parameter list * formatted as an Element * @param e * */ public void addParameterFromElement( Element e ) { NamedNodeMap attrs = e.getAttributes(); Node Type = attrs.getNamedItem("type"); Node n1 = e.getFirstChild(); if (null != n1) { String value = n1.getNodeValue(); if (value == null) value = ""; m_ParameterList.addElement( new QueryParameter(value, Type.getNodeValue()) ); } } /** * Add a section of parameters to the Parameter List * Do each element from the list * @param nl * */ public void addParameterFromElement( NodeList nl ) { // // Each child of the NodeList represents a node // match from the select= statment. Process each // of them as a seperate list. // The XML Format is as follows // // // value // value // value // // // The XSL to process this is formatted as follows // // value //value //value // // The name of the Node is not important just is value // and if it contains a type attribute Node n = elem.getFirstChild(); if (null == n) return; do { if (n.getNodeType() == Node.ELEMENT_NODE) { NamedNodeMap attrs = n.getAttributes(); Node Type = attrs.getNamedItem("type"); String TypeStr; if (Type == null) TypeStr = "string"; else TypeStr = Type.getNodeValue(); Node n1 = n.getFirstChild(); if (null != n1) { String value = n1.getNodeValue(); if (value == null) value = ""; m_ParameterList.addElement( new QueryParameter(value, TypeStr) ); } } } while ( (n = n.getNextSibling()) != null); } /** * */ public void clearParameters( ) { m_ParameterList.removeAllElements(); } /** * There is a problem with some JDBC drivers when a Connection * is open and the JVM shutsdown. If there is a problem, there * is no way to control the currently open connections in the * pool. So for the default connection pool, the actuall pooling * mechinsm is disabled by default. The Stylesheet designer can * re-enabled pooling to take advantage of connection pools. * The connection pool can even be disabled which will close all * outstanding connections. * * @deprecated Use setFeature("default-pool-enabled", "true"); */ public void enableDefaultConnectionPool( ) { if (DEBUG) System.out.println("Enabling Default Connection Pool"); m_DefaultPoolingEnabled = true; if (m_ConnectionPool == null) return; if (m_IsDefaultPool) return; m_ConnectionPool.setPoolEnabled(true); } /** * See enableDefaultConnectionPool * * @deprecated Use setFeature("default-pool-enabled", "false"); */ public void disableDefaultConnectionPool( ) { if (DEBUG) System.out.println("Disabling Default Connection Pool"); m_DefaultPoolingEnabled = false; if (m_ConnectionPool == null) return; if (!m_IsDefaultPool) return; m_ConnectionPool.setPoolEnabled(false); } /** * Control how the SQL Document uses memory. In Streaming Mode, * memory consumption is greatly reduces so you can have queries * of unlimited size but it will not let you traverse the data * more than once. * * @deprecated Use setFeature("streaming", "true"); */ public void enableStreamingMode( ) { if (DEBUG) System.out.println("Enabling Streaming Mode"); m_IsStreamingEnabled = true; } /** * Control how the SQL Document uses memory. In Streaming Mode, * memory consumption is greatly reduces so you can have queries * of unlimited size but it will not let you traverse the data * more than once. * * @deprecated Use setFeature("streaming", "false"); */ public void disableStreamingMode( ) { if (DEBUG) System.out.println("Disable Streaming Mode"); m_IsStreamingEnabled = false; } /** * Provide access to the last error that occued. This error * may be over written when the next operation occurs. * */ public DTM getError( ) { if ( m_FullErrors ) { for ( int idx = 0 ; idx < m_OpenSQLDocuments.size() ; idx++ ) { SQLDocument doc = (SQLDocument)m_OpenSQLDocuments.elementAt(idx); SQLWarning warn = doc.checkWarnings(); if ( warn != null ) setError(null, doc, warn); } } return(buildErrorDocument()); } /** * Close the connection to the data source. * * @throws SQLException */ public void close( )throws SQLException { if (DEBUG) System.out.println("Entering XConnection.close()"); // // This function is included just for Legacy support // If it is really called then we must me using a single // document interface, so close all open documents. while(m_OpenSQLDocuments.size() != 0) { SQLDocument d = (SQLDocument) m_OpenSQLDocuments.elementAt(0); try { // If we are using the Default Connection Pool, then // force the connection pool to flush unused connections. d.close(m_IsDefaultPool); } catch (Exception se ) {} m_OpenSQLDocuments.removeElementAt(0); } if ( null != m_Connection ) { m_ConnectionPool.releaseConnection(m_Connection); m_Connection = null; } if (DEBUG) System.out.println("Exiting XConnection.close"); } /** * Close the connection to the data source. Only close the connections * for a single document. * * @throws SQLException */ public void close(ExpressionContext exprContext, Object doc) throws SQLException { if (DEBUG) System.out.println("Entering XConnection.close(" + doc + ")"); SQLDocument sqlDoc = locateSQLDocument(exprContext, doc); if (sqlDoc != null) { // If we are using the Default Connection Pool, then // force the connection pool to flush unused connections. sqlDoc.close(m_IsDefaultPool); m_OpenSQLDocuments.remove(sqlDoc); } } /** * When an SQL Document is returned as a DTM object, the XSL variable is actually * assigned as a DTMIterator. This is a helper function that will allow you to get * a reference to the original SQLDocument from the iterator. * * Original code submitted by * Moraine Didier mailto://[email protected] * @param doc * @return */ private SQLDocument locateSQLDocument(ExpressionContext exprContext, Object doc) { try { if (doc instanceof DTMNodeIterator) { DTMNodeIterator dtmIter = (DTMNodeIterator)doc; try { DTMNodeProxy root = (DTMNodeProxy)dtmIter.getRoot(); return (SQLDocument) root.getDTM(); } catch (Exception e) { XNodeSet xNS = (XNodeSet)dtmIter.getDTMIterator(); DTMIterator iter = (DTMIterator)xNS.getContainedIter(); DTM dtm = iter.getDTM(xNS.nextNode()); return (SQLDocument)dtm; } } /* XNodeSet xNS = (XNodeSet)dtmIter.getDTMIterator(); OneStepIterator iter = (OneStepIterator)xNS.getContainedIter(); DTMManager aDTMManager = (DTMManager)iter.getDTMManager(); return (SQLDocument)aDTMManager.getDTM(xNS.nextNode()); */ setError(new Exception("SQL Extension:close - Can Not Identify SQLDocument"), exprContext); return null; } catch(Exception e) { setError(e, exprContext); return null; } } /** * @param exprContext * @param excp * */ private SQLErrorDocument buildErrorDocument() { SQLErrorDocument eDoc = null; if ( m_LastSQLDocumentWithError != null) { // @todo // Do we need to do something with this ?? // m_Error != null || (m_FullErrors && m_Warning != null) ) ExpressionContext ctx = m_LastSQLDocumentWithError.getExpressionContext(); SQLWarning warn = m_LastSQLDocumentWithError.checkWarnings(); try { DTMManager mgr = ((XPathContext.XPathExpressionContext)ctx).getDTMManager(); DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr; int dtmIdent = mgrDefault.getFirstFreeDTMID(); eDoc = new SQLErrorDocument( mgr, dtmIdent<




© 2015 - 2025 Weber Informatics LLC | Privacy Policy