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

org.flywaydb.ant.AbstractFlywayTask Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2017 Boxfuse GmbH
 *
 * 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.flywaydb.ant;

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 org.flywaydb.core.Flyway;
import org.flywaydb.core.internal.util.ExceptionUtils;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.StringUtils;
import org.flywaydb.core.internal.util.jdbc.DriverDataSource;
import org.flywaydb.core.internal.util.logging.Log;
import org.flywaydb.core.internal.util.logging.LogFactory;

import javax.sql.DataSource;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Base class for all Flyway Ant tasks.
 */
@SuppressWarnings({"UnusedDeclaration"})
public abstract class AbstractFlywayTask extends Task {
    /**
     * Property name prefix for placeholders that are configured through properties.
     */
    private static final String PLACEHOLDERS_PROPERTY_PREFIX = "flyway.placeholders.";

    private Flyway flyway = new Flyway();

    /**
     * Logger.
     */
    protected Log log;

    /**
     * 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.
Also configurable with Ant Property: * ${flyway.driver} */ private String driver; /** * The jdbc url to use to connect to the database.
Also configurable with Ant Property: ${flyway.url} */ private String url; /** * The user to use to connect to the database. (default: blank)
Also configurable with Ant Property: ${flyway.user}
* 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: blank)
Also configurable with Ant Property: ${flyway.password} */ private String password; /** * Locations on the classpath to scan recursively for migrations. Locations may contain both sql * and java-based migrations. (default: db.migration)
Also configurable with Ant Property: ${flyway.locations} */ private String[] locations = flyway.getLocations(); /** * The custom MigrationResolvers to be used in addition or as replacement to the built-in (as determined by the * skipDefaultResolvers property) ones for resolving Migrations to apply. *

(default: none)

*/ private String[] resolvers; /** * The callbacks for lifecycle notifications. *

(default: none)

*/ private String[] callbacks; /** * A map of <placeholder, replacementValue> to apply to sql migration scripts. */ private Map placeholders = flyway.getPlaceholders(); /** * @param classpath The classpath used to load the JDBC driver and the migrations.
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.
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.
* By default, the driver is autodetected based on the url.
* 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.
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.
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: blank)
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. These schema names are case-sensitive.
* (default: The default schema for the datasource connection) *

Consequences:

*
    *
  • The first schema in the list will be automatically set as the default one during the migration.
  • *
  • The first schema in the list will also be the one containing the metadata table.
  • *
  • The schemas will be cleaned in the order of this list.
  • *
Also configurable with Ant Property: * ${flyway.schemas} */ public void setSchemas(String schemas) { flyway.setSchemas(StringUtils.tokenizeToStringArray(schemas, ",")); } /** * @param resolvers The custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. *

(default: none)

*/ public void setResolvers(String resolvers) { this.resolvers = StringUtils.tokenizeToStringArray(resolvers, ","); } /** * @param skipDefaultResolvers Whether built-int resolvers should be skipped. * If true, only custom resolvers are used.

(default: false)

*
Also configurable with Ant Property: ${flyway.skipDefaultResolvers} */ public void setSkipDefaultResolvers(boolean skipDefaultResolvers) { flyway.setSkipDefaultResolvers(skipDefaultResolvers); } /** * @param callbacks A comma-separated list of fully qualified FlywayCallback implementation class names. These classes * will be instantiated and wired into the Flyway lifecycle notification events. */ public void setCallbacks(String callbacks) { this.callbacks = StringUtils.tokenizeToStringArray(callbacks, ","); } /** * @param skipDefaultCallbacks Whether built-int callbacks should be skipped. * If true, only custom callbacks are used.

(default: false)

*
Also configurable with Ant Property: ${flyway.skipDefaultCallbacks} */ public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { flyway.setSkipDefaultCallbacks(skipDefaultCallbacks); } /** * @param table

The name of the schema metadata table that will be used by Flyway.

By default (single-schema mode) the * metadata table is placed in the default schema for the connection provided by the datasource.

When the * flyway.schemas property is set (multi-schema mode), the metadata table is placed in the first schema of * the list.

(default: schema_version)
Also configurable with Ant Property: ${flyway.table} */ public void setTable(String table) { flyway.setTable(table); } /** * @param baselineVersion The version to tag an existing schema with when executing baseline. (default: 1)
Also configurable with Ant Property: ${flyway.baselineVersion} */ public void setBaselineVersion(String baselineVersion) { flyway.setBaselineVersionAsString(baselineVersion); } /** * @param baselineDescription The description to tag an existing schema with when executing baseline. (default: << Flyway Baseline >>)
Also configurable with Ant Property: * ${flyway.baselineDescription} */ public void setBaselineDescription(String baselineDescription) { flyway.setBaselineDescription(baselineDescription); } /** * Whether to allow mixing transactional and non-transactional statements within the same migration.
* Also configurable with Ant Property: ${flyway.allowMixedMigrations} * * @param allowMixedMigrations {@code true} if mixed migrations should be allowed. {@code false} if an error should be thrown instead. (default: {@code false}) * @deprecated Use mixed instead. Will be removed in Flyway 5.0. */ @Deprecated public void setAllowMixedMigrations(boolean allowMixedMigrations) { flyway.setAllowMixedMigrations(allowMixedMigrations); } /** * Whether to allow mixing transactional and non-transactional statements within the same migration.
* Also configurable with Ant Property: ${flyway.mixed} * * @param mixed {@code true} if mixed migrations should be allowed. {@code false} if an error should be thrown instead. (default: {@code false}) */ public void setMixed(boolean mixed) { flyway.setMixed(mixed); } /** * Whether to group all pending migrations together in the same transaction when applying them (only recommended for databases with support for DDL transactions). * * Also configurable with Ant Property: ${flyway.group} * * @param group {@code true} if migrations should be grouped. {@code false} if they should be applied individually instead. (default: {@code false}) */ public void setGroup(boolean group) { flyway.setGroup(group); } /** * The username that will be recorded in the metadata table as having applied the migration. * * @param installedBy The username or blank for the current database user of the connection. (default: blank). */ public void setInstalledBy(String installedBy) { flyway.setInstalledBy(installedBy); } /** * 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"); return new DriverDataSource(Thread.currentThread().getContextClassLoader(), driverValue, urlValue, userValue, passwordValue, null); } /** * 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; } /** * Retrieves a boolean value either from an Ant property or if not set, directly. * * @param value The boolean value to check. * @param flywayProperty The flyway Ant property. Ex. 'url' for 'flyway.url' * @return The boolean value. */ protected boolean useValueIfPropertyNotSet(boolean value, String flywayProperty) { String propertyValue = getProject().getProperty("flyway." + flywayProperty); if (propertyValue != null) { return Boolean.parseBoolean(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); } /** * Do not use. For Ant itself. * * @param locationsElement The locations on the classpath. */ public void addConfiguredLocations(LocationsElement locationsElement) { this.locations = locationsElement.locations.toArray(new String[locationsElement.locations.size()]); } /** * Do not use. For Ant itself. * * @param resolversElement The resolvers on the classpath. */ public void addConfiguredResolvers(ResolversElement resolversElement) { this.resolvers = resolversElement.resolvers.toArray(new String[resolversElement.resolvers.size()]); } /** * Do not use. For Ant itself. * * @param callbacksElement The callbacks on the classpath. */ public void addConfiguredCallbacks(CallbacksElement callbacksElement) { this.callbacks = callbacksElement.callbacks.toArray(new String[callbacksElement.callbacks.size()]); } /** * Do not use. For Ant itself. * * @param schemasElement The schemas. */ public void addConfiguredSchemas(SchemasElement schemasElement) { flyway.setSchemas(schemasElement.schemas.toArray(new String[schemasElement.schemas.size()])); } /** * @param encoding The encoding of Sql migrations. (default: UTF-8)
Also configurable with Ant Property: ${flyway.encoding} */ public void setEncoding(String encoding) { flyway.setEncoding(encoding); } /** *

Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix , * which using the defaults translates to V1_1__My_description.sql

* * @param sqlMigrationPrefix The file name prefix for Sql migrations (default: V)
Also configurable with Ant Property: ${flyway.sqlMigrationPrefix} */ public void setSqlMigrationPrefix(String sqlMigrationPrefix) { flyway.setSqlMigrationPrefix(sqlMigrationPrefix); } /** *

Repeatable sql migrations have the following file name structure: prefixSeparatorDESCRIPTIONsuffix , * which using the defaults translates to R__My_description.sql

* * @param repeatableSqlMigrationPrefix The file name prefix for repeatable sql migrations (default: R)
Also configurable with Ant Property: ${flyway.repeatableSqlMigrationPrefix} */ public void setRepeatableSqlMigrationPrefix(String repeatableSqlMigrationPrefix) { flyway.setRepeatableSqlMigrationPrefix(repeatableSqlMigrationPrefix); } /** *

Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix , * which using the defaults translates to V1_1__My_description.sql

* * @param sqlMigrationSeparator The file name separator for Sql migrations (default: V)
Also configurable with Ant Property: ${flyway.sqlMigrationPrefix} */ public void setSqlMigrationSeparator(String sqlMigrationSeparator) { flyway.setSqlMigrationSeparator(sqlMigrationSeparator); } /** *

Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix , * which using the defaults translates to V1_1__My_description.sql

* * @param sqlMigrationSuffix The file name suffix for Sql migrations (default: .sql)
Also configurable with Ant Property: ${flyway.sqlMigrationSuffix} */ public void setSqlMigrationSuffix(String sqlMigrationSuffix) { flyway.setSqlMigrationSuffix(sqlMigrationSuffix); } /** * @param target The target version up to which Flyway should consider migrations. * Migrations with a higher version number will be ignored. * The special value {@code current} designates the current version of the schema. (default: the latest version)
Also configurable with Ant Property: ${flyway.target} */ public void setTarget(String target) { flyway.setTargetAsString(target); } /** * @param cleanOnValidationError Whether to automatically call clean or not when a validation error occurs. (default: {@code false})
*

This is exclusively intended as a convenience for development. Even tough we * strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a * way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that * the next migration will bring you back to the state checked into SCM.

*

Warning ! Do not enable in production !

*
Also configurable with Ant Property: ${flyway.cleanOnValidationError} */ public void setCleanOnValidationError(boolean cleanOnValidationError) { flyway.setCleanOnValidationError(cleanOnValidationError); } /** * @param cleanDisabled Whether to disable clean. (default: {@code false}) *

This is especially useful for production environments where running clean can be quite a career limiting move.

*/ public void setCleanDisabled(boolean cleanDisabled) { flyway.setCleanDisabled(cleanDisabled); } /** * @param outOfOrder Allows migrations to be run "out of order" (default: {@code false}). *

If you already have versions 1 and 3 applied, and now a version 2 is found, * it will be applied too instead of being ignored.

* Also configurable with Ant Property: ${flyway.outOfOrder} */ public void setOutOfOrder(boolean outOfOrder) { flyway.setOutOfOrder(outOfOrder); } /** * @param placeholderReplacement Whether placeholders should be replaced. (default: true)
Also configurable with Ant Property: ${flyway.placeholderReplacement} */ public void setPlaceholderReplacement(boolean placeholderReplacement) { flyway.setPlaceholderReplacement(placeholderReplacement); } /** * @param placeholderPrefix The prefix of every placeholder. (default: ${ )
Also configurable with Ant Property: ${flyway.placeholderPrefix} */ public void setPlaceholderPrefix(String placeholderPrefix) { flyway.setPlaceholderPrefix(placeholderPrefix); } /** * @param placeholderSuffix The suffix of every placeholder. (default: } )
Also configurable with Ant Property: ${flyway.placeholderSuffix} */ public void setPlaceholderSuffix(String placeholderSuffix) { flyway.setPlaceholderSuffix(placeholderSuffix); } /** * Adds placeholders from a nested <placeholders> element. Called by Ant. * * @param placeholders The fully configured placeholders element. */ public void addConfiguredPlaceholders(PlaceholdersElement placeholders) { this.placeholders = placeholders.placeholders; } /** * Ignore missing migrations when reading the metadata table. These are migrations that were performed by an * older deployment of the application that are no longer available in this version. For example: we have migrations * available on the classpath with versions 1.0 and 3.0. The metadata table indicates that a migration with version 2.0 * (unknown to us) has also been applied. Instead of bombing out (fail fast) with an exception, a * warning is logged and Flyway continues normally. This is useful for situations where one must be able to deploy * a newer version of the application even though it doesn't contain migrations included with an older one anymore. * * @param ignoreMissingMigrations {@code true} to continue normally and log a warning, {@code false} to fail fast with an exception. * (default: {@code false}) */ public void setIgnoreMissingMigrations(boolean ignoreMissingMigrations) { flyway.setIgnoreMissingMigrations(ignoreMissingMigrations); } /** * Whether to ignore future migrations when reading the metadata table. These are migrations that were performed by a * newer deployment of the application that are not yet available in this version. For example: we have migrations * available on the classpath up to version 3.0. The metadata table indicates that a migration to version 4.0 * (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a * warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy * an older version of the application after the database has been migrated by a newer one. *
Also configurable with Ant Property: ${flyway.ignoreFutureMigrations} * * @param ignoreFutureMigrations {@code true} to continue normally and log a warning, {@code false} to fail * fast with an exception. (default: {@code true}) */ public void setIgnoreFutureMigrations(boolean ignoreFutureMigrations) { flyway.setIgnoreFutureMigrations(ignoreFutureMigrations); } /** * @param ignoreFailedFutureMigration Ignores failed future migrations when reading the metadata table. These are migrations that we performed by a * newer deployment of the application that are not yet available in this version. For example: we have migrations * available on the classpath up to version 3.0. The metadata table indicates that a migration to version 4.0 * (unknown to us) has already been attempted and failed. Instead of bombing out (fail fast) with an exception, a * warning is logged and Flyway terminates normally. This is useful for situations where a database rollback is not * an option. An older version of the application can then be redeployed, even though a newer one failed due to a * bad migration. (default: false)
Also configurable with Ant Property: ${flyway.ignoreFailedFutureMigration} * @deprecated Use the more generic setIgnoreFutureMigrations() instead. Will be removed in Flyway 5.0. */ @Deprecated public void setIgnoreFailedFutureMigration(boolean ignoreFailedFutureMigration) { flyway.setIgnoreFailedFutureMigration(ignoreFailedFutureMigration); } /** * @param validateOnMigrate Whether to automatically call validate or not when running migrate. (default: {@code true})
* Also configurable with Ant Property: ${flyway.validateOnMigrate} */ public void setValidateOnMigrate(boolean validateOnMigrate) { flyway.setValidateOnMigrate(validateOnMigrate); } /** *

* Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table. * This schema will then be baselined with the {@code initialVersion} before executing the migrations. * Only migrations above {@code initialVersion} will then be applied. *

*

* This is useful for initial Flyway production deployments on projects with an existing DB. *

*

* Be careful when enabling this as it removes the safety net that ensures * Flyway does not migrate the wrong database in case of a configuration mistake! *

* Also configurable with Ant Property: ${flyway.baselineOnMigrate} * * @param baselineOnMigrate {@code true} if baseline should be called on migrate for non-empty schemas, {@code false} if not. (default: {@code false}) */ public void setBaselineOnMigrate(boolean baselineOnMigrate) { flyway.setBaselineOnMigrate(baselineOnMigrate); } @Override public void init() throws BuildException { AntLogCreator.INSTANCE.setAntProject(getProject()); LogFactory.setLogCreator(AntLogCreator.INSTANCE); log = LogFactory.getLog(getClass()); } @Override public void execute() throws BuildException { prepareClassPath(); try { flyway.setClassLoader(Thread.currentThread().getContextClassLoader()); flyway.setDataSource(createDataSource()); if (resolvers != null) { flyway.setResolversAsClassNames(resolvers); } if (callbacks != null) { flyway.setCallbacksAsClassNames(callbacks); } Properties projectProperties = new Properties(); projectProperties.putAll(getProject().getProperties()); flyway.configure(projectProperties); flyway.configure(System.getProperties()); flyway.setLocations(getLocations()); addPlaceholdersFromProperties(placeholders, getProject().getProperties()); flyway.setPlaceholders(placeholders); doExecute(flyway); } catch (Exception e) { throw new BuildException("Flyway Error: " + e.toString(), ExceptionUtils.getRootCause(e)); } } /** * Executes this task. * * @param flyway The flyway instance to operate on. * @throws Exception any exception */ protected abstract void doExecute(Flyway flyway) throws Exception; /** * @return The locations configured through Ant. */ private String[] getLocations() { String[] locationsVal = locations; String locationsProperty = getProject().getProperty("flyway.locations"); if (locationsProperty != null) { locationsVal = StringUtils.tokenizeToStringArray(locationsProperty, ","); } //Adjust relative locations to be relative from Ant's basedir. File baseDir = getProject().getBaseDir(); for (int i = 0; i < locationsVal.length; i++) { locationsVal[i] = adjustRelativeFileSystemLocationToBaseDir(baseDir, locationsVal[i]); } return locationsVal; } /** * Adjusts a relative filesystem location to Ant's basedir. All other locations are left untouched. * * @param baseDir Ant's basedir. * @param locationStr The location to adjust. * @return The adjusted location. */ /* private -> testing */ static String adjustRelativeFileSystemLocationToBaseDir(File baseDir, String locationStr) { Location location = new Location(locationStr); if (location.isFileSystem() && !new File(location.getPath()).isAbsolute()) { return Location.FILESYSTEM_PREFIX + baseDir.getAbsolutePath() + "/" + location.getPath(); } return locationStr; } /** * Adds the additional placeholders contained in these properties to the existing list. * * @param placeholders The existing list of placeholders. * @param properties The properties containing additional placeholders. */ private static void addPlaceholdersFromProperties(Map placeholders, Hashtable properties) { for (Object property : properties.keySet()) { String propertyName = (String) property; if (propertyName.startsWith(PLACEHOLDERS_PROPERTY_PREFIX) && propertyName.length() > PLACEHOLDERS_PROPERTY_PREFIX.length()) { String placeholderName = propertyName.substring(PLACEHOLDERS_PROPERTY_PREFIX.length()); String placeholderValue = (String) properties.get(propertyName); placeholders.put(placeholderName, placeholderValue); } } } /** * The nested <locations> element of the task. Contains 1 or more <location> sub-elements. */ public static class LocationsElement { /** * The classpath locations. */ List locations = new ArrayList(); /** * Do not use. For Ant itself. * * @param location A location on the classpath. */ public void addConfiguredLocation(LocationElement location) { locations.add(location.path); } } /** * One <location> sub-element within the <locations> element. */ public static class LocationElement { /** * The path of the location. */ private String path; /** * Do not use. For Ant itself. * * @param path The path of the location. */ public void setPath(String path) { this.path = path; } } /** * The nested <schemas> element of the task. Contains 1 or more <schema> sub-elements. */ public static class SchemasElement { /** * The schema names. */ List schemas = new ArrayList(); /** * Do not use. For Ant itself. * * @param schema A schema. */ public void addConfiguredLocation(SchemaElement schema) { schemas.add(schema.name); } } /** * One <location> sub-element within the <locations> element. */ public static class SchemaElement { /** * The name of the schema. */ private String name; /** * Do not use. For Ant itself. * * @param name The name of the schema. */ public void setPath(String name) { this.name = name; } } /** * The nested <resolvers> element of the task. Contains 1 or more <resolver> sub-elements. */ public static class ResolversElement { /** * The classpath locations. */ List resolvers = new ArrayList(); /** * Do not use. For Ant itself. * * @param resolver A resolver on the classpath. */ public void addConfiguredResolver(ResolverElement resolver) { resolvers.add(resolver.clazz); } } /** * One <resolver> sub-element within the <resolvers> element. */ public static class ResolverElement { /** * The fully qualified class name of the resolver. */ private String clazz; /** * Do not use. For Ant itself. * * @param clazz The fully qualified class name of the resolver. */ public void setClass(String clazz) { this.clazz = clazz; } } /** * The nested <callbacks> element of the task. Contains 1 or more <callback> sub-elements. */ public static class CallbacksElement { /** * The classpath locations. */ List callbacks = new ArrayList(); /** * Do not use. For Ant itself. * * @param callback A callback on the classpath. */ public void addConfiguredCallback(CallbackElement callback) { callbacks.add(callback.clazz); } } /** * One <callback> sub-element within the <callbacks> element. */ public static class CallbackElement { /** * The fully qualified class name of the callback. */ private String clazz; /** * Do not use. For Ant itself. * * @param clazz The fully qualified class name of the callback. */ public void setClass(String clazz) { this.clazz = clazz; } } /** * Nested <placeholders> element of the migrate Ant task. */ public static class PlaceholdersElement { /** * A map of <placeholder, replacementValue> to apply to sql migration scripts. */ Map placeholders = new HashMap(); /** * Adds a placeholder from a nested <placeholder> element. Called by Ant. * * @param placeholder The fully configured placeholder element. */ public void addConfiguredPlaceholder(PlaceholderElement placeholder) { placeholders.put(placeholder.name, placeholder.value); } } /** * Nested <placeholder> element inside the <placeholders> element of the migrate Ant task. */ public static class PlaceholderElement { /** * The name of the placeholder. */ private String name; /** * The value of the placeholder. */ private String value; /** * @param name The name of the placeholder. */ public void setName(String name) { this.name = name; } /** * @param value The value of the placeholder. */ public void setValue(String value) { this.value = value; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy