Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 487   Methods: 24
NCLOC: 193   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JDBCTask.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs;
 56   
 
 57   
 import java.sql.Connection;
 58   
 import java.sql.DatabaseMetaData;
 59   
 import java.sql.Driver;
 60   
 import java.sql.SQLException;
 61   
 import java.util.Hashtable;
 62   
 import java.util.Properties;
 63   
 import org.apache.tools.ant.AntClassLoader;
 64   
 import org.apache.tools.ant.BuildException;
 65   
 import org.apache.tools.ant.Project;
 66   
 import org.apache.tools.ant.Task;
 67   
 import org.apache.tools.ant.types.Path;
 68   
 import org.apache.tools.ant.types.Reference;
 69   
 
 70   
 /**
 71   
  * Handles JDBC configuration needed by SQL type tasks.
 72   
  * <p>
 73   
  * The following example class prints the contents of the first column of each row in TableName.
 74   
  *</p>
 75   
  *<code><pre>
 76   
 package examples;
 77   
 import java.sql.Connection;
 78   
 import java.sql.ResultSet;
 79   
 import java.sql.SQLException;
 80   
 import java.sql.Statement;
 81   
 
 82   
 import org.apache.tools.ant.BuildException;
 83   
 import org.apache.tools.ant.taskdefs.JDBCTask;
 84   
 
 85   
 public class SQLExampleTask extends JDBCTask {
 86   
 
 87   
     private String tableName;
 88   
 
 89   
     public void execute() throws BuildException {
 90   
         Connection conn = getConnection();
 91   
         Statement stmt=null;
 92   
         try {
 93   
             if (tableName == null ) {
 94   
                 throw new BuildException("TableName must be specified",location);
 95   
             }
 96   
             String sql = "SELECT * FROM "+tableName;
 97   
             stmt= conn.createStatement();
 98   
             ResultSet rs = stmt.executeQuery(sql);
 99   
             while (rs.next()) {
 100   
                 log(rs.getObject(1).toString());
 101   
             }
 102   
         } catch (SQLException e) {
 103   
 
 104   
         } finally {
 105   
             if (stmt != null) {
 106   
                 try {stmt.close();}catch (SQLException ingore){}
 107   
             }
 108   
             if (conn != null) {
 109   
                 try {conn.close();}catch (SQLException ingore){}
 110   
             }
 111   
         }
 112   
     }
 113   
     public void setTableName(String tableName) {
 114   
         this.tableName = tableName;
 115   
     }
 116   
 
 117   
 }
 118   
 
 119   
 
 120   
 </pre></code>
 121   
 
 122   
 
 123   
  * @author <a href="mailto:nick@chalko.com">Nick Chalko</a>
 124   
  * @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a>
 125   
  * @author <A href="mailto:gholam@xtra.co.nz">Michael McCallum</A>
 126   
  * @author <A href="mailto:tim.stephenson@sybase.com">Tim Stephenson</A>
 127   
  *
 128   
  * @since Ant 1.5
 129   
  *
 130   
  */
 131   
 
 132   
 public abstract class JDBCTask extends Task {
 133   
 
 134   
 
 135   
     /**
 136   
      * Used for caching loaders / driver. This is to avoid
 137   
      * getting an OutOfMemoryError when calling this task
 138   
      * multiple times in a row.
 139   
      */
 140   
     private static Hashtable loaderMap = new Hashtable(3);
 141   
 
 142   
     private boolean caching = true;
 143   
 
 144   
     private Path classpath;
 145   
 
 146   
     private AntClassLoader loader;
 147   
 
 148   
     /**
 149   
      * Autocommit flag. Default value is false
 150   
      */
 151   
     private boolean autocommit = false;
 152   
 
 153   
     /**
 154   
      * DB driver.
 155   
      */
 156   
     private String driver = null;
 157   
 
 158   
     /**
 159   
      * DB url.
 160   
      */
 161   
     private String url = null;
 162   
 
 163   
     /**
 164   
      * User name.
 165   
      */
 166   
     private String userId = null;
 167   
 
 168   
     /**
 169   
      * Password
 170   
      */
 171   
     private String password = null;
 172   
 
 173   
     /**
 174   
      * RDBMS Product needed for this SQL.
 175   
      **/
 176   
     private String rdbms = null;
 177   
 
 178   
     /**
 179   
      * RDBMS Version needed for this SQL.
 180   
      **/
 181   
     private String version = null;
 182   
 
 183   
     /**
 184   
      * Sets the classpath for loading the driver.
 185   
      * @param classpath The classpath to set
 186   
      */
 187  0
     public void setClasspath(Path classpath) {
 188  0
         this.classpath = classpath;
 189   
     }
 190   
 
 191   
     /**
 192   
      * Caching loaders / driver. This is to avoid
 193   
      * getting an OutOfMemoryError when calling this task
 194   
      * multiple times in a row; default: true
 195   
      * @param enable
 196   
      */
 197  0
     public void setCaching(boolean enable) {
 198  0
         caching = enable;
 199   
     }
 200   
 
 201   
     /**
 202   
      * Add a path to the classpath for loading the driver.
 203   
      */
 204  0
     public Path createClasspath() {
 205  0
         if (this.classpath == null) {
 206  0
             this.classpath = new Path(getProject());
 207   
         }
 208  0
         return this.classpath.createPath();
 209   
     }
 210   
 
 211   
     /**
 212   
      * Set the classpath for loading the driver
 213   
      * using the classpath reference.
 214   
      */
 215  0
     public void setClasspathRef(Reference r) {
 216  0
         createClasspath().setRefid(r);
 217   
     }
 218   
 
 219   
     /**
 220   
      * Class name of the JDBC driver; required.
 221   
      * @param driver The driver to set
 222   
      */
 223  0
     public void setDriver(String driver) {
 224  0
         this.driver = driver;
 225   
     }
 226   
 
 227   
     /**
 228   
      * Sets the database connection URL; required.
 229   
      * @param url The url to set
 230   
      */
 231  0
     public void setUrl(String url) {
 232  0
         this.url = url;
 233   
     }
 234   
 
 235   
     /**
 236   
      * Sets the password; required.
 237   
      * @param password The password to set
 238   
      */
 239  0
     public void setPassword(String password) {
 240  0
         this.password = password;
 241   
     }
 242   
 
 243   
     /**
 244   
      * Auto commit flag for database connection;
 245   
      * optional, default false.
 246   
      * @param autocommit The autocommit to set
 247   
      */
 248  0
     public void setAutocommit(boolean autocommit) {
 249  0
         this.autocommit = autocommit;
 250   
     }
 251   
 
 252   
     /**
 253   
      * Execute task only if the lower case product name
 254   
      * of the DB matches this
 255   
      * @param rdbms The rdbms to set
 256   
      */
 257  0
     public void setRdbms(String rdbms) {
 258  0
         this.rdbms = rdbms;
 259   
     }
 260   
 
 261   
     /**
 262   
      * Sets the version string, execute task only if
 263   
      * rdbms version match; optional.
 264   
      * @param version The version to set
 265   
      */
 266  0
     public void setVersion(String version) {
 267  0
         this.version = version;
 268   
     }
 269   
 
 270   
     /**
 271   
      * Verify we are connected to the correct RDBMS
 272   
      */
 273  0
     protected boolean isValidRdbms(Connection conn) {
 274  0
         if (rdbms == null && version == null) {
 275  0
             return true;
 276   
         }
 277   
 
 278  0
         try {
 279  0
             DatabaseMetaData dmd = conn.getMetaData();
 280   
 
 281  0
             if (rdbms != null) {
 282  0
                 String theVendor = dmd.getDatabaseProductName().toLowerCase();
 283   
 
 284  0
                 log("RDBMS = " + theVendor, Project.MSG_VERBOSE);
 285  0
                 if (theVendor == null || theVendor.indexOf(rdbms) < 0) {
 286  0
                     log("Not the required RDBMS: " + rdbms, Project.MSG_VERBOSE);
 287  0
                     return false;
 288   
                 }
 289   
             }
 290   
 
 291  0
             if (version != null) {
 292   
                 // XXX maybe better toLowerCase(Locale.US)
 293  0
                 String theVersion = dmd.getDatabaseProductVersion().toLowerCase();
 294   
 
 295  0
                 log("Version = " + theVersion, Project.MSG_VERBOSE);
 296  0
                 if (theVersion == null
 297   
                         || !(theVersion.startsWith(version) || theVersion.indexOf(" " + version) >= 0)) {
 298  0
                     log("Not the required version: \"" + version + "\"", Project.MSG_VERBOSE);
 299  0
                     return false;
 300   
                 }
 301   
             }
 302   
         } catch (SQLException e) {
 303   
             // Could not get the required information
 304  0
             log("Failed to obtain required RDBMS information", Project.MSG_ERR);
 305  0
             return false;
 306   
         }
 307   
 
 308  0
         return true;
 309   
     }
 310   
 
 311  0
     protected static Hashtable getLoaderMap() {
 312  0
         return loaderMap;
 313   
     }
 314   
 
 315  0
     protected AntClassLoader getLoader() {
 316  0
         return loader;
 317   
     }
 318   
 
 319   
     /**
 320   
      * Creates a new Connection as using the driver, url, userid and password specified.
 321   
      * The calling method is responsible for closing the connection.
 322   
      * @return Connection the newly created connection.
 323   
      * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load.
 324   
      */
 325  0
     protected Connection getConnection() throws BuildException {
 326  0
         if (userId == null) {
 327  0
             throw new BuildException("User Id attribute must be set!", getLocation());
 328   
         }
 329  0
         if (password == null) {
 330  0
             throw new BuildException("Password attribute must be set!", getLocation());
 331   
         }
 332  0
         if (url == null) {
 333  0
             throw new BuildException("Url attribute must be set!", getLocation());
 334   
         }
 335  0
         try {
 336   
 
 337  0
             log("connecting to " + getUrl(), Project.MSG_VERBOSE);
 338  0
             Properties info = new Properties();
 339  0
             info.put("user", getUserId());
 340  0
             info.put("password", getPassword());
 341  0
             Connection conn = getDriver().connect(getUrl(), info);
 342   
 
 343  0
             if (conn == null) {
 344   
                 // Driver doesn't understand the URL
 345  0
                 throw new SQLException("No suitable Driver for " + url);
 346   
             }
 347   
 
 348  0
             conn.setAutoCommit(autocommit);
 349  0
             return conn;
 350   
         } catch (SQLException e) {
 351  0
             throw new BuildException(e, getLocation());
 352   
         }
 353   
 
 354   
     }
 355   
 
 356   
     /**
 357   
      * Gets an instance of the required driver.
 358   
      * Uses the ant class loader and the optionally the provided classpath.
 359   
      * @return Driver
 360   
      * @throws BuildException
 361   
      */
 362  0
     private Driver getDriver() throws BuildException {
 363  0
         if (driver == null) {
 364  0
             throw new BuildException("Driver attribute must be set!", getLocation());
 365   
         }
 366   
 
 367  0
         Driver driverInstance = null;
 368  0
         try {
 369  0
             Class dc;
 370  0
             if (classpath != null) {
 371   
                 // check first that it is not already loaded otherwise
 372   
                 // consecutive runs seems to end into an OutOfMemoryError
 373   
                 // or it fails when there is a native library to load
 374   
                 // several times.
 375   
                 // this is far from being perfect but should work
 376   
                 // in most cases.
 377  0
                 synchronized (loaderMap) {
 378  0
                     if (caching) {
 379  0
                         loader = (AntClassLoader) loaderMap.get(driver);
 380   
                     }
 381  0
                     if (loader == null) {
 382  0
                         log(
 383   
                                 "Loading " + driver + " using AntClassLoader with classpath " + classpath,
 384   
                                 Project.MSG_VERBOSE);
 385  0
                         loader = getProject().createClassLoader(classpath);
 386  0
                         if (caching) {
 387  0
                             loaderMap.put(driver, loader);
 388   
                         }
 389   
                     } else {
 390  0
                         log(
 391   
                                 "Loading " + driver + " using a cached AntClassLoader.",
 392   
                                 Project.MSG_VERBOSE);
 393   
                     }
 394   
                 }
 395  0
                 dc = loader.loadClass(driver);
 396   
             } else {
 397  0
                 log("Loading " + driver + " using system loader.", Project.MSG_VERBOSE);
 398  0
                 dc = Class.forName(driver);
 399   
             }
 400  0
             driverInstance = (Driver) dc.newInstance();
 401   
         } catch (ClassNotFoundException e) {
 402  0
             throw new BuildException(
 403   
                     "Class Not Found: JDBC driver " + driver + " could not be loaded",
 404   
                     getLocation());
 405   
         } catch (IllegalAccessException e) {
 406  0
             throw new BuildException(
 407   
                     "Illegal Access: JDBC driver " + driver + " could not be loaded",
 408   
                     getLocation());
 409   
         } catch (InstantiationException e) {
 410  0
             throw new BuildException(
 411   
                     "Instantiation Exception: JDBC driver " + driver + " could not be loaded",
 412   
                     getLocation());
 413   
         }
 414  0
         return driverInstance;
 415   
     }
 416   
 
 417   
 
 418  0
     public void isCaching(boolean value) {
 419  0
         caching = value;
 420   
     }
 421   
 
 422   
     /**
 423   
      * Gets the classpath.
 424   
      * @return Returns a Path
 425   
      */
 426  0
     public Path getClasspath() {
 427  0
         return classpath;
 428   
     }
 429   
 
 430   
     /**
 431   
      * Gets the autocommit.
 432   
      * @return Returns a boolean
 433   
      */
 434  0
     public boolean isAutocommit() {
 435  0
         return autocommit;
 436   
     }
 437   
 
 438   
     /**
 439   
      * Gets the url.
 440   
      * @return Returns a String
 441   
      */
 442  0
     public String getUrl() {
 443  0
         return url;
 444   
     }
 445   
 
 446   
     /**
 447   
      * Gets the userId.
 448   
      * @return Returns a String
 449   
      */
 450  0
     public String getUserId() {
 451  0
         return userId;
 452   
     }
 453   
 
 454   
     /**
 455   
      * Set the user name for the connection; required.
 456   
      * @param userId The userId to set
 457   
      */
 458  0
     public void setUserid(String userId) {
 459  0
         this.userId = userId;
 460   
     }
 461   
 
 462   
     /**
 463   
      * Gets the password.
 464   
      * @return Returns a String
 465   
      */
 466  0
     public String getPassword() {
 467  0
         return password;
 468   
     }
 469   
 
 470   
     /**
 471   
      * Gets the rdbms.
 472   
      * @return Returns a String
 473   
      */
 474  0
     public String getRdbms() {
 475  0
         return rdbms;
 476   
     }
 477   
 
 478   
     /**
 479   
      * Gets the version.
 480   
      * @return Returns a String
 481   
      */
 482  0
     public String getVersion() {
 483  0
         return version;
 484   
     }
 485   
 
 486   
 }
 487