All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tools.ant.taskdefs.JDBCTask Maven / Gradle / Ivy

There is a newer version: 1.10.15
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
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.
 * 

* The following example class prints the contents of the first column of each row in TableName. *

*
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 ignore) {}
            }
            if (conn != null) {
                try {conn.close();}catch (SQLException ignore) {}
            }
        }
    }
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

}
* * @since Ant 1.5 * */ public abstract class JDBCTask extends Task { private static final int HASH_TABLE_SIZE = 3; /** * Used for caching loaders / driver. This is to avoid * getting an OutOfMemoryError when calling this task * multiple times in a row. */ private static Hashtable LOADER_MAP = new Hashtable(HASH_TABLE_SIZE); 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; /** * whether the task fails when ant fails to connect to the database. * @since Ant 1.8.0 */ private boolean failOnConnectionError = true; /** * Additional properties to put into the JDBC connection string. * * @since Ant 1.8.0 */ private List connectionProperties = new ArrayList(); /** * 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 a boolean value */ public void setCaching(boolean enable) { caching = enable; } /** * Add a path to the classpath for loading the driver. * @return a path to be configured */ 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. * @param r a reference to a classpath */ 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.trim(); } /** * 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; } /** * whether the task should cause the build to fail if it cannot * connect to the database. * @since Ant 1.8.0 */ public void setFailOnConnectionError(boolean b) { failOnConnectionError = b; } /** * Verify we are connected to the correct RDBMS * @param conn the jdbc connection * @return true if 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) { String theVersion = dmd.getDatabaseProductVersion().toLowerCase(Locale.ENGLISH); 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; } /** * Get the cache of loaders and drivers. * @return a hashtable */ protected static Hashtable getLoaderMap() { return LOADER_MAP; } /** * Get the classloader used to create a driver. * @return the classloader */ protected AntClassLoader getLoader() { return loader; } /** * Additional properties to put into the JDBC connection string. * * @since Ant 1.8.0 */ public void addConnectionProperty(Property var) { connectionProperties.add(var); } /** * 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 or null if the * connection failed and failOnConnectionError is false. * @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("UserId 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()); for (Iterator props = connectionProperties.iterator(); props.hasNext();) { Property p = props.next(); String name = p.getName(); String value = p.getValue(); if (name == null || value == null) { log("Only name/value pairs are supported as connection" + " properties.", Project.MSG_WARN); } else { log("Setting connection property " + name + " to " + value, Project.MSG_VERBOSE); info.put(name, value); } } 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) { // failed to connect if (!failOnConnectionError) { log("Failed to connect: " + e.getMessage(), Project.MSG_WARN); return null; } else { 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 (LOADER_MAP) { if (caching) { loader = LOADER_MAP.get(driver); } if (loader == null) { log("Loading " + driver + " using AntClassLoader with classpath " + classpath, Project.MSG_VERBOSE); loader = getProject().createClassLoader(classpath); if (caching) { LOADER_MAP.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", e, getLocation()); } catch (IllegalAccessException e) { throw new BuildException( "Illegal Access: JDBC driver " + driver + " could not be loaded", e, getLocation()); } catch (InstantiationException e) { throw new BuildException( "Instantiation Exception: JDBC driver " + driver + " could not be loaded", e, getLocation()); } return driverInstance; } /** * Set the caching attribute. * @param value a boolean value */ 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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy