You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sb...@locus.apache.org on 2000/08/07 04:48:14 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/lib/sql Column.java ColumnAttribute.java ColumnData.java ColumnHeader.java Row.java RowSet.java StreamableNode.java XConnection.java XStatement.java

sboag       00/08/06 19:48:14

  Added:       java/src/org/apache/xalan/lib/sql Column.java
                        ColumnAttribute.java ColumnData.java
                        ColumnHeader.java Row.java RowSet.java
                        StreamableNode.java XConnection.java
                        XStatement.java
  Log:
  Xalan SQL Library.  A work in progress, with limited ability.  Heavily under-commented.
  
  Revision  Changes    Path
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/Column.java
  
  Index: Column.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  import org.w3c.dom.NamedNodeMap;
  
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  
  /**
   * This class represents a column node from a row in a JDBC-accessed 
   * database.
   */
  public class Column extends StreamableNode
  {
    int m_columnIndex;
    Row m_parent;
    private static final boolean DEBUG = false;
    ColumnData m_text;
    
    public Column(XStatement statement, Row parent, int columnIndex, 
                  ResultSetMetaData metadata)
    {
      super(statement);
      m_columnIndex = columnIndex;
      m_parent = parent;
      m_text = null;
    }
    
    /**
     * The parent of a document is null.
     */
    public Document getOwnerDocument()
    {
      return this.getXStatement();
    }
    
    /**
     * Return "#Document".
     */
    public String getNodeName()
    {
      return XStatement.S_COLUMNNAME;
    }
        
    /**
     * Return the document element node.
     */
    public Node getFirstChild()
    {
      if(DEBUG)
        System.out.println("In Column.getFirstChild");
      
      if(null == m_text)
        m_text = new ColumnData(this.getXStatement(), this);
      
      return m_text;
    }
    
    /**
     * This always returns null.
     */
    public Node getNextSibling()
    {
      if(DEBUG)
        System.out.println("In Column.getNextSibling");
      int nextIndex = m_columnIndex+1;
      return (nextIndex < m_parent.m_childCount) 
             ? m_parent.m_columns[nextIndex] : null;
    }
    
    /**
     * The parent node of document is always null.
     */
    public Node getParentNode()
    {
      if(DEBUG)
        System.out.println("In Column.getParentNode");
      return m_parent;
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In Column.hasChildNodes");
      return true;
    }
    
    public NamedNodeMap       getAttributes()
    {
      return m_parent.m_parent.m_columnHeaders[m_columnIndex];
    }
  
  
    
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/ColumnAttribute.java
  
  Index: ColumnAttribute.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Element;
  import org.w3c.dom.Node;
  import org.w3c.dom.Attr;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  import java.sql.SQLException;
  import java.sql.ResultSet;
  
  import org.apache.xalan.res.XSLTErrorResources;
  
  /**
   * This class represents a column attribute on a ColumnHeader element.
   */
  public class ColumnAttribute extends StreamableNode implements Attr
  {
    Element m_owner;
    ResultSetMetaData m_metadata;
    String m_name;
    int m_type;
    int m_columnIndex;
    ColumnAttribute m_columnAttr;
    static final String S_ISTRUE = "true";
    static final String S_ISFALSE = "false";
    
    public static final int CATALOGUE_NAME = 0;
    public static final int DISPLAY_SIZE = 1;
    public static final int COLUMN_LABEL = 2;
    public static final int COLUMN_NAME = 3;
    public static final int COLUMN_TYPE = 4;
    public static final int COLUMN_TYPENAME = 5;
    public static final int PRECISION = 6;
    public static final int SCALE = 7;
    public static final int SCHEMA_NAME = 8;
    public static final int TABLE_NAME = 9;
    public static final int CASESENSITIVE = 10;
    public static final int DEFINATELYWRITABLE = 11;
    public static final int ISNULLABLE = 12;
    public static final int ISSIGNED = 13;
    public static final int ISWRITEABLE = 14;
    public static final int ISSEARCHABLE = 15;
    
    public static final int NUMBER_ATTRIBUTES = 16;
  
    public static final String S_CATALOGUE_NAME = "catalogue-name";
    public static final String S_DISPLAY_SIZE = "column-display-size";
    public static final String S_COLUMN_LABEL = "column-label";
    public static final String S_COLUMN_NAME = "column-name";
    public static final String S_COLUMN_TYPE = "column-type";
    public static final String S_COLUMN_TYPENAME = "column-type-name";
    public static final String S_PRECISION = "precision";
    public static final String S_SCALE = "scale";
    public static final String S_SCHEMA_NAME = "schema-name";
    public static final String S_TABLE_NAME = "table-name";
    public static final String S_CASESENSITIVE = "case-sensitive";
    public static final String S_DEFINATELYWRITABLE = "definitely-writable";
    public static final String S_ISNULLABLE = "nullable";
    public static final String S_ISSIGNED = "signed";
    public static final String S_ISWRITEABLE = "writable";
    public static final String S_ISSEARCHABLE = "searchable";
    
    static java.util.Hashtable m_namelookup = new java.util.Hashtable();
    
    static
    {
      m_namelookup.put(S_CATALOGUE_NAME, new Integer(CATALOGUE_NAME));
      m_namelookup.put(S_DISPLAY_SIZE, new Integer(DISPLAY_SIZE));
      m_namelookup.put(S_COLUMN_LABEL, new Integer(COLUMN_LABEL));
      m_namelookup.put(S_COLUMN_NAME, new Integer(COLUMN_NAME));
      m_namelookup.put(S_COLUMN_TYPE, new Integer(COLUMN_TYPE));
      m_namelookup.put(S_COLUMN_TYPENAME, new Integer(COLUMN_TYPENAME));
      m_namelookup.put(S_PRECISION, new Integer(PRECISION));
      m_namelookup.put(S_SCALE, new Integer(SCALE));
      m_namelookup.put(S_SCHEMA_NAME, new Integer(SCHEMA_NAME));
      m_namelookup.put(S_TABLE_NAME, new Integer(TABLE_NAME));
      m_namelookup.put(S_CASESENSITIVE, new Integer(CASESENSITIVE));
      m_namelookup.put(S_DEFINATELYWRITABLE, new Integer(DEFINATELYWRITABLE));
      m_namelookup.put(S_ISNULLABLE, new Integer(ISNULLABLE));
      m_namelookup.put(S_ISSIGNED, new Integer(ISSIGNED));
      m_namelookup.put(S_ISWRITEABLE, new Integer(ISWRITEABLE));
      m_namelookup.put(S_ISSEARCHABLE, new Integer(ISSEARCHABLE));
    }
  
    public ColumnAttribute(XStatement statement, Element owner,
                           int columnIndex, int type, ResultSetMetaData metadata)
    {
      super(statement);
      m_owner = owner;
      m_metadata = metadata;
      m_columnIndex = columnIndex;
      m_type = type;
    }
    
    static String getAttrNameFromPos(int pos)
    {
      switch(pos)
      {
      case  CATALOGUE_NAME:
        return S_CATALOGUE_NAME;
      case  DISPLAY_SIZE:
        return S_DISPLAY_SIZE;
      case  COLUMN_LABEL:
        return S_COLUMN_LABEL;
      case  COLUMN_NAME:
        return S_COLUMN_NAME;
      case  COLUMN_TYPE:
        return S_COLUMN_TYPE;
      case  COLUMN_TYPENAME:
        return S_COLUMN_TYPENAME;
      case  PRECISION:
        return S_PRECISION;
      case  SCALE:
        return S_SCALE;
      case  SCHEMA_NAME:
        return S_SCHEMA_NAME;
      case  TABLE_NAME:
        return S_TABLE_NAME;
      case  CASESENSITIVE:
        return S_CASESENSITIVE;
      case  DEFINATELYWRITABLE:
        return S_DEFINATELYWRITABLE;
      case  ISNULLABLE:
        return S_ISNULLABLE;
      case  ISSIGNED:
        return S_ISSIGNED;
      case  ISWRITEABLE:
        return S_ISWRITEABLE;
      case  ISSEARCHABLE:
        return S_ISSEARCHABLE;
      default:
        return null;
      }
    }
  
    
    static int getAttrPosFromName(String name)
    {
      Integer intObj = (Integer)m_namelookup.get(name);
      if(null != intObj)
      {
        return intObj.intValue();
      }
      else
        return -1;
    }
    
    public boolean setName(String name)
    {
      m_name = name;
      int i = getAttrPosFromName(name);
      return (i >= 0);
    }
    
    public String getNodeName()
    {
      return m_name;
    }
  
    public String getName() 
    {
      return m_name;
    }
  
    public boolean getSpecified()
    {
      return true;
    }
    
    public String getNodeValue()
    {
      return getValue();
    }
  
    public String getValue()
    {
      int i = m_columnIndex+1; // sql counts by 1
      try
      {
        // System.out.println("m_type: "+m_type);
        switch(m_type)
        {
        case  CATALOGUE_NAME:
          return m_metadata.getCatalogName(i);
        case  DISPLAY_SIZE:
          return Integer.toString(m_metadata.getColumnDisplaySize(i));
        case  COLUMN_LABEL:
          return m_metadata.getColumnLabel(i);
        case  COLUMN_NAME:
          return m_metadata.getColumnName(i);
        case  COLUMN_TYPE:
          return Integer.toString(m_metadata.getColumnType(i));
        case  COLUMN_TYPENAME:
          return m_metadata.getColumnTypeName(i);
        case  PRECISION:
          return Integer.toString(m_metadata.getPrecision(i));
        case  SCALE:
          return Integer.toString(m_metadata.getScale(i));
        case  SCHEMA_NAME:
          return m_metadata.getSchemaName(i);
        case  TABLE_NAME:
          return m_metadata.getTableName(i);
        case  CASESENSITIVE:
          return m_metadata.isCaseSensitive(i) ? S_ISTRUE : S_ISFALSE;
        case  DEFINATELYWRITABLE:
          return m_metadata.isDefinitelyWritable(i) ? S_ISTRUE : S_ISFALSE;
        case  ISNULLABLE:
          return Integer.toString(m_metadata.isNullable(i));
        case  ISSIGNED:
          return m_metadata.isSigned(i) ? S_ISTRUE : S_ISFALSE;
        case  ISWRITEABLE:
          return m_metadata.isWritable(i) ? S_ISTRUE : S_ISFALSE;
        case  ISSEARCHABLE:
          return m_metadata.isSearchable(i) ? S_ISTRUE : S_ISFALSE;
        default:
          return "";
        }
      }
      catch(SQLException sqle)
      {
        return "SQL ERROR!";
      }
    }
    
    public void setValue(String value)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
  
    public Element getOwnerElement()
    {
      return m_owner;
    }
  
    public Node getParentNode()
    {
      return null;
    }
    
    /**
     * Return Node.ATTRIBUTE_NODE.
     */
    public short getNodeType()
    {
      return Node.ATTRIBUTE_NODE;
    }
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/ColumnData.java
  
  Index: ColumnData.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Text;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  import java.sql.SQLException;
  
  import org.apache.xalan.res.XSLTErrorResources;
  
  /**
   * This class represents a text node from a Column element.
   */
  public class ColumnData extends StreamableNode implements Text
  {
    Column m_parent;
    private static final boolean DEBUG = false;
    
    public ColumnData(XStatement statement, Column parent)
    {
      super(statement);
      m_parent = parent;
    }
    
    /**
     * Return Node.TEXT_NODE.
     */
    public short getNodeType()
    {
      return Node.TEXT_NODE;
    }
    
    public Text splitText(int offset)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
      return null;
    }
  
    public String getData()
      throws DOMException
    {
      try
      {
        ResultSet rs = this.getXStatement().getResultSet();
        int columnIndex = m_parent.m_columnIndex;
        
        if(DEBUG)
          System.out.println("In ColumnData.getData, columnIndex: "+columnIndex);
        if(columnIndex < m_parent.m_parent.m_childCount)
        {
          return rs.getString(columnIndex+1);
        }
        else
          return null;
      }
      catch(SQLException sqle)
      {
        return null;
      }
    }
    
    public String getNodeValue()
      throws DOMException
    {
      return getData();
    }
    
    /**
     *  The number of  16-bit units that are available through 
     * <code>data</code> and the <code>substringData</code> method below.  
     * This may have the value zero, i.e., <code>CharacterData</code> nodes 
     * may be empty.
     */
    public int getLength()
    {
      String s = getData();
      return (null != s) ? s.length() : 0;
    }
    
    public String substringData(int offset, 
                                int count)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
      return null;
    }
    
    public void appendData(String arg)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
    
    public void insertData(int offset, 
                           String arg)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
  
    public void deleteData(int offset, 
                           int count)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
  
    public void replaceData(int offset, 
                            int count, 
                            String arg)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
    
    public void setData(String data)
      throws DOMException
    {
      // TODO: It would be cool to make this callable, to set 
      // a value in the database.
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED);
    }
  
    
    /**
     * The parent of a document is null.
     */
    public Document getOwnerDocument()
    {
      return this.getXStatement();
    }
    
    /**
     * Return "#Text".
     */
    public String getNodeName()
    {
      return "#Text";
    }
        
    /**
     * Return null.
     */
    public Node               getFirstChild()
    {
      if(DEBUG)
        System.out.println("In ColumnData.getNextSibling");
      return null;
    }
    
    /**
     * This always returns null.
     */
    public Node               getNextSibling()
    {
      if(DEBUG)
        System.out.println("In ColumnData.getNextSibling");
      return null;
    }
    
    /**
     * The parent node of document is always null.
     */
    public Node               getParentNode()
    {
      if(DEBUG)
        System.out.println("In ColumnData.getParentNode");
      return m_parent;
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In ColumnData.hasChildNodes");
      return false;
    }
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/ColumnHeader.java
  
  Index: ColumnHeader.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  import org.w3c.dom.NamedNodeMap;
  
  import java.sql.ResultSetMetaData;
  import java.sql.SQLException;
  
  import org.apache.xalan.res.XSLTErrorResources;
  
  /**
   * This class represents a ColumnHeader, which represents the metadata 
   * for a column.
   */
  public class ColumnHeader extends StreamableNode implements NamedNodeMap
  {
    private static final boolean DEBUG = false;
    int m_columnIndex;
    ResultSetMetaData m_metaData;
    RowSet m_parent;
    
    public ColumnHeader(XStatement statement, RowSet parent, int columnIndex, 
                        ResultSetMetaData metaData)
    {
      super(statement);
      m_columnIndex = columnIndex;
      m_metaData = metaData;
      m_parent = parent;
    }
  
    /**
     * Return "row-set".
     */
    public String getNodeName()
    {
      return XStatement.S_COLUMNHEADERNAME;
    }
    
    /**
     * Return the document element node.
     */
    public Node               getFirstChild()
    {
      if(DEBUG)
        System.out.println("In ColumnHeader.getFirstChild");
      
      return null;
    }
    
    /**
     * This always returns null.
     */
    public Node               getNextSibling()
    {
      if(DEBUG)
        System.out.println("In ColumnHeader.getNextSibling");
      // try
      {
        if(this.getNodeTest().getNamespace() == null)
        {
          if(this.getNodeTest().getLocalName().equals(XStatement.S_COLUMNHEADERNAME))
          {
            int nextIndex = m_columnIndex+1;
            if(nextIndex < m_parent.m_columnHeaders.length)
            {
              if(null == m_parent.m_columnHeaders[nextIndex])
                m_parent.m_columnHeaders[nextIndex] 
                  = new ColumnHeader(getXStatement(), m_parent, nextIndex, m_metaData);
              return m_parent.m_columnHeaders[nextIndex];
            }
            else
              return null;
          }
        }
      }
      // catch(SQLException sqle)
      {
        // diagnostics?
      }
      return null;
    }
    
    /**
     * The parent node of document is always null.
     */
    public Node               getParentNode()
    {
      if(DEBUG)
        System.out.println("In ColumnHeader.getParentNode");
      return m_parent;
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In ColumnHeader.hasChildNodes");
      return false;
    }
    
    public NamedNodeMap       getAttributes()
    {
      return this;
    }
    
    // ============= NamedNodeMap ===============
    
    ColumnAttribute[] m_attributes = null;
    
    private void allocAttrs()
    {
      // try
      {
        m_attributes = new ColumnAttribute[ColumnAttribute.NUMBER_ATTRIBUTES];
      }
      // catch(SQLException sqle)
      {
        // diagnostics?
      }
    }
    
    private ColumnAttribute allocAttr(int pos, String name)
    {
      if(null == m_attributes[pos])
      {
        ColumnAttribute attr
          = new ColumnAttribute(this.getXStatement(),
                                this,
                                m_columnIndex, pos, m_metaData);
        attr.m_name = name;
        m_attributes[pos] = attr;
      }
      return m_attributes[pos];
    }
    
    public Node getNamedItem(String name)
    {
      if(null == m_attributes)
        allocAttrs();
      int pos = ColumnAttribute.getAttrPosFromName(name);
      if(pos >= 0)
      {
        return allocAttr(pos, name);
      }
      else
        return null;
    }
      
    public Node item(int index)
    {
      if(null == m_attributes)
        allocAttrs();
      
      String name = ColumnAttribute.getAttrNameFromPos(index);
      if(null != name)
      {
        return allocAttr(index, name);
      }
      else
        return null;
    }
  
    public int getLength()
    {
      return ColumnAttribute.NUMBER_ATTRIBUTES;
    }
  
    public Node getNamedItemNS(String namespaceURI, 
                               String localName)
    {
      if(null == namespaceURI)
        return getNamedItem(localName);
      return null;
    }
    
    public Node setNamedItem(Node arg)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED); 
      return null;
    }
    
    public Node removeNamedItem(String name)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED); 
      return null;
    }
    
    public Node setNamedItemNS(Node arg)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED); 
      return null;
    }
    
    public Node removeNamedItemNS(String namespaceURI, 
                                  String localName)
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED); 
      return null;
    }
  
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/Row.java
  
  Index: Row.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  import org.apache.xalan.utils.UnImplNode;
  
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  import java.sql.SQLException;
  import java.sql.ResultSet;
  
  /**
   * This class represents a row from a database.  It is used 
   * over and over, and so is certainly not fully DOM complient, 
   * and will result in strange results in the stylesheet if the 
   * user is not carefull.
   */
  public class Row extends StreamableNode
  {
    int m_childCount;
    Column[] m_columns;
    ResultSetMetaData m_metadata;
    boolean m_isStreamable = false;
    Row m_next; // normally null, if streamable.
    private static final boolean DEBUG = false;
    RowSet m_parent;
    
    public Row(XStatement statement, RowSet parent)
    {
      super(statement);
      try
      {
        m_parent = parent;
        XStatement xstatement = this.getXStatement();
        ResultSet resultSet = xstatement.getResultSet();
        ResultSetMetaData metadata = resultSet.getMetaData();
        m_metadata = metadata;
        m_childCount = metadata.getColumnCount();
        m_columns = new Column[m_childCount];
        for(int i = 0; i < m_childCount; i++)
        {
          m_columns[i] = new Column(xstatement, this, i, metadata);
        }
      }
      catch(SQLException sqle)
      {
        // diagnostics?
      }
    }
      
    // ===== Element implementation =====
      
    /**
     * The parent of a document is null.
     */
    public Document getOwnerDocument()
    {
      return this.getXStatement();
    }
    
    /**
     * Return "#Document".
     */
    public String getNodeName()
    {
      return XStatement.S_ROWNAME;
    }
        
    /**
     * Return the document element node.
     */
    public Node               getFirstChild()
    {
      if(DEBUG)
        System.out.println("In Row.getFirstChild");
      
      if(this.hasChildNodes())
        return m_columns[0];
      else
        return null;
    }
    
    /**
     * This always returns null.
     */
    public Node               getNextSibling()
    {
      if(DEBUG)
        System.out.println("In Row.getNextSibling");
      XStatement xstatement = this.getXStatement();
      ResultSet resultSet = xstatement.getResultSet();
      try
      {
        if(m_isStreamable)
        {
          if(resultSet.next())
            return this;
          else
            return null;
        }
        else
        {
          if(null == m_next)
          {
            try
            {
              if(resultSet.next())
                m_next = new Row(getXStatement(), m_parent);
            }
            catch(SQLException sqle)
            {
              // Diagnostics?
            }
          }
          return m_next;
        }
      }
      catch(SQLException sqle)
      {
        // Diagnostics?
        return null;
      }
    }
      
    /**
     * Return the RowSet parent.
     */
    public Node               getParentNode()
    {
      if(DEBUG)
        System.out.println("In Row.getParentNode");
      return m_parent;
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In Row.hasChildNodes");
      return (m_childCount > 0);
    }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/RowSet.java
  
  Index: RowSet.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  
  import java.sql.SQLException;
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  
  /**
   * This class represents the document element of a virtual 
   * document that represents a JDBC query.
   */
  public class RowSet extends StreamableNode
  {
    ColumnHeader[] m_columnHeaders;
    Row m_firstrow;
    private static final boolean DEBUG = false;
  
    public RowSet(XStatement statement)
    {
      super(statement);
    }
    
    // ===== Element implementation =====
      
    /**
     * Return "row-set".
     */
    public String getNodeName()
    {
      return XStatement.S_DOCELEMENTNAME;
    }
      
    /**
     * Return the document element node.
     */
    public Node               getFirstChild()
    {
      if(DEBUG)
        System.out.println("In RowSet.getFirstChild");
  
      try
      {
        if(this.getNodeTest().getNamespace() == null)
        {
          if(this.getNodeTest().getLocalName().equals(XStatement.S_COLUMNHEADERNAME))
          {
            if(null == m_columnHeaders)
            {
              ResultSetMetaData metaData = getXStatement().m_resultSet.getMetaData();
              int columnCount = metaData.getColumnCount();
              if(columnCount > 0)
              {
                m_columnHeaders = new ColumnHeader[columnCount];
                m_columnHeaders[0] = new ColumnHeader(getXStatement(), this, 0, metaData);
                return m_columnHeaders[0];
              }
              else 
                return null;
            }
            else
              return m_columnHeaders[0];
          }
          else if(this.getNodeTest().getLocalName().equals(XStatement.S_ROWNAME))
          {
            if(null == m_firstrow)
            {
              m_firstrow = new Row(getXStatement(), this);
            }
            return m_firstrow;
          }
          else
            return null;
        }
        else
          return null;
      }
      catch(SQLException sqle)
      {
        // diagnostics?
        return null;
      }
    }
    
    /**
     * This always returns null.
     */
    public Node               getNextSibling()
    {
      if(DEBUG)
        System.out.println("In RowSet.getNextSibling");
      return null;
    }
    
    /**
     * The parent node of document is always null.
     */
    public Node               getParentNode()
    {
      if(DEBUG)
        System.out.println("In RowSet.getParentNode");
      return this.getXStatement();
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In RowSet.hasChildNodes");
      return true;
    }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/StreamableNode.java
  
  Index: StreamableNode.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  import org.apache.xalan.utils.UnImplNode;
  import org.apache.xpath.patterns.NodeTestFilter;
  import org.apache.xpath.patterns.NodeTest;
  
  /**
   * This is the superclass for all nodes in the Xalan sql package.
   */
  public class StreamableNode extends UnImplNode implements NodeTestFilter
  {
    private XStatement m_statement;
    
    public XStatement getXStatement()
    {
      return m_statement;
    }
    
    private NodeTest m_nodetest;
    
    public NodeTest getNodeTest()
    {
      return m_nodetest;
    }
    
    public StreamableNode(XStatement statement)
    {
      m_statement = statement;
    }
    
    public void setNodeTest(NodeTest nodeTest)
    {
      m_nodetest = nodeTest;
    }
    
    public Document getOwnerDocument()
    {
      return m_statement;
    }
  
    /**
     * Streamable nodes default to being elements.
     */
    public short getNodeType()
    {
      return Node.ELEMENT_NODE;
    }
    
    /**
     * Return "#Document".
     */
    public String       getLocalName()
    {
      return getNodeName();
    }
  
    /**
     * Returns null.
     */
    public String             getNamespaceURI()
    {
      return null;
    }
  
    /** Returns null. */
    public String             getPrefix()
    {
      return null;
    }
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/XConnection.java
  
  Index: XConnection.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import java.sql.Connection;
  import java.sql.DatabaseMetaData;
  import java.sql.DriverManager;
  import java.sql.SQLException;
  
  import org.w3c.dom.traversal.NodeIterator;
  
  /**
   * This is an extension for XSLT that allows a stylesheet to 
   * access JDBC data.
   */
  public class XConnection
  { 
    private static final boolean DEBUG = false;
  
    /**
     * A database url of the form jdbc:subprotocol:subname.
     */
    public String m_driver;
    
    /**
     * A list of arbitrary string tag/value pairs as connection 
     * arguments; normally at least a "user" and "password" 
     * property should be included.
     */
    public String m_protocol;
    
    /**
     * The JDBC connection.
     */
    public Connection m_connection = null;
      
    /**
     * Create a SimpleNodeLocator object.
     */
    public XConnection(String driver, String protocol)
    {
      super();
      init(driver, protocol);
    }
    
    /**
     * Initialize.
     */
    private void init(String driver, String protocol)
    {
      m_driver = driver;
      m_protocol = protocol;
      connect(driver, protocol);
    }
    
    /**
     * Connect to the JDBC database. 
     * @param driver Database url of the form jdbc:subprotocol:subname .
     * @param protocol List of arbitrary string tag/value pairs as 
     * connection arguments; normally at least a "user" and "password" 
     * property should be included.
     */
    public void connect(String driver, String protocol) 
    {    
    try 
      {      
        // The driver is installed by loading its class.
        Class.forName(driver).newInstance();
  
        m_connection = DriverManager.getConnection(protocol);
        
        /*
        We could also turn autocommit off by putting
        ;autocommit=false on the URL.
        */
        m_connection.setAutoCommit(false);
        
			DatabaseMetaData dma = m_connection.getMetaData ();
  
        if(DEBUG)
        {
          System.out.println("\nConnected to " + dma.getURL());
          System.out.println("Driver   " + dma.getDriverName());
          System.out.println("Version  " + dma.getDriverVersion());
          System.out.println("");
        }
  
      }
      catch (Throwable e) 
      {
        e.printStackTrace();
      }
    }
    
    public NodeIterator query(String queryString)
      throws SQLException
    {
      // TODO: These need to be pooled.
      return new XStatement(this, queryString);
    }
    
    public void close()
      throws SQLException
    {
      if(DEBUG)
        System.out.println("Entering XConnection.close");
      if(null != m_connection)
      {
        m_connection.close();
        m_connection = null;
      }
      if(DEBUG)
        System.out.println("Exiting XConnection.close");
    }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/lib/sql/XStatement.java
  
  Index: XStatement.java
  ===================================================================
  package org.apache.xalan.lib.sql;
  
  import org.w3c.dom.traversal.NodeIterator;
  import org.w3c.dom.traversal.NodeFilter;
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.DOMException;
  
  import java.sql.Statement;
  import java.sql.SQLException;
  import java.sql.ResultSet;
  
  import org.apache.xpath.axes.ContextNodeList;
  import org.apache.xalan.res.XSLTErrorResources;
  
  /**
   * This class represents a JDBC query statement, and also
   * acts as both a NodeIterator and the Document node.
   */
  public class XStatement extends StreamableNode 
    implements NodeIterator, ContextNodeList, Cloneable
  {
    private static final boolean DEBUG = false;
    private Statement m_statement;
    
    public Statement getStatement()
    {
      return m_statement;
    }
    
    ResultSet m_resultSet;
    
    public ResultSet getResultSet()
    {
      return m_resultSet;
    }
    
    private XConnection m_xconnection;
    private String m_queryString; 
    RowSet m_rowset;
    boolean m_nextHasBeenCalled = false;
    
    static final String S_DOCELEMENTNAME = "row-set";
    static final String S_COLUMNHEADERNAME = "column-header";
    static final String S_ROWNAME = "row";
    static final String S_COLUMNNAME = "col";
    
    public XStatement(XConnection connection, String queryString)
      throws SQLException
    {
      super(null);
      if(DEBUG)
        System.out.println("In XStatement constructor");
      // The SQL statement which let's us execute commands against the connection.
      m_xconnection = connection;
      m_statement = m_xconnection.m_connection.createStatement();
      m_queryString = queryString;
      m_resultSet = m_statement.executeQuery(m_queryString);
      m_rowset = new RowSet(this);
  
      if(DEBUG)
        System.out.println("Exiting XStatement constructor");
    }
    
    public XStatement getXStatement()
    {
      return this;
    }
      
    // ============== NodeIterator interface =============
    
    /**
     *  The root node of the Iterator, as specified when it was created.
     */
    public Node getRoot()
    {
      if(DEBUG)
        System.out.println("In XStatement.getRoot");
      return this;
    }
  
    /**
     *  This attribute determines which node types are presented via the 
     * iterator. The available set of constants is defined in the 
     * <code>NodeFilter</code> interface.
     */
    public int getWhatToShow()
    {
      if(DEBUG)
        System.out.println("In XStatement.getWhatToShow");
      // TODO: ??
      return NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_ENTITY_REFERENCE;
    }
  
    /**
     *  The filter used to screen nodes.
     */
    public NodeFilter getFilter()
    {
      if(DEBUG)
        System.out.println("In XStatement.getFilter");
      return null;
    }
  
    /**
     *  The value of this flag determines whether the children of entity 
     * reference nodes are visible to the iterator. If false, they will be 
     * skipped over.
     * <br> To produce a view of the document that has entity references 
     * expanded and does not expose the entity reference node itself, use the 
     * whatToShow flags to hide the entity reference node and set 
     * expandEntityReferences to true when creating the iterator. To produce 
     * a view of the document that has entity reference nodes but no entity 
     * expansion, use the whatToShow flags to show the entity reference node 
     * and set expandEntityReferences to false.
     */
    public boolean getExpandEntityReferences()
    {
      if(DEBUG)
        System.out.println("In XStatement.getExpandEntityReferences");
      return true;
    }
      
    /**
     * Return the document node.
     */
    public Node nextNode()
      throws DOMException
    {
      if(DEBUG)
        System.out.println("In XStatement.nextNode");
      if(!m_nextHasBeenCalled)
      {
        m_nextHasBeenCalled = true;
        return this;
      }
      else
        return null;
    }
    
    /**
     * Throw an exception, since streaming nodes and iterators can not 
     * go backwards.
     */
    public Node previousNode()
      throws DOMException
    {
      error(XSLTErrorResources.ER_FUNCTION_NOT_SUPPORTED); //"getParentNode not supported!");
      return null;
    }
  
    /**
     *  Detaches the iterator from the set which it iterated over, releasing 
     * any computational resources and placing the iterator in the INVALID 
     * state. After<code>detach</code> has been invoked, calls to 
     * <code>nextNode</code> or<code>previousNode</code> will raise the 
     * exception INVALID_STATE_ERR.
     */
    public void detach()
    {
      if(DEBUG)
        System.out.println("XStatement.detach");
      try
      {
        m_statement.close();
        m_statement = null;
        m_resultSet = null;
      }
      catch(SQLException sqle)
      { 
        // diagnostics?
      }
    }
    
    public String toString()
    {
      return "XStatement: "+m_queryString;
    }
  
  
    // ===== Document implementation ====
    
    /**
     * The parent of a document is null.
     */
    public Document getOwnerDocument()
    {
      return null;
    }
  
    /**
     * Return Node.DOCUMENT_NODE.
     */
    public short getNodeType()
    {
      return Node.DOCUMENT_NODE;
    }
    
    /**
     * Return "#Document".
     */
    public String getNodeName()
    {
      return "#Document";
    }
    
    /**
     * Return the document element node.
     */
    public Node               getFirstChild()
    {
      if(DEBUG)
        System.out.println("In XStatement.getFirstChild: "+this.getNodeTest());
      
      try
      {
        if((this.getNodeTest().getNamespace() == null) && 
           (this.getNodeTest().getLocalName().equals(S_DOCELEMENTNAME)))
          return m_rowset;
        else
          return null;
      }
      catch(NullPointerException e)
      {
        e.printStackTrace();
        throw e;
      }
    }
    
    /**
     * This always returns null.
     */
    public Node               getNextSibling()
    {
      if(DEBUG)
        System.out.println("In XStatement.getNextSibling");
      return null;
    }
    
    /**
     * The parent node of document is always null.
     */
    public Node               getParentNode()
    {
      if(DEBUG)
        System.out.println("In XStatement.getParentNode");
      return null;
    }
    
    /**
     * Tell if there are any children of the document, 
     * which is always true.
     */
    public boolean            hasChildNodes()
    {
      if(DEBUG)
        System.out.println("In XStatement.hasChildNodes");
      return true;
    }
    
    // ===== ContextNodeList implementation =====
    
    public Node getCurrentNode()
    {
      return this.m_rowset;
    }
    
    public int getCurrentPos()
    {
      return 0; // Not totally sure...
    }
    
    public void reset()
    {
      this.m_nextHasBeenCalled = false;
    }
  
    public void setShouldCacheNodes(boolean b)
    {
      // Set streamable?
    }
  
    public void runTo(int index)
    {
      // Throw exception if not streamable!
    }
  
    public void setCurrentPos(int i)
    {
      // Throw exception if not streamable!
    }
    
    public int size()
    {
      return 1;
    }
    
    public boolean isFresh()
    {
      return (!this.m_nextHasBeenCalled);
    }
    
    public NodeIterator cloneWithReset()
      throws CloneNotSupportedException
    {
      XStatement clone = (XStatement)super.clone();
      clone.reset();
      return clone;
    }
  
    public Object clone()
      throws CloneNotSupportedException
    {
      XStatement clone = (XStatement)super.clone();
      return clone;
    }
  
  
  }