ehatcher 02/04/25 17:24:05
Modified: src/main/org/apache/tools/ant/taskdefs SQLExec.java
Added: src/main/org/apache/tools/ant/taskdefs JDBCTask.java
Log:
PR 8429 patch submitted by Nick Chalko - enables SQL tasks to be easily
created using a common abstract base class.
Revision Changes Path
1.42 +35 -272
jakarta-ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
Index: SQLExec.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- SQLExec.java 15 Apr 2002 14:56:29 -0000 1.41
+++ SQLExec.java 26 Apr 2002 00:24:05 -0000 1.42
@@ -104,7 +104,7 @@
*
* @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 @@
}
}
- /**
- * 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 @@
*/
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 @@
*/
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,28 +231,10 @@
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
*
* @param encoding the encoding to use on the files
@@ -329,21 +244,9 @@
}
- /**
- * 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.
*
* <p>For example, set this to "go" and delimitertype to "ROW" for
@@ -395,20 +298,8 @@
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 @@
+ "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 @@
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 @@
e.hasMoreElements();) {
((Transaction) e.nextElement()).runTransaction(out);
- if (!autocommit) {
+ if (!isAutocommit()) {
log("Commiting transaction",
Project.MSG_VERBOSE);
conn.commit();
}
@@ -571,16 +383,16 @@
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 @@
}
}
+
protected void runStatements(Reader reader, PrintStream out)
throws SQLException, IOException {
String sql = "";
@@ -657,51 +470,7 @@
}
}
- /**
- * 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 @@
}
}
- protected static Hashtable getLoaderMap(){
- return loaderMap;
- }
- protected AntClassLoader getLoader(){
- return loader;
- }
}
1.1
jakarta-ant/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
Index: JDBCTask.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", "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 [EMAIL PROTECTED]
*
* 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.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 <a href="mailto:[EMAIL PROTECTED]">Nick Chalko</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Jeff Martin</a>
* @author <A href="mailto:[EMAIL PROTECTED]">Michael McCallum</A>
* @author <A href="mailto:[EMAIL PROTECTED]">Tim Stephenson</A>
*
* @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;
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>