diff --git a/pom.xml b/pom.xml
index a5d47378892..5826f7c8cdf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,6 +19,7 @@
2.2.4.RELEASE
2.2.0.RELEASE
2.1.6
+ 1.6
7.0.42
8.1.9.v20130131
1.7.3
@@ -42,11 +43,34 @@
spring-boot-loader
spring-boot-loader-tools
spring-boot-maven-plugin
+ spring-boot-gradle-plugin
spring-boot-ops
spring-boot-ups
spring-boot-cli
spring-boot-integration-tests
+
+
+ spring-ext
+ http://repo.springsource.org/ext-release-local/
+
+ true
+
+
+ false
+
+
+
+ gradle
+ http://repo.gradle.org/gradle/libs-releases-local
+
+ true
+
+
+ false
+
+
+
@@ -368,6 +392,11 @@
groovy
${groovy.version}
+
+ org.codehaus.groovy
+ groovy-all
+ ${groovy.version}
+
org.codehaus.groovy
groovy-templates
@@ -409,6 +438,26 @@
jetty-annotations
${jetty.version}
+
+ org.gradle
+ gradle-core
+ ${gradle.version}
+
+
+ org.gradle
+ gradle-base-services
+ ${gradle.version}
+
+
+ org.gradle
+ gradle-base-services-groovy
+ ${gradle.version}
+
+
+ org.gradle
+ gradle-plugins
+ ${gradle.version}
+
org.hamcrest
hamcrest-library
diff --git a/spring-boot-gradle-plugin/README.md b/spring-boot-gradle-plugin/README.md
new file mode 100644
index 00000000000..b059aacb9f0
--- /dev/null
+++ b/spring-boot-gradle-plugin/README.md
@@ -0,0 +1 @@
+# Spring Boot - Gradle Plugin
diff --git a/spring-boot-gradle-plugin/pom.xml b/spring-boot-gradle-plugin/pom.xml
new file mode 100644
index 00000000000..125e6d2ba15
--- /dev/null
+++ b/spring-boot-gradle-plugin/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-parent
+ 0.5.0.BUILD-SNAPSHOT
+
+ spring-boot-gradle-plugin
+
+ ${basedir}/..
+
+
+
+
+ ${project.groupId}
+ spring-boot-loader-tools
+ ${project.version}
+
+
+
+ org.codehaus.groovy
+ groovy-all
+ provided
+
+
+ org.gradle
+ gradle-core
+ provided
+
+
+ org.gradle
+ gradle-base-services
+ provided
+
+
+ org.gradle
+ gradle-base-services-groovy
+ provided
+
+
+ org.gradle
+ gradle-plugins
+ provided
+
+
+
+ src/main/groovy
+
+
+ maven-compiler-plugin
+
+ groovy-eclipse-compiler
+
+
+
+ org.codehaus.groovy
+ groovy-eclipse-compiler
+ 2.8.0-01
+
+
+ org.codehaus.groovy
+ groovy-eclipse-batch
+ 2.1.5-03
+
+
+
+
+
+
diff --git a/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPlugin.java b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPlugin.java
new file mode 100644
index 00000000000..fa36b9f4866
--- /dev/null
+++ b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPlugin.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-2013 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;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.plugins.BasePlugin;
+import org.gradle.api.plugins.JavaPlugin;
+import org.springframework.boot.gradle.task.Repackage;
+
+/**
+ * Gradle 'Spring Boot' {@link Plugin}.
+ *
+ * @author Phillip Webb
+ */
+public class SpringBootPlugin implements Plugin {
+
+ private static final String REPACKAGE_TASK_NAME = "repackage";
+
+ @Override
+ public void apply(Project project) {
+ project.getPlugins().apply(BasePlugin.class);
+ project.getPlugins().apply(JavaPlugin.class);
+ project.getExtensions().create("springBoot", SpringBootPluginExtension.class);
+ Repackage packageTask = addRepackageTask(project);
+ ensureTaksRunsOnAssembly(project, packageTask);
+ }
+
+ 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 ensureTaksRunsOnAssembly(Project project, Repackage task) {
+ project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
+ }
+}
diff --git a/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPluginExtension.groovy b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPluginExtension.groovy
new file mode 100644
index 00000000000..19afbb24559
--- /dev/null
+++ b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPluginExtension.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-2013 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
+
+/**
+ * Gradle DSL Extension for 'Spring Boot'.
+ *
+ * @author Phillip Webb
+ */
+public class SpringBootPluginExtension {
+
+ /**
+ * 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.
+ */
+ String mainClass
+
+ /**
+ * The name of the provided configuration. If not specified 'providedRuntime' will
+ * be used.
+ */
+ String providedConfiguration
+
+ /**
+ * If the original source archive should be backed-up before being repackaged.
+ */
+ boolean backupSource = true;
+}
diff --git a/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/ProjectLibraries.java b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/ProjectLibraries.java
new file mode 100644
index 00000000000..794df876518
--- /dev/null
+++ b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/ProjectLibraries.java
@@ -0,0 +1,68 @@
+package org.springframework.boot.gradle.task;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.file.FileCollection;
+import org.springframework.boot.loader.tools.Libraries;
+import org.springframework.boot.loader.tools.LibraryCallback;
+import org.springframework.boot.loader.tools.LibraryScope;
+
+/**
+ * Expose Gradle {@link Configuration}s as {@link Libraries}.
+ *
+ * @author Phillip Webb
+ */
+class ProjectLibraries implements Libraries {
+
+ private final Project project;
+
+ private String providedConfigurationName = "providedRuntime";
+
+ /**
+ * Create a new {@link ProjectLibraries} instance of the specified {@link Project}.
+ * @param project the gradle project
+ */
+ public ProjectLibraries(Project project) {
+ this.project = project;
+ }
+
+ /**
+ * Set the name of the provided configuration. Defaults to 'providedRuntime'.
+ * @param providedConfigurationName the providedConfigurationName to set
+ */
+ public void setProvidedConfigurationName(String providedConfigurationName) {
+ this.providedConfigurationName = providedConfigurationName;
+ }
+
+ @Override
+ public void doWithLibraries(LibraryCallback callback) throws IOException {
+
+ FileCollection compile = this.project.getConfigurations().getByName("compile");
+
+ FileCollection runtime = this.project.getConfigurations().getByName("runtime");
+ runtime = runtime.minus(compile);
+
+ FileCollection provided = this.project.getConfigurations().findByName(
+ this.providedConfigurationName);
+ if (provided != null) {
+ compile = compile.minus(provided);
+ runtime = compile.minus(provided);
+ }
+
+ libraries(LibraryScope.COMPILE, compile, callback);
+ libraries(LibraryScope.RUNTIME, runtime, callback);
+ libraries(LibraryScope.PROVIDED, provided, callback);
+ }
+
+ private void libraries(LibraryScope scope, FileCollection files,
+ LibraryCallback callback) throws IOException {
+ if (files != null) {
+ for (File file : files) {
+ callback.library(file, scope);
+ }
+ }
+ }
+}
diff --git a/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/Repackage.java b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/Repackage.java
new file mode 100644
index 00000000000..9b455ae0775
--- /dev/null
+++ b/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/Repackage.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012-2013 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 org.gradle.api.Action;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.api.tasks.bundling.Jar;
+import org.springframework.boot.gradle.SpringBootPluginExtension;
+import org.springframework.boot.loader.tools.Repackager;
+
+/**
+ * Repackage task.
+ *
+ * @author Phillip Webb
+ */
+public class Repackage extends DefaultTask {
+
+ @TaskAction
+ public void repackage() {
+ Project project = getProject();
+ final SpringBootPluginExtension extension = project.getExtensions().getByType(
+ SpringBootPluginExtension.class);
+ final ProjectLibraries libraries = new ProjectLibraries(project);
+ if (extension.getProvidedConfiguration() != null) {
+ libraries.setProvidedConfigurationName(extension.getProvidedConfiguration());
+ }
+ project.getTasks().withType(Jar.class, new Action() {
+ @Override
+ public void execute(Jar archive) {
+ File file = archive.getArchivePath();
+ if (file.exists()) {
+ Repackager repackager = new Repackager(file);
+ repackager.setMainClass(extension.getMainClass());
+ repackager.setBackupSource(extension.isBackupSource());
+ try {
+ repackager.repackage(libraries);
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex.getMessage(), ex);
+ }
+ }
+ }
+ });
+ }
+}
diff --git a/spring-boot-gradle-plugin/src/main/resources/META-INF/gradle-plugins/spring-boot.properties b/spring-boot-gradle-plugin/src/main/resources/META-INF/gradle-plugins/spring-boot.properties
new file mode 100644
index 00000000000..68069d5e992
--- /dev/null
+++ b/spring-boot-gradle-plugin/src/main/resources/META-INF/gradle-plugins/spring-boot.properties
@@ -0,0 +1 @@
+implementation-class=org.springframework.boot.gradle.SpringBootPlugin