Browse Source
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-912pull/941/head
18 changed files with 586 additions and 448 deletions
@ -0,0 +1,35 @@
@@ -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); |
||||
|
||||
} |
||||
@ -0,0 +1,34 @@
@@ -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 @@
@@ -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"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,65 @@
@@ -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); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -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); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,59 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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