com.googlecode.flyway.ant.AbstractFlywayTask.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.flyway.ant.AbstractFlywayTask.java

Source

/**
 * Copyright (C) 2010-2012 the original author or authors.
 *
 * 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 com.googlecode.flyway.ant;

import com.googlecode.flyway.core.Flyway;
import com.googlecode.flyway.core.util.ExceptionUtils;
import com.googlecode.flyway.core.util.StringUtils;
import com.googlecode.flyway.core.util.jdbc.DriverDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;

import javax.sql.DataSource;

/**
 * Base class for all Flyway Ant tasks.
 */
@SuppressWarnings({ "UnusedDeclaration" })
public abstract class AbstractFlywayTask extends Task {
    /**
     * Logger.
     */
    private static final Log LOG = LogFactory.getLog(AbstractFlywayTask.class);

    /**
     * The classpath used to load the JDBC driver and the migrations.
     */
    private Path classPath;

    /**
     * The fully qualified classname of the jdbc driver to use to connect to the database.<br/>Also configurable with Ant Property:
     * ${flyway.driver}
     */
    private String driver;

    /**
     * The jdbc url to use to connect to the database.<br/>Also configurable with Ant Property: ${flyway.url}
     */
    private String url;

    /**
     * The user to use to connect to the database.<br/>Also configurable with Ant Property: ${flyway.user}<br>
     * The credentials can be specified by user/password or serverId from settings.xml
     */
    private String user;

    /**
     * The password to use to connect to the database. (default: <i>blank</i>)<br/>Also configurable with Ant Property: ${flyway.password}
     */
    private String password;

    /**
     * Comma-separated list of the schemas managed by Flyway. The first schema in the list will be the one containing
     * the metadata table. (default: The default schema for the datasource connection)<br/>Also configurable with Ant Property:
     * ${flyway.schemas}
     */
    private String schemas;

    /**
     * <p>The name of the schema metadata table that will be used by Flyway.</p><p> By default (single-schema mode) the
     * metadata table is placed in the default schema for the connection provided by the datasource. </p> <p> When the
     * <i>flyway.schemas</i> property is set (multi-schema mode), the metadata table is placed in the first schema of
     * the list. </p> (default: schema_version)<br/>Also configurable with Ant Property: ${flyway.table}
     */
    private String table;

    /**
     * @param classpath The classpath used to load the JDBC driver and the migrations.<br/>Also configurable with Ant
     *                  Property: ${flyway.classpath}
     */
    public void setClasspath(Path classpath) {
        this.classPath = classpath;
    }

    /**
     * @param classpathref The reference to the classpath used to load the JDBC driver and the migrations.<br/>Also
     *                     configurable with Ant Property: ${flyway.classpathref}
     */
    public void setClasspathref(Reference classpathref) {
        Path classPath = new Path(getProject());
        classPath.setRefid(classpathref);
        this.classPath = classPath;
    }

    /**
     * @param driver The fully qualified classname of the jdbc driver to use to connect to the database.<br/>Also configurable with Ant Property:
     *               ${flyway.driver}
     */
    public void setDriver(String driver) {
        this.driver = driver;
    }

    /**
     * @param url The jdbc url to use to connect to the database.<br/>Also configurable with Ant Property: ${flyway.url}
     */
    public void setUrl(String url) {
        this.url = url;
    }

    /**
     * @param user The user to use to connect to the database.<br/>Also configurable with Ant Property: ${flyway.user}
     */
    public void setUser(String user) {
        this.user = user;
    }

    /**
     * @param password The password to use to connect to the database. (default: <i>blank</i>)<br/>Also configurable with Ant Property: ${flyway.password}
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @param schemas Comma-separated list of the schemas managed by Flyway. The first schema in the list will be the one containing
     *                the metadata table. (default: The default schema for the datasource connection)<br/>Also configurable with Ant Property:
     *                ${flyway.schemas}
     */
    public void setSchemas(String schemas) {
        this.schemas = schemas;
    }

    /**
     * @param table <p>The name of the schema metadata table that will be used by Flyway.</p><p> By default (single-schema mode) the
     *              metadata table is placed in the default schema for the connection provided by the datasource. </p> <p> When the
     *              <i>flyway.schemas</i> property is set (multi-schema mode), the metadata table is placed in the first schema of
     *              the list. </p> (default: schema_version)<br/>Also configurable with Ant Property: ${flyway.table}
     */
    public void setTable(String table) {
        this.table = table;
    }

    /**
     * Creates the datasource base on the provided parameters.
     *
     * @return The fully configured datasource.
     * @throws Exception Thrown when the datasource could not be created.
     */
    /* private -> for testing */ DataSource createDataSource() throws Exception {
        String driverValue = useValueIfPropertyNotSet(driver, "driver");
        String urlValue = useValueIfPropertyNotSet(url, "url");
        String userValue = useValueIfPropertyNotSet(user, "user");
        String passwordValue = useValueIfPropertyNotSet(password, "password");
        if (passwordValue == null) {
            passwordValue = "";
        }

        return new DriverDataSource(driverValue, urlValue, userValue, passwordValue);
    }

    /**
     * Retrieves a value either from an Ant property or if not set, directly.
     *
     * @param value          The value to check.
     * @param flywayProperty The flyway Ant property. Ex. 'url' for 'flyway.url'
     * @return The value.
     */
    protected String useValueIfPropertyNotSet(String value, String flywayProperty) {
        String propertyValue = getProject().getProperty("flyway." + flywayProperty);
        if (propertyValue != null) {
            return propertyValue;
        }

        return value;
    }

    /**
     * Prepares the classpath this task runs in, so that it includes both the classpath for Flyway and the classpath for
     * the JDBC drivers and migrations.
     */
    private void prepareClassPath() {
        Path classpath = (Path) getProject().getReference("flyway.classpath");
        if (classpath != null) {
            setClasspath(classpath);
        } else {
            Reference classpathRef = (Reference) getProject().getReference("flyway.classpathref");
            if (classpathRef != null) {
                setClasspathref(classpathRef);
            }
        }

        ClassLoader classLoader = new AntClassLoader(getClass().getClassLoader(), getProject(), classPath);
        Thread.currentThread().setContextClassLoader(classLoader);
    }

    @Override
    public void execute() throws BuildException {
        AntLogAppender.startTaskLog(getProject());

        prepareClassPath();

        try {
            Flyway flyway = new Flyway();

            flyway.setDataSource(createDataSource());
            String schemasValue = useValueIfPropertyNotSet(schemas, "schemas");
            if (schemasValue != null) {
                flyway.setSchemas(StringUtils.tokenizeToStringArray(schemasValue, ","));
            }
            String tableValue = useValueIfPropertyNotSet(table, "table");
            if (tableValue != null) {
                flyway.setTable(tableValue);
            }

            doExecute(flyway);
        } catch (Exception e) {
            LOG.error(e.toString());

            @SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
            Throwable rootCause = ExceptionUtils.getRootCause(e);
            if (rootCause != null) {
                LOG.error("Caused by " + rootCause.toString());
            }
            throw new BuildException("Flyway Error: " + e.toString(), e);
        } finally {
            AntLogAppender.endTaskLog();
        }
    }

    /**
     * Executes this task.
     *
     * @param flyway The flyway instance to operate on.
     * @throws Exception any exception
     */
    protected abstract void doExecute(Flyway flyway) throws Exception;
}