commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject cvs commit: jakarta-commons-sandbox/jelly/jelly-tags/sql .cvsignore maven.xml project.properties project.xml
Date Tue, 07 Jan 2003 13:47:13 GMT
dion        2003/01/07 05:47:13

  Added:       jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql
                        TransactionTag.java DriverTag.java
                        SetDataSourceTag.java UpdateTag.java
                        DateParamTag.java DataSourceUtil.java
                        DataSourceWrapper.java package.html
                        SqlTagSupport.java ResultImpl.java
                        SqlTagLibrary.java ResultSetTag.java QueryTag.java
                        RowTag.java ParamTag.java
               jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql
                        TestJUnit.java example.jelly example3.jelly
                        example2.jelly suite.jelly testSql.jelly
               jelly/jelly-tags/sql .cvsignore maven.xml project.properties
                        project.xml
  Log:
  Move sql taglib out of core
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/TransactionTag.java
  
  Index: TransactionTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.Connection;
  import java.sql.SQLException;
  
  import javax.sql.DataSource;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  
  /**
   * <p>Tag handler for &lt;Transaction&gt; in JSTL.  
   * 
   * @author Hans Bergsten
   */
  
  public class TransactionTag extends TagSupport {
  
      //*********************************************************************
      // Private constants
  
      private static final String TRANSACTION_READ_COMMITTED = "read_committed";
      private static final String TRANSACTION_READ_UNCOMMITTED = "read_uncommitted";
      private static final String TRANSACTION_REPEATABLE_READ = "repeatable_read";
      private static final String TRANSACTION_SERIALIZABLE = "serializable";
  
      //*********************************************************************
      // Protected state
  
      protected Object rawDataSource;
      protected boolean dataSourceSpecified;
  
      //*********************************************************************
      // Private state
  
      private Connection conn;
      private int isolation = Connection.TRANSACTION_NONE;
      private int origIsolation;
  
      //*********************************************************************
      // Constructor and initialization
  
      public TransactionTag() {
      }
  
      /**
       * Sets the SQL DataSource. DataSource can be
       * a String or a DataSource object.
       */
      public void setDataSource(Object dataSource) {
          this.rawDataSource = dataSource;
          this.dataSourceSpecified = true;
      }
  
  
      //*********************************************************************
      // Tag logic
  
      /**
       * Prepares for execution by setting the initial state, such as
       * getting the <code>Connection</code> and preparing it for
       * the transaction.
       */
      public void doTag(XMLOutput output) throws Exception {
  
          if ((rawDataSource == null) && dataSourceSpecified) {
              throw new JellyException(Resources.getMessage("SQL_DATASOURCE_NULL"));
          }
  
          DataSource dataSource = DataSourceUtil.getDataSource(rawDataSource, context);
  
          try {
              conn = dataSource.getConnection();
              origIsolation = conn.getTransactionIsolation();
              if (origIsolation == Connection.TRANSACTION_NONE) {
                  throw new JellyException(Resources.getMessage("TRANSACTION_NO_SUPPORT"));
              }
              if ((isolation != Connection.TRANSACTION_NONE)
                  && (isolation != origIsolation)) {
                  conn.setTransactionIsolation(isolation);
              }
              conn.setAutoCommit(false);
          }
          catch (SQLException e) {
              throw new JellyException(
                  Resources.getMessage("ERROR_GET_CONNECTION", e.getMessage()));
          }
  
          boolean finished = false;
          try {
              invokeBody(output);
              finished = true;
          }
          catch (Exception e) {
              if (conn != null) {
                  try {
                      conn.rollback();
                  }
                  catch (SQLException s) {
                      // Ignore to not hide orignal exception
                  }
                  doFinally();
              }
              throw e;
          }
  
          // lets commit          
          try {
              conn.commit();
          }
          catch (SQLException e) {
              throw new JellyException(
                  Resources.getMessage("TRANSACTION_COMMIT_ERROR", e.getMessage()));
          }
          finally {
              doFinally();
          }
      }
  
      //*********************************************************************
      // Public utility methods
  
      /**
       * Sets the transaction isolation level.
       */
      public void setIsolation(String iso) throws JellyException {
  
          if (TRANSACTION_READ_COMMITTED.equals(iso)) {
              isolation = Connection.TRANSACTION_READ_COMMITTED;
          }
          else if (TRANSACTION_READ_UNCOMMITTED.equals(iso)) {
              isolation = Connection.TRANSACTION_READ_UNCOMMITTED;
          }
          else if (TRANSACTION_REPEATABLE_READ.equals(iso)) {
              isolation = Connection.TRANSACTION_REPEATABLE_READ;
          }
          else if (TRANSACTION_SERIALIZABLE.equals(iso)) {
              isolation = Connection.TRANSACTION_SERIALIZABLE;
          }
          else {
              throw new JellyException(Resources.getMessage("TRANSACTION_INVALID_ISOLATION"));
          }
      }
  
      /**
       * Called by nested parameter elements to get a reference to
       * the Connection.
       */
      public Connection getSharedConnection() {
          return conn;
      }
  
      //*********************************************************************
      // Implementation methods methods
  
      /**
       * Restores the <code>Connection</code> to its initial state and
       * closes it.
       */
      protected void doFinally() {
          if (conn != null) {
              try {
                  if ((isolation != Connection.TRANSACTION_NONE)
                      && (isolation != origIsolation)) {
                      conn.setTransactionIsolation(origIsolation);
                  }
                  conn.setAutoCommit(true);
                  conn.close();
              }
              catch (SQLException e) {
                  // Not much we can do
              }
          }
          conn = null;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/DriverTag.java
  
  Index: DriverTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * <p>Tag handler for &lt;Driver&gt; in JSTL, used to create
   * a simple DataSource for prototyping.</p>
   * 
   * @author Hans Bergsten
   */
  public class DriverTag extends TagSupport {
      private static final String DRIVER_CLASS_NAME =
          "javax.servlet.jsp.jstl.sql.driver";
      private static final String JDBC_URL = "javax.servlet.jsp.jstl.sql.jdbcURL";
      private static final String USER_NAME = "javax.servlet.jsp.jstl.sql.userName";
      private static final String PASSWORD = "javax.servlet.jsp.jstl.sql.password";
  
      private String driverClassName;
      private String jdbcURL;
      private String scope = "page";
      private String userName;
      private String var;
  
      //*********************************************************************
      // Accessor methods
  
      public void setDriver(String driverClassName) {
          this.driverClassName = driverClassName;
      }
  
      public void setJdbcURL(String jdbcURL) {
          this.jdbcURL = jdbcURL;
      }
  
      /**
       * Sets the scope of the variable to hold the
       * result.
       *
       */
      public void setScope(String scopeName) {
          this.scope = scopeName;
      }
  
      public void setUserName(String userName) {
          this.userName = userName;
      }
  
      public void setVar(String var) {
          this.var = var;
      }
  
      //*********************************************************************
      // Tag logic
  
      public void doTag(XMLOutput output) throws Exception {
          DataSourceWrapper ds = new DataSourceWrapper();
          try {
              ds.setDriverClassName(getDriverClassName());
          }
          catch (Exception e) {
              throw new JellyException("Invalid driver class name: " + e.getMessage());
          }
          ds.setJdbcURL(getJdbcURL());
          ds.setUserName(getUserName());
          ds.setPassword(getPassword());
          context.setVariable(var, ds);
      }
  
      //*********************************************************************
      // Private utility methods
  
      private String getDriverClassName() {
          if (driverClassName != null) {
              return driverClassName;
          }
          return getInitParameter(DRIVER_CLASS_NAME);
      }
  
      private String getJdbcURL() {
          if (jdbcURL != null) {
              return jdbcURL;
          }
          return getInitParameter(JDBC_URL);
      }
  
      private String getUserName() {
          if (userName != null) {
              return userName;
          }
          return getInitParameter(USER_NAME);
      }
  
      private String getPassword() {
          return getInitParameter(PASSWORD);
      }
      
      protected String getInitParameter(String key) {
          return "";
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/SetDataSourceTag.java
  
  Index: SetDataSourceTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import javax.sql.DataSource;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * <p>Tag handler for &lt;SetDataSource&gt; in JSTL, used to create
   * a simple DataSource for prototyping.</p>
   * 
   * @author Hans Bergsten
   * @author Justyna Horwat
   */
  public class SetDataSourceTag extends TagSupport {
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(SetDataSourceTag.class);
  
      protected Object dataSource;
      protected boolean dataSourceSpecified;
      protected String jdbcURL;
      protected String driverClassName;
      protected String userName;
      protected String password;
  
      private String scope = "page";
      private String var;
  
      //*********************************************************************
      // Constructor and initialization
  
      public SetDataSourceTag() {
      }
  
      //*********************************************************************
      // Accessor methods
  
      /**
       * Sets the scope of the variable to hold the
       * result.
       *
       */
      public void setScope(String scope) {
          this.scope = scope;
      }
  
      public void setVar(String var) {
          this.var = var;
      }
  
      public void setDataSource(Object dataSource) {
          this.dataSource = dataSource;
          this.dataSourceSpecified = true;
      }
  
      public void setDriver(String driverClassName) {
          this.driverClassName = driverClassName;
      }
  
      public void setUrl(String jdbcURL) {
          this.jdbcURL = jdbcURL;
      }
  
      public void setUser(String userName) {
          this.userName = userName;
      }
  
      public void setPassword(String password) {
          this.password = password;
      }
  
      //*********************************************************************
      // Tag logic
  
      public void doTag(XMLOutput output) throws Exception {
          DataSource ds = null;
  
          if (dataSource != null) {
              ds = DataSourceUtil.getDataSource(dataSource, context);
          }
          else {
              if (dataSourceSpecified) {
                  throw new JellyException(Resources.getMessage("SQL_DATASOURCE_NULL"));
              }
  
              DataSourceWrapper dsw = new DataSourceWrapper();
              try {
                  // set driver class iff provided by the tag
                  if (driverClassName != null) {
                      dsw.setDriverClassName(driverClassName);
                  }
              }
              catch (Exception e) {
                  log.error( "Could not load driver class: " + e, e );
                  throw new JellyException(
                      Resources.getMessage("DRIVER_INVALID_CLASS", e.getMessage()));
              }
              dsw.setJdbcURL(jdbcURL);
              dsw.setUserName(userName);
              dsw.setPassword(password);
              ds = (DataSource) dsw;
          }
  
          if (var != null) {
              context.setVariable(var, ds);
          }
          else {
              context.setVariable("org.apache.commons.jelly.sql.DataSource", ds);
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/UpdateTag.java
  
  Index: UpdateTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  import java.sql.Statement;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * <p>Tag handler for &lt;Update&gt; in JSTL.  
   * 
   * @author Hans Bergsten
   * @author Justyna Horwat
   */
  
  public class UpdateTag extends SqlTagSupport {
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(UpdateTag.class);
      
      /*
       * Instance variables that are not for attributes
       */
      private Connection conn;
  
      //*********************************************************************
      // Constructor and initialization
  
      public UpdateTag() {
      }
  
      //*********************************************************************
      // Tag logic
  
      /**
       * <p>Execute the SQL statement, set either through the <code>sql</code>
       * attribute or as the body, and save the result as a variable
       * named by the <code>var</code> attribute in the scope specified
       * by the <code>scope</code> attribute, as an object that implements
       * the Result interface.
       *
       * <p>The connection used to execute the statement comes either
       * from the <code>DataSource</code> specified by the
       * <code>dataSource</code> attribute, provided by a parent action
       * element, or is retrieved from a JSP scope  attribute
       * named <code>javax.servlet.jsp.jstl.sql.dataSource</code>.
       */
      public void doTag(XMLOutput output) throws Exception {
          try {
              conn = getConnection();
          }
          catch (SQLException e) {
              throw new JellyException(sql + ": " + e.getMessage(), e);
          }
  
          /*
           * Use the SQL statement specified by the sql attribute, if any,
           * otherwise use the body as the statement.
           */
          String sqlStatement = null;
          if (sql != null) {
              sqlStatement = sql;
          }
          else {
              sqlStatement = getBodyText();
          }
          if (sqlStatement == null || sqlStatement.trim().length() == 0) {
              throw new JellyException(Resources.getMessage("SQL_NO_STATEMENT"));
          }
  
          Statement statement = null;
          int result = 0;
          try {
              if ( hasParameters() ) {
                  PreparedStatement ps = conn.prepareStatement(sqlStatement);
                  statement = ps;
                  setParameters(ps);
                  result = ps.executeUpdate();
              }
              else {
                  statement = conn.createStatement();
                  result = statement.executeUpdate(sqlStatement);
              }
              if (var != null) {
                  context.setVariable(var, new Integer(result));
              }
  
              // lets nullify before we close in case we get exceptions
              // while closing, we don't want to try to close again
              Statement tempStatement = statement;
              statement = null;
              tempStatement.close();
          }
          catch (SQLException e) {
              throw new JellyException(sqlStatement + ": " + e.getMessage(), e);
          }
          finally {
              if (statement != null) {
                  try {
                      statement.close();
                  }
                  catch (SQLException e) {
                      log.error("Caught exception while closing statement: " + e, e);
                  }
              }
              if (conn != null && !isPartOfTransaction) {
                  try {
                      conn.close();
                  }
                  catch (SQLException e) {
                      log.error("Caught exception while closing connection: " + e, e);
                  }
              }
              clearParameters();
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/DateParamTag.java
  
  Index: DateParamTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.Date;
  
  import javax.servlet.jsp.jstl.sql.SQLExecutionTag;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  
  /**
   * <p>Tag handler for &lt;Param&gt; in JSTL, used to set
   * parameter values for a SQL statement.</p>
   * 
   * @author Justyna Horwat
   */
  
  public class DateParamTag extends TagSupport {
  
      //*********************************************************************
      // Private constants
  
      private static final String TIMESTAMP_TYPE = "timestamp";
      private static final String TIME_TYPE = "time";
      private static final String DATE_TYPE = "date";
  
      //*********************************************************************
      // Protected state
  
      protected String type;
      protected java.util.Date value;
  
      //*********************************************************************
      // Constructor
  
      public DateParamTag() {
      }
  
      //*********************************************************************
      // Properties
      
      public void setValue(Date value) {
          this.value = value;
      }
  
      public void setType(String type) {
          this.type = type;
      }
  
      //*********************************************************************
      // Tag logic
  
      public void doTag(XMLOutput output) throws Exception {
          SQLExecutionTag parent =
              (SQLExecutionTag) findAncestorWithClass(this, SQLExecutionTag.class);
          if (parent == null) {
              throw new JellyException(Resources.getMessage("SQL_PARAM_OUTSIDE_PARENT"));
          }
  
          if (value != null) {
              convertValue();
          }
  
          parent.addSQLParameter(value);
      }
  
      //*********************************************************************
      // Private utility methods
  
      private void convertValue() throws JellyException {
  
          if ((type == null) || (type.equalsIgnoreCase(TIMESTAMP_TYPE))) {
              if (!(value instanceof java.sql.Timestamp)) {
                  value = new java.sql.Timestamp(value.getTime());
              }
          }
          else if (type.equalsIgnoreCase(TIME_TYPE)) {
              if (!(value instanceof java.sql.Time)) {
                  value = new java.sql.Time(value.getTime());
              }
          }
          else if (type.equalsIgnoreCase(DATE_TYPE)) {
              if (!(value instanceof java.sql.Date)) {
                  value = new java.sql.Date(value.getTime());
              }
          }
          else {
              throw new JellyException(
                  Resources.getMessage("SQL_DATE_PARAM_INVALID_TYPE", type));
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/DataSourceUtil.java
  
  Index: DataSourceUtil.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import javax.sql.DataSource;
  import javax.naming.InitialContext;
  import javax.naming.Context;
  import javax.naming.NamingException;
  
  import org.apache.commons.jelly.JellyContext;
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.tags.Resources;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * <p>A simple <code>DataSource</code> utility for the standard
   * <code>DriverManager</code> class.
   *
   * TO DO: need to cache DataSource
   * 
   * @author Justyna Horwat
   */
  public class DataSourceUtil {
  
      private static final String ESCAPE = "\\";
      private static final String TOKEN = ",";
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(DataSourceUtil.class);
  
      /**
       * If dataSource is a String first do JNDI lookup.
       * If lookup fails parse String like it was a set of JDBC parameters
       * Otherwise check to see if dataSource is a DataSource object and use as
       * is
       */
      static DataSource getDataSource(Object rawDataSource, JellyContext pc)
          throws JellyException {
          DataSource dataSource = null;
  
          if (rawDataSource == null) {
              rawDataSource = pc.getVariable("org.apache.commons.jelly.sql.DataSource");
          }
  
          if (rawDataSource == null) {
              return null;
          }
  
          /*
          * If the 'dataSource' attribute's value resolves to a String
          * after rtexpr/EL evaluation, use the string as JNDI path to
          * a DataSource
          */
          if (rawDataSource instanceof String) {
              try {
                  Context ctx = new InitialContext();
                  // relative to standard JNDI root for J2EE app
                  Context envCtx = (Context) ctx.lookup("java:comp/env");
                  dataSource = (DataSource) envCtx.lookup((String) rawDataSource);
              }
              catch (NamingException ex) {
                  dataSource = getDataSource((String) rawDataSource);
              }
          }
          else if (rawDataSource instanceof DataSource) {
              dataSource = (DataSource) rawDataSource;
          }
          else {
              throw new JellyException(Resources.getMessage("SQL_DATASOURCE_INVALID_TYPE"));
          }
  
          return dataSource;
      }
  
      /**
       * Parse JDBC parameters and setup dataSource appropriately
       */
      private static DataSource getDataSource(String params) throws JellyException {
          DataSourceWrapper dataSource = new DataSourceWrapper();
  
          String[] paramString = new String[4];
          int escCount = 0;
          int aryCount = 0;
          int begin = 0;
  
          for (int index = 0; index < params.length(); index++) {
              char nextChar = params.charAt(index);
              if (TOKEN.indexOf(nextChar) != -1) {
                  if (escCount == 0) {
                      paramString[aryCount] = params.substring(begin, index);
                      begin = index + 1;
                      if (++aryCount > 4) {
                          throw new JellyException(Resources.getMessage("JDBC_PARAM_COUNT"));
                      }
                  }
              }
              if (ESCAPE.indexOf(nextChar) != -1) {
                  escCount++;
              }
              else {
                  escCount = 0;
              }
          }
          paramString[aryCount] = params.substring(begin);
  
          // use the JDBC URL from the parameter string
          dataSource.setJdbcURL(paramString[0]);
  
          // try to load a driver if it's present
          if (paramString[1] != null) {
              try {
                  dataSource.setDriverClassName(paramString[1]);
              }
              catch (Exception ex) {
                  throw new JellyException(
                      Resources.getMessage("DRIVER_INVALID_CLASS", ex.getMessage()));
              }
          }
  
          // set the username and password
          dataSource.setUserName(paramString[2]);
          dataSource.setPassword(paramString[3]);
  
          return dataSource;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/DataSourceWrapper.java
  
  Index: DataSourceWrapper.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.io.PrintWriter;
  import java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.SQLException;
  
  import javax.sql.DataSource;
  
  import org.apache.commons.jelly.tags.Resources;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * <p>A simple <code>DataSource</code> wrapper for the standard
   * <code>DriverManager</code> class.
   * 
   * @author Hans Bergsten
   */
  public class DataSourceWrapper implements DataSource {
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(DataSourceWrapper.class);
  
      private String driverClassName;
      private String jdbcURL;
      private String userName;
      private String password;
  
      public void setDriverClassName(String driverClassName)
          throws ClassNotFoundException, InstantiationException, IllegalAccessException {
  
          if (log.isDebugEnabled()) {
              log.debug("Loading JDBC driver: [" + driverClassName + "]");
          }
  
          this.driverClassName = driverClassName;
          getClass().getClassLoader().loadClass(driverClassName).newInstance();
      }
  
      public void setJdbcURL(String jdbcURL) {
          this.jdbcURL = jdbcURL;
      }
  
      public void setUserName(String userName) {
          this.userName = userName;
      }
  
      public void setPassword(String password) {
          this.password = password;
      }
  
      /**
       * Returns a Connection using the DriverManager and all
       * set properties.
       */
      public Connection getConnection() throws SQLException {
          Connection conn = null;
          if (userName != null) {
              if (log.isDebugEnabled()) {
                  log.debug(
                      "Creating connection from url: " + jdbcURL + " userName: " + userName);
              }
  
              conn = DriverManager.getConnection(jdbcURL, userName, password);
          }
          else {
              if (log.isDebugEnabled()) {
                  log.debug("Creating connection from url: " + jdbcURL);
              }
  
              conn = DriverManager.getConnection(jdbcURL);
          }
          if (log.isDebugEnabled()) {
              log.debug(
                  "Created connection: " + conn );
          }
          return conn;
      }
  
      /**
       * Always throws a SQLException. Username and password are set
       * in the constructor and can not be changed.
       */
      public Connection getConnection(String username, String password)
          throws SQLException {
          throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
      }
  
      /**
       * Always throws a SQLException. Not supported.
       */
      public int getLoginTimeout() throws SQLException {
          throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
      }
  
      /**
       * Always throws a SQLException. Not supported.
       */
      public PrintWriter getLogWriter() throws SQLException {
          throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
      }
  
      /**
       * Always throws a SQLException. Not supported.
       */
      public void setLoginTimeout(int seconds) throws SQLException {
          throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
      }
  
      /**
       * Always throws a SQLException. Not supported.
       */
      public synchronized void setLogWriter(PrintWriter out) throws SQLException {
          throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/package.html
  
  Index: package.html
  ===================================================================
  <html>
  <head>
  </head>
  <body>
  
    <p>The SQL Tags from the JSTL
    </p>
    
    <p>There are some examples of these tags in action 
    <a href="http://cvs.apache.org/viewcvs.cgi/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/sql/">here</a>
    </p>
  </body>
  </html>
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/SqlTagSupport.java
  
  Index: SqlTagSupport.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.servlet.jsp.jstl.sql.SQLExecutionTag;
  import javax.sql.DataSource;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.tags.Resources;
  
  /**
   * <p>Abstract base class for any SQL related tag in JSTL.  
   * 
   * @author Hans Bergsten
   * @author Justyna Horwat
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
   */
  
  public abstract class SqlTagSupport extends TagSupport implements SQLExecutionTag {
  
      protected String var;
      protected String scope = "page";
  
      /*
       * The following properties take expression values, so the
       * setter methods are implemented by the expression type
       * specific subclasses.
       */
      protected Object rawDataSource;
      protected boolean dataSourceSpecified;
      protected String sql;
  
      /*
       * Instance variables that are not for attributes
       */
      private List parameters;
      protected boolean isPartOfTransaction;
  
      //*********************************************************************
      // Constructor and initialization
  
      public SqlTagSupport() {
      }
  
      //*********************************************************************
      // Accessor methods
  
      /**
       * Sets the name of the variable to hold the
       * result.
       */
      public void setVar(String var) {
          this.var = var;
      }
  
      /**
       * Sets the scope of the variable to hold the
       * result.
       */
      public void setScope(String scopeName) {
          this.scope = scopeName;
      }
  
      /**
       * Sets the SQL DataSource. DataSource can be
       * a String or a DataSource object.
       */
      public void setDataSource(Object dataSource) {
          this.rawDataSource = dataSource;
          this.dataSourceSpecified = true;
      }
  
      /**
       * Sets the SQL statement to use for the
       * query. The statement may contain parameter markers
       * (question marks, ?). If so, the parameter values must
       * be set using nested value elements.
       */
      public void setSql(String sql) {
          this.sql = sql;
      }    
      
  
      //*********************************************************************
      // Public utility methods
  
      /**
       * Called by nested parameter elements to add PreparedStatement
       * parameter values.
       */
      public void addSQLParameter(Object o) {
          if (parameters == null) {
              parameters = new ArrayList();
          }
          parameters.add(o);
      }
  
      //*********************************************************************
      // Protected utility methods
  
      /**
       * @return true if there are SQL parameters
       */
      protected boolean hasParameters() {
          return parameters != null && parameters.size() > 0;
      }
      
      protected void clearParameters() {
          parameters = null;
      }
  
      protected Connection getConnection() throws JellyException, SQLException {
          // Fix: Add all other mechanisms
          Connection conn = null;
          isPartOfTransaction = false;
  
          TransactionTag parent =
              (TransactionTag) findAncestorWithClass(TransactionTag.class);
          if (parent != null) {
              if (dataSourceSpecified) {
                  throw new JellyException(Resources.getMessage("ERROR_NESTED_DATASOURCE"));
              }
              conn = parent.getSharedConnection();
              isPartOfTransaction = true;
          }
          else {
              if ((rawDataSource == null) && dataSourceSpecified) {
                  throw new JellyException(Resources.getMessage("SQL_DATASOURCE_NULL"));
              }
              DataSource dataSource = DataSourceUtil.getDataSource(rawDataSource, context);
              try {
                  conn = dataSource.getConnection();
              }
              catch (Exception ex) {
                  throw new JellyException(
                      Resources.getMessage("DATASOURCE_INVALID", ex.getMessage()));
              }
          }
  
          return conn;
      }
  
      protected void setParameters(PreparedStatement ps)
          throws SQLException {
          if (parameters != null) {
              for (int i = 0; i < parameters.size(); i++) {
                  // The first parameter has index 1
                  ps.setObject(i + 1, parameters.get(i));
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/ResultImpl.java
  
  Index: ResultImpl.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */ 
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.*;
  import java.util.*;
  import javax.servlet.jsp.jstl.sql.Result;
  
  /**
   * <p>This class creates a cached version of a <tt>ResultSet</tt>.
   * It's represented as a <tt>Result</tt> implementation, capable of 
   * returing an array of <tt>Row</tt> objects containing a <tt>Column</tt> 
   * instance for each column in the row.</p>
   *
   * <p>Note -- this is a private copy for the RI to avoid making the
   * corresponding class in javax.servlet.* public.</p>
   *
   * @author Hans Bergsten
   * @author Justyna Horwat
   */
  
  public class ResultImpl implements Result {
      private List rowMap;
      private List rowByIndex;
      private String[] columnNames;
      private boolean isLimited;
  
      /**
       * This constructor reads the ResultSet and saves a cached
       * copy.
       *
       * @param rs an open <tt>ResultSet</tt>, positioned before the first
       * row
       * @param startRow, beginning row to be cached
       * @param maxRows, query maximum rows limit
       * @exception if a database error occurs
       */
      public ResultImpl(ResultSet rs, int startRow, int maxRows)
          throws SQLException {
              
          rowMap = new ArrayList();
          rowByIndex = new ArrayList();
  
          ResultSetMetaData rsmd = rs.getMetaData();
          int noOfColumns = rsmd.getColumnCount();
  
          // Create the column name array
          columnNames = new String[noOfColumns];
          for (int i = 1; i <= noOfColumns; i++) {
              columnNames[i-1] = rsmd.getColumnName(i);
          }
  
          // Throw away all rows upto startRow
          for (int i = 0; i < startRow; i++) {
              rs.next();
          }
  
          // Process the remaining rows upto maxRows
          int processedRows = 0;
          while (rs.next()) {
              if ((maxRows != -1) && (processedRows == maxRows)) {
                  isLimited = true; 
                  break;
              }
              Object[] columns = new Object[noOfColumns];
              SortedMap columnMap = 
                  new TreeMap(String.CASE_INSENSITIVE_ORDER);
  
              // JDBC uses 1 as the lowest index!
              for (int i = 1; i <= noOfColumns; i++) {
                  Object value =  rs.getObject(i);
                  if (rs.wasNull()) {
                      value = null;
                  }
                  columns[i-1] = value;
                  columnMap.put(columnNames[i-1], value);
              }
              rowMap.add(columnMap);
              rowByIndex.add(columns);
              processedRows++;
          }
      }
  
      /**
       * This constructor is given a List of Maps where each Map represents a Row of data.
       * This constructor is typically used to create a Mock Object representing a result set.
       *
       * @param listOfMaps is a list of Maps where a Map represents a Row keyed by the column name
       */
      public ResultImpl(List listOfMaps) {
              
          rowMap = new ArrayList();
          rowByIndex = new ArrayList();
          isLimited = false;
  
          // lets build up a Set of all the unique column names
          HashSet keySet = new HashSet();
          for (Iterator iter = listOfMaps.iterator(); iter.hasNext(); ) {
              Map row = (Map) iter.next();
              keySet.addAll( row.keySet() );
          }
          
          // Create the column name array
          int noOfColumns = keySet.size();
          columnNames = new String[noOfColumns];        
          int i = 0;
          for (Iterator iter = keySet.iterator(); iter.hasNext(); i++ ) {
              columnNames[i] = (String) iter.next();
          }
          
          // Now add each row to the result set
          for (Iterator iter = listOfMaps.iterator(); iter.hasNext(); ) {
              Map row = (Map) iter.next();
              
              Object[] columns = new Object[noOfColumns];
              SortedMap columnMap = 
                  new TreeMap(String.CASE_INSENSITIVE_ORDER);
  
              for (i = 0; i < noOfColumns; i++) {
                  String columnName = columnNames[i];
                  Object value = row.get(columnName);
                  columns[i] = value;
                  columnMap.put(columnName, value);
              }
              rowMap.add(columnMap);
              rowByIndex.add(columns);
          }
      }
  
      /**
       * Returns an array of SortedMap objects. The SortedMap
       * object key is the ColumnName and the value is the ColumnValue.
       * SortedMap was created using the CASE_INSENSITIVE_ORDER
       * Comparator so the key is the case insensitive representation
       * of the ColumnName.
       *
       * @return an array of Map, or null if there are no rows
       */
      public SortedMap[] getRows() {
          if (rowMap == null) {
              return null;
          }
  
          //should just be able to return SortedMap[] object
          return (SortedMap []) rowMap.toArray(new SortedMap[0]);
      }
  
  
      /**
       * Returns an array of Object[] objects. The first index
       * designates the Row, the second the Column. The array
       * stores the value at the specified row and column.
       *
       * @return an array of Object[], or null if there are no rows
       */
      public Object[][] getRowsByIndex() {
          if (rowByIndex == null) {
              return null;
          }
  
          //should just be able to return Object[][] object
          return (Object [][])rowByIndex.toArray(new Object[0][0]);
      }
  
      /**
       * Returns an array of String objects. The array represents
       * the names of the columns arranged in the same order as in
       * the getRowsByIndex() method.
       *
       * @return an array of String[]
       */
      public String[] getColumnNames() {
          return columnNames;
      }
  
      /**
       * Returns the number of rows in the cached ResultSet
       *
       * @return the number of cached rows, or -1 if the Result could
       *    not be initialized due to SQLExceptions
       */
      public int getRowCount() {
          if (rowMap == null) {
              return -1;
          }
          return rowMap.size();
      }
  
      /**
       * Returns true of the query was limited by a maximum row setting
       *
       * @return true if the query was limited by a MaxRows attribute
       */
      public boolean isLimitedByMaxRows() {
          return isLimited;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/SqlTagLibrary.java
  
  Index: SqlTagLibrary.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/SqlTagLibrary.java,v 1.1 2003/01/07 13:47:05 dion Exp $
   * $Revision: 1.1 $
   * $Date: 2003/01/07 13:47:05 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id: SqlTagLibrary.java,v 1.1 2003/01/07 13:47:05 dion Exp $
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import org.apache.commons.jelly.tags.core.CoreTagLibrary;
  
  /** Describes the Taglib. This class could be generated by XDoclet
    *
    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
    * @version $Revision: 1.1 $
    */
  
  public class SqlTagLibrary extends CoreTagLibrary {
  
      public SqlTagLibrary() {
          registerTag("driver", DriverTag.class);
          registerTag("param", ParamTag.class);
          registerTag("query", QueryTag.class);
          registerTag("setDataSource", SetDataSourceTag.class);
          registerTag("transaction", TransactionTag.class);
          registerTag("update", UpdateTag.class);
          
          // extension tags for Mock Tags support
          registerTag("resultSet", ResultSetTag.class);
          registerTag("row", RowTag.class);
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/ResultSetTag.java
  
  Index: ResultSetTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.jelly.tags.sql;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.jelly.MissingAttributeException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * This Tag creates a result set object based on its body content via child row tags. 
   * This tag is useful for unit testing with Mock Tags to simulate the results returned by databases.
   * 
   */
  public class ResultSetTag extends TagSupport {
      
      private List rows;
      private String var;
      
      /** 
       * Adds the given row to the list of rows
       */
      public void addRow(Map row) {
          rows.add(row);
      }                    
      
      // Tag interface
      //------------------------------------------------------------------------- 
      public void doTag(XMLOutput output) throws Exception {
          if (var == null) {
              throw new MissingAttributeException( "var" );
          }
          rows = new ArrayList();
          invokeBody(output);
          
          // now lets create a new Result implementation
          ResultImpl results = new ResultImpl( rows );
          context.setVariable(var, results);
          rows = null;
      }
      
      // Properties
      //------------------------------------------------------------------------- 
      /**
       * Sets the variable to export the result set to.
       */
      public void setVar(String var) {
          this.var = var;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/QueryTag.java
  
  Index: QueryTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.jelly.tags.sql;
  
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  
  import javax.servlet.jsp.jstl.sql.Result;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  
  /**
   * <p>Tag handler for &lt;Query&gt; in JSTL.  
   * 
   * @author Hans Bergsten
   * @author Justyna Horwat
   */
  
  public class QueryTag extends SqlTagSupport {
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(QueryTag.class);
  
      /*
       * The following properties take expression values, so the
       * setter methods are implemented by the expression type
       * specific subclasses.
       */
      protected int maxRows = -1;
      protected boolean maxRowsSpecified;
      protected int startRow;
  
      /*
       * Instance variables that are not for attributes
       */
      private Connection conn;
  
      //*********************************************************************
      // Constructor and initialization
  
      public QueryTag() {
      }
  
      //*********************************************************************
      // Accessor methods
  
      /**
       * The index of the first row returned can be
       * specified using startRow.
       */
      public void setStartRow(int startRow) {
          this.startRow = startRow;
      }
  
      /**
       * Query result can be limited by specifying
       * the maximum number of rows returned.
       */
      public void setMaxRows(int maxRows) {
          this.maxRows = maxRows;
          this.maxRowsSpecified = true;
      }
  
      //*********************************************************************
      // Tag logic
  
      /**
       * <p>Execute the SQL statement, set either through the <code>sql</code>
       * attribute or as the body, and save the result as a variable
       * named by the <code>var</code> attribute in the scope specified
       * by the <code>scope</code> attribute, as an object that implements
       * the Result interface.
       *
       * <p>The connection used to execute the statement comes either
       * from the <code>DataSource</code> specified by the
       * <code>dataSource</code> attribute, provided by a parent action
       * element, or is retrieved from a JSP scope  attribute
       * named <code>javax.servlet.jstl.sql.dataSource</code>.
       */
      public void doTag(XMLOutput output) throws Exception {
  
          if (!maxRowsSpecified) {
              Object obj = context.getVariable("org.apache.commons.jelly.sql.maxRows");
              if (obj != null) {
                  if (obj instanceof Integer) {
                      maxRows = ((Integer) obj).intValue();
                  }
                  else if (obj instanceof String) {
                      try {
                          maxRows = Integer.parseInt((String) obj);
                      }
                      catch (NumberFormatException nfe) {
                          throw new JellyException(
                              Resources.getMessage("SQL_MAXROWS_PARSE_ERROR", (String) obj),
                              nfe);
                      }
                  }
                  else {
                      throw new JellyException(Resources.getMessage("SQL_MAXROWS_INVALID"));
                  }
              }
          }
  
          Result result = null;
          String sqlStatement = null;
  
          log.debug( "About to lookup connection" );
          
          ResultSet rs = null;
          Statement statement = null;
          try {
              conn = getConnection();
  
              /*
               * Use the SQL statement specified by the sql attribute, if any,
               * otherwise use the body as the statement.
               */
              if (sql != null) {
                  sqlStatement = sql;
              }
              else {
                  sqlStatement = getBodyText();
              }
              if (sqlStatement == null || sqlStatement.trim().length() == 0) {
                  throw new JellyException(Resources.getMessage("SQL_NO_STATEMENT"));
              }
              /*
               * We shouldn't have a negative startRow or illegal maxrows
               */
              if ((startRow < 0) || (maxRows < -1)) {
                  throw new JellyException(Resources.getMessage("PARAM_BAD_VALUE"));
              }
  
              /* 
               * Note! We must not use the setMaxRows() method on the
               * the statement to limit the number of rows, since the
               * Result factory must be able to figure out the correct
               * value for isLimitedByMaxRows(); there's no way to check
               * if it was from the ResultSet.
               */
              if ( log.isDebugEnabled() ) {
                  log.debug( "About to execute query: " + sqlStatement );
              }
              
              if ( hasParameters() ) {
                  PreparedStatement ps = conn.prepareStatement(sqlStatement);
                  statement = ps;
                  setParameters(ps);            
                  rs = ps.executeQuery();
              }
              else {
                  statement = conn.createStatement();
                  rs = statement.executeQuery(sqlStatement);
              }
              
              result = new ResultImpl(rs, startRow, maxRows);
              context.setVariable(var, result);
              
              // always close the result set first since it may be closed by 
              // JDBC 3 when closing statements 
              
              // lets nullify before we close in case we get exceptions
              // while closing, we don't want to try to close again
              ResultSet tempRs = rs;
              rs = null;
              tempRs.close();
              Statement tempStatement = statement;
              statement = null;
              tempStatement.close();
          }
          catch (SQLException e) {
              throw new JellyException(sqlStatement + ": " + e.getMessage(), e);
          }
          finally {
              if (rs != null) {
                  try {
                      rs.close();
                  }
                  catch (SQLException e) {
                      log.error("Caught exception while closing result set: " + e, e);
                  } 
              }
              if (statement != null) {
                  try {
                      statement.close();
                  }
                  catch (SQLException e) {
                      log.error("Caught exception while closing statement: " + e, e);
                  }
              }
              if (conn != null && !isPartOfTransaction) {
                  try {
                      conn.close();
                  }
                  catch (SQLException e) {
                      log.error("Caught exception while closing connection: " + e, e);
                  }
                  conn = null;
              }
              clearParameters();
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/RowTag.java
  
  Index: RowTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.jelly.tags.sql;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.MapTagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * Adds a new row to a parent &lt;resultSet&gt; Tag. 
   * This tag is useful for unit testing with Mock Tags to simulate the results returned by databases.
   * 
   */
  public class RowTag extends MapTagSupport {
      
      // Tag interface
      //------------------------------------------------------------------------- 
      public void doTag(XMLOutput output) throws Exception {
          ResultSetTag tag = (ResultSetTag) findAncestorWithClass( ResultSetTag.class );
          if ( tag == null ) {
              throw new JellyException( "This tag must be nested with in a <resultSet> tag" );
          }
          tag.addRow( getAttributes() );
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/java/org/apache/commons/jelly/tags/sql/ParamTag.java
  
  Index: ParamTag.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.jelly.tags.sql;
  
  import javax.servlet.jsp.jstl.sql.SQLExecutionTag;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.tags.Resources;
  
  /**
   * <p>Tag handler for &lt;Param&gt; in JSTL, used to set
   * parameter values for a SQL statement.</p>
   * 
   * @author Hans Bergsten
   */
  
  public class ParamTag extends TagSupport {
      protected Object value;
  
      
      public void setValue(Object value) {
          this.value = value;
      }
      
      //*********************************************************************
      // Tag logic
  
      public void doTag(XMLOutput output) throws Exception {
          SQLExecutionTag parent =
              (SQLExecutionTag) findAncestorWithClass(this, SQLExecutionTag.class);
          if (parent == null) {
              throw new JellyException(Resources.getMessage("SQL_PARAM_OUTSIDE_PARENT"));
          }
  
          Object paramValue = value;
          if (value != null) {
              paramValue = value;
          }
          else {
              String bodyContent = getBodyText();
              if (bodyContent != null) {
                  bodyContent = bodyContent.trim();
                  if (bodyContent.length() > 0) {
                      paramValue = bodyContent;
                  }
              }
          }
  
          parent.addSQLParameter(paramValue);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/TestJUnit.java
  
  Index: TestJUnit.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/TestJUnit.java,v 1.1 2003/01/07 13:47:09 dion Exp $
   * $Revision: 1.1 $
   * $Date: 2003/01/07 13:47:09 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id: TestJUnit.java,v 1.1 2003/01/07 13:47:09 dion Exp $
   */
  package org.apache.commons.jelly.tags.sql;
  
  import junit.framework.TestSuite;
  import junit.textui.TestRunner;
  
  import org.apache.commons.jelly.tags.junit.JellyTestSuite;
  
  /** 
   * A helper class to run jelly test cases as part of Ant's JUnit tests
   *
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
   * @version $Revision: 1.1 $
   */
  public class TestJUnit extends JellyTestSuite {
  
      public static void main( String[] args ) throws Exception {
          TestRunner.run( suite() );
      }
      
      public static TestSuite suite() throws Exception {
          return createTestSuite(TestJUnit.class, "suite.jelly");        
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/example.jelly
  
  Index: example.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <j:jelly xmlns:j="jelly:core" xmlns:sql="jelly:sql">
  
    <sql:setDataSource 
      url="${databaseUrl}" 
      driver="${databaseDriver}" 
      user="${databaseUser}"
      password="${databasePassword}"/>
  
    <sql:query var="results">
        select * from ${databaseTable}
    </sql:query>
  
    <dataSet>
  
      <j:forEach items="${results.rowsByIndex}" var="row">
        <row>
          <j:forEach var="columnName" items="${results.columnNames}" indexVar="i">
            <field column="${columnName}">${row[i]}</field>                                
          </j:forEach>
        </row>
      </j:forEach>                  
  
    </dataSet>
  
  </j:jelly>
  
  
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/example3.jelly
  
  Index: example3.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <j:jelly xmlns:j="jelly:core" xmlns:sql="jelly:sql" xmlns:log="jelly:log">
  
    <sql:setDataSource 
      url="${databaseUrl}" 
      driver="${databaseDriver}" 
      user="${databaseUser}"
      password="${databasePassword}"/>
  
    <j:set var="databaseTable" value="dummy"/>
  
  
    <log:info>Dropping and recreating the table ${databaseTable}...</log:info>
    
    <j:catch>
      <!-- ignore any exceptions -->
      <sql:update>
        drop table ${databaseTable}
      </sql:update>
    </j:catch>
    	
    <sql:update>
    	create table ${databaseTable} (
    	  id integer,
    	  name varchar(255)
    	)
    </sql:update>
  
  
    <log:info>Inserting some data...</log:info>
    
    <j:forEach begin="1" end="20" var="i">
      <sql:update>
        insert into ${databaseTable} (id, name) values (?, ?)
        <sql:param value="${i}"/>
        <sql:param value="Foo_${i}"/>
      </sql:update>
    
    </j:forEach>
    	
    <log:info>Now performing a query...</log:info>
    
    <sql:query var="results">
        select * from ${databaseTable}
    </sql:query>
  
    <dataSet>
  
      <!-- we'll turn off whitespace trimming for the loop -->
      <j:forEach trim="false" items="${results.rowsByIndex}" var="row">
        <row>
          <j:forEach var="columnName" items="${results.columnNames}" indexVar="i">
            <field column="${columnName}">${row[i]}</field>                                
          </j:forEach>
        </row>
      </j:forEach>                  
  
    </dataSet>
  
  </j:jelly>
  
  
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/example2.jelly
  
  Index: example2.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <j:jelly xmlns:j="jelly:core" xmlns:sql="jelly:sql">
  
    <sql:setDataSource 
    	var="db"
      url="${databaseUrl}" 
      driver="${databaseDriver}" 
      user="${databaseUser}"
      password="${databasePassword}"/>
  
    <sql:query var="results" dataSource="${db}">
        select * from ${databaseTable}
    </sql:query>
  
    <dataSet>
  
      <j:forEach var="columnName" items="${results.columnNames}" indexVar="i">
        <column>${columnName}</column>                                
      </j:forEach>
  
      <j:forEach items="${results.rowsByIndex}" var="row">
        <row>
          <j:forEach var="field" items="${row}">
            <field>${field}</field>                                
          </j:forEach>
        </row>
      </j:forEach>                  
    </dataSet>
  
  </j:jelly>
  
  
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/suite.jelly
  
  Index: suite.jelly
  ===================================================================
  <?xml version="1.0"?>
  <test:suite xmlns:j="jelly:core" xmlns:test="jelly:junit" xmlns:sql="jelly:sql">
  
  	<test:case name="testResultSet">
  	
  	  <sql:resultSet var="results">
  	    <sql:row id="abc" name="James"/>
  	    <sql:row id="def" name="Joe"/>
  	  </sql:resultSet>
  	
  		<test:assert test="${results != null}">created a results object</test:assert>		
  		
  		<test:assert test="${results.rowCount == 2}">contains 2 rows</test:assert>
  
  		<test:assertEquals expected="abc" actual="${results.rows[0].id}"/>
  		<test:assertEquals expected="def" actual="${results.rows[1].id}"/>
  		
  		<test:assertEquals expected="James" actual="${results.rows[0].name}"/>
  		<test:assertEquals expected="Joe" actual="${results.rows[1].name}"/>
  		
  	</test:case>
  
  </test:suite>
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/src/test/org/apache/commons/jelly/tags/sql/testSql.jelly
  
  Index: testSql.jelly
  ===================================================================
  <?xml version="1.0"?>
  <j:jelly xmlns:j="jelly:core" xmlns:sql="jelly:sql">
  
    <sql:setDataSource 
    	var="db"
      url="${databaseUrl}" 
      driver="${databaseDriver}" 
      user="${databaseUser}"
      password="${databasePassword}"/>
  
    <sql:query var="results" dataSource="${db}">
        select * from ${databaseTable}
    </sql:query>
  
    <dataSet>
      <size>${results.rowCount}</size>
    </dataSet>
  
  </j:jelly>
  
  
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  maven.log
  target
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/maven.xml
  
  Index: maven.xml
  ===================================================================
  <project default="java:jar">
  
  </project>
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/project.properties
  
  Index: project.properties
  ===================================================================
  # -------------------------------------------------------------------
  # P R O J E C T  P R O P E R T I E S
  # -------------------------------------------------------------------
  
  maven.junit.fork=true
  
  maven.compile.deprecation = on
  
  # Installation dir
  maven.dist.install.dir = /usr/local/jelly
  
  maven.checkstyle.properties=../tag-checkstyle.properties
  
  
  1.1                  jakarta-commons-sandbox/jelly/jelly-tags/sql/project.xml
  
  Index: project.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE project [
    <!-- see file for description -->
    <!ENTITY commonDeps SYSTEM "file:../../commonDependencies.ent">
  ]>
  <project>
    <extend>../tag-project.xml</extend>
    <id>commons-jelly-tags-sql</id>
    <name>commons-jelly-tags-sql</name>
    <package>org.apache.commons.jelly.tags.sql</package>
  
    <description>
        This is a Jelly interface for SQL.
    </description>
    <shortDescription>Commons Jelly SQL Tag Library</shortDescription>
    
    <siteDirectory>/www/jakarta.apache.org/commons/sandbox/jelly/tags/sql</siteDirectory>
    <distributionDirectory>/www/jakarta.apache.org/builds/jakarta-commons-sandbox/jelly/tags/sql</distributionDirectory>
    <repository>
      <connection>scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons-sandbox/jelly/jelly-tags/sql/</connection>
      <url>http://cvs.apache.org/viewcvs/jakarta-commons-sandbox/jelly/jelly-tags/sql/</url>
    </repository>
    
      
    <dependencies>
    
      &commonDeps;
    
      <!-- START for compilation -->
    
      <dependency>
        <id>commons-jelly</id>
        <version>SNAPSHOT</version>
      </dependency>
    
      <dependency>
        <id>jdbc</id>
        <version>2.0</version>
      </dependency>
  
    </dependencies>
    
  </project>
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message