getProcessedTypes() {
+ return this.processedSourceTypes;
+ }
+
+ @Override
+ public boolean isIncremental() {
+ return super.isIncremental();
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java
new file mode 100644
index 00000000000..d17a9b1a871
--- /dev/null
+++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/TestProject.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2012-2015 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.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.rules.TemporaryFolder;
+import org.springframework.boot.configurationprocessor.TestCompiler.TestCompilationTask;
+import org.springframework.boot.configurationsample.ConfigurationProperties;
+import org.springframework.boot.configurationsample.NestedConfigurationProperty;
+import org.springframework.boot.configurationsample.incremental.BarProperties;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.FileSystemUtils;
+
+import static org.springframework.boot.configurationprocessor.TestCompiler.ORIGINAL_SOURCE_FOLDER;
+import static org.springframework.boot.configurationprocessor.TestCompiler.sourcePathFor;
+
+/**
+ * A TestProject contains a copy of a subset of test sample code.
+ *
+ * Why a copy? Because when doing incremental build testing, we need to make modifications
+ * to the contents of the 'test project'. But we don't want to actually modify the
+ * original content itself.
+ *
+ * @author Kris De Volder
+ */
+public class TestProject {
+
+ private static final Class>[] ALWAYS_INCLUDE = { ConfigurationProperties.class,
+ NestedConfigurationProperty.class };
+
+ /**
+ * Contains copies of the original source so we can modify it safely to test
+ * incremental builds.
+ */
+ private File sourceFolder;
+ private TestCompiler compiler;
+
+ private Set sourceFiles = new LinkedHashSet();
+
+ public TestProject(TemporaryFolder tempFolder, Class>... classes)
+ throws IOException {
+ this.sourceFolder = tempFolder.newFolder();
+ this.compiler = new TestCompiler(tempFolder) {
+ @Override
+ protected File getSourceFolder() {
+ return TestProject.this.sourceFolder;
+ }
+ };
+ Set> contents = new HashSet>(Arrays.asList(classes));
+ contents.addAll(Arrays.asList(ALWAYS_INCLUDE));
+ copySources(contents);
+ }
+
+ private void copySources(Set> contents) throws IOException {
+ for (Class> klass : contents) {
+ copySources(klass);
+ }
+ }
+
+ private void copySources(Class> klass) throws IOException {
+ File original = getOriginalSourceFile(klass);
+ File target = getSourceFile(klass);
+ target.getParentFile().mkdirs();
+ FileCopyUtils.copy(original, target);
+ this.sourceFiles.add(target);
+ }
+
+ public File getSourceFile(Class> klass) {
+ return new File(this.sourceFolder, sourcePathFor(klass));
+ }
+
+ public BuildResult fullBuild() {
+ TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
+ this.compiler.getOutputLocation());
+ TestCompilationTask task = this.compiler.getTask(this.sourceFiles);
+ deleteFolderContents(this.compiler.getOutputLocation());
+ task.call(processor);
+ return new BuildResult(processor);
+ }
+
+ public BuildResult incrementalBuild(Class>... toRecompile) {
+ TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
+ this.compiler.getOutputLocation());
+ TestCompilationTask task = this.compiler.getTask(toRecompile);
+ task.call(processor);
+ return new BuildResult(processor);
+ }
+
+ private void deleteFolderContents(File outputFolder) {
+ FileSystemUtils.deleteRecursively(outputFolder);
+ outputFolder.mkdirs();
+ }
+
+ /**
+ * Retrieve File relative to project's output folder.
+ */
+ public File getOutputFile(String relativePath) {
+ Assert.assertFalse(new File(relativePath).isAbsolute());
+ return new File(this.compiler.getOutputLocation(), relativePath);
+ }
+
+ /**
+ * Add source code at the end of file, just before last '}'
+ */
+ public void addSourceCode(Class target, String text) throws Exception {
+ File targetFile = getSourceFile(target);
+ String contents = getContents(targetFile);
+ int insertAt = contents.lastIndexOf('}');
+ contents = contents.substring(0, insertAt) + text + contents.substring(insertAt);
+ putContents(targetFile, contents);
+ }
+
+ /**
+ * Delete source file for given class from project.
+ */
+ public void delete(Class> klass) {
+ File target = getSourceFile(klass);
+ target.delete();
+ this.sourceFiles.remove(target);
+ }
+
+ /**
+ * Restore source code of given class to its original contents.
+ */
+ public void revert(Class> klass) throws IOException {
+ Assert.assertTrue(getSourceFile(klass).exists());
+ copySources(klass);
+ }
+
+ /**
+ * Add source code of given class to this project.
+ */
+ public void add(Class> klass) throws IOException {
+ Assert.assertFalse(getSourceFile(klass).exists());
+ copySources(klass);
+ }
+
+ public void replaceText(Class> klass, String find, String replace) throws Exception {
+ File target = getSourceFile(klass);
+ String contents = getContents(target);
+ contents = contents.replace(find, replace);
+ putContents(target, contents);
+ }
+
+ /**
+ * Find the 'original' source code for given test class. Clients or subclasses should
+ * have no need to know about these. They should work only with the copied source
+ * code.
+ */
+ private File getOriginalSourceFile(Class> klass) {
+ return new File(ORIGINAL_SOURCE_FOLDER, sourcePathFor(klass));
+ }
+
+ private static void putContents(File targetFile, String contents)
+ throws FileNotFoundException, IOException, UnsupportedEncodingException {
+ FileCopyUtils.copy(new StringReader(contents), new FileWriter(targetFile));
+ }
+
+ private static String getContents(File file) throws Exception {
+ return FileCopyUtils.copyToString(new FileReader(file));
+ }
+}
diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/BarProperties.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/BarProperties.java
new file mode 100644
index 00000000000..f0f143a1625
--- /dev/null
+++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/BarProperties.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2015 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.configurationsample.incremental;
+
+import org.springframework.boot.configurationsample.ConfigurationProperties;
+
+@ConfigurationProperties("bar")
+public class BarProperties {
+
+ private String name;
+
+ private String description;
+
+ /**
+ * A nice counter description.
+ */
+ private Integer counter = 0;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Integer getCounter() {
+ return this.counter;
+ }
+
+ public void setCounter(Integer counter) {
+ this.counter = counter;
+ }
+}
diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/FooProperties.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/FooProperties.java
new file mode 100644
index 00000000000..2a046b3e12a
--- /dev/null
+++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/FooProperties.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2015 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.configurationsample.incremental;
+
+import org.springframework.boot.configurationsample.ConfigurationProperties;
+
+@ConfigurationProperties("foo")
+public class FooProperties {
+
+ private String name;
+
+ private String description;
+
+ /**
+ * A nice counter description.
+ */
+ private Integer counter = 0;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Integer getCounter() {
+ return this.counter;
+ }
+
+ public void setCounter(Integer counter) {
+ this.counter = counter;
+ }
+
+}
diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/RenamedBarProperties.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/RenamedBarProperties.java
new file mode 100644
index 00000000000..8dc73f04e53
--- /dev/null
+++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/incremental/RenamedBarProperties.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2015 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.configurationsample.incremental;
+
+import org.springframework.boot.configurationsample.ConfigurationProperties;
+
+@ConfigurationProperties("bar")
+public class RenamedBarProperties {
+
+ private String name;
+
+ private String description;
+
+ /**
+ * A nice counter description.
+ */
+ private Integer counter = 0;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Integer getCounter() {
+ return this.counter;
+ }
+
+ public void setCounter(Integer counter) {
+ this.counter = counter;
+ }
+}