diff --git a/buildSrc/src/main/java/org/springframework/boot/build/ExtractResources.java b/buildSrc/src/main/java/org/springframework/boot/build/ExtractResources.java new file mode 100644 index 0000000000..1930013896 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/boot/build/ExtractResources.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-2020 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 + * + * https://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.build; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.Task; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.OutputDirectory; +import org.gradle.api.tasks.TaskAction; + +import org.springframework.util.FileCopyUtils; +import org.springframework.util.PropertyPlaceholderHelper; + +/** + * {@link Task} to extract resources from the classpath and write them to disk. + * + * @author Andy Wilkinson + */ +public class ExtractResources extends DefaultTask { + + private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("${", "}"); + + private final Map properties = new HashMap<>(); + + private final DirectoryProperty destinationDirectory; + + private List resourceNames = new ArrayList<>(); + + public ExtractResources() { + this.destinationDirectory = getProject().getObjects().directoryProperty(); + } + + @Input + public List getResourceNames() { + return this.resourceNames; + } + + public void setResourcesNames(List resourceNames) { + this.resourceNames = resourceNames; + } + + @OutputDirectory + public DirectoryProperty getDestinationDirectory() { + return this.destinationDirectory; + } + + public void property(String name, String value) { + this.properties.put(name, value); + } + + @Input + public Map getProperties() { + return this.properties; + } + + @TaskAction + void extractResources() throws IOException { + for (String resourceName : this.resourceNames) { + InputStream resourceStream = getClass().getClassLoader().getResourceAsStream(resourceName); + if (resourceStream == null) { + throw new GradleException("Resource '" + resourceName + "' does not exist"); + } + String resource = FileCopyUtils.copyToString(new InputStreamReader(resourceStream, StandardCharsets.UTF_8)); + resource = this.propertyPlaceholderHelper.replacePlaceholders(resource, + (placeholder) -> this.properties.get(placeholder)); + FileCopyUtils.copy(resource, + new FileWriter(this.destinationDirectory.file(resourceName).get().getAsFile())); + } + } + +} diff --git a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java index b43ee67099..d6a94ee82a 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java @@ -16,12 +16,7 @@ package org.springframework.boot.build; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -29,14 +24,11 @@ import java.util.function.Consumer; import io.spring.javaformat.gradle.FormatTask; import io.spring.javaformat.gradle.SpringJavaFormatPlugin; -import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.artifacts.DependencySet; -import org.gradle.api.file.CopySpec; import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.quality.CheckstyleExtension; import org.gradle.api.plugins.quality.CheckstylePlugin; -import org.gradle.api.resources.TextResourceFactory; import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.compile.JavaCompile; import org.gradle.api.tasks.javadoc.Javadoc; @@ -45,7 +37,6 @@ import org.gradle.testretry.TestRetryPlugin; import org.gradle.testretry.TestRetryTaskExtension; import org.springframework.boot.build.testing.TestFailuresPlugin; -import org.springframework.util.FileCopyUtils; /** * Conventions that are applied in the presence of the {@link JavaBasePlugin}. When the @@ -93,8 +84,13 @@ class JavaConventions { } private void configureJarManifestConventions(Project project) { + ExtractResources extractLegalResources = project.getTasks().create("extractLegalResources", + ExtractResources.class); + extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal")); + extractLegalResources.setResourcesNames(Arrays.asList("LICENSE.txt", "NOTICE.txt")); + extractLegalResources.property("version", project.getVersion().toString()); project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate((evaluated) -> { - jar.metaInf((metaInf) -> copyLegalFiles(project, metaInf)); + jar.metaInf((metaInf) -> metaInf.from(extractLegalResources)); jar.manifest((manifest) -> { Map attributes = new TreeMap<>(); attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); @@ -166,41 +162,4 @@ class JavaConventions { .add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version)); } - void copyLegalFiles(Project project, CopySpec metaInf) { - copyNoticeFile(project, metaInf); - copyLicenseFile(project, metaInf); - } - - void copyNoticeFile(Project project, CopySpec metaInf) { - try { - InputStream notice = getClass().getClassLoader().getResourceAsStream("NOTICE.txt"); - String noticeContent = FileCopyUtils.copyToString(new InputStreamReader(notice, StandardCharsets.UTF_8)) - .replace("${version}", project.getVersion().toString()); - TextResourceFactory resourceFactory = project.getResources().getText(); - File file = createLegalFile(resourceFactory.fromString(noticeContent).asFile(), "NOTICE.txt"); - metaInf.from(file); - } - catch (IOException ex) { - throw new GradleException("Failed to copy NOTICE.txt", ex); - } - } - - void copyLicenseFile(Project project, CopySpec metaInf) { - URL license = getClass().getClassLoader().getResource("LICENSE.txt"); - try { - TextResourceFactory resourceFactory = project.getResources().getText(); - File file = createLegalFile(resourceFactory.fromUri(license.toURI()).asFile(), "LICENSE.txt"); - metaInf.from(file); - } - catch (URISyntaxException ex) { - throw new GradleException("Failed to copy LICENSE.txt", ex); - } - } - - File createLegalFile(File source, String filename) { - File legalFile = new File(source.getParentFile(), filename); - source.renameTo(legalFile); - return legalFile; - } - }