mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Various improvements to the Gradle plugin
Refactor and rework several areas of the Gradle plugin: - Refactor package structure into functional areas and configure each area separately via a new PluginFeatures interface. - Convert BootRunTask to extend RunTask rather than attempting to find existing RunTasks. - Simplify agent integration by no longer needing specific BootRunTask code. - Update the repackage task to consider the `mainClassName` property in addition to `springBoot.mainClass`. - Automatically set `mainClassName` when calling `run` or `runBoot` from `springBoot.mainClass` if there is one. - Ensure that explicitly defined `main` options on JavaExec tasks always take precedence. Fixes gh-547, gh-820, gh-886, gh-912
This commit is contained in:
parent
d31988b552
commit
794808b6b8
@ -400,8 +400,9 @@ The following configuration options are available:
|
||||
|Name |Description
|
||||
|
||||
|`mainClass`
|
||||
|The main class that should be run. If not specified the value from the manifest will be
|
||||
used, or if no manifest entry is the archive will be searched for a suitable class.
|
||||
|The main class that should be run. If not specified the `mainClassName` project property
|
||||
will be used or, if the no `mainClassName` id defined the archive will be searched for a
|
||||
suitable class.
|
||||
|
||||
|`providedConfiguration`
|
||||
|The name of the provided configuration (defaults to `providedRuntime`).
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* A specific set of {@link Plugin} features applied via the {@link SpringBootPlugin}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface PluginFeatures {
|
||||
|
||||
/**
|
||||
* Apply the features to the specified project.
|
||||
* @param project the project to apply features to
|
||||
*/
|
||||
public void apply(Project project);
|
||||
|
||||
}
|
@ -16,19 +16,15 @@
|
||||
|
||||
package org.springframework.boot.gradle;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.plugins.ApplicationPlugin;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.springframework.boot.gradle.task.ComputeMain;
|
||||
import org.springframework.boot.gradle.task.Repackage;
|
||||
import org.springframework.boot.gradle.task.RunApp;
|
||||
import org.springframework.boot.gradle.task.RunWithAgent;
|
||||
import org.springframework.boot.gradle.agent.AgentPluginFeatures;
|
||||
import org.springframework.boot.gradle.repackage.RepackagePluginFeatures;
|
||||
import org.springframework.boot.gradle.resolve.ResolvePluginFeatures;
|
||||
import org.springframework.boot.gradle.run.RunPluginFeatures;
|
||||
|
||||
/**
|
||||
* Gradle 'Spring Boot' {@link Plugin}.
|
||||
@ -38,91 +34,18 @@ import org.springframework.boot.gradle.task.RunWithAgent;
|
||||
*/
|
||||
public class SpringBootPlugin implements Plugin<Project> {
|
||||
|
||||
private static final String REPACKAGE_TASK_NAME = "bootRepackage";
|
||||
|
||||
private static final String RUN_APP_TASK_NAME = "bootRun";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
|
||||
project.getConfigurations().create(
|
||||
SpringBootResolutionStrategy.VERSION_MANAGEMENT_CONFIGURATION);
|
||||
|
||||
applyRepackage(project);
|
||||
applyRun(project);
|
||||
|
||||
project.getPlugins().apply(BasePlugin.class);
|
||||
project.getPlugins().apply(JavaPlugin.class);
|
||||
project.getPlugins().apply(ApplicationPlugin.class);
|
||||
|
||||
project.getExtensions().create("springBoot", SpringBootPluginExtension.class);
|
||||
|
||||
applyResolutionStrategy(project);
|
||||
|
||||
new AgentPluginFeatures().apply(project);
|
||||
new ResolvePluginFeatures().apply(project);
|
||||
new RepackagePluginFeatures().apply(project);
|
||||
new RunPluginFeatures().apply(project);
|
||||
}
|
||||
|
||||
private void applyRepackage(Project project) {
|
||||
Repackage packageTask = addRepackageTask(project);
|
||||
ensureTaskRunsOnAssembly(project, packageTask);
|
||||
// register BootRepackage so that we can use task foo(type: BootRepackage) {}
|
||||
project.getExtensions().getExtraProperties()
|
||||
.set("BootRepackage", Repackage.class);
|
||||
}
|
||||
|
||||
private void applyRun(Project project) {
|
||||
enhanceRunTask(project);
|
||||
addRunAppTask(project);
|
||||
if (project.getTasks().withType(JavaExec.class).isEmpty()) {
|
||||
// Add the ApplicationPlugin so that a JavaExec task is available (run) to
|
||||
// enhance
|
||||
project.getPlugins().apply(ApplicationPlugin.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void enhanceRunTask(Project project) {
|
||||
project.getLogger().debug("Enhancing run tasks");
|
||||
project.getTasks().whenTaskAdded(new RunWithAgent(project));
|
||||
project.getTasks().whenTaskAdded(new ComputeMain(project));
|
||||
}
|
||||
|
||||
private void applyResolutionStrategy(final Project project) {
|
||||
project.getConfigurations().all(new Action<Configuration>() {
|
||||
|
||||
@Override
|
||||
public void execute(Configuration configuration) {
|
||||
SpringBootResolutionStrategy.apply(project, configuration);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private Repackage addRepackageTask(Project project) {
|
||||
Repackage packageTask = project.getTasks().create(REPACKAGE_TASK_NAME,
|
||||
Repackage.class);
|
||||
packageTask.setDescription("Repackage existing JAR and WAR "
|
||||
+ "archives so that they can be executed from the command "
|
||||
+ "line using 'java -jar'");
|
||||
packageTask.setGroup(BasePlugin.BUILD_GROUP);
|
||||
packageTask.dependsOn(project.getConfigurations()
|
||||
.getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts()
|
||||
.getBuildDependencies());
|
||||
return packageTask;
|
||||
}
|
||||
|
||||
private void addRunAppTask(Project project) {
|
||||
RunApp runJarTask = project.getTasks().create(RUN_APP_TASK_NAME, RunApp.class);
|
||||
runJarTask.setDescription("Run the project with support for "
|
||||
+ "auto-detecting main class and reloading static resources");
|
||||
runJarTask.setGroup("Execution");
|
||||
if (!project.getTasksByName("compileJava", false).isEmpty()) {
|
||||
if (!project.getTasksByName("compileGroovy", false).isEmpty()) {
|
||||
runJarTask.dependsOn("compileJava", "compileGroovy");
|
||||
}
|
||||
else {
|
||||
runJarTask.dependsOn("compileJava");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureTaskRunsOnAssembly(Project project, Repackage task) {
|
||||
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.boot.gradle
|
||||
import org.springframework.boot.loader.tools.Layout
|
||||
import org.springframework.boot.loader.tools.Layouts
|
||||
|
||||
|
||||
/**
|
||||
* Gradle DSL Extension for 'Spring Boot'. Most of the time Spring Boot can guess the
|
||||
* settings in this extension, but occasionally you might need to explicitly set one
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.agent;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.springframework.boot.gradle.PluginFeatures;
|
||||
|
||||
/**
|
||||
* {@link PluginFeatures} to add Java Agent support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AgentPluginFeatures implements PluginFeatures {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.afterEvaluate(new AgentTasksEnhancer());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.agent;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.CodeSource;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.springframework.boot.gradle.SpringBootPluginExtension;
|
||||
|
||||
/**
|
||||
* Add a java agent to the "run" task if configured. You can add an agent in 3 ways (4 if
|
||||
* you want to use native gradle features as well):
|
||||
*
|
||||
* <ol>
|
||||
* <li>Use "-Prun.agent=[path-to-jar]" on the gradle command line</li>
|
||||
* <li>Add an "agent" property (jar file) to the "springBoot" extension in build.gradle</li>
|
||||
* <li>As a special case springloaded is detected as a build script dependency</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AgentTasksEnhancer implements Action<Project> {
|
||||
|
||||
private static final String SPRING_LOADED_AGENT_CLASSNAME = "org.springsource.loaded.agent.SpringLoadedAgent";
|
||||
|
||||
private File agent;
|
||||
|
||||
private Boolean noverify;
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
setup(project);
|
||||
if (this.agent != null) {
|
||||
for (Task task : project.getTasks()) {
|
||||
addAgent(project, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(Project project) {
|
||||
project.getLogger().info("Configuring agent");
|
||||
SpringBootPluginExtension extension = project.getExtensions().getByType(
|
||||
SpringBootPluginExtension.class);
|
||||
this.noverify = extension.getNoverify();
|
||||
this.agent = getAgent(project, extension);
|
||||
if (this.agent == null) {
|
||||
this.agent = getSpringLoadedAgent();
|
||||
if (this.noverify == null) {
|
||||
this.noverify = true;
|
||||
}
|
||||
}
|
||||
project.getLogger().debug("Agent: " + this.agent);
|
||||
}
|
||||
|
||||
private File getAgent(Project project, SpringBootPluginExtension extension) {
|
||||
if (project.hasProperty("run.agent")) {
|
||||
return project.file(project.property("run.agent"));
|
||||
}
|
||||
return extension.getAgent();
|
||||
}
|
||||
|
||||
private File getSpringLoadedAgent() {
|
||||
try {
|
||||
Class<?> loaded = Class.forName(SPRING_LOADED_AGENT_CLASSNAME);
|
||||
if (loaded != null) {
|
||||
CodeSource source = loaded.getProtectionDomain().getCodeSource();
|
||||
if (source != null) {
|
||||
return new File(source.getLocation().getFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// ignore;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addAgent(Project project, Task task) {
|
||||
if (task instanceof JavaExec) {
|
||||
addAgent(project, (JavaExec) task);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAgent(Project project, JavaExec exec) {
|
||||
project.getLogger().debug("Attaching to: " + exec);
|
||||
if (this.agent != null) {
|
||||
project.getLogger().info("Attaching agent: " + this.agent);
|
||||
exec.jvmArgs("-javaagent:" + this.agent.getAbsolutePath());
|
||||
if (this.noverify != null && this.noverify) {
|
||||
exec.jvmArgs("-noverify");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.task;
|
||||
package org.springframework.boot.gradle.repackage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.repackage;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.springframework.boot.gradle.PluginFeatures;
|
||||
|
||||
/**
|
||||
* {@link PluginFeatures} to add repackage support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RepackagePluginFeatures implements PluginFeatures {
|
||||
|
||||
private static final String REPACKAGE_TASK_NAME = "bootRepackage";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
addRepackageTask(project);
|
||||
registerRepackageTaskProperty(project);
|
||||
}
|
||||
|
||||
private void addRepackageTask(Project project) {
|
||||
RepackageTask task = project.getTasks().create(REPACKAGE_TASK_NAME,
|
||||
RepackageTask.class);
|
||||
task.setDescription("Repackage existing JAR and WAR "
|
||||
+ "archives so that they can be executed from the command "
|
||||
+ "line using 'java -jar'");
|
||||
task.setGroup(BasePlugin.BUILD_GROUP);
|
||||
task.dependsOn(project.getConfigurations()
|
||||
.getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts()
|
||||
.getBuildDependencies());
|
||||
ensureTaskRunsOnAssembly(project, task);
|
||||
}
|
||||
|
||||
private void ensureTaskRunsOnAssembly(Project project, Task task) {
|
||||
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register BootRepackage so that we can use task {@code foo(type: BootRepackage)}.
|
||||
*/
|
||||
private void registerRepackageTaskProperty(Project project) {
|
||||
project.getExtensions().getExtraProperties()
|
||||
.set("BootRepackage", RepackageTask.class);
|
||||
}
|
||||
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.task;
|
||||
package org.springframework.boot.gradle.repackage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.bundling.Jar;
|
||||
import org.springframework.boot.gradle.SpringBootPluginExtension;
|
||||
@ -31,11 +30,11 @@ import org.springframework.boot.loader.tools.Repackager;
|
||||
|
||||
/**
|
||||
* Repackage task.
|
||||
*
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class Repackage extends DefaultTask {
|
||||
public class RepackageTask extends DefaultTask {
|
||||
|
||||
private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
@ -72,11 +71,6 @@ public class Repackage extends DefaultTask {
|
||||
else if (extension.getCustomConfiguration() != null) {
|
||||
libraries.setCustomConfigurationName(extension.getCustomConfiguration());
|
||||
}
|
||||
JavaExec runner = (JavaExec) project.getTasks().findByName("run");
|
||||
if (runner != null && this.mainClass == null) {
|
||||
getLogger().info("Found main in run task: " + runner.getMain());
|
||||
setMainClass(runner.getMain());
|
||||
}
|
||||
project.getTasks().withType(Jar.class, new RepackageAction(extension, libraries));
|
||||
}
|
||||
|
||||
@ -95,8 +89,8 @@ public class Repackage extends DefaultTask {
|
||||
@Override
|
||||
public void execute(Jar archive) {
|
||||
// if withJarTask is set, compare tasks and bail out if we didn't match
|
||||
if (Repackage.this.withJarTask != null
|
||||
&& !archive.equals(Repackage.this.withJarTask)) {
|
||||
if (RepackageTask.this.withJarTask != null
|
||||
&& !archive.equals(RepackageTask.this.withJarTask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -104,10 +98,7 @@ public class Repackage extends DefaultTask {
|
||||
File file = archive.getArchivePath();
|
||||
if (file.exists()) {
|
||||
Repackager repackager = new LoggingRepackager(file);
|
||||
repackager.setMainClass(this.extension.getMainClass());
|
||||
if (Repackage.this.mainClass != null) {
|
||||
repackager.setMainClass(Repackage.this.mainClass);
|
||||
}
|
||||
setMainClass(repackager);
|
||||
if (this.extension.convertLayout() != null) {
|
||||
repackager.setLayout(this.extension.convertLayout());
|
||||
}
|
||||
@ -121,6 +112,16 @@ public class Repackage extends DefaultTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setMainClass(Repackager repackager) {
|
||||
repackager.setMainClass((String) getProject().property("mainClassName"));
|
||||
if (this.extension.getMainClass() != null) {
|
||||
repackager.setMainClass(this.extension.getMainClass());
|
||||
}
|
||||
if (RepackageTask.this.mainClass != null) {
|
||||
repackager.setMainClass(RepackageTask.this.mainClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LoggingRepackager extends Repackager {
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.resolve;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.springframework.boot.gradle.PluginFeatures;
|
||||
|
||||
/**
|
||||
* {@link PluginFeatures} to add version resolution support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ResolvePluginFeatures implements PluginFeatures {
|
||||
|
||||
@Override
|
||||
public void apply(final Project project) {
|
||||
project.getConfigurations().create(
|
||||
SpringBootResolutionStrategy.VERSION_MANAGEMENT_CONFIGURATION);
|
||||
project.getConfigurations().all(new Action<Configuration>() {
|
||||
@Override
|
||||
public void execute(Configuration configuration) {
|
||||
SpringBootResolutionStrategy.applyToConfiguration(project, configuration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle;
|
||||
package org.springframework.boot.gradle.resolve;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -31,7 +46,7 @@ public class SpringBootResolutionStrategy {
|
||||
|
||||
private static final String SPRING_BOOT_GROUP = "org.springframework.boot";
|
||||
|
||||
public static void apply(final Project project, Configuration configuration) {
|
||||
public static void applyToConfiguration(final Project project, Configuration configuration) {
|
||||
if (VERSION_MANAGEMENT_CONFIGURATION.equals(configuration.getName())) {
|
||||
return;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.run;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.internal.file.collections.SimpleFileCollection;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
|
||||
/**
|
||||
* Extension of the standard 'run' task with additional Spring Boot features.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class BootRunTask extends JavaExec {
|
||||
|
||||
@Override
|
||||
public void exec() {
|
||||
SourceSet mainSourceSet = SourceSets.findMainSourceSet(getProject());
|
||||
final File outputDir = (mainSourceSet == null ? null : mainSourceSet.getOutput()
|
||||
.getResourcesDir());
|
||||
final Set<File> resources = new LinkedHashSet<File>();
|
||||
if (mainSourceSet != null) {
|
||||
resources.addAll(mainSourceSet.getResources().getSrcDirs());
|
||||
}
|
||||
List<File> classPath = new ArrayList<File>(getClasspath().getFiles());
|
||||
classPath.addAll(0, resources);
|
||||
getLogger().info("Adding classpath: " + resources);
|
||||
setClasspath(new SimpleFileCollection(classPath));
|
||||
if (outputDir != null) {
|
||||
for (File directory : resources) {
|
||||
FileUtils.removeDuplicatesFromOutputDirectory(outputDir, directory);
|
||||
}
|
||||
}
|
||||
super.exec();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package org.springframework.boot.gradle.run;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.springframework.boot.gradle.SpringBootPluginExtension;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
* Task to find and set the 'mainClassName' convention when it's missing by searching the
|
||||
* main source code.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class FindMainClassTask extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
public void setMainClassNameProperty() {
|
||||
Project project = getProject();
|
||||
if (project.property("mainClassName") == null) {
|
||||
project.setProperty("mainClassName", findMainClass());
|
||||
}
|
||||
}
|
||||
|
||||
private String findMainClass() {
|
||||
Project project = getProject();
|
||||
|
||||
// Try the SpringBoot extension setting
|
||||
SpringBootPluginExtension bootExtension = project.getExtensions().getByType(
|
||||
SpringBootPluginExtension.class);
|
||||
if(bootExtension.getMainClass() != null) {
|
||||
return bootExtension.getMainClass();
|
||||
}
|
||||
|
||||
// Search
|
||||
SourceSet mainSourceSet = SourceSets.findMainSourceSet(project);
|
||||
if (mainSourceSet == null) {
|
||||
return null;
|
||||
}
|
||||
project.getLogger().debug(
|
||||
"Looking for main in: " + mainSourceSet.getOutput().getClassesDir());
|
||||
try {
|
||||
String mainClass = MainClassFinder.findSingleMainClass(mainSourceSet
|
||||
.getOutput().getClassesDir());
|
||||
project.getLogger().info("Computed main class: " + mainClass);
|
||||
return mainClass;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot find main class", ex);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.run;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.springframework.boot.gradle.PluginFeatures;
|
||||
|
||||
/**
|
||||
* {@link PluginFeatures} to add run support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RunPluginFeatures implements PluginFeatures {
|
||||
|
||||
private static final String FIND_MAIN_CLASS_TASK_NAME = "findMainClass";
|
||||
|
||||
private static final String RUN_APP_TASK_NAME = "bootRun";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
mainClassNameFinder(project);
|
||||
addBootRunTask(project);
|
||||
}
|
||||
|
||||
private void mainClassNameFinder(Project project) {
|
||||
project.getTasks().create(FIND_MAIN_CLASS_TASK_NAME, FindMainClassTask.class);
|
||||
project.getTasks().all(new Action<Task>() {
|
||||
@Override
|
||||
public void execute(Task task) {
|
||||
if(task instanceof JavaExec) {
|
||||
task.dependsOn(FIND_MAIN_CLASS_TASK_NAME);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addBootRunTask(final Project project) {
|
||||
final JavaPluginConvention javaConvention = project.getConvention().getPlugin(
|
||||
JavaPluginConvention.class);
|
||||
|
||||
BootRunTask run = project.getTasks().create(RUN_APP_TASK_NAME, BootRunTask.class);
|
||||
run.setDescription("Run the project with support for "
|
||||
+ "auto-detecting main class and reloading static resources");
|
||||
run.setGroup("application");
|
||||
run.setClasspath(javaConvention.getSourceSets().findByName("main")
|
||||
.getRuntimeClasspath());
|
||||
run.getConventionMapping().map("main", new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
return project.property("mainClassName");
|
||||
}
|
||||
});
|
||||
run.getConventionMapping().map("jvmArgs", new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
return project.property("applicationDefaultJvmArgs");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.run;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
/**
|
||||
* Utilities for working with {@link SourceSet}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class SourceSets {
|
||||
|
||||
public static SourceSet findMainSourceSet(Project project) {
|
||||
for (SourceSet sourceSet : getJavaSourceSets(project)) {
|
||||
if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) {
|
||||
return sourceSet;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Iterable<SourceSet> getJavaSourceSets(Project project) {
|
||||
JavaPluginConvention plugin = project.getConvention().getPlugin(
|
||||
JavaPluginConvention.class);
|
||||
if(plugin == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return plugin.getSourceSets();
|
||||
}
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.task;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
* Add a main class if one is missing from the build
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ComputeMain implements Action<Task> {
|
||||
|
||||
private Project project;
|
||||
|
||||
public ComputeMain(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Task task) {
|
||||
if (task instanceof JavaExec) {
|
||||
final JavaExec exec = (JavaExec) task;
|
||||
this.project.afterEvaluate(new Action<Project>() {
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
addMain(exec);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void addMain(JavaExec exec) {
|
||||
if (exec.getMain() == null) {
|
||||
this.project.getLogger().debug("Computing main for: " + exec);
|
||||
this.project.setProperty("mainClassName", findMainClass(this.project));
|
||||
}
|
||||
}
|
||||
|
||||
private String findMainClass(Project project) {
|
||||
SourceSet main = findMainSourceSet(project);
|
||||
if (main == null) {
|
||||
return null;
|
||||
}
|
||||
project.getLogger().debug(
|
||||
"Looking for main in: " + main.getOutput().getClassesDir());
|
||||
try {
|
||||
String mainClass = MainClassFinder.findSingleMainClass(main.getOutput()
|
||||
.getClassesDir());
|
||||
project.getLogger().info("Computed main class: " + mainClass);
|
||||
return mainClass;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot find main class", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static SourceSet findMainSourceSet(Project project) {
|
||||
final AtomicReference<SourceSet> main = new AtomicReference<SourceSet>();
|
||||
JavaPluginConvention javaConvention = project.getConvention().getPlugin(
|
||||
JavaPluginConvention.class);
|
||||
javaConvention.getSourceSets().all(new Action<SourceSet>() {
|
||||
|
||||
@Override
|
||||
public void execute(SourceSet set) {
|
||||
if (SourceSet.MAIN_SOURCE_SET_NAME.equals(set.getName())) {
|
||||
main.set(set);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
return main.get();
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.task;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.internal.file.collections.SimpleFileCollection;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
* Run the project from Gradle.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class RunApp extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
public void runApp() {
|
||||
|
||||
final Project project = getProject();
|
||||
final SourceSet main = ComputeMain.findMainSourceSet(project);
|
||||
final File outputDir = (main == null ? null : main.getOutput().getResourcesDir());
|
||||
final Set<File> allResources = new LinkedHashSet<File>();
|
||||
if (main != null) {
|
||||
allResources.addAll(main.getResources().getSrcDirs());
|
||||
}
|
||||
|
||||
project.getTasks().withType(JavaExec.class, new Action<JavaExec>() {
|
||||
|
||||
@Override
|
||||
public void execute(JavaExec exec) {
|
||||
ArrayList<File> files = new ArrayList<File>(exec.getClasspath()
|
||||
.getFiles());
|
||||
files.addAll(0, allResources);
|
||||
getLogger().info("Adding classpath: " + allResources);
|
||||
exec.setClasspath(new SimpleFileCollection(files));
|
||||
if (exec.getMain() == null) {
|
||||
final String mainClass = findMainClass(main);
|
||||
exec.setMain(mainClass);
|
||||
exec.getConventionMapping().map("main", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
});
|
||||
getLogger().info("Found main: " + mainClass);
|
||||
}
|
||||
if (outputDir != null) {
|
||||
for (File directory : allResources) {
|
||||
FileUtils.removeDuplicatesFromOutputDirectory(outputDir, directory);
|
||||
}
|
||||
}
|
||||
exec.exec();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private String findMainClass(SourceSet main) {
|
||||
if (main == null) {
|
||||
return null;
|
||||
}
|
||||
getLogger().info("Looking for main in: " + main.getOutput().getClassesDir());
|
||||
try {
|
||||
return MainClassFinder.findSingleMainClass(main.getOutput().getClassesDir());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot find main class", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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 org.springframework.boot.gradle.task;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.CodeSource;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.springframework.boot.gradle.SpringBootPluginExtension;
|
||||
import org.springframework.boot.loader.tools.AgentAttacher;
|
||||
import org.springframework.core.task.TaskRejectedException;
|
||||
|
||||
/**
|
||||
* Add a java agent to the "run" task if configured. You can add an agent in 3 ways (4 if
|
||||
* you want to use native gradle features as well):
|
||||
*
|
||||
* <ol>
|
||||
* <li>Use "-Prun.agent=[path-to-jar]" on the gradle command line</li>
|
||||
* <li>Add an "agent" property (jar file) to the "springBoot" extension in build.gradle</li>
|
||||
* <li>As a special case springloaded is detected as a build script dependency</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class RunWithAgent implements Action<Task> {
|
||||
|
||||
private static final String SPRING_LOADED_AGENT_CLASSNAME = "org.springsource.loaded.agent.SpringLoadedAgent";
|
||||
|
||||
private File agent;
|
||||
|
||||
private Project project;
|
||||
|
||||
private Boolean noverify;
|
||||
|
||||
public RunWithAgent(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final Task task) {
|
||||
if (task instanceof JavaExec) {
|
||||
this.project.afterEvaluate(new Action<Project>() {
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
addAgent((JavaExec) task);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (task instanceof RunApp) {
|
||||
this.project.beforeEvaluate(new Action<Project>() {
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
addAgent((RunApp) task);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void addAgent(RunApp exec) {
|
||||
this.project.getLogger().debug("Attaching to: " + exec);
|
||||
findAgent(this.project.getExtensions().getByType(SpringBootPluginExtension.class));
|
||||
if (this.agent != null) {
|
||||
exec.doFirst(new Action<Task>() {
|
||||
@Override
|
||||
public void execute(Task task) {
|
||||
RunWithAgent.this.project.getLogger().info(
|
||||
"Attaching agent: " + RunWithAgent.this.agent);
|
||||
if (RunWithAgent.this.noverify != null && RunWithAgent.this.noverify
|
||||
&& !AgentAttacher.hasNoVerify()) {
|
||||
throw new TaskRejectedException(
|
||||
"The JVM must be started with -noverify for this "
|
||||
+ "agent to work. You can use JAVA_OPTS "
|
||||
+ "to add that flag.");
|
||||
}
|
||||
AgentAttacher.attach(RunWithAgent.this.agent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void addAgent(JavaExec exec) {
|
||||
this.project.getLogger().debug("Attaching to: " + exec);
|
||||
findAgent(this.project.getExtensions().getByType(SpringBootPluginExtension.class));
|
||||
if (this.agent != null) {
|
||||
this.project.getLogger().info("Attaching agent: " + this.agent);
|
||||
exec.jvmArgs("-javaagent:" + this.agent.getAbsolutePath());
|
||||
if (this.noverify != null && this.noverify) {
|
||||
exec.jvmArgs("-noverify");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void findAgent(SpringBootPluginExtension extension) {
|
||||
if (this.agent != null) {
|
||||
return;
|
||||
}
|
||||
this.noverify = this.project.getExtensions()
|
||||
.getByType(SpringBootPluginExtension.class).getNoverify();
|
||||
this.project.getLogger().info("Finding agent");
|
||||
if (this.project.hasProperty("run.agent")) {
|
||||
this.agent = this.project.file(this.project.property("run.agent"));
|
||||
}
|
||||
else if (extension.getAgent() != null) {
|
||||
this.agent = extension.getAgent();
|
||||
}
|
||||
if (this.agent == null) {
|
||||
try {
|
||||
Class<?> loaded = Class.forName(SPRING_LOADED_AGENT_CLASSNAME);
|
||||
if (this.agent == null && loaded != null) {
|
||||
if (this.noverify == null) {
|
||||
this.noverify = true;
|
||||
}
|
||||
CodeSource source = loaded.getProtectionDomain().getCodeSource();
|
||||
if (source != null) {
|
||||
this.agent = new File(source.getLocation().getFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// ignore;
|
||||
}
|
||||
}
|
||||
this.project.getLogger().debug("Agent: " + this.agent);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user