diff --git a/flyway-core/src/main/java/org/flywaydb/core/internal/configuration/ConfigUtils.java b/flyway-core/src/main/java/org/flywaydb/core/internal/configuration/ConfigUtils.java index 1e877690f9..40f86d09c7 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/internal/configuration/ConfigUtils.java +++ b/flyway-core/src/main/java/org/flywaydb/core/internal/configuration/ConfigUtils.java @@ -95,6 +95,9 @@ public class ConfigUtils { // Command-line specific public static final String JAR_DIRS = "flyway.jarDirs"; + // Gradle specific + public static final String CONFIGURATIONS = "flyway.configurations"; + private ConfigUtils() { // Utility class } @@ -252,6 +255,11 @@ private static String convertKey(String key) { return JAR_DIRS; } + // Gradle specific + if ("FLYWAY_CONFIGURATIONS".equals(key)) { + return CONFIGURATIONS; + } + return null; } diff --git a/flyway-gradle-plugin/pom.xml b/flyway-gradle-plugin/pom.xml index c0d8ec34bf..920261b09b 100644 --- a/flyway-gradle-plugin/pom.xml +++ b/flyway-gradle-plugin/pom.xml @@ -28,7 +28,6 @@ ${project.artifactId} - ${project.groupId} flyway-core ${project.version} @@ -64,6 +63,13 @@ + + + + + + + @@ -91,6 +97,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/FlywayExtension.java b/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/FlywayExtension.java index edca1db032..0c73ac5713 100644 --- a/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/FlywayExtension.java +++ b/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/FlywayExtension.java @@ -15,9 +15,6 @@ */ package org.flywaydb.gradle; -import org.gradle.api.artifacts.Configuration; - -import java.util.List; import java.util.Map; /** @@ -288,12 +285,11 @@ public class FlywayExtension { public String installedBy; /** - * Configurations that will be added to the classpath for running flyway tasks. - *

- * By default flyway respects compile, runtime, testCompile, testRuntime (in this order). - * {@code empty list or null} for accepting the default classpath. (default: {@code null}). + * Gradle configurations that will be added to the classpath for running Flyway tasks. + * (default: compile, runtime, testCompile, testRuntime) + *

Also configurable with Gradle or System Property: ${flyway.configurations}

*/ - public List classpathExtensions; + public String[] configurations; /** * The fully qualified class names of handlers for errors and warnings that occur during a migration. This can be @@ -329,4 +325,4 @@ public class FlywayExtension { *

Also configurable with Gradle or System Property: ${flyway.configFiles}

*/ public String[] configFiles; -} +} \ No newline at end of file diff --git a/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/task/AbstractFlywayTask.java b/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/task/AbstractFlywayTask.java index 9641b25cf1..e396bca339 100644 --- a/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/task/AbstractFlywayTask.java +++ b/flyway-gradle-plugin/src/main/java/org/flywaydb/gradle/task/AbstractFlywayTask.java @@ -22,8 +22,8 @@ import org.flywaydb.core.internal.util.StringUtils; import org.flywaydb.gradle.FlywayExtension; import org.gradle.api.DefaultTask; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ResolvedArtifact; +import org.gradle.api.artifacts.ResolvedConfiguration; import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; @@ -32,17 +32,18 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import static org.flywaydb.core.internal.configuration.ConfigUtils.putIfSet; @@ -51,6 +52,11 @@ */ @SuppressWarnings("WeakerAccess") public abstract class AbstractFlywayTask extends DefaultTask { + /** + * The default Gradle configurations to use. + */ + private static final String[] DEFAULT_CONFIGURATIONS = {"compile", "runtime", "testCompile", "testRuntime"}; + /** * The flyway {} block in the build script. */ @@ -318,12 +324,11 @@ public abstract class AbstractFlywayTask extends DefaultTask { public String installedBy; /** - * Configurations that will be added to the classpath for running flyway tasks. - *

- * By default flyway respects compile, runtime, testCompile, testRuntime (in this order). - * {@code empty list or null} for accepting the default classpath. (default: {@code null}). + * Gradle configurations that will be added to the classpath for running Flyway tasks. + * (default: compile, runtime, testCompile, testRuntime) + *

Also configurable with Gradle or System Property: ${flyway.configurations}

*/ - public List classpathExtensions; + public String[] configurations; /** * The fully qualified class names of handlers for errors and warnings that occur during a migration. This can be @@ -370,79 +375,80 @@ public AbstractFlywayTask() { @TaskAction public Object runTask() { try { - List extraURLs = new ArrayList<>(); - if (isJavaProject()) { - JavaPluginConvention plugin = getProject().getConvention().getPlugin(JavaPluginConvention.class); - - for (SourceSet sourceSet : plugin.getSourceSets()) { - try { - @SuppressWarnings("JavaReflectionMemberAccess") - Method getClassesDirs = SourceSetOutput.class.getMethod("getClassesDirs"); - - // use alternative method available in Gradle 4.0 - FileCollection classesDirs = (FileCollection) getClassesDirs.invoke(sourceSet.getOutput()); - for (File directory : classesDirs.getFiles()) { - URL classesUrl = directory.toURI().toURL(); - getLogger().debug("Adding directory to Classpath: " + classesUrl); - extraURLs.add(classesUrl); - } - } catch (NoSuchMethodException e) { - // use original method available in Gradle 3.x - URL classesUrl = sourceSet.getOutput().getClassesDir().toURI().toURL(); - getLogger().debug("Adding directory to Classpath: " + classesUrl); - extraURLs.add(classesUrl); - } - - URL resourcesUrl = sourceSet.getOutput().getResourcesDir().toURI().toURL(); - getLogger().debug("Adding directory to Classpath: " + resourcesUrl); - extraURLs.add(resourcesUrl); - } + Map envVars = ConfigUtils.environmentVariablesToPropertyMap(); - addClasspathDependencies(extraURLs); + Set extraURLs = new HashSet<>(); + if (isJavaProject()) { + addClassesAndResourcesDirs(extraURLs); + addConfigurationArtifacts(determineConfigurations(envVars), extraURLs); } ClassLoader classLoader = new URLClassLoader( extraURLs.toArray(new URL[extraURLs.size()]), getProject().getBuildscript().getClassLoader()); - return run(Flyway.config(classLoader).configure(createFlywayConfig()).load()); + return run(Flyway.config(classLoader).configure(createFlywayConfig(envVars)).load()); } catch (Exception e) { handleException(e); return null; } } - // classpath methods having protected access to allow for adaption/override in a users custom flyway tasks - protected void addClasspathDependencies(List urls) throws IOException { - addDefaultClasspathDependencies(urls); - addClasspathExtensionDependencies(urls); - } + private void addClassesAndResourcesDirs(Set extraURLs) throws IllegalAccessException, InvocationTargetException, MalformedURLException { + JavaPluginConvention plugin = getProject().getConvention().getPlugin(JavaPluginConvention.class); - protected void addDefaultClasspathDependencies(List urls) throws IOException { - for (String scope : Arrays.asList("compile", "runtime", "testCompile", "testRuntime")) { - addDependenciesWithScope(urls, scope); - } - } + for (SourceSet sourceSet : plugin.getSourceSets()) { + try { + @SuppressWarnings("JavaReflectionMemberAccess") + Method getClassesDirs = SourceSetOutput.class.getMethod("getClassesDirs"); - protected void addDependenciesWithScope(List urls, String scope) throws IOException { - final Configuration configuration = getProject().getConfigurations().getByName(scope); - addDependenciesWithScope(urls, configuration); + // use alternative method available in Gradle 4.0 + FileCollection classesDirs = (FileCollection) getClassesDirs.invoke(sourceSet.getOutput()); + for (File directory : classesDirs.getFiles()) { + URL classesUrl = directory.toURI().toURL(); + getLogger().debug("Adding directory to Classpath: " + classesUrl); + extraURLs.add(classesUrl); + } + } catch (NoSuchMethodException e) { + // use original method available in Gradle 3.x + URL classesUrl = sourceSet.getOutput().getClassesDir().toURI().toURL(); + getLogger().debug("Adding directory to Classpath: " + classesUrl); + extraURLs.add(classesUrl); + } + + URL resourcesUrl = sourceSet.getOutput().getResourcesDir().toURI().toURL(); + getLogger().debug("Adding directory to Classpath: " + resourcesUrl); + extraURLs.add(resourcesUrl); + } } - protected void addClasspathExtensionDependencies(List urls) throws IOException { - List classPathConfigs = this.classpathExtensions != null ? this.classpathExtensions : nullToEmpty(this.extension.classpathExtensions); - for (Configuration configuration : classPathConfigs) { - getLogger().debug("Adding extension to classpath: " + configuration); - addDependenciesWithScope(urls, configuration); + private void addConfigurationArtifacts(String[] configurations, Set urls) throws IOException { + for (String configuration : configurations) { + getLogger().debug("Adding configuration to classpath: " + configuration); + ResolvedConfiguration resolvedConfiguration = + getProject().getConfigurations().getByName(configuration).getResolvedConfiguration(); + for (ResolvedArtifact artifact : resolvedConfiguration.getResolvedArtifacts()) { + URL artifactUrl = artifact.getFile().toURI().toURL(); + getLogger().debug("Adding artifact to classpath: " + artifactUrl); + urls.add(artifactUrl); + } } } - protected void addDependenciesWithScope(List urls, Configuration configuration) throws MalformedURLException { - for (ResolvedArtifact artifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) { - URL artifactUrl = artifact.getFile().toURI().toURL(); - getLogger().debug("Adding dependency to classpath: " + artifactUrl); - urls.add(artifactUrl); + private String[] determineConfigurations(Map envVars) { + if (envVars.containsKey(ConfigUtils.CONFIGURATIONS)) { + return StringUtils.tokenizeToStringArray(envVars.get(ConfigUtils.CONFIGURATIONS), ","); + } + if (System.getProperties().containsKey(ConfigUtils.CONFIGURATIONS)) { + return StringUtils.tokenizeToStringArray(System.getProperties().getProperty(ConfigUtils.CONFIGURATIONS), ","); } + if (configurations != null) { + return configurations; + } + if (extension.configurations != null) { + return extension.configurations; + } + return DEFAULT_CONFIGURATIONS; } /** @@ -456,11 +462,10 @@ protected void addDependenciesWithScope(List urls, Configuration configurat /** * Creates the Flyway config to use. */ - private Map createFlywayConfig() { + private Map createFlywayConfig(Map envVars) { Map conf = new HashMap<>(); conf.put(ConfigUtils.LOCATIONS, Location.FILESYSTEM_PREFIX + getProject().getProjectDir().getAbsolutePath() + "/src/main/resources/db/migration"); - Map envVars = ConfigUtils.environmentVariablesToPropertyMap(); addConfigFromProperties(conf, loadConfigurationFromDefaultConfigFiles(envVars)); putIfSet(conf, ConfigUtils.DRIVER, driver, extension.driver); @@ -643,6 +648,7 @@ private File toFile(String fileName) { private static void removeGradlePluginSpecificPropertiesToAvoidWarnings(Map conf) { conf.remove(ConfigUtils.CONFIG_FILES); conf.remove(ConfigUtils.CONFIG_FILE_ENCODING); + conf.remove(ConfigUtils.CONFIGURATIONS); conf.remove("flyway.version"); } @@ -685,14 +691,7 @@ private String collectMessages(Throwable throwable, String message) { return message; } - private List nullToEmpty(List input) { - if (input != null) { - return input; - } - return Collections.emptyList(); - } - private boolean isJavaProject() { return getProject().getPluginManager().hasPlugin("java"); } -} +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5f007a8c50..a083404321 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,6 @@ -