diff --git a/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java b/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
new file mode 100644
index 000000000..7ef8fe7b1
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
@@ -0,0 +1,440 @@
+/*
+ * 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", "Ant", 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.util.Hashtable;
+import java.util.Properties;
+
+/**
+ * Handles JDBC configuration needed by SQL type tasks.
+ *
+ * @author Nick Chalko
+ * @author Jeff Martin
+ * @author Michael McCallum
+ * @author Tim Stephenson
+ *
+ * @since Ant 1.5
+ *
+ */
+
+public abstract class JDBCTask extends Task {
+
+
+ /**
+ * Used for caching loaders / driver. This is to avoid
+ * getting an OutOfMemoryError when calling this task
+ * multiple times in a row.
+ */
+ private static Hashtable loaderMap = new Hashtable(3);
+
+ private boolean caching = true;
+
+ private Path classpath;
+
+ private AntClassLoader loader;
+
+ /**
+ * Autocommit flag. Default value is false
+ */
+ private boolean autocommit = false;
+
+ /**
+ * DB driver.
+ */
+ private String driver = null;
+
+ /**
+ * DB url.
+ */
+ private String url = null;
+
+ /**
+ * User name.
+ */
+ private String userId = null;
+
+ /**
+ * Password
+ */
+ private String password = null;
+
+ /**
+ * RDBMS Product needed for this SQL.
+ **/
+ private String rdbms = null;
+
+ /**
+ * RDBMS Version needed for this SQL.
+ **/
+ private String version = null;
+
+ /**
+ * Sets the classpath.
+ * @param classpath The classpath to set
+ */
+ public void setClasspath(Path classpath) {
+ this.classpath = classpath;
+ }
+
+ /**
+ * Caching loaders / driver. This is to avoid
+ * getting an OutOfMemoryError when calling this task
+ * multiple times in a row.
+ * @param enable
+ */
+ public void setCaching(boolean enable) {
+ caching = enable;
+ }
+
+ /**
+ * Create the classpath for loading the driver.
+ */
+ public Path createClasspath() {
+ if (this.classpath == null) {
+ this.classpath = new Path(project);
+ }
+ return this.classpath.createPath();
+ }
+
+ /**
+ * Set the classpath for loading the driver using the classpath reference.
+ */
+ public void setClasspathRef(Reference r) {
+ createClasspath().setRefid(r);
+ }
+
+ /**
+ * Sets the driver.
+ * @param driver The driver to set
+ */
+ public void setDriver(String driver) {
+ this.driver = driver;
+ }
+
+ /**
+ * Sets the url.
+ * @param url The url to set
+ */
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ /**
+ * Set the user name for the DB connection.
+ */
+ public void setUserid(String userId) {
+ this.userId = userId;
+ }
+
+ /**
+ * Sets the password.
+ * @param password The password to set
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ /**
+ * Sets the autocommit.
+ * @param autocommit The autocommit to set
+ */
+ public void setAutocommit(boolean autocommit) {
+ this.autocommit = autocommit;
+ }
+
+ /**
+ * Sets the rdbms.
+ * @param rdbms The rdbms to set
+ */
+ public void setRdbms(String rdbms) {
+ this.rdbms = rdbms;
+ }
+
+ /**
+ * Sets the version.
+ * @param version The version to set
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ /**
+ * Verify if connected to the correct RDBMS
+ **/
+ protected boolean isValidRdbms(Connection conn) {
+ if (rdbms == null && version == null) {
+ return true;
+ }
+
+ try {
+ DatabaseMetaData dmd = conn.getMetaData();
+
+ if (rdbms != null) {
+ String theVendor = dmd.getDatabaseProductName().toLowerCase();
+
+ log("RDBMS = " + theVendor, Project.MSG_VERBOSE);
+ if (theVendor == null || theVendor.indexOf(rdbms) < 0) {
+ log("Not the required RDBMS: " + rdbms, Project.MSG_VERBOSE);
+ return false;
+ }
+ }
+
+ if (version != null) {
+ // XXX maybe better toLowerCase(Locale.US)
+ String theVersion = dmd.getDatabaseProductVersion().toLowerCase();
+
+ log("Version = " + theVersion, Project.MSG_VERBOSE);
+ if (theVersion == null
+ || !(theVersion.startsWith(version) || theVersion.indexOf(" " + version) >= 0)) {
+ log("Not the required version: \"" + version + "\"", Project.MSG_VERBOSE);
+ return false;
+ }
+ }
+ } catch (SQLException e) {
+ // Could not get the required information
+ log("Failed to obtain required RDBMS information", Project.MSG_ERR);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected static Hashtable getLoaderMap() {
+ return loaderMap;
+ }
+
+ protected AntClassLoader getLoader() {
+ return loader;
+ }
+
+ /**
+ * Creates a new Connection as using the driver, url, userid and password specified.
+ * The calling method is responsible for closing the connection.
+ * @return Connection the newly created connection.
+ * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load.
+ */
+ protected Connection getConnection() throws BuildException {
+ if (userId == null) {
+ throw new BuildException("User Id attribute must be set!", location);
+ }
+ if (password == null) {
+ throw new BuildException("Password attribute must be set!", location);
+ }
+ if (url == null) {
+ throw new BuildException("Url attribute must be set!", location);
+ }
+ try {
+
+ log("connecting to " + getUrl(), Project.MSG_VERBOSE);
+ Properties info = new Properties();
+ info.put("user", getUserId());
+ info.put("password", getPassword());
+ Connection conn = getDriver().connect(getUrl(), info);
+
+ if (conn == null) {
+ // Driver doesn't understand the URL
+ throw new SQLException("No suitable Driver for " + url);
+ }
+
+ conn.setAutoCommit(autocommit);
+ return conn;
+ } catch (SQLException e) {
+ throw new BuildException(e, location);
+ }
+
+ }
+
+ /**
+ * Gets an instance of the required driver.
+ * Uses the ant class loader and the optionally the provided classpath.
+ * @return Driver
+ * @throws BuildException
+ */
+ private Driver getDriver() throws BuildException {
+ if (driver == null) {
+ throw new BuildException("Driver attribute must be set!", location);
+ }
+
+ Driver driverInstance = null;
+ try {
+ Class dc;
+ if (classpath != null) {
+ // check first that it is not already loaded otherwise
+ // consecutive runs seems to end into an OutOfMemoryError
+ // or it fails when there is a native library to load
+ // several times.
+ // this is far from being perfect but should work
+ // in most cases.
+ synchronized (loaderMap) {
+ if (caching) {
+ loader = (AntClassLoader) loaderMap.get(driver);
+ }
+ if (loader == null) {
+ log(
+ "Loading " + driver + " using AntClassLoader with classpath " + classpath,
+ Project.MSG_VERBOSE);
+ loader = new AntClassLoader(project, classpath);
+ if (caching) {
+ loaderMap.put(driver, loader);
+ }
+ } else {
+ log(
+ "Loading " + driver + " using a cached AntClassLoader.",
+ Project.MSG_VERBOSE);
+ }
+ }
+ dc = loader.loadClass(driver);
+ } else {
+ log("Loading " + driver + " using system loader.", Project.MSG_VERBOSE);
+ dc = Class.forName(driver);
+ }
+ driverInstance = (Driver) dc.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new BuildException(
+ "Class Not Found: JDBC driver " + driver + " could not be loaded",
+ location);
+ } catch (IllegalAccessException e) {
+ throw new BuildException(
+ "Illegal Access: JDBC driver " + driver + " could not be loaded",
+ location);
+ } catch (InstantiationException e) {
+ throw new BuildException(
+ "Instantiation Exception: JDBC driver " + driver + " could not be loaded",
+ location);
+ }
+ return driverInstance;
+ }
+
+
+ public void isCaching(boolean value) {
+ caching = value;
+ }
+
+ /**
+ * Gets the classpath.
+ * @return Returns a Path
+ */
+ public Path getClasspath() {
+ return classpath;
+ }
+
+ /**
+ * Gets the autocommit.
+ * @return Returns a boolean
+ */
+ public boolean isAutocommit() {
+ return autocommit;
+ }
+
+ /**
+ * Gets the url.
+ * @return Returns a String
+ */
+ public String getUrl() {
+ return url;
+ }
+
+ /**
+ * Gets the userId.
+ * @return Returns a String
+ */
+ public String getUserId() {
+ return userId;
+ }
+
+ /**
+ * Sets the userId.
+ * @param userId The userId to set
+ */
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ /**
+ * Gets the password.
+ * @return Returns a String
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Gets the rdbms.
+ * @return Returns a String
+ */
+ public String getRdbms() {
+ return rdbms;
+ }
+
+ /**
+ * Gets the version.
+ * @return Returns a String
+ */
+ public String getVersion() {
+ return version;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
index 87a109ffc..baa2dd4bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
@@ -104,7 +104,7 @@ import java.sql.ResultSetMetaData;
*
* @ant.task name="sql" category="database"
*/
-public class SQLExec extends Task {
+public class SQLExec extends JDBCTask {
public static class DelimiterType extends EnumeratedAttribute {
public static final String NORMAL = "normal";
@@ -114,61 +114,30 @@ public class SQLExec extends Task {
}
}
- /**
- * Used for caching loaders / driver. This is to avoid
- * getting an OutOfMemoryError when calling this task
- * multiple times in a row.
- */
- private static Hashtable loaderMap = new Hashtable(3);
-
- // XXX - why is this public?
- public boolean caching = true;
-
+
+
private int goodSql = 0;
private int totalSql = 0;
- private Path classpath;
-
- private AntClassLoader loader;
-
- private Vector filesets = new Vector();
-
- /**
+ /**
* Database connection
*/
private Connection conn = null;
-
- /**
- * Autocommit flag. Default value is false
- */
- private boolean autocommit = false;
-
- /**
- * SQL statement
- */
- private Statement statement = null;
-
- /**
- * DB driver.
- */
- private String driver = null;
-
- /**
- * DB url.
- */
- private String url = null;
- /**
- * User name.
- */
- private String userId = null;
+ private Vector filesets = new Vector();
+
+
/**
- * Password
+ * SQL statement
*/
- private String password = null;
+ private Statement statement = null;
+
+
+
+
/**
* SQL input file
*/
@@ -210,16 +179,8 @@ public class SQLExec extends Task {
*/
private File output = null;
- /**
- * RDBMS Product needed for this SQL.
- **/
- private String rdbms = null;
-
- /**
- * RDBMS Version needed for this SQL.
- **/
- private String version = null;
-
+
+
/**
* Action to perform if an error is found
**/
@@ -235,38 +196,10 @@ public class SQLExec extends Task {
*/
private boolean append = false;
- public void setCaching(boolean value){
- caching = value;
- }
-
- /**
- * Set the classpath for loading the driver.
- */
- public void setClasspath(Path classpath) {
- if (this.classpath == null) {
- this.classpath = classpath;
- } else {
- this.classpath.append(classpath);
- }
- }
- /**
- * Create the classpath for loading the driver.
- */
- public Path createClasspath() {
- if (this.classpath == null) {
- this.classpath = new Path(project);
- }
- return this.classpath.createPath();
- }
-
- /**
- * Set the classpath for loading the driver using the classpath reference.
- */
- public void setClasspathRef(Reference r) {
- createClasspath().setRefid(r);
- }
+
+
/**
* Set the name of the sql file to be run.
*/
@@ -298,27 +231,9 @@ public class SQLExec extends Task {
return t;
}
- /**
- * Set the JDBC driver to be used.
- */
- public void setDriver(String driver) {
- this.driver = driver;
- }
-
- /**
- * Set the DB connection url.
- */
- public void setUrl(String url) {
- this.url = url;
- }
+
+
- /**
- * Set the user name for the DB connection.
- */
- public void setUserid(String userId) {
- this.userId = userId;
- }
-
/**
* Set the file encoding to use on the sql files read in
*
@@ -329,20 +244,8 @@ public class SQLExec extends Task {
}
- /**
- * Set the password for the DB connection.
- */
- public void setPassword(String password) {
- this.password = password;
- }
+
- /**
- * Set the autocommit flag for the DB connection.
- */
- public void setAutocommit(boolean autocommit) {
- this.autocommit = autocommit;
- }
-
/**
* Set the statement delimiter.
*
@@ -395,20 +298,8 @@ public class SQLExec extends Task {
this.append = append;
}
- /**
- * Set the rdbms required
- */
- public void setRdbms(String vendor) {
- this.rdbms = vendor.toLowerCase();
- }
-
- /**
- * Set the version required
- */
- public void setVersion(String version) {
- this.version = version.toLowerCase();
- }
-
+
+
/**
* Set the action to perform onerror
*/
@@ -434,75 +325,10 @@ public class SQLExec extends Task {
+ "must be set!", location);
}
}
- if (driver == null) {
- throw new BuildException("Driver attribute must be set!",
- location);
- }
- if (userId == null) {
- throw new BuildException("User Id attribute must be set!",
- location);
- }
- if (password == null) {
- throw new BuildException("Password attribute must be set!",
- location);
- }
- if (url == null) {
- throw new BuildException("Url attribute must be set!",
- location);
- }
- if (srcFile != null && !srcFile.exists()) {
- throw new BuildException("Source file does not exist!",
- location);
- }
- Driver driverInstance = null;
- try {
- Class dc;
- if (classpath != null) {
- // check first that it is not already loaded otherwise
- // consecutive runs seems to end into an OutOfMemoryError
- // or it fails when there is a native library to load
- // several times.
- // this is far from being perfect but should work
- // in most cases.
- synchronized (loaderMap){
- if (caching){
- loader = (AntClassLoader) loaderMap.get(driver);
- }
- if (loader == null){
- log("Loading " + driver
- + " using AntClassLoader with classpath "
- + classpath,
- Project.MSG_VERBOSE);
- loader = new AntClassLoader(project, classpath);
- if (caching){
- loaderMap.put(driver, loader);
- }
- } else {
- log("Loading " + driver
- + " using a cached AntClassLoader.",
- Project.MSG_VERBOSE);
- }
- }
- dc = loader.loadClass(driver);
- } else {
- log("Loading " + driver + " using system loader.",
- Project.MSG_VERBOSE);
- dc = Class.forName(driver);
- }
- driverInstance = (Driver) dc.newInstance();
- } catch (ClassNotFoundException e){
- throw new BuildException("Class Not Found: JDBC driver "
- + driver + " could not be loaded",
- location);
- } catch (IllegalAccessException e){
- throw new BuildException("Illegal Access: JDBC driver "
- + driver + " could not be loaded",
- location);
- } catch (InstantiationException e) {
- throw new BuildException("Instantiation Exception: JDBC driver "
- + driver + " could not be loaded",
- location);
- }
+
+ if (srcFile != null && !srcFile.exists()) {
+ throw new BuildException("Source file does not exist!", location);
+ }
// deal with the filesets
for (int i = 0; i < filesets.size(); i++) {
@@ -523,25 +349,11 @@ public class SQLExec extends Task {
Transaction t = createTransaction();
t.setSrc(srcFile);
t.addText(sqlCommand);
-
+ conn = getConnection();
+ if (!isValidRdbms(conn)) {
+ return;
+ }
try {
- log("connecting to " + url, Project.MSG_VERBOSE);
- Properties info = new Properties();
- info.put("user", userId);
- info.put("password", password);
- conn = driverInstance.connect(url, info);
-
- if (conn == null) {
- // Driver doesn't understand the URL
- throw new SQLException("No suitable Driver for " + url);
- }
-
- if (!isValidRdbms(conn)) {
- return;
- }
-
- conn.setAutoCommit(autocommit);
-
statement = conn.createStatement();
@@ -562,7 +374,7 @@ public class SQLExec extends Task {
e.hasMoreElements();) {
((Transaction) e.nextElement()).runTransaction(out);
- if (!autocommit) {
+ if (!isAutocommit()) {
log("Commiting transaction", Project.MSG_VERBOSE);
conn.commit();
}
@@ -571,16 +383,16 @@ public class SQLExec extends Task {
if (out != null && out != System.out) {
out.close();
}
- }
+ }
} catch (IOException e){
- if (!autocommit && conn != null && onError.equals("abort")) {
+ if (!isAutocommit() && conn != null && onError.equals("abort")) {
try {
conn.rollback();
} catch (SQLException ex) {}
}
throw new BuildException(e, location);
} catch (SQLException e){
- if (!autocommit && conn != null && onError.equals("abort")) {
+ if (!isAutocommit() && conn != null && onError.equals("abort")) {
try {
conn.rollback();
} catch (SQLException ex) {}
@@ -605,6 +417,7 @@ public class SQLExec extends Task {
}
}
+
protected void runStatements(Reader reader, PrintStream out)
throws SQLException, IOException {
String sql = "";
@@ -657,51 +470,7 @@ public class SQLExec extends Task {
}
}
- /**
- * Verify if connected to the correct RDBMS
- **/
- protected boolean isValidRdbms(Connection conn) {
- if (rdbms == null && version == null) {
- return true;
- }
- try {
- DatabaseMetaData dmd = conn.getMetaData();
-
- if (rdbms != null) {
- String theVendor = dmd.getDatabaseProductName().toLowerCase();
-
- log("RDBMS = " + theVendor, Project.MSG_VERBOSE);
- if (theVendor == null || theVendor.indexOf(rdbms) < 0) {
- log("Not the required RDBMS: " + rdbms,
- Project.MSG_VERBOSE);
- return false;
- }
- }
-
- if (version != null) {
- // XXX maybe better toLowerCase(Locale.US)
- String theVersion =
- dmd.getDatabaseProductVersion().toLowerCase();
-
- log("Version = " + theVersion, Project.MSG_VERBOSE);
- if (theVersion == null ||
- !(theVersion.startsWith(version) ||
- theVersion.indexOf(" " + version) >= 0)) {
- log("Not the required version: \""
- + version + "\"", Project.MSG_VERBOSE);
- return false;
- }
- }
- } catch (SQLException e) {
- // Could not get the required information
- log("Failed to obtain required RDBMS information", Project.MSG_ERR);
- return false;
- }
-
- return true;
- }
-
/**
* Exec the sql statement.
*/
@@ -835,12 +604,6 @@ public class SQLExec extends Task {
}
}
- protected static Hashtable getLoaderMap(){
- return loaderMap;
- }
- protected AntClassLoader getLoader(){
- return loader;
- }
}