From 980b83c0d8b4b3de39dae532d1bbec0776bd9941 Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Thu, 13 Jul 2017 19:52:49 -0700 Subject: [PATCH 1/2] Locate additional metadata when using Gradle 4 Closes gh-9758 --- .../configurationprocessor/MetadataStore.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java index f26ca1b6d08..3f5a3cae14f 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java @@ -110,18 +110,34 @@ public class MetadataStore { private InputStream getAdditionalMetadataStream() throws IOException { // Most build systems will have copied the file to the class output location - FileObject fileObject = this.environment.getFiler() - .getResource(StandardLocation.CLASS_OUTPUT, "", ADDITIONAL_METADATA_PATH); + FileObject fileObject = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", ADDITIONAL_METADATA_PATH); + File file = new File(fileObject.toUri()); + if (!file.exists()) { // Gradle keeps things separate String path = file.getPath(); + int index = path.lastIndexOf(CLASSES_FOLDER); if (index >= 0) { - path = path.substring(0, index) + RESOURCES_FOLDER - + path.substring(index + CLASSES_FOLDER.length()); - file = new File(path); + /* + Gradle 4 introduces a new 'java' directory which causes issues for one-to-one path mapping + of class locations and resources. Ensure resources can be found under '/build/resources/main' + rather than '/build/resources/java/main'. + */ + final String pathBeforeClassFolder = path.substring(0, index); + /* + In order to retrieve the the class output resource, we MUST pass in a relative path. + An empty path causes a InvalidArgumentException as it must be resolvable. In reality, + this means nothing since we are going to traverse upstream to its parent to locate + the 'main' directory. + */ + FileObject classOutputLocation = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", "dummy"); + File classesFolder = new File(classOutputLocation.toUri()); + File resourcesFolder = new File(pathBeforeClassFolder + RESOURCES_FOLDER + '/' + classesFolder.getParentFile().getName()); + file = new File(resourcesFolder, ADDITIONAL_METADATA_PATH); } + } return (file.exists() ? new FileInputStream(file) : fileObject.toUri().toURL().openStream()); From e0be40cd94680f8c0baa483651d2e632dcae32b0 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 25 Jul 2017 16:47:39 +0100 Subject: [PATCH 2/2] Polish "Locate additional metadata when using Gradle 4" Closes gh-9732 --- .../configurationprocessor/MetadataStore.java | 55 ++++++----- .../MetadataStoreTests.java | 91 +++++++++++++++++++ 2 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataStoreTests.java diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java index 3f5a3cae14f..b2d96398ac7 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataStore.java @@ -18,6 +18,7 @@ package org.springframework.boot.configurationprocessor; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -110,37 +111,33 @@ public class MetadataStore { private InputStream getAdditionalMetadataStream() throws IOException { // Most build systems will have copied the file to the class output location - FileObject fileObject = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", ADDITIONAL_METADATA_PATH); - - File file = new File(fileObject.toUri()); - - if (!file.exists()) { - // Gradle keeps things separate - String path = file.getPath(); - - int index = path.lastIndexOf(CLASSES_FOLDER); - if (index >= 0) { - /* - Gradle 4 introduces a new 'java' directory which causes issues for one-to-one path mapping - of class locations and resources. Ensure resources can be found under '/build/resources/main' - rather than '/build/resources/java/main'. - */ - final String pathBeforeClassFolder = path.substring(0, index); - /* - In order to retrieve the the class output resource, we MUST pass in a relative path. - An empty path causes a InvalidArgumentException as it must be resolvable. In reality, - this means nothing since we are going to traverse upstream to its parent to locate - the 'main' directory. - */ - FileObject classOutputLocation = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", "dummy"); - File classesFolder = new File(classOutputLocation.toUri()); - File resourcesFolder = new File(pathBeforeClassFolder + RESOURCES_FOLDER + '/' + classesFolder.getParentFile().getName()); - file = new File(resourcesFolder, ADDITIONAL_METADATA_PATH); - } - - } + FileObject fileObject = this.environment.getFiler() + .getResource(StandardLocation.CLASS_OUTPUT, "", ADDITIONAL_METADATA_PATH); + File file = locateAdditionalMetadataFile(new File(fileObject.toUri())); return (file.exists() ? new FileInputStream(file) : fileObject.toUri().toURL().openStream()); } + File locateAdditionalMetadataFile(File standardLocation) throws IOException { + if (standardLocation.exists()) { + return standardLocation; + } + return new File(locateGradleResourcesFolder(standardLocation), + ADDITIONAL_METADATA_PATH); + } + + private File locateGradleResourcesFolder(File standardAdditionalMetadataLocation) + throws FileNotFoundException { + String path = standardAdditionalMetadataLocation.getPath(); + int index = path.lastIndexOf(CLASSES_FOLDER); + if (index < 0) { + throw new FileNotFoundException(); + } + String buildFolderPath = path.substring(0, index); + File classOutputLocation = standardAdditionalMetadataLocation.getParentFile() + .getParentFile(); + return new File(buildFolderPath, + RESOURCES_FOLDER + '/' + classOutputLocation.getName()); + } + } diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataStoreTests.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataStoreTests.java new file mode 100644 index 00000000000..c54e0579725 --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataStoreTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2017 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.configurationprocessor; + +import java.io.File; +import java.io.IOException; + +import javax.annotation.processing.ProcessingEnvironment; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link MetadataStore}. + * + * @author Andy Wilkinson + */ +public class MetadataStoreTests { + + @Rule + public final TemporaryFolder temp = new TemporaryFolder(); + + private final MetadataStore metadataStore = new MetadataStore( + mock(ProcessingEnvironment.class)); + + @Test + public void additionalMetadataIsLocatedInMavenBuild() throws IOException { + File app = this.temp.newFolder("app"); + File classesLocation = new File(app, "target/classes"); + File metaInf = new File(classesLocation, "META-INF"); + metaInf.mkdirs(); + File additionalMetadata = new File(metaInf, + "additional-spring-configuration-metadata.json"); + additionalMetadata.createNewFile(); + assertThat( + this.metadataStore.locateAdditionalMetadataFile(new File(classesLocation, + "META-INF/additional-spring-configuration-metadata.json"))) + .isEqualTo(additionalMetadata); + } + + @Test + public void additionalMetadataIsLocatedInGradle3Build() throws IOException { + File app = this.temp.newFolder("app"); + File classesLocation = new File(app, "build/classes/main"); + File resourcesLocation = new File(app, "build/resources/main"); + File metaInf = new File(resourcesLocation, "META-INF"); + metaInf.mkdirs(); + File additionalMetadata = new File(metaInf, + "additional-spring-configuration-metadata.json"); + additionalMetadata.createNewFile(); + assertThat( + this.metadataStore.locateAdditionalMetadataFile(new File(classesLocation, + "META-INF/additional-spring-configuration-metadata.json"))) + .isEqualTo(additionalMetadata); + } + + @Test + public void additionalMetadataIsLocatedInGradle4Build() throws IOException { + File app = this.temp.newFolder("app"); + File classesLocation = new File(app, "build/classes/java/main"); + File resourcesLocation = new File(app, "build/resources/main"); + File metaInf = new File(resourcesLocation, "META-INF"); + metaInf.mkdirs(); + File additionalMetadata = new File(metaInf, + "additional-spring-configuration-metadata.json"); + additionalMetadata.createNewFile(); + assertThat( + this.metadataStore.locateAdditionalMetadataFile(new File(classesLocation, + "META-INF/additional-spring-configuration-metadata.json"))) + .isEqualTo(additionalMetadata); + } + +}