- /*
- * Copyright 2002-2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
- package org.apache.tools.ant.taskdefs;
-
- import java.sql.Connection;
- import java.sql.DatabaseMetaData;
- import java.sql.Driver;
- import java.sql.SQLException;
- import java.util.Hashtable;
- import java.util.Properties;
- 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;
-
- /**
- * Handles JDBC configuration needed by SQL type tasks.
- * <p>
- * The following example class prints the contents of the first column of each row in TableName.
- *</p>
- *<code><pre>
- package examples;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
-
- import org.apache.tools.ant.BuildException;
- import org.apache.tools.ant.taskdefs.JDBCTask;
-
- public class SQLExampleTask extends JDBCTask {
-
- private String tableName;
-
- public void execute() throws BuildException {
- Connection conn = getConnection();
- Statement stmt=null;
- try {
- if (tableName == null) {
- throw new BuildException("TableName must be specified",location);
- }
- String sql = "SELECT * FROM "+tableName;
- stmt= conn.createStatement();
- ResultSet rs = stmt.executeQuery(sql);
- while (rs.next()) {
- log(rs.getObject(1).toString());
- }
- } catch (SQLException e) {
-
- } finally {
- if (stmt != null) {
- try {stmt.close();}catch (SQLException ingore) {}
- }
- if (conn != null) {
- try {conn.close();}catch (SQLException ingore) {}
- }
- }
- }
- public void setTableName(String tableName) {
- this.tableName = tableName;
- }
-
- }
-
-
- </pre></code>
-
-
- * @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 for loading the driver.
- * @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; default: true
- * @param enable
- */
- public void setCaching(boolean enable) {
- caching = enable;
- }
-
- /**
- * Add a path to the classpath for loading the driver.
- */
- public Path createClasspath() {
- if (this.classpath == null) {
- this.classpath = new Path(getProject());
- }
- return this.classpath.createPath();
- }
-
- /**
- * Set the classpath for loading the driver
- * using the classpath reference.
- */
- public void setClasspathRef(Reference r) {
- createClasspath().setRefid(r);
- }
-
- /**
- * Class name of the JDBC driver; required.
- * @param driver The driver to set
- */
- public void setDriver(String driver) {
- this.driver = driver;
- }
-
- /**
- * Sets the database connection URL; required.
- * @param url The url to set
- */
- public void setUrl(String url) {
- this.url = url;
- }
-
- /**
- * Sets the password; required.
- * @param password The password to set
- */
- public void setPassword(String password) {
- this.password = password;
- }
-
- /**
- * Auto commit flag for database connection;
- * optional, default false.
- * @param autocommit The autocommit to set
- */
- public void setAutocommit(boolean autocommit) {
- this.autocommit = autocommit;
- }
-
- /**
- * Execute task only if the lower case product name
- * of the DB matches this
- * @param rdbms The rdbms to set
- */
- public void setRdbms(String rdbms) {
- this.rdbms = rdbms;
- }
-
- /**
- * Sets the version string, execute task only if
- * rdbms version match; optional.
- * @param version The version to set
- */
- public void setVersion(String version) {
- this.version = version;
- }
-
- /**
- * Verify we are 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!", getLocation());
- }
- if (password == null) {
- throw new BuildException("Password attribute must be set!", getLocation());
- }
- if (url == null) {
- throw new BuildException("Url attribute must be set!", getLocation());
- }
- 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, getLocation());
- }
-
- }
-
- /**
- * 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!", getLocation());
- }
-
- 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 = getProject().createClassLoader(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",
- getLocation());
- } catch (IllegalAccessException e) {
- throw new BuildException(
- "Illegal Access: JDBC driver " + driver + " could not be loaded",
- getLocation());
- } catch (InstantiationException e) {
- throw new BuildException(
- "Instantiation Exception: JDBC driver " + driver + " could not be loaded",
- getLocation());
- }
- 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;
- }
-
- /**
- * Set the user name for the connection; required.
- * @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;
- }
-
- }