git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272577 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -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 | |||||
| * <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:nick@chalko.com">Nick Chalko</a> | |||||
| * @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a> | |||||
| * @author <A href="mailto:gholam@xtra.co.nz">Michael McCallum</A> | |||||
| * @author <A href="mailto:tim.stephenson@sybase.com">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; | |||||
| } | |||||
| } | |||||
| @@ -104,7 +104,7 @@ import java.sql.ResultSetMetaData; | |||||
| * | * | ||||
| * @ant.task name="sql" category="database" | * @ant.task name="sql" category="database" | ||||
| */ | */ | ||||
| public class SQLExec extends Task { | |||||
| public class SQLExec extends JDBCTask { | |||||
| public static class DelimiterType extends EnumeratedAttribute { | public static class DelimiterType extends EnumeratedAttribute { | ||||
| public static final String NORMAL = "normal"; | 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 goodSql = 0; | ||||
| private int totalSql = 0; | private int totalSql = 0; | ||||
| private Path classpath; | |||||
| private AntClassLoader loader; | |||||
| private Vector filesets = new Vector(); | |||||
| /** | |||||
| /** | |||||
| * Database connection | * Database connection | ||||
| */ | */ | ||||
| private Connection conn = null; | 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 | * SQL input file | ||||
| */ | */ | ||||
| @@ -210,16 +179,8 @@ public class SQLExec extends Task { | |||||
| */ | */ | ||||
| private File output = null; | 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 | * Action to perform if an error is found | ||||
| **/ | **/ | ||||
| @@ -235,38 +196,10 @@ public class SQLExec extends Task { | |||||
| */ | */ | ||||
| private boolean append = false; | 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. | * Set the name of the sql file to be run. | ||||
| */ | */ | ||||
| @@ -298,27 +231,9 @@ public class SQLExec extends Task { | |||||
| return t; | 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 | * 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. | * Set the statement delimiter. | ||||
| * | * | ||||
| @@ -395,20 +298,8 @@ public class SQLExec extends Task { | |||||
| this.append = append; | 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 | * Set the action to perform onerror | ||||
| */ | */ | ||||
| @@ -434,75 +325,10 @@ public class SQLExec extends Task { | |||||
| + "must be set!", location); | + "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 | // deal with the filesets | ||||
| for (int i = 0; i < filesets.size(); i++) { | for (int i = 0; i < filesets.size(); i++) { | ||||
| @@ -523,25 +349,11 @@ public class SQLExec extends Task { | |||||
| Transaction t = createTransaction(); | Transaction t = createTransaction(); | ||||
| t.setSrc(srcFile); | t.setSrc(srcFile); | ||||
| t.addText(sqlCommand); | t.addText(sqlCommand); | ||||
| conn = getConnection(); | |||||
| if (!isValidRdbms(conn)) { | |||||
| return; | |||||
| } | |||||
| try { | 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(); | statement = conn.createStatement(); | ||||
| @@ -562,7 +374,7 @@ public class SQLExec extends Task { | |||||
| e.hasMoreElements();) { | e.hasMoreElements();) { | ||||
| ((Transaction) e.nextElement()).runTransaction(out); | ((Transaction) e.nextElement()).runTransaction(out); | ||||
| if (!autocommit) { | |||||
| if (!isAutocommit()) { | |||||
| log("Commiting transaction", Project.MSG_VERBOSE); | log("Commiting transaction", Project.MSG_VERBOSE); | ||||
| conn.commit(); | conn.commit(); | ||||
| } | } | ||||
| @@ -571,16 +383,16 @@ public class SQLExec extends Task { | |||||
| if (out != null && out != System.out) { | if (out != null && out != System.out) { | ||||
| out.close(); | out.close(); | ||||
| } | } | ||||
| } | |||||
| } | |||||
| } catch (IOException e){ | } catch (IOException e){ | ||||
| if (!autocommit && conn != null && onError.equals("abort")) { | |||||
| if (!isAutocommit() && conn != null && onError.equals("abort")) { | |||||
| try { | try { | ||||
| conn.rollback(); | conn.rollback(); | ||||
| } catch (SQLException ex) {} | } catch (SQLException ex) {} | ||||
| } | } | ||||
| throw new BuildException(e, location); | throw new BuildException(e, location); | ||||
| } catch (SQLException e){ | } catch (SQLException e){ | ||||
| if (!autocommit && conn != null && onError.equals("abort")) { | |||||
| if (!isAutocommit() && conn != null && onError.equals("abort")) { | |||||
| try { | try { | ||||
| conn.rollback(); | conn.rollback(); | ||||
| } catch (SQLException ex) {} | } catch (SQLException ex) {} | ||||
| @@ -605,6 +417,7 @@ public class SQLExec extends Task { | |||||
| } | } | ||||
| } | } | ||||
| protected void runStatements(Reader reader, PrintStream out) | protected void runStatements(Reader reader, PrintStream out) | ||||
| throws SQLException, IOException { | throws SQLException, IOException { | ||||
| String sql = ""; | 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. | * Exec the sql statement. | ||||
| */ | */ | ||||
| @@ -835,12 +604,6 @@ public class SQLExec extends Task { | |||||
| } | } | ||||
| } | } | ||||
| protected static Hashtable getLoaderMap(){ | |||||
| return loaderMap; | |||||
| } | |||||
| protected AntClassLoader getLoader(){ | |||||
| return loader; | |||||
| } | |||||
| } | } | ||||