From ac20d0498515c2be0a798b59f7bf54533dfcf3c6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 8 Feb 2017 09:02:36 +0000 Subject: [PATCH] Migrate `initializr-generator` to Java --- initializr-generator/pom.xml | 9 +- .../generator/BasicProjectRequest.groovy | 45 - .../generator/CommandLineHelpGenerator.groovy | 265 ------ .../generator/ProjectGenerator.groovy | 444 ---------- .../generator/ProjectRequest.groovy | 235 ----- .../ProjectRequestPostProcessorAdapter.groovy | 21 - .../generator/ProjectRequestResolver.groovy | 40 - .../metadata/BillOfMaterials.groovy | 156 ---- .../metadata/DependenciesCapability.groovy | 106 --- .../initializr/metadata/Dependency.groovy | 279 ------ .../metadata/DependencyMetadata.groovy | 44 - .../metadata/InitializrConfiguration.groovy | 307 ------- .../metadata/InitializrMetadata.groovy | 227 ----- .../metadata/InitializrMetadataBuilder.groovy | 185 ---- .../metadata/InitializrProperties.groovy | 133 --- .../io/spring/initializr/metadata/Link.groovy | 119 --- .../initializr/metadata/Repository.groovy | 36 - .../metadata/ServiceCapability.groovy | 94 -- .../metadata/SingleSelectCapability.groovy | 66 -- .../io/spring/initializr/metadata/Type.groovy | 44 - .../io/spring/initializr/util/Agent.groovy | 117 --- .../initializr/util/GroovyTemplate.groovy | 78 -- .../io/spring/initializr/util/Version.groovy | 167 ---- .../initializr/util/VersionRange.groovy | 90 -- .../initializr/InitializrException.java} | 20 +- .../generator/BasicProjectRequest.java | 168 ++++ .../generator/BuildProperties.java} | 25 +- .../generator/CommandLineHelpGenerator.java | 307 +++++++ .../InvalidProjectRequestException.java} | 17 +- .../generator/ProjectFailedEvent.java} | 16 +- .../generator/ProjectGeneratedEvent.java} | 8 +- .../generator/ProjectGenerator.java | 563 ++++++++++++ .../initializr/generator/ProjectRequest.java | 311 +++++++ .../generator/ProjectRequestEvent.java} | 20 +- .../ProjectRequestPostProcessor.java} | 6 +- .../ProjectRequestPostProcessorAdapter.java | 21 + .../generator/ProjectRequestResolver.java | 43 + .../generator/ProjectResourceLocator.java} | 49 +- .../initializr/metadata/BillOfMaterials.java | 315 +++++++ .../metadata/DefaultMetadataElement.java | 57 ++ .../initializr/metadata/Defaultable.java} | 13 +- .../metadata/DependenciesCapability.java | 123 +++ .../initializr/metadata/Dependency.java | 513 +++++++++++ .../initializr/metadata/DependencyGroup.java} | 61 +- .../metadata/DependencyMetadata.java | 66 ++ .../metadata/DependencyMetadataProvider.java} | 8 +- .../initializr/metadata/Describable.java} | 2 +- .../metadata/InitializrConfiguration.java | 478 ++++++++++ .../metadata/InitializrMetadata.java | 300 +++++++ .../metadata/InitializrMetadataBuilder.java | 205 +++++ .../InitializrMetadataCustomizer.java} | 6 +- .../metadata/InitializrMetadataProvider.java} | 6 +- .../metadata/InitializrProperties.java | 213 +++++ .../InvalidInitializrMetadataException.java} | 20 +- .../io/spring/initializr/metadata/Link.java | 178 ++++ .../initializr/metadata/MetadataElement.java} | 41 +- .../initializr/metadata/Repository.java | 109 +++ .../metadata/ServiceCapability.java | 123 +++ .../metadata/ServiceCapabilityType.java} | 22 +- .../SimpleInitializrMetadataProvider.java} | 14 +- .../metadata/SingleSelectCapability.java | 74 ++ .../initializr/metadata/TextCapability.java} | 28 +- .../io/spring/initializr/metadata/Type.java | 71 ++ .../initializr/metadata/TypeCapability.java} | 43 +- .../java/io/spring/initializr/util/Agent.java | 136 +++ .../initializr/util/GroovyTemplate.java | 104 +++ .../util/InvalidVersionException.java} | 16 +- .../io/spring/initializr/util/Version.java | 290 +++++++ .../initializr/util/VersionParser.java} | 107 +-- .../spring/initializr/util/VersionRange.java | 150 ++++ .../resources/templates/starter-build.gradle | 4 +- .../main/resources/templates/starter-pom.xml | 4 +- .../AbstractProjectGeneratorTests.groovy | 134 --- .../CommandLineHelpGeneratorTests.groovy | 135 --- .../ProjectGeneratorBuildTests.groovy | 173 ---- .../ProjectGeneratorLanguageTests.groovy | 162 ---- .../generator/ProjectGeneratorTests.groovy | 787 ----------------- .../ProjectRequestResolverTests.groovy | 86 -- .../generator/ProjectRequestTests.groovy | 375 -------- .../metadata/BillOfMaterialsTests.groovy | 133 --- .../DependenciesCapabilityTests.groovy | 165 ---- .../metadata/DependencyTests.groovy | 257 ------ .../InitializrConfigurationTests.groovy | 156 ---- .../InitializrMetadataBuilderTests.groovy | 203 ----- .../metadata/InitializrMetadataTests.groovy | 191 ---- .../initializr/metadata/LinkTests.groovy | 92 -- .../SingleSelectCapabilityTests.groovy | 68 -- .../metadata/TextCapabilityTests.groovy | 60 -- .../metadata/TypeCapabilityTests.groovy | 69 -- .../test/generator/GradleBuildAssert.groovy | 78 -- .../test/generator/PomAssert.groovy | 376 -------- .../test/generator/ProjectAssert.groovy | 195 ----- .../test/generator/SourceCodeAssert.groovy | 82 -- .../InitializrMetadataTestBuilder.groovy | 190 ---- .../spring/initializr/util/AgentTests.groovy | 96 -- .../initializr/util/VersionParserTests.groovy | 134 --- .../initializr/util/VersionRangeTests.groovy | 150 ---- .../initializr/util/VersionTests.groovy | 133 --- .../AbstractProjectGeneratorTests.java | 144 +++ .../CommandLineHelpGeneratorTests.java | 155 ++++ .../generator/ProjectGeneratorBuildTests.java | 181 ++++ .../ProjectGeneratorLanguageTests.java | 165 ++++ .../generator/ProjectGeneratorTests.java | 821 ++++++++++++++++++ .../ProjectRequestResolverTests.java | 96 ++ .../generator/ProjectRequestTests.java | 398 +++++++++ .../metadata/BillOfMaterialsTests.java | 143 +++ .../metadata/DependenciesCapabilityTests.java | 173 ++++ .../initializr/metadata/DependencyTests.java | 270 ++++++ .../InitializrConfigurationTests.java | 156 ++++ .../InitializrMetadataBuilderTests.java | 232 +++++ .../metadata/InitializrMetadataTests.java | 203 +++++ .../spring/initializr/metadata/LinkTests.java | 105 +++ .../metadata/SingleSelectCapabilityTests.java | 68 ++ .../metadata/TextCapabilityTests.java | 60 ++ .../metadata/TypeCapabilityTests.java | 88 ++ .../initializr/metadata/TypeTests.java} | 16 +- .../test/generator/GradleBuildAssert.java | 81 ++ .../initializr/test/generator/PomAssert.java | 512 +++++++++++ .../test/generator/ProjectAssert.java | 248 ++++++ .../test/generator/SourceCodeAssert.java | 88 ++ .../InitializrMetadataTestBuilder.java | 224 +++++ .../io/spring/initializr/util/AgentTests.java | 96 ++ .../initializr/util/VersionParserTests.java | 138 +++ .../initializr/util/VersionRangeTests.java | 153 ++++ .../spring/initializr/util/VersionTests.java | 135 +++ ...efaultDependencyMetadataProviderTests.java | 8 +- pom.xml | 15 - 127 files changed, 10413 insertions(+), 8220 deletions(-) delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/BasicProjectRequest.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestResolver.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/BillOfMaterials.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadata.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/Link.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/Repository.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/metadata/Type.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/util/Agent.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/util/Version.groovy delete mode 100644 initializr-generator/src/main/groovy/io/spring/initializr/util/VersionRange.groovy rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy => java/io/spring/initializr/InitializrException.java} (68%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/BasicProjectRequest.java rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/BuildProperties.groovy => java/io/spring/initializr/generator/BuildProperties.java} (62%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/CommandLineHelpGenerator.java rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy => java/io/spring/initializr/generator/InvalidProjectRequestException.java} (65%) rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/ProjectFailedEvent.groovy => java/io/spring/initializr/generator/ProjectFailedEvent.java} (72%) rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/ProjectGeneratedEvent.groovy => java/io/spring/initializr/generator/ProjectGeneratedEvent.java} (79%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGenerator.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequest.java rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/ProjectRequestEvent.groovy => java/io/spring/initializr/generator/ProjectRequestEvent.java} (72%) rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/ProjectRequestPostProcessor.groovy => java/io/spring/initializr/generator/ProjectRequestPostProcessor.java} (93%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestResolver.java rename initializr-generator/src/main/{groovy/io/spring/initializr/generator/ProjectResourceLocator.groovy => java/io/spring/initializr/generator/ProjectResourceLocator.java} (51%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/BillOfMaterials.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/DefaultMetadataElement.java rename initializr-generator/src/main/{groovy/io/spring/initializr/InitializrException.groovy => java/io/spring/initializr/metadata/Defaultable.java} (74%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/DependenciesCapability.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/Dependency.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/DependencyGroup.groovy => java/io/spring/initializr/metadata/DependencyGroup.java} (52%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadata.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/DependencyMetadataProvider.groovy => java/io/spring/initializr/metadata/DependencyMetadataProvider.java} (86%) rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/Describable.groovy => java/io/spring/initializr/metadata/Describable.java} (95%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrConfiguration.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadata.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataBuilder.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy => java/io/spring/initializr/metadata/InitializrMetadataCustomizer.java} (86%) rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy => java/io/spring/initializr/metadata/InitializrMetadataProvider.java} (88%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrProperties.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy => java/io/spring/initializr/metadata/InvalidInitializrMetadataException.java} (60%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/Link.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/MetadataElement.groovy => java/io/spring/initializr/metadata/MetadataElement.java} (58%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/Repository.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapability.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy => java/io/spring/initializr/metadata/ServiceCapabilityType.java} (75%) rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.groovy => java/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.java} (69%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/SingleSelectCapability.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/TextCapability.groovy => java/io/spring/initializr/metadata/TextCapability.java} (61%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/metadata/Type.java rename initializr-generator/src/main/{groovy/io/spring/initializr/metadata/TypeCapability.groovy => java/io/spring/initializr/metadata/TypeCapability.java} (51%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/util/Agent.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/util/GroovyTemplate.java rename initializr-generator/src/main/{groovy/io/spring/initializr/util/InvalidVersionException.groovy => java/io/spring/initializr/util/InvalidVersionException.java} (70%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/util/Version.java rename initializr-generator/src/main/{groovy/io/spring/initializr/util/VersionParser.groovy => java/io/spring/initializr/util/VersionParser.java} (52%) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/util/VersionRange.java delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/AbstractProjectGeneratorTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/CommandLineHelpGeneratorTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorBuildTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorLanguageTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestResolverTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/BillOfMaterialsTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependenciesCapabilityTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependencyTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataBuilderTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/LinkTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/SingleSelectCapabilityTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/TextCapabilityTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeCapabilityTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/test/generator/GradleBuildAssert.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/test/generator/PomAssert.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/test/generator/ProjectAssert.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/test/generator/SourceCodeAssert.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/util/AgentTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/util/VersionParserTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/util/VersionRangeTests.groovy delete mode 100644 initializr-generator/src/test/groovy/io/spring/initializr/util/VersionTests.groovy create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/AbstractProjectGeneratorTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/CommandLineHelpGeneratorTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorBuildTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorLanguageTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestResolverTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/BillOfMaterialsTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/DependenciesCapabilityTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/DependencyTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrConfigurationTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataBuilderTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/LinkTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/SingleSelectCapabilityTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/TextCapabilityTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/metadata/TypeCapabilityTests.java rename initializr-generator/src/test/{groovy/io/spring/initializr/metadata/TypeTests.groovy => java/io/spring/initializr/metadata/TypeTests.java} (69%) create mode 100644 initializr-generator/src/test/java/io/spring/initializr/test/generator/GradleBuildAssert.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/test/generator/PomAssert.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/test/generator/ProjectAssert.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/test/generator/SourceCodeAssert.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/util/AgentTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/util/VersionParserTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/util/VersionRangeTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/util/VersionTests.java diff --git a/initializr-generator/pom.xml b/initializr-generator/pom.xml index 9d39cb9c..232bd4f7 100644 --- a/initializr-generator/pom.xml +++ b/initializr-generator/pom.xml @@ -49,6 +49,11 @@ xmlunit test + + org.springframework.boot + spring-boot-configuration-processor + true + @@ -64,10 +69,6 @@ - - org.codehaus.gmavenplus - gmavenplus-plugin - diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/BasicProjectRequest.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/BasicProjectRequest.groovy deleted file mode 100644 index 6d52aa48..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/BasicProjectRequest.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -/** - * The base settings of a project request. Only these can be bound by user's - * input. - * - * @author Stephane Nicoll - */ -class BasicProjectRequest { - - List style = [] - List dependencies = [] - String name - String type - String description - String groupId - String artifactId - String version - String bootVersion - String packaging - String applicationName - String language - String packageName - String javaVersion - - // The base directory to create in the archive - no baseDir by default - String baseDir - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy deleted file mode 100644 index 5324634d..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.metadata.Type -import io.spring.initializr.util.GroovyTemplate - -/** - * Generate help pages for command-line clients. - * - * @author Stephane Nicoll - */ -class CommandLineHelpGenerator { - - private static final String logo = ''' - . ____ _ __ _ _ - /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\ -( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\ - \\\\/ ___)| |_)| | | | | || (_| | ) ) ) ) - ' |____| .__|_| |_|_| |_\\__, | / / / / - =========|_|==============|___/=/_/_/_/ - ''' - - private final GroovyTemplate template - - CommandLineHelpGenerator(GroovyTemplate template) { - this.template = template - } - - /** - * Generate the capabilities of the service as a generic plain text - * document. Used when no particular agent was detected. - */ - String generateGenericCapabilities(InitializrMetadata metadata, String serviceUrl) { - def model = initializeCommandLineModel(metadata, serviceUrl) - model['hasExamples'] = false - template.process 'cli-capabilities.txt', model - } - - /** - * Generate the capabilities of the service using "curl" as a plain text - * document. - */ - String generateCurlCapabilities(InitializrMetadata metadata, String serviceUrl) { - def model = initializeCommandLineModel(metadata, serviceUrl) - model['examples'] = template.process 'curl-examples.txt', model - model['hasExamples'] = true - template.process 'cli-capabilities.txt', model - } - - /** - * Generate the capabilities of the service using "HTTPie" as a plain text - * document. - */ - String generateHttpieCapabilities(InitializrMetadata metadata, String serviceUrl) { - def model = initializeCommandLineModel(metadata, serviceUrl) - model['examples'] = template.process 'httpie-examples.txt', model - model['hasExamples'] = true - template.process 'cli-capabilities.txt', model - } - - /** - * Generate the capabilities of the service using Spring Boot CLI as a plain - * text document. - */ - String generateSpringBootCliCapabilities(InitializrMetadata metadata, String serviceUrl) { - def model = initializeSpringBootCliModel(metadata, serviceUrl) - model['hasExamples'] = false - template.process('boot-cli-capabilities.txt', model) - } - - protected Map initializeCommandLineModel(InitializrMetadata metadata, serviceUrl) { - Map model = [:] - model['logo'] = logo - model['serviceUrl'] = serviceUrl - model['dependencies'] = generateDependencyTable(metadata) - model['types'] = generateTypeTable(metadata, 'Rel', false) - - Map defaults = metadata.defaults() - defaults['applicationName'] = metadata.configuration.generateApplicationName(metadata.name.content) - defaults['baseDir'] = 'no base dir' - defaults['dependencies'] = 'none' - - Map parametersDescription = buildParametersDescription(metadata) - String[][] parameterTable = new String[defaults.size() + 1][]; - parameterTable[0] = ["Parameter", "Description", "Default value"] - defaults.sort().keySet().eachWithIndex { id, i -> - String[] data = new String[3] - data[0] = id - data[1] = parametersDescription[id] - data[2] = defaults[id] - parameterTable[i + 1] = data - } - model['parameters'] = TableGenerator.generate(parameterTable) - - model - } - - protected Map initializeSpringBootCliModel(InitializrMetadata metadata, serviceUrl) { - Map model = [:] - model['logo'] = logo - model['serviceUrl'] = serviceUrl - model['dependencies'] = generateDependencyTable(metadata) - model['types'] = generateTypeTable(metadata, 'Id', true) - - - Map defaults = metadata.defaults() - Map parametersDescription = buildParametersDescription(metadata) - String[][] parameterTable = new String[defaults.size() + 1][]; - parameterTable[0] = ["Id", "Description", "Default value"] - defaults.keySet().eachWithIndex { id, i -> - String[] data = new String[3] - data[0] = id - data[1] = parametersDescription[id] - data[2] = defaults[id] - parameterTable[i + 1] = data - } - model['parameters'] = TableGenerator.generate(parameterTable) - model - } - - protected String generateDependencyTable(InitializrMetadata metadata) { - String[][] dependencyTable = new String[metadata.dependencies.all.size() + 1][]; - dependencyTable[0] = ["Id", "Description", "Required version"] - new ArrayList(metadata.dependencies.all).sort { a, b -> a.id <=> b.id } - .eachWithIndex { dep, i -> - String[] data = new String[3] - data[0] = dep.id - data[1] = dep.description ?: dep.name - data[2] = dep.versionRequirement - dependencyTable[i + 1] = data - } - TableGenerator.generate(dependencyTable) - } - - protected String generateTypeTable(InitializrMetadata metadata, String linkHeader, boolean addTags) { - String[][] typeTable = new String[metadata.types.content.size() + 1][]; - if (addTags) { - typeTable[0] = [linkHeader, "Description", "Tags"] - } - else { - typeTable[0] = [linkHeader, "Description"] - } - new ArrayList<>(metadata.types.content).sort { a, b -> a.id <=> b.id }.eachWithIndex { type, i -> - String[] data = new String[typeTable[0].length] - data[0] = (type.default ? type.id + " *" : type.id) - data[1] = type.description ?: type.name - if (addTags) { - data[2] = buildTagRepresentation(type) - } - typeTable[i + 1] = data; - } - TableGenerator.generate(typeTable) - } - - protected Map buildParametersDescription(InitializrMetadata metadata) { - Map result = [:] - metadata.properties.each { key, value -> - if (value.hasProperty('description') && value.hasProperty('id')) { - result[value.id] = value['description'] - } - } - result['applicationName'] = 'application name' - result['baseDir'] = 'base directory to create in the archive' - result - } - - private static String buildTagRepresentation(Type type) { - if (type.tags.isEmpty()) { - return ""; - } - type.tags.collect { key, value -> - "$key:$value" - }.join(",") - } - - private static class TableGenerator { - - static final String NEW_LINE = System.getProperty("line.separator") - - /** - * Generate a table description for the specified {@code content}. - *

- * The {@code content} is a two-dimensional array holding the rows - * of the table. The first entry holds the header of the table. - */ - public static String generate(String[][] content) { - StringBuilder sb = new StringBuilder() - int[] columnsLength = computeColumnsLength(content) - appendTableSeparation(sb, columnsLength) - appendRow(sb, content, columnsLength, 0) // Headers - appendTableSeparation(sb, columnsLength) - for (int i = 1; i < content.length; i++) { - appendRow(sb, content, columnsLength, i) - } - appendTableSeparation(sb, columnsLength) - sb.toString() - } - - - private static void appendRow(StringBuilder sb, String[][] content, - int[] columnsLength, int rowIndex) { - String[] row = content[rowIndex] - for (int i = 0; i < row.length; i++) { - sb.append("| ").append(fill(row[i], columnsLength[i])).append(" ") - } - sb.append("|") - sb.append(NEW_LINE) - } - - private static void appendTableSeparation(StringBuilder sb, int[] headersLength) { - for (int headerLength : headersLength) { - sb.append("+").append("-".multiply(headerLength + 2)) - } - sb.append("+") - sb.append(NEW_LINE) - } - - private static String fill(String data, int columnSize) { - if (data == null) { - return " ".multiply(columnSize) - } else { - int i = columnSize - data.length() - return data + " ".multiply(i) - } - } - - private static int[] computeColumnsLength(String[][] content) { - int count = content[0].length - int[] result = new int[count] - for (int i = 0; i < count; i++) { - result[i] = largest(content, i) - } - return result - } - - private static int largest(String[][] content, int column) { - int max = 0 - for (String[] rows : content) { - String s = rows[column] - if (s && s.length() > max) { - max = s.length() - } - } - return max - } - - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy deleted file mode 100644 index eadb5927..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy +++ /dev/null @@ -1,444 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -import groovy.util.logging.Slf4j -import io.spring.initializr.InitializrException -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrMetadataProvider -import io.spring.initializr.util.GroovyTemplate -import io.spring.initializr.util.Version - -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Value -import org.springframework.context.ApplicationEventPublisher -import org.springframework.util.Assert - -import static io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom - -/** - * Generate a project based on the configured metadata. - * - * @author Dave Syer - * @author Stephane Nicoll - * @author Sebastien Deleuze - */ -@Slf4j -class ProjectGenerator { - - private static final VERSION_1_2_0_RC1 = Version.parse('1.2.0.RC1') - - private static final VERSION_1_3_0_M1 = Version.parse('1.3.0.M1') - - private static final VERSION_1_4_0_M2 = Version.parse('1.4.0.M2') - - private static final VERSION_1_4_0_M3 = Version.parse('1.4.0.M3') - - private static final VERSION_1_4_2_M1 = Version.parse('1.4.2.M1') - - private static final VERSION_2_0_0_M1 = Version.parse('2.0.0.M1') - - @Autowired - ApplicationEventPublisher eventPublisher - - @Autowired - InitializrMetadataProvider metadataProvider - - @Autowired - ProjectRequestResolver requestResolver - - @Autowired - GroovyTemplate groovyTemplate = new GroovyTemplate() - - @Autowired - ProjectResourceLocator projectResourceLocator = new ProjectResourceLocator() - - @Value('${TMPDIR:.}/initializr') - String tmpdir - - private File temporaryDirectory - private transient Map> temporaryFiles = [:] - - /** - * Generate a Maven pom for the specified {@link ProjectRequest}. - */ - byte[] generateMavenPom(ProjectRequest request) { - try { - def model = resolveModel(request) - if (!isMavenBuild(request)) { - throw new InvalidProjectRequestException("Could not generate Maven pom, " + - "invalid project type $request.type") - } - def content = doGenerateMavenPom(model) - publishProjectGeneratedEvent(request) - content - } catch (InitializrException ex) { - publishProjectFailedEvent(request, ex) - throw ex - } - } - - /** - * Generate a Gradle build file for the specified {@link ProjectRequest}. - */ - byte[] generateGradleBuild(ProjectRequest request) { - try { - def model = resolveModel(request) - if (!isGradleBuild(request)) { - throw new InvalidProjectRequestException("Could not generate Gradle build, " + - "invalid project type $request.type") - } - def content = doGenerateGradleBuild(model) - publishProjectGeneratedEvent(request) - content - } catch (InitializrException ex) { - publishProjectFailedEvent(request, ex) - throw ex - } - } - - /** - * Generate a project structure for the specified {@link ProjectRequest}. Returns - * a directory containing the project. - */ - File generateProjectStructure(ProjectRequest request) { - try { - doGenerateProjectStructure(request) - } catch (InitializrException ex) { - publishProjectFailedEvent(request, ex) - throw ex - } - } - - protected File doGenerateProjectStructure(ProjectRequest request) { - def model = resolveModel(request) - - def rootDir = File.createTempFile('tmp', '', getTemporaryDirectory()) - addTempFile(rootDir.name, rootDir) - rootDir.delete() - rootDir.mkdirs() - - def dir = initializerProjectDir(rootDir, request) - - if (isGradleBuild(request)) { - def gradle = new String(doGenerateGradleBuild(model)) - new File(dir, 'build.gradle').write(gradle) - writeGradleWrapper(dir, Version.safeParse(request.bootVersion)) - } else { - def pom = new String(doGenerateMavenPom(model)) - new File(dir, 'pom.xml').write(pom) - writeMavenWrapper(dir) - } - - generateGitIgnore(dir, request) - - def applicationName = request.applicationName - def language = request.language - - String codeLocation = language - def src = new File(new File(dir, "src/main/$codeLocation"), request.packageName.replace('.', '/')) - src.mkdirs() - def extension = (language.equals('kotlin') ? 'kt' : language) - write(new File(src, "${applicationName}.${extension}"), "Application.$extension", model) - - if (request.packaging == 'war') { - def fileName = "ServletInitializer.$extension" - write(new File(src, fileName), fileName, model) - } - - def test = new File(new File(dir, "src/test/$codeLocation"), request.packageName.replace('.', '/')) - test.mkdirs() - setupTestModel(request, model) - write(new File(test, "${applicationName}Tests.${extension}"), "ApplicationTests.$extension", model) - - def resources = new File(dir, 'src/main/resources') - resources.mkdirs() - new File(resources, 'application.properties').write('') - - if (request.hasWebFacet()) { - new File(dir, 'src/main/resources/templates').mkdirs() - new File(dir, 'src/main/resources/static').mkdirs() - } - publishProjectGeneratedEvent(request) - rootDir - - } - - /** - * Create a distribution file for the specified project structure - * directory and extension - */ - File createDistributionFile(File dir, String extension) { - def download = new File(getTemporaryDirectory(), dir.name + extension) - addTempFile(dir.name, download) - download - } - - private File getTemporaryDirectory() { - if (!temporaryDirectory) { - temporaryDirectory = new File(tmpdir, 'initializr') - temporaryDirectory.mkdirs() - } - temporaryDirectory - } - - /** - * Clean all the temporary files that are related to this root - * directory. - * @see #createDistributionFile - */ - void cleanTempFiles(File dir) { - def tempFiles = temporaryFiles.remove(dir.name) - if (tempFiles) { - tempFiles.each { File file -> - if (file.directory) { - file.deleteDir() - } else { - file.delete() - } - } - } - } - - private void publishProjectGeneratedEvent(ProjectRequest request) { - ProjectGeneratedEvent event = new ProjectGeneratedEvent(request) - eventPublisher.publishEvent(event) - } - - private void publishProjectFailedEvent(ProjectRequest request, Exception cause) { - ProjectFailedEvent event = new ProjectFailedEvent(request, cause) - eventPublisher.publishEvent(event) - } - - /** - * Generate a {@code .gitignore} file for the specified {@link ProjectRequest} - * @param dir the root directory of the project - * @param request the request to handle - */ - protected void generateGitIgnore(File dir, ProjectRequest request) { - def model = [:] - model['build'] = isGradleBuild(request) ? 'gradle' : 'maven' - write(new File(dir, '.gitignore'), 'gitignore.tmpl', model) - } - - /** - * Resolve the specified {@link ProjectRequest} and return the model to use - * to generate the project - * @param request the request to handle - * @return a model for that request - */ - protected Map resolveModel(ProjectRequest originalRequest) { - Assert.notNull originalRequest.bootVersion, 'boot version must not be null' - def model = [:] - def metadata = metadataProvider.get() - - ProjectRequest request = requestResolver.resolve(originalRequest, metadata) - - // request resolved so we can log what has been requested - def dependencies = request.resolvedDependencies - def dependencyIds = dependencies.collect { it.id } - log.info("Processing request{type=$request.type, dependencies=$dependencyIds}") - - if (isMavenBuild(request)) { - ParentPom parentPom = metadata.configuration.env.maven.resolveParentPom(request.bootVersion) - if (parentPom.includeSpringBootBom && !request.boms['spring-boot']) { - request.boms['spring-boot'] = metadata.createSpringBootBom( - request.bootVersion, 'spring-boot.version') - } - - model['mavenParentGroupId'] = parentPom.groupId - model['mavenParentArtifactId'] = parentPom.artifactId - model['mavenParentVersion'] = parentPom.version - model['includeSpringBootBom'] = parentPom.includeSpringBootBom - } - - model['resolvedBoms'] = request.boms.values().sort {a, b -> a.order <=> b.order } - - model['compileDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_COMPILE) - model['runtimeDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_RUNTIME) - model['compileOnlyDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_COMPILE_ONLY) - model['providedDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_PROVIDED) - model['testDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_TEST) - - request.boms.each { k, v -> - if (v.versionProperty) { - request.buildProperties.versions[v.versionProperty] = { v.version } - } - } - - // Add various versions - model['dependencyManagementPluginVersion'] = metadata.configuration.env.gradle.dependencyManagementPluginVersion - model['kotlinVersion'] = metadata.configuration.env.kotlin.version - - // @SpringBootApplication available as from 1.2.0.RC1 - model['useSpringBootApplication'] = VERSION_1_2_0_RC1 - .compareTo(Version.safeParse(request.bootVersion)) <= 0 - - // Gradle plugin has changed as from 1.3.0 - model['bootOneThreeAvailable'] = VERSION_1_3_0_M1 - .compareTo(Version.safeParse(request.bootVersion)) <= 0 - - // Gradle plugin has changed again as from 1.4.2 - model['springBootPluginName'] = (VERSION_1_4_2_M1.compareTo( - Version.safeParse(request.bootVersion)) <= 0 ? 'org.springframework.boot' : 'spring-boot') - - // New testing stuff - model['newTestInfrastructure'] = isNewTestInfrastructureAvailable(request) - - // New Servlet Initializer location - model['newServletInitializer'] = isNewServletInitializerAvailable(request) - - // Append the project request to the model - request.properties.each { model[it.key] = it.value } - - model - } - - protected void setupTestModel(ProjectRequest request, Map model) { - String imports = '' - String testAnnotations = '' - def newTestInfrastructure = isNewTestInfrastructureAvailable(request) - if (newTestInfrastructure) { - imports += String.format(generateImport('org.springframework.boot.test.context.SpringBootTest', - request.language) + "%n") - imports += String.format(generateImport('org.springframework.test.context.junit4.SpringRunner', - request.language) + "%n") - } else { - imports += String.format(generateImport('org.springframework.boot.test.SpringApplicationConfiguration', - request.language) + "%n") - imports += String.format(generateImport('org.springframework.test.context.junit4.SpringJUnit4ClassRunner', - request.language) + "%n") - } - if (request.hasWebFacet() && !newTestInfrastructure) { - imports += String.format(generateImport('org.springframework.test.context.web.WebAppConfiguration', - request.language) + "%n") - testAnnotations = String.format('@WebAppConfiguration%n') - } - model.testImports = imports - model.testAnnotations = testAnnotations - } - - protected String generateImport(String type, String language) { - String end = (language.equals("groovy") || language.equals("kotlin")) ? '' : ';' - "import $type$end" - } - - private static isGradleBuild(ProjectRequest request) { - return 'gradle'.equals(request.build) - } - - private static isMavenBuild(ProjectRequest request) { - return 'maven'.equals(request.build) - } - - private static boolean isNewTestInfrastructureAvailable(ProjectRequest request) { - VERSION_1_4_0_M2 - .compareTo(Version.safeParse(request.bootVersion)) <= 0 - } - - private static boolean isNewServletInitializerAvailable(ProjectRequest request) { - VERSION_1_4_0_M3 - .compareTo(Version.safeParse(request.bootVersion)) <= 0 - } - - private static boolean isGradle3Available(Version bootVersion) { - VERSION_2_0_0_M1.compareTo(bootVersion) <= 0 - } - - private byte[] doGenerateMavenPom(Map model) { - groovyTemplate.process 'starter-pom.xml', model - } - - - private byte[] doGenerateGradleBuild(Map model) { - groovyTemplate.process 'starter-build.gradle', model - } - - private void writeGradleWrapper(File dir, Version bootVersion) { - String gradlePrefix = isGradle3Available(bootVersion) ? 'gradle3' : 'gradle' - writeTextResource(dir, 'gradlew.bat', "$gradlePrefix/gradlew.bat") - writeTextResource(dir, 'gradlew', "$gradlePrefix/gradlew") - - def wrapperDir = new File(dir, 'gradle/wrapper') - wrapperDir.mkdirs() - writeTextResource(wrapperDir, 'gradle-wrapper.properties', - "$gradlePrefix/gradle/wrapper/gradle-wrapper.properties") - writeBinaryResource(wrapperDir, 'gradle-wrapper.jar', - "$gradlePrefix/gradle/wrapper/gradle-wrapper.jar") - } - - private void writeMavenWrapper(File dir) { - writeTextResource(dir, 'mvnw.cmd', 'maven/mvnw.cmd') - writeTextResource(dir, 'mvnw', 'maven/mvnw') - - def wrapperDir = new File(dir, '.mvn/wrapper') - wrapperDir.mkdirs() - writeTextResource(wrapperDir, 'maven-wrapper.properties', - 'maven/wrapper/maven-wrapper.properties') - writeBinaryResource(wrapperDir, 'maven-wrapper.jar', - 'maven/wrapper/maven-wrapper.jar') - } - - private File writeBinaryResource(File dir, String name, String location) { - doWriteProjectResource(dir, name, location, true) - } - - private File writeTextResource(File dir, String name, String location) { - doWriteProjectResource(dir, name, location, false) - } - - private File doWriteProjectResource(File dir, String name, String location, boolean binary) { - def target = new File(dir, name) - if (binary) { - target << projectResourceLocator.getBinaryResource("classpath:project/$location") - } - else { - target.write(projectResourceLocator.getTextResource("classpath:project/$location")) - } - target - } - - private File initializerProjectDir(File rootDir, ProjectRequest request) { - if (request.baseDir) { - File dir = new File(rootDir, request.baseDir) - dir.mkdirs() - return dir - } else { - return rootDir - } - } - - def write(File target, String templateName, def model) { - def tmpl = templateName.endsWith('.groovy') ? templateName + '.tmpl' : templateName - def body = groovyTemplate.process tmpl, model - target.write(body, 'utf-8') - } - - private void addTempFile(String group, File file) { - def content = temporaryFiles[group] - if (!content) { - content = [] - temporaryFiles[group] = content - } - content << file - } - - private static def filterDependencies(def dependencies, String scope) { - dependencies.findAll { dep -> scope.equals(dep.scope) }.sort { a, b -> a.id <=> b.id } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy deleted file mode 100644 index d26d16ef..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -import groovy.transform.ToString -import groovy.util.logging.Slf4j -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.metadata.Repository -import io.spring.initializr.metadata.Type -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionRange - -/** - * A request to generate a project. - * - * @author Dave Syer - * @author Stephane Nicoll - */ -@Slf4j -@ToString(ignoreNulls = true, includePackage = false, includeNames = true) -class ProjectRequest extends BasicProjectRequest { - - /** - * The id of the starter to use if no dependency is defined. - */ - public static final DEFAULT_STARTER = 'root_starter' - - /** - * Additional parameters that can be used to further identify the request. - */ - final Map parameters = [:] - - // Resolved dependencies based on the ids provided by either "style" or "dependencies" - List resolvedDependencies - - final Map boms = [:] - - final Map repositories = [:] - - /** - * Build properties. - */ - final BuildProperties buildProperties = new BuildProperties() - - def facets = [] - def build - - /** - * Initializes this instance with the defaults defined in the specified {@link InitializrMetadata}. - */ - void initialize(InitializrMetadata metadata) { - metadata.defaults().each { key, value -> - if (owner.hasProperty(key)) { - owner.setProperty(key, value) - } - } - } - - /** - * Resolve this instance against the specified {@link InitializrMetadata} - */ - void resolve(InitializrMetadata metadata) { - List depIds = style ? style : dependencies - String actualBootVersion = bootVersion ?: metadata.bootVersions.default.id - Version requestedVersion = Version.parse(actualBootVersion) - resolvedDependencies = depIds.collect { - def dependency = metadata.dependencies.get(it) - if (dependency == null) { - throw new InvalidProjectRequestException("Unknown dependency '$it' check project metadata") - } - dependency.resolve(requestedVersion) - } - resolvedDependencies.each { - it.facets.each { - if (!facets.contains(it)) { - facets.add(it) - } - } - if (!it.match(requestedVersion)) { - throw new InvalidProjectRequestException("Dependency '$it.id' is not compatible " + - "with Spring Boot $requestedVersion") - } - if (it.bom) { - resolveBom(metadata, it.bom, requestedVersion) - } - if (it.repository) { - String repositoryId = it.repository - if (!repositories[repositoryId]) { - repositories[repositoryId] = metadata.configuration.env.repositories[repositoryId] - } - } - } - - if (this.type) { - Type type = metadata.types.get(this.type) - if (!type) { - throw new InvalidProjectRequestException("Unknown type '${this.type}' check project metadata") - } - String buildTag = type.tags['build'] - if (buildTag) { - this.build = buildTag - } - } - if (this.packaging) { - def packaging = metadata.packagings.get(this.packaging) - if (!packaging) { - throw new InvalidProjectRequestException("Unknown packaging '${this.packaging}' check project metadata") - } - } - if (this.language) { - def language = metadata.languages.get(this.language) - if (!language) { - throw new InvalidProjectRequestException("Unknown language '${this.language}' check project metadata") - } - } - - if (!applicationName) { - this.applicationName = metadata.configuration.generateApplicationName(this.name) - } - packageName = metadata.configuration.cleanPackageName(this.packageName, metadata.packageName.content) - - initializeRepositories(metadata, requestedVersion) - - initializeProperties(metadata) - - afterResolution(metadata) - } - - /** - * Set the repositories that this instance should use based on the {@link InitializrMetadata} - * and the requested Spring Boot {@link Version}. - */ - protected void initializeRepositories(InitializrMetadata metadata, Version requestedVersion) { - if (!'RELEASE'.equals(requestedVersion.qualifier.qualifier)) { - repositories['spring-snapshots'] = metadata.configuration.env.repositories['spring-snapshots'] - repositories['spring-milestones'] = metadata.configuration.env.repositories['spring-milestones'] - } - boms.values().each { - it.repositories.each { - if (!repositories[it]) { - repositories[it] = metadata.configuration.env.repositories[it] - } - } - } - } - - protected void initializeProperties(InitializrMetadata metadata) { - if ('gradle'.equals(build)) { - buildProperties.gradle['springBootVersion'] = { getBootVersion() } - if ('kotlin'.equals(language)) { - buildProperties.gradle['kotlinVersion'] = { metadata.configuration.env.kotlin.version } - } - } else { - buildProperties.maven['project.build.sourceEncoding'] = { 'UTF-8' } - buildProperties.maven['project.reporting.outputEncoding'] = { 'UTF-8' } - buildProperties.versions['java.version'] = { getJavaVersion() } - if ('kotlin'.equals(language)) { - buildProperties.versions['kotlin.version'] = { metadata.configuration.env.kotlin.version } - } - } - } - - private void resolveBom(InitializrMetadata metadata, String bomId, Version requestedVersion) { - if (!boms[bomId]) { - def bom = metadata.configuration.env.boms[bomId].resolve(requestedVersion) - boms[bomId] = bom - bom.additionalBoms.each { id -> - resolveBom(metadata, id, requestedVersion) - } - } - } - - /** - * Update this request once it has been resolved with the specified {@link InitializrMetadata}. - */ - protected afterResolution(InitializrMetadata metadata) { - if (packaging == 'war') { - if (!hasWebFacet()) { - // Need to be able to bootstrap the web app - resolvedDependencies << metadata.dependencies.get('web') - facets << 'web' - } - // Add the tomcat starter in provided scope - def tomcat = new Dependency().asSpringBootStarter('tomcat') - tomcat.scope = Dependency.SCOPE_PROVIDED - resolvedDependencies << tomcat - } - if (!resolvedDependencies.find { it.starter }) { - // There's no starter so we add the default one - addDefaultDependency() - } - } - - /** - * Add a default dependency if the project does not define any - * dependency - */ - protected addDefaultDependency() { - def root = new Dependency() - root.id = DEFAULT_STARTER - root.asSpringBootStarter('') - resolvedDependencies << root - } - - /** - * Specify if this request has the web facet enabled. - */ - boolean hasWebFacet() { - hasFacet('web') - } - - /** - * Specify if this request has the specified facet enabled - */ - boolean hasFacet(String facet) { - facets.contains(facet) - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.groovy deleted file mode 100644 index b6dbefe5..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package io.spring.initializr.generator - -import io.spring.initializr.metadata.InitializrMetadata - -/** - * An implementation of {@link ProjectRequestPostProcessor} with empty methods allowing - * sub-classes to override only the methods they're interested in. - * - * @author Stephane Nicoll - */ -class ProjectRequestPostProcessorAdapter implements ProjectRequestPostProcessor { - - @Override - void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { - } - - @Override - void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestResolver.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestResolver.groovy deleted file mode 100644 index 7d708c9e..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestResolver.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package io.spring.initializr.generator - -import io.spring.initializr.metadata.InitializrMetadata - -import org.springframework.util.Assert - -/** - * Resolve {@link ProjectRequest} instances, honoring callback hook points. - * - * @author Stephane Nicoll - */ -class ProjectRequestResolver { - - private final List postProcessors - - ProjectRequestResolver(List postProcessors) { - this.postProcessors = new ArrayList<>(postProcessors) - } - - ProjectRequest resolve(ProjectRequest request, InitializrMetadata metadata) { - Assert.notNull(request, "Request must not be null") - applyPostProcessBeforeResolution(request, metadata) - request.resolve(metadata) - applyPostProcessAfterResolution(request, metadata) - request - } - - private void applyPostProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { - for (ProjectRequestPostProcessor processor : postProcessors) { - processor.postProcessBeforeResolution(request, metadata) - } - } - - private void applyPostProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { - for (ProjectRequestPostProcessor processor : postProcessors) { - processor.postProcessAfterResolution(request, metadata) - } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/BillOfMaterials.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/BillOfMaterials.groovy deleted file mode 100644 index cba01d40..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/BillOfMaterials.groovy +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import com.fasterxml.jackson.annotation.JsonInclude -import groovy.transform.ToString -import io.spring.initializr.metadata.BillOfMaterials.Mapping; -import io.spring.initializr.util.InvalidVersionException -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionParser -import io.spring.initializr.util.VersionRange - -/** - * Define a Bill Of Materials to be represented in the generated project - * if a dependency refers to it. - * - * @author Stephane Nicoll - */ -@ToString(ignoreNulls = true, excludes = 'mappings', includePackage = false) -@JsonInclude(JsonInclude.Include.NON_DEFAULT) -class BillOfMaterials { - - String groupId - String artifactId - - /** - * The version of the BOM. Can be {@code null} if it is provided via a mapping. - */ - String version - - /** - * The property to use to externalize the version of the BOM. When this is set, - * a version property is automatically added rather than setting the version - * in the bom declaration itself. - */ - String versionProperty - - /** - * The relative order of this BOM where lower values have higher priority. The - * default value is {@code Integer.MAX_VALUE}, indicating lowest priority. The - * Spring Boot dependencies bom has an order of 100. - */ - Integer order = Integer.MAX_VALUE - - /** - * The BOM(s) that should be automatically included if this BOM is required. Can be - * {@code null} if it is provided via a mapping. - */ - List additionalBoms = [] - - /** - * The repositories that are required if this BOM is required. Can be {@code null} if - * it is provided via a mapping. - */ - List repositories = [] - - final List mappings = [] - - /** - * Determine the version placeholder to use for this instance. If a version - * property is defined, this returns the reference for the property. Otherwise - * this returns the plain {@link #version} - */ - String determineVersionToken() { - return (versionProperty ? '${' + versionProperty + '}' : version) - } - - void validate() { - if (!version && !mappings) { - throw new InvalidInitializrMetadataException("No version available for $this"); - } - updateVersionRange(VersionParser.DEFAULT) - } - - void updateVersionRange(VersionParser versionParser) { - mappings.each { - try { - it.range = versionParser.parseRange(it.versionRange) - } catch (InvalidVersionException ex) { - throw new InvalidInitializrMetadataException("Invalid version range $it.versionRange for $this", ex) - } - } - } - - /** - * Resolve this instance according to the specified Spring Boot {@link Version}. Return - * a {@link BillOfMaterials} instance that holds the version, repositories and - * additional BOMs to use, if any. - */ - BillOfMaterials resolve(Version bootVersion) { - if (!mappings) { - return this - } - - for (Mapping mapping : mappings) { - if (mapping.range.match(bootVersion)) { - def resolvedBom = new BillOfMaterials(groupId: groupId, artifactId: artifactId, - version: mapping.version, versionProperty: versionProperty, order: order) - resolvedBom.repositories += mapping.repositories ?: repositories - resolvedBom.additionalBoms += mapping.additionalBoms ?: additionalBoms - return resolvedBom - } - } - throw new IllegalStateException("No suitable mapping was found for $this and version $bootVersion") - } - - @ToString(ignoreNulls = true, includePackage = false) - static class Mapping { - - String versionRange - - String version - - List repositories = [] - - List additionalBoms = [] - - private VersionRange range - - String determineVersionRangeRequirement() { - range.toString() - } - - public static Mapping create(String range, String version) { - return new Mapping(versionRange: range, version: version); - } - - public static Mapping create(String range, String version, String... repositories) { - return new Mapping(versionRange: range, version: version, repositories: repositories); - } - - } - - public static BillOfMaterials create(String groupId, String artifactId) { - return new BillOfMaterials(groupId: groupId, artifactId: artifactId); - } - - public static BillOfMaterials create(String groupId, String artifactId, String version) { - return new BillOfMaterials(groupId: groupId, artifactId: artifactId, version: version); - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy deleted file mode 100644 index 585cd5e3..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import io.spring.initializr.util.VersionParser - -/** - * A {@link ServiceCapability} listing the available dependencies defined as a - * {@link ServiceCapabilityType#HIERARCHICAL_MULTI_SELECT} capability. - * - * @author Stephane Nicoll - */ -class DependenciesCapability extends ServiceCapability> { - - final List content = [] - - private final Map indexedDependencies = [:] - - DependenciesCapability() { - super('dependencies', ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT, - 'Project dependencies', 'dependency identifiers (comma-separated)') - } - - /** - * Return the {@link Dependency} with the specified id or {@code null} if - * no such dependency exists. - */ - Dependency get(String id) { - indexedDependencies[id] - } - - /** - * Return all dependencies as a flat collection - */ - Collection getAll() { - Collections.unmodifiableCollection(indexedDependencies.values()) - } - - void validate() { - index() - } - - void updateVersionRange(VersionParser versionParser) { - indexedDependencies.values().each { - it.updateVersionRanges(versionParser) - } - } - - @Override - void merge(List otherContent) { - otherContent.each { group -> - if (!content.find { group.name.equals(it.name)}) { - content << group - } - } - index() - } - - private void index() { - indexedDependencies.clear() - content.each { group -> - group.content.each { dependency -> - // Apply defaults - if (!dependency.versionRange && group.versionRange) { - dependency.versionRange = group.versionRange - } - if (!dependency.bom && group.bom) { - dependency.bom = group.bom - } - if (!dependency.repository && group.repository) { - dependency.repository = group.repository - } - - dependency.resolve() - indexDependency(dependency.id, dependency) - for (String alias : dependency.aliases) { - indexDependency(alias, dependency) - } - } - } - } - - private void indexDependency(String id, Dependency dependency) { - def existing = indexedDependencies[id] - if (existing) { - throw new IllegalArgumentException("Could not register $dependency another dependency " + - "has also the '$id' id $existing"); - } - indexedDependencies[id] = dependency - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy deleted file mode 100644 index 9e62249b..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.fasterxml.jackson.annotation.JsonInclude -import groovy.transform.AutoClone -import groovy.transform.AutoCloneStyle -import groovy.transform.ToString -import io.spring.initializr.metadata.Dependency.Mapping; -import io.spring.initializr.util.InvalidVersionException -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionParser -import io.spring.initializr.util.VersionRange - -/** - * Meta-data for a dependency. Each dependency has a primary identifier and an - * arbitrary number of {@code aliases}. - * - * @author Stephane Nicoll - */ -@ToString(ignoreNulls = true, includePackage = false) -@JsonInclude(JsonInclude.Include.NON_EMPTY) -@AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) - -class Dependency extends MetadataElement implements Describable { - static final String SCOPE_COMPILE = 'compile' - static final String SCOPE_COMPILE_ONLY = 'compileOnly' - static final String SCOPE_RUNTIME = 'runtime' - static final String SCOPE_PROVIDED = 'provided' - static final String SCOPE_TEST = 'test' - static final List SCOPE_ALL = [ - SCOPE_COMPILE, - SCOPE_RUNTIME, - SCOPE_COMPILE_ONLY, - SCOPE_PROVIDED, - SCOPE_TEST - ] - - List aliases = [] - - List facets = [] - - String groupId - - String artifactId - - /** - * The default version, can be {@code null} to indicate that the - * version is managed by the project and does not need to be specified. - */ - String version - - /** - * The type, can be {@code null} to indicate that the default type - * should be used (i.e. {@code jar}). - */ - String type - - /** - * Dependency mapping if an attribute of the dependency differs according to the - * Spring Boot version. If no mapping matches, default attributes are used. - */ - List mappings = [] - - String scope = SCOPE_COMPILE - - String description - - String versionRange - - @JsonIgnore - String versionRequirement - - private VersionRange range - - String bom - - String repository - - @JsonInclude(JsonInclude.Include.NON_DEFAULT) - int weight - - /** - * Specify if the dependency represents a "starter", i.e. the sole presence of - * that dependency is enough to bootstrap the context. - */ - boolean starter = true - - List keywords = [] - - List links = [] - - void setScope(String scope) { - if (!SCOPE_ALL.contains(scope)) { - throw new InvalidInitializrMetadataException("Invalid scope $scope must be one of $SCOPE_ALL") - } - this.scope = scope - } - - void setVersionRange(String versionRange) { - this.versionRange = versionRange ? versionRange.trim() : null - } - - /** - * Specify if the dependency has its coordinates set, i.e. {@code groupId} - * and {@code artifactId}. - */ - boolean hasCoordinates() { - groupId && artifactId - } - - /** - * Define this dependency as a standard spring boot starter with the specified name - *

If no name is specified, the root 'spring-boot-starter' is assumed. - */ - Dependency asSpringBootStarter(String name) { - groupId = 'org.springframework.boot' - artifactId = name ? 'spring-boot-starter-' + name : 'spring-boot-starter' - if (name) { - id = name - } - this - } - - /** - * Validate the dependency and complete its state based on the - * available information. - */ - def resolve() { - if (id == null) { - if (!hasCoordinates()) { - throw new InvalidInitializrMetadataException( - 'Invalid dependency, should have at least an id or a groupId/artifactId pair.') - } - generateId() - } else if (!hasCoordinates()) { - // Let's build the coordinates from the id - def st = new StringTokenizer(id, ':') - if (st.countTokens() == 1) { // assume spring-boot-starter - asSpringBootStarter(id) - } else if (st.countTokens() == 2 || st.countTokens() == 3) { - groupId = st.nextToken() - artifactId = st.nextToken() - if (st.hasMoreTokens()) { - version = st.nextToken() - } - } else { - throw new InvalidInitializrMetadataException( - "Invalid dependency, id should have the form groupId:artifactId[:version] but got $id") - } - } - links.forEach { l -> - l.resolve() - } - updateVersionRanges(VersionParser.DEFAULT) - } - - def updateVersionRanges(VersionParser versionParser) { - if (versionRange) { - try { - range = versionParser.parseRange(versionRange) - versionRequirement = range.toString() - } catch (InvalidVersionException ex) { - throw new InvalidInitializrMetadataException("Invalid version range '$versionRange' for " + - "dependency with id '$id'", ex) - } - } - mappings.each { - try { - it.range = versionParser.parseRange(it.versionRange) - } catch (InvalidVersionException ex) { - throw new InvalidInitializrMetadataException("Invalid version range $it.versionRange for $this", ex) - } - } - } - - /** - * Resolve this instance according to the specified Spring Boot {@link Version}. Return - * a {@link Dependency} instance that has its state resolved against the specified version. - */ - Dependency resolve(Version bootVersion) { - for (Mapping mapping : mappings) { - if (mapping.range.match(bootVersion)) { - def dependency = new Dependency(this) - dependency.groupId = mapping.groupId ? mapping.groupId : this.groupId - dependency.artifactId = mapping.artifactId ? mapping.artifactId : this.artifactId - dependency.version = mapping.version ? mapping.version : this.version - dependency.versionRequirement = mapping.range.toString() - dependency.mappings = null - return dependency - } - } - return this - } - - /** - * Specify if this dependency is available for the specified Spring Boot version. - */ - boolean match(Version version) { - if (range) { - return range.match(version) - } - true - } - - /** - * Generate an id using the groupId and artifactId - */ - def generateId() { - if (groupId == null || artifactId == null) { - throw new IllegalArgumentException( - "Could not generate id for $this: at least groupId and artifactId must be set.") - } - StringBuilder sb = new StringBuilder() - sb.append(groupId).append(':').append(artifactId) - id = sb.toString() - } - - /** - * Map several attribute of the dependency for a given version range. - */ - static class Mapping { - - /** - * The version range of this mapping. - */ - String versionRange - - /** - * The version to use for this mapping or {@code null} to use the default. - */ - String groupId; - - /** - * The groupId to use for this mapping or {@code null} to use the default. - */ - String artifactId; - - /** - * The artifactId to use for this mapping or {@code null} to use the default. - */ - String version - - private VersionRange range - - public static Mapping create(String range, String groupId, String artifactId, - String version) { - new Mapping(versionRange: range, groupId: groupId, artifactId: artifactId, version: version); - } - } - - public static Dependency create(String groupId, String artifactId, String version, String scope) { - return new Dependency(groupId: groupId, artifactId: artifactId, version: version, scope: scope); - } - - public static Dependency withId(String id, String groupId, String artifactId, String version) { - return new Dependency(groupId: groupId, artifactId: artifactId, versionRange: version, id: id); - } - - public static Dependency withId(String id, String groupId, String artifactId) { - return new Dependency(groupId: groupId, artifactId: artifactId, id: id); - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadata.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadata.groovy deleted file mode 100644 index bc47afe5..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadata.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import io.spring.initializr.util.Version - -/** - * Dependency metadata for a given spring boot {@link Version}. - * - * @author Stephane Nicoll - */ -class DependencyMetadata { - - final Version bootVersion - - final Map dependencies - - final Map repositories - - final Map boms - - DependencyMetadata(Version bootVersion, Map dependencies, - Map repositories, Map boms) { - this.bootVersion = bootVersion - this.dependencies = dependencies - this.repositories = repositories - this.boms = boms - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy deleted file mode 100644 index 04bab76f..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -/** - * Various configuration options used by the service. - * - * @author Stephane Nicoll - */ -class InitializrConfiguration { - - /** - * Environment options. - */ - final Env env = new Env() - - void validate() { - env.validate() - } - - void merge(InitializrConfiguration other) { - env.merge(other.env) - } - - /** - * Generate a suitable application name based on the specified name. If no suitable - * application name can be generated from the specified {@code name}, the - * {@link Env#fallbackApplicationName} is used instead. - *

No suitable application name can be generated if the name is {@code null} or - * if it contains an invalid character for a class identifier. - * @see Env#fallbackApplicationName - * @see Env#invalidApplicationNames - */ - String generateApplicationName(String name) { - if (!name) { - return env.fallbackApplicationName - } - String text = splitCamelCase(name.trim()) - String result = text.replaceAll("(_|-| |:)+([A-Za-z0-9])", { Object[] it -> - it[2].toUpperCase() - }) - if (!result.endsWith('Application')) { - result += 'Application' - } - String candidate = result.capitalize(); - if (hasInvalidChar(candidate) || env.invalidApplicationNames.contains(candidate)) { - return env.fallbackApplicationName - } else { - return candidate - } - } - - /** - * Clean the specified package name if necessary. If the package name cannot - * be transformed to a valid package name, the {@code defaultPackageName} - * is used instead. - *

The package name cannot be cleaned if the specified {@code packageName} - * is {@code null} or if it contains an invalid character for a class identifier. - * @see Env#invalidPackageNames - */ - String cleanPackageName(String packageName, String defaultPackageName) { - if (!packageName) { - return defaultPackageName - } - String candidate = packageName.trim().split('\\W+').join('.') - if (hasInvalidChar(candidate.replace('.', '')) || env.invalidPackageNames.contains(candidate)) { - return defaultPackageName - } else { - candidate - } - } - - private static String splitCamelCase(String text) { - text.split('(? 1) { - for (int i = 1; i < text.length(); i++) { - if (!Character.isJavaIdentifierPart(text.charAt(i))) { - return true - } - } - } - return false - } - - /** - * Defines additional environment settings. - */ - static class Env { - - /** - * The url of the repository servicing distribution bundle. - */ - String artifactRepository = 'https://repo.spring.io/release/' - - /** - * The metadata url of the Spring Boot project. - */ - String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot' - - /** - * Tracking code for Google Analytics. Only enabled if a value is explicitly provided. - */ - String googleAnalyticsTrackingCode - - /** - * The application name to use if none could be generated. - */ - String fallbackApplicationName = 'Application' - - /** - * The list of invalid application names. If such name is chosen or generated, - * the "fallbackApplicationName" should be used instead. - */ - List invalidApplicationNames = [ - 'SpringApplication', - 'SpringBootApplication' - ] - - /** - * The list of invalid package names. If such name is chosen or generated, - * the the default package name should be used instead. - */ - List invalidPackageNames = [ - 'org.springframework' - ] - - /** - * Force SSL support. When enabled, any access using http generate https links. - */ - boolean forceSsl = true - - /** - * The "BillOfMaterials" that are referenced in this instance, identified by an - * arbitrary identifier that can be used in the dependencies definition. - */ - final Map boms = [:] - - /** - * The "Repository" instances that are referenced in this instance, identified by - * an arbitrary identifier that can be used in the dependencies definition. - */ - final Map repositories = [:] - - /** - * Gradle-specific settings. - */ - final Gradle gradle = new Gradle() - - /** - * Kotlin-specific settings. - */ - final Kotlin kotlin = new Kotlin() - - /** - * Maven-specific settings. - */ - final Maven maven = new Maven() - - Env() { - repositories['spring-snapshots'] = new Repository(name: 'Spring Snapshots', - url: new URL('https://repo.spring.io/snapshot'), snapshotsEnabled: true) - repositories['spring-milestones'] = new Repository(name: 'Spring Milestones', - url: new URL('https://repo.spring.io/milestone'), snapshotsEnabled: false) - } - - void setArtifactRepository(String artifactRepository) { - if (!artifactRepository.endsWith('/')) { - artifactRepository = artifactRepository + '/' - } - this.artifactRepository = artifactRepository - } - - void validate() { - maven.parent.validate() - boms.each { - it.value.validate() - } - } - - void merge(Env other) { - artifactRepository = other.artifactRepository - springBootMetadataUrl = other.springBootMetadataUrl - googleAnalyticsTrackingCode = other.googleAnalyticsTrackingCode - fallbackApplicationName = other.fallbackApplicationName - invalidApplicationNames = other.invalidApplicationNames - forceSsl = other.forceSsl - gradle.merge(other.gradle) - kotlin.version = other.kotlin.version - maven.merge(other.maven) - other.boms.each { id, bom -> - if (!boms[id]) { - boms[id] = bom - } - } - other.repositories.each { id, repo -> - if (!repositories[id]) { - repositories[id] = repo - } - } - } - - static class Gradle { - - /** - * Version of the "dependency-management-plugin" to use. - */ - String dependencyManagementPluginVersion - - private void merge(Gradle other) { - dependencyManagementPluginVersion = other.dependencyManagementPluginVersion - } - - } - - static class Kotlin { - - /** - * Kotlin version to use. - */ - String version - } - - static class Maven { - - /** - * Custom parent pom to use for generated projects. - */ - final ParentPom parent = new ParentPom() - - private void merge(Maven other) { - parent.groupId = other.parent.groupId - parent.artifactId = other.parent.artifactId - parent.version = other.parent.version - parent.includeSpringBootBom = other.parent.includeSpringBootBom - } - - /** - * Resolve the parent pom to use. If no custom parent pom is set, - * the standard spring boot parent pom with the specified {@code bootVersion} - * is used. - */ - ParentPom resolveParentPom(String bootVersion) { - return parent.groupId ? parent : - new ParentPom(groupId: "org.springframework.boot", - artifactId: "spring-boot-starter-parent", version: bootVersion) - } - - static class ParentPom { - - /** - * Parent pom groupId. - */ - String groupId - - /** - * Parent pom artifactId. - */ - String artifactId - - /** - * Parent pom version. - */ - String version - - /** - * Add the "spring-boot-dependencies" BOM to the project. - */ - boolean includeSpringBootBom - - void validate() { - if (!((!groupId && !artifactId && !version) || - (groupId && artifactId && version))) { - throw new InvalidInitializrMetadataException("Custom maven pom " + - "requires groupId, artifactId and version") - } - } - - } - - } - - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy deleted file mode 100644 index 29c0e266..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionParser - -/** - * Meta-data used to generate a project. - * - * @author Stephane Nicoll - * @see ServiceCapability - */ -class InitializrMetadata { - - final InitializrConfiguration configuration - - final DependenciesCapability dependencies = new DependenciesCapability() - - final TypeCapability types = new TypeCapability() - - final SingleSelectCapability bootVersions = - new SingleSelectCapability('bootVersion', 'Spring Boot Version', 'spring boot version') - - final SingleSelectCapability packagings = - new SingleSelectCapability('packaging', 'Packaging', 'project packaging') - - final SingleSelectCapability javaVersions = - new SingleSelectCapability('javaVersion', 'Java Version', 'language level') - - final SingleSelectCapability languages = - new SingleSelectCapability('language', 'Language', 'programming language') - - final TextCapability name = new TextCapability('name', 'Name', 'project name (infer application name)') - - final TextCapability description = new TextCapability('description', 'Description', 'project description') - - final TextCapability groupId = new TextCapability('groupId', 'Group', 'project coordinates') - - final TextCapability artifactId = new ArtifactIdCapability(name) - - final TextCapability version = new TextCapability('version', 'Version', 'project version') - - final TextCapability packageName = new PackageCapability(groupId) - - InitializrMetadata() { - this(new InitializrConfiguration()) - } - - protected InitializrMetadata(InitializrConfiguration configuration) { - this.configuration = configuration - } - - /** - * Merge this instance with the specified argument - * @param other - */ - void merge(InitializrMetadata other) { - this.configuration.merge(other.configuration) - this.dependencies.merge(other.dependencies) - this.types.merge(other.types) - this.bootVersions.merge(other.bootVersions) - this.packagings.merge(other.packagings) - this.javaVersions.merge(other.javaVersions) - this.languages.merge(other.languages) - this.name.merge(other.name) - this.description.merge(other.description) - this.groupId.merge(other.groupId) - this.artifactId.merge(other.artifactId) - this.version.merge(other.version) - this.packageName.merge(other.packageName) - } - - /** - * Validate the metadata. - */ - void validate() { - this.configuration.validate() - dependencies.validate() - - def repositories = configuration.env.repositories - def boms = configuration.env.boms - for (Dependency dependency : dependencies.all) { - if (dependency.bom && !boms[dependency.bom]) { - throw new InvalidInitializrMetadataException("Dependency $dependency " + - "defines an invalid BOM id $dependency.bom, available boms $boms") - } - - if (dependency.repository && !repositories[dependency.repository]) { - throw new InvalidInitializrMetadataException("Dependency $dependency " + - "defines an invalid repository id $dependency.repository, available repositores $repositories") - } - } - for (BillOfMaterials bom : boms.values()) { - for (String r : bom.repositories) { - if (!repositories[r]) { - throw new InvalidInitializrMetadataException("$bom " + - "defines an invalid repository id $r, available repositores $repositories") - } - } - for (String b : bom.additionalBoms) { - if (!boms[b]) { - throw new InvalidInitializrMetadataException("$bom defines an invalid " + - "additional bom id $b, available boms $boms") - } - } - for (BillOfMaterials.Mapping m : bom.mappings) { - for (String r : m.repositories) { - if (!repositories[r]) { - throw new InvalidInitializrMetadataException("$m of $bom " + - "defines an invalid repository id $r, available repositores $repositories") - } - - } - for (String b : m.additionalBoms) { - if (!boms[b]) { - throw new InvalidInitializrMetadataException("$m of $bom defines " + - "an invalid additional bom id $b, available boms $boms") - } - } - } - } - } - - /** - * Update the available Spring Boot versions with the specified capabilities. - * @param versionsMetadata the Spring Boot boot versions metadata to use - */ - void updateSpringBootVersions(List versionsMetadata) { - bootVersions.content.clear() - bootVersions.content.addAll(versionsMetadata) - List bootVersions = bootVersions.content.collect { - Version.parse(it.id) - } - VersionParser parser = new VersionParser(bootVersions) - dependencies.updateVersionRange(parser) - configuration.env.boms.values().each { - it.updateVersionRange(parser) - } - } - - /** - * Create an URL suitable to download Spring Boot cli for the specified version and extension. - */ - String createCliDistributionURl(String extension) { - String bootVersion = defaultId(bootVersions) - configuration.env.artifactRepository + "org/springframework/boot/spring-boot-cli/" + - "$bootVersion/spring-boot-cli-$bootVersion-bin.$extension" - } - - /** - * Create a {@link BillOfMaterials} for the spring boot BOM. - */ - BillOfMaterials createSpringBootBom(String bootVersion, String versionProperty) { - new BillOfMaterials(groupId: 'org.springframework.boot', artifactId: 'spring-boot-dependencies', - version: bootVersion, versionProperty: versionProperty, order: 100) - } - - /** - * Return the defaults for the capabilities defined on this instance. - */ - Map defaults() { - def defaults = [:] - defaults['type'] = defaultId(types) - defaults['bootVersion'] = defaultId(bootVersions) - defaults['packaging'] = defaultId(packagings) - defaults['javaVersion'] = defaultId(javaVersions) - defaults['language'] = defaultId(languages) - defaults['groupId'] = groupId.content - defaults['artifactId'] = artifactId.content - defaults['version'] = version.content - defaults['name'] = name.content - defaults['description'] = description.content - defaults['packageName'] = packageName.content - defaults - } - - private static String defaultId(def element) { - def defaultValue = element.default - defaultValue ? defaultValue.id : null - } - - private static class ArtifactIdCapability extends TextCapability { - private final TextCapability nameCapability - - ArtifactIdCapability(TextCapability nameCapability) { - super('artifactId', 'Artifact', 'project coordinates (infer archive name)') - this.nameCapability = nameCapability - } - - @Override - String getContent() { - String value = super.getContent() - value == null ? nameCapability.content : value - } - } - - private static class PackageCapability extends TextCapability { - private final TextCapability nameCapability - - PackageCapability(TextCapability nameCapability) { - super('packageName', 'Package Name', 'root package') - this.nameCapability = nameCapability - } - - @Override - String getContent() { - String value = super.getContent() - value ?: (nameCapability.content != null ? nameCapability.content.replace('-', '.') : null) - } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy deleted file mode 100644 index 8204add9..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import java.nio.charset.Charset - -import com.fasterxml.jackson.databind.ObjectMapper -import groovy.util.logging.Log - -import org.springframework.core.io.Resource -import org.springframework.util.StreamUtils - -/** - * Builder for {@link InitializrMetadata}. Allows to read metadata from any arbitrary resource, - * including remote URLs. - * - * @author Stephane Nicoll - * @see InitializrMetadataCustomizer - */ -class InitializrMetadataBuilder { - - private final List customizers = [] - private final InitializrConfiguration configuration - - private InitializrMetadataBuilder(InitializrConfiguration configuration) { - this.configuration = configuration - } - - /** - * Create a builder instance from the specified {@link InitializrProperties}. Initialize - * the configuration to use. - * @see #withInitializrProperties(InitializrProperties) - */ - public static InitializrMetadataBuilder fromInitializrProperties(InitializrProperties configuration) { - new InitializrMetadataBuilder(configuration).withInitializrProperties(configuration) - } - - /** - * Create an empty builder instance with a default {@link InitializrConfiguration} - */ - public static InitializrMetadataBuilder create() { - new InitializrMetadataBuilder(new InitializrConfiguration()) - } - - - /** - * Add a {@link InitializrProperties} to be merged with other content. Merges the settings only - * and not the configuration. - * @see #withInitializrProperties(InitializrProperties, boolean) - */ - InitializrMetadataBuilder withInitializrProperties(InitializrProperties properties) { - withInitializrProperties(properties, false) - } - - /** - * Add a {@link InitializrProperties} to be merged with other content. - * @param properties the settings to merge onto this instance - * @param mergeConfiguration specify if service configuration should be merged as well - */ - InitializrMetadataBuilder withInitializrProperties(InitializrProperties properties, boolean mergeConfiguration) { - if (mergeConfiguration) { - this.configuration.merge(properties) - } - withCustomizer(new InitializerPropertiesCustomizer(properties)) - } - - /** - * Add a {@link InitializrMetadata} to be merged with other content. - * @param resource a resource to a json document describing the metadata to include - */ - InitializrMetadataBuilder withInitializrMetadata(Resource resource) { - withCustomizer(new ResourceInitializrMetadataCustomizer(resource)) - } - - /** - * Add a {@link InitializrMetadataCustomizer}. customizers are invoked in their - * order of addition. - * @see InitializrMetadataCustomizer - */ - InitializrMetadataBuilder withCustomizer(InitializrMetadataCustomizer customizer) { - customizers << customizer - this - } - - /** - * Build a {@link InitializrMetadata} based on the state of this builder. - */ - InitializrMetadata build() { - InitializrConfiguration config = this.configuration ?: new InitializrConfiguration() - InitializrMetadata metadata = createInstance(config) - for (InitializrMetadataCustomizer customizer : customizers) { - customizer.customize(metadata) - } - applyDefaults(metadata) - metadata.validate() - metadata - } - - /** - * Creates an empty instance based on the specified {@link InitializrConfiguration} - */ - protected InitializrMetadata createInstance(InitializrConfiguration configuration) { - new InitializrMetadata(configuration) - } - - /** - * Apply defaults to capabilities that have no value. - */ - protected applyDefaults(InitializrMetadata metadata) { - if (!metadata.name.content) { - metadata.name.content = 'demo' - } - if (!metadata.description.content) { - metadata.description.content = 'Demo project for Spring Boot' - } - if (!metadata.groupId.content) { - metadata.groupId.content = 'com.example' - } - if (!metadata.version.content) { - metadata.version.content = '0.0.1-SNAPSHOT' - } - } - - private static class InitializerPropertiesCustomizer implements InitializrMetadataCustomizer { - - private final InitializrProperties properties - - InitializerPropertiesCustomizer(InitializrProperties properties) { - this.properties = properties - } - - @Override - void customize(InitializrMetadata metadata) { - metadata.dependencies.merge(properties.dependencies) - metadata.types.merge(properties.types) - metadata.bootVersions.merge(properties.bootVersions) - metadata.packagings.merge(properties.packagings) - metadata.javaVersions.merge(properties.javaVersions) - metadata.languages.merge(properties.languages) - properties.groupId.apply(metadata.groupId) - properties.artifactId.apply(metadata.artifactId) - properties.version.apply(metadata.version) - properties.name.apply(metadata.name) - properties.description.apply(metadata.description) - properties.packageName.apply(metadata.packageName) - } - } - - @Log - private static class ResourceInitializrMetadataCustomizer implements InitializrMetadataCustomizer { - - private static final Charset UTF_8 = Charset.forName('UTF-8') - - private final Resource resource - - ResourceInitializrMetadataCustomizer(Resource resource) { - this.resource = resource - } - - @Override - void customize(InitializrMetadata metadata) { - log.info("Loading initializr metadata from $resource") - def content = StreamUtils.copyToString(resource.getInputStream(), UTF_8) - ObjectMapper objectMapper = new ObjectMapper() - def anotherMetadata = objectMapper.readValue(content, InitializrMetadata) - metadata.merge(anotherMetadata) - } - - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy deleted file mode 100644 index c52853b3..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import com.fasterxml.jackson.annotation.JsonIgnore - -import org.springframework.boot.context.properties.ConfigurationProperties - -/** - * Configuration of the initializr service. - * - * @author Stephane Nicoll - */ -@ConfigurationProperties(prefix = 'initializr') -class InitializrProperties extends InitializrConfiguration { - - /** - * Dependencies, organized in groups (i.e. themes). - */ - @JsonIgnore - final List dependencies = [] - - /** - * Available project types. - */ - @JsonIgnore - final List types = [] - - /** - * Available packaging types. - */ - @JsonIgnore - final List packagings = [] - - /** - * Available java versions. - */ - @JsonIgnore - final List javaVersions = [] - - /** - * Available programming languages. - */ - @JsonIgnore - final List languages = [] - - /** - * Available Spring Boot versions. - */ - @JsonIgnore - final List bootVersions = [] - - /** - * GroupId metadata. - */ - @JsonIgnore - final SimpleElement groupId = new SimpleElement(value: 'com.example') - - /** - * ArtifactId metadata. - */ - @JsonIgnore - final SimpleElement artifactId = new SimpleElement() - - /** - * Version metadata. - */ - @JsonIgnore - final SimpleElement version = new SimpleElement(value: '0.0.1-SNAPSHOT') - - /** - * Name metadata. - */ - @JsonIgnore - final SimpleElement name = new SimpleElement(value: 'demo') - - /** - * Description metadata. - */ - @JsonIgnore - final SimpleElement description = new SimpleElement(value: 'Demo project for Spring Boot') - - /** - * Package name metadata. - */ - @JsonIgnore - final SimpleElement packageName = new SimpleElement() - - - static class SimpleElement { - /** - * Element title. - */ - String title - - /** - * Element description. - */ - String description - - /** - * Element default value. - */ - String value - - void apply(TextCapability capability) { - if (title) { - capability.title = title - } - if (description) { - capability.description = description - } - if (value) { - capability.content = value - } - } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Link.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Link.groovy deleted file mode 100644 index 95ad317a..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Link.groovy +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.fasterxml.jackson.annotation.JsonInclude -import groovy.transform.ToString - -/** - * Metadata for a link. Each link has a "relation" that potentially attaches a strong - * semantic to the nature of the link. The URI of the link itself can be templated by - * including variables in the form `{variableName}`. - *

- * An actual {@code URI} can be generated using {@code expand}, providing a mapping for - * those variables. - * - * @author Dave Syer - * @author Stephane Nicoll - */ -@ToString(ignoreNulls = true, includePackage = false) -class Link { - - private static final String VARIABLE_REGEX = "\\{(\\w+)\\}"; - - /** - * The relation of the link. - */ - String rel; - - /** - * The URI the link is pointing to. - */ - String href - - /** - * Specify if the URI is templated. - */ - @JsonInclude(JsonInclude.Include.NON_DEFAULT) - boolean templated - - @JsonIgnore - final Set templateVariables = [] - - /** - * A description of the link. - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - String description - - Set getTemplateVariables() { - Collections.unmodifiableSet(templateVariables) - } - - void setHref(String href) { - this.href = href - } - - void resolve() { - if (!rel) { - throw new InvalidInitializrMetadataException( - "Invalid link $this: rel attribute is mandatory") - } - if (!href) { - throw new InvalidInitializrMetadataException( - "Invalid link $this: href attribute is mandatory") - } - def matcher = (href =~ VARIABLE_REGEX) - while (matcher.find()) { - def variable = matcher.group(1) - this.templateVariables << variable - } - this.templated = this.templateVariables - } - - /** - * Expand the link using the specified parameters. - * @param parameters the parameters value - * @return an URI where all variables have been expanded - */ - URI expand(Map parameters) { - String result = href - templateVariables.forEach { var -> - Object value = parameters[var] - if (!value) { - throw new IllegalArgumentException( - "Could not explan $href, missing value for '$var'") - } - result = result.replace("{$var}", value.toString()) - } - new URI(result) - } - - public static Link create(String rel, String href) { - return new Link(rel: rel, href: href); - } - - public static Link create(String rel, String href, String description) { - return new Link(rel: rel, href: href, description: description); - } - - public static Link create(String rel, String href, boolean templated) { - return new Link(rel: rel, href: href, templated: templated); - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Repository.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Repository.groovy deleted file mode 100644 index 70c83207..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Repository.groovy +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import groovy.transform.EqualsAndHashCode -import groovy.transform.ToString - -/** - * Define a repository to be represented in the generated project - * if a dependency refers to it. - * - * @author Stephane Nicoll - */ -@EqualsAndHashCode -@ToString(includePackage = false) -class Repository { - - String name - URL url - boolean snapshotsEnabled - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy deleted file mode 100644 index b70d6e36..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonInclude -import groovy.transform.AutoClone -import groovy.transform.AutoCloneStyle - -import org.springframework.util.Assert - -/** - * Defines a capability of the initializr service. Each capability - * is defined by a id and a {@link ServiceCapabilityType type}. - * - * @author Stephane Nicoll - */ -@JsonIgnoreProperties(["default", "all"]) -@JsonInclude(JsonInclude.Include.NON_NULL) -@AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) -abstract class ServiceCapability implements Cloneable { - - final String id - - final ServiceCapabilityType type - - /** - * A title of the capability, used as a header text or label. - */ - String title - - /** - * A description of the capability, used in help usage or UI tooltips. - */ - String description - - protected ServiceCapability(String id, ServiceCapabilityType type) { - this.id = id - this.type = type - } - - protected ServiceCapability(String id, ServiceCapabilityType type, String title, String description) { - this.id = id - this.type = type - this.title = title - this.description = description - } - - /** - * Return the "content" of this capability. The structure of the content - * vastly depends on the {@link ServiceCapability type} of the capability. - */ - abstract T getContent() - - /** - * Merge the content of this instance with the specified content. - * @see #merge(io.spring.initializr.metadata.ServiceCapability) - */ - abstract void merge(T otherContent) - - /** - * Merge this capability with the specified argument. The service capabilities - * should match (i.e have the same {@code id} and {@code type}). Sub-classes - * may merge additional content. - */ - void merge(ServiceCapability other) { - Assert.notNull(other, "Other must not be null") - Assert.state(this.id.equals(other.id)) - Assert.state(this.type.equals(other.type)) - if (other.title) { - this.title = other.title - } - if (other.description) { - this.description = other.description - } - merge(other.content) - } - -} - diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy deleted file mode 100644 index 743fc6eb..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import java.util.concurrent.CopyOnWriteArrayList - -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty - -/** - * A {@link ServiceCapabilityType#SINGLE_SELECT single select} capability. - * - * @author Stephane Nicoll - */ -class SingleSelectCapability extends ServiceCapability> { - - final List content = new CopyOnWriteArrayList() - - @JsonCreator - SingleSelectCapability(@JsonProperty("id") String id) { - this(id, null, null) - } - - SingleSelectCapability(String id, String title, String description) { - super(id, ServiceCapabilityType.SINGLE_SELECT, title, description) - } - - /** - * Return the default element of this capability. - */ - DefaultMetadataElement getDefault() { - return content.find { it.default } - } - - /** - * Return the element with the specified id or {@code null} if no such - * element exists. - */ - DefaultMetadataElement get(String id) { - return content.find { id.equals(it.id)} - } - - @Override - void merge(List otherContent) { - otherContent.each { - if (!get(it.id)) { - content << it - } - } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Type.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Type.groovy deleted file mode 100644 index 12431b29..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Type.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -/** - * Defines a particular project type. Each type is associated to a concrete - * action that should be invoked to generate the content of that type. - * - * @author Stephane Nicoll - */ -class Type extends DefaultMetadataElement implements Describable { - - String description - - @Deprecated - String stsId - - String action - - final Map tags = [:] - - void setAction(String action) { - String actionToUse = action - if (!actionToUse.startsWith("/")) { - actionToUse = "/" + actionToUse - } - this.action = actionToUse - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/Agent.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/util/Agent.groovy deleted file mode 100644 index 9b34269b..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/Agent.groovy +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 io.spring.initializr.util - -/** - * Defines the agent that submitted a request. - * - * @author Stephane Nicoll - */ -class Agent { - - /** - * The {@link AgentId}. - */ - final AgentId id - - /** - * The version of the agent, if any - */ - final String version - - Agent(AgentId id, String version) { - this.id = id - this.version = version - } - - /** - * Create an {@link Agent} based on the specified {@code User-Agent} header. - * @param userAgent the user agent - * @return an {@link Agent} instance or {@code null} - */ - static Agent fromUserAgent(String userAgent) { - UserAgentHandler.parse(userAgent) - } - - /** - * Defines the various known agents. - */ - static enum AgentId { - - CURL('curl', 'curl'), - - HTTPIE('httpie', 'HTTPie'), - - SPRING_BOOT_CLI('spring', 'SpringBootCli'), - - STS('sts', 'STS'), - - INTELLIJ_IDEA('intellijidea', 'IntelliJ IDEA'), - - NETBEANS('netbeans', 'NetBeans'), - - BROWSER('browser', 'Browser') - - final String id - final String name - - private AgentId(String id, String name) { - this.id = id - this.name = name - } - } - - private static class UserAgentHandler { - - private static final TOOL_REGEX = '([^\\/]*)\\/([^ ]*).*' - - private static final STS_REGEX = 'STS (.*)' - - private static final NETBEANS_REGEX = 'nb-springboot-plugin\\/(.*)' - - static Agent parse(String userAgent) { - def matcher = (userAgent =~ TOOL_REGEX) - if (matcher.matches()) { - String name = matcher.group(1) - for (AgentId id : AgentId.values()) { - if (name.equals(id.name)) { - String version = matcher.group(2) - return new Agent(id, version) - } - } - } - matcher = userAgent =~ STS_REGEX - if (matcher.matches()) { - return new Agent(AgentId.STS, matcher.group(1)) - } - matcher = userAgent =~ NETBEANS_REGEX - if (matcher.matches()) { - return new Agent(AgentId.NETBEANS, matcher.group(1)) - } - - if (userAgent.equals(AgentId.INTELLIJ_IDEA.name)) { - return new Agent(AgentId.INTELLIJ_IDEA, null) - } - if (userAgent.contains('Mozilla/5.0')) { // Super heuristics - return new Agent(AgentId.BROWSER, null) - } - return null - } - - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy deleted file mode 100644 index 99d47f83..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 io.spring.initializr.util - -import java.util.concurrent.ConcurrentMap - -import groovy.text.GStringTemplateEngine -import groovy.text.Template -import groovy.text.TemplateEngine -import org.codehaus.groovy.control.CompilationFailedException - -import org.springframework.util.ConcurrentReferenceHashMap - -/** - * @author Dave Syer - */ -class GroovyTemplate { - - boolean cache = true - - private final TemplateEngine engine - private final ConcurrentMap templateCaches = new ConcurrentReferenceHashMap<>() - - GroovyTemplate(TemplateEngine engine) { - this.engine = engine - } - - GroovyTemplate() { - this(new GStringTemplateEngine()) - } - - String process(String name, Map model) - throws IOException, CompilationFailedException, ClassNotFoundException { - def template = getTemplate(name) - def writable = template.make(model) - def result = new StringWriter() - writable.writeTo(result) - result.toString() - } - - Template getTemplate(String name) - throws CompilationFailedException, ClassNotFoundException, IOException { - if (cache) { - return this.templateCaches.computeIfAbsent(name, { n -> loadTemplate(n) }) - } - return loadTemplate(name) - } - - protected Template loadTemplate(String name) { - def file = new File("templates", name) - if (file.exists()) { - return engine.createTemplate(file) - } - - def classLoader = GroovyTemplate.class.classLoader - def resource = classLoader.getResource("templates/" + name) - if (resource) { - return engine.createTemplate(resource.getText('utf-8')) - } - - return engine.createTemplate(name) - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/Version.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/util/Version.groovy deleted file mode 100644 index dfb7b7d0..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/Version.groovy +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 io.spring.initializr.util - -import groovy.transform.EqualsAndHashCode -import groovy.transform.ToString - -import org.springframework.util.Assert - -/** - * Define the version number of a module. A typical version is represented - * as {@code MAJOR.MINOR.PATCH.QUALIFIER} where the qualifier can have an - * extra version. - *

- * For example: {@code 1.2.0.RC1} is the first release candidate of 1.2.0 - * and {@code 1.5.0.M4} is the fourth milestone of 1.5.0. The special - * {@code RELEASE} qualifier indicates a final release (a.k.a. GA) - *

- * The main purpose of parsing a version is to compare it with another - * version, see {@link Comparable}. - * - * @author Stephane Nicoll - */ -@EqualsAndHashCode -@SuppressWarnings("serial") -final class Version implements Serializable, Comparable { - - private static final String VERSION_REGEX = '^(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.([^0-9]+)(\\d+)?)?$' - - private static final VersionQualifierComparator qualifierComparator = new VersionQualifierComparator() - - private static final VersionParser parser = new VersionParser(Collections.EMPTY_LIST) - - final Integer major - final Integer minor - final Integer patch - final Qualifier qualifier - - Version(Integer major, Integer minor, Integer patch, Qualifier qualifier) { - this.major = major - this.minor = minor - this.patch = patch - this.qualifier = qualifier - } - - @Override - String toString() { - "${major}.${minor}.${patch}" + (qualifier?".${qualifier.qualifier}${qualifier.version?:''}" : '') - } - - /** - * Parse the string representation of a {@link Version}. Throws an - * {@link InvalidVersionException} if the version could not be parsed. - * @param text the version text - * @return a Version instance for the specified version text - * @throws InvalidVersionException if the version text could not be parsed - * @see {@link VersionParser} - */ - static Version parse(String text) { - return parser.parse(text) - } - - /** - * Parse safely the specified string representation of a {@link Version}. - *

- * Return {@code null} if the text represents an invalid version. - * @param text the version text - * @return a Version instance for the specified version text - * @see {@link VersionParser} - */ - static Version safeParse(String text) { - try { - return parse(text) - } catch (InvalidVersionException e) { - return null - } - } - - @Override - int compareTo(Version other) { - if (other == null) { - return 1 - } - int majorDiff = safeCompare(this.major, other.major) - if (majorDiff != 0) { - return majorDiff - } - int minorDiff = safeCompare(this.minor, other.minor) - if (minorDiff != 0) { - return minorDiff - } - int patch = safeCompare(this.patch, other.patch) - if (patch != 0) { - return patch - } - qualifierComparator.compare(this.qualifier, other.qualifier) - } - - private static int safeCompare(Integer first, Integer second) { - int firstIndex = first ?: 0 - int secondIndex = second ?: 0 - return firstIndex.compareTo(secondIndex) - } - - @ToString - @EqualsAndHashCode - static class Qualifier { - String qualifier - Integer version - } - - - private static class VersionQualifierComparator implements Comparator { - - static final String RELEASE = 'RELEASE' - static final String SNAPSHOT = 'BUILD-SNAPSHOT' - static final String MILESTONE = 'M' - static final String RC = 'RC' - - static final List KNOWN_QUALIFIERS = Arrays.asList(MILESTONE, RC, SNAPSHOT, RELEASE) - - @Override - int compare(Qualifier o1, Qualifier o2) { - Qualifier first = o1 ?: new Qualifier(qualifier: RELEASE) - Qualifier second = o2 ?: new Qualifier(qualifier: RELEASE) - - int qualifier = compareQualifier(first, second) - qualifier ? qualifier : compareQualifierVersion(first, second) - } - - private static int compareQualifierVersion(Qualifier first, Qualifier second) { - int firstVersion = first.getVersion() ?: 0 - int secondVersion = second.getVersion() ?: 0 - firstVersion.compareTo(secondVersion) - } - - private static int compareQualifier(Qualifier first, Qualifier second) { - int firstIndex = getQualifierIndex(first.qualifier) - int secondIndex = getQualifierIndex(second.qualifier) - - if (firstIndex == -1 && secondIndex == -1) { // Unknown qualifier, alphabetic ordering - return first.qualifier.compareTo(second.qualifier) - } else { - return firstIndex.compareTo(secondIndex) - } - } - - private static int getQualifierIndex(String qualifier) { - qualifier ? KNOWN_QUALIFIERS.indexOf(qualifier) : RELEASE - } - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/VersionRange.groovy b/initializr-generator/src/main/groovy/io/spring/initializr/util/VersionRange.groovy deleted file mode 100644 index bfc0e5ae..00000000 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/VersionRange.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 io.spring.initializr.util - -import groovy.transform.EqualsAndHashCode - -import org.springframework.util.Assert - -/** - * Define a {@link Version} range. A square bracket "[" or "]" denotes an inclusive - * end of the range and a round bracket "(" or ")" denotes an exclusive end of the - * range. A range can also be unbounded by defining a a single {@link Version}. The - * examples below make this clear. - * - *

    - *
  • "[1.2.0.RELEASE,1.3.0.RELEASE)" version 1.2.0 and any version after - * this, up to, but not including, version 1.3.0.
  • - *
  • "(2.0.0.RELEASE,3.2.0.RELEASE]" any version after 2.0.0 up to and - * including version 3.2.0.
  • - *
  • "1.4.5.RELEASE", version 1.4.5 and all later versions.
  • - *
- * - * @author Stephane Nicoll - */ -@EqualsAndHashCode -class VersionRange { - - final Version lowerVersion - final boolean lowerInclusive - final Version higherVersion - final boolean higherInclusive - - protected VersionRange(Version lowerVersion, boolean lowerInclusive, - Version higherVersion, boolean higherInclusive) { - this.lowerVersion = lowerVersion - this.lowerInclusive = lowerInclusive - this.higherVersion = higherVersion - this.higherInclusive = higherInclusive - } - - /** - * Specify if the {@link Version} matches this range. Returns {@code true} - * if the version is contained within this range, {@code false} otherwise. - */ - boolean match(Version version) { - Assert.notNull(version, "Version must not be null") - def lower = lowerVersion.compareTo(version) - if (lower > 0) { - return false; - } else if (!lowerInclusive && lower == 0) { - return false; - } - if (higherVersion) { - def higher = higherVersion.compareTo(version) - if (higher < 0) { - return false - } else if (!higherInclusive && higher == 0) { - return false - } - } - return true - } - - @Override - String toString() { - StringBuffer sb = new StringBuffer() - if (lowerVersion) { - sb.append("${lowerInclusive ? '>=' : '>'}${lowerVersion}") - } - if (higherVersion) { - sb.append(" and ${higherInclusive ? '<=' : '<'}${higherVersion}") - } - return sb.toString() - } - -} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy b/initializr-generator/src/main/java/io/spring/initializr/InitializrException.java similarity index 68% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy rename to initializr-generator/src/main/java/io/spring/initializr/InitializrException.java index 942d03b4..82b6087e 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/InitializrException.java @@ -14,17 +14,21 @@ * limitations under the License. */ -package io.spring.initializr.metadata - -import groovy.transform.InheritConstructors -import io.spring.initializr.InitializrException +package io.spring.initializr; /** - * Thrown when the configuration defines invalid metadata. + * Base Initializr exception. * * @author Stephane Nicoll */ -@InheritConstructors -class InvalidInitializrMetadataException extends InitializrException { -} +@SuppressWarnings("serial") +public class InitializrException extends RuntimeException { + public InitializrException(String message, Throwable cause) { + super(message, cause); + } + + public InitializrException(String message) { + super(message); + } +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/BasicProjectRequest.java b/initializr-generator/src/main/java/io/spring/initializr/generator/BasicProjectRequest.java new file mode 100644 index 00000000..fea2da59 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/BasicProjectRequest.java @@ -0,0 +1,168 @@ +/* + * 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 io.spring.initializr.generator; + +import java.util.ArrayList; +import java.util.List; + +/** + * The base settings of a project request. Only these can be bound by user's + * input. + * + * @author Stephane Nicoll + */ +public class BasicProjectRequest { + + private List style = new ArrayList<>(); + private List dependencies = new ArrayList<>(); + private String name; + private String type; + private String description; + private String groupId; + private String artifactId; + private String version; + private String bootVersion; + private String packaging; + private String applicationName; + private String language; + private String packageName; + private String javaVersion; + + // The base directory to create in the archive - no baseDir by default + private String baseDir; + + public List getStyle() { + return style; + } + + public void setStyle(List style) { + this.style = style; + } + + public List getDependencies() { + return dependencies; + } + + public void setDependencies(List dependencies) { + this.dependencies = dependencies; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getBootVersion() { + return bootVersion; + } + + public void setBootVersion(String bootVersion) { + this.bootVersion = bootVersion; + } + + public String getPackaging() { + return packaging; + } + + public void setPackaging(String packaging) { + this.packaging = packaging; + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getJavaVersion() { + return javaVersion; + } + + public void setJavaVersion(String javaVersion) { + this.javaVersion = javaVersion; + } + + public String getBaseDir() { + return baseDir; + } + + public void setBaseDir(String baseDir) { + this.baseDir = baseDir; + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/BuildProperties.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/BuildProperties.java similarity index 62% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/BuildProperties.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/BuildProperties.java index 2d63b8af..47c6f912 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/BuildProperties.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/BuildProperties.java @@ -14,29 +14,44 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; + +import java.util.TreeMap; +import java.util.function.Supplier; /** * Build properties associated to a project request. * * @author Stephane Nicoll */ -class BuildProperties { +public class BuildProperties { /** * Maven-specific build properties, added to the regular {@code properties} element. */ - final TreeMap> maven = new TreeMap<>() + private final TreeMap> maven = new TreeMap<>(); /** * Gradle-specific build properties, added to the {@code buildscript} section * of the gradle build. */ - final TreeMap> gradle = new TreeMap<>() + private final TreeMap> gradle = new TreeMap<>(); /** * Version properties. Shared between the two build systems. */ - final TreeMap> versions = new TreeMap<>() + private final TreeMap> versions = new TreeMap<>(); + + public TreeMap> getMaven() { + return maven; + } + + public TreeMap> getGradle() { + return gradle; + } + + public TreeMap> getVersions() { + return versions; + } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/CommandLineHelpGenerator.java b/initializr-generator/src/main/java/io/spring/initializr/generator/CommandLineHelpGenerator.java new file mode 100644 index 00000000..bff98221 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/CommandLineHelpGenerator.java @@ -0,0 +1,307 @@ +/* + * 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 io.spring.initializr.generator; + +import java.beans.PropertyDescriptor; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.BeanWrapperImpl; + +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.Type; +import io.spring.initializr.util.GroovyTemplate; + +/** + * Generate help pages for command-line clients. + * + * @author Stephane Nicoll + */ +public class CommandLineHelpGenerator { + + private static final String logo = " . ____ _ __ _ _\n" + + " /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\\n" + + "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\\n" + + " \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )\n" + + " ' |____| .__|_| |_|_| |_\\__, | / / / /\n" + + " =========|_|==============|___/=/_/_/_/"; + + private final GroovyTemplate template; + + public CommandLineHelpGenerator(GroovyTemplate template) { + this.template = template; + } + + /** + * Generate the capabilities of the service as a generic plain text document. Used + * when no particular agent was detected. + */ + public String generateGenericCapabilities(InitializrMetadata metadata, + String serviceUrl) { + Map model = initializeCommandLineModel(metadata, serviceUrl); + model.put("hasExamples", false); + return template.process("cli-capabilities.txt", model); + } + + /** + * Generate the capabilities of the service using "curl" as a plain text document. + */ + public String generateCurlCapabilities(InitializrMetadata metadata, + String serviceUrl) { + Map model = initializeCommandLineModel(metadata, serviceUrl); + model.put("examples", template.process("curl-examples.txt", model)); + model.put("hasExamples", true); + return template.process("cli-capabilities.txt", model); + } + + /** + * Generate the capabilities of the service using "HTTPie" as a plain text document. + */ + public String generateHttpieCapabilities(InitializrMetadata metadata, + String serviceUrl) { + Map model = initializeCommandLineModel(metadata, serviceUrl); + model.put("examples", template.process("httpie-examples.txt", model)); + model.put("hasExamples", true); + return template.process("cli-capabilities.txt", model); + } + + /** + * Generate the capabilities of the service using Spring Boot CLI as a plain text + * document. + */ + public String generateSpringBootCliCapabilities(InitializrMetadata metadata, + String serviceUrl) { + Map model = initializeSpringBootCliModel(metadata, serviceUrl); + model.put("hasExamples", false); + return template.process("boot-cli-capabilities.txt", model); + } + + protected Map initializeCommandLineModel(InitializrMetadata metadata, + String serviceUrl) { + Map model = new LinkedHashMap<>(); + model.put("logo", logo); + model.put("serviceUrl", serviceUrl); + model.put("dependencies", generateDependencyTable(metadata)); + model.put("types", generateTypeTable(metadata, "Rel", false)); + + Map defaults = metadata.defaults(); + defaults.put("applicationName", metadata.getConfiguration() + .generateApplicationName(metadata.getName().getContent())); + defaults.put("baseDir", "no base dir"); + defaults.put("dependencies", "none"); + + Map parametersDescription = buildParametersDescription(metadata); + String[][] parameterTable = new String[defaults.size() + 1][]; + parameterTable[0] = new String[] { "Parameter", "Description", "Default value" }; + int i = 1; + for (String id : defaults.keySet().stream().sorted() + .collect(Collectors.toList())) { + String[] data = new String[3]; + data[0] = id; + data[1] = (String) parametersDescription.get(id); + data[2] = (String) defaults.get(id); + parameterTable[i++] = data; + } + model.put("parameters", TableGenerator.generate(parameterTable)); + + return model; + } + + protected Map initializeSpringBootCliModel( + InitializrMetadata metadata, String serviceUrl) { + Map model = new LinkedHashMap<>(); + model.put("logo", logo); + model.put("serviceUrl", serviceUrl); + model.put("dependencies", generateDependencyTable(metadata)); + model.put("types", generateTypeTable(metadata, "Id", true)); + + Map defaults = metadata.defaults(); + Map parametersDescription = buildParametersDescription(metadata); + String[][] parameterTable = new String[defaults.size() + 1][]; + parameterTable[0] = new String[] { "Id", "Description", "Default value" }; + int i = 1; + for (String id : defaults.keySet().stream().sorted() + .collect(Collectors.toList())) { + String[] data = new String[3]; + data[0] = id; + data[1] = (String) parametersDescription.get(id); + data[2] = (String) defaults.get(id); + parameterTable[i++] = data; + } + model.put("parameters", TableGenerator.generate(parameterTable)); + return model; + } + + protected String generateDependencyTable(InitializrMetadata metadata) { + String[][] dependencyTable = new String[metadata.getDependencies().getAll().size() + + 1][]; + dependencyTable[0] = new String[] { "Id", "Description", "Required version" }; + int i = 1; + for (Dependency dep : metadata.getDependencies().getAll().stream() + .sorted((a, b) -> a.getId().compareTo(b.getId())) + .collect(Collectors.toList())) { + String[] data = new String[3]; + data[0] = dep.getId(); + data[1] = dep.getDescription() != null ? dep.getDescription() : dep.getName(); + data[2] = dep.getVersionRequirement(); + dependencyTable[i++] = data; + } + ; + return TableGenerator.generate(dependencyTable); + } + + protected String generateTypeTable(InitializrMetadata metadata, String linkHeader, + boolean addTags) { + String[][] typeTable = new String[metadata.getTypes().getContent().size() + 1][]; + if (addTags) { + typeTable[0] = new String[] { linkHeader, "Description", "Tags" }; + } + else { + typeTable[0] = new String[] { linkHeader, "Description" }; + } + int i = 1; + for (Type type : metadata.getTypes().getContent().stream() + .sorted((a, b) -> a.getId().compareTo(b.getId())) + .collect(Collectors.toList())) { + String[] data = new String[typeTable[0].length]; + data[0] = (type.isDefault() ? type.getId() + " *" : type.getId()); + data[1] = type.getDescription() != null ? type.getDescription() + : type.getName(); + if (addTags) { + data[2] = buildTagRepresentation(type); + } + typeTable[i++] = data; + } + return TableGenerator.generate(typeTable); + } + + protected Map buildParametersDescription( + InitializrMetadata metadata) { + Map result = new LinkedHashMap<>(); + BeanWrapperImpl wrapper = new BeanWrapperImpl(metadata); + for (PropertyDescriptor descriptor : wrapper.getPropertyDescriptors()) { + Object value = wrapper.getPropertyValue(descriptor.getName()); + BeanWrapperImpl nested = new BeanWrapperImpl(value); + if (nested.isReadableProperty("description") + && nested.isReadableProperty("id")) { + result.put((String) nested.getPropertyValue("id"), + nested.getPropertyValue("description")); + } + } + result.put("applicationName", "application name"); + result.put("baseDir", "base directory to create in the archive"); + return result; + } + + private static String buildTagRepresentation(Type type) { + if (type.getTags().isEmpty()) { + return ""; + } + return String.join(",", + type.getTags().entrySet().stream() + .map(entry -> entry.getKey() + ":" + entry.getValue()) + .collect(Collectors.toList()).toArray(new String[0])); + } + + private static class TableGenerator { + + static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Generate a table description for the specified {@code content}. + *

+ * The {@code content} is a two-dimensional array holding the rows of the table. + * The first entry holds the header of the table. + */ + public static String generate(String[][] content) { + StringBuilder sb = new StringBuilder(); + int[] columnsLength = computeColumnsLength(content); + appendTableSeparation(sb, columnsLength); + appendRow(sb, content, columnsLength, 0); // Headers + appendTableSeparation(sb, columnsLength); + for (int i = 1; i < content.length; i++) { + appendRow(sb, content, columnsLength, i); + } + appendTableSeparation(sb, columnsLength); + return sb.toString(); + } + + private static void appendRow(StringBuilder sb, String[][] content, + int[] columnsLength, int rowIndex) { + String[] row = content[rowIndex]; + if (row != null) { + for (int i = 0; i < row.length; i++) { + sb.append("| ").append(fill(row[i], columnsLength[i])).append(" "); + } + } + sb.append("|"); + sb.append(NEW_LINE); + } + + private static void appendTableSeparation(StringBuilder sb, int[] headersLength) { + for (int headerLength : headersLength) { + sb.append("+").append(multiply("-", headerLength + 2)); + } + sb.append("+"); + sb.append(NEW_LINE); + } + + private static String fill(String data, int columnSize) { + if (data == null) { + return multiply(" ", columnSize); + } + else { + int i = columnSize - data.length(); + return data + multiply(" ", i); + } + } + + private static String multiply(String value, int size) { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < size; i++) { + s.append(value); + } + return s.toString(); + } + + private static int[] computeColumnsLength(String[][] content) { + int count = content[0].length; + int[] result = new int[count]; + for (int i = 0; i < count; i++) { + result[i] = largest(content, i); + } + return result; + } + + private static int largest(String[][] content, int column) { + int max = 0; + for (String[] rows : content) { + if (rows != null) { + String s = rows[column]; + if (s != null && s.length() > max) { + max = s.length(); + } + } + } + return max; + } + + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/InvalidProjectRequestException.java similarity index 65% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/InvalidProjectRequestException.java index 2669a383..a0d0c14c 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/InvalidProjectRequestException.java @@ -14,16 +14,23 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; -import groovy.transform.InheritConstructors -import io.spring.initializr.InitializrException +import io.spring.initializr.InitializrException; /** * Thrown when a {@link ProjectRequest} is invalid. * * @author Stephane Nicoll */ -@InheritConstructors -class InvalidProjectRequestException extends InitializrException { +@SuppressWarnings("serial") +public class InvalidProjectRequestException extends InitializrException { + + public InvalidProjectRequestException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidProjectRequestException(String message) { + super(message); + } } diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectFailedEvent.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectFailedEvent.java similarity index 72% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectFailedEvent.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/ProjectFailedEvent.java index 7eb19270..a23ea2b6 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectFailedEvent.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectFailedEvent.java @@ -14,23 +14,27 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; /** * Event published when an error occured trying to generate a project. * * @author Stephane Nicoll */ -class ProjectFailedEvent extends ProjectRequestEvent { +public class ProjectFailedEvent extends ProjectRequestEvent { /** * The cause of the failure. */ - final Exception cause + final Exception cause; - ProjectFailedEvent(ProjectRequest projectRequest, Exception cause) { - super(projectRequest) - this.cause = cause + public ProjectFailedEvent(ProjectRequest projectRequest, Exception cause) { + super(projectRequest); + this.cause = cause; + } + + public Exception getCause() { + return cause; } } diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGeneratedEvent.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGeneratedEvent.java similarity index 79% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGeneratedEvent.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGeneratedEvent.java index c9129c96..1d8f36a8 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectGeneratedEvent.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGeneratedEvent.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; /** * Event published when a new project has been generated successfully. * * @author Stephane Nicoll */ -class ProjectGeneratedEvent extends ProjectRequestEvent { +public class ProjectGeneratedEvent extends ProjectRequestEvent { - ProjectGeneratedEvent(ProjectRequest projectRequest) { - super(projectRequest) + public ProjectGeneratedEvent(ProjectRequest projectRequest) { + super(projectRequest); } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGenerator.java b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGenerator.java new file mode 100644 index 00000000..93df1c9b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGenerator.java @@ -0,0 +1,563 @@ +/* + * 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 io.spring.initializr.generator; + +import java.beans.PropertyDescriptor; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.util.Assert; +import org.springframework.util.FileSystemUtils; +import org.springframework.util.StreamUtils; + +import io.spring.initializr.InitializrException; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.InitializrMetadataProvider; +import io.spring.initializr.util.GroovyTemplate; +import io.spring.initializr.util.Version; + +/** + * Generate a project based on the configured metadata. + * + * @author Dave Syer + * @author Stephane Nicoll + * @author Sebastien Deleuze + */ +public class ProjectGenerator { + + private static final Logger log = LoggerFactory.getLogger(ProjectGenerator.class); + + private static final Version VERSION_1_2_0_RC1 = Version.parse("1.2.0.RC1"); + + private static final Version VERSION_1_3_0_M1 = Version.parse("1.3.0.M1"); + + private static final Version VERSION_1_4_0_M2 = Version.parse("1.4.0.M2"); + + private static final Version VERSION_1_4_0_M3 = Version.parse("1.4.0.M3"); + + private static final Version VERSION_1_4_2_M1 = Version.parse("1.4.2.M1"); + + private static final Version VERSION_2_0_0_M1 = Version.parse("2.0.0.M1"); + + @Autowired + private ApplicationEventPublisher eventPublisher; + + @Autowired + private InitializrMetadataProvider metadataProvider; + + @Autowired + private ProjectRequestResolver requestResolver; + + @Autowired + private GroovyTemplate groovyTemplate = new GroovyTemplate(); + + @Autowired + private ProjectResourceLocator projectResourceLocator = new ProjectResourceLocator(); + + @Value("${TMPDIR:.}/initializr") + private String tmpdir; + + private File temporaryDirectory; + private transient Map> temporaryFiles = new LinkedHashMap<>(); + + public InitializrMetadataProvider getMetadataProvider() { + return metadataProvider; + } + + public void setEventPublisher(ApplicationEventPublisher eventPublisher) { + this.eventPublisher = eventPublisher; + } + + public void setMetadataProvider(InitializrMetadataProvider metadataProvider) { + this.metadataProvider = metadataProvider; + } + + public void setRequestResolver(ProjectRequestResolver requestResolver) { + this.requestResolver = requestResolver; + } + + public void setGroovyTemplate(GroovyTemplate groovyTemplate) { + this.groovyTemplate = groovyTemplate; + } + + public void setProjectResourceLocator(ProjectResourceLocator projectResourceLocator) { + this.projectResourceLocator = projectResourceLocator; + } + + public void setTmpdir(String tmpdir) { + this.tmpdir = tmpdir; + } + + public void setTemporaryDirectory(File temporaryDirectory) { + this.temporaryDirectory = temporaryDirectory; + } + + public void setTemporaryFiles(Map> temporaryFiles) { + this.temporaryFiles = temporaryFiles; + } + + /** + * Generate a Maven pom for the specified {@link ProjectRequest}. + */ + public byte[] generateMavenPom(ProjectRequest request) { + try { + Map model = resolveModel(request); + if (!isMavenBuild(request)) { + throw new InvalidProjectRequestException("Could not generate Maven pom, " + + "invalid project type " + request.getType()); + } + byte[] content = doGenerateMavenPom(model); + publishProjectGeneratedEvent(request); + return content; + } + catch (InitializrException ex) { + publishProjectFailedEvent(request, ex); + throw ex; + } + } + + /** + * Generate a Gradle build file for the specified {@link ProjectRequest}. + */ + public byte[] generateGradleBuild(ProjectRequest request) { + try { + Map model = resolveModel(request); + if (!isGradleBuild(request)) { + throw new InvalidProjectRequestException( + "Could not generate Gradle build, " + "invalid project type " + + request.getType()); + } + byte[] content = doGenerateGradleBuild(model); + publishProjectGeneratedEvent(request); + return content; + } + catch (InitializrException ex) { + publishProjectFailedEvent(request, ex); + throw ex; + } + } + + /** + * Generate a project structure for the specified {@link ProjectRequest}. Returns a + * directory containing the project. + */ + public File generateProjectStructure(ProjectRequest request) { + try { + return doGenerateProjectStructure(request); + } + catch (InitializrException ex) { + publishProjectFailedEvent(request, ex); + throw ex; + } + } + + protected File doGenerateProjectStructure(ProjectRequest request) { + Map model = resolveModel(request); + + File rootDir; + try { + rootDir = File.createTempFile("tmp", "", getTemporaryDirectory()); + } + catch (IOException e) { + throw new IllegalStateException("Cannot create temp dir", e); + } + addTempFile(rootDir.getName(), rootDir); + rootDir.delete(); + rootDir.mkdirs(); + + File dir = initializerProjectDir(rootDir, request); + + if (isGradleBuild(request)) { + String gradle = new String(doGenerateGradleBuild(model)); + writeText(new File(dir, "build.gradle"), gradle); + writeGradleWrapper(dir, Version.safeParse(request.getBootVersion())); + } + else { + String pom = new String(doGenerateMavenPom(model)); + writeText(new File(dir, "pom.xml"), pom); + writeMavenWrapper(dir); + } + + generateGitIgnore(dir, request); + + String applicationName = request.getApplicationName(); + String language = request.getLanguage(); + + String codeLocation = language; + File src = new File(new File(dir, "src/main/" + codeLocation), + request.getPackageName().replace(".", "/")); + src.mkdirs(); + String extension = (language.equals("kotlin") ? "kt" : language); + write(new File(src, applicationName + "." + extension), + "Application." + extension, model); + + if ("war".equals(request.getPackaging())) { + String fileName = "ServletInitializer." + extension; + write(new File(src, fileName), fileName, model); + } + + File test = new File(new File(dir, "src/test/" + codeLocation), + request.getPackageName().replace(".", "/")); + test.mkdirs(); + setupTestModel(request, model); + write(new File(test, applicationName + "Tests." + extension), + "ApplicationTests." + extension, model); + + File resources = new File(dir, "src/main/resources"); + resources.mkdirs(); + writeText(new File(resources, "application.properties"), ""); + + if (request.hasWebFacet()) { + new File(dir, "src/main/resources/templates").mkdirs(); + new File(dir, "src/main/resources/static").mkdirs(); + } + publishProjectGeneratedEvent(request); + return rootDir; + + } + + /** + * Create a distribution file for the specified project structure directory and + * extension + */ + public File createDistributionFile(File dir, String extension) { + File download = new File(getTemporaryDirectory(), dir.getName() + extension); + addTempFile(dir.getName(), download); + return download; + } + + private File getTemporaryDirectory() { + if (temporaryDirectory == null) { + temporaryDirectory = new File(tmpdir, "initializr"); + temporaryDirectory.mkdirs(); + } + return temporaryDirectory; + } + + /** + * Clean all the temporary files that are related to this root directory. + * @see #createDistributionFile + */ + public void cleanTempFiles(File dir) { + List tempFiles = temporaryFiles.remove(dir.getName()); + if (!tempFiles.isEmpty()) { + tempFiles.forEach((File file) -> { + if (file.isDirectory()) { + FileSystemUtils.deleteRecursively(file); + } + else if (file.exists()) { + file.delete(); + } + }); + } + } + + private void publishProjectGeneratedEvent(ProjectRequest request) { + ProjectGeneratedEvent event = new ProjectGeneratedEvent(request); + eventPublisher.publishEvent(event); + } + + private void publishProjectFailedEvent(ProjectRequest request, Exception cause) { + ProjectFailedEvent event = new ProjectFailedEvent(request, cause); + eventPublisher.publishEvent(event); + } + + /** + * Generate a {@code .gitignore} file for the specified {@link ProjectRequest} + * @param dir the root directory of the project + * @param request the request to handle + */ + protected void generateGitIgnore(File dir, ProjectRequest request) { + Map model = new LinkedHashMap<>(); + model.put("build", isGradleBuild(request) ? "gradle" : "maven"); + write(new File(dir, ".gitignore"), "gitignore.tmpl", model); + } + + /** + * Resolve the specified {@link ProjectRequest} and return the model to use to + * generate the project + * @param request the request to handle + * @return a model for that request + */ + protected Map resolveModel(ProjectRequest originalRequest) { + Assert.notNull(originalRequest.getBootVersion(), "boot version must not be null"); + Map model = new LinkedHashMap<>(); + InitializrMetadata metadata = metadataProvider.get(); + + ProjectRequest request = requestResolver.resolve(originalRequest, metadata); + + // request resolved so we can log what has been requested + List dependencies = request.getResolvedDependencies(); + List dependencyIds = dependencies.stream().map(Dependency::getId) + .collect(Collectors.toList()); + log.info("Processing request{type=" + request.getType() + ", dependencies=" + + dependencyIds); + + if (isMavenBuild(request)) { + ParentPom parentPom = metadata.getConfiguration().getEnv().getMaven() + .resolveParentPom(request.getBootVersion()); + if (parentPom.isIncludeSpringBootBom() + && !request.getBoms().containsKey("spring-boot")) { + request.getBoms().put("spring-boot", metadata.createSpringBootBom( + request.getBootVersion(), "spring-boot.version")); + } + + model.put("mavenParentGroupId", parentPom.getGroupId()); + model.put("mavenParentArtifactId", parentPom.getArtifactId()); + model.put("mavenParentVersion", parentPom.getVersion()); + model.put("includeSpringBootBom", parentPom.isIncludeSpringBootBom()); + } + + model.put("resolvedBoms", + request.getBoms().values().stream() + .sorted((a, b) -> a.getOrder().compareTo(b.getOrder())) + .collect(Collectors.toList())); + + model.put("compileDependencies", + filterDependencies(dependencies, Dependency.SCOPE_COMPILE)); + model.put("runtimeDependencies", + filterDependencies(dependencies, Dependency.SCOPE_RUNTIME)); + model.put("compileOnlyDependencies", + filterDependencies(dependencies, Dependency.SCOPE_COMPILE_ONLY)); + model.put("providedDependencies", + filterDependencies(dependencies, Dependency.SCOPE_PROVIDED)); + model.put("testDependencies", + filterDependencies(dependencies, Dependency.SCOPE_TEST)); + + request.getBoms().forEach((k, v) -> { + if (v.getVersionProperty() != null) { + request.getBuildProperties().getVersions() + .computeIfAbsent(v.getVersionProperty(), key -> { + return () -> v.getVersion(); + }); + } + }); + + // Add various versions + model.put("dependencyManagementPluginVersion", metadata.getConfiguration() + .getEnv().getGradle().getDependencyManagementPluginVersion()); + model.put("kotlinVersion", + metadata.getConfiguration().getEnv().getKotlin().getVersion()); + + // @SpringBootApplication available as from 1.2.0.RC1 + model.put("useSpringBootApplication", VERSION_1_2_0_RC1 + .compareTo(Version.safeParse(request.getBootVersion())) <= 0); + + // Gradle plugin has changed as from 1.3.0 + model.put("bootOneThreeAvailable", VERSION_1_3_0_M1 + .compareTo(Version.safeParse(request.getBootVersion())) <= 0); + + // Gradle plugin has changed again as from 1.4.2 + model.put("springBootPluginName", + (VERSION_1_4_2_M1 + .compareTo(Version.safeParse(request.getBootVersion())) <= 0 + ? "org.springframework.boot" : "spring-boot")); + + // New testing stuff + model.put("newTestInfrastructure", isNewTestInfrastructureAvailable(request)); + + // New Servlet Initializer location + model.put("newServletInitializer", isNewServletInitializerAvailable(request)); + + // Append the project request to the model + BeanWrapperImpl bean = new BeanWrapperImpl(request); + for (PropertyDescriptor descriptor : bean.getPropertyDescriptors()) { + if (bean.isReadableProperty(descriptor.getName())) { + model.put(descriptor.getName(), + bean.getPropertyValue(descriptor.getName())); + } + } + + return model; + } + + protected void setupTestModel(ProjectRequest request, Map model) { + String imports = ""; + String testAnnotations = ""; + boolean newTestInfrastructure = isNewTestInfrastructureAvailable(request); + if (newTestInfrastructure) { + imports += String.format( + generateImport("org.springframework.boot.test.context.SpringBootTest", + request.getLanguage()) + "%n"); + imports += String.format( + generateImport("org.springframework.test.context.junit4.SpringRunner", + request.getLanguage()) + "%n"); + } + else { + imports += String.format(generateImport( + "org.springframework.boot.test.SpringApplicationConfiguration", + request.getLanguage()) + "%n"); + imports += String.format(generateImport( + "org.springframework.test.context.junit4.SpringJUnit4ClassRunner", + request.getLanguage()) + "%n"); + } + if (request.hasWebFacet() && !newTestInfrastructure) { + imports += String.format(generateImport( + "org.springframework.test.context.web.WebAppConfiguration", + request.getLanguage()) + "%n"); + testAnnotations = String.format("@WebAppConfiguration%n"); + } + model.put("testImports", imports); + model.put("testAnnotations", testAnnotations); + } + + protected String generateImport(String type, String language) { + String end = (language.equals("groovy") || language.equals("kotlin")) ? "" : ";"; + return "import " + type + end; + } + + private static boolean isGradleBuild(ProjectRequest request) { + return "gradle".equals(request.getBuild()); + } + + private static boolean isMavenBuild(ProjectRequest request) { + return "maven".equals(request.getBuild()); + } + + private static boolean isNewTestInfrastructureAvailable(ProjectRequest request) { + return VERSION_1_4_0_M2 + .compareTo(Version.safeParse(request.getBootVersion())) <= 0; + } + + private static boolean isNewServletInitializerAvailable(ProjectRequest request) { + return VERSION_1_4_0_M3 + .compareTo(Version.safeParse(request.getBootVersion())) <= 0; + } + + private static boolean isGradle3Available(Version bootVersion) { + return VERSION_2_0_0_M1.compareTo(bootVersion) <= 0; + } + + private byte[] doGenerateMavenPom(Map model) { + return groovyTemplate.process("starter-pom.xml", model).getBytes(); + } + + private byte[] doGenerateGradleBuild(Map model) { + return groovyTemplate.process("starter-build.gradle", model).getBytes(); + } + + private void writeGradleWrapper(File dir, Version bootVersion) { + String gradlePrefix = isGradle3Available(bootVersion) ? "gradle3" : "gradle"; + writeTextResource(dir, "gradlew.bat", gradlePrefix + "/gradlew.bat"); + writeTextResource(dir, "gradlew", gradlePrefix + "/gradlew"); + + File wrapperDir = new File(dir, "gradle/wrapper"); + wrapperDir.mkdirs(); + writeTextResource(wrapperDir, "gradle-wrapper.properties", + gradlePrefix + "/gradle/wrapper/gradle-wrapper.properties"); + writeBinaryResource(wrapperDir, "gradle-wrapper.jar", + gradlePrefix + "/gradle/wrapper/gradle-wrapper.jar"); + } + + private void writeMavenWrapper(File dir) { + writeTextResource(dir, "mvnw.cmd", "maven/mvnw.cmd"); + writeTextResource(dir, "mvnw", "maven/mvnw"); + + File wrapperDir = new File(dir, ".mvn/wrapper"); + wrapperDir.mkdirs(); + writeTextResource(wrapperDir, "maven-wrapper.properties", + "maven/wrapper/maven-wrapper.properties"); + writeBinaryResource(wrapperDir, "maven-wrapper.jar", + "maven/wrapper/maven-wrapper.jar"); + } + + private File writeBinaryResource(File dir, String name, String location) { + return doWriteProjectResource(dir, name, location, true); + } + + private File writeTextResource(File dir, String name, String location) { + return doWriteProjectResource(dir, name, location, false); + } + + private File doWriteProjectResource(File dir, String name, String location, + boolean binary) { + File target = new File(dir, name); + if (binary) { + writeBinary(target, projectResourceLocator + .getBinaryResource("classpath:project/" + location)); + } + else { + writeText(target, projectResourceLocator + .getTextResource("classpath:project/" + location)); + } + return target; + } + + private File initializerProjectDir(File rootDir, ProjectRequest request) { + if (request.getBaseDir() != null) { + File dir = new File(rootDir, request.getBaseDir()); + dir.mkdirs(); + return dir; + } + else { + return rootDir; + } + } + + public void write(File target, String templateName, Map model) { + String tmpl = templateName.endsWith(".groovy") ? templateName + ".tmpl" + : templateName; + String body = groovyTemplate.process(tmpl, model); + writeText(target, body); + } + + private void writeText(File target, String body) { + try (OutputStream stream = new FileOutputStream(target)) { + StreamUtils.copy(body, Charset.forName("UTF-8"), stream); + } + catch (Exception e) { + throw new IllegalStateException("Cannot write file " + target, e); + } + } + + private void writeBinary(File target, byte[] body) { + try (OutputStream stream = new FileOutputStream(target)) { + StreamUtils.copy(body, stream); + } + catch (Exception e) { + throw new IllegalStateException("Cannot write file " + target, e); + } + } + + private void addTempFile(String group, File file) { + temporaryFiles.computeIfAbsent(group, (key) -> new ArrayList()).add(file); + } + + private static List filterDependencies(List dependencies, + String scope) { + return dependencies.stream().filter(dep -> scope.equals(dep.getScope())) + .sorted((a, b) -> a.getId().compareTo(b.getId())) + .collect(Collectors.toList()); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequest.java b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequest.java new file mode 100644 index 00000000..3b94b924 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequest.java @@ -0,0 +1,311 @@ +/* + * 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 io.spring.initializr.generator; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.util.StringUtils; + +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.DefaultMetadataElement; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.Repository; +import io.spring.initializr.metadata.Type; +import io.spring.initializr.util.Version; + +/** + * A request to generate a project. + * + * @author Dave Syer + * @author Stephane Nicoll + */ +// @ToString(ignoreNulls = true, includePackage = false, includeNames = true) +public class ProjectRequest extends BasicProjectRequest { + + /** + * The id of the starter to use if no dependency is defined. + */ + public static final String DEFAULT_STARTER = "root_starter"; + + /** + * Additional parameters that can be used to further identify the request. + */ + private final Map parameters = new LinkedHashMap(); + + // Resolved dependencies based on the ids provided by either "style" or "dependencies" + private List resolvedDependencies; + + private final Map boms = new LinkedHashMap<>(); + + private final Map repositories = new LinkedHashMap<>(); + + /** + * Build properties. + */ + private final BuildProperties buildProperties = new BuildProperties(); + + private List facets = new ArrayList<>(); + private String build; + + public List getResolvedDependencies() { + return resolvedDependencies; + } + + public void setResolvedDependencies(List resolvedDependencies) { + this.resolvedDependencies = resolvedDependencies; + } + + public List getFacets() { + return facets; + } + + public void setFacets(List facets) { + this.facets = facets; + } + + public String getBuild() { + return build; + } + + public void setBuild(String build) { + this.build = build; + } + + public Map getParameters() { + return parameters; + } + + public Map getBoms() { + return boms; + } + + public Map getRepositories() { + return repositories; + } + + public BuildProperties getBuildProperties() { + return buildProperties; + } + + /** + * Initializes this instance with the defaults defined in the specified + * {@link InitializrMetadata}. + */ + public void initialize(InitializrMetadata metadata) { + BeanWrapperImpl bean = new BeanWrapperImpl(this); + metadata.defaults().forEach((key, value) -> { + if (bean.isWritableProperty(key)) { + bean.setPropertyValue(key, value); + } + }); + } + + /** + * Resolve this instance against the specified {@link InitializrMetadata} + */ + public void resolve(InitializrMetadata metadata) { + List depIds = !getStyle().isEmpty() ? getStyle() : getDependencies(); + String actualBootVersion = getBootVersion() != null ? getBootVersion() + : metadata.getBootVersions().getDefault().getId(); + Version requestedVersion = Version.parse(actualBootVersion); + this.resolvedDependencies = depIds.stream().map(it -> { + Dependency dependency = metadata.getDependencies().get(it); + if (dependency == null) { + throw new InvalidProjectRequestException( + "Unknown dependency '" + it + "' check project metadata"); + } + return dependency.resolve(requestedVersion); + }).collect(Collectors.toList()); + this.resolvedDependencies.forEach(it -> { + it.getFacets().forEach(facet -> { + if (!facets.contains(facet)) { + facets.add(facet); + } + }); + if (!it.match(requestedVersion)) { + throw new InvalidProjectRequestException( + "Dependency '" + it.getId() + "' is not compatible " + + "with Spring Boot " + requestedVersion); + } + if (it.getBom() != null) { + resolveBom(metadata, it.getBom(), requestedVersion); + } + if (it.getRepository() != null) { + String repositoryId = it.getRepository(); + this.repositories.computeIfAbsent(repositoryId, s -> metadata + .getConfiguration().getEnv().getRepositories().get(s)); + } + }); + if (getType() != null) { + Type type = metadata.getTypes().get(getType()); + if (type == null) { + throw new InvalidProjectRequestException( + "Unknown type '" + getType() + "' check project metadata"); + } + String buildTag = type.getTags().get("build"); + if (buildTag != null) { + this.build = buildTag; + } + } + if (getPackaging() != null) { + DefaultMetadataElement packaging = metadata.getPackagings() + .get(getPackaging()); + if (packaging == null) { + throw new InvalidProjectRequestException("Unknown packaging '" + + getPackaging() + "' check project metadata"); + } + } + if (getLanguage() != null) { + DefaultMetadataElement language = metadata.getLanguages().get(getLanguage()); + if (language == null) { + throw new InvalidProjectRequestException("Unknown language '" + + getLanguage() + "' check project metadata"); + } + } + + if (!StringUtils.hasText(getApplicationName())) { + setApplicationName( + metadata.getConfiguration().generateApplicationName(getName())); + } + setPackageName(metadata.getConfiguration().cleanPackageName(getPackageName(), + metadata.getPackageName().getContent())); + + initializeRepositories(metadata, requestedVersion); + + initializeProperties(metadata); + + afterResolution(metadata); + } + + /** + * Set the repositories that this instance should use based on the + * {@link InitializrMetadata} and the requested Spring Boot {@link Version}. + */ + protected void initializeRepositories(InitializrMetadata metadata, + Version requestedVersion) { + if (!"RELEASE".equals(requestedVersion.getQualifier().getQualifier())) { + repositories.put("spring-snapshots", metadata.getConfiguration().getEnv() + .getRepositories().get("spring-snapshots")); + repositories.put("spring-milestones", metadata.getConfiguration().getEnv() + .getRepositories().get("spring-milestones")); + } + boms.values().forEach(it -> { + it.getRepositories().forEach(key -> { + repositories.computeIfAbsent(key, s -> metadata.getConfiguration() + .getEnv().getRepositories().get(s)); + }); + }); + } + + protected void initializeProperties(InitializrMetadata metadata) { + if ("gradle".equals(build)) { + buildProperties.getGradle().put("springBootVersion", this::getBootVersion); + if ("kotlin".equals(getLanguage())) { + buildProperties.getGradle().put("kotlinVersion", () -> metadata + .getConfiguration().getEnv().getKotlin().getVersion()); + } + } + else { + buildProperties.getMaven().put("project.build.sourceEncoding", () -> "UTF-8"); + buildProperties.getMaven().put("project.reporting.outputEncoding", + () -> "UTF-8"); + buildProperties.getVersions().put("java.version", this::getJavaVersion); + if ("kotlin".equals(getLanguage())) { + buildProperties.getVersions().put("kotlin.version", () -> metadata + .getConfiguration().getEnv().getKotlin().getVersion()); + } + } + } + + private void resolveBom(InitializrMetadata metadata, String bomId, + Version requestedVersion) { + boms.computeIfAbsent(bomId, key -> { + BillOfMaterials bom = metadata.getConfiguration().getEnv().getBoms().get(key) + .resolve(requestedVersion); + bom.getAdditionalBoms() + .forEach(id -> resolveBom(metadata, id, requestedVersion)); + return bom; + }); + } + + /** + * Update this request once it has been resolved with the specified + * {@link InitializrMetadata}. + */ + protected void afterResolution(InitializrMetadata metadata) { + if ("war".equals(getPackaging())) { + if (!hasWebFacet()) { + // Need to be able to bootstrap the web app + resolvedDependencies.add(metadata.getDependencies().get("web")); + facets.add("web"); + } + // Add the tomcat starter in provided scope + Dependency tomcat = new Dependency().asSpringBootStarter("tomcat"); + tomcat.setScope(Dependency.SCOPE_PROVIDED); + resolvedDependencies.add(tomcat); + } + if (!resolvedDependencies.stream().anyMatch(it -> it.isStarter())) { + // There"s no starter so we add the default one + addDefaultDependency(); + } + } + + /** + * Add a default dependency if the project does not define any dependency + */ + protected void addDefaultDependency() { + Dependency root = new Dependency(); + root.setId(DEFAULT_STARTER); + root.asSpringBootStarter(""); + resolvedDependencies.add(root); + } + + /** + * Specify if this request has the web facet enabled. + */ + public boolean hasWebFacet() { + return hasFacet("web"); + } + + /** + * Specify if this request has the specified facet enabled + */ + public boolean hasFacet(String facet) { + return facets.contains(facet); + } + + @Override + public String toString() { + return "ProjectRequest [" + + (parameters != null ? "parameters=" + parameters + ", " : "") + + (resolvedDependencies != null + ? "resolvedDependencies=" + resolvedDependencies + ", " : "") + + (boms != null ? "boms=" + boms + ", " : "") + + (repositories != null ? "repositories=" + repositories + ", " : "") + + (buildProperties != null ? "buildProperties=" + buildProperties + ", " + : "") + + (facets != null ? "facets=" + facets + ", " : "") + + (build != null ? "build=" + build : "") + "]"; + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestEvent.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestEvent.java similarity index 72% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestEvent.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestEvent.java index 9096b2d3..d546e6bb 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestEvent.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; /** * Event published when a {@link ProjectRequest} has been processed. @@ -23,21 +23,29 @@ package io.spring.initializr.generator * @see ProjectGeneratedEvent * @see ProjectFailedEvent */ -abstract class ProjectRequestEvent { +public abstract class ProjectRequestEvent { /** * The {@link ProjectRequest} used to generate the project. */ - final ProjectRequest projectRequest + private final ProjectRequest projectRequest; /** * The timestamp at which the request was processed. */ - final long timestamp + private final long timestamp; protected ProjectRequestEvent(ProjectRequest projectRequest) { - this.projectRequest = projectRequest - this.timestamp = System.currentTimeMillis() + this.projectRequest = projectRequest; + this.timestamp = System.currentTimeMillis(); + } + + public ProjectRequest getProjectRequest() { + return projectRequest; + } + + public long getTimestamp() { + return timestamp; } } diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessor.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessor.java similarity index 93% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessor.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessor.java index fa67a008..588facdc 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectRequestPostProcessor.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessor.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; -import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.InitializrMetadata; /** * Project generation hook that allows for custom modification of {@link ProjectRequest} @@ -25,7 +25,7 @@ import io.spring.initializr.metadata.InitializrMetadata * * @author Stephane Nicoll */ -interface ProjectRequestPostProcessor { +public interface ProjectRequestPostProcessor { /** * Apply this post processor to the given {@code ProjectRequest} before it diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.java b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.java new file mode 100644 index 00000000..8ec589f9 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestPostProcessorAdapter.java @@ -0,0 +1,21 @@ +package io.spring.initializr.generator; + +import io.spring.initializr.metadata.InitializrMetadata; + +/** + * An implementation of {@link ProjectRequestPostProcessor} with empty methods allowing + * sub-classes to override only the methods they're interested in. + * + * @author Stephane Nicoll + */ +public class ProjectRequestPostProcessorAdapter implements ProjectRequestPostProcessor { + + @Override + public void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { + } + + @Override + public void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestResolver.java b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestResolver.java new file mode 100644 index 00000000..9e71cb51 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectRequestResolver.java @@ -0,0 +1,43 @@ +package io.spring.initializr.generator; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.util.Assert; + +import io.spring.initializr.metadata.InitializrMetadata; + +/** + * Resolve {@link ProjectRequest} instances, honouring callback hook points. + * + * @author Stephane Nicoll + */ +public class ProjectRequestResolver { + + private final List postProcessors; + + public ProjectRequestResolver(List postProcessors) { + this.postProcessors = new ArrayList<>(postProcessors); + } + + public ProjectRequest resolve(ProjectRequest request, InitializrMetadata metadata) { + Assert.notNull(request, "Request must not be null"); + applyPostProcessBeforeResolution(request, metadata); + request.resolve(metadata); + applyPostProcessAfterResolution(request, metadata); + return request; + } + + private void applyPostProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { + for (ProjectRequestPostProcessor processor : postProcessors) { + processor.postProcessBeforeResolution(request, metadata); + } + } + + private void applyPostProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { + for (ProjectRequestPostProcessor processor : postProcessors) { + processor.postProcessAfterResolution(request, metadata); + } + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectResourceLocator.groovy b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectResourceLocator.java similarity index 51% rename from initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectResourceLocator.groovy rename to initializr-generator/src/main/java/io/spring/initializr/generator/ProjectResourceLocator.java index 716ff029..6af04a77 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/generator/ProjectResourceLocator.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectResourceLocator.java @@ -14,22 +14,24 @@ * limitations under the License. */ -package io.spring.initializr.generator +package io.spring.initializr.generator; -import java.nio.charset.Charset +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; -import org.springframework.cache.annotation.Cacheable -import org.springframework.util.ResourceUtils -import org.springframework.util.StreamUtils +import org.springframework.cache.annotation.Cacheable; +import org.springframework.util.ResourceUtils; +import org.springframework.util.StreamUtils; /** * Locate project resources. * * @author Stephane Nicoll */ -class ProjectResourceLocator { +public class ProjectResourceLocator { - private static final Charset UTF_8 = Charset.forName("UTF-8") + private static final Charset UTF_8 = Charset.forName("UTF-8"); /** * Return the binary content of the resource at the specified location. @@ -37,12 +39,12 @@ class ProjectResourceLocator { * @return the content of the resource */ @Cacheable("project-resources") - byte[] getBinaryResource(String location) { - InputStream stream = getInputStream(location) - try { - return StreamUtils.copyToByteArray(stream) - } finally { - stream.close() + public byte[] getBinaryResource(String location) { + try (InputStream stream = getInputStream(location)) { + return StreamUtils.copyToByteArray(stream); + } + catch (Exception e) { + throw new IllegalStateException("Cannot get resource", e); } } @@ -52,19 +54,20 @@ class ProjectResourceLocator { * @return the content of the resource */ @Cacheable("project-resources") - String getTextResource(String location) { - InputStream stream = getInputStream(location) - try { - return StreamUtils.copyToString(stream, UTF_8) - } finally { - stream.close() + public String getTextResource(String location) { + try (InputStream stream = getInputStream(location)) { + return StreamUtils.copyToString(stream, UTF_8); } + catch (Exception e) { + throw new IllegalStateException("Cannot get resource", e); + } + } - private InputStream getInputStream(String location) { - def url = ResourceUtils.getURL(location) - def stream = url.openStream() - stream + private InputStream getInputStream(String location) throws Exception { + URL url = ResourceUtils.getURL(location); + InputStream stream = url.openStream(); + return stream; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/BillOfMaterials.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/BillOfMaterials.java new file mode 100644 index 00000000..afa81769 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/BillOfMaterials.java @@ -0,0 +1,315 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import io.spring.initializr.util.InvalidVersionException; +import io.spring.initializr.util.Version; +import io.spring.initializr.util.VersionParser; +import io.spring.initializr.util.VersionRange; + +/** + * Define a Bill Of Materials to be represented in the generated project if a dependency + * refers to it. + * + * @author Stephane Nicoll + */ +@JsonInclude(JsonInclude.Include.NON_DEFAULT) +public class BillOfMaterials { + + private String groupId; + private String artifactId; + + /** + * The version of the BOM. Can be {@code null} if it is provided via a mapping. + */ + private String version; + + /** + * The property to use to externalize the version of the BOM. When this is set, a + * version property is automatically added rather than setting the version in the bom + * declaration itself. + */ + private String versionProperty; + + /** + * The relative order of this BOM where lower values have higher priority. The default + * value is {@code Integer.MAX_VALUE}, indicating lowest priority. The Spring Boot + * dependencies bom has an order of 100. + */ + private Integer order = Integer.MAX_VALUE; + + /** + * The BOM(s) that should be automatically included if this BOM is required. Can be + * {@code null} if it is provided via a mapping. + */ + private List additionalBoms = new ArrayList<>(); + + /** + * The repositories that are required if this BOM is required. Can be {@code null} if + * it is provided via a mapping. + */ + private List repositories = new ArrayList<>(); + + private final List mappings = new ArrayList<>(); + + public BillOfMaterials() { + } + + private BillOfMaterials(String groupId, String artifactId) { + this(groupId, artifactId, null); + } + + private BillOfMaterials(String groupId, String artifactId, String version) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getVersionProperty() { + return versionProperty; + } + + public void setVersionProperty(String versionProperty) { + this.versionProperty = versionProperty; + } + + public Integer getOrder() { + return order; + } + + public void setOrder(Integer order) { + this.order = order; + } + + public List getAdditionalBoms() { + return additionalBoms; + } + + public void setAdditionalBoms(List additionalBoms) { + this.additionalBoms = additionalBoms; + } + + public List getRepositories() { + return repositories; + } + + public void setRepositories(List repositories) { + this.repositories = repositories; + } + + public List getMappings() { + return mappings; + } + + /** + * Determine the version placeholder to use for this instance. If a version property + * is defined, this returns the reference for the property. Otherwise this returns the + * plain {@link #version} + */ + public String determineVersionToken() { + return (versionProperty != null ? "${" + versionProperty + "}" : version); + } + + public void validate() { + if (version == null && mappings.isEmpty()) { + throw new InvalidInitializrMetadataException( + "No version available for " + this); + } + updateVersionRange(VersionParser.DEFAULT); + } + + public void updateVersionRange(VersionParser versionParser) { + mappings.forEach(it -> { + try { + it.range = versionParser.parseRange(it.versionRange); + } + catch (InvalidVersionException ex) { + throw new InvalidInitializrMetadataException( + "Invalid version range " + it.versionRange + " for " + this, ex); + } + }); + } + + /** + * Resolve this instance according to the specified Spring Boot {@link Version}. + * Return a {@link BillOfMaterials} instance that holds the version, repositories and + * additional BOMs to use, if any. + */ + public BillOfMaterials resolve(Version bootVersion) { + if (mappings.isEmpty()) { + return this; + } + + for (Mapping mapping : mappings) { + if (mapping.range.match(bootVersion)) { + BillOfMaterials resolvedBom = new BillOfMaterials(groupId, artifactId, + mapping.version); + resolvedBom.setVersionProperty(versionProperty); + resolvedBom.setOrder(order); + resolvedBom.repositories.addAll(!mapping.repositories.isEmpty() + ? mapping.repositories : repositories); + resolvedBom.additionalBoms.addAll(!mapping.additionalBoms.isEmpty() + ? mapping.additionalBoms : additionalBoms); + return resolvedBom; + } + } + throw new IllegalStateException( + "No suitable mapping was found for " + this + " and version " + bootVersion); + } + + @Override + public String toString() { + return "BillOfMaterials [" + (groupId != null ? "groupId=" + groupId + ", " : "") + + (artifactId != null ? "artifactId=" + artifactId + ", " : "") + + (version != null ? "version=" + version + ", " : "") + + (versionProperty != null ? "versionProperty=" + versionProperty + ", " + : "") + + (order != null ? "order=" + order + ", " : "") + + (additionalBoms != null ? "additionalBoms=" + additionalBoms + ", " + : "") + + (repositories != null ? "repositories=" + repositories : "") + "]"; + } + + public static class Mapping { + + private String versionRange; + + private String version; + + private List repositories = new ArrayList<>(); + + private List additionalBoms = new ArrayList<>(); + + @JsonIgnore + private VersionRange range; + + public Mapping() { + } + + private Mapping(String range, String version, String... repositories) { + this.versionRange = range; + this.version = version; + this.repositories.addAll(Arrays.asList(repositories)); + } + + public String determineVersionRangeRequirement() { + return range.toString(); + } + + public static Mapping create(String range, String version) { + return new Mapping(range, version); + } + + public static Mapping create(String range, String version, + String... repositories) { + return new Mapping(range, version, repositories); + } + + public String getVersionRange() { + return versionRange; + } + + public String getVersion() { + return version; + } + + public List getRepositories() { + return repositories; + } + + public List getAdditionalBoms() { + return additionalBoms; + } + + public VersionRange getRange() { + return range; + } + + public void setVersionRange(String versionRange) { + this.versionRange = versionRange; + } + + public void setVersion(String version) { + this.version = version; + } + + public void setRepositories(List repositories) { + this.repositories = repositories; + } + + public void setAdditionalBoms(List additionalBoms) { + this.additionalBoms = additionalBoms; + } + + public void setRange(VersionRange range) { + this.range = range; + } + + @Override + public String toString() { + return "Mapping [" + + (versionRange != null ? "versionRange=" + versionRange + ", " : "") + + (version != null ? "version=" + version + ", " : "") + + (repositories != null ? "repositories=" + repositories + ", " : "") + + (additionalBoms != null ? "additionalBoms=" + additionalBoms + ", " + : "") + + (range != null ? "range=" + range : "") + "]"; + } + + } + + public static BillOfMaterials create(String groupId, String artifactId) { + return new BillOfMaterials(groupId, artifactId); + } + + public static BillOfMaterials create(String groupId, String artifactId, + String version) { + return new BillOfMaterials(groupId, artifactId, version); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/DefaultMetadataElement.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/DefaultMetadataElement.java new file mode 100644 index 00000000..d74d3b17 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/DefaultMetadataElement.java @@ -0,0 +1,57 @@ +/* + * 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 io.spring.initializr.metadata; + +/** + * A {@link MetadataElement} that specifies if its + * the default for a given capability. + * + * @author Stephane Nicoll + */ +public class DefaultMetadataElement extends MetadataElement { + + private boolean defaultValue; + + public DefaultMetadataElement() { + } + + public DefaultMetadataElement(String id, String name, boolean defaultValue) { + super(id, name); + this.defaultValue = defaultValue; + } + + public DefaultMetadataElement(String id, boolean defaultValue) { + this(id, null, defaultValue); + } + + public void setDefault(boolean defaultValue) { + this.defaultValue = defaultValue; + } + + public boolean isDefault() { + return this.defaultValue; + } + + public static DefaultMetadataElement create(String id, boolean defaultValue) { + return new DefaultMetadataElement(id, defaultValue); + } + + public static DefaultMetadataElement create(String id, String name, boolean defaultValue) { + return new DefaultMetadataElement(id, name, defaultValue); + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/InitializrException.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/Defaultable.java similarity index 74% rename from initializr-generator/src/main/groovy/io/spring/initializr/InitializrException.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/Defaultable.java index 0c049bd6..5e0a8079 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/InitializrException.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Defaultable.java @@ -14,15 +14,8 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.metadata; -import groovy.transform.InheritConstructors - -/** - * Base Initializr exception. - * - * @author Stephane Nicoll - */ -@InheritConstructors -class InitializrException extends RuntimeException { +public interface Defaultable { + T getDefault(); } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/DependenciesCapability.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependenciesCapability.java new file mode 100644 index 00000000..665a1105 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependenciesCapability.java @@ -0,0 +1,123 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import io.spring.initializr.util.VersionParser; + +/** + * A {@link ServiceCapability} listing the available dependencies defined as a + * {@link ServiceCapabilityType#HIERARCHICAL_MULTI_SELECT} capability. + * + * @author Stephane Nicoll + */ +public class DependenciesCapability extends ServiceCapability> { + + final List content = new ArrayList<>(); + + @JsonIgnore + private final Map indexedDependencies = new LinkedHashMap<>(); + + public DependenciesCapability() { + super("dependencies", ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT, + "Project dependencies", "dependency identifiers (comma-separated)"); + } + + public List getContent() { + return content; + } + + /** + * Return the {@link Dependency} with the specified id or {@code null} if no such + * dependency exists. + */ + public Dependency get(String id) { + return indexedDependencies.get(id); + } + + /** + * Return all dependencies as a flat collection + */ + public Collection getAll() { + return Collections.unmodifiableCollection(indexedDependencies.values()); + } + + public void validate() { + index(); + } + + public void updateVersionRange(VersionParser versionParser) { + indexedDependencies.values().forEach(it -> { + it.updateVersionRanges(versionParser); + }); + } + + @Override + public void merge(List otherContent) { + otherContent.forEach(group -> { + if (!content.stream().anyMatch(it -> group.getName() != null + && group.getName().equals(it.getName()))) { + content.add(group); + } + }); + index(); + } + + private void index() { + indexedDependencies.clear(); + content.forEach(group -> { + group.content.forEach(dependency -> { + // Apply defaults + if (dependency.getVersionRange() == null + && group.getVersionRange() != null) { + dependency.setVersionRange(group.getVersionRange()); + } + if (dependency.getBom() == null && group.getBom() != null) { + dependency.setBom(group.getBom()); + } + if (dependency.getRepository() == null && group.getRepository() != null) { + dependency.setRepository(group.getRepository()); + } + + dependency.resolve(); + indexDependency(dependency.getId(), dependency); + for (String alias : dependency.getAliases()) { + indexDependency(alias, dependency); + } + }); + }); + } + + private void indexDependency(String id, Dependency dependency) { + Dependency existing = indexedDependencies.get(id); + if (existing != null) { + throw new IllegalArgumentException( + "Could not register " + dependency + " another dependency " + + "has also the '" + id + "' id " + existing); + } + indexedDependencies.put(id, dependency); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/Dependency.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/Dependency.java new file mode 100644 index 00000000..30d841c0 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Dependency.java @@ -0,0 +1,513 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import io.spring.initializr.util.InvalidVersionException; +import io.spring.initializr.util.Version; +import io.spring.initializr.util.VersionParser; +import io.spring.initializr.util.VersionRange; + +/** + * Meta-data for a dependency. Each dependency has a primary identifier and an arbitrary + * number of {@code aliases}. + * + * @author Stephane Nicoll + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +// @AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) +public class Dependency extends MetadataElement implements Describable { + + public static final String SCOPE_COMPILE = "compile"; + public static final String SCOPE_COMPILE_ONLY = "compileOnly"; + public static final String SCOPE_RUNTIME = "runtime"; + public static final String SCOPE_PROVIDED = "provided"; + public static final String SCOPE_TEST = "test"; + public static final List SCOPE_ALL = Arrays.asList(SCOPE_COMPILE, + SCOPE_RUNTIME, SCOPE_COMPILE_ONLY, SCOPE_PROVIDED, SCOPE_TEST); + + private List aliases = new ArrayList<>(); + + private List facets = new ArrayList<>(); + + private String groupId; + + private String artifactId; + + /** + * The default version, can be {@code null} to indicate that the version is managed by + * the project and does not need to be specified. + */ + private String version; + + /** + * The type, can be {@code null} to indicate that the default type should be used + * (i.e. {@code jar}). + */ + private String type; + + /** + * Dependency mapping if an attribute of the dependency differs according to the + * Spring Boot version. If no mapping matches, default attributes are used. + */ + private List mappings = new ArrayList<>(); + + private String scope = SCOPE_COMPILE; + + private String description; + + private String versionRange; + + @JsonIgnore + private String versionRequirement; + + @JsonIgnore + private VersionRange range; + + private String bom; + + private String repository; + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + private int weight; + + /** + * Specify if the dependency represents a "starter", i.e. the sole presence of that + * dependency is enough to bootstrap the context. + */ + private boolean starter = true; + + private List keywords = new ArrayList<>(); + + private List links = new ArrayList<>(); + + public Dependency() { + } + + public Dependency(Dependency dependency) { + super(dependency); + this.aliases.addAll(dependency.aliases); + this.facets.addAll(dependency.facets); + this.groupId = dependency.groupId; + this.artifactId = dependency.artifactId; + this.version = dependency.version; + this.type = dependency.type; + this.mappings.addAll(dependency.mappings); + this.scope = dependency.scope; + this.description = dependency.description; + this.versionRange = dependency.versionRange; + this.versionRequirement = dependency.versionRequirement; + this.range = dependency.range; + this.bom = dependency.bom; + this.repository = dependency.repository; + this.weight = dependency.weight; + this.starter = dependency.starter; + this.keywords.addAll(dependency.keywords); + this.links.addAll(dependency.links); + } + + public void setScope(String scope) { + if (!SCOPE_ALL.contains(scope)) { + throw new InvalidInitializrMetadataException( + "Invalid scope " + scope + " must be one of " + SCOPE_ALL); + } + this.scope = scope; + } + + public void setVersionRange(String versionRange) { + this.versionRange = StringUtils.hasText(versionRange) ? versionRange.trim() + : null; + } + + /** + * Specify if the dependency has its coordinates set, i.e. {@code groupId} and + * {@code artifactId}. + */ + public boolean hasCoordinates() { + return groupId != null && artifactId != null; + } + + /** + * Define this dependency as a standard spring boot starter with the specified name + *

+ * If no name is specified, the root "spring-boot-starter" is assumed. + */ + public Dependency asSpringBootStarter(String name) { + groupId = "org.springframework.boot"; + artifactId = StringUtils.hasText(name) ? "spring-boot-starter-" + name + : "spring-boot-starter"; + if (StringUtils.hasText(name)) { + setId(name); + } + return this; + } + + /** + * Validate the dependency and complete its state based on the available information. + */ + public void resolve() { + if (getId() == null) { + if (!hasCoordinates()) { + throw new InvalidInitializrMetadataException( + "Invalid dependency, should have at least an id or a groupId/artifactId pair."); + } + generateId(); + } + else if (!hasCoordinates()) { + // Let"s build the coordinates from the id + StringTokenizer st = new StringTokenizer(getId(), ":"); + if (st.countTokens() == 1) { // assume spring-boot-starter + asSpringBootStarter(getId()); + } + else if (st.countTokens() == 2 || st.countTokens() == 3) { + groupId = st.nextToken(); + artifactId = st.nextToken(); + if (st.hasMoreTokens()) { + version = st.nextToken(); + } + } + else { + throw new InvalidInitializrMetadataException( + "Invalid dependency, id should have the form groupId:artifactId[:version] but got " + + getId()); + } + } + links.forEach(Link::resolve); + updateVersionRanges(VersionParser.DEFAULT); + } + + public void updateVersionRanges(VersionParser versionParser) { + if (versionRange != null) { + try { + range = versionParser.parseRange(versionRange); + versionRequirement = range.toString(); + } + catch (InvalidVersionException ex) { + throw new InvalidInitializrMetadataException("Invalid version range '" + + versionRange + " for " + "dependency with id '" + getId() + "'", + ex); + } + } + mappings.forEach(it -> { + try { + it.range = versionParser.parseRange(it.versionRange); + } + catch (InvalidVersionException ex) { + throw new InvalidInitializrMetadataException( + "Invalid version range " + it.versionRange + " for " + this, ex); + } + }); + } + + /** + * Resolve this instance according to the specified Spring Boot {@link Version}. + * Return a {@link Dependency} instance that has its state resolved against the + * specified version. + */ + public Dependency resolve(Version bootVersion) { + for (Mapping mapping : mappings) { + if (mapping.range.match(bootVersion)) { + Dependency dependency = new Dependency(this); + dependency.groupId = mapping.groupId != null ? mapping.groupId + : this.groupId; + dependency.artifactId = mapping.artifactId != null ? mapping.artifactId + : this.artifactId; + dependency.version = mapping.version != null ? mapping.version + : this.version; + dependency.versionRequirement = mapping.range.toString(); + dependency.mappings = null; + return dependency; + } + } + return this; + } + + /** + * Specify if this dependency is available for the specified Spring Boot version. + */ + public boolean match(Version version) { + if (range!=null) { + return range.match(version); + } + return true; + } + + /** + * Generate an id using the groupId and artifactId + */ + public String generateId() { + if (groupId == null || artifactId == null) { + throw new IllegalArgumentException("Could not generate id for " + this + + ": at least groupId and artifactId must be set."); + } + StringBuilder sb = new StringBuilder(); + sb.append(groupId).append(":").append(artifactId); + setId(sb.toString()); + return getId(); + } + + public List getAliases() { + return aliases; + } + + public void setAliases(List aliases) { + this.aliases = aliases; + } + + public List getFacets() { + return facets; + } + + public void setFacets(List facets) { + this.facets = facets; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getMappings() { + return mappings; + } + + public void setMappings(List mappings) { + this.mappings = mappings; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersionRequirement() { + return versionRequirement; + } + + public void setVersionRequirement(String versionRequirement) { + this.versionRequirement = versionRequirement; + } + + public VersionRange getRange() { + return range; + } + + public void setRange(VersionRange range) { + this.range = range; + } + + public String getBom() { + return bom; + } + + public void setBom(String bom) { + this.bom = bom; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public boolean isStarter() { + return starter; + } + + public void setStarter(boolean starter) { + this.starter = starter; + } + + public List getKeywords() { + return keywords; + } + + public void setKeywords(List keywords) { + this.keywords = keywords; + } + + public List getLinks() { + return links; + } + + public void setLinks(List links) { + this.links = links; + } + + public String getScope() { + return scope; + } + + public String getVersionRange() { + return versionRange; + } + + /** + * Map several attribute of the dependency for a given version range. + */ + public static class Mapping { + + /** + * The version range of this mapping. + */ + private String versionRange; + + /** + * The version to use for this mapping or {@code null} to use the default. + */ + private String groupId; + + /** + * The groupId to use for this mapping or {@code null} to use the default. + */ + private String artifactId; + + /** + * The artifactId to use for this mapping or {@code null} to use the default. + */ + private String version; + + private VersionRange range; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public VersionRange getRange() { + return range; + } + + public String getVersionRange() { + return versionRange; + } + + public void setVersionRange(String versionRange) { + this.versionRange = versionRange; + } + + public static Mapping create(String range, String groupId, String artifactId, + String version) { + Mapping mapping = new Mapping(); + mapping.versionRange = range; + mapping.groupId = groupId; + mapping.artifactId = artifactId; + mapping.version = version; + return mapping; + } + } + + public static Dependency create(String groupId, String artifactId, String version, + String scope) { + Dependency dependency = withId(null, groupId, artifactId, version); + dependency.setScope(scope); + return dependency; + } + + public static Dependency withId(String id, String groupId, String artifactId, + String version) { + Dependency dependency = new Dependency(); + dependency.setId(id); + dependency.groupId = groupId; + dependency.artifactId = artifactId; + dependency.version = version; + return dependency; + } + + public static Dependency withId(String id, String groupId, String artifactId) { + return withId(id, groupId, artifactId, null); + } + + public static Dependency withId(String id, String scope) { + Dependency dependency = withId(id, null, null); + dependency.setScope(scope); + return dependency; + } + + public static Dependency withId(String id) { + return withId(id, SCOPE_COMPILE); + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyGroup.java similarity index 52% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyGroup.java index b623b718..4747d252 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyGroup.java @@ -14,43 +14,88 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; -import com.fasterxml.jackson.annotation.JsonIgnore +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnore; /** * A group of {@link Dependency} instances identified by a name. * * @author Stephane Nicoll */ -class DependencyGroup { +public class DependencyGroup { /** * Name of this group. */ - String name + private String name; /** * The default version range to apply to all dependencies of this group unless * specified otherwise. */ @JsonIgnore - String versionRange + private String versionRange; /** * The default bom to associate to all dependencies of this group unless * specified otherwise. */ @JsonIgnore - String bom + private String bom; /** * The default repository to associate to all dependencies of this group unless * specified otherwise. */ @JsonIgnore - String repository + private String repository; - final List content = [] + final List content = new ArrayList<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersionRange() { + return versionRange; + } + + public void setVersionRange(String versionRange) { + this.versionRange = versionRange; + } + + public String getBom() { + return bom; + } + + public void setBom(String bom) { + this.bom = bom; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } + + public List getContent() { + return content; + } + + public static DependencyGroup create(String name) { + DependencyGroup group = new DependencyGroup(); + group.setName(name); + return group; + } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadata.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadata.java new file mode 100644 index 00000000..dd31417a --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadata.java @@ -0,0 +1,66 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.Map; + +import io.spring.initializr.util.Version; + +/** + * Dependency metadata for a given spring boot {@link Version}. + * + * @author Stephane Nicoll + */ +public class DependencyMetadata { + + final Version bootVersion; + + final Map dependencies; + + final Map repositories; + + final Map boms; + + public DependencyMetadata() { + this(null, null, null, null); + } + + public DependencyMetadata(Version bootVersion, Map dependencies, + Map repositories, Map boms) { + this.bootVersion = bootVersion; + this.dependencies = dependencies; + this.repositories = repositories; + this.boms = boms; + } + + public Version getBootVersion() { + return bootVersion; + } + + public Map getDependencies() { + return dependencies; + } + + public Map getRepositories() { + return repositories; + } + + public Map getBoms() { + return boms; + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadataProvider.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadataProvider.java similarity index 86% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadataProvider.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadataProvider.java index 50b57ae2..3c7a7468 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DependencyMetadataProvider.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/DependencyMetadataProvider.java @@ -14,20 +14,20 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; -import io.spring.initializr.util.Version +import io.spring.initializr.util.Version; /** * Provide the {@link DependencyMetadata} for a given spring boot version. * * @author Stephane Nicoll */ -interface DependencyMetadataProvider { +public interface DependencyMetadataProvider { /** * Return the dependency metadata to use for the specified {@code bootVersion}. */ - DependencyMetadata get(InitializrMetadata metadata, Version bootVersion) + DependencyMetadata get(InitializrMetadata metadata, Version bootVersion); } \ No newline at end of file diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Describable.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/Describable.java similarity index 95% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/Describable.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/Describable.java index ea0a89e2..98d822c4 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/Describable.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Describable.java @@ -16,6 +16,6 @@ package io.spring.initializr.metadata; -interface Describable { +public interface Describable { String getDescription(); } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrConfiguration.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrConfiguration.java new file mode 100644 index 00000000..829639c2 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrConfiguration.java @@ -0,0 +1,478 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.util.StringUtils; + +/** + * Various configuration options used by the service. + * + * @author Stephane Nicoll + */ +public class InitializrConfiguration { + + /** + * Environment options. + */ + private final Env env = new Env(); + + public Env getEnv() { + return env; + } + + public void validate() { + env.validate(); + } + + public void merge(InitializrConfiguration other) { + env.merge(other.env); + } + + /** + * Generate a suitable application name based on the specified name. If no suitable + * application name can be generated from the specified {@code name}, the + * {@link Env#fallbackApplicationName} is used instead. + *

+ * No suitable application name can be generated if the name is {@code null} or if it + * contains an invalid character for a class identifier. + * @see Env#fallbackApplicationName + * @see Env#invalidApplicationNames + */ + public String generateApplicationName(String name) { + if (!StringUtils.hasText(name)) { + return env.fallbackApplicationName; + } + String text = splitCamelCase(name.trim()); + // TODO: fix this + String result = unsplitWords(text); + if (!result.endsWith("Application")) { + result = result + "Application"; + } + String candidate = StringUtils.capitalize(result); + if (hasInvalidChar(candidate) + || env.invalidApplicationNames.contains(candidate)) { + return env.fallbackApplicationName; + } + else { + return candidate; + } + } + + /** + * Clean the specified package name if necessary. If the package name cannot be + * transformed to a valid package name, the {@code defaultPackageName} is used + * instead. + *

+ * The package name cannot be cleaned if the specified {@code packageName} is + * {@code null} or if it contains an invalid character for a class identifier. + * @see Env#invalidPackageNames + */ + public String cleanPackageName(String packageName, String defaultPackageName) { + if (!StringUtils.hasText(packageName)) { + return defaultPackageName; + } + String candidate = String.join(".", packageName.trim().split("\\W+")); + if (hasInvalidChar(candidate.replace(".", "")) + || env.invalidPackageNames.contains(candidate)) { + return defaultPackageName; + } + else { + return candidate; + } + } + + private static String unsplitWords(String text) { + return String + .join("", Arrays + .asList(text + .split("(_|-| |:)+")) + .stream().map(it -> StringUtils.capitalize(it)) + .collect(Collectors.toList()).toArray(new String[0])); + } + + private static String splitCamelCase(String text) { + return String + .join("", Arrays + .asList(text + .split("(? StringUtils.capitalize(it.toLowerCase())) + .collect(Collectors.toList()).toArray(new String[0])); + } + + private static boolean hasInvalidChar(String text) { + if (!Character.isJavaIdentifierStart(text.charAt(0))) { + return true; + } + if (text.length() > 1) { + for (int i = 1; i < text.length(); i++) { + if (!Character.isJavaIdentifierPart(text.charAt(i))) { + return true; + } + } + } + return false; + } + + /** + * Defines additional environment settings. + */ + public static class Env { + + /** + * The url of the repository servicing distribution bundle. + */ + private String artifactRepository = "https://repo.spring.io/release/"; + + /** + * The metadata url of the Spring Boot project. + */ + private String springBootMetadataUrl = "https://spring.io/project_metadata/spring-boot"; + + /** + * Tracking code for Google Analytics. Only enabled if a value is explicitly + * provided. + */ + private String googleAnalyticsTrackingCode; + + /** + * The application name to use if none could be generated. + */ + private String fallbackApplicationName = "Application"; + + /** + * The list of invalid application names. If such name is chosen or generated, the + * "fallbackApplicationName" should be used instead. + */ + private List invalidApplicationNames = new ArrayList<>( + Arrays.asList("SpringApplication", "SpringBootApplication")); + + /** + * The list of invalid package names. If such name is chosen or generated, the the + * default package name should be used instead. + */ + private List invalidPackageNames = new ArrayList<>( + Arrays.asList("org.springframework")); + + /** + * Force SSL support. When enabled, any access using http generate https links. + */ + private boolean forceSsl = true; + + /** + * The "BillOfMaterials" that are referenced in this instance, identified by an + * arbitrary identifier that can be used in the dependencies definition. + */ + private final Map boms = new LinkedHashMap<>(); + + /** + * The "Repository" instances that are referenced in this instance, identified by + * an arbitrary identifier that can be used in the dependencies definition. + */ + private final Map repositories = new LinkedHashMap<>(); + + /** + * Gradle-specific settings. + */ + private final Gradle gradle = new Gradle(); + + /** + * Kotlin-specific settings. + */ + private final Kotlin kotlin = new Kotlin(); + + /** + * Maven-specific settings. + */ + private final Maven maven = new Maven(); + + public String getSpringBootMetadataUrl() { + return springBootMetadataUrl; + } + + public void setSpringBootMetadataUrl(String springBootMetadataUrl) { + this.springBootMetadataUrl = springBootMetadataUrl; + } + + public String getGoogleAnalyticsTrackingCode() { + return googleAnalyticsTrackingCode; + } + + public void setGoogleAnalyticsTrackingCode(String googleAnalyticsTrackingCode) { + this.googleAnalyticsTrackingCode = googleAnalyticsTrackingCode; + } + + public String getFallbackApplicationName() { + return fallbackApplicationName; + } + + public void setFallbackApplicationName(String fallbackApplicationName) { + this.fallbackApplicationName = fallbackApplicationName; + } + + public List getInvalidApplicationNames() { + return invalidApplicationNames; + } + + public void setInvalidApplicationNames(List invalidApplicationNames) { + this.invalidApplicationNames = invalidApplicationNames; + } + + public List getInvalidPackageNames() { + return invalidPackageNames; + } + + public void setInvalidPackageNames(List invalidPackageNames) { + this.invalidPackageNames = invalidPackageNames; + } + + public boolean isForceSsl() { + return forceSsl; + } + + public void setForceSsl(boolean forceSsl) { + this.forceSsl = forceSsl; + } + + public String getArtifactRepository() { + return artifactRepository; + } + + public Map getBoms() { + return boms; + } + + public Map getRepositories() { + return repositories; + } + + public Gradle getGradle() { + return gradle; + } + + public Kotlin getKotlin() { + return kotlin; + } + + public Maven getMaven() { + return maven; + } + + public Env() { + try { + repositories.put("spring-snapshots", new Repository("Spring Snapshots", + new URL("https://repo.spring.io/snapshot"), true)); + repositories.put("spring-milestones", new Repository("Spring Milestones", + new URL("https://repo.spring.io/milestone"), false)); + } + catch (MalformedURLException e) { + throw new IllegalStateException("Cannot parse URL", e); + } + } + + public void setArtifactRepository(String artifactRepository) { + if (!artifactRepository.endsWith("/")) { + artifactRepository = artifactRepository + "/"; + } + this.artifactRepository = artifactRepository; + } + + public void validate() { + maven.parent.validate(); + boms.forEach((k, v) -> { + v.validate(); + }); + } + + public void merge(Env other) { + artifactRepository = other.artifactRepository; + springBootMetadataUrl = other.springBootMetadataUrl; + googleAnalyticsTrackingCode = other.googleAnalyticsTrackingCode; + fallbackApplicationName = other.fallbackApplicationName; + invalidApplicationNames = other.invalidApplicationNames; + forceSsl = other.forceSsl; + gradle.merge(other.gradle); + kotlin.version = other.kotlin.version; + maven.merge(other.maven); + other.boms.forEach((id, bom) -> { + if (boms.get(id) == null) { + boms.put(id, bom); + } + }); + other.repositories.forEach((id, repo) -> { + if (repositories.get(id) == null) { + repositories.put(id, repo); + } + }); + } + + public static class Gradle { + + /** + * Version of the "dependency-management-plugin" to use. + */ + private String dependencyManagementPluginVersion; + + private void merge(Gradle other) { + dependencyManagementPluginVersion = other.dependencyManagementPluginVersion; + } + + public String getDependencyManagementPluginVersion() { + return dependencyManagementPluginVersion; + } + + public void setDependencyManagementPluginVersion( + String dependencyManagementPluginVersion) { + this.dependencyManagementPluginVersion = dependencyManagementPluginVersion; + } + + } + + public static class Kotlin { + + /** + * Kotlin version to use. + */ + private String version; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + } + + public static class Maven { + + /** + * Custom parent pom to use for generated projects. + */ + private final ParentPom parent = new ParentPom(); + + public ParentPom getParent() { + return parent; + } + + private void merge(Maven other) { + parent.groupId = other.parent.groupId; + parent.artifactId = other.parent.artifactId; + parent.version = other.parent.version; + parent.includeSpringBootBom = other.parent.includeSpringBootBom; + } + + /** + * Resolve the parent pom to use. If no custom parent pom is set, the standard + * spring boot parent pom with the specified {@code bootVersion} is used. + */ + public ParentPom resolveParentPom(String bootVersion) { + return StringUtils.hasText(parent.groupId) ? parent + : new ParentPom("org.springframework.boot", + "spring-boot-starter-parent", bootVersion); + } + + public static class ParentPom { + + /** + * Parent pom groupId. + */ + private String groupId; + + /** + * Parent pom artifactId. + */ + private String artifactId; + + /** + * Parent pom version. + */ + private String version; + + /** + * Add the "spring-boot-dependencies" BOM to the project. + */ + private boolean includeSpringBootBom; + + public ParentPom(String groupId, String artifactId, String version) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + public ParentPom() { + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public boolean isIncludeSpringBootBom() { + return includeSpringBootBom; + } + + public void setIncludeSpringBootBom(boolean includeSpringBootBom) { + this.includeSpringBootBom = includeSpringBootBom; + } + + public void validate() { + if (!((!StringUtils.hasText(groupId) + && !StringUtils.hasText(artifactId) + && !StringUtils.hasText(version)) + || (StringUtils.hasText(groupId) + && StringUtils.hasText(artifactId) + && StringUtils.hasText(version)))) { + throw new InvalidInitializrMetadataException("Custom maven pom " + + "requires groupId, artifactId and version"); + } + } + + } + + } + + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadata.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadata.java new file mode 100644 index 00000000..e9e93a91 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadata.java @@ -0,0 +1,300 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import io.spring.initializr.util.Version; +import io.spring.initializr.util.VersionParser; + +/** + * Meta-data used to generate a project. + * + * @author Stephane Nicoll + * @see ServiceCapability + */ +public class InitializrMetadata { + + private final InitializrConfiguration configuration; + + private final DependenciesCapability dependencies = new DependenciesCapability(); + + private final TypeCapability types = new TypeCapability(); + + private final SingleSelectCapability bootVersions = new SingleSelectCapability("bootVersion", + "Spring Boot Version", "spring boot version"); + + private final SingleSelectCapability packagings = new SingleSelectCapability("packaging", + "Packaging", "project packaging"); + + private final SingleSelectCapability javaVersions = new SingleSelectCapability("javaVersion", + "Java Version", "language level"); + + private final SingleSelectCapability languages = new SingleSelectCapability("language", + "Language", "programming language"); + + private final TextCapability name = new TextCapability("name", "Name", + "project name (infer application name)"); + + private final TextCapability description = new TextCapability("description", "Description", + "project description"); + + private final TextCapability groupId = new TextCapability("groupId", "Group", + "project coordinates"); + + private final TextCapability artifactId = new ArtifactIdCapability(name); + + private final TextCapability version = new TextCapability("version", "Version", + "project version"); + + private final TextCapability packageName = new PackageCapability(groupId); + + public InitializrMetadata() { + this(new InitializrConfiguration()); + } + + protected InitializrMetadata(InitializrConfiguration configuration) { + this.configuration = configuration; + } + + public InitializrConfiguration getConfiguration() { + return configuration; + } + + public DependenciesCapability getDependencies() { + return dependencies; + } + + public TypeCapability getTypes() { + return types; + } + + public SingleSelectCapability getBootVersions() { + return bootVersions; + } + + public SingleSelectCapability getPackagings() { + return packagings; + } + + public SingleSelectCapability getJavaVersions() { + return javaVersions; + } + + public SingleSelectCapability getLanguages() { + return languages; + } + + public TextCapability getName() { + return name; + } + + public TextCapability getDescription() { + return description; + } + + public TextCapability getGroupId() { + return groupId; + } + + public TextCapability getArtifactId() { + return artifactId; + } + + public TextCapability getVersion() { + return version; + } + + public TextCapability getPackageName() { + return packageName; + } + + /** + * Merge this instance with the specified argument + * @param other + */ + public void merge(InitializrMetadata other) { + this.configuration.merge(other.configuration); + this.dependencies.merge(other.dependencies); + this.types.merge(other.types); + this.bootVersions.merge(other.bootVersions); + this.packagings.merge(other.packagings); + this.javaVersions.merge(other.javaVersions); + this.languages.merge(other.languages); + this.name.merge(other.name); + this.description.merge(other.description); + this.groupId.merge(other.groupId); + this.artifactId.merge(other.artifactId); + this.version.merge(other.version); + this.packageName.merge(other.packageName); + } + + /** + * Validate the metadata. + */ + public void validate() { + this.configuration.validate(); + dependencies.validate(); + + Map repositories = configuration.getEnv().getRepositories(); + Map boms = configuration.getEnv().getBoms(); + for (Dependency dependency : dependencies.getAll()) { + if (dependency.getBom() != null && !boms.containsKey(dependency.getBom())) { + throw new InvalidInitializrMetadataException( + "Dependency " + dependency + "defines an invalid BOM id " + + dependency.getBom() + ", available boms " + boms); + } + + if (dependency.getRepository() != null + && !repositories.containsKey(dependency.getRepository())) { + throw new InvalidInitializrMetadataException("Dependency " + dependency + + "defines an invalid repository id " + dependency.getRepository() + + ", available repositores " + repositories); + } + } + for (BillOfMaterials bom : boms.values()) { + for (String r : bom.getRepositories()) { + if (!repositories.containsKey(r)) { + throw new InvalidInitializrMetadataException( + bom + "defines an invalid repository id " + r + + ", available repositories " + repositories); + } + } + for (String b : bom.getAdditionalBoms()) { + if (!boms.containsKey(b)) { + throw new InvalidInitializrMetadataException( + bom + " defines an invalid " + "additional bom id " + b + + ", available boms " + boms); + } + } + for (BillOfMaterials.Mapping m : bom.getMappings()) { + for (String r : m.getRepositories()) { + if (!repositories.containsKey(r)) { + throw new InvalidInitializrMetadataException( + m + " of " + bom + "defines an invalid repository id " + r + + ", available repositores " + repositories); + } + + } + for (String b : m.getAdditionalBoms()) { + if (!boms.containsKey(b)) { + throw new InvalidInitializrMetadataException(m + " of " + bom + + " defines " + "an invalid additional bom id " + b + + ", available boms " + boms); + } + } + } + } + } + + /** + * Update the available Spring Boot versions with the specified capabilities. + * @param versionsMetadata the Spring Boot boot versions metadata to use + */ + public void updateSpringBootVersions(List versionsMetadata) { + this.bootVersions.getContent().clear(); + this.bootVersions.getContent().addAll(versionsMetadata); + List bootVersions = this.bootVersions.getContent().stream() + .map(it -> Version.parse(it.getId())).collect(Collectors.toList()); + VersionParser parser = new VersionParser(bootVersions); + dependencies.updateVersionRange(parser); + configuration.getEnv().getBoms().values() + .forEach(it -> it.updateVersionRange(parser)); + } + + /** + * Create an URL suitable to download Spring Boot cli for the specified version and + * extension. + */ + public String createCliDistributionURl(String extension) { + String bootVersion = defaultId(bootVersions); + return configuration.getEnv().getArtifactRepository() + + "org/springframework/boot/spring-boot-cli/" + bootVersion + + "/spring-boot-cli-" + bootVersion + "-bin." + extension; + } + + /** + * Create a {@link BillOfMaterials} for the spring boot BOM. + */ + public BillOfMaterials createSpringBootBom(String bootVersion, String versionProperty) { + BillOfMaterials bom = BillOfMaterials.create("org.springframework.boot", + "spring-boot-dependencies", bootVersion); + bom.setVersionProperty(versionProperty); + bom.setOrder(100); + return bom; + } + + /** + * Return the defaults for the capabilities defined on this instance. + */ + public Map defaults() { + Map defaults = new LinkedHashMap<>(); + defaults.put("type", defaultId(types)); + defaults.put("bootVersion", defaultId(bootVersions)); + defaults.put("packaging", defaultId(packagings)); + defaults.put("javaVersion", defaultId(javaVersions)); + defaults.put("language", defaultId(languages)); + defaults.put("groupId", groupId.getContent()); + defaults.put("artifactId", artifactId.getContent()); + defaults.put("version", version.getContent()); + defaults.put("name", name.getContent()); + defaults.put("description", description.getContent()); + defaults.put("packageName", packageName.getContent()); + return defaults; + } + + private static String defaultId(Defaultable element) { + DefaultMetadataElement defaultValue = element.getDefault(); + return defaultValue != null ? defaultValue.getId() : null; + } + + private static class ArtifactIdCapability extends TextCapability { + private final TextCapability nameCapability; + + ArtifactIdCapability(TextCapability nameCapability) { + super("artifactId", "Artifact", "project coordinates (infer archive name)"); + this.nameCapability = nameCapability; + } + + @Override + public String getContent() { + String value = super.getContent(); + return value == null ? nameCapability.getContent() : value; + } + } + + private static class PackageCapability extends TextCapability { + private final TextCapability nameCapability; + + PackageCapability(TextCapability nameCapability) { + super("packageName", "Package Name", "root package"); + this.nameCapability = nameCapability; + } + + @Override + public String getContent() { + String value = super.getContent(); + return value != null ? value + : (nameCapability.getContent() != null + ? nameCapability.getContent().replace("-", ".") : null); + } + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataBuilder.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataBuilder.java new file mode 100644 index 00000000..ae90eca9 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataBuilder.java @@ -0,0 +1,205 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Builder for {@link InitializrMetadata}. Allows to read metadata from any arbitrary + * resource, including remote URLs. + * + * @author Stephane Nicoll + * @see InitializrMetadataCustomizer + */ +public class InitializrMetadataBuilder { + + private final List customizers = new ArrayList<>(); + private final InitializrConfiguration configuration; + + private InitializrMetadataBuilder(InitializrConfiguration configuration) { + this.configuration = configuration; + } + + /** + * Create a builder instance from the specified {@link InitializrProperties}. + * Initialize the configuration to use. + * @see #withInitializrProperties(InitializrProperties) + */ + public static InitializrMetadataBuilder fromInitializrProperties( + InitializrProperties configuration) { + return new InitializrMetadataBuilder(configuration) + .withInitializrProperties(configuration); + } + + /** + * Create an empty builder instance with a default {@link InitializrConfiguration} + */ + public static InitializrMetadataBuilder create() { + return new InitializrMetadataBuilder(new InitializrConfiguration()); + } + + /** + * Add a {@link InitializrProperties} to be merged with other content. Merges the + * settings only and not the configuration. + * @see #withInitializrProperties(InitializrProperties, boolean) + */ + public InitializrMetadataBuilder withInitializrProperties( + InitializrProperties properties) { + return withInitializrProperties(properties, false); + } + + /** + * Add a {@link InitializrProperties} to be merged with other content. + * @param properties the settings to merge onto this instance + * @param mergeConfiguration specify if service configuration should be merged as well + */ + public InitializrMetadataBuilder withInitializrProperties( + InitializrProperties properties, boolean mergeConfiguration) { + if (mergeConfiguration) { + this.configuration.merge(properties); + } + return withCustomizer(new InitializerPropertiesCustomizer(properties)); + } + + /** + * Add a {@link InitializrMetadata} to be merged with other content. + * @param resource a resource to a json document describing the metadata to include + */ + public InitializrMetadataBuilder withInitializrMetadata(Resource resource) { + return withCustomizer(new ResourceInitializrMetadataCustomizer(resource)); + } + + /** + * Add a {@link InitializrMetadataCustomizer}. customizers are invoked in their order + * of addition. + * @see InitializrMetadataCustomizer + */ + public InitializrMetadataBuilder withCustomizer( + InitializrMetadataCustomizer customizer) { + customizers.add(customizer); + return this; + } + + /** + * Build a {@link InitializrMetadata} based on the state of this builder. + */ + public InitializrMetadata build() { + InitializrConfiguration config = this.configuration != null ? this.configuration + : new InitializrConfiguration(); + InitializrMetadata metadata = createInstance(config); + for (InitializrMetadataCustomizer customizer : customizers) { + customizer.customize(metadata); + } + applyDefaults(metadata); + metadata.validate(); + return metadata; + } + + /** + * Creates an empty instance based on the specified {@link InitializrConfiguration} + */ + protected InitializrMetadata createInstance(InitializrConfiguration configuration) { + return new InitializrMetadata(configuration); + } + + /** + * Apply defaults to capabilities that have no value. + */ + protected void applyDefaults(InitializrMetadata metadata) { + if (!StringUtils.hasText(metadata.getName().getContent())) { + metadata.getName().setContent("demo"); + } + if (!StringUtils.hasText(metadata.getDescription().getContent())) { + metadata.getDescription().setContent("Demo project for Spring Boot"); + } + if (!StringUtils.hasText(metadata.getGroupId().getContent())) { + metadata.getGroupId().setContent("com.example"); + } + if (!StringUtils.hasText(metadata.getVersion().getContent())) { + metadata.getVersion().setContent("0.0.1-SNAPSHOT"); + } + } + + private static class InitializerPropertiesCustomizer + implements InitializrMetadataCustomizer { + + private final InitializrProperties properties; + + InitializerPropertiesCustomizer(InitializrProperties properties) { + this.properties = properties; + } + + @Override + public void customize(InitializrMetadata metadata) { + metadata.getDependencies().merge(properties.getDependencies()); + metadata.getTypes().merge(properties.getTypes()); + metadata.getBootVersions().merge(properties.getBootVersions()); + metadata.getPackagings().merge(properties.getPackagings()); + metadata.getJavaVersions().merge(properties.getJavaVersions()); + metadata.getLanguages().merge(properties.getLanguages()); + properties.getGroupId().apply(metadata.getGroupId()); + properties.getArtifactId().apply(metadata.getArtifactId()); + properties.getVersion().apply(metadata.getVersion()); + properties.getName().apply(metadata.getName()); + properties.getDescription().apply(metadata.getDescription()); + properties.getPackageName().apply(metadata.getPackageName()); + } + } + + private static class ResourceInitializrMetadataCustomizer + implements InitializrMetadataCustomizer { + + private static final Logger log = LoggerFactory.getLogger( + InitializrMetadataBuilder.ResourceInitializrMetadataCustomizer.class); + + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private final Resource resource; + + ResourceInitializrMetadataCustomizer(Resource resource) { + this.resource = resource; + } + + @Override + public void customize(InitializrMetadata metadata) { + log.info("Loading initializr metadata from " + resource); + try { + String content = StreamUtils.copyToString(resource.getInputStream(), + UTF_8); + ObjectMapper objectMapper = new ObjectMapper(); + InitializrMetadata anotherMetadata = objectMapper.readValue(content, + InitializrMetadata.class); + metadata.merge(anotherMetadata); + } + catch (Exception e) { + throw new IllegalStateException("Cannot merge", e); + } + } + + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataCustomizer.java similarity index 86% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataCustomizer.java index 36292e75..4edb9956 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataCustomizer.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; /** * Strategy interface used to customize the {@link InitializrMetadata}. * * @author Dave Syer */ -interface InitializrMetadataCustomizer { +public interface InitializrMetadataCustomizer { /** * Customize the {@link InitializrMetadata}, updating or moving around * capabilities before they are validated. */ - void customize(InitializrMetadata metadata) + void customize(InitializrMetadata metadata); } diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataProvider.java similarity index 88% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataProvider.java index 3db8ceee..32a87dda 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrMetadataProvider.java @@ -14,20 +14,20 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; /** * Provide the {@link InitializrMetadata} to use. * * @author Stephane Nicoll */ -interface InitializrMetadataProvider { +public interface InitializrMetadataProvider { /** * Return the metadata to use. Rather than keeping a handle to * a particular instance, implementations may decide to refresh * or recompute the metadata if necessary. */ - InitializrMetadata get() + InitializrMetadata get(); } \ No newline at end of file diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrProperties.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrProperties.java new file mode 100644 index 00000000..d058e639 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InitializrProperties.java @@ -0,0 +1,213 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Configuration of the initializr service. + * + * @author Stephane Nicoll + */ +@ConfigurationProperties(prefix = "initializr") +public class InitializrProperties extends InitializrConfiguration { + + /** + * Dependencies, organized in groups (i.e. themes). + */ + @JsonIgnore + private final List dependencies = new ArrayList<>(); + + /** + * Available project types. + */ + @JsonIgnore + private final List types = new ArrayList<>(); + + /** + * Available packaging types. + */ + @JsonIgnore + private final List packagings = new ArrayList<>(); + + /** + * Available java versions. + */ + @JsonIgnore + private final List javaVersions = new ArrayList<>(); + + /** + * Available programming languages. + */ + @JsonIgnore + private final List languages = new ArrayList<>(); + + /** + * Available Spring Boot versions. + */ + @JsonIgnore + private final List bootVersions = new ArrayList<>(); + + /** + * GroupId metadata. + */ + @JsonIgnore + private final SimpleElement groupId = new SimpleElement("com.example"); + + /** + * ArtifactId metadata. + */ + @JsonIgnore + private final SimpleElement artifactId = new SimpleElement(null); + + /** + * Version metadata. + */ + @JsonIgnore + private final SimpleElement version = new SimpleElement("0.0.1-SNAPSHOT"); + + /** + * Name metadata. + */ + @JsonIgnore + private final SimpleElement name = new SimpleElement("demo"); + + /** + * Description metadata. + */ + @JsonIgnore + private final SimpleElement description = new SimpleElement( + "Demo project for Spring Boot"); + + /** + * Package name metadata. + */ + @JsonIgnore + private final SimpleElement packageName = new SimpleElement(null); + + public List getDependencies() { + return dependencies; + } + + public List getTypes() { + return types; + } + + public List getPackagings() { + return packagings; + } + + public List getJavaVersions() { + return javaVersions; + } + + public List getLanguages() { + return languages; + } + + public List getBootVersions() { + return bootVersions; + } + + public SimpleElement getGroupId() { + return groupId; + } + + public SimpleElement getArtifactId() { + return artifactId; + } + + public SimpleElement getVersion() { + return version; + } + + public SimpleElement getName() { + return name; + } + + public SimpleElement getDescription() { + return description; + } + + public SimpleElement getPackageName() { + return packageName; + } + + public static class SimpleElement { + /** + * Element title. + */ + private String title; + + /** + * Element description. + */ + private String description; + + /** + * Element default value. + */ + private String value; + + public SimpleElement(String value) { + this.value = value; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public void apply(TextCapability capability) { + if (StringUtils.hasText(title)) { + capability.setTitle(title); + } + if (StringUtils.hasText(description)) { + capability.setDescription(description); + } + if (StringUtils.hasText(value)) { + capability.setContent(value); + } + } + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/InvalidInitializrMetadataException.java similarity index 60% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/InvalidInitializrMetadataException.java index 8819070f..2572f053 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/InvalidInitializrMetadataException.java @@ -14,23 +14,23 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; + +import io.spring.initializr.InitializrException; /** - * A {@link MetadataElement} that specifies if its - * the default for a given capability. + * Thrown when the configuration defines invalid metadata. * * @author Stephane Nicoll */ -class DefaultMetadataElement extends MetadataElement { +@SuppressWarnings("serial") +public class InvalidInitializrMetadataException extends InitializrException { - private boolean defaultValue - - void setDefault(boolean defaultValue) { - this.defaultValue = defaultValue + public InvalidInitializrMetadataException(String message, Throwable cause) { + super(message, cause); } - boolean isDefault() { - this.defaultValue + public InvalidInitializrMetadataException(String message) { + super(message); } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/Link.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/Link.java new file mode 100644 index 00000000..c8749c22 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Link.java @@ -0,0 +1,178 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Metadata for a link. Each link has a "relation" that potentially attaches a strong + * semantic to the nature of the link. The URI of the link itself can be templated by + * including variables in the form `{variableName}`. + *

+ * An actual {@code URI} can be generated using {@code expand}, providing a mapping for + * those variables. + * + * @author Dave Syer + * @author Stephane Nicoll + */ +public class Link { + + private static final Pattern VARIABLE_REGEX = Pattern.compile("\\{(\\w+)\\}"); + + /** + * The relation of the link. + */ + private String rel; + + /** + * The URI the link is pointing to. + */ + private String href; + + /** + * Specify if the URI is templated. + */ + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + private boolean templated; + + @JsonIgnore + private final Set templateVariables = new LinkedHashSet<>(); + + /** + * A description of the link. + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + private String description; + + public Link() { + } + + private Link(String rel, String href) { + this(rel, href, (String)null); + } + + private Link(String rel, String href, String description) { + this.rel = rel; + this.href = href; + this.description = description; + } + + private Link(String rel, String href, boolean templated) { + this(rel, href); + this.templated = templated; + } + + public String getRel() { + return rel; + } + + public void setRel(String rel) { + this.rel = rel; + } + + public boolean isTemplated() { + return templated; + } + + public void setTemplated(boolean templated) { + this.templated = templated; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getHref() { + return href; + } + + public Set getTemplateVariables() { + return Collections.unmodifiableSet(templateVariables); + } + + public void setHref(String href) { + this.href = href; + } + + public void resolve() { + if (rel==null) { + throw new InvalidInitializrMetadataException( + "Invalid link " + this + ": rel attribute is mandatory"); + } + if (href==null) { + throw new InvalidInitializrMetadataException( + "Invalid link " + this + ": href attribute is mandatory"); + } + Matcher matcher = VARIABLE_REGEX.matcher(href); + while (matcher.find()) { + String variable = matcher.group(1); + this.templateVariables.add(variable); + } + this.templated = !this.templateVariables.isEmpty(); + } + + /** + * Expand the link using the specified parameters. + * @param parameters the parameters value + * @return an URI where all variables have been expanded + */ + public URI expand(Map parameters) { + AtomicReference result = new AtomicReference(href); + templateVariables.forEach( var -> { + Object value = parameters.get(var); + if (value==null) { + throw new IllegalArgumentException( + "Could not expand " + href + ", missing value for '" + var + "'"); + } + result.set(result.get().replace("{" + var+"}", value.toString())); + }); + try { + return new URI(result.get()); + } + catch (URISyntaxException e) { + throw new IllegalStateException("Invalid URL", e); + } + } + + public static Link create(String rel, String href) { + return new Link(rel, href); + } + + public static Link create(String rel, String href, String description) { + return new Link(rel, href, description); + } + + public static Link create(String rel, String href, boolean templated) { + return new Link(rel, href, templated); + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/MetadataElement.java similarity index 58% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/MetadataElement.java index 4dabd3fd..234d8a3a 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/MetadataElement.java @@ -14,30 +14,51 @@ * limitations under the License. */ -package io.spring.initializr.metadata - -import groovy.transform.AutoClone -import groovy.transform.AutoCloneStyle +package io.spring.initializr.metadata; /** * A basic metadata element * * @author Stephane Nicoll */ -@AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) -class MetadataElement { +// @AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) +public class MetadataElement { /** * A visual representation of this element. */ - String name + private String name; /** * The unique id of this element for a given capability. */ - String id + private String id; + + public MetadataElement() { + } - String getName() { - (name ?: id) + public MetadataElement(MetadataElement other) { + this(other.id, other.name); + } + + public MetadataElement(String id, String name) { + this.id = id; + this.name = name; + } + + public String getName() { + return name!=null ? name: id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; } } \ No newline at end of file diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/Repository.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/Repository.java new file mode 100644 index 00000000..506ee337 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Repository.java @@ -0,0 +1,109 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.net.URL; + +/** + * Define a repository to be represented in the generated project if a dependency refers + * to it. + * + * @author Stephane Nicoll + */ +public class Repository { + + private String name; + private URL url; + private boolean snapshotsEnabled; + + public Repository() { + } + + public Repository(String name, URL url, boolean snapshotsEnabled) { + this.name = name; + this.url = url; + this.snapshotsEnabled = snapshotsEnabled; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public URL getUrl() { + return url; + } + + public void setUrl(URL url) { + this.url = url; + } + + public boolean isSnapshotsEnabled() { + return snapshotsEnabled; + } + + public void setSnapshotsEnabled(boolean snapshotsEnabled) { + this.snapshotsEnabled = snapshotsEnabled; + } + + @Override + public String toString() { + return "Repository [" + (name != null ? "name=" + name + ", " : "") + + (url != null ? "url=" + url + ", " : "") + "snapshotsEnabled=" + + snapshotsEnabled + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + (snapshotsEnabled ? 1231 : 1237); + result = prime * result + ((url == null) ? 0 : url.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Repository other = (Repository) obj; + if (name == null) { + if (other.name != null) + return false; + } + else if (!name.equals(other.name)) + return false; + if (snapshotsEnabled != other.snapshotsEnabled) + return false; + if (url == null) { + if (other.url != null) + return false; + } + else if (!url.equals(other.url)) + return false; + return true; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapability.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapability.java new file mode 100644 index 00000000..03341958 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapability.java @@ -0,0 +1,123 @@ +/* + * 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 io.spring.initializr.metadata; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Defines a capability of the initializr service. Each capability is defined by a id and + * a {@link ServiceCapabilityType type}. + * + * @author Stephane Nicoll + */ +@JsonIgnoreProperties({ "default", "all" }) +@JsonInclude(JsonInclude.Include.NON_NULL) +// @AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) +public abstract class ServiceCapability implements Cloneable { + + private final String id; + + private final ServiceCapabilityType type; + + /** + * A title of the capability, used as a header text or label. + */ + private String title; + + /** + * A description of the capability, used in help usage or UI tooltips. + */ + private String description; + + public ServiceCapability(ServiceCapability other) { + this.id = other.id; + this.type = other.type; + merge(other); + } + + protected ServiceCapability(String id, ServiceCapabilityType type) { + this.id = id; + this.type = type; + } + + protected ServiceCapability(String id, ServiceCapabilityType type, String title, + String description) { + this.id = id; + this.type = type; + this.title = title; + this.description = description; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getId() { + return id; + } + + public ServiceCapabilityType getType() { + return type; + } + + /** + * Return the "content" of this capability. The structure of the content vastly + * depends on the {@link ServiceCapability type} of the capability. + */ + public abstract T getContent(); + + /** + * Merge the content of this instance with the specified content. + * @see #merge(io.spring.initializr.metadata.ServiceCapability) + */ + public abstract void merge(T otherContent); + + /** + * Merge this capability with the specified argument. The service capabilities should + * match (i.e have the same {@code id} and {@code type}). Sub-classes may merge + * additional content. + */ + public void merge(ServiceCapability other) { + Assert.notNull(other, "Other must not be null"); + Assert.state(this.id.equals(other.id)); + Assert.state(this.type.equals(other.type)); + if (StringUtils.hasText(other.title)) { + this.title = other.title; + } + if (StringUtils.hasText(other.description)) { + this.description = other.description; + } + merge(other.getContent()); + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapabilityType.java similarity index 75% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapabilityType.java index edd5a53b..d876409e 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/ServiceCapabilityType.java @@ -14,40 +14,44 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; /** * Defines the supported service capability type. * * @author Stephane Nicoll */ -enum ServiceCapabilityType { +public enum ServiceCapabilityType { /** * A special type that defines the action to use. */ - ACTION('action'), + ACTION("action"), /** * A simple text value with no option. */ - TEXT('text'), + TEXT("text"), /** * A simple value to be chosen amongst the specified options. */ - SINGLE_SELECT('single-select'), + SINGLE_SELECT("single-select"), /** * A hierarchical set of values (values in values) with the ability to * select multiple values. */ - HIERARCHICAL_MULTI_SELECT('hierarchical-multi-select') + HIERARCHICAL_MULTI_SELECT("hierarchical-multi-select"); - final String name + final String name; - ServiceCapabilityType(String name) { - this.name = name + private ServiceCapabilityType(String name) { + this.name = name; + } + + public String getName() { + return name; } } diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.java similarity index 69% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.java index ff8ac995..69686953 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/SimpleInitializrMetadataProvider.java @@ -14,23 +14,23 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; /** * A simple {@link InitializrMetadataProvider} implementation. * * @author Stephane Nicoll */ -class SimpleInitializrMetadataProvider implements InitializrMetadataProvider { +public class SimpleInitializrMetadataProvider implements InitializrMetadataProvider { - private final InitializrMetadata metadata + private final InitializrMetadata metadata; - SimpleInitializrMetadataProvider(InitializrMetadata metadata) { - this.metadata = metadata + public SimpleInitializrMetadataProvider(InitializrMetadata metadata) { + this.metadata = metadata; } @Override - InitializrMetadata get() { - this.metadata + public InitializrMetadata get() { + return this.metadata; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/SingleSelectCapability.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/SingleSelectCapability.java new file mode 100644 index 00000000..cdeb7c3a --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/SingleSelectCapability.java @@ -0,0 +1,74 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A {@link ServiceCapabilityType#SINGLE_SELECT single select} capability. + * + * @author Stephane Nicoll + */ +public class SingleSelectCapability + extends ServiceCapability> + implements Defaultable { + + private final List content = new CopyOnWriteArrayList(); + + @JsonCreator + SingleSelectCapability(@JsonProperty("id") String id) { + this(id, null, null); + } + + public SingleSelectCapability(String id, String title, String description) { + super(id, ServiceCapabilityType.SINGLE_SELECT, title, description); + } + + public List getContent() { + return content; + } + + /** + * Return the default element of this capability. + */ + public DefaultMetadataElement getDefault() { + return content.stream().filter(DefaultMetadataElement::isDefault).findFirst() + .orElse(null); + } + + /** + * Return the element with the specified id or {@code null} if no such element exists. + */ + public DefaultMetadataElement get(String id) { + return content.stream().filter(it -> id.equals(it.getId())).findFirst() + .orElse(null); + } + + @Override + public void merge(List otherContent) { + otherContent.forEach(it -> { + if (get(it.getId()) == null) { + content.add(it); + } + }); + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/TextCapability.java similarity index 61% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/TextCapability.java index 81510caa..130c9c30 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/TextCapability.java @@ -14,33 +14,41 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; /** * A {@link ServiceCapabilityType#TEXT text} capability. * * @author Stephane Nicoll */ -class TextCapability extends ServiceCapability { +public class TextCapability extends ServiceCapability { - String content + private String content; @JsonCreator TextCapability(@JsonProperty("id") String id) { - this(id, null, null) + this(id, null, null); } TextCapability(String id, String title, String description) { - super(id, ServiceCapabilityType.TEXT, title, description) + super(id, ServiceCapabilityType.TEXT, title, description); + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; } @Override - void merge(String otherContent) { - if (otherContent) { - this.content = otherContent + public void merge(String otherContent) { + if (otherContent != null) { + this.content = otherContent; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/metadata/Type.java b/initializr-generator/src/main/java/io/spring/initializr/metadata/Type.java new file mode 100644 index 00000000..06d7f74d --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/Type.java @@ -0,0 +1,71 @@ +/* + * 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 io.spring.initializr.metadata; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Defines a particular project type. Each type is associated to a concrete action that + * should be invoked to generate the content of that type. + * + * @author Stephane Nicoll + */ +public class Type extends DefaultMetadataElement implements Describable { + + private String description; + + @Deprecated + private String stsId; + + private String action; + + private final Map tags = new LinkedHashMap<>(); + + public void setAction(String action) { + String actionToUse = action; + if (!actionToUse.startsWith("/")) { + actionToUse = "/" + actionToUse; + } + this.action = actionToUse; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStsId() { + return stsId; + } + + public void setStsId(String stsId) { + this.stsId = stsId; + } + + public String getAction() { + return action; + } + + public Map getTags() { + return tags; + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy b/initializr-generator/src/main/java/io/spring/initializr/metadata/TypeCapability.java similarity index 51% rename from initializr-generator/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy rename to initializr-generator/src/main/java/io/spring/initializr/metadata/TypeCapability.java index 19060a96..bf1e2d6c 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/metadata/TypeCapability.java @@ -14,47 +14,52 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; -import groovy.transform.AutoClone -import groovy.transform.AutoCloneStyle +import java.util.ArrayList; +import java.util.List; /** * An {@link ServiceCapabilityType#ACTION action} capability. * * @author Stephane Nicoll */ -@AutoClone(style = AutoCloneStyle.COPY_CONSTRUCTOR) -class TypeCapability extends ServiceCapability> { +public class TypeCapability extends ServiceCapability> implements Defaultable { - final List content = [] + final List content = new ArrayList<>(); - TypeCapability() { - super('type', ServiceCapabilityType.ACTION, 'Type', 'project type') + public TypeCapability() { + super("type", ServiceCapabilityType.ACTION, "Type", "project type"); + } + + public List getContent() { + return content; } /** - * Return the {@link Type} with the specified id or {@code null} if no - * such type exists. + * Return the {@link Type} with the specified id or {@code null} if no such type + * exists. */ - Type get(String id) { - return content.find { id.equals(it.id) || id.equals(it.stsId) } + public Type get(String id) { + return content.stream() + .filter(it -> id.equals(it.getId()) || id.equals(it.getStsId())) + .findFirst().orElse(null); } /** * Return the default {@link Type}. */ - Type getDefault() { - return content.find { it.default } + public Type getDefault() { + return content.stream().filter(it -> it.isDefault()).findFirst().orElse(null); } @Override - void merge(List otherContent) { - otherContent.each { - if (!get(it.id)) { - content << it + public void merge(List otherContent) { + otherContent.forEach(it -> { + if (get(it.getId())==null) { + content.add(it); } - } + }); } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/util/Agent.java b/initializr-generator/src/main/java/io/spring/initializr/util/Agent.java new file mode 100644 index 00000000..55f17ffe --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/util/Agent.java @@ -0,0 +1,136 @@ +/* + * 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 io.spring.initializr.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Defines the agent that submitted a request. + * + * @author Stephane Nicoll + */ +public class Agent { + + /** + * The {@link AgentId}. + */ + private final AgentId id; + + /** + * The version of the agent, if any + */ + private final String version; + + public Agent(AgentId id, String version) { + this.id = id; + this.version = version; + } + + public AgentId getId() { + return id; + } + + public String getVersion() { + return version; + } + + /** + * Create an {@link Agent} based on the specified {@code User-Agent} header. + * @param userAgent the user agent + * @return an {@link Agent} instance or {@code null} + */ + public static Agent fromUserAgent(String userAgent) { + return UserAgentHandler.parse(userAgent); + } + + /** + * Defines the various known agents. + */ + public static enum AgentId { + + CURL("curl", "curl"), + + HTTPIE("httpie", "HTTPie"), + + SPRING_BOOT_CLI("spring", "SpringBootCli"), + + STS("sts", "STS"), + + INTELLIJ_IDEA("intellijidea", "IntelliJ IDEA"), + + NETBEANS("netbeans", "NetBeans"), + + BROWSER("browser", "Browser"); + + final String id; + final String name; + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + private AgentId(String id, String name) { + this.id = id; + this.name = name; + } + } + + private static class UserAgentHandler { + + private static final Pattern TOOL_REGEX = Pattern.compile("([^\\/]*)\\/([^ ]*).*"); + + private static final Pattern STS_REGEX = Pattern.compile("STS (.*)"); + + private static final Pattern NETBEANS_REGEX = Pattern.compile("nb-springboot-plugin\\/(.*)"); + + public static Agent parse(String userAgent) { + Matcher matcher = TOOL_REGEX.matcher(userAgent); + if (matcher.matches()) { + String name = matcher.group(1); + for (AgentId id : AgentId.values()) { + if (name.equals(id.name)) { + String version = matcher.group(2); + return new Agent(id, version); + } + } + } + matcher = STS_REGEX.matcher(userAgent); + if (matcher.matches()) { + return new Agent(AgentId.STS, matcher.group(1)); + } + matcher = NETBEANS_REGEX.matcher(userAgent); + if (matcher.matches()) { + return new Agent(AgentId.NETBEANS, matcher.group(1)); + } + + if (userAgent.equals(AgentId.INTELLIJ_IDEA.name)) { + return new Agent(AgentId.INTELLIJ_IDEA, null); + } + if (userAgent.contains("Mozilla/5.0")) { // Super heuristics + return new Agent(AgentId.BROWSER, null); + } + return null; + } + + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/util/GroovyTemplate.java b/initializr-generator/src/main/java/io/spring/initializr/util/GroovyTemplate.java new file mode 100644 index 00000000..d859ccfe --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/util/GroovyTemplate.java @@ -0,0 +1,104 @@ +/* + * 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 io.spring.initializr.util; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + +import org.codehaus.groovy.control.CompilationFailedException; +import org.springframework.util.ConcurrentReferenceHashMap; +import org.springframework.util.StreamUtils; + +import groovy.lang.Writable; +import groovy.text.GStringTemplateEngine; +import groovy.text.Template; +import groovy.text.TemplateEngine; + +/** + * @author Dave Syer + */ +public class GroovyTemplate { + + private boolean cache = true; + + private final TemplateEngine engine; + private final ConcurrentMap templateCaches = new ConcurrentReferenceHashMap<>(); + + public GroovyTemplate(TemplateEngine engine) { + this.engine = engine; + } + + public GroovyTemplate() { + this(new GStringTemplateEngine()); + } + + public boolean isCache() { + return cache; + } + + public void setCache(boolean cache) { + this.cache = cache; + } + + public String process(String name, Map model) { + try { + Template template = getTemplate(name); + Writable writable = template.make(model); + StringWriter result = new StringWriter(); + writable.writeTo(result); + return result.toString(); + } + catch (Exception e) { + throw new IllegalStateException("Cannot render template", e); + } + } + + public Template getTemplate(String name) + throws CompilationFailedException, ClassNotFoundException, IOException { + if (cache) { + return this.templateCaches.computeIfAbsent(name, n -> loadTemplate(n)); + } + return loadTemplate(name); + } + + protected Template loadTemplate(String name) { + try { + File file = new File("templates", name); + if (file.exists()) { + return engine.createTemplate(file); + } + + ClassLoader classLoader = GroovyTemplate.class.getClassLoader(); + URL resource = classLoader.getResource("templates/" + name); + if (resource != null) { + return engine.createTemplate(StreamUtils + .copyToString(resource.openStream(), Charset.forName("UTF-8"))); + } + + return engine.createTemplate(name); + } + catch (Exception e) { + throw new IllegalStateException("Cannot load template " + name, e); + } + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy b/initializr-generator/src/main/java/io/spring/initializr/util/InvalidVersionException.java similarity index 70% rename from initializr-generator/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy rename to initializr-generator/src/main/java/io/spring/initializr/util/InvalidVersionException.java index 1d5b174e..1a93d61e 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/util/InvalidVersionException.java @@ -14,16 +14,22 @@ * limitations under the License. */ -package io.spring.initializr.util - -import groovy.transform.InheritConstructors +package io.spring.initializr.util; /** * Thrown if a input represents an invalid version. * * @author Stephane Nicoll */ -@InheritConstructors -class InvalidVersionException extends RuntimeException { +@SuppressWarnings("serial") +public class InvalidVersionException extends RuntimeException { + + public InvalidVersionException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidVersionException(String message) { + super(message); + } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/util/Version.java b/initializr-generator/src/main/java/io/spring/initializr/util/Version.java new file mode 100644 index 00000000..3dfb8f58 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/util/Version.java @@ -0,0 +1,290 @@ +/* + * 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 io.spring.initializr.util; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.springframework.util.StringUtils; + +/** + * Define the version number of a module. A typical version is represented + * as {@code MAJOR.MINOR.PATCH.QUALIFIER} where the qualifier can have an + * extra version. + *

+ * For example: {@code 1.2.0.RC1} is the first release candidate of 1.2.0 + * and {@code 1.5.0.M4} is the fourth milestone of 1.5.0. The special + * {@code RELEASE} qualifier indicates a final release (a.k.a. GA) + *

+ * The main purpose of parsing a version is to compare it with another + * version, see {@link Comparable}. + * + * @author Stephane Nicoll + */ +@SuppressWarnings("serial") +public final class Version implements Serializable, Comparable { + + private static final VersionQualifierComparator qualifierComparator = new VersionQualifierComparator(); + + private static final VersionParser parser = new VersionParser(Collections.emptyList()); + + private final Integer major; + private final Integer minor; + private final Integer patch; + private final Qualifier qualifier; + + // For Jackson + @SuppressWarnings("unused") + private Version() { + this(null, null, null, null); + } + + public Version(Integer major, Integer minor, Integer patch, Qualifier qualifier) { + this.major = major; + this.minor = minor; + this.patch = patch; + this.qualifier = qualifier; + } + + public Integer getMajor() { + return major; + } + + public Integer getMinor() { + return minor; + } + + public Integer getPatch() { + return patch; + } + + public Qualifier getQualifier() { + return qualifier; + } + + @Override + public String toString() { + return major + "." + minor + "." + patch + + (qualifier!=null ? "." + qualifier.qualifier + + (qualifier.version!=null ? qualifier.version : "") : ""); + } + + /** + * Parse the string representation of a {@link Version}. Throws an + * {@link InvalidVersionException} if the version could not be parsed. + * @param text the version text + * @return a Version instance for the specified version text + * @throws InvalidVersionException if the version text could not be parsed + * @see {@link VersionParser} + */ + public static Version parse(String text) { + return parser.parse(text); + } + + /** + * Parse safely the specified string representation of a {@link Version}. + *

+ * Return {@code null} if the text represents an invalid version. + * @param text the version text + * @return a Version instance for the specified version text + * @see {@link VersionParser} + */ + public static Version safeParse(String text) { + try { + return parse(text); + } catch (InvalidVersionException e) { + return null; + } + } + + @Override + public int compareTo(Version other) { + if (other == null) { + return 1; + } + int majorDiff = safeCompare(this.major, other.major); + if (majorDiff != 0) { + return majorDiff; + } + int minorDiff = safeCompare(this.minor, other.minor); + if (minorDiff != 0) { + return minorDiff; + } + int patch = safeCompare(this.patch, other.patch); + if (patch != 0) { + return patch; + } + return qualifierComparator.compare(this.qualifier, other.qualifier); + } + + private static int safeCompare(Integer first, Integer second) { + Integer firstIndex = first !=null ? first : 0; + Integer secondIndex = second !=null ? second : 0; + return firstIndex.compareTo(secondIndex); + } + + public static class Qualifier { + public Qualifier() { + } + public Qualifier(String qualifier) { + this.qualifier = qualifier; + } + String qualifier; + Integer version; + public String getQualifier() { + return qualifier; + } + public void setQualifier(String qualifier) { + this.qualifier = qualifier; + } + public Integer getVersion() { + return version; + } + public void setVersion(Integer version) { + this.version = version; + } + @Override + public String toString() { + return "Qualifier [" + + (qualifier != null ? "qualifier=" + qualifier + ", " : "") + + (version != null ? "version=" + version : "") + "]"; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((qualifier == null) ? 0 : qualifier.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Qualifier other = (Qualifier) obj; + if (qualifier == null) { + if (other.qualifier != null) + return false; + } + else if (!qualifier.equals(other.qualifier)) + return false; + if (version == null) { + if (other.version != null) + return false; + } + else if (!version.equals(other.version)) + return false; + return true; + } + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((major == null) ? 0 : major.hashCode()); + result = prime * result + ((minor == null) ? 0 : minor.hashCode()); + result = prime * result + ((patch == null) ? 0 : patch.hashCode()); + result = prime * result + ((qualifier == null) ? 0 : qualifier.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Version other = (Version) obj; + if (major == null) { + if (other.major != null) + return false; + } + else if (!major.equals(other.major)) + return false; + if (minor == null) { + if (other.minor != null) + return false; + } + else if (!minor.equals(other.minor)) + return false; + if (patch == null) { + if (other.patch != null) + return false; + } + else if (!patch.equals(other.patch)) + return false; + if (qualifier == null) { + if (other.qualifier != null) + return false; + } + else if (!qualifier.equals(other.qualifier)) + return false; + return true; + } + + private static class VersionQualifierComparator implements Comparator { + + static final String RELEASE = "RELEASE"; + static final String SNAPSHOT = "BUILD-SNAPSHOT"; + static final String MILESTONE = "M"; + static final String RC = "RC"; + + static final List KNOWN_QUALIFIERS = Arrays.asList(MILESTONE, RC, SNAPSHOT, RELEASE); + + @Override + public int compare(Qualifier o1, Qualifier o2) { + Qualifier first = o1!=null ? o1 : new Qualifier(RELEASE); + Qualifier second = o2!=null ? o2 : new Qualifier(RELEASE); + + int qualifier = compareQualifier(first, second); + return qualifier!=0 ? qualifier : compareQualifierVersion(first, second); + } + + private static int compareQualifierVersion(Qualifier first, Qualifier second) { + Integer firstVersion = first.getVersion()!=null ? first.getVersion() : 0; + Integer secondVersion = second.getVersion()!=null ? second.getVersion(): 0; + return firstVersion.compareTo(secondVersion); + } + + private static int compareQualifier(Qualifier first, Qualifier second) { + Integer firstIndex = getQualifierIndex(first.qualifier); + Integer secondIndex = getQualifierIndex(second.qualifier); + + if (firstIndex == -1 && secondIndex == -1) { // Unknown qualifier, alphabetic ordering + return first.qualifier.compareTo(second.qualifier); + } else { + return firstIndex.compareTo(secondIndex); + } + } + + private static int getQualifierIndex(String qualifier) { + return StringUtils.hasText(qualifier) ? KNOWN_QUALIFIERS.indexOf(qualifier) : 0; + } + } + +} diff --git a/initializr-generator/src/main/groovy/io/spring/initializr/util/VersionParser.groovy b/initializr-generator/src/main/java/io/spring/initializr/util/VersionParser.java similarity index 52% rename from initializr-generator/src/main/groovy/io/spring/initializr/util/VersionParser.groovy rename to initializr-generator/src/main/java/io/spring/initializr/util/VersionParser.java index a9cae65a..a224de3c 100644 --- a/initializr-generator/src/main/groovy/io/spring/initializr/util/VersionParser.groovy +++ b/initializr-generator/src/main/java/io/spring/initializr/util/VersionParser.java @@ -14,9 +14,18 @@ * limitations under the License. */ -package io.spring.initializr.util +package io.spring.initializr.util; -import org.springframework.util.Assert +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import io.spring.initializr.util.Version.Qualifier; /** * Parser for {@link Version} and {@link VersionRange} that allows to resolve the minor @@ -31,18 +40,18 @@ import org.springframework.util.Assert * * @author Stephane Nicoll */ -class VersionParser { +public class VersionParser { - public static final VersionParser DEFAULT = new VersionParser(Collections.emptyList()) + public static final VersionParser DEFAULT = new VersionParser(Collections.emptyList()); - private static final String VERSION_REGEX = '^(\\d+)\\.(\\d+|x)\\.(\\d+|x)(?:\\.([^0-9]+)(\\d+)?)?$' + private static final Pattern VERSION_REGEX = Pattern.compile("^(\\d+)\\.(\\d+|x)\\.(\\d+|x)(?:\\.([^0-9]+)(\\d+)?)?$"); - private static final String RANGE_REGEX = "(\\(|\\[)(.*),(.*)(\\)|\\])" + private static final Pattern RANGE_REGEX = Pattern.compile("(\\(|\\[)(.*),(.*)(\\)|\\])"); private final List latestVersions; - VersionParser(List latestVersions) { - this.latestVersions = latestVersions + public VersionParser(List latestVersions) { + this.latestVersions = latestVersions; } /** @@ -53,35 +62,35 @@ class VersionParser { * @throws InvalidVersionException if the version text could not be parsed * @see #safeParse(java.lang.String) */ - Version parse(String text) { - Assert.notNull(text, 'Text must not be null') - def matcher = (text.trim() =~ VERSION_REGEX) + public Version parse(String text) { + Assert.notNull(text, "Text must not be null"); + Matcher matcher = VERSION_REGEX.matcher(text.trim()); if (!matcher.matches()) { - throw new InvalidVersionException("Could not determine version based on '$text': version format " + - "is Minor.Major.Patch.Qualifier (e.g. 1.0.5.RELEASE)") + throw new InvalidVersionException("Could not determine version based on '" + text + "': version format " + + "is Minor.Major.Patch.Qualifier (e.g. 1.0.5.RELEASE)"); } - Integer major = Integer.valueOf(matcher[0][1]) - String minor = matcher[0][2] - String patch = matcher[0][3] - def qualifier = null; - String qualifierId = matcher[0][4] - if (qualifierId) { - qualifier = new Version.Qualifier(qualifier: qualifierId) - String o = matcher[0][5] + Integer major = Integer.valueOf(matcher.group(1)); + String minor = matcher.group(2); + String patch = matcher.group(3); + Qualifier qualifier = null; + String qualifierId = matcher.group(4); + if (StringUtils.hasText(qualifierId)) { + qualifier = new Version.Qualifier(qualifierId); + String o = matcher.group(5); if (o != null) { - qualifier.version = Integer.valueOf(o) + qualifier.version = Integer.valueOf(o); } } - if (minor == "x" || patch == "x") { - Integer minorInt = minor == "x" ? null : Integer.parseInt(minor) - Version latest = findLatestVersion(major, minorInt, qualifier) - if (!latest) { - return new Version(major, (minor == "x" ? 999 : Integer.parseInt(minor)), - (patch == "x" ? 999 : Integer.parseInt(patch)), qualifier) + if ("x".equals(minor) || "x".equals(patch)) { + Integer minorInt = "x".equals(minor) ? null : Integer.parseInt(minor); + Version latest = findLatestVersion(major, minorInt, qualifier); + if (latest==null) { + return new Version(major, ("x".equals(minor) ? 999 : Integer.parseInt(minor)), + ("x".equals(patch) ? 999 : Integer.parseInt(patch)), qualifier); } - return new Version(major, latest.minor, latest.patch, latest.qualifier) + return new Version(major, latest.getMinor(), latest.getPatch(), latest.getQualifier()); } else { - return new Version(major, Integer.parseInt(minor), Integer.parseInt(patch), qualifier) + return new Version(major, Integer.parseInt(minor), Integer.parseInt(patch), qualifier); } } @@ -93,11 +102,11 @@ class VersionParser { * @return a Version instance for the specified version text * @see #parse(java.lang.String) */ - Version safeParse(String text) { + public Version safeParse(String text) { try { - return parse(text) + return parse(text); } catch (InvalidVersionException ex) { - return null + return null; } } @@ -108,36 +117,36 @@ class VersionParser { * @return a VersionRange instance for the specified range text * @throws InvalidVersionException if the range text could not be parsed */ - VersionRange parseRange(String text) { - Assert.notNull(text, "Text must not be null") - def matcher = (text.trim() =~ RANGE_REGEX) + public VersionRange parseRange(String text) { + Assert.notNull(text, "Text must not be null"); + Matcher matcher = RANGE_REGEX.matcher(text.trim()); if (!matcher.matches()) { // Try to read it as simple string - Version version = parse(text) - return new VersionRange(version, true, null, true) + Version version = parse(text); + return new VersionRange(version, true, null, true); } - boolean lowerInclusive = matcher[0][1].equals('[') - Version lowerVersion = parse(matcher[0][2]) - Version higherVersion = parse(matcher[0][3]) - boolean higherInclusive = matcher[0][4].equals(']') - new VersionRange(lowerVersion, lowerInclusive, higherVersion, higherInclusive) + boolean lowerInclusive = matcher.group(1).equals("["); + Version lowerVersion = parse(matcher.group(2)); + Version higherVersion = parse(matcher.group(3)); + boolean higherInclusive = matcher.group(4).equals("]"); + return new VersionRange(lowerVersion, lowerInclusive, higherVersion, higherInclusive); } private Version findLatestVersion(Integer major, Integer minor, Version.Qualifier qualifier) { - def matches = this.latestVersions.findAll { - if (major && major != it.major) { + List matches = this.latestVersions.stream().filter(it -> { + if (major!=null && !major.equals(it.getMajor())) { return false; } - if (minor && minor != it.minor) { + if (minor!=null && !minor.equals(it.getMinor())) { return false; } - if (qualifier && it.qualifier != qualifier) { + if (qualifier!=null && !qualifier.equals(it.getQualifier())) { return false; } return true; - } - return (matches.size() == 1 ? matches[0] : null) + }).collect(Collectors.toList()); + return (matches.size() == 1 ? matches.get(0) : null); } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/util/VersionRange.java b/initializr-generator/src/main/java/io/spring/initializr/util/VersionRange.java new file mode 100644 index 00000000..bd3cf36c --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/util/VersionRange.java @@ -0,0 +1,150 @@ +/* + * 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 io.spring.initializr.util; + +import org.springframework.util.Assert; + +/** + * Define a {@link Version} range. A square bracket "[" or "]" denotes an inclusive + * end of the range and a round bracket "(" or ")" denotes an exclusive end of the + * range. A range can also be unbounded by defining a a single {@link Version}. The + * examples below make this clear. + * + *

    + *
  • "[1.2.0.RELEASE,1.3.0.RELEASE)" version 1.2.0 and any version after + * this, up to, but not including, version 1.3.0.
  • + *
  • "(2.0.0.RELEASE,3.2.0.RELEASE]" any version after 2.0.0 up to and + * including version 3.2.0.
  • + *
  • "1.4.5.RELEASE", version 1.4.5 and all later versions.
  • + *
+ * + * @author Stephane Nicoll + */ +public class VersionRange { + + final Version lowerVersion; + final boolean lowerInclusive; + final Version higherVersion; + final boolean higherInclusive; + + // For Jackson + @SuppressWarnings("unused") + private VersionRange() { + this(null, false, null, false); + } + + protected VersionRange(Version lowerVersion, boolean lowerInclusive, + Version higherVersion, boolean higherInclusive) { + this.lowerVersion = lowerVersion; + this.lowerInclusive = lowerInclusive; + this.higherVersion = higherVersion; + this.higherInclusive = higherInclusive; + } + + /** + * Specify if the {@link Version} matches this range. Returns {@code true} + * if the version is contained within this range, {@code false} otherwise. + */ + public boolean match(Version version) { + Assert.notNull(version, "Version must not be null"); + int lower = lowerVersion.compareTo(version); + if (lower > 0) { + return false; + } else if (!lowerInclusive && lower == 0) { + return false; + } + if (higherVersion!=null) { + int higher = higherVersion.compareTo(version); + if (higher < 0) { + return false; + } else if (!higherInclusive && higher == 0) { + return false; + } + } + return true; + } + + public Version getLowerVersion() { + return lowerVersion; + } + + public boolean isLowerInclusive() { + return lowerInclusive; + } + + public Version getHigherVersion() { + return higherVersion; + } + + public boolean isHigherInclusive() { + return higherInclusive; + } + + @Override + public + String toString() { + StringBuffer sb = new StringBuffer(); + if (lowerVersion!=null) { + sb.append((lowerInclusive ? ">=" : ">") + lowerVersion); + } + if (higherVersion!=null) { + sb.append(" and " + (higherInclusive ? "<=" : "<") + higherVersion); + } + return sb.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (higherInclusive ? 1231 : 1237); + result = prime * result + + ((higherVersion == null) ? 0 : higherVersion.hashCode()); + result = prime * result + (lowerInclusive ? 1231 : 1237); + result = prime * result + ((lowerVersion == null) ? 0 : lowerVersion.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VersionRange other = (VersionRange) obj; + if (higherInclusive != other.higherInclusive) + return false; + if (higherVersion == null) { + if (other.higherVersion != null) + return false; + } + else if (!higherVersion.equals(other.higherVersion)) + return false; + if (lowerInclusive != other.lowerInclusive) + return false; + if (lowerVersion == null) { + if (other.lowerVersion != null) + return false; + } + else if (!lowerVersion.equals(other.lowerVersion)) + return false; + return true; + } + +} diff --git a/initializr-generator/src/main/resources/templates/starter-build.gradle b/initializr-generator/src/main/resources/templates/starter-build.gradle index 5a684213..d10c34d0 100644 --- a/initializr-generator/src/main/resources/templates/starter-build.gradle +++ b/initializr-generator/src/main/resources/templates/starter-build.gradle @@ -1,6 +1,6 @@ buildscript { ext {<% buildProperties.gradle.each { %> - ${it.key} = '${it.value.call()}'<% } %> + ${it.key} = '${((java.util.function.Supplier)it.value).get()}'<% } %> } repositories { mavenCentral()<% if (!bootVersion.contains("RELEASE")) { %> @@ -39,7 +39,7 @@ repositories { providedRuntime } <% } %><% if (buildProperties.versions) { %><%buildProperties.versions.each { %> -ext['${it.key}'] = '${it.value.call()}'<% } %> +ext['${it.key}'] = '${((java.util.function.Supplier)it.value).get()}'<% } %> <% } %> dependencies {<% compileDependencies.each { %> compile('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %><% if (language=='groovy') { %> diff --git a/initializr-generator/src/main/resources/templates/starter-pom.xml b/initializr-generator/src/main/resources/templates/starter-pom.xml index 452a25aa..83a8d0db 100644 --- a/initializr-generator/src/main/resources/templates/starter-pom.xml +++ b/initializr-generator/src/main/resources/templates/starter-pom.xml @@ -19,8 +19,8 @@ <% buildProperties.maven.each { %> - <${it.key}>${it.value()}<% } %><%buildProperties.versions.each { %> - <${it.key}>${it.value()}<%}%> + <${it.key}>${((java.util.function.Supplier)it.value).get()}<% } %><%buildProperties.versions.each { %> + <${it.key}>${((java.util.function.Supplier)it.value).get()}<%}%> <% compileDependencies.each { %> diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/AbstractProjectGeneratorTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/AbstractProjectGeneratorTests.groovy deleted file mode 100644 index 6fb22d38..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/AbstractProjectGeneratorTests.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.metadata.SimpleInitializrMetadataProvider -import io.spring.initializr.test.generator.GradleBuildAssert -import io.spring.initializr.test.generator.PomAssert -import io.spring.initializr.test.generator.ProjectAssert -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.mockito.ArgumentMatcher - -import org.springframework.context.ApplicationEventPublisher - -import static org.mockito.Matchers.argThat -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.times -import static org.mockito.Mockito.verify - -/** - * - * @author Stephane Nicoll - */ -abstract class AbstractProjectGeneratorTests { - - @Rule - public final TemporaryFolder folder = new TemporaryFolder() - - protected final ProjectGenerator projectGenerator = new ProjectGenerator() - - private final ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher) - - @Before - void setup() { - def web = new Dependency(id: 'web') - web.facets << 'web' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('web', web) - .addDependencyGroup('test', 'security', 'data-jpa', 'aop', 'batch', 'integration').build() - applyMetadata(metadata) - projectGenerator.eventPublisher = eventPublisher - projectGenerator.requestResolver = new ProjectRequestResolver([]) - projectGenerator.tmpdir = folder.newFolder().absolutePath - } - - - protected PomAssert generateMavenPom(ProjectRequest request) { - request.type = 'maven-build' - def content = new String(projectGenerator.generateMavenPom(request)) - new PomAssert(content).validateProjectRequest(request) - } - - protected GradleBuildAssert generateGradleBuild(ProjectRequest request) { - request.type = 'gradle-build' - def content = new String(projectGenerator.generateGradleBuild(request)) - new GradleBuildAssert(content).validateProjectRequest(request) - } - - protected ProjectAssert generateProject(ProjectRequest request) { - def dir = projectGenerator.generateProjectStructure(request) - new ProjectAssert(dir) - } - - ProjectRequest createProjectRequest(String... styles) { - def request = new ProjectRequest() - request.initialize(projectGenerator.metadataProvider.get()) - request.style.addAll Arrays.asList(styles) - request - } - - protected void applyMetadata(InitializrMetadata metadata) { - projectGenerator.metadataProvider = new SimpleInitializrMetadataProvider(metadata) - } - - protected verifyProjectSuccessfulEventFor(ProjectRequest request) { - verify(eventPublisher, times(1)).publishEvent(argThat(new ProjectGeneratedEventMatcher(request))) - } - - protected verifyProjectFailedEventFor(ProjectRequest request, Exception ex) { - verify(eventPublisher, times(1)).publishEvent(argThat(new ProjectFailedEventMatcher(request, ex))) - } - - private static class ProjectGeneratedEventMatcher extends ArgumentMatcher { - - private final ProjectRequest request - - ProjectGeneratedEventMatcher(ProjectRequest request) { - this.request = request - } - - @Override - boolean matches(Object argument) { - ProjectGeneratedEvent event = (ProjectGeneratedEvent) argument - return request.equals(event.projectRequest) - } - } - - private static class ProjectFailedEventMatcher extends ArgumentMatcher { - - private final ProjectRequest request - private final Exception cause - - ProjectFailedEventMatcher(ProjectRequest request, Exception cause) { - this.request = request - this.cause = cause - } - - @Override - boolean matches(Object argument) { - ProjectFailedEvent event = (ProjectFailedEvent) argument - return request.equals(event.projectRequest) && cause.equals(event.cause) - } - } - - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/CommandLineHelpGeneratorTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/CommandLineHelpGeneratorTests.groovy deleted file mode 100644 index d32bf43b..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/CommandLineHelpGeneratorTests.groovy +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.Type -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import io.spring.initializr.util.GroovyTemplate -import org.junit.Test - -import static org.hamcrest.CoreMatchers.containsString -import static org.hamcrest.core.IsNot.not -import static org.junit.Assert.assertThat - -/** - * @author Stephane Nicoll - */ -class CommandLineHelpGeneratorTests { - - private CommandLineHelpGenerator generator = new CommandLineHelpGenerator(new GroovyTemplate()) - - @Test - void generateGenericCapabilities() { - def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", - createDependency('id-b', 'depB'), - createDependency('id-a', 'depA', 'and some description')).build() - String content = generator.generateGenericCapabilities(metadata, "https://fake-service") - assertCommandLineCapabilities(content) - assertThat content, containsString('id-a | and some description |') - assertThat content, containsString('id-b | depB') - assertThat content, containsString("https://fake-service") - assertThat content, not(containsString('Examples:')) - assertThat content, not(containsString('curl')) - } - - @Test - void generateCapabilitiesWithTypeDescription() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addType(new Type(id: 'foo', name: 'foo-name', description: 'foo-desc')) - .build() - String content = generator.generateGenericCapabilities(metadata, "https://fake-service") - assertCommandLineCapabilities(content) - assertThat content, containsString('| foo') - assertThat content, containsString('| foo-desc') - } - - @Test - void generateCurlCapabilities() { - def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", - createDependency('id-b', 'depB'), - createDependency('id-a', 'depA', 'and some description')).build() - String content = generator.generateCurlCapabilities(metadata, "https://fake-service") - assertCommandLineCapabilities(content) - assertThat content, containsString('id-a | and some description |') - assertThat content, containsString('id-b | depB') - assertThat content, containsString("https://fake-service") - assertThat content, containsString('Examples:') - assertThat content, containsString('curl') - } - - @Test - void generateHttpCapabilities() { - def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", - createDependency('id-b', 'depB'), - createDependency('id-a', 'depA', 'and some description')).build() - String content = generator.generateHttpieCapabilities(metadata, "https://fake-service") - assertCommandLineCapabilities(content) - assertThat content, containsString('id-a | and some description |') - assertThat content, containsString('id-b | depB') - assertThat content, containsString("https://fake-service") - assertThat content, containsString('Examples:') - assertThat content, not(containsString('curl')) - assertThat content, containsString("http https://fake-service") - } - - @Test - void generateSpringBootCliCapabilities() { - def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", - createDependency('id-b', 'depB'), - createDependency('id-a', 'depA', 'and some description')).build() - String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service") - assertThat content, containsString("| Id") - assertThat content, containsString("| Tags") - assertThat content, containsString('id-a | and some description |') - assertThat content, containsString('id-b | depB') - assertThat content, containsString("https://fake-service") - assertThat content, not(containsString('Examples:')) - assertThat content, not(containsString('curl')) - assertThat content, not(containsString('| Rel')) - assertThat content, not(containsString("| dependencies")) - assertThat content, not(containsString("| applicationName")) - assertThat content, not(containsString("| baseDir")) - } - - @Test - void generateCapabilitiesWithVersionRange() { - def first = new Dependency(id: 'first', description: 'first desc', versionRange: '1.2.0.RELEASE') - def second = new Dependency(id: 'second', description: 'second desc', versionRange: ' [1.2.0.RELEASE,1.3.0.M1) ') - def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", first, second).build() - String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service") - assertThat content, containsString('| first | first desc | >=1.2.0.RELEASE |') - assertThat content, containsString('| second | second desc | >=1.2.0.RELEASE and <1.3.0.M1 |') - } - - private static assertCommandLineCapabilities(String content) { - assertThat content, containsString("| Rel") - assertThat content, containsString("| dependencies") - assertThat content, containsString("| applicationName") - assertThat content, containsString("| baseDir") - assertThat content, not(containsString('| Tags')) - } - - private static createDependency(String id, String name) { - createDependency(id, name, null) - } - - private static createDependency(String id, String name, String description) { - new Dependency(id: id, name: name, description: description) - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorBuildTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorBuildTests.groovy deleted file mode 100644 index 992e563d..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorBuildTests.groovy +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -import org.springframework.core.io.ClassPathResource - -/** - * Project generator tests for supported build systems. - * - * @author Stephane Nicoll - */ -@RunWith(Parameterized.class) -class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests { - - @Parameterized.Parameters(name = "{0}") - static Object[] parameters() { - Object[] maven = ["maven", "pom.xml"] - Object[] gradle = ["gradle", "build.gradle"] - Object[] parameters = [maven, gradle] - parameters - } - - private final String build - private final String fileName - private final String assertFileName - - ProjectGeneratorBuildTests(String build, String fileName) { - this.build = build - this.fileName = fileName - this.assertFileName = fileName + ".gen" - } - - @Test - void standardJarJava() { - testStandardJar('java') - } - - @Test - void standardJarGroovy() { - testStandardJar('groovy') - } - - @Test - void standardJarKotlin() { - testStandardJar('kotlin') - } - - private void testStandardJar(def language) { - def request = createProjectRequest() - request.language = language - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$language/standard/$assertFileName")) - } - - @Test - void standardWarJava() { - testStandardWar('java') - } - - @Test - void standardWarGroovy() { - testStandardWar('java') - } - - @Test - void standardWarKotlin() { - testStandardWar('kotlin') - } - - private void testStandardWar(def language) { - def request = createProjectRequest('web') - request.packaging = 'war' - request.language = language - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$language/war/$assertFileName")) - } - - @Test - void versionOverride() { - def request = createProjectRequest('web') - request.buildProperties.versions['spring-foo.version'] = {'0.1.0.RELEASE'} - request.buildProperties.versions['spring-bar.version'] = {'0.2.0.RELEASE'} - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$build/version-override-$assertFileName")) - } - - @Test - void bomWithVersionProperty() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'the-bom') - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom', - version: '1.3.3', versionProperty: 'foo.version') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('the-bom', bom).build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$build/bom-property-$assertFileName")) - } - - @Test - void compileOnlyDependency() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', - scope: Dependency.SCOPE_COMPILE_ONLY) - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'data-jpa') - .addDependencyGroup('foo', foo) - .build() - applyMetadata(metadata) - def request = createProjectRequest('foo', 'web', 'data-jpa') - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$build/compile-only-dependency-$assertFileName")) - } - - @Test - void bomWithOrdering() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'foo-bom') - def barBom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'bar-bom', - version: '1.0', order: 50) - def bizBom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'biz-bom', - order: 40, additionalBoms: ['bar-bom']) - bizBom.mappings << new BillOfMaterials.Mapping(versionRange: '1.0.0.RELEASE', - version: '1.0') - def fooBom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom', - version: '1.0', order: 20, additionalBoms: ['biz-bom']) - - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('foo-bom', fooBom) - .addBom('bar-bom', barBom) - .addBom('biz-bom', bizBom) - .build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - def project = generateProject(request) - project.sourceCodeAssert("$fileName") - .equalsTo(new ClassPathResource("project/$build/bom-ordering-$assertFileName")) - } - - @Override - ProjectRequest createProjectRequest(String... styles) { - def request = super.createProjectRequest(styles) - request.type = "$build-project" - request - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorLanguageTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorLanguageTests.groovy deleted file mode 100644 index 64c5c654..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorLanguageTests.groovy +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.generator - -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -import org.springframework.core.io.ClassPathResource - -import static io.spring.initializr.test.generator.ProjectAssert.DEFAULT_APPLICATION_NAME -import static io.spring.initializr.test.generator.ProjectAssert.DEFAULT_PACKAGE_NAME - -/** - * Project generator tests for supported languages. - * - * @author Stephane Nicoll - */ -@RunWith(Parameterized.class) -class ProjectGeneratorLanguageTests extends AbstractProjectGeneratorTests { - - @Parameterized.Parameters(name = "{0}") - static Object[] parameters() { - Object[] java = ["java", "java"] - Object[] groovy = ["groovy", "groovy"] - Object[] kotlin = ["kotlin", "kt"] - Object[] parameters = [java, groovy, kotlin] - parameters - } - - private final String language - private final String extension - private final String expectedExtension - - ProjectGeneratorLanguageTests(String language, String extension) { - this.language = language - this.extension = extension - this.expectedExtension = extension + '.gen' - } - - @Test - void standardJar() { - def request = createProjectRequest() - request.language = language - generateProject(request).isGenericProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME, - language, extension) - } - - @Test - void standardWar() { - def request = createProjectRequest('web') - request.language = language - request.packaging = 'war' - generateProject(request).isGenericWarProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME, - language, extension) - } - - @Test - void standardMainClass() { - def request = createProjectRequest() - request.language = language - - def project = generateProject(request) - project.sourceCodeAssert("src/main/$language/com/example/DemoApplication.$extension") - .equalsTo(new ClassPathResource("project/$language/standard/DemoApplication.$expectedExtension")) - } - - @Test - void standardTestClass() { - def request = createProjectRequest() - request.language = language - - def project = generateProject(request) - project.sourceCodeAssert("src/test/$language/com/example/DemoApplicationTests.$extension") - .equalsTo(new ClassPathResource("project/$language/standard/DemoApplicationTests.$expectedExtension")) - } - - @Test - void standardTestClassWeb() { - def request = createProjectRequest('web') - request.language = language - - def project = generateProject(request) - project.sourceCodeAssert("src/test/$language/com/example/DemoApplicationTests.$extension") - .equalsTo(new ClassPathResource("project/$language/standard/DemoApplicationTestsWeb.$expectedExtension")) - } - - @Test - void standardServletInitializer() { - testServletInitializr(null, 'standard') - } - - @Test - void springBoot14M2ServletInitializer() { - testServletInitializr('1.4.0.M2', 'standard') - } - - @Test - void springBoot14ServletInitializer() { - testServletInitializr('1.4.0.M3', 'spring-boot-1.4') - } - - private void testServletInitializr(String bootVersion, String expectedOutput) { - def request = createProjectRequest() - request.language = language - request.packaging = 'war' - if (bootVersion) { - request.bootVersion = bootVersion - } - def project = generateProject(request) - project.sourceCodeAssert("src/main/$language/com/example/ServletInitializer.$extension") - .equalsTo(new ClassPathResource("project/$language/$expectedOutput/ServletInitializer.$expectedExtension")) - } - - @Test - void springBoot14M1TestClass() { - def request = createProjectRequest() - request.language = language - request.bootVersion = '1.4.0.M1' - - def project = generateProject(request) - project.sourceCodeAssert("src/test/$language/com/example/DemoApplicationTests.$extension") - .equalsTo(new ClassPathResource("project/$language/standard/DemoApplicationTests.$expectedExtension")) - } - - @Test - void springBoot14TestClass() { - def request = createProjectRequest() - request.language = language - request.bootVersion = '1.4.0.M2' - - def project = generateProject(request) - project.sourceCodeAssert("src/test/$language/com/example/DemoApplicationTests.$extension") - .equalsTo(new ClassPathResource("project/$language/spring-boot-1.4/DemoApplicationTests.$expectedExtension")) - } - - @Test - void springBoot14TestClassWeb() { - def request = createProjectRequest('web') - request.language = language - request.bootVersion = '1.4.0.M2' - - def project = generateProject(request) - project.sourceCodeAssert("src/test/$language/com/example/DemoApplicationTests.$extension") - .equalsTo(new ClassPathResource("project/$language/spring-boot-1.4/DemoApplicationTests.$expectedExtension")) - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorTests.groovy deleted file mode 100644 index 1874da0c..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectGeneratorTests.groovy +++ /dev/null @@ -1,787 +0,0 @@ -/* - * 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource - -import static org.hamcrest.CoreMatchers.containsString -import static org.junit.Assert.assertThat -import static org.junit.Assert.fail - -/** - * Tests for {@link ProjectGenerator} - * - * @author Stephane Nicoll - */ -class ProjectGeneratorTests extends AbstractProjectGeneratorTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void defaultMavenPom() { - def request = createProjectRequest('web') - generateMavenPom(request).hasNoRepository() - .hasSpringBootStarterDependency('web') - verifyProjectSuccessfulEventFor(request) - } - - @Test - void defaultGradleBuild() { - def request = createProjectRequest('web') - generateGradleBuild(request) - verifyProjectSuccessfulEventFor(request) - } - - @Test - void defaultProject() { - def request = createProjectRequest('web') - generateProject(request).isJavaProject().isMavenProject().pomAssert() - .hasNoRepository().hasSpringBootStarterDependency('web') - verifyProjectSuccessfulEventFor(request) - } - - @Test - void noDependencyAddsRootStarter() { - def request = createProjectRequest() - generateProject(request).isJavaProject().isMavenProject().pomAssert() - .hasSpringBootStarterRootDependency() - } - - @Test - void mavenPomWithBootSnapshot() { - def request = createProjectRequest('web') - request.bootVersion = '1.0.1.BUILD-SNAPSHOT' - generateMavenPom(request).hasSnapshotRepository() - .hasSpringBootParent('1.0.1.BUILD-SNAPSHOT') - .hasSpringBootStarterDependency('web') - } - - @Test - void mavenPomWithTarDependency() { - def dependency = new Dependency(id: 'custom-artifact', groupId: 'org.foo', artifactId: 'custom-artifact', type: "tar.gz") - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('test', dependency).build() - applyMetadata(metadata) - - def request = createProjectRequest('custom-artifact') - generateMavenPom(request).hasDependency(dependency) - .hasDependenciesCount(2) - } - - @Test - void gradleBuildWithTarDependency() { - def dependency = new Dependency(id: 'custom-artifact', groupId: 'org.foo', artifactId: 'custom-artifact', type: "tar.gz") - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('test', dependency).build() - applyMetadata(metadata) - - def request = createProjectRequest('custom-artifact') - generateGradleBuild(request) - .contains("compile('org.foo:custom-artifact@tar.gz')") - } - - @Test - void mavenPomWithWebFacet() { - def dependency = new Dependency(id: 'thymeleaf', groupId: 'org.foo', artifactId: 'thymeleaf') - dependency.facets << 'web' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('test', dependency).build() - applyMetadata(metadata) - - def request = createProjectRequest('thymeleaf') - generateMavenPom(request) - .hasDependency('org.foo', 'thymeleaf') - .hasDependenciesCount(2) - } - - @Test - void mavenWarWithWebFacet() { - def dependency = new Dependency(id: 'thymeleaf', groupId: 'org.foo', artifactId: 'thymeleaf') - dependency.facets << 'web' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('test', dependency).build() - applyMetadata(metadata) - - def request = createProjectRequest('thymeleaf') - request.packaging = 'war' - generateProject(request).isJavaWarProject().isMavenProject(). - pomAssert() - .hasSpringBootStarterTomcat() - .hasDependency('org.foo', 'thymeleaf') // This is tagged as web facet so it brings the web one - .hasSpringBootStarterTest() - .hasDependenciesCount(3) - } - - @Test - void mavenWarPomWithoutWebFacet() { - def request = createProjectRequest('data-jpa') - request.packaging = 'war' - generateMavenPom(request) - .hasSpringBootStarterTomcat() - .hasSpringBootStarterDependency('data-jpa') - .hasSpringBootStarterDependency('web') // Added by war packaging - .hasSpringBootStarterTest() - .hasDependenciesCount(4) - } - - @Test - void gradleWarWithWebFacet() { - def dependency = new Dependency(id: 'thymeleaf', groupId: 'org.foo', artifactId: 'thymeleaf') - dependency.facets << 'web' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('test', dependency).build() - applyMetadata(metadata) - - def request = createProjectRequest('thymeleaf') - request.packaging = 'war' - request.type = 'gradle-project' - generateProject(request).isJavaWarProject().isGradleProject(). - gradleBuildAssert() - .contains("compile('org.foo:thymeleaf')") // This is tagged as web facet so it brings the web one - .doesNotContain("compile('org.springframework.boot:spring-boot-starter-web')") - .contains("testCompile('org.springframework.boot:spring-boot-starter-test')") - .contains("configurations {") // declare providedRuntime config - .contains("providedRuntime") - .contains("providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')") - } - - @Test - void gradleWarPomWithoutWebFacet() { - def request = createProjectRequest('data-jpa') - request.packaging = 'war' - generateGradleBuild(request) - .contains("compile('org.springframework.boot:spring-boot-starter-data-jpa')") - .contains("compile('org.springframework.boot:spring-boot-starter-web')") // Added by war packaging - .contains("testCompile('org.springframework.boot:spring-boot-starter-test')") - .contains("configurations {") // declare providedRuntime config - .contains("providedRuntime") - .contains("providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')") - } - - @Test - void springBoot11UseEnableAutoConfigurationJava() { - def request = createProjectRequest('web') - request.bootVersion = '1.1.9.RELEASE' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/java/foo/MyDemoApplication.java') - .hasImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .doesNotHaveImports(SpringBootApplication.class.name) - .contains('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - .doesNotContain('@SpringBootApplication') - } - - @Test - void springBootUseSpringBootApplicationJava() { - def request = createProjectRequest('web') - request.bootVersion = '1.2.0.RC1' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/java/foo/MyDemoApplication.java') - .hasImports(SpringBootApplication.class.name) - .doesNotHaveImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .contains('@SpringBootApplication') - .doesNotContain('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - } - - @Test - void springBoot11UseEnableAutoConfigurationGroovy() { - def request = createProjectRequest('web') - request.language = 'groovy' - request.bootVersion = '1.1.9.RELEASE' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/groovy/foo/MyDemoApplication.groovy') - .hasImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .doesNotHaveImports(SpringBootApplication.class.name) - .contains('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - .doesNotContain('@SpringBootApplication') - } - - @Test - void springBootUseSpringBootApplicationGroovy() { - def request = createProjectRequest('web') - request.language = 'groovy' - request.bootVersion = '1.2.0.RC1' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/groovy/foo/MyDemoApplication.groovy') - .hasImports(SpringBootApplication.class.name) - .doesNotHaveImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .contains('@SpringBootApplication') - .doesNotContain('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - } - - @Test - void springBoot11UseEnableAutoConfigurationKotlin() { - def request = createProjectRequest('web') - request.language = 'kotlin' - request.bootVersion = '1.1.9.RELEASE' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/kotlin/foo/MyDemoApplication.kt') - .hasImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .doesNotHaveImports(SpringBootApplication.class.name) - .contains('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - .doesNotContain('@SpringBootApplication') - } - - @Test - void springBootUseSpringBootApplicationKotlin() { - def request = createProjectRequest('web') - request.language = 'kotlin' - request.bootVersion = '1.2.0.RC1' - request.name = 'MyDemo' - request.packageName = 'foo' - generateProject(request).sourceCodeAssert('src/main/kotlin/foo/MyDemoApplication.kt') - .hasImports(SpringBootApplication.class.name) - .doesNotHaveImports(EnableAutoConfiguration.class.name, ComponentScan.class.name, Configuration.class.name) - .contains('@SpringBootApplication') - .doesNotContain('@EnableAutoConfiguration', '@Configuration', '@ComponentScan') - } - - @Test - void springBootUseGradle2() { - def request = createProjectRequest('web') - request.type = 'gradle-project' - generateProject(request).isGradleProject('2.13') - } - - @Test - void springBoot2UseGradle3() { - def request = createProjectRequest('web') - request.type = 'gradle-project' - request.bootVersion = '2.0.0.BUILD-SNAPSHOT' - generateProject(request).isGradleProject('3.2.1') - } - - @Test - void customBaseDirectory() { - def request = createProjectRequest() - request.baseDir = 'my-project' - generateProject(request).hasBaseDir('my-project') - .isJavaProject() - .isMavenProject() - } - - @Test - void customBaseDirectoryNested() { - def request = createProjectRequest() - request.baseDir = 'foo-bar/my-project' - generateProject(request).hasBaseDir('foo-bar/my-project') - .isJavaProject() - .isMavenProject() - } - - @Test - void groovyWithMavenUsesGroovyDir() { - def request = createProjectRequest('web') - request.type = 'maven-project' - request.language = 'groovy' - generateProject(request).isMavenProject().isGroovyProject() - } - - @Test - void groovyWithGradleUsesGroovyDir() { - def request = createProjectRequest('web') - request.type = 'gradle-project' - request.language = 'groovy' - generateProject(request).isGradleProject().isGroovyProject() - } - - @Test - void mavenPomWithCustomVersion() { - def whatever = new Dependency(id: 'whatever', groupId: 'org.acme', artifactId: 'whatever', version: '1.2.3') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('foo', whatever).build() - applyMetadata(metadata) - def request = createProjectRequest('whatever', 'data-jpa', 'web') - generateMavenPom(request).hasDependency(whatever) - .hasSpringBootStarterDependency('data-jpa') - .hasSpringBootStarterDependency('web') - } - - @Test - void defaultMavenPomHasSpringBootParent() { - def request = createProjectRequest('web') - generateMavenPom(request).hasSpringBootParent(request.bootVersion) - } - - @Test - void mavenPomWithCustomParentPom() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .setMavenParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT', false) - .build() - applyMetadata(metadata) - def request = createProjectRequest('web') - generateMavenPom(request) - .hasParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT') - .hasBomsCount(0) - } - - @Test - void mavenPomWithCustomParentPomAndSpringBootBom() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .setMavenParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT', true) - .build() - applyMetadata(metadata) - def request = createProjectRequest('web') - request.bootVersion = '1.0.2.RELEASE' - generateMavenPom(request) - .hasParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT') - .hasProperty('spring-boot.version', '1.0.2.RELEASE') - .hasBom('org.springframework.boot', 'spring-boot-dependencies', '${spring-boot.version}') - .hasBomsCount(1) - } - - @Test - void gradleBuildWithCustomParentPomAndSpringBootBom() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .setMavenParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT', true) - .build() - applyMetadata(metadata) - def request = createProjectRequest('web') - request.bootVersion = '1.0.2.RELEASE' - generateGradleBuild(request) - .doesNotContain("ext['spring-boot.version'] = '1.0.2.RELEASE'") - .doesNotContain("mavenBom \"org.springframework.boot:spring-boot-dependencies:1.0.2.RELEASE\"") - } - - @Test - void gradleBuildWithBootSnapshot() { - def request = createProjectRequest('web') - request.bootVersion = '1.0.1.BUILD-SNAPSHOT' - generateGradleBuild(request).hasSnapshotRepository() - } - - @Test - void gradleBuildWithCustomVersion() { - def whatever = new Dependency(id: 'whatever', groupId: 'org.acme', artifactId: 'whatever', version: '1.2.3') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('foo', whatever).build() - applyMetadata(metadata) - def request = createProjectRequest('whatever', 'data-jpa', 'web') - generateGradleBuild(request) - .contains("compile('org.springframework.boot:spring-boot-starter-web')") - .contains("compile('org.springframework.boot:spring-boot-starter-data-jpa')") - .contains("compile('org.acme:whatever:1.2.3')") - } - - @Test - void mavenPomWithCustomScope() { - def h2 = new Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime') - def hamcrest = new Dependency(id: 'hamcrest', groupId: 'org.hamcrest', - artifactId: 'hamcrest', scope: 'test') - def servlet = new Dependency(id: 'servlet-api', groupId: 'javax.servlet', - artifactId: 'servlet-api', scope: 'provided') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('database', h2) - .addDependencyGroup('container', servlet) - .addDependencyGroup('test', hamcrest).build() - applyMetadata(metadata) - def request = createProjectRequest('hamcrest', 'h2', 'servlet-api', 'data-jpa', 'web') - generateMavenPom(request).hasDependency(h2).hasDependency(hamcrest).hasDependency(servlet) - .hasSpringBootStarterDependency('data-jpa') - .hasSpringBootStarterDependency('web') - } - - @Test - void gradleBuildWithCustomScope() { - def h2 = new Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime') - def hamcrest = new Dependency(id: 'hamcrest', groupId: 'org.hamcrest', - artifactId: 'hamcrest', scope: 'test') - def servlet = new Dependency(id: 'servlet-api', groupId: 'javax.servlet', - artifactId: 'servlet-api', scope: 'provided') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'security', 'data-jpa') - .addDependencyGroup('database', h2) - .addDependencyGroup('container', servlet) - .addDependencyGroup('test', hamcrest).build() - applyMetadata(metadata) - def request = createProjectRequest('hamcrest', 'h2', 'servlet-api', 'data-jpa', 'web') - generateGradleBuild(request) - .contains("compile('org.springframework.boot:spring-boot-starter-web')") - .contains("compile('org.springframework.boot:spring-boot-starter-data-jpa')") - .contains("runtime('org.h2:h2')") - .contains("configurations {") // declare providedRuntime config - .contains("providedRuntime") - .contains("providedRuntime('javax.servlet:servlet-api')") - .contains("testCompile('org.hamcrest:hamcrest')") - } - - @Test - void gradleBuildBeforeWithSpringBoot13() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'jpa') - .setGradleEnv('0.5.9.RELEASE').build() - applyMetadata(metadata) - def request = createProjectRequest('web') - request.bootVersion = '1.2.3.RELEASE' - generateGradleBuild(request) - .contains("springBootVersion = '1.2.3.RELEASE'") - .contains("classpath('io.spring.gradle:dependency-management-plugin:0.5.9.RELEASE')") - .contains("apply plugin: 'spring-boot'") - .contains("apply plugin: 'io.spring.dependency-management'") - } - - @Test - void gradleBuildAsFromSpringBoot13() { - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('core', 'web', 'jpa') - .setGradleEnv('0.5.9.RELEASE').build() - applyMetadata(metadata) - def request = createProjectRequest('web') - request.bootVersion = '1.3.0.BUILD-SNAPSHOT' - generateGradleBuild(request) - .contains("springBootVersion = '1.3.0.BUILD-SNAPSHOT'") - .contains("apply plugin: 'spring-boot'") - .doesNotContain("classpath('io.spring.gradle:dependency-management-plugin:0.5.9.RELEASE')") - .doesNotContain("apply plugin: 'io.spring.dependency-management'") - } - - @Test - void gradleBuildAsFromSpringBoot142() { - def request = createProjectRequest('web') - request.bootVersion = '1.4.2.BUILD-SNAPSHOT' - generateGradleBuild(request) - .contains("springBootVersion = '1.4.2.BUILD-SNAPSHOT'") - .contains("apply plugin: 'org.springframework.boot'") - .doesNotContain("apply plugin: 'spring-boot'") - } - - @Test - void mavenBom() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'foo-bom') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('foo-bom', 'org.acme', 'foo-bom', '1.2.3').build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - generateMavenPom(request).hasDependency(foo) - .hasBom('org.acme', 'foo-bom', '1.2.3') - } - - @Test - void mavenBomWithSeveralDependenciesOnSameBom() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'the-bom') - def bar = new Dependency(id: 'bar', groupId: 'org.acme', artifactId: 'bar', bom: 'the-bom') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('group', foo, bar) - .addBom('the-bom', 'org.acme', 'the-bom', '1.2.3').build() - applyMetadata(metadata) - def request = createProjectRequest('foo', 'bar') - generateMavenPom(request).hasDependency(foo) - .hasBom('org.acme', 'the-bom', '1.2.3') - .hasBomsCount(1) - } - - @Test - void mavenBomWithVersionMapping() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'the-bom') - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '1.3.0.M1', version: '1.2.0') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('the-bom', bom).build() - applyMetadata(metadata) - - // First version - def request = createProjectRequest('foo') - request.bootVersion = '1.2.5.RELEASE' - generateMavenPom(request).hasDependency(foo) - .hasSpringBootParent('1.2.5.RELEASE') - .hasBom('org.acme', 'foo-bom', '1.0.0') - - // Second version - def request2 = createProjectRequest('foo') - request2.bootVersion = '1.3.0.M1' - generateMavenPom(request2).hasDependency(foo) - .hasSpringBootParent('1.3.0.M1') - .hasBom('org.acme', 'foo-bom', '1.2.0') - } - - @Test - void mavenBomWithVersionMappingAndExtraRepositories() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'the-bom') - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom', repositories: ['foo-repo']) - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '1.3.0.M1', version: '1.2.0', repositories: ['foo-repo', 'bar-repo']) - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('the-bom', bom) - .addRepository('foo-repo', 'repo', 'http://example.com/foo', true) - .addRepository('bar-repo', 'repo', 'http://example.com/bar', false).build() - applyMetadata(metadata) - - // Second version - def request = createProjectRequest('foo') - request.bootVersion = '1.3.0.RELEASE' - generateMavenPom(request).hasDependency(foo) - .hasSpringBootParent('1.3.0.RELEASE') - .hasBom('org.acme', 'foo-bom', '1.2.0') - .hasRepository('foo-repo', 'repo', 'http://example.com/foo', true) - .hasRepository('bar-repo', 'repo', 'http://example.com/bar', false) - .hasRepositoriesCount(2) - } - - @Test - void gradleBom() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'foo-bom') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addBom('foo-bom', 'org.acme', 'foo-bom', '1.2.3').build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - generateGradleBuild(request) - .contains("dependencyManagement {") - .contains("imports {") - .contains("mavenBom \"org.acme:foo-bom:1.2.3\"") - } - - @Test - void mavenRepository() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addRepository('foo-repo', 'foo', 'http://example.com/repo', false).build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - generateMavenPom(request).hasDependency(foo) - .hasRepository('foo-repo', 'foo', 'http://example.com/repo', false) - } - - @Test - void mavenRepositoryWithSeveralDependenciesOnSameRepository() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'the-repo') - def bar = new Dependency(id: 'bar', groupId: 'org.acme', artifactId: 'bar', repository: 'the-repo') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('group', foo, bar) - .addRepository('the-repo', 'repo', 'http://example.com/repo', true).build() - applyMetadata(metadata) - def request = createProjectRequest('foo', 'bar') - generateMavenPom(request).hasDependency(foo) - .hasRepository('the-repo', 'repo', 'http://example.com/repo', true) - .hasRepositoriesCount(1) - } - - @Test - void gradleRepository() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo) - .addRepository('foo-repo', 'foo', 'http://example.com/repo', false).build() - applyMetadata(metadata) - def request = createProjectRequest('foo') - generateGradleBuild(request) - .hasRepository('http://example.com/repo') - } - - @Test - void projectWithOnlyStarterDependency() { - def foo = new Dependency(id: 'foo', groupId: 'org.foo', artifactId: 'custom-my-starter') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo).build() - applyMetadata(metadata) - - def request = createProjectRequest('foo') - generateMavenPom(request) - .hasDependency('org.foo', 'custom-my-starter') - .hasSpringBootStarterTest() - .hasDependenciesCount(2) - } - - @Test - void projectWithOnlyNonStarterDependency() { - def foo = new Dependency(id: 'foo', groupId: 'org.foo', artifactId: 'foo') - foo.starter = false - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo).build() - applyMetadata(metadata) - - def request = createProjectRequest('foo') - generateMavenPom(request) - .hasDependency('org.foo', 'foo') - .hasSpringBootStarterRootDependency() - .hasSpringBootStarterTest() - .hasDependenciesCount(3) - } - - @Test - void buildPropertiesMaven() { - def request = createProjectRequest('web') - request.buildProperties.maven['name'] = { 'test' } - request.buildProperties.versions['foo.version'] = { '1.2.3' } - request.buildProperties.gradle['ignore.property'] = { 'yes' } - - generateMavenPom(request) - .hasProperty('name', 'test') - .hasProperty('foo.version', '1.2.3') - .hasNoProperty('ignore.property') - } - - @Test - void buildPropertiesGradle() { - def request = createProjectRequest('web') - request.buildProperties.gradle['name'] = { 'test' } - request.buildProperties.versions['foo.version'] = { '1.2.3' } - request.buildProperties.maven['ignore.property'] = { 'yes' } - - generateGradleBuild(request) - .contains("name = 'test'") - .contains("ext['foo.version'] = '1.2.3'") - .doesNotContain('ignore.property') - } - - @Test - void versionRangeWithPostProcessor() { - Dependency foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo') - foo.mappings << new Dependency.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', version: '1.0.0') - foo.mappings << new Dependency.Mapping(versionRange: '1.3.0.M1', version: '1.2.0') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('foo', foo).build() - applyMetadata(metadata) - - // First without processor, get the correct version - def request = createProjectRequest('foo') - request.bootVersion = '1.2.5.RELEASE' - generateMavenPom(request).hasDependency( - new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', version: '1.0.0')) - - // First after processor that flips Spring Boot version - projectGenerator.requestResolver = new ProjectRequestResolver(Collections.singletonList( - new ProjectRequestPostProcessorAdapter() { - @Override - void postProcessBeforeResolution(ProjectRequest r, InitializrMetadata m) { - r.bootVersion = '1.3.0.M2' - } - } - )) - generateMavenPom(request).hasDependency( - new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', version: '1.2.0')) - } - - @Test - void gitIgnoreMaven() { - def request = createProjectRequest() - request.type = 'maven-project' - def project = generateProject(request) - project.sourceCodeAssert(".gitignore") - .equalsTo(new ClassPathResource("project/maven/gitignore.gen")) - } - - @Test - void gitIgnoreGradle() { - def request = createProjectRequest() - request.type = 'gradle-project' - def project = generateProject(request) - project.sourceCodeAssert(".gitignore") - .equalsTo(new ClassPathResource("project/gradle/gitignore.gen")) - } - - @Test - void invalidProjectTypeMavenPom() { - def request = createProjectRequest('web') - request.type = 'gradle-build' - this.thrown.expect(InvalidProjectRequestException) - this.thrown.expectMessage('gradle-build') - projectGenerator.generateMavenPom(request) - } - - @Test - void invalidProjectTypeGradleBuild() { - def request = createProjectRequest('web') - request.type = 'maven-build' - this.thrown.expect(InvalidProjectRequestException) - this.thrown.expectMessage('maven-build') - projectGenerator.generateGradleBuild(request) - } - - @Test - void invalidDependency() { - def request = createProjectRequest('foo-bar') - try { - generateMavenPom(request) - fail("Should have failed to generate project") - } catch (InvalidProjectRequestException ex) { - assertThat ex.message, containsString('foo-bar') - verifyProjectFailedEventFor(request, ex) - } - } - - @Test - void invalidType() { - def request = createProjectRequest('web') - request.type = 'foo-bar' - try { - generateProject(request) - fail("Should have failed to generate project") - } catch (InvalidProjectRequestException ex) { - assertThat ex.message, containsString('foo-bar') - verifyProjectFailedEventFor(request, ex) - } - } - - @Test - void invalidPackaging() { - def request = createProjectRequest('web') - request.packaging = 'foo-bar' - try { - generateGradleBuild(request) - fail("Should have failed to generate project") - } catch (InvalidProjectRequestException ex) { - assertThat ex.message, containsString('foo-bar') - verifyProjectFailedEventFor(request, ex) - } - } - - @Test - void invalidLanguage() { - def request = createProjectRequest('web') - request.language = 'foo-bar' - try { - generateProject(request) - fail("Should have failed to generate project") - } catch (InvalidProjectRequestException ex) { - assertThat ex.message, containsString('foo-bar') - verifyProjectFailedEventFor(request, ex) - } - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestResolverTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestResolverTests.groovy deleted file mode 100644 index 1a6be5b1..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestResolverTests.groovy +++ /dev/null @@ -1,86 +0,0 @@ -package io.spring.initializr.generator - -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import org.junit.Before -import org.junit.Test - -import static org.junit.Assert.assertEquals - -/** - * Tests for {@link ProjectRequestResolver}. - * - * @author Stephane Nicoll - */ -class ProjectRequestResolverTests { - - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('test', 'web', 'security', 'data-jpa') - .build() - - final List postProcessors = [] - final GenericProjectRequestPostProcessor processor = new GenericProjectRequestPostProcessor() - - @Before - void setup() { - this.postProcessors << processor - } - - @Test - void beforeResolution() { - processor.before['javaVersion'] = '1.2' - ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors) - assertEquals '1.2', request.javaVersion - assertEquals '1.2', request.buildProperties.versions['java.version'].call() - } - - @Test - void afterResolution() { - postProcessors << new ProjectRequestPostProcessorAdapter() { - @Override - void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { - request.buildProperties.maven.clear() - request.buildProperties.maven['foo'] = { 'bar' } - } - } - ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors) - assertEquals 1, request.buildProperties.maven.size() - assertEquals 'bar', request.buildProperties.maven['foo'].call() - } - - ProjectRequest resolve(def request, def processors) { - new ProjectRequestResolver(processors) - .resolve(request, metadata) - } - - ProjectRequest createMavenProjectRequest(String... styles) { - def request = createProjectRequest(styles) - request.type = 'maven-project' - request - } - - ProjectRequest createProjectRequest(String... styles) { - def request = new ProjectRequest() - request.initialize(metadata) - request.style.addAll Arrays.asList(styles) - request - } - - static class GenericProjectRequestPostProcessor implements ProjectRequestPostProcessor { - - final Map before = [:] - final Map after = [:] - - @Override - void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { - before.forEach { k, v -> request.setProperty(k, v) } - } - - @Override - void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { - after.forEach { k, v -> request.setProperty(k, v) } - } - - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy deleted file mode 100644 index 55f7779a..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.generator - -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrMetadataBuilder -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNull - -/** - * @author Stephane Nicoll - */ -class ProjectRequestTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void initializeProjectRequest() { - def metadata = InitializrMetadataBuilder.create().build() - metadata.groupId.content = 'org.acme' - metadata.artifactId.content = 'my-project' - ProjectRequest request = new ProjectRequest() - request.initialize(metadata) - assertEquals 'org.acme', request.groupId - assertEquals 'my-project', request.artifactId - } - - @Test - void initializeProjectRequestWithDefaults() { - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - ProjectRequest request = new ProjectRequest() - request.initialize(metadata) - assertEquals metadata.name.content, request.name - assertEquals metadata.types.default.id, request.type - assertEquals metadata.description.content, request.description - assertEquals metadata.groupId.content, request.groupId - assertEquals metadata.artifactId.content, request.artifactId - assertEquals metadata.version.content, request.version - assertEquals metadata.bootVersions.default.id, request.bootVersion - assertEquals metadata.packagings.default.id, request.packaging - } - - @Test - void resolve() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', 'web', 'security', 'spring-data').build() - - request.type = 'maven-project' - request.style << 'web' << 'spring-data' - request.resolve(metadata) - assertEquals 'Build type not detected', 'maven', request.build - assertBootStarter(request.resolvedDependencies[0], 'web') - assertBootStarter(request.resolvedDependencies[1], 'spring-data') - } - - @Test - void resolveWithDependencies() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', 'web', 'security', 'spring-data').build() - - request.type = 'maven-project' - request.dependencies << 'web' << 'spring-data' - request.resolve(metadata) - assertEquals 'Build type not detected', 'maven', request.build - assertBootStarter(request.resolvedDependencies[0], 'web') - assertBootStarter(request.resolvedDependencies[1], 'spring-data') - } - - @Test - void resolveFullMetadata() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', createDependency('org.foo', 'acme', '1.2.0')).build() - request.style << 'org.foo:acme' - request.resolve(metadata) - assertDependency(request.resolvedDependencies[0], 'org.foo', 'acme', '1.2.0') - } - - @Test - void resolveUnknownSimpleId() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', 'org.foo:bar').build() - - request.style << 'org.foo:bar' << 'foo-bar' - - thrown.expect(InvalidProjectRequestException) - thrown.expectMessage('foo-bar') - request.resolve(metadata) - assertEquals(1, request.resolvedDependencies.size()) - } - - @Test - void resolveUnknownDependency() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', 'org.foo:bar').build() - - request.style << 'org.foo:acme' // does not exist - - thrown.expect(InvalidProjectRequestException) - thrown.expectMessage('org.foo:acme') - request.resolve(metadata) - assertEquals(1, request.resolvedDependencies.size()) - } - - @Test - void resolveDependencyInRange() { - def request = new ProjectRequest() - def dependency = createDependency('org.foo', 'bar', '1.2.0.RELEASE') - dependency.versionRange = '[1.0.1.RELEASE, 1.2.0.RELEASE)' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', dependency).build() - - request.style << 'org.foo:bar' - request.bootVersion = '1.1.2.RELEASE' - request.resolve(metadata) - } - - @Test - void resolveDependencyNotInRange() { - def request = new ProjectRequest() - def dependency = createDependency('org.foo', 'bar', '1.2.0.RELEASE') - dependency.versionRange = '[1.0.1.RELEASE, 1.2.0.RELEASE)' - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', dependency).build() - - request.style << 'org.foo:bar' - request.bootVersion = '0.9.9.RELEASE' - - thrown.expect(InvalidProjectRequestException) - thrown.expectMessage('org.foo:bar') - thrown.expectMessage('0.9.9.RELEASE') - request.resolve(metadata) - } - - @Test - void resolveDependencyVersion() { - def dependency = createDependency('org.foo', 'bar', '1.2.0.RELEASE') - dependency.mappings << new Dependency.Mapping( - version: '0.1.0.RELEASE', versionRange: '[1.0.0.RELEASE, 1.1.0.RELEASE)') - dependency.mappings << new Dependency.Mapping( - version: '0.2.0.RELEASE', versionRange: '1.1.0.RELEASE') - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addDependencyGroup('code', dependency).build() - - def request = new ProjectRequest() - request.bootVersion = '1.0.5.RELEASE' - request.style << 'org.foo:bar' - request.resolve(metadata) - assertDependency(request.resolvedDependencies[0], 'org.foo', 'bar', '0.1.0.RELEASE') - - def anotherRequest = new ProjectRequest() - anotherRequest.bootVersion = '1.1.0.RELEASE' - anotherRequest.style << 'org.foo:bar' - anotherRequest.resolve(metadata) - assertDependency(anotherRequest.resolvedDependencies[0], 'org.foo', 'bar', '0.2.0.RELEASE') - } - - @Test - void resolveBuild() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - request.type = 'gradle-project' - - request.resolve(metadata) - assertEquals 'gradle', request.build - } - - @Test - void resolveBuildNoTag() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults() - .addType('foo', false, '/foo.zip', null, null).build() - request.type = 'foo' - - request.resolve(metadata) - assertNull request.build - } - - @Test - void resolveUnknownType() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - request.type = 'foo-project' - - thrown.expect(InvalidProjectRequestException) - thrown.expectMessage('foo-project') - request.resolve(metadata) - } - - @Test - void resolveApplicationNameWithNoName() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - - request.resolve(metadata) - assertEquals metadata.configuration.env.fallbackApplicationName, request.applicationName - } - - @Test - void resolveApplicationName() { - def request = new ProjectRequest() - request.name = 'Foo2' - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - - request.resolve(metadata) - assertEquals 'Foo2Application', request.applicationName - } - - @Test - void resolveApplicationNameWithApplicationNameSet() { - def request = new ProjectRequest() - request.name = 'Foo2' - request.applicationName = 'MyApplicationName' - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - - request.resolve(metadata) - assertEquals 'MyApplicationName', request.applicationName - } - - @Test - void cleanPackageNameWithNoName() { - def request = new ProjectRequest() - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - - request.resolve(metadata) - assertEquals metadata.packageName.content, request.packageName - } - - @Test - void cleanPackageName() { - def request = new ProjectRequest() - request.packageName = 'com:foo bar' - def metadata = InitializrMetadataTestBuilder.withDefaults().build() - - request.resolve(metadata) - assertEquals 'com.foo.bar', request.packageName - } - - @Test - void resolveAdditionalBoms() { - def request = new ProjectRequest() - def dependency = new Dependency(id: 'foo', bom: 'foo-bom') - def bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'foo-bom', - version: '1.0.0', additionalBoms: ['bar-bom']) - def additionalBom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bar-bom', version: '1.1.0') - def metadata = InitializrMetadataTestBuilder - .withDefaults() - .addBom('foo-bom', bom) - .addBom('bar-bom', additionalBom) - .addDependencyGroup('test', dependency) - .build() - request.style << 'foo' - request.resolve(metadata) - assertEquals(1, request.resolvedDependencies.size()) - assertEquals 2, request.boms.size() - assertEquals bom, request.boms['foo-bom'] - assertEquals additionalBom, request.boms['bar-bom'] - } - - @Test - void resolveAdditionalBomsDuplicates() { - def request = new ProjectRequest() - def dependency = new Dependency(id: 'foo', bom: 'foo-bom') - def anotherDependency = new Dependency(id: 'bar', bom: 'bar-bom') - def bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'foo-bom', - version: '1.0.0', additionalBoms: ['bar-bom']) - def additionalBom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bar-bom', version: '1.1.0') - def metadata = InitializrMetadataTestBuilder - .withDefaults() - .addBom('foo-bom', bom) - .addBom('bar-bom', additionalBom) - .addDependencyGroup('test', dependency, anotherDependency) - .build() - request.style << 'foo' << 'bar' - request.resolve(metadata) - assertEquals(2, request.resolvedDependencies.size()) - assertEquals 2, request.boms.size() - assertEquals bom, request.boms['foo-bom'] - assertEquals additionalBom, request.boms['bar-bom'] - } - - @Test - void resolveAdditionalRepositories() { - def request = new ProjectRequest() - def dependency = new Dependency(id: 'foo', bom: 'foo-bom', repository: 'foo-repo') - def bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'foo-bom', - version: '1.0.0', repositories: ['bar-repo']) - def metadata = InitializrMetadataTestBuilder - .withDefaults() - .addBom('foo-bom', bom) - .addRepository('foo-repo', 'foo-repo', 'http://example.com/foo', false) - .addRepository('bar-repo', 'bar-repo', 'http://example.com/bar', false) - .addDependencyGroup('test', dependency) - .build() - request.style << 'foo' - request.resolve(metadata) - assertEquals(1, request.resolvedDependencies.size()) - assertEquals 1, request.boms.size() - assertEquals 2, request.repositories.size() - assertEquals metadata.configuration.env.repositories['foo-repo'], - request.repositories['foo-repo'] - assertEquals metadata.configuration.env.repositories['bar-repo'], - request.repositories['bar-repo'] - } - - @Test - void resolveAdditionalRepositoriesDuplicates() { - def request = new ProjectRequest() - def dependency = new Dependency(id: 'foo', bom: 'foo-bom', repository: 'foo-repo') - def anotherDependency = new Dependency(id: 'bar', repository: 'bar-repo') - def bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'foo-bom', - version: '1.0.0', repositories: ['bar-repo']) - def metadata = InitializrMetadataTestBuilder - .withDefaults() - .addBom('foo-bom', bom) - .addRepository('foo-repo', 'foo-repo', 'http://example.com/foo', false) - .addRepository('bar-repo', 'bar-repo', 'http://example.com/bar', false) - .addDependencyGroup('test', dependency, anotherDependency) - .build() - request.style << 'foo' << 'bar' - request.resolve(metadata) - assertEquals(2, request.resolvedDependencies.size()) - assertEquals 1, request.boms.size() - assertEquals 2, request.repositories.size() - assertEquals metadata.configuration.env.repositories['foo-repo'], - request.repositories['foo-repo'] - assertEquals metadata.configuration.env.repositories['bar-repo'], - request.repositories['bar-repo'] - } - - private static void assertBootStarter(Dependency actual, String name) { - def expected = new Dependency() - expected.asSpringBootStarter(name) - assertDependency(actual, expected.groupId, expected.artifactId, expected.version) - assertEquals name, actual.id - } - - private static Dependency createDependency(String groupId, String artifactId, String version) { - new Dependency(groupId: groupId, artifactId: artifactId, version: version) - } - - private static void assertDependency(Dependency actual, String groupId, - String artifactId, String version) { - assertEquals groupId, actual.groupId - assertEquals artifactId, actual.artifactId - assertEquals version, actual.version - } -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/BillOfMaterialsTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/BillOfMaterialsTests.groovy deleted file mode 100644 index b8b025fc..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/BillOfMaterialsTests.groovy +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.metadata - -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionParser -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.hamcrest.CoreMatchers.equalTo -import static org.hamcrest.CoreMatchers.nullValue -import static org.hamcrest.CoreMatchers.sameInstance -import static org.junit.Assert.assertThat - -/** - * @author Stephane Nicoll - */ -class BillOfMaterialsTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void resolveSimpleBom() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bom', version: '1.0.0') - bom.validate() - BillOfMaterials resolved = bom.resolve(Version.parse('1.2.3.RELEASE')) - assertThat(bom, sameInstance(resolved)) - } - - @Test - void resolveSimpleRange() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'bom', - version: '1.0.0', versionProperty: "bom.version", - repositories: ['repo-main'], additionalBoms: ['bom-main']) - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', - version: '1.1.0') - bom.validate() - BillOfMaterials resolved = bom.resolve(Version.parse('1.2.3.RELEASE')) - assertThat(resolved.groupId, equalTo('com.example')) - assertThat(resolved.artifactId, equalTo('bom')) - assertThat(resolved.version, equalTo('1.1.0')) - assertThat(resolved.versionProperty, equalTo('bom.version')) - assertThat(resolved.repositories.size(), equalTo(1)) - assertThat(resolved.repositories[0], equalTo('repo-main')) - assertThat(resolved.additionalBoms.size(), equalTo(1)) - assertThat(resolved.additionalBoms[0], equalTo('bom-main')) - } - - @Test - void resolveRangeOverride() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bom', version: '1.0.0', repositories: ['repo-main'], additionalBoms: ['bom-main']) - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', - version: '1.1.0', repositories: ['repo-foo'], additionalBoms: ['bom-foo']) - bom.validate() - BillOfMaterials resolved = bom.resolve(Version.parse('1.2.3.RELEASE')) - assertThat(resolved.groupId, equalTo('com.example')) - assertThat(resolved.artifactId, equalTo('bom')) - assertThat(resolved.version, equalTo('1.1.0')) - assertThat(resolved.versionProperty, nullValue()) - assertThat(resolved.repositories.size(), equalTo(1)) - assertThat(resolved.repositories[0], equalTo('repo-foo')) - assertThat(resolved.additionalBoms.size(), equalTo(1)) - assertThat(resolved.additionalBoms[0], equalTo('bom-foo')) - } - - @Test - void resolveRangeOverrideAndMapping() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bom', version: '1.0.0', versionProperty: 'example.version') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', - version: '1.1.0') - bom.validate() - BillOfMaterials resolved = bom.resolve(Version.parse('1.2.3.RELEASE')) - assertThat(resolved.groupId, equalTo('com.example')) - assertThat(resolved.artifactId, equalTo('bom')) - assertThat(resolved.version, equalTo('1.1.0')) - assertThat(resolved.versionProperty, equalTo('example.version')) - } - - @Test - void noRangeAvailable() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', - version: '1.1.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.3.0.M1,1.4.0.M1)', - version: '1.2.0') - bom.validate() - - thrown.expect(IllegalStateException) - thrown.expectMessage('1.4.1.RELEASE') - bom.resolve(Version.parse('1.4.1.RELEASE')) - } - - @Test - void resolveRangeWithVariablePatch() { - BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', - artifactId: 'bom', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping( - versionRange: '[1.3.0.RELEASE,1.3.x.RELEASE]', version: '1.1.0') - bom.mappings << new BillOfMaterials.Mapping( - versionRange: '[1.3.x.BUILD-SNAPSHOT,1.4.0.RELEASE)', version: '1.1.1-SNAPSHOT') - bom.validate() - - bom.updateVersionRange(new VersionParser(Arrays.asList( - Version.parse("1.3.8.RELEASE"), Version.parse("1.3.9.BUILD-SNAPSHOT")))) - assertThat(bom.resolve(Version.parse('1.3.8.RELEASE')).version, equalTo('1.1.0')) - assertThat(bom.resolve(Version.parse('1.3.9.RELEASE')).version, equalTo('1.1.1-SNAPSHOT')) - - bom.updateVersionRange(new VersionParser(Arrays.asList( - Version.parse("1.3.9.RELEASE"), Version.parse("1.3.10.BUILD-SNAPSHOT")))) - assertThat(bom.resolve(Version.parse('1.3.8.RELEASE')).version, equalTo('1.1.0')) - assertThat(bom.resolve(Version.parse('1.3.9.RELEASE')).version, equalTo('1.1.0')) - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependenciesCapabilityTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependenciesCapabilityTests.groovy deleted file mode 100644 index 79ec51f9..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependenciesCapabilityTests.groovy +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.metadata - -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNotNull -import static org.junit.Assert.assertNull -import static org.junit.Assert.assertSame - -/** - * @author Stephane Nicoll - */ -class DependenciesCapabilityTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void indexedDependencies() { - def dependency = new Dependency(id: 'first') - def dependency2 = new Dependency(id: 'second') - def capability = createDependenciesCapability('foo', dependency, dependency2) - capability.validate() - - assertSame dependency, capability.get('first') - assertSame dependency2, capability.get('second') - assertNull capability.get('anotherId') - } - - @Test - void addTwoDependenciesWithSameId() { - def dependency = new Dependency(id: 'conflict') - def dependency2 = new Dependency(id: 'conflict') - def capability = createDependenciesCapability('foo', dependency, dependency2) - - thrown.expect(IllegalArgumentException) - thrown.expectMessage('conflict') - capability.validate() - } - - @Test - void addDependencyWithAliases() { - def dependency = new Dependency(id: 'first') - dependency.aliases.add('alias1') - dependency.aliases.add('alias2') - def capability = createDependenciesCapability('foo', dependency) - capability.validate() - - assertSame dependency, capability.get('first') - assertSame dependency, capability.get('alias1') - assertSame dependency, capability.get('alias2') - } - - @Test - void aliasClashWithAnotherDependency() { - def dependency = new Dependency(id: 'first') - dependency.aliases.add('alias1') - dependency.aliases.add('alias2') - def dependency2 = new Dependency(id: 'alias2') - - def capability = new DependenciesCapability() - capability.content << createDependencyGroup('foo', dependency) - capability.content << createDependencyGroup('bar', dependency2) - - thrown.expect(IllegalArgumentException) - thrown.expectMessage('alias2') - capability.validate() - } - - @Test - void mergeAddEntry() { - DependenciesCapability capability = createDependenciesCapability('foo', - new Dependency(id: 'first'), new Dependency(id: 'second')) - - DependenciesCapability anotherCapability = createDependenciesCapability('foo', - new Dependency(id: 'bar'), new Dependency(id: 'biz')) - anotherCapability.content << createDependencyGroup('bar', new Dependency(id: 'third')) - - capability.merge(anotherCapability) - assertEquals 2, capability.content.size() - assertNotNull capability.get('first') - assertNotNull capability.get('second') - assertNotNull capability.get('third') - } - - @Test - void addDefaultVersionRange() { - def first = new Dependency(id: 'first') - def second = new Dependency(id: 'second', versionRange: '1.2.3.RELEASE') - def group = createDependencyGroup('test', first, second) - group.versionRange = '1.2.0.RELEASE' - - DependenciesCapability capability = new DependenciesCapability() - capability.content << group - capability.validate() - - assertEquals '1.2.0.RELEASE', capability.get('first').versionRange - assertEquals '1.2.3.RELEASE', capability.get('second').versionRange - } - - @Test - void addDefaultBom() { - def first = new Dependency(id: 'first') - def second = new Dependency(id: 'second', bom: 'da-bom') - def group = createDependencyGroup('test', first, second) - group.bom = 'test-bom' - - DependenciesCapability capability = new DependenciesCapability() - capability.content << group - capability.validate() - - assertEquals 'test-bom', capability.get('first').bom - assertEquals 'da-bom', capability.get('second').bom - } - - @Test - void addDefaultRepository() { - def first = new Dependency(id: 'first') - def second = new Dependency(id: 'second', repository: 'da-repo') - def group = createDependencyGroup('test', first, second) - group.repository = 'test-repo' - - DependenciesCapability capability = new DependenciesCapability() - capability.content << group - capability.validate() - - assertEquals 'test-repo', capability.get('first').repository - assertEquals 'da-repo', capability.get('second').repository - } - - - private static DependenciesCapability createDependenciesCapability(String groupName, Dependency... dependencies) { - DependenciesCapability capability = new DependenciesCapability() - DependencyGroup group = createDependencyGroup(groupName, dependencies) - capability.content << group - capability - } - - private static DependencyGroup createDependencyGroup(String groupName, Dependency... dependencies) { - DependencyGroup group = new DependencyGroup(name: groupName) - for (Dependency dependency : dependencies) { - group.content << dependency - } - group - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependencyTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependencyTests.groovy deleted file mode 100644 index ee521a11..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/DependencyTests.groovy +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import io.spring.initializr.util.Version -import io.spring.initializr.util.VersionParser -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNull -import static org.junit.Assert.assertSame - -/** - * @author Stephane Nicoll - */ -class DependencyTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void createRootSpringBootStarter() { - Dependency d = new Dependency(); - d.asSpringBootStarter("") - assertEquals 'org.springframework.boot', d.groupId - assertEquals 'spring-boot-starter', d.artifactId - } - - @Test - void setCoordinatesFromId() { - def dependency = new Dependency(id: 'org.foo:bar:1.2.3') - dependency.resolve() - assertEquals 'org.foo', dependency.groupId - assertEquals 'bar', dependency.artifactId - assertEquals '1.2.3', dependency.version - assertEquals 'org.foo:bar:1.2.3', dependency.id - } - - @Test - void setCoordinatesFromIdNoVersion() { - def dependency = new Dependency(id: 'org.foo:bar') - dependency.resolve() - assertEquals 'org.foo', dependency.groupId - assertEquals 'bar', dependency.artifactId - assertNull dependency.version - assertEquals 'org.foo:bar', dependency.id - } - - @Test - void setIdFromCoordinates() { - def dependency = new Dependency() - dependency.groupId = 'org.foo' - dependency.artifactId = 'bar' - dependency.version = '1.0' - dependency.resolve() - assertEquals 'org.foo:bar', dependency.id - } - - @Test - void setIdFromCoordinatesNoVersion() { - def dependency = new Dependency() - dependency.groupId = 'org.foo' - dependency.artifactId = 'bar' - dependency.resolve() - assertEquals 'org.foo:bar', dependency.id - } - - @Test - void setIdFromSimpleName() { - def dependency = new Dependency(id: 'web') - dependency.resolve() - assertEquals 'org.springframework.boot', dependency.groupId - assertEquals 'spring-boot-starter-web', dependency.artifactId - assertNull dependency.version - assertEquals 'web', dependency.id - } - - @Test - void invalidDependency() { - thrown.expect(InvalidInitializrMetadataException) - new Dependency().resolve() - } - - @Test - void invalidDependencyScope() { - def dependency = new Dependency(id: 'web') - - thrown.expect(InvalidInitializrMetadataException) - dependency.setScope('whatever') - } - - @Test - void invalidSpringBootRange() { - def dependency = new Dependency(id: 'web') - dependency.versionRange = 'A.B.C' - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage('A.B.C') - dependency.resolve() - } - - @Test - void invalidIdFormatTooManyColons() { - def dependency = new Dependency(id: 'org.foo:bar:1.0:test:external') - - thrown.expect(InvalidInitializrMetadataException) - dependency.resolve() - } - - @Test - void invalidLink() { - def dependency = new Dependency(id : 'foo') - dependency.links << new Link(href: 'https://example.com') - - thrown.expect(InvalidInitializrMetadataException) - dependency.resolve() - } - - @Test - void generateIdWithNoGroupId() { - def dependency = new Dependency() - dependency.artifactId = 'bar' - thrown.expect(IllegalArgumentException) - dependency.generateId() - } - - @Test - void generateIdWithNoArtifactId() { - def dependency = new Dependency() - dependency.groupId = 'foo' - thrown.expect(IllegalArgumentException) - dependency.generateId() - } - - @Test - void resolveNoMapping() { - def dependency = new Dependency(id: 'web') - dependency.resolve() - assertSame dependency, dependency.resolve(Version.parse('1.2.0.RELEASE')) - } - - @Test - void resolveInvalidMapping() { - def dependency = new Dependency(id: 'web') - dependency.mappings << new Dependency.Mapping( - versionRange: 'foo-bar', version: '0.1.0.RELEASE') - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage('foo-bar') - dependency.resolve() - } - - @Test - void resolveVersionRequirement() { - def dependency = new Dependency(id: 'web') - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.1.0.RELEASE, 1.2.0.RELEASE)', version: '0.1.0.RELEASE') - dependency.resolve() - def resolved = dependency.resolve(Version.parse('1.1.5.RELEASE')) - assertEquals ">=1.1.0.RELEASE and <1.2.0.RELEASE", resolved.versionRequirement - } - - @Test - void resolveMatchingVersionMapping() { - def dependency = new Dependency(id: 'web', description: 'A web dependency', version: '0.3.0.RELEASE', - keywords: ['foo', 'bar'], aliases: ['the-web'], facets: ['web']) - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.1.0.RELEASE, 1.2.0.RELEASE)', version: '0.1.0.RELEASE') - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.2.0.RELEASE, 1.3.0.RELEASE)', version: '0.2.0.RELEASE') - dependency.resolve() - - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.5.RELEASE')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.1.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('1.2.0.RELEASE')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.2.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('2.1.3.M1')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.3.0.RELEASE') // default - } - - @Test - void resolveMatchArtifactMapping() { - def dependency = new Dependency(id: 'web', description: 'A web dependency', version: '0.3.0.RELEASE', - keywords: ['foo', 'bar'], aliases: ['the-web'], facets: ['web']) - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.1.0.RELEASE, 1.2.0.RELEASE)', groupId: 'org.spring.boot') - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.2.0.RELEASE, 1.3.0.RELEASE)', artifactId: 'starter-web') - dependency.resolve() - - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.5.RELEASE')), - 'org.spring.boot', 'spring-boot-starter-web', '0.3.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('1.2.0.RELEASE')), - 'org.springframework.boot', 'starter-web', '0.3.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('2.1.3.M1')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.3.0.RELEASE') // default - } - - @Test - void resolveMatchingVersionWithVariablePatch() { - def dependency = new Dependency(id: 'web', description: 'A web dependency', version: '0.3.0.RELEASE', - keywords: ['foo', 'bar'], aliases: ['the-web'], facets: ['web']) - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.1.0.RELEASE, 1.1.x.RELEASE]', version: '0.1.0.RELEASE') - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.1.x.BUILD-SNAPSHOT, 1.2.0.RELEASE)', version: '0.2.0.RELEASE') - dependency.resolve() - - dependency.updateVersionRanges(new VersionParser(Arrays.asList( - Version.parse("1.1.5.RELEASE"), Version.parse("1.1.6.BUILD-SNAPSHOT")))) - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.5.RELEASE')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.1.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.6.BUILD-SNAPSHOT')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.2.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('2.1.3.M1')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.3.0.RELEASE') // default - - dependency.updateVersionRanges(new VersionParser(Arrays.asList( - Version.parse("1.1.6.RELEASE"), Version.parse("1.1.7.BUILD-SNAPSHOT")))) - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.5.RELEASE')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.1.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.6.RELEASE')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.1.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('1.1.7.BUILD-SNAPSHOT')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.2.0.RELEASE') - validateResolvedWebDependency(dependency.resolve(Version.parse('2.1.3.M1')), - 'org.springframework.boot', 'spring-boot-starter-web', '0.3.0.RELEASE') // default - } - - static void validateResolvedWebDependency( - def dependency, def expectedGroupId, def expectedArtifactId, def expectedVersion) { - assertEquals expectedVersion, dependency.version - assertEquals 'web', dependency.id - assertEquals expectedGroupId, dependency.groupId - assertEquals expectedArtifactId, dependency.artifactId - assertEquals 2, dependency.keywords.size() - assertEquals 1, dependency.aliases.size() - assertEquals 1, dependency.facets.size() - - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy deleted file mode 100644 index dca1d5b0..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Test - -import static org.junit.Assert.assertEquals - -/** - * @author Stephane Nicoll - */ -class InitializrConfigurationTests { - - private final InitializrConfiguration properties = new InitializrConfiguration() - - @Test - void generateApplicationNameSimple() { - assertEquals 'DemoApplication', this.properties.generateApplicationName('demo') - } - - @Test - void generateApplicationNameSimpleApplication() { - assertEquals 'DemoApplication', this.properties.generateApplicationName('demoApplication') - } - - @Test - void generateApplicationNameSimpleCamelCase() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('myDemo') - } - - @Test - void generateApplicationNameSimpleUnderscore() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my_demo') - } - - @Test - void generateApplicationNameSimpleColon() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my:demo') - } - - @Test - void generateApplicationNameSimpleSpace() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my demo') - } - - @Test - void generateApplicationNamSimpleDash() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my-demo') - } - - @Test - void generateApplicationNameUpperCaseUnderscore() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('MY_DEMO') - } - - @Test - void generateApplicationNameUpperCaseDash() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName('MY-DEMO') - } - - @Test - void generateApplicationNameMultiSpaces() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName(' my demo ') - } - - @Test - void generateApplicationNameMultiSpacesUpperCase() { - assertEquals 'MyDemoApplication', this.properties.generateApplicationName(' MY DEMO ') - } - - @Test - void generateApplicationNameNull() { - assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName(null) - } - - @Test - void generateApplicationNameInvalidStartCharacter() { - assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('1MyDemo') - } - - @Test - void generateApplicationNameInvalidPartCharacter() { - assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('MyDe|mo') - } - - @Test - void generateApplicationNameInvalidApplicationName() { - assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('SpringBoot') - } - - @Test - void generateApplicationNameAnotherInvalidApplicationName() { - assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('Spring') - } - - @Test - void generatePackageNameSimple() { - assertEquals 'com.foo', this.properties.cleanPackageName('com.foo', 'com.example') - } - - @Test - void generatePackageNameSimpleUnderscore() { - assertEquals 'com.my_foo', this.properties.cleanPackageName('com.my_foo', 'com.example') - } - - @Test - void generatePackageNameSimpleColon() { - assertEquals 'com.foo', this.properties.cleanPackageName('com:foo', 'com.example') - } - - @Test - void generatePackageNameMultipleDashers() { - assertEquals 'com.foo', this.properties.cleanPackageName('com--foo', 'com.example') - } - - @Test - void generatePackageNameMultipleSpaces() { - assertEquals 'com.foo', this.properties.cleanPackageName(' com foo ', 'com.example') - } - - @Test - void generatePackageNameNull() { - assertEquals 'com.example', this.properties.cleanPackageName(null, 'com.example') - } - - @Test - void generatePackageNameInvalidStartCharacter() { - assertEquals 'com.example', this.properties.cleanPackageName('0om.foo', 'com.example') - } - - @Test - void generatePackageNameInvalidPackageName() { - assertEquals 'com.example', this.properties.cleanPackageName('org.springframework', 'com.example') - } - - @Test - void validateArtifactRepository() { - this.properties.env.artifactRepository = 'http://foo/bar' - assertEquals 'http://foo/bar/', this.properties.env.artifactRepository - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataBuilderTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataBuilderTests.groovy deleted file mode 100644 index f526bae4..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataBuilderTests.groovy +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Test - -import org.springframework.beans.factory.config.YamlPropertiesFactoryBean -import org.springframework.boot.bind.PropertiesConfigurationFactory -import org.springframework.core.env.MutablePropertySources -import org.springframework.core.env.PropertiesPropertySource -import org.springframework.core.env.PropertySources -import org.springframework.core.io.ClassPathResource -import org.springframework.core.io.Resource - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNotNull - -/** - * @author Stephane Nicoll - */ -class InitializrMetadataBuilderTests { - - @Test - void loadDefaultConfig() { - def bean = load(new ClassPathResource("application-test-default.yml")) - def metadata = InitializrMetadataBuilder.fromInitializrProperties(bean).build() - assertDefaultConfig(metadata) - } - - @Test - void mergeIdenticalConfig() { - def bean = load(new ClassPathResource("application-test-default.yml")) - def metadata = InitializrMetadataBuilder - .fromInitializrProperties(bean) - .withInitializrProperties(bean, true).build() - assertDefaultConfig(metadata) - } - - @Test - void mergeConfig() { - def config = load(new ClassPathResource("application-test-default.yml")) - def customDefaultsConfig = load(new ClassPathResource("application-test-custom-defaults.yml")) - def metadata = InitializrMetadataBuilder - .fromInitializrProperties(config) - .withInitializrProperties(customDefaultsConfig).build() - assertDefaultConfig(metadata) - assertEquals 'org.foo', metadata.groupId.content - assertEquals 'foo-bar', metadata.artifactId.content - assertEquals '1.2.4-SNAPSHOT', metadata.version.content - assertEquals 'FooBar', metadata.name.content - assertEquals 'FooBar Project', metadata.description.content - assertEquals 'org.foo.demo', metadata.packageName.content - } - - @Test - void mergeMetadata() { - def metadata = InitializrMetadataBuilder.create().withInitializrMetadata( - new ClassPathResource('metadata/config/test-min.json')).build() - assertEquals false, metadata.configuration.env.forceSsl - assertEquals 1, metadata.dependencies.content.size() - Dependency dependency = metadata.dependencies.get('test') - assertNotNull dependency - assertEquals 'org.springframework.boot', dependency.groupId - assertEquals 1, metadata.types.content.size() - assertEquals 2, metadata.bootVersions.content.size() - assertEquals 2, metadata.packagings.content.size() - assertEquals 1, metadata.javaVersions.content.size() - assertEquals 3, metadata.languages.content.size() - assertEquals 'metadata-merge', metadata.name.content - assertEquals 'Demo project for metadata merge', metadata.description.content - assertEquals 'org.acme', metadata.groupId.content - assertEquals 'metadata', metadata.artifactId.content - assertEquals '1.0.0-SNAPSHOT', metadata.version.content - assertEquals 'org.acme.demo', metadata.packageName.content - } - - @Test - void mergeMetadataWithBom() { - def metadata = InitializrMetadataBuilder.create().withInitializrMetadata( - new ClassPathResource('metadata/config/test-bom.json')).build() - - def boms = metadata.configuration.env.boms - assertEquals 2, boms.size() - BillOfMaterials myBom = boms['my-bom'] - assertNotNull myBom - assertEquals 'org.acme', myBom.groupId - assertEquals 'my-bom', myBom.artifactId - assertEquals '1.2.3.RELEASE', myBom.version - - BillOfMaterials anotherBom = boms['another-bom'] - assertNotNull anotherBom - assertEquals 'org.acme', anotherBom.groupId - assertEquals 'another-bom', anotherBom.artifactId - assertEquals '4.5.6.RELEASE', anotherBom.version - } - - @Test - void mergeMetadataWithRepository() { - def metadata = InitializrMetadataBuilder.create().withInitializrMetadata( - new ClassPathResource('metadata/config/test-repository.json')).build() - - def repositories = metadata.configuration.env.repositories - assertEquals 4, repositories.size() // 2 standard repos - Repository myRepo = repositories['my-repo'] - assertNotNull myRepo - assertEquals 'my repo', myRepo.name - assertEquals new URL('http://example.com/my'), myRepo.url - assertEquals true, myRepo.snapshotsEnabled - - Repository anotherRepo = repositories['another-repo'] - assertNotNull anotherRepo - assertEquals 'another repo', anotherRepo.name - assertEquals new URL('http://example.com/another'), anotherRepo.url - assertEquals false, anotherRepo.snapshotsEnabled - } - - @Test - void mergeConfigurationDisabledByDefault() { - def config = load(new ClassPathResource("application-test-default.yml")) - def customDefaultsConfig = load(new ClassPathResource("application-test-custom-env.yml")) - def metadata = InitializrMetadataBuilder - .fromInitializrProperties(config) - .withInitializrProperties(customDefaultsConfig).build() - InitializrConfiguration.Env defaultEnv = new InitializrConfiguration().env - InitializrConfiguration.Env actualEnv = metadata.configuration.env - assertEquals defaultEnv.artifactRepository, actualEnv.artifactRepository - assertEquals defaultEnv.springBootMetadataUrl, actualEnv.springBootMetadataUrl - assertEquals defaultEnv.fallbackApplicationName, actualEnv.fallbackApplicationName - assertEquals defaultEnv.forceSsl, actualEnv.forceSsl - assertEquals defaultEnv.kotlin.version, actualEnv.kotlin.version - } - - @Test - void mergeConfiguration() { - def config = load(new ClassPathResource("application-test-default.yml")) - def customDefaultsConfig = load(new ClassPathResource("application-test-custom-env.yml")) - def metadata = InitializrMetadataBuilder - .fromInitializrProperties(config) - .withInitializrProperties(customDefaultsConfig, true).build() - InitializrConfiguration.Env defaultEnv = new InitializrConfiguration().env - InitializrConfiguration.Env actualEnv = metadata.configuration.env - assertEquals 'https://repo.spring.io/lib-release/', actualEnv.artifactRepository - assertEquals defaultEnv.springBootMetadataUrl, actualEnv.springBootMetadataUrl - assertEquals 'FooBarApplication', actualEnv.fallbackApplicationName - assertEquals false, actualEnv.forceSsl - assertEquals '1.0.0-beta-2423', actualEnv.kotlin.version - } - - @Test - void addDependencyInCustomizer() { - def group = new DependencyGroup(name: 'Extra') - def dependency = new Dependency(id: 'com.foo:foo:1.0.0') - group.content << dependency - def metadata = InitializrMetadataBuilder.create().withCustomizer(new InitializrMetadataCustomizer() { - @Override - void customize(InitializrMetadata metadata) { - metadata.dependencies.content << group - } - }).build() - assertEquals 1, metadata.dependencies.content.size() - assertEquals group, metadata.dependencies.content[0] - } - - private static assertDefaultConfig(InitializrMetadata metadata) { - assertNotNull metadata - assertEquals "Wrong number of dependencies", 9, metadata.dependencies.all.size() - assertEquals "Wrong number of dependency group", 2, metadata.dependencies.content.size() - assertEquals "Wrong number of types", 4, metadata.types.content.size() - } - - private static InitializrProperties load(Resource resource) { - PropertiesConfigurationFactory factory = - new PropertiesConfigurationFactory<>(InitializrProperties) - factory.setTargetName("initializr") - PropertySources sources = new MutablePropertySources() - sources.addFirst(new PropertiesPropertySource("main", loadProperties(resource))) - factory.setPropertySources(sources) - factory.afterPropertiesSet(); - return factory.getObject(); - } - - private static Properties loadProperties(Resource resource) { - YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean() - yamlFactory.setResources(resource) - yamlFactory.afterPropertiesSet() - return yamlFactory.getObject() - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataTests.groovy deleted file mode 100644 index ed585bf7..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/InitializrMetadataTests.groovy +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.metadata - -import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder -import io.spring.initializr.util.Version -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.assertj.core.api.Assertions.assertThat - -/** - * @author Stephane Nicoll - */ -class InitializrMetadataTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void invalidBom() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'foo-bom') - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('my-bom', 'org.acme', 'foo', '1.2.3') - .addDependencyGroup('test', foo); - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("foo-bom") - thrown.expectMessage("my-bom") - builder.build() - } - - @Test - void invalidRepository() { - def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo') - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addRepository('my-repo', 'repo', 'http://example.com/repo', true) - .addDependencyGroup('test', foo); - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("foo-repo") - thrown.expectMessage("my-repo") - builder.build() - } - - @Test - void invalidBomNoVersion() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("No version") - thrown.expectMessage("foo-bom") - builder.build() - } - - @Test - void invalidBomUnknownRepository() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom', - version: '1.0.0.RELEASE', repositories: ['foo-repo']) - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("invalid repository id foo-repo") - thrown.expectMessage("foo-bom") - builder.build() - } - - @Test - void invalidBomUnknownAdditionalBom() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom', - version: '1.0.0.RELEASE', additionalBoms: ['bar-bom', 'biz-bom']) - def barBom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'bar-bom', - version: '1.0.0.RELEASE') - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom).addBom('bar-bom', barBom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("invalid additional bom") - thrown.expectMessage("biz-bom") - builder.build() - } - - @Test - void invalidBomVersionRangeMapping() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: 'FOO_BAR', version: '1.2.0') - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("FOO_BAR") - thrown.expectMessage("foo-bom") - builder.build() - } - - @Test - void invalidBomVersionRangeMappingUnknownRepo() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.0.0.RELEASE,1.3.0.M1)', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '1.3.0.M2', version: '1.2.0', repositories: ['foo-repo']) - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("invalid repository id foo-repo") - thrown.expectMessage('1.3.0.M2') - thrown.expectMessage("foo-bom") - builder.build() - } - - @Test - void invalidBomVersionRangeMappingUnknownAdditionalBom() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.0.0.RELEASE,1.3.0.M1)', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '1.3.0.M2', version: '1.2.0', - additionalBoms: ['bar-bom']) - - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults().addBom('foo-bom', bom) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("invalid additional bom") - thrown.expectMessage('1.3.0.M2') - thrown.expectMessage("bar-bom") - builder.build() - } - - @Test - void updateSpringBootVersions() { - def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.3.0.RELEASE,1.3.x.RELEASE]', version: '1.0.0') - bom.mappings << new BillOfMaterials.Mapping(versionRange: '1.3.x.BUILD-SNAPSHOT', version: '1.1.0-BUILD-SNAPSHOT') - def dependency = new Dependency(id: 'bar') - dependency.mappings << new Dependency.Mapping( - versionRange: '[1.3.0.RELEASE, 1.3.x.RELEASE]', version: '0.1.0.RELEASE') - dependency.mappings << new Dependency.Mapping( - versionRange: '1.3.x.BUILD-SNAPSHOT', version: '0.2.0.RELEASE') - InitializrMetadata metadata = InitializrMetadataTestBuilder - .withDefaults().addDependencyGroup("test", dependency) - .addBom('foo-bom', bom).build(); - - List bootVersions = Arrays.asList( - new DefaultMetadataElement(id: '1.3.6.RELEASE', name: '1.3.6'), - new DefaultMetadataElement(id: '1.3.7.BUILD-SNAPSHOT', name: '1.3.7')) - metadata.updateSpringBootVersions(bootVersions) - assertThat(metadata.configuration.env.boms['foo-bom'] - .resolve(Version.parse('1.3.6.RELEASE')).version).isEqualTo('1.0.0') - assertThat(metadata.configuration.env.boms['foo-bom'] - .resolve(Version.parse('1.3.7.BUILD-SNAPSHOT')).version).isEqualTo('1.1.0-BUILD-SNAPSHOT') - assertThat(metadata.dependencies.get('bar') - .resolve(Version.parse('1.3.6.RELEASE')).version).isEqualTo('0.1.0.RELEASE') - assertThat(metadata.dependencies.get('bar') - .resolve(Version.parse('1.3.7.BUILD-SNAPSHOT')).version).isEqualTo('0.2.0.RELEASE') - } - - @Test - void invalidParentMissingVersion() { - InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder - .withDefaults() - .setMavenParent('org.foo', 'foo-parent', null, false) - - thrown.expect(InvalidInitializrMetadataException) - thrown.expectMessage("Custom maven pom requires groupId, artifactId and version") - builder.build() - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/LinkTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/LinkTests.groovy deleted file mode 100644 index 58afbfe2..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/LinkTests.groovy +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -/** - * Tests for {@link Link}. - * - * @author Stephane Nicoll - */ -class LinkTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void resolveInvalidLinkNoRel() { - def link = new Link(href: 'https://example.com') - thrown.expect(InvalidInitializrMetadataException) - link.resolve() - } - - @Test - void resolveInvalidLinkNoHref() { - def link = new Link(rel: 'reference', description: 'foo doc') - - thrown.expect(InvalidInitializrMetadataException) - link.resolve() - } - - @Test - void resolveLinkNoVariables() { - def link = new Link(rel: 'reference', href: 'https://example.com/2') - link.resolve() - assert !link.templated - assert link.templateVariables.size() == 0 - } - - @Test - void resolveLinkWithVariables() { - def link = new Link(rel: 'reference', href: 'https://example.com/{a}/2/{b}') - link.resolve() - assert link.templated - assert link.templateVariables.size() == 2 - assert link.templateVariables.contains('a') - assert link.templateVariables.contains('b') - } - - @Test - void expandLink() { - def link = new Link(rel: 'reference', href: 'https://example.com/{a}/2/{b}') - link.resolve() - assert link.expand(['a': 'test', 'b': 'another']) == - new URI('https://example.com/test/2/another') - } - - @Test - void expandLinkWithSameAttributeAtTwoPlaces() { - def link = new Link(rel: 'reference', href: 'https://example.com/{a}/2/{a}') - link.resolve() - assert link.expand(['a': 'test', 'b': 'another']) == - new URI('https://example.com/test/2/test') - } - - @Test - void expandLinkMissingVariable() { - def link = new Link(rel: 'reference', href: 'https://example.com/{a}/2/{b}') - link.resolve() - - thrown.expect(IllegalArgumentException) - thrown.expectMessage("missing value for 'b'") - link.expand(['a': 'test']) - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/SingleSelectCapabilityTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/SingleSelectCapabilityTests.groovy deleted file mode 100644 index 13d91d5b..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/SingleSelectCapabilityTests.groovy +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Test - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNull - -/** - * @author Stephane Nicoll - */ -class SingleSelectCapabilityTests { - - @Test - void defaultEmpty() { - SingleSelectCapability capability = new SingleSelectCapability('test') - assertNull capability.default - } - - @Test - void defaultNoDefault() { - SingleSelectCapability capability = new SingleSelectCapability('test') - capability.content << new DefaultMetadataElement(id: 'foo', default: false) - capability.content << new DefaultMetadataElement(id: 'bar', default: false) - assertNull capability.default - } - - @Test - void defaultType() { - SingleSelectCapability capability = new SingleSelectCapability('test') - DefaultMetadataElement first = new DefaultMetadataElement(id: 'foo', default: false) - DefaultMetadataElement second = new DefaultMetadataElement(id: 'bar', default: true) - capability.content << first << second - assertEquals second, capability.default - } - - @Test - void mergeAddEntry() { - SingleSelectCapability capability = new SingleSelectCapability('test') - def foo = new DefaultMetadataElement(id: 'foo', default: false) - capability.content << foo - - SingleSelectCapability anotherCapability = new SingleSelectCapability('test') - def bar = new DefaultMetadataElement(id: 'bar', default: false) - anotherCapability.content << bar - - capability.merge(anotherCapability) - assertEquals 2, capability.content.size() - assertEquals foo, capability.get('foo') - assertEquals bar, capability.get('bar') - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TextCapabilityTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TextCapabilityTests.groovy deleted file mode 100644 index b37b8b3d..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TextCapabilityTests.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Test - -import static org.junit.Assert.assertEquals - -/** - * @author Stephane Nicoll - */ -class TextCapabilityTests { - - @Test - void mergeValue() { - TextCapability capability = new TextCapability('foo') - capability.content = '1234' - def another = new TextCapability('foo') - another.content = '4567' - capability.merge(another) - assertEquals 'foo', capability.id - assertEquals ServiceCapabilityType.TEXT, capability.type - assertEquals '4567', capability.content - } - - @Test - void mergeTitle() { - TextCapability capability = new TextCapability('foo', 'Foo', 'my desc') - capability.merge(new TextCapability('foo', 'AnotherFoo', '')) - assertEquals 'foo', capability.id - assertEquals ServiceCapabilityType.TEXT, capability.type - assertEquals 'AnotherFoo', capability.title - assertEquals 'my desc', capability.description - } - - @Test - void mergeDescription() { - TextCapability capability = new TextCapability('foo', 'Foo', 'my desc') - capability.merge(new TextCapability('foo', '', 'another desc')) - assertEquals 'foo', capability.id - assertEquals ServiceCapabilityType.TEXT, capability.type - assertEquals 'Foo', capability.title - assertEquals 'another desc', capability.description - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeCapabilityTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeCapabilityTests.groovy deleted file mode 100644 index 26b57758..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeCapabilityTests.groovy +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 io.spring.initializr.metadata - -import org.junit.Test - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertNull - -/** - * @author Stephane Nicoll - */ -class TypeCapabilityTests { - - @Test - void defaultEmpty() { - TypeCapability capability = new TypeCapability() - assertNull capability.default - } - - @Test - void defaultNoDefault() { - TypeCapability capability = new TypeCapability() - capability.content << new Type(id: 'foo', default: false) << new Type(id: 'bar', default: false) - assertNull capability.default - } - - @Test - void defaultType() { - TypeCapability capability = new TypeCapability() - Type first = new Type(id: 'foo', default: false) - Type second = new Type(id: 'bar', default: true) - capability.content << first << second - assertEquals second, capability.default - } - - @Test - void mergeAddEntry() { - TypeCapability capability = new TypeCapability() - def foo = new Type(id: 'foo', default: false) - capability.content << foo - - TypeCapability anotherCapability = new TypeCapability() - def foo2 =new Type(id: 'foo', default: true) - def bar =new Type(id: 'bar', default: true) - anotherCapability.content << foo2 << bar - - capability.merge(anotherCapability) - assertEquals 2, capability.content.size() - assertEquals foo, capability.get('foo') - assertEquals bar, capability.get('bar') - assertEquals bar, capability.default - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/GradleBuildAssert.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/GradleBuildAssert.groovy deleted file mode 100644 index d190f9c0..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/GradleBuildAssert.groovy +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 io.spring.initializr.test.generator - -import io.spring.initializr.generator.ProjectRequest - -import static org.junit.Assert.assertFalse -import static org.junit.Assert.assertTrue - -/** - * Very simple assertions for the gradle build. - * - * @author Stephane Nicoll - */ -class GradleBuildAssert { - - private final String content - - GradleBuildAssert(String content) { - this.content = content - } - - /** - * Validate that this generated gradle build validates against its request. - */ - GradleBuildAssert validateProjectRequest(ProjectRequest request) { - hasArtifactId(request.artifactId).hasVersion(request.version). - hasBootVersion(request.bootVersion).hasJavaVersion(request.javaVersion) - } - - GradleBuildAssert hasArtifactId(String artifactId) { - contains("baseName = '$artifactId'") - } - - GradleBuildAssert hasVersion(String version) { - contains("version = '$version'") - } - - GradleBuildAssert hasBootVersion(String bootVersion) { - contains("springBootVersion = '$bootVersion'") - } - - GradleBuildAssert hasJavaVersion(String javaVersion) { - contains("sourceCompatibility = $javaVersion") - } - - GradleBuildAssert hasSnapshotRepository() { - contains('https://repo.spring.io/snapshot') - } - - GradleBuildAssert hasRepository(String url) { - contains("maven { url \"$url\" }") - } - - GradleBuildAssert contains(String expression) { - assertTrue "$expression has not been found in gradle build $content", content.contains(expression) - this - } - - GradleBuildAssert doesNotContain(String expression) { - assertFalse "$expression is not expected in gradle build $content", content.contains(expression) - this - } -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/PomAssert.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/PomAssert.groovy deleted file mode 100644 index 0fbe7e41..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/PomAssert.groovy +++ /dev/null @@ -1,376 +0,0 @@ -/* - * 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 io.spring.initializr.test.generator - -import io.spring.initializr.generator.ProjectRequest -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom -import io.spring.initializr.metadata.Repository -import org.custommonkey.xmlunit.SimpleNamespaceContext -import org.custommonkey.xmlunit.XMLUnit -import org.custommonkey.xmlunit.XpathEngine -import org.junit.Assert -import org.w3c.dom.Document -import org.w3c.dom.Element - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertFalse -import static org.junit.Assert.assertNotNull -import static org.junit.Assert.assertTrue - -/** - * XPath assertions that are specific to a standard Maven POM. - * - * @author Stephane Nicoll - */ -class PomAssert { - - final XpathEngine eng - final Document doc - final ParentPom parentPom - final Map properties = [:] - final Map dependencies = [:] - final Map boms = [:] - final Map repositories = [:] - - PomAssert(String content) { - eng = XMLUnit.newXpathEngine() - def context = [:] - context['pom'] = 'http://maven.apache.org/POM/4.0.0' - def namespaceContext = new SimpleNamespaceContext(context) - eng.namespaceContext = namespaceContext - doc = XMLUnit.buildControlDocument(content) - this.parentPom = parseParent() - parseProperties() - parseDependencies() - parseBoms() - parseRepositories() - } - - /** - * Validate that this generated pom validates against its request. - */ - PomAssert validateProjectRequest(ProjectRequest request) { - hasGroupId(request.groupId).hasArtifactId(request.artifactId).hasVersion(request.version). - hasPackaging(request.packaging).hasName(request.name).hasDescription(request.description). - hasJavaVersion(request.javaVersion) - } - - PomAssert hasGroupId(String groupId) { - assertEquals groupId, eng.evaluate(createRootNodeXPath('groupId'), doc) - this - } - - PomAssert hasArtifactId(String artifactId) { - assertEquals artifactId, eng.evaluate(createRootNodeXPath('artifactId'), doc) - this - } - - PomAssert hasVersion(String version) { - assertEquals version, eng.evaluate(createRootNodeXPath('version'), doc) - this - } - - PomAssert hasPackaging(String packaging) { - assertEquals packaging, eng.evaluate(createRootNodeXPath('packaging'), doc) - this - } - - PomAssert hasName(String name) { - assertEquals name, eng.evaluate(createRootNodeXPath('name'), doc) - this - } - - PomAssert hasDescription(String description) { - assertEquals description, eng.evaluate(createRootNodeXPath('description'), doc) - this - } - - PomAssert hasJavaVersion(String javaVersion) { - assertEquals javaVersion, eng.evaluate(createPropertyNodeXpath('java.version'), doc) - this - } - - PomAssert hasProperty(String name, String value) { - assertTrue "No property $name found", properties.containsKey(name) - assertEquals "Wrong value for property $name", value, properties[name] - this - } - - PomAssert hasNoProperty(String name) { - assertFalse "No property $name should have been found", properties.containsKey(name) - this - } - - PomAssert hasDependenciesCount(int count) { - assertEquals "Wrong number of declared dependencies -->'${dependencies.keySet()}", - count, dependencies.size() - this - } - - PomAssert hasSpringBootStarterTomcat() { - hasDependency(new Dependency(id: 'tomcat', scope: 'provided').asSpringBootStarter('tomcat')) - } - - PomAssert hasSpringBootStarterTest() { - hasDependency(new Dependency(id: 'test', scope: 'test').asSpringBootStarter('test')) - } - - PomAssert hasSpringBootStarterDependency(String dependency) { - hasDependency('org.springframework.boot', "spring-boot-starter-$dependency") - } - - PomAssert hasSpringBootStarterRootDependency() { - hasDependency('org.springframework.boot', 'spring-boot-starter') - } - - PomAssert hasDependency(String groupId, String artifactId) { - hasDependency(groupId, artifactId, null) - } - - PomAssert hasDependency(String groupId, String artifactId, String version) { - hasDependency(new Dependency(groupId: groupId, artifactId: artifactId, version: version)) - } - - PomAssert hasParent(String groupId, String artifactId, String version) { - assertEquals groupId, this.parentPom.groupId - assertEquals artifactId, this.parentPom.artifactId - assertEquals version, this.parentPom.version - this - } - - PomAssert hasSpringBootParent(String version) { - hasParent('org.springframework.boot', 'spring-boot-starter-parent', version) - } - - PomAssert hasDependency(Dependency expected) { - def id = generateDependencyId(expected.groupId, expected.artifactId) - def dependency = dependencies[id] - assertNotNull "No dependency found with '$id' --> ${dependencies.keySet()}", dependency - if (expected.version) { - assertEquals "Wrong version for $dependency", expected.version, dependency.version - } - if (expected.scope) { - assertEquals "Wrong scope for $dependency", expected.scope, dependency.scope - } - if (expected.type) { - assertEquals "Wrong type for $dependency", expected.type, dependency.type - } - this - } - - PomAssert hasBom(String groupId, String artifactId, String version) { - def id = generateBomId(groupId, artifactId) - def bom = boms[id] - assertNotNull "No BOM found with '$id' --> ${boms.keySet()}", bom - assertEquals "Wrong version for $bom", version, bom.version - this - } - - PomAssert hasBomsCount(int count) { - assertEquals "Wrong number of declared boms -->'${boms.keySet()}", - count, boms.size() - this - } - - PomAssert hasNoRepository() { - Assert.assertEquals 0, eng.getMatchingNodes(createRootNodeXPath('repositories'), doc).length - this - } - - PomAssert hasSnapshotRepository() { - hasRepository('spring-snapshots', 'Spring Snapshots', - 'https://repo.spring.io/snapshot', true) - hasPluginRepository('spring-snapshots') - this - } - - PomAssert hasRepository(String id, String name, String url, Boolean snapshotsEnabled) { - Repository repository = repositories[id] - assertNotNull "No repository found with '$id' --> ${repositories.keySet()}", repository - if (name) { - assertEquals "Wrong name for $repository", name, repository.name - } - if (url) { - assertEquals "Wrong url for $repository", new URL(url), repository.url - } - if (snapshotsEnabled) { - assertEquals "Wrong snapshots enabled flag for $repository", snapshotsEnabled, repository.snapshotsEnabled - } - this - } - - PomAssert hasRepositoriesCount(int count) { - assertEquals "Wrong number of declared repositories -->'${repositories.keySet()}", - count, repositories.size() - this - } - - - def hasPluginRepository(String name) { - def nodes = eng.getMatchingNodes(createRootNodeXPath('pluginRepositories/pom:pluginRepository/pom:id'), doc) - for (int i = 0; i < nodes.length; i++) { - if (name.equals(nodes.item(i).textContent)) { - return - } - } - throw new IllegalArgumentException("No plugin repository found with id $name") - } - - static String createPropertyNodeXpath(String propertyName) { - createRootNodeXPath("properties/pom:$propertyName") - } - - static String createRootNodeXPath(String node) { - "/pom:project/pom:$node" - } - - private ParentPom parseParent() { - new ParentPom( - groupId: eng.evaluate(createRootNodeXPath('parent/pom:groupId'), doc), - artifactId: eng.evaluate(createRootNodeXPath('parent/pom:artifactId'), doc), - version: eng.evaluate(createRootNodeXPath('parent/pom:version'), doc)) - } - - private def parseProperties() { - def nodes = eng.getMatchingNodes(createRootNodeXPath('properties/*'), doc) - for (int i = 0; i < nodes.length; i++) { - def item = nodes.item(i) - if (item instanceof Element) { - def element = (Element) item - properties[element.tagName] = element.textContent - } - } - } - - private def parseDependencies() { - def nodes = eng.getMatchingNodes(createRootNodeXPath('dependencies/pom:dependency'), doc) - for (int i = 0; i < nodes.length; i++) { - def item = nodes.item(i) - if (item instanceof Element) { - def dependency = new Dependency() - def element = (Element) item - def groupId = element.getElementsByTagName('groupId') - if (groupId.length > 0) { - dependency.groupId = groupId.item(0).textContent - } - def artifactId = element.getElementsByTagName('artifactId') - if (artifactId.length > 0) { - dependency.artifactId = artifactId.item(0).textContent - } - def version = element.getElementsByTagName('version') - if (version.length > 0) { - dependency.version = version.item(0).textContent - } - def scope = element.getElementsByTagName('scope') - if (scope.length > 0) { - dependency.scope = scope.item(0).textContent - } - def type = element.getElementsByTagName('type') - if (type.length > 0) { - dependency.type = type.item(0).textContent - } - def id = dependency.generateId() - assertFalse("Duplicate dependency with id $id", dependencies.containsKey(id)) - dependencies[id] = dependency - } - } - } - - private def parseBoms() { - def nodes = eng.getMatchingNodes(createRootNodeXPath('dependencyManagement/pom:dependencies/pom:dependency'), doc) - for (int i = 0; i < nodes.length; i++) { - def item = nodes.item(i) - if (item instanceof Element) { - def element = (Element) item - def type = element.getElementsByTagName('type') - def scope = element.getElementsByTagName('scope') - if (isBom(type, scope)) { - def bom = new BillOfMaterials() - def groupId = element.getElementsByTagName('groupId') - if (groupId.length > 0) { - bom.groupId = groupId.item(0).textContent - } - def artifactId = element.getElementsByTagName('artifactId') - if (artifactId.length > 0) { - bom.artifactId = artifactId.item(0).textContent - } - def version = element.getElementsByTagName('version') - if (version.length > 0) { - bom.version = version.item(0).textContent - } - def id = generateBomId(bom.groupId, bom.artifactId) - assertFalse("Duplicate BOM with id $id", boms.containsKey(id)) - boms[id] = bom - } - } - } - } - - private def parseRepositories() { - def nodes = eng.getMatchingNodes(createRootNodeXPath('repositories/pom:repository'), doc) - for (int i = 0; i < nodes.length; i++) { - def item = nodes.item(i) - if (item instanceof Element) { - def repository = new Repository() - def element = (Element) item - def type = element.getElementsByTagName('id') - def id = type.item(0).textContent - def name = element.getElementsByTagName('name') - if (name.length > 0) { - repository.name = name.item(0).textContent - } - def url = element.getElementsByTagName('url') - if (url.length > 0) { - repository.url = new URL(url.item(0).textContent) - } - def snapshots = element.getElementsByTagName('snapshots') - if (snapshots.length > 0) { - Element snapshotsElement = (Element) snapshots.item(0); - def snapshotsEnabled = snapshotsElement.getElementsByTagName('enabled') - if (snapshotsEnabled.length > 0) { - repository.snapshotsEnabled = snapshotsEnabled.item(0).textContent - } - } - assertFalse("Duplicate Repository with id $id", repositories.containsKey(id)) - repositories[id] = repository - } - } - } - - private static boolean isBom(def type, def scope) { - if (type.length == 0 || scope.length == 0) { - return false - } - String typeValue = type.item(0).textContent - String scopeValue = scope.item(0).textContent - return "pom".equals(typeValue) && "import".equals(scopeValue) - } - - private static String generateBomId(def groupId, def artifactId) { - "$groupId:$artifactId" - } - - private static String generateDependencyId(String groupId, String artifactId) { - def dependency = new Dependency() - dependency.groupId = groupId - dependency.artifactId = artifactId - dependency.generateId() - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/ProjectAssert.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/ProjectAssert.groovy deleted file mode 100644 index 98e73768..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/ProjectAssert.groovy +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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 io.spring.initializr.test.generator - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertTrue - -/** - * Various project based assertions. - * - * @author Stephane Nicoll - */ -class ProjectAssert { - - public static final DEFAULT_PACKAGE_NAME = 'com.example' - - public static final DEFAULT_APPLICATION_NAME = 'DemoApplication' - - final File dir - Boolean mavenProject - - /** - * Create a new instance with the directory holding the generated project. - * @param dir - */ - ProjectAssert(File dir) { - this.dir = dir - } - - /** - * Validate that the project contains a base directory with the specified name. - *

When extracting such archive, a directory with the specified {@code name} - * will be created with the content of the project instead of extracting it in - * the directory itself. - * @param name the expected name of the base directory - * @return an updated project assert on that base directory - */ - ProjectAssert hasBaseDir(String name) { - File projectDir = file(name) - assertTrue "No directory $name found in $dir.absolutePath", projectDir.exists() - assertTrue "$name is not a directory", projectDir.isDirectory() - new ProjectAssert(projectDir) // Replacing the root dir so that other assertions match the root - } - - /** - * Return a {@link PomAssert} for this project. - */ - PomAssert pomAssert() { - new PomAssert(file('pom.xml').text) - } - - /** - * Return a {@link GradleBuildAssert} for this project. - */ - GradleBuildAssert gradleBuildAssert() { - new GradleBuildAssert(file('build.gradle').text) - } - - /** - * Return a {@link SourceCodeAssert} for the specified source code. - */ - SourceCodeAssert sourceCodeAssert(String sourceCodePath) { - hasFile(sourceCodePath) - new SourceCodeAssert(sourceCodePath, file(sourceCodePath).text) - } - - ProjectAssert isMavenProject() { - hasFile('pom.xml').hasNoFile('build.gradle') - hasFile('mvnw', 'mvnw.cmd', - '.mvn/wrapper/maven-wrapper.properties', - '.mvn/wrapper/maven-wrapper.jar') - mavenProject = true - this - } - - ProjectAssert isGradleProject(String version) { - hasFile('build.gradle').hasNoFile('pom.xml') - hasFile('gradlew', 'gradlew.bat', - 'gradle/wrapper/gradle-wrapper.properties', - 'gradle/wrapper/gradle-wrapper.jar') - mavenProject = false - if (version) { - Properties properties = properties("gradle/wrapper/gradle-wrapper.properties") - String distributionUrl = properties['distributionUrl'] - assertTrue("Wrong gradle version for project $distributionUrl", - distributionUrl.contains(version)) - } - this - } - - ProjectAssert isGradleProject() { - isGradleProject(null) - } - - ProjectAssert isJavaProject(String expectedPackageName, String expectedApplicationName) { - isGenericProject(expectedPackageName, expectedApplicationName, 'java', 'java') - } - - ProjectAssert isJavaProject() { - isJavaProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME) - } - - ProjectAssert isGroovyProject(String expectedPackageName, String expectedApplicationName) { - isGenericProject(expectedPackageName, expectedApplicationName, 'groovy', 'groovy') - } - - ProjectAssert isKotlinProject(String expectedPackageName, String expectedApplicationName) { - isGenericProject(expectedPackageName, expectedApplicationName, 'kotlin', 'kt') - } - - ProjectAssert isGroovyProject() { - isGroovyProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME) - } - - ProjectAssert isKotlinProject() { - isKotlinProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME) - } - - ProjectAssert isGenericProject(String expectedPackageName, String expectedApplicationName, - String codeLocation, String extension) { - String packageName = expectedPackageName.replace('.', '/') - hasFile("src/main/$codeLocation/$packageName/${expectedApplicationName}.$extension", - "src/test/$codeLocation/$packageName/${expectedApplicationName}Tests.$extension", - 'src/main/resources/application.properties') - } - - ProjectAssert isJavaWarProject(String expectedApplicationName) { - isGenericWarProject(DEFAULT_PACKAGE_NAME, expectedApplicationName, 'java', 'java') - } - - ProjectAssert isJavaWarProject() { - isJavaWarProject(DEFAULT_APPLICATION_NAME) - } - - ProjectAssert isGenericWarProject(String expectedPackageName, String expectedApplicationName, - String codeLocation, String extension) { - String packageName = expectedPackageName.replace('.', '/') - isGenericProject(expectedPackageName, expectedApplicationName, codeLocation, extension) - .hasStaticAndTemplatesResources(true) - .hasFile("src/main/$codeLocation/$packageName/ServletInitializer.$extension") - } - - ProjectAssert hasStaticAndTemplatesResources(boolean web) { - assertFile('src/main/resources/templates', web) - assertFile('src/main/resources/static', web) - } - - ProjectAssert hasFile(String... localPaths) { - for (String localPath : localPaths) { - assertFile(localPath, true) - } - this - } - - ProjectAssert hasNoFile(String... localPaths) { - for (String localPath : localPaths) { - assertFile(localPath, false) - } - this - } - - ProjectAssert assertFile(String localPath, boolean exist) { - def candidate = file(localPath) - assertEquals "Invalid presence ('$exist') for $localPath", exist, candidate.exists() - this - } - - private File file(String localPath) { - new File(dir, localPath) - } - - private Properties properties(String localPath) { - File f = file(localPath) - Properties properties = new Properties() - f.withInputStream { - properties.load(it) - } - properties - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/SourceCodeAssert.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/SourceCodeAssert.groovy deleted file mode 100644 index d33e6967..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/test/generator/SourceCodeAssert.groovy +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 io.spring.initializr.test.generator - -import java.nio.charset.Charset - -import org.springframework.core.io.Resource -import org.springframework.util.StreamUtils - -import static org.junit.Assert.assertEquals -import static org.junit.Assert.assertFalse -import static org.junit.Assert.assertTrue - -/** - * Source code assertions. - * - * @author Stephane Nicoll - */ -class SourceCodeAssert { - - private final String name - private final String content - - SourceCodeAssert(String name, String content) { - this.name = name - this.content = content.normalize() - } - - SourceCodeAssert equalsTo(Resource expected) { - def stream = expected.inputStream - try { - String expectedContent = StreamUtils.copyToString(stream, Charset.forName('UTF-8')) - assertEquals "Unexpected content for $name", expectedContent.normalize(), content - } finally { - stream.close() - } - this - } - - SourceCodeAssert hasImports(String... classNames) { - for (String className : classNames) { - contains("import $className") - } - this - } - - SourceCodeAssert doesNotHaveImports(String... classNames) { - for (String className : classNames) { - doesNotContain("import $className") - } - this - } - - SourceCodeAssert contains(String... expressions) { - for (String expression : expressions) { - assertTrue "$expression has not been found in source code '$name'", content.contains(expression) - } - this - } - - SourceCodeAssert doesNotContain(String... expressions) { - for (String expression : expressions) { - assertFalse "$expression should not have been found in source code '$name'", content.contains(expression) - } - this - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.groovy deleted file mode 100644 index 0a077403..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.groovy +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 io.spring.initializr.test.metadata - -import io.spring.initializr.metadata.BillOfMaterials -import io.spring.initializr.metadata.DefaultMetadataElement -import io.spring.initializr.metadata.Dependency -import io.spring.initializr.metadata.DependencyGroup -import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.metadata.InitializrMetadataBuilder -import io.spring.initializr.metadata.Repository -import io.spring.initializr.metadata.Type - -/** - * Easily create a {@link InitializrMetadata} instance for testing purposes. - * - * @author Stephane Nicoll - */ -class InitializrMetadataTestBuilder { - - private final InitializrMetadataBuilder builder = InitializrMetadataBuilder.create() - - static InitializrMetadataTestBuilder withDefaults() { - new InitializrMetadataTestBuilder().addDefaults() - } - - InitializrMetadata build() { - builder.build() - } - - InitializrMetadataTestBuilder addDependencyGroup(String name, String... ids) { - builder.withCustomizer { - def group = new DependencyGroup(name: name) - for (String id : ids) { - def dependency = new Dependency(id: id) - group.content << dependency - } - it.dependencies.content << group - } - this - } - - InitializrMetadataTestBuilder addDependencyGroup(String name, Dependency... dependencies) { - builder.withCustomizer { - def group = new DependencyGroup(name: name) - group.content.addAll(dependencies) - it.dependencies.content << group - } - this - } - - InitializrMetadataTestBuilder addDefaults() { - addDefaultTypes().addDefaultPackagings().addDefaultJavaVersions() - .addDefaultLanguages().addDefaultBootVersions() - .setGradleEnv('0.5.1.RELEASE').setKotlinEnv('1.0.1') - } - - InitializrMetadataTestBuilder addDefaultTypes() { - addType('maven-build', false, '/pom.xml', 'maven', 'build') - .addType('maven-project', true, '/starter.zip', 'maven', 'project') - .addType('gradle-build', false, '/build.gradle', 'gradle', 'build') - .addType('gradle-project', false, '/starter.zip', 'gradle', 'project') - } - - InitializrMetadataTestBuilder addType(String id, boolean defaultValue, String action, String build, String format) { - def type = new Type(id: id, name: id, default: defaultValue, action: action) - if (build) { - type.tags['build'] = build - } - if (format) { - type.tags['format'] = format - } - addType(type) - } - - InitializrMetadataTestBuilder addType(Type type) { - builder.withCustomizer { it.types.content << type } - this - } - - InitializrMetadataTestBuilder addDefaultPackagings() { - addPackaging('jar', true).addPackaging('war', false) - } - - InitializrMetadataTestBuilder addPackaging(String id, boolean defaultValue) { - builder.withCustomizer { - def packaging = new DefaultMetadataElement(id: id, name: id, default: defaultValue) - it.packagings.content << packaging - } - this - } - - InitializrMetadataTestBuilder addDefaultJavaVersions() { - addJavaVersion('1.6', false).addJavaVersion('1.7', false).addJavaVersion('1.8', true) - } - - InitializrMetadataTestBuilder addJavaVersion(String version, boolean defaultValue) { - builder.withCustomizer { - def javaVersion = new DefaultMetadataElement(id: version, name: version, default: defaultValue) - it.javaVersions.content << javaVersion - } - this - } - - InitializrMetadataTestBuilder addDefaultLanguages() { - addLanguage('java', true).addLanguage('groovy', false).addLanguage('kotlin', false) - } - - InitializrMetadataTestBuilder addLanguage(String id, boolean defaultValue) { - builder.withCustomizer { - def language = new DefaultMetadataElement(id: id, name: id, default: defaultValue) - it.languages.content << language - } - this - } - - InitializrMetadataTestBuilder addDefaultBootVersions() { - addBootVersion('1.1.2.RELEASE', false).addBootVersion('1.2.3.RELEASE', true) - .addBootVersion('1.3.0.BUILD-SNAPSHOT', false) - } - - InitializrMetadataTestBuilder addBootVersion(String id, boolean defaultValue) { - builder.withCustomizer { - def bootVersion = new DefaultMetadataElement(id: id, name: id, default: defaultValue) - it.bootVersions.content << bootVersion - } - this - } - - InitializrMetadataTestBuilder addBom(String id, String groupId, String artifactId, String version) { - addBom(id, new BillOfMaterials(groupId: groupId, artifactId: artifactId, version: version)) - } - - InitializrMetadataTestBuilder addBom(String id, BillOfMaterials bom) { - builder.withCustomizer { - it.configuration.env.boms[id] = bom - } - this - } - - InitializrMetadataTestBuilder setGradleEnv(String dependencyManagementPluginVersion) { - builder.withCustomizer { - it.configuration.env.gradle.dependencyManagementPluginVersion = dependencyManagementPluginVersion - } - this - } - - InitializrMetadataTestBuilder setKotlinEnv(String kotlinVersion) { - builder.withCustomizer { - it.configuration.env.kotlin.version = kotlinVersion - } - this - } - - InitializrMetadataTestBuilder setMavenParent(String groupId, String artifactId, - String version, boolean includeSpringBootBom) { - builder.withCustomizer { - def parent = it.configuration.env.maven.parent - parent.groupId = groupId - parent.artifactId = artifactId - parent.version = version - parent.includeSpringBootBom = includeSpringBootBom - } - this - } - - InitializrMetadataTestBuilder addRepository(String id, String name, String url, boolean snapshotsEnabled) { - builder.withCustomizer { - Repository repo = new Repository( - name: name, url: new URL(url), snapshotsEnabled: snapshotsEnabled) - it.configuration.env.repositories[id] = repo - } - this - } - -} \ No newline at end of file diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/util/AgentTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/util/AgentTests.groovy deleted file mode 100644 index b65d71e3..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/util/AgentTests.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.util - -import org.junit.Test - -import static org.hamcrest.CoreMatchers.equalTo -import static org.hamcrest.CoreMatchers.is -import static org.hamcrest.CoreMatchers.nullValue -import static org.junit.Assert.assertThat - -/** - * Tests for {@link Agent}. - * - * @author Stephane Nicoll - */ -class AgentTests { - - @Test - void checkCurl() { - Agent agent = Agent.fromUserAgent('curl/1.2.4') - assertThat(agent.id, equalTo(Agent.AgentId.CURL)) - assertThat(agent.version, equalTo('1.2.4')) - } - - @Test - void checkHttpie() { - Agent agent = Agent.fromUserAgent('HTTPie/0.8.0') - assertThat(agent.id, equalTo(Agent.AgentId.HTTPIE)) - assertThat(agent.version, equalTo('0.8.0')) - } - - @Test - void checkSpringBootCli() { - Agent agent = Agent.fromUserAgent('SpringBootCli/1.3.1.RELEASE') - assertThat(agent.id, equalTo(Agent.AgentId.SPRING_BOOT_CLI)) - assertThat(agent.version, equalTo('1.3.1.RELEASE')) - } - - @Test - void checkSts() { - Agent agent = Agent.fromUserAgent('STS 3.7.0.201506251244-RELEASE') - assertThat(agent.id, equalTo(Agent.AgentId.STS)) - assertThat(agent.version, equalTo('3.7.0.201506251244-RELEASE')) - } - - @Test - void checkIntelliJIDEA() { - Agent agent = Agent.fromUserAgent('IntelliJ IDEA') - assertThat(agent.id, equalTo(Agent.AgentId.INTELLIJ_IDEA)) - assertThat(agent.version, is(nullValue())) - } - - @Test - void checkIntelliJIDEAWithVersion() { - Agent agent = Agent.fromUserAgent('IntelliJ IDEA/144.2 (Community edition; en-us)') - assertThat(agent.id, equalTo(Agent.AgentId.INTELLIJ_IDEA)) - assertThat(agent.version, is('144.2')) - } - - @Test - void checkNetBeans() { - Agent agent = Agent.fromUserAgent('nb-springboot-plugin/0.1') - assertThat(agent.id, equalTo(Agent.AgentId.NETBEANS)) - assertThat(agent.version, is('0.1')) - } - - @Test - void checkGenericBrowser() { - Agent agent = Agent.fromUserAgent( - 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MMB29K) ') - assertThat(agent.id, equalTo(Agent.AgentId.BROWSER)) - assertThat(agent.version, is(nullValue())) - } - - @Test - void checkRobot() { - Agent agent = Agent.fromUserAgent('Googlebot-Mobile') - assertThat(agent, is(nullValue())) - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionParserTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionParserTests.groovy deleted file mode 100644 index 11812cf9..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionParserTests.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.util - -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.lessThan -import static org.junit.Assert.assertNull - -/** - * Tests for {@link VersionParser}. - * - * @author Stephane Nicoll - */ -class VersionParserTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - private VersionParser parser = new VersionParser(Collections.EMPTY_LIST) - - @Test - void noQualifierString() { - def version = parser.parse('1.2.0') - assertThat(version.toString(), equalTo('1.2.0')) - } - - @Test - void withQualifierString() { - def version = parser.parse('1.2.0.RELEASE') - assertThat(version.toString(), equalTo('1.2.0.RELEASE')) - } - - @Test - void withQualifierAndVersionString() { - def version = parser.parse('1.2.0.RC2') - assertThat(version.toString(), equalTo('1.2.0.RC2')) - } - - @Test - void parseInvalidVersion() { - thrown.expect(InvalidVersionException) - parser.parse('foo') - } - - @Test - void safeParseInvalidVersion() { - assertNull parser.safeParse('foo') - } - - @Test - void parseVersionWithSpaces() { - assertThat(parser.parse(' 1.2.0.RC3 '), - lessThan(parser.parse('1.3.0.RELEASE'))) - } - - @Test - void parseVariableVersionMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.3.9.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('1.3.x.BUILD-SNAPSHOT').toString(), - equalTo('1.3.9.BUILD-SNAPSHOT')) - } - - @Test - void parseVariableVersionNoPatchMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.3.9.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('1.x.x.RELEASE').toString(), - equalTo('1.3.8.RELEASE')) - } - - @Test - void parseVariableVersionNoQualifierMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.4.0.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('1.4.x').toString(), - equalTo('1.4.0.BUILD-SNAPSHOT')) - } - - @Test - void parseVariableVersionNoMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.3.9.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('1.4.x.BUILD-SNAPSHOT').toString(), - equalTo("1.4.999.BUILD-SNAPSHOT")) - } - - @Test - void parseVariableVersionNoPatchNoMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.3.9.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('2.x.x.RELEASE').toString(), - equalTo("2.999.999.RELEASE")) - } - - @Test - void parseVariableVersionNoQualifierNoMatch() { - List currentVersions = Arrays.asList(parser.parse('1.3.8.RELEASE'), - parser.parse('1.4.0.BUILD-SNAPSHOT')) - parser = new VersionParser(currentVersions) - assertThat(parser.parse('1.2.x').toString(), equalTo("1.2.999")) - } - - @Test - void invalidRange() { - thrown.expect(InvalidVersionException) - parser.parseRange("foo-bar") - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionRangeTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionRangeTests.groovy deleted file mode 100644 index 5548a8ff..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionRangeTests.groovy +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.util - -import org.hamcrest.BaseMatcher -import org.hamcrest.Description -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -import static org.hamcrest.core.IsNot.not -import static org.junit.Assert.assertThat - -/** - * @author Stephane Nicoll - */ -class VersionRangeTests { - - @Rule - public final ExpectedException thrown = ExpectedException.none() - - @Test - void matchSimpleRange() { - assertThat('1.2.0.RC3', match('[1.2.0.RC1,1.2.0.RC5]')) - } - - @Test - void matchSimpleRangeBefore() { - assertThat('1.1.9.RC3', not(match('[1.2.0.RC1,1.2.0.RC5]'))) - } - - @Test - void matchSimpleRangeAfter() { - assertThat('1.2.0.RC6', not(match('[1.2.0.RC1,1.2.0.RC5]'))) - } - - @Test - void matchInclusiveLowerRange() { - assertThat('1.2.0.RC1', match('[1.2.0.RC1,1.2.0.RC5]')) - } - - @Test - void matchInclusiveHigherRange() { - assertThat('1.2.0.RC5', match('[1.2.0.RC1,1.2.0.RC5]')) - } - - @Test - void matchExclusiveLowerRange() { - assertThat('1.2.0.RC1', not(match('(1.2.0.RC1,1.2.0.RC5)'))) - } - - @Test - void matchExclusiveHigherRange() { - assertThat('1.2.0.RC5', not(match('[1.2.0.RC1,1.2.0.RC5)'))) - } - - @Test - void matchUnboundedRangeEqual() { - assertThat('1.2.0.RELEASE', match('1.2.0.RELEASE')) - } - - @Test - void matchUnboundedRangeAfter() { - assertThat('2.2.0.RELEASE', match('1.2.0.RELEASE')) - } - - @Test - void matchUnboundedRangeBefore() { - assertThat('1.1.9.RELEASE', not(match('1.2.0.RELEASE'))) - } - - @Test - void rangeWithSpaces() { - assertThat('1.2.0.RC3', match('[ 1.2.0.RC1 , 1.2.0.RC5]')) - } - - @Test - void matchLatestVersion() { - assertThat('1.2.8.RELEASE', match('[1.2.0.RELEASE,1.2.x.BUILD-SNAPSHOT]', - new VersionParser(Arrays.asList(Version.parse('1.2.9.BUILD-SNAPSHOT'))))) - } - - @Test - void matchOverLatestVersion() { - assertThat('1.2.10.RELEASE', not(match('[1.2.0.RELEASE,1.2.x.BUILD-SNAPSHOT]', - new VersionParser(Arrays.asList(Version.parse('1.2.9.BUILD-SNAPSHOT')))))) - } - - @Test - void matchAsOfCurrentVersion() { - assertThat('1.3.5.RELEASE', match('[1.3.x.RELEASE,1.3.x.BUILD-SNAPSHOT]', - new VersionParser(Arrays.asList(Version.parse('1.3.4.RELEASE'), - Version.parse('1.3.6.BUILD-SNAPSHOT'))))) - } - - @Test - void matchOverAsOfCurrentVersion() { - assertThat('1.3.5.RELEASE', not(match('[1.3.x.RELEASE,1.3.x.BUILD-SNAPSHOT]', - new VersionParser(Arrays.asList(Version.parse('1.3.7.RELEASE'), - Version.parse('1.3.6.BUILD-SNAPSHOT')))))) - } - - private static VersionRangeMatcher match(String range) { - new VersionRangeMatcher(range, new VersionParser(Collections.EMPTY_LIST)) - } - - private static VersionRangeMatcher match(String range, VersionParser parser) { - new VersionRangeMatcher(range, parser) - } - - - static class VersionRangeMatcher extends BaseMatcher { - - private final VersionRange range; - private final VersionParser parser; - - VersionRangeMatcher(String text, VersionParser parser) { - this.parser = parser - this.range = parser.parseRange(text) - } - - @Override - boolean matches(Object item) { - if (!item instanceof String) { - return false; - } - return this.range.match(this.parser.parse((String) item)) - } - - @Override - void describeTo(Description description) { - description.appendText(range.toString()) - } - } - -} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionTests.groovy b/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionTests.groovy deleted file mode 100644 index 12d730cf..00000000 --- a/initializr-generator/src/test/groovy/io/spring/initializr/util/VersionTests.groovy +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2012-2016 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 io.spring.initializr.util - -import org.junit.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.comparesEqualTo -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.greaterThan -import static org.hamcrest.Matchers.lessThan - -/** - * @author Stephane Nicoll - */ -class VersionTests { - - private static final VersionParser parser = new VersionParser(Collections.EMPTY_LIST) - - @Test - void equalNoQualifier() { - def first = parse('1.2.0') - def second = parse('1.2.0') - assertThat(first, comparesEqualTo(second)) - assertThat(first, equalTo(second)) - } - - @Test - void equalQualifierNoVersion() { - def first = parse('1.2.0.RELEASE') - def second = parse('1.2.0.RELEASE') - assertThat(first, comparesEqualTo(second)) - assertThat(first, equalTo(second)) - } - - @Test - void equalQualifierVersion() { - def first = parse('1.2.0.RC1') - def second = parse('1.2.0.RC1') - assertThat(first, comparesEqualTo(second)) - assertThat(first, equalTo(second)) - } - - @Test - void compareMajorOnly() { - assertThat(parse('2.2.0'), greaterThan(parse('1.8.0'))) - } - - @Test - void compareMinorOnly() { - assertThat(parse('2.2.0'), greaterThan(parse('2.1.9'))) - } - - @Test - void comparePatchOnly() { - assertThat(parse('2.2.4'), greaterThan(parse('2.2.3'))) - } - - @Test - void compareHigherVersion() { - assertThat(parse('1.2.0.RELEASE'), greaterThan(parse('1.1.9.RELEASE'))) - } - - @Test - void compareHigherQualifier() { - assertThat(parse('1.2.0.RC1'), greaterThan(parse('1.2.0.M1'))) - } - - @Test - void compareHigherQualifierVersion() { - assertThat(parse('1.2.0.RC2'), greaterThan(parse('1.2.0.RC1'))) - } - - @Test - void compareLowerVersion() { - assertThat(parse('1.0.5.RELEASE'), lessThan(parse('1.1.9.RELEASE'))) - } - - @Test - void compareLowerQualifier() { - assertThat(parse('1.2.0.RC1'), lessThan(parse('1.2.0.RELEASE'))) - } - - @Test - void compareLessQualifierVersion() { - assertThat(parse('1.2.0.RC2'), lessThan(parse('1.2.0.RC3'))) - } - - @Test - void compareWithNull() { - assertThat(parse('1.2.0.RC2'), greaterThan(null)) - } - - @Test - void compareUnknownQualifier() { - assertThat(parse('1.2.0.Beta'), lessThan(parse('1.2.0.CR'))) - } - - @Test - void compareUnknownQualifierVersion() { - assertThat(parse('1.2.0.Beta1'), lessThan(parse('1.2.0.Beta2'))) - } - - @Test - void snapshotGreaterThanRC() { - assertThat(parse('1.2.0.BUILD-SNAPSHOT'), greaterThan(parse('1.2.0.RC1'))) - } - - @Test - void snapshotLowerThanRelease() { - assertThat(parse('1.2.0.BUILD-SNAPSHOT'), lessThan(parse('1.2.0.RELEASE'))) - } - - private static Version parse(String text) { - def version = parser.parse(text) - version - } - -} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/AbstractProjectGeneratorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/AbstractProjectGeneratorTests.java new file mode 100644 index 00000000..6707b378 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/AbstractProjectGeneratorTests.java @@ -0,0 +1,144 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.generator; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentMatcher; +import org.springframework.context.ApplicationEventPublisher; + +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.SimpleInitializrMetadataProvider; +import io.spring.initializr.test.generator.GradleBuildAssert; +import io.spring.initializr.test.generator.PomAssert; +import io.spring.initializr.test.generator.ProjectAssert; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; + +/** + * + * @author Stephane Nicoll + */ +public abstract class AbstractProjectGeneratorTests { + + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + + protected final ProjectGenerator projectGenerator = new ProjectGenerator(); + + private final ApplicationEventPublisher eventPublisher = mock( + ApplicationEventPublisher.class); + + @Before + public void setup() throws IOException { + Dependency web = Dependency.withId("web"); + web.getFacets().add("web"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("web", web).addDependencyGroup("test", "security", + "data-jpa", "aop", "batch", "integration") + .build(); + applyMetadata(metadata); + projectGenerator.setEventPublisher(eventPublisher); + projectGenerator + .setRequestResolver(new ProjectRequestResolver(new ArrayList<>())); + projectGenerator.setTmpdir(folder.newFolder().getAbsolutePath()); + } + + protected PomAssert generateMavenPom(ProjectRequest request) { + request.setType("maven-build"); + String content = new String(projectGenerator.generateMavenPom(request)); + return new PomAssert(content).validateProjectRequest(request); + } + + protected GradleBuildAssert generateGradleBuild(ProjectRequest request) { + request.setType("gradle-build"); + String content = new String(projectGenerator.generateGradleBuild(request)); + return new GradleBuildAssert(content).validateProjectRequest(request); + } + + protected ProjectAssert generateProject(ProjectRequest request) { + File dir = projectGenerator.generateProjectStructure(request); + return new ProjectAssert(dir); + } + + public ProjectRequest createProjectRequest(String... styles) { + ProjectRequest request = new ProjectRequest(); + request.initialize(projectGenerator.getMetadataProvider().get()); + request.getStyle().addAll(Arrays.asList(styles)); + return request; + } + + protected void applyMetadata(InitializrMetadata metadata) { + projectGenerator.setMetadataProvider(new SimpleInitializrMetadataProvider(metadata)); + } + + protected void verifyProjectSuccessfulEventFor(ProjectRequest request) + { + verify(eventPublisher, times(1)).publishEvent(argThat(new ProjectGeneratedEventMatcher(request))); + } + + protected void verifyProjectFailedEventFor(ProjectRequest request, Exception ex) { + verify(eventPublisher, times(1)).publishEvent(argThat(new ProjectFailedEventMatcher(request, ex))); + } + + private static class ProjectGeneratedEventMatcher + extends ArgumentMatcher { + + private final ProjectRequest request; + + ProjectGeneratedEventMatcher(ProjectRequest request) { + this.request = request; + } + + @Override + public boolean matches(Object argument) { + ProjectGeneratedEvent event = (ProjectGeneratedEvent) argument; + return request.equals(event.getProjectRequest()); + } + } + + private static class ProjectFailedEventMatcher + extends ArgumentMatcher { + + private final ProjectRequest request; + private final Exception cause; + + ProjectFailedEventMatcher(ProjectRequest request, Exception cause) { + this.request = request; + this.cause = cause; + } + + @Override + public boolean matches(Object argument) { + ProjectFailedEvent event = (ProjectFailedEvent) argument; + return request.equals(event.getProjectRequest()) + && cause.equals(event.getCause()); + } + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/CommandLineHelpGeneratorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/CommandLineHelpGeneratorTests.java new file mode 100644 index 00000000..714fbad0 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/CommandLineHelpGeneratorTests.java @@ -0,0 +1,155 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.generator; + +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.Type; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; +import io.spring.initializr.util.GroovyTemplate; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +/** + * @author Stephane Nicoll + */ +public class CommandLineHelpGeneratorTests { + + private CommandLineHelpGenerator generator = new CommandLineHelpGenerator( + new GroovyTemplate()); + + @Test + public void generateGenericCapabilities() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", createDependency("id-b", "depB"), + createDependency("id-a", "depA", "and some description")) + .build(); + String content = generator.generateGenericCapabilities(metadata, + "https://fake-service"); + assertCommandLineCapabilities(content); + assertThat(content, containsString("id-a | and some description |")); + assertThat(content, containsString("id-b | depB")); + assertThat(content, containsString("https://fake-service")); + assertThat(content, not(containsString("Examples:"))); + assertThat(content, not(containsString("curl"))); + } + + @Test + public void generateCapabilitiesWithTypeDescription() { + Type type = new Type(); + type.setId("foo"); + type.setName("foo-name"); + type.setDescription("foo-desc"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addType(type).build(); + String content = generator.generateGenericCapabilities(metadata, + "https://fake-service"); + assertCommandLineCapabilities(content); + assertThat(content, containsString("| foo")); + assertThat(content, containsString("| foo-desc")); + } + + @Test + public void generateCurlCapabilities() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", createDependency("id-b", "depB"), + createDependency("id-a", "depA", "and some description")) + .build(); + String content = generator.generateCurlCapabilities(metadata, + "https://fake-service"); + assertCommandLineCapabilities(content); + assertThat(content, containsString("id-a | and some description |")); + assertThat(content, containsString("id-b | depB")); + assertThat(content, containsString("https://fake-service")); + assertThat(content, containsString("Examples:")); + assertThat(content, containsString("curl")); + } + + @Test + public void generateHttpCapabilities() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", createDependency("id-b", "depB"), + createDependency("id-a", "depA", "and some description")) + .build(); + String content = generator.generateHttpieCapabilities(metadata, + "https://fake-service"); + assertCommandLineCapabilities(content); + assertThat(content, containsString("id-a | and some description |")); + assertThat(content, containsString("id-b | depB")); + assertThat(content, containsString("https://fake-service")); + assertThat(content, containsString("Examples:")); + assertThat(content, not(containsString("curl"))); + assertThat(content, containsString("http https://fake-service")); + } + + @Test + public void generateSpringBootCliCapabilities() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", + createDependency("id-b", "depB"), + createDependency("id-a", "depA", "and some description")).build(); + String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service"); + assertThat(content, containsString("| Id")); + assertThat(content, containsString("| Tags")); + assertThat(content, containsString("id-a | and some description |")); + assertThat(content, containsString("id-b | depB")); + assertThat(content, containsString("https://fake-service")); + assertThat(content, not(containsString("Examples:"))); + assertThat(content, not(containsString("curl"))); + assertThat(content, not(containsString("| Rel"))); + assertThat(content, not(containsString("| dependencies"))); + assertThat(content, not(containsString("| applicationName"))); + assertThat(content, not(containsString("| baseDir"))); + } + + @Test + public void generateCapabilitiesWithVersionRange() { + Dependency first = Dependency.withId("first"); + first.setDescription("first desc"); + first.setVersionRange("1.2.0.RELEASE"); + Dependency second = Dependency.withId("second"); + second.setDescription("second desc"); + second.setVersionRange(" [1.2.0.RELEASE,1.3.0.M1) "); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", first, second).build(); + String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service"); + assertThat(content, containsString("| first | first desc | >=1.2.0.RELEASE |")); + assertThat(content, containsString("| second | second desc | >=1.2.0.RELEASE and <1.3.0.M1 |")); + } + + private static void assertCommandLineCapabilities(String content) { + assertThat(content, containsString("| Rel")); + assertThat(content, containsString("| dependencies")); + assertThat(content, containsString("| applicationName")); + assertThat(content, containsString("| baseDir")); + assertThat(content, not(containsString("| Tags"))); + } + + private static Dependency createDependency(String id, String name) { + return createDependency(id, name, null); + } + + private static Dependency createDependency(String id, String name, + String description) { + Dependency dependency = Dependency.withId(id); + dependency.setDescription(description); + dependency.setName(name); + return dependency; + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorBuildTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorBuildTests.java new file mode 100644 index 00000000..fca4fb5e --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorBuildTests.java @@ -0,0 +1,181 @@ +/* + * 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 io.spring.initializr.generator; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.springframework.core.io.ClassPathResource; + +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.test.generator.ProjectAssert; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; + +/** + * Project generator tests for supported build systems. + * + * @author Stephane Nicoll + */ +@RunWith(Parameterized.class) +public class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests { + + @Parameterized.Parameters(name = "{0}") + public static Object[] parameters() { + Object[] maven = new Object[] { "maven", "pom.xml" }; + Object[] gradle = new Object[] { "gradle", "build.gradle" }; + Object[] parameters = new Object[] { maven, gradle }; + return parameters; + } + + private final String build; + private final String fileName; + private final String assertFileName; + + public ProjectGeneratorBuildTests(String build, String fileName) { + this.build = build; + this.fileName = fileName; + this.assertFileName = fileName + ".gen"; + } + + @Test + public void standardJarJava() { + testStandardJar("java"); + } + + @Test + public void standardJarGroovy() { + testStandardJar("groovy"); + } + + @Test + public void standardJarKotlin() { + testStandardJar("kotlin"); + } + + private void testStandardJar(String language) { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName).equalsTo( + new ClassPathResource("project/" + language + "/standard/" + assertFileName)); + } + + @Test + public void standardWarJava() { + testStandardWar("java"); + } + + @Test + public void standardWarGroovy() { + testStandardWar("java"); + } + + @Test + public void standardWarKotlin() { + testStandardWar("kotlin"); + } + + private void testStandardWar(String language) { + ProjectRequest request = createProjectRequest("web"); + request.setPackaging("war"); + request.setLanguage(language); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName).equalsTo( + new ClassPathResource("project/" + language + "/war/" + assertFileName)); + } + + @Test + public void versionOverride() { + ProjectRequest request = createProjectRequest("web"); + request.getBuildProperties().getVersions().put("spring-foo.version", + () -> "0.1.0.RELEASE"); + request.getBuildProperties().getVersions().put("spring-bar.version", + () -> "0.2.0.RELEASE"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName).equalsTo(new ClassPathResource( + "project/" + build + "/version-override-" + assertFileName)); + } + + @Test + public void bomWithVersionProperty() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("the-bom"); + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom", "1.3.3"); + bom.setVersionProperty("foo.version"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).addBom("the-bom", bom).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName).equalsTo(new ClassPathResource( + "project/" + build + "/bom-property-" + assertFileName)); + } + + @Test + public void compileOnlyDependency() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setScope(Dependency.SCOPE_COMPILE_ONLY); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "data-jpa") + .addDependencyGroup("foo", foo) + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo", "web", "data-jpa"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName) + .equalsTo(new ClassPathResource("project/" + build + "/compile-only-dependency-" + assertFileName)); + } + + @Test + public void bomWithOrdering() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("foo-bom"); + BillOfMaterials barBom = BillOfMaterials.create("org.acme", "bar-bom", + "1.0"); + barBom.setOrder(50); + BillOfMaterials bizBom = BillOfMaterials.create("org.acme", "biz-bom"); + bizBom.setOrder(40); + bizBom.getAdditionalBoms().add("bar-bom"); + bizBom.getMappings().add(BillOfMaterials.Mapping.create("1.0.0.RELEASE", "1.0")); + BillOfMaterials fooBom = BillOfMaterials.create("org.acme", "foo-bom", + "1.0"); + fooBom.setOrder(20); + fooBom.getAdditionalBoms().add("biz-bom"); + + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo) + .addBom("foo-bom", fooBom) + .addBom("bar-bom", barBom) + .addBom("biz-bom", bizBom) + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(fileName) + .equalsTo(new ClassPathResource("project/" + build + "/bom-ordering-" + assertFileName)); + } + + @Override + public ProjectRequest createProjectRequest(String... styles) { + ProjectRequest request = super.createProjectRequest(styles); + request.setType(build + "-project"); + return request; + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorLanguageTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorLanguageTests.java new file mode 100644 index 00000000..1ebef325 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorLanguageTests.java @@ -0,0 +1,165 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.generator; + +import static io.spring.initializr.test.generator.ProjectAssert.DEFAULT_APPLICATION_NAME; +import static io.spring.initializr.test.generator.ProjectAssert.DEFAULT_PACKAGE_NAME; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.springframework.core.io.ClassPathResource; + +import io.spring.initializr.test.generator.ProjectAssert; + +/** + * Project generator tests for supported languages. + * + * @author Stephane Nicoll + */ +@RunWith(Parameterized.class) +public class ProjectGeneratorLanguageTests extends AbstractProjectGeneratorTests { + + @Parameterized.Parameters(name = "{0}") + public static Object[] parameters() { + Object[] java = new Object[] { "java", "java" }; + Object[] groovy = new Object[] { "groovy", "groovy" }; + Object[] kotlin = new Object[] { "kotlin", "kt" }; + Object[] parameters = new Object[] { java, groovy, kotlin }; + return parameters; + } + + private final String language; + private final String extension; + private final String expectedExtension; + + public ProjectGeneratorLanguageTests(String language, String extension) { + this.language = language; + this.extension = extension; + this.expectedExtension = extension + ".gen"; + } + + @Test + public void standardJar() { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + generateProject(request).isGenericProject(DEFAULT_PACKAGE_NAME, + DEFAULT_APPLICATION_NAME, language, extension); + } + + @Test + public void standardWar() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage(language); + request.setPackaging("war"); + generateProject(request).isGenericWarProject(DEFAULT_PACKAGE_NAME, + DEFAULT_APPLICATION_NAME, language, extension); + } + + @Test + public void standardMainClass() { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/main/" + language + "/com/example/DemoApplication." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/standard/DemoApplication." + expectedExtension)); + } + + @Test + public void standardTestClass() { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert( + "src/test/" + language + "/com/example/DemoApplicationTests." + extension) + .equalsTo(new ClassPathResource("project/" + language + + "/standard/DemoApplicationTests." + expectedExtension)); + } + + @Test + public void standardTestClassWeb() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage(language); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/test/" + language + "/com/example/DemoApplicationTests." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/standard/DemoApplicationTestsWeb." + expectedExtension)); + } + + @Test + public void standardServletInitializer() { + testServletInitializr(null, "standard"); + } + + @Test + public void springBoot14M2ServletInitializer() { + testServletInitializr("1.4.0.M2", "standard"); + } + + @Test + public void springBoot14ServletInitializer() { + testServletInitializr("1.4.0.M3", "spring-boot-1.4"); + } + + private void testServletInitializr(String bootVersion, String expectedOutput) { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + request.setPackaging("war"); + if (bootVersion!=null) { + request.setBootVersion(bootVersion); + } + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/main/" + language + "/com/example/ServletInitializer." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/" + expectedOutput + "/ServletInitializer." + expectedExtension)); + } + + @Test + public void springBoot14M1TestClass() { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + request.setBootVersion("1.4.0.M1"); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/test/" + language + "/com/example/DemoApplicationTests." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/standard/DemoApplicationTests." + expectedExtension)); + } + + @Test + public void springBoot14TestClass() { + ProjectRequest request = createProjectRequest(); + request.setLanguage(language); + request.setBootVersion("1.4.0.M2"); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/test/" + language + "/com/example/DemoApplicationTests." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/spring-boot-1.4/DemoApplicationTests." + expectedExtension)); + } + + @Test + public void springBoot14TestClassWeb() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage(language); + request.setBootVersion("1.4.0.M2"); + + ProjectAssert project = generateProject(request); + project.sourceCodeAssert("src/test/" + language + "/com/example/DemoApplicationTests." + extension) + .equalsTo(new ClassPathResource("project/" + language + "/spring-boot-1.4/DemoApplicationTests." + expectedExtension)); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorTests.java new file mode 100644 index 00000000..39539eb8 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectGeneratorTests.java @@ -0,0 +1,821 @@ +/* + * 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 io.spring.initializr.generator; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.util.Collections; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.test.generator.ProjectAssert; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; + +/** + * Tests for {@link ProjectGenerator} + * + * @author Stephane Nicoll + */ +public class ProjectGeneratorTests extends AbstractProjectGeneratorTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void defaultMavenPom() { + ProjectRequest request = createProjectRequest("web"); + generateMavenPom(request).hasNoRepository().hasSpringBootStarterDependency("web"); + verifyProjectSuccessfulEventFor(request); + } + + @Test + public void defaultGradleBuild() { + ProjectRequest request = createProjectRequest("web"); + generateGradleBuild(request); + verifyProjectSuccessfulEventFor(request); + } + + @Test + public void defaultProject() { + ProjectRequest request = createProjectRequest("web"); + generateProject(request).isJavaProject().isMavenProject().pomAssert() + .hasNoRepository().hasSpringBootStarterDependency("web"); + verifyProjectSuccessfulEventFor(request); + } + + @Test + public void noDependencyAddsRootStarter() { + ProjectRequest request = createProjectRequest(); + generateProject(request).isJavaProject().isMavenProject().pomAssert() + .hasSpringBootStarterRootDependency(); + } + + @Test + public void mavenPomWithBootSnapshot() { + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.0.1.BUILD-SNAPSHOT"); + generateMavenPom(request).hasSnapshotRepository() + .hasSpringBootParent("1.0.1.BUILD-SNAPSHOT") + .hasSpringBootStarterDependency("web"); + } + + @Test + public void mavenPomWithTarDependency() { + Dependency dependency = Dependency.withId("custom-artifact", "org.foo", + "custom-artifact"); + dependency.setType("tar.gz"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", dependency).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("custom-artifact"); + generateMavenPom(request).hasDependency(dependency).hasDependenciesCount(2); + } + + @Test + public void gradleBuildWithTarDependency() { + Dependency dependency = Dependency.withId("custom-artifact", "org.foo", + "custom-artifact"); + dependency.setType("tar.gz"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", dependency).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("custom-artifact"); + generateGradleBuild(request) + .contains("compile('org.foo:custom-artifact@tar.gz')"); + } + + @Test + public void mavenPomWithWebFacet() { + Dependency dependency = Dependency.withId("thymeleaf", "org.foo", "thymeleaf"); + dependency.getFacets().add("web"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("test", dependency).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("thymeleaf"); + generateMavenPom(request).hasDependency("org.foo", "thymeleaf") + .hasDependenciesCount(2); + } + + @Test + public void mavenWarWithWebFacet() { + Dependency dependency = Dependency.withId("thymeleaf", "org.foo", "thymeleaf"); + dependency.getFacets().add("web"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("test", dependency).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("thymeleaf"); + request.setPackaging("war"); + generateProject(request).isJavaWarProject().isMavenProject().pomAssert() + .hasSpringBootStarterTomcat() + // This is tagged as web facet so it brings the web one + .hasDependency("org.foo", "thymeleaf").hasSpringBootStarterTest() + .hasDependenciesCount(3); + } + + @Test + public void mavenWarPomWithoutWebFacet() { + ProjectRequest request = createProjectRequest("data-jpa"); + request.setPackaging("war"); + generateMavenPom(request).hasSpringBootStarterTomcat() + .hasSpringBootStarterDependency("data-jpa") + .hasSpringBootStarterDependency("web") // Added by war packaging + .hasSpringBootStarterTest().hasDependenciesCount(4); + } + + @Test + public void gradleWarWithWebFacet() { + Dependency dependency = Dependency.withId("thymeleaf", "org.foo", "thymeleaf"); + dependency.getFacets().add("web"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("test", dependency).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("thymeleaf"); + request.setPackaging("war"); + request.setType("gradle-project"); + generateProject(request).isJavaWarProject().isGradleProject().gradleBuildAssert() + .contains("compile('org.foo:thymeleaf')") // This is tagged as web facet + // so it brings the web one + .doesNotContain( + "compile('org.springframework.boot:spring-boot-starter-web')") + .contains( + "testCompile('org.springframework.boot:spring-boot-starter-test')") + .contains("configurations {") // declare providedRuntime config + .contains("providedRuntime").contains( + "providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')"); + } + + @Test + public void gradleWarPomWithoutWebFacet() { + ProjectRequest request = createProjectRequest("data-jpa"); + request.setPackaging("war"); + generateGradleBuild(request) + .contains( + "compile('org.springframework.boot:spring-boot-starter-data-jpa')") + .contains("compile('org.springframework.boot:spring-boot-starter-web')") // Added + // by + // war + // packaging + .contains( + "testCompile('org.springframework.boot:spring-boot-starter-test')") + .contains("configurations {") // declare providedRuntime config + .contains("providedRuntime").contains( + "providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')"); + } + + @Test + public void springBoot11UseEnableAutoConfigurationJava() { + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.1.9.RELEASE"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/java/foo/MyDemoApplication.java") + .hasImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .doesNotHaveImports(SpringBootApplication.class.getName()) + .contains("@EnableAutoConfiguration", "@Configuration", "@ComponentScan") + .doesNotContain("@SpringBootApplication"); + } + + @Test + public void springBootUseSpringBootApplicationJava() { + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.2.0.RC1"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/java/foo/MyDemoApplication.java") + .hasImports(SpringBootApplication.class.getName()) + .doesNotHaveImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .contains("@SpringBootApplication").doesNotContain( + "@EnableAutoConfiguration", "@Configuration", "@ComponentScan"); + } + + @Test + public void springBoot11UseEnableAutoConfigurationGroovy() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage("groovy"); + request.setBootVersion("1.1.9.RELEASE"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/groovy/foo/MyDemoApplication.groovy") + .hasImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .doesNotHaveImports(SpringBootApplication.class.getName()) + .contains("@EnableAutoConfiguration", "@Configuration", "@ComponentScan") + .doesNotContain("@SpringBootApplication"); + } + + @Test + public void springBootUseSpringBootApplicationGroovy() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage("groovy"); + request.setBootVersion("1.2.0.RC1"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/groovy/foo/MyDemoApplication.groovy") + .hasImports(SpringBootApplication.class.getName()) + .doesNotHaveImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .contains("@SpringBootApplication").doesNotContain( + "@EnableAutoConfiguration", "@Configuration", "@ComponentScan"); + } + + @Test + public void springBoot11UseEnableAutoConfigurationKotlin() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage("kotlin"); + request.setBootVersion("1.1.9.RELEASE"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/kotlin/foo/MyDemoApplication.kt") + .hasImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .doesNotHaveImports(SpringBootApplication.class.getName()) + .contains("@EnableAutoConfiguration", "@Configuration", "@ComponentScan") + .doesNotContain("@SpringBootApplication"); + } + + @Test + public void springBootUseSpringBootApplicationKotlin() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage("kotlin"); + request.setBootVersion("1.2.0.RC1"); + request.setName("MyDemo"); + request.setPackageName("foo"); + generateProject(request) + .sourceCodeAssert("src/main/kotlin/foo/MyDemoApplication.kt") + .hasImports(SpringBootApplication.class.getName()) + .doesNotHaveImports(EnableAutoConfiguration.class.getName(), + ComponentScan.class.getName(), Configuration.class.getName()) + .contains("@SpringBootApplication").doesNotContain( + "@EnableAutoConfiguration", "@Configuration", "@ComponentScan"); + } + + @Test + public void springBootUseGradle2() { + ProjectRequest request = createProjectRequest("web"); + request.setType("gradle-project"); + generateProject(request).isGradleProject("2.13"); + } + + @Test + public void springBoot2UseGradle3() { + ProjectRequest request = createProjectRequest("web"); + request.setType("gradle-project"); + request.setBootVersion("2.0.0.BUILD-SNAPSHOT"); + generateProject(request).isGradleProject("3.2.1"); + } + + @Test + public void customBaseDirectory() { + ProjectRequest request = createProjectRequest(); + request.setBaseDir("my-project"); + generateProject(request).hasBaseDir("my-project").isJavaProject() + .isMavenProject(); + } + + @Test + public void customBaseDirectoryNested() { + ProjectRequest request = createProjectRequest(); + request.setBaseDir("foo-bar/my-project"); + generateProject(request).hasBaseDir("foo-bar/my-project").isJavaProject() + .isMavenProject(); + } + + @Test + public void groovyWithMavenUsesGroovyDir() { + ProjectRequest request = createProjectRequest("web"); + request.setType("maven-project"); + request.setLanguage("groovy"); + generateProject(request).isMavenProject().isGroovyProject(); + } + + @Test + public void groovyWithGradleUsesGroovyDir() { + ProjectRequest request = createProjectRequest("web"); + request.setType("gradle-project"); + request.setLanguage("groovy"); + generateProject(request).isGradleProject().isGroovyProject(); + } + + @Test + public void mavenPomWithCustomVersion() { + Dependency whatever = Dependency.withId("whatever", "org.acme", "whatever", + "1.2.3"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("foo", whatever).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("whatever", "data-jpa", "web"); + generateMavenPom(request).hasDependency(whatever) + .hasSpringBootStarterDependency("data-jpa") + .hasSpringBootStarterDependency("web"); + } + + @Test + public void defaultMavenPomHasSpringBootParent() { + ProjectRequest request = createProjectRequest("web"); + generateMavenPom(request).hasSpringBootParent(request.getBootVersion()); + } + + @Test + public void mavenPomWithCustomParentPom() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .setMavenParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT", false).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("web"); + generateMavenPom(request).hasParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT") + .hasBomsCount(0); + } + + @Test + public void mavenPomWithCustomParentPomAndSpringBootBom() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .setMavenParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT", true).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.0.2.RELEASE"); + generateMavenPom(request).hasParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT") + .hasProperty("spring-boot.version", "1.0.2.RELEASE") + .hasBom("org.springframework.boot", "spring-boot-dependencies", + "${spring-boot.version}") + .hasBomsCount(1); + } + + @Test + public void gradleBuildWithCustomParentPomAndSpringBootBom() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .setMavenParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT", true).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.0.2.RELEASE"); + generateGradleBuild(request) + .doesNotContain("ext['spring-boot.version'] = '1.0.2.RELEASE'") + .doesNotContain( + "mavenBom \"org.springframework.boot:spring-boot-dependencies:1.0.2.RELEASE\""); + } + + @Test + public void gradleBuildWithBootSnapshot() { + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.0.1.BUILD-SNAPSHOT"); + generateGradleBuild(request).hasSnapshotRepository(); + } + + @Test + public void gradleBuildWithCustomVersion() { + Dependency whatever = Dependency.withId("whatever", "org.acme", "whatever", + "1.2.3"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("foo", whatever).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("whatever", "data-jpa", "web"); + generateGradleBuild(request) + .contains("compile('org.springframework.boot:spring-boot-starter-web')") + .contains( + "compile('org.springframework.boot:spring-boot-starter-data-jpa')") + .contains("compile('org.acme:whatever:1.2.3')"); + } + + @Test + public void mavenPomWithCustomScope() { + Dependency h2 = Dependency.withId("h2", "org.h2", "h2"); + h2.setScope("runtime"); + Dependency hamcrest = Dependency.withId("hamcrest", "org.hamcrest", "hamcrest"); + hamcrest.setScope("test"); + Dependency servlet = Dependency.withId("servlet-api", "javax.servlet", + "servlet-api"); + servlet.setScope("provided"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("database", h2) + .addDependencyGroup("container", servlet) + .addDependencyGroup("test", hamcrest).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("hamcrest", "h2", "servlet-api", + "data-jpa", "web"); + generateMavenPom(request).hasDependency(h2).hasDependency(hamcrest) + .hasDependency(servlet).hasSpringBootStarterDependency("data-jpa") + .hasSpringBootStarterDependency("web"); + } + + @Test + public void gradleBuildWithCustomScope() { + Dependency h2 = Dependency.withId("h2", "org.h2", "h2"); + h2.setScope("runtime"); + Dependency hamcrest = Dependency.withId("hamcrest", "org.hamcrest", "hamcrest"); + hamcrest.setScope("test"); + Dependency servlet = Dependency.withId("servlet-api", "javax.servlet", + "servlet-api"); + servlet.setScope("provided"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "security", "data-jpa") + .addDependencyGroup("database", h2) + .addDependencyGroup("container", servlet) + .addDependencyGroup("test", hamcrest).build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("hamcrest", "h2", "servlet-api", + "data-jpa", "web"); + generateGradleBuild(request) + .contains("compile('org.springframework.boot:spring-boot-starter-web')") + .contains( + "compile('org.springframework.boot:spring-boot-starter-data-jpa')") + .contains("runtime('org.h2:h2')").contains("configurations {") // declare + // providedRuntime + // config + .contains("providedRuntime") + .contains("providedRuntime('javax.servlet:servlet-api')") + .contains("testCompile('org.hamcrest:hamcrest')"); + } + + @Test + public void gradleBuildBeforeWithSpringBoot13() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "jpa").setGradleEnv("0.5.9.RELEASE") + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.2.3.RELEASE"); + generateGradleBuild(request).contains("springBootVersion = '1.2.3.RELEASE'") + .contains( + "classpath('io.spring.gradle:dependency-management-plugin:0.5.9.RELEASE')") + .contains("apply plugin: 'spring-boot'") + .contains("apply plugin: 'io.spring.dependency-management'"); + } + + @Test + public void gradleBuildAsFromSpringBoot13() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("core", "web", "jpa").setGradleEnv("0.5.9.RELEASE") + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.3.0.BUILD-SNAPSHOT"); + generateGradleBuild(request) + .contains("springBootVersion = '1.3.0.BUILD-SNAPSHOT'") + .contains("apply plugin: 'spring-boot'") + .doesNotContain( + "classpath('io.spring.gradle:dependency-management-plugin:0.5.9.RELEASE')") + .doesNotContain("apply plugin: 'io.spring.dependency-management'"); + } + + @Test + public void gradleBuildAsFromSpringBoot142() { + ProjectRequest request = createProjectRequest("web"); + request.setBootVersion("1.4.2.BUILD-SNAPSHOT"); + generateGradleBuild(request) + .contains("springBootVersion = '1.4.2.BUILD-SNAPSHOT'") + .contains("apply plugin: 'org.springframework.boot'") + .doesNotContain("apply plugin: 'spring-boot'"); + } + + @Test + public void mavenBom() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("foo-bom"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo) + .addBom("foo-bom", "org.acme", "foo-bom", "1.2.3").build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + generateMavenPom(request).hasDependency(foo).hasBom("org.acme", "foo-bom", + "1.2.3"); + } + + @Test + public void mavenBomWithSeveralDependenciesOnSameBom() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("the-bom"); + Dependency bar = Dependency.withId("bar", "org.acme", "bar"); + bar.setBom("the-bom"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("group", foo, bar) + .addBom("the-bom", "org.acme", "the-bom", "1.2.3").build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo", "bar"); + generateMavenPom(request).hasDependency(foo) + .hasBom("org.acme", "the-bom", "1.2.3").hasBomsCount(1); + } + + @Test + public void mavenBomWithVersionMapping() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("the-bom"); + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.0.0")); + bom.getMappings().add(BillOfMaterials.Mapping.create("1.3.0.M1", "1.2.0")); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).addBom("the-bom", bom).build(); + applyMetadata(metadata); + + // First version + ProjectRequest request = createProjectRequest("foo"); + request.setBootVersion("1.2.5.RELEASE"); + generateMavenPom(request).hasDependency(foo).hasSpringBootParent("1.2.5.RELEASE") + .hasBom("org.acme", "foo-bom", "1.0.0"); + + // Second version + ProjectRequest request2 = createProjectRequest("foo"); + request2.setBootVersion("1.3.0.M1"); + generateMavenPom(request2).hasDependency(foo).hasSpringBootParent("1.3.0.M1") + .hasBom("org.acme", "foo-bom", "1.2.0"); + } + + @Test + public void mavenBomWithVersionMappingAndExtraRepositories() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("the-bom"); + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getRepositories().add("foo-repo"); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.0.0")); + bom.getMappings().add(BillOfMaterials.Mapping.create("1.3.0.M1", "1.2.0", + "foo-repo", "bar-repo")); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).addBom("the-bom", bom) + .addRepository("foo-repo", "repo", "http://example.com/foo", true) + .addRepository("bar-repo", "repo", "http://example.com/bar", false) + .build(); + applyMetadata(metadata); + + // Second version + ProjectRequest request = createProjectRequest("foo"); + request.setBootVersion("1.3.0.RELEASE"); + generateMavenPom(request).hasDependency(foo).hasSpringBootParent("1.3.0.RELEASE") + .hasBom("org.acme", "foo-bom", "1.2.0") + .hasRepository("foo-repo", "repo", "http://example.com/foo", true) + .hasRepository("bar-repo", "repo", "http://example.com/bar", false) + .hasRepositoriesCount(2); + } + + @Test + public void gradleBom() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("foo-bom"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo) + .addBom("foo-bom", "org.acme", "foo-bom", "1.2.3").build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + generateGradleBuild(request).contains("dependencyManagement {") + .contains("imports {").contains("mavenBom \"org.acme:foo-bom:1.2.3\""); + } + + @Test + public void mavenRepository() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setRepository("foo-repo"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo) + .addRepository("foo-repo", "foo", "http://example.com/repo", false) + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + generateMavenPom(request).hasDependency(foo).hasRepository("foo-repo", "foo", + "http://example.com/repo", false); + } + + @Test + public void mavenRepositoryWithSeveralDependenciesOnSameRepository() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setRepository("the-repo"); + Dependency bar = Dependency.withId("bar", "org.acme", "bar"); + foo.setRepository("the-repo"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("group", foo, bar) + .addRepository("the-repo", "repo", "http://example.com/repo", true) + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo", "bar"); + generateMavenPom(request).hasDependency(foo) + .hasRepository("the-repo", "repo", "http://example.com/repo", true) + .hasRepositoriesCount(1); + } + + @Test + public void gradleRepository() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setRepository("foo-repo"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo) + .addRepository("foo-repo", "foo", "http://example.com/repo", false) + .build(); + applyMetadata(metadata); + ProjectRequest request = createProjectRequest("foo"); + generateGradleBuild(request).hasRepository("http://example.com/repo"); + } + + @Test + public void projectWithOnlyStarterDependency() { + Dependency foo = Dependency.withId("foo", "org.foo", "custom-my-starter"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("foo"); + generateMavenPom(request).hasDependency("org.foo", "custom-my-starter") + .hasSpringBootStarterTest().hasDependenciesCount(2); + } + + @Test + public void projectWithOnlyNonStarterDependency() { + Dependency foo = Dependency.withId("foo", "org.foo", "foo"); + foo.setStarter(false); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).build(); + applyMetadata(metadata); + + ProjectRequest request = createProjectRequest("foo"); + generateMavenPom(request).hasDependency("org.foo", "foo") + .hasSpringBootStarterRootDependency().hasSpringBootStarterTest() + .hasDependenciesCount(3); + } + + @Test + public void buildPropertiesMaven() { + ProjectRequest request = createProjectRequest("web"); + request.getBuildProperties().getMaven().put("name", () -> "test"); + request.getBuildProperties().getVersions().put("foo.version", () -> "1.2.3"); + request.getBuildProperties().getGradle().put("ignore.property", () -> "yes"); + + generateMavenPom(request).hasProperty("name", "test") + .hasProperty("foo.version", "1.2.3").hasNoProperty("ignore.property"); + } + + @Test + public void buildPropertiesGradle() { + ProjectRequest request = createProjectRequest("web"); + request.getBuildProperties().getGradle().put("name", () -> "test"); + request.getBuildProperties().getVersions().put("foo.version", () -> "1.2.3"); + request.getBuildProperties().getMaven().put("ignore.property", () -> "yes"); + + generateGradleBuild(request).contains("name = 'test'") + .contains("ext['foo.version'] = '1.2.3'") + .doesNotContain("ignore.property"); + } + + @Test + public void versionRangeWithPostProcessor() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.getMappings().add(Dependency.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", null, + null, "1.0.0")); + foo.getMappings().add(Dependency.Mapping.create("1.3.0.M1", null, null, "1.2.0")); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("foo", foo).build(); + applyMetadata(metadata); + + // First without processor, get the correct version + ProjectRequest request = createProjectRequest("foo"); + request.setBootVersion("1.2.5.RELEASE"); + generateMavenPom(request) + .hasDependency(Dependency.withId("foo", "org.acme", "foo", "1.0.0")); + + // First after processor that flips Spring Boot version + projectGenerator.setRequestResolver(new ProjectRequestResolver( + Collections.singletonList(new ProjectRequestPostProcessorAdapter() { + @Override + public void postProcessBeforeResolution(ProjectRequest r, + InitializrMetadata m) { + r.setBootVersion("1.3.0.M2"); + } + }))); + generateMavenPom(request) + .hasDependency(Dependency.withId("foo", "org.acme", "foo", "1.2.0")); + } + + @Test + public void gitIgnoreMaven() { + ProjectRequest request = createProjectRequest(); + request.setType("maven-project"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(".gitignore") + .equalsTo(new ClassPathResource("project/maven/gitignore.gen")); + } + + @Test + public void gitIgnoreGradle() { + ProjectRequest request = createProjectRequest(); + request.setType("gradle-project"); + ProjectAssert project = generateProject(request); + project.sourceCodeAssert(".gitignore") + .equalsTo(new ClassPathResource("project/gradle/gitignore.gen")); + } + + @Test + public void invalidProjectTypeMavenPom() { + ProjectRequest request = createProjectRequest("web"); + request.setType("gradle-build"); + this.thrown.expect(InvalidProjectRequestException.class); + this.thrown.expectMessage("gradle-build"); + projectGenerator.generateMavenPom(request); + } + + @Test + public void invalidProjectTypeGradleBuild() { + ProjectRequest request = createProjectRequest("web"); + request.setType("maven-build"); + this.thrown.expect(InvalidProjectRequestException.class); + this.thrown.expectMessage("maven-build"); + projectGenerator.generateGradleBuild(request); + } + + @Test + public void invalidDependency() { + ProjectRequest request = createProjectRequest("foo-bar"); + try { + generateMavenPom(request); + fail("Should have failed to generate project"); + } + catch (InvalidProjectRequestException ex) { + assertThat(ex.getMessage(), containsString("foo-bar")); + verifyProjectFailedEventFor(request, ex); + } + } + + @Test + public void invalidType() { + ProjectRequest request = createProjectRequest("web"); + request.setType("foo-bar"); + try { + generateProject(request); + fail("Should have failed to generate project"); + } + catch (InvalidProjectRequestException ex) { + assertThat(ex.getMessage(), containsString("foo-bar")); + verifyProjectFailedEventFor(request, ex); + } + } + + @Test + public void invalidPackaging() { + ProjectRequest request = createProjectRequest("web"); + request.setPackaging("foo-bar"); + try { + generateGradleBuild(request); + fail("Should have failed to generate project"); + } + catch (InvalidProjectRequestException ex) { + assertThat(ex.getMessage(), containsString("foo-bar")); + verifyProjectFailedEventFor(request, ex); + } + } + + @Test + public void invalidLanguage() { + ProjectRequest request = createProjectRequest("web"); + request.setLanguage("foo-bar"); + try { + generateProject(request); + fail("Should have failed to generate project"); + } + catch (InvalidProjectRequestException ex) { + assertThat(ex.getMessage(), containsString("foo-bar")); + verifyProjectFailedEventFor(request, ex); + } + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestResolverTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestResolverTests.java new file mode 100644 index 00000000..98f8de84 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestResolverTests.java @@ -0,0 +1,96 @@ +package io.spring.initializr.generator; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.BeanWrapperImpl; + +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; + +/** + * Tests for {@link ProjectRequestResolver}. + * + * @author Stephane Nicoll + */ +public class ProjectRequestResolverTests { + + private InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("test", "web", "security", "data-jpa") + .build(); + + final List postProcessors = new ArrayList<>(); + final GenericProjectRequestPostProcessor processor = new GenericProjectRequestPostProcessor(); + + @Before + public void setup() { + this.postProcessors.add(processor); + } + + @Test + public void beforeResolution() { + processor.before.put("javaVersion", "1.2"); + ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors); + assertEquals("1.2", request.getJavaVersion()); + assertEquals("1.2", request.getBuildProperties().getVersions().get("java.version").get()); + } + + @Test + public void afterResolution() { + postProcessors.add(new ProjectRequestPostProcessorAdapter() { + @Override + public void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { + request.getBuildProperties().getMaven().clear(); + request.getBuildProperties().getMaven().put("foo", () -> "bar"); + } + }); + ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors); + assertEquals(1, request.getBuildProperties().getMaven().size()); + assertEquals("bar", request.getBuildProperties().getMaven().get("foo").get()); + } + + ProjectRequest resolve(ProjectRequest request, List processors) { + return new ProjectRequestResolver(processors) + .resolve(request, metadata); + } + + ProjectRequest createMavenProjectRequest(String... styles) { + ProjectRequest request = createProjectRequest(styles); + request.setType("maven-project"); + return request; + } + + ProjectRequest createProjectRequest(String... styles) { + ProjectRequest request = new ProjectRequest(); + request.initialize(metadata); + request.getStyle().addAll(Arrays.asList(styles)); + return request; + } + + static class GenericProjectRequestPostProcessor implements ProjectRequestPostProcessor { + + final Map before = new LinkedHashMap<>(); + final Map after = new LinkedHashMap<>(); + + @Override + public void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) { + BeanWrapperImpl wrapper = new BeanWrapperImpl(request); + before.forEach((k, v) -> wrapper.setPropertyValue(k, v)); + } + + @Override + public void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) { + BeanWrapperImpl wrapper = new BeanWrapperImpl(request); + after.forEach((k, v) -> wrapper.setPropertyValue(k, v)); + } + + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestTests.java new file mode 100644 index 00000000..5f88dfe1 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/ProjectRequestTests.java @@ -0,0 +1,398 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.generator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.InitializrMetadataBuilder; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; + +/** + * @author Stephane Nicoll + */ +public class ProjectRequestTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void initializeProjectRequest() { + InitializrMetadata metadata = InitializrMetadataBuilder.create().build(); + metadata.getGroupId().setContent("org.acme"); + metadata.getArtifactId().setContent("my-project"); + ProjectRequest request = new ProjectRequest(); + request.initialize(metadata); + assertEquals("org.acme", request.getGroupId()); + assertEquals("my-project", request.getArtifactId()); + } + + @Test + public void initializeProjectRequestWithDefaults() { + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + ProjectRequest request = new ProjectRequest(); + request.initialize(metadata); + assertEquals(metadata.getName().getContent(), request.getName()); + assertEquals(metadata.getTypes().getDefault().getId(), request.getType()); + assertEquals(metadata.getDescription().getContent(), request.getDescription()); + assertEquals(metadata.getGroupId().getContent(), request.getGroupId()); + assertEquals(metadata.getArtifactId().getContent(), request.getArtifactId()); + assertEquals(metadata.getVersion().getContent(), request.getVersion()); + assertEquals(metadata.getBootVersions().getDefault().getId(), + request.getBootVersion()); + assertEquals(metadata.getPackagings().getDefault().getId(), + request.getPackaging()); + } + + @Test + public void resolve() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", "web", "security", "spring-data").build(); + + request.setType("maven-project"); + request.getStyle().addAll(Arrays.asList("web", "spring-data")); + request.resolve(metadata); + assertEquals("Build type not detected", "maven", request.getBuild()); + assertBootStarter(request.getResolvedDependencies().get(0), "web"); + assertBootStarter(request.getResolvedDependencies().get(1), "spring-data"); + } + + @Test + public void resolveWithDependencies() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", "web", "security", "spring-data").build(); + + request.setType("maven-project"); + request.getDependencies().addAll(Arrays.asList("web", "spring-data")); + request.resolve(metadata); + assertEquals("Build type not detected", "maven", request.getBuild()); + assertBootStarter(request.getResolvedDependencies().get(0), "web"); + assertBootStarter(request.getResolvedDependencies().get(1), "spring-data"); + } + + @Test + public void resolveFullMetadata() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", createDependency("org.foo", "acme", "1.2.0")) + .build(); + request.getStyle().add("org.foo:acme"); + request.resolve(metadata); + assertDependency(request.getResolvedDependencies().get(0), "org.foo", "acme", + "1.2.0"); + } + + @Test + public void resolveUnknownSimpleId() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", "org.foo:bar").build(); + + request.getStyle().addAll(Arrays.asList("org.foo:bar", "foo-bar")); + + thrown.expect(InvalidProjectRequestException.class); + thrown.expectMessage("foo-bar"); + request.resolve(metadata); + assertEquals(1, request.getResolvedDependencies().size()); + } + + @Test + public void resolveUnknownDependency() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", "org.foo:bar").build(); + + request.getStyle().add("org.foo:acme"); // does not exist + + thrown.expect(InvalidProjectRequestException.class); + thrown.expectMessage("org.foo:acme"); + request.resolve(metadata); + assertEquals(1, request.getResolvedDependencies().size()); + } + + @Test + public void resolveDependencyInRange() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = createDependency("org.foo", "bar", "1.2.0.RELEASE"); + dependency.setVersionRange("[1.0.1.RELEASE, 1.2.0.RELEASE)"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", dependency).build(); + + request.getStyle().add("org.foo:bar"); + request.setBootVersion("1.1.2.RELEASE"); + request.resolve(metadata); + } + + @Test + public void resolveDependencyNotInRange() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = createDependency("org.foo", "bar", "1.2.0.RELEASE"); + dependency.setVersionRange("[1.0.1.RELEASE, 1.2.0.RELEASE)"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", dependency).build(); + + request.getStyle().add("org.foo:bar"); + request.setBootVersion("0.9.9.RELEASE"); + + thrown.expect(InvalidProjectRequestException.class); + thrown.expectMessage("org.foo:bar"); + thrown.expectMessage("0.9.9.RELEASE"); + request.resolve(metadata); + } + + @Test + public void resolveDependencyVersion() { + Dependency dependency = createDependency("org.foo", "bar", "1.2.0.RELEASE"); + dependency.getMappings().add(Dependency.Mapping.create("[1.0.0.RELEASE, 1.1.0.RELEASE)", null, + null, "0.1.0.RELEASE")); + dependency.getMappings().add( + Dependency.Mapping.create("1.1.0.RELEASE", null, null, "0.2.0.RELEASE")); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addDependencyGroup("code", dependency).build(); + + ProjectRequest request = new ProjectRequest(); + request.setBootVersion("1.0.5.RELEASE"); + request.getStyle().add("org.foo:bar"); + request.resolve(metadata); + assertDependency(request.getResolvedDependencies().get(0), "org.foo", "bar", + "0.1.0.RELEASE"); + + ProjectRequest anotherRequest = new ProjectRequest(); + anotherRequest.setBootVersion("1.1.0.RELEASE"); + anotherRequest.getStyle().add("org.foo:bar"); + anotherRequest.resolve(metadata); + assertDependency(anotherRequest.getResolvedDependencies().get(0), "org.foo", + "bar", "0.2.0.RELEASE"); + } + + @Test + public void resolveBuild() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + request.setType("gradle-project"); + + request.resolve(metadata); + assertEquals("gradle", request.getBuild()); + } + + @Test + public void resolveBuildNoTag() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addType("foo", false, "/foo.zip", null, null).build(); + request.setType("foo"); + + request.resolve(metadata); + assertNull(request.getBuild()); + } + + @Test + public void resolveUnknownType() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + request.setType("foo-project"); + + thrown.expect(InvalidProjectRequestException.class); + thrown.expectMessage("foo-project"); + request.resolve(metadata); + } + + @Test + public void resolveApplicationNameWithNoName() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + + request.resolve(metadata); + assertEquals(metadata.getConfiguration().getEnv().getFallbackApplicationName(), + request.getApplicationName()); + } + + @Test + public void resolveApplicationName() { + ProjectRequest request = new ProjectRequest(); + request.setName("Foo2"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + + request.resolve(metadata); + assertEquals("Foo2Application", request.getApplicationName()); + } + + @Test + public void resolveApplicationNameWithApplicationNameSet() { + ProjectRequest request = new ProjectRequest(); + request.setName("Foo2"); + request.setApplicationName("MyApplicationName"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + + request.resolve(metadata); + assertEquals("MyApplicationName", request.getApplicationName()); + } + + @Test + public void cleanPackageNameWithNoName() { + ProjectRequest request = new ProjectRequest(); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + + request.resolve(metadata); + assertEquals(metadata.getPackageName().getContent(), request.getPackageName()); + } + + @Test + public void cleanPackageName() { + ProjectRequest request = new ProjectRequest(); + request.setPackageName("com:foo bar"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .build(); + + request.resolve(metadata); + assertEquals("com.foo.bar", request.getPackageName()); + } + + @Test + public void resolveAdditionalBoms() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = Dependency.withId("foo"); + dependency.setBom("foo-bom"); + BillOfMaterials bom = BillOfMaterials.create("com.example", "foo-bom", "1.0.0"); + bom.getAdditionalBoms().add("bar-bom"); + BillOfMaterials additionalBom = BillOfMaterials.create("com.example", "bar-bom", + "1.1.0"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addBom("foo-bom", bom).addBom("bar-bom", additionalBom) + .addDependencyGroup("test", dependency).build(); + request.getStyle().add("foo"); + request.resolve(metadata); + assertEquals(1, (request.getResolvedDependencies().size())); + assertEquals(2, request.getBoms().size()); + assertEquals(bom, request.getBoms().get("foo-bom")); + assertEquals(additionalBom, request.getBoms().get("bar-bom")); + } + + @Test + public void resolveAdditionalBomsDuplicates() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = Dependency.withId("foo"); + dependency.setBom("foo-bom"); + Dependency anotherDependency = Dependency.withId("bar"); + anotherDependency.setBom("bar-bom"); + BillOfMaterials bom = BillOfMaterials.create("com.example", "foo-bom", "1.0.0"); + bom.getAdditionalBoms().add("bar-bom"); + BillOfMaterials additionalBom = BillOfMaterials.create("com.example", "bar-bom", + "1.1.0"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addBom("foo-bom", bom).addBom("bar-bom", additionalBom) + .addDependencyGroup("test", dependency, anotherDependency).build(); + request.getStyle().addAll(Arrays.asList("foo", "bar")); + request.resolve(metadata); + assertEquals(2, request.getResolvedDependencies().size()); + assertEquals(2, request.getBoms().size()); + assertEquals(bom, request.getBoms().get("foo-bom")); + assertEquals(additionalBom, request.getBoms().get("bar-bom")); + } + + @Test + public void resolveAdditionalRepositories() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = Dependency.withId("foo"); + dependency.setBom("foo-bom"); + dependency.setRepository("foo-repo"); + BillOfMaterials bom = BillOfMaterials.create("com.example", "foo-bom", "1.0.0"); + bom.getRepositories().add("bar-repo"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addBom("foo-bom", bom) + .addRepository("foo-repo", "foo-repo", "http://example.com/foo", false) + .addRepository("bar-repo", "bar-repo", "http://example.com/bar", false) + .addDependencyGroup("test", dependency).build(); + request.getStyle().add("foo"); + request.resolve(metadata); + assertEquals(1, request.getResolvedDependencies().size()); + assertEquals(1, request.getBoms().size()); + assertEquals(2, request.getRepositories().size()); + assertEquals( + metadata.getConfiguration().getEnv().getRepositories().get("foo-repo"), + request.getRepositories().get("foo-repo")); + assertEquals( + metadata.getConfiguration().getEnv().getRepositories().get("bar-repo"), + request.getRepositories().get("bar-repo")); + } + + @Test + public void resolveAdditionalRepositoriesDuplicates() { + ProjectRequest request = new ProjectRequest(); + Dependency dependency = Dependency.withId("foo"); + dependency.setBom("foo-bom"); + dependency.setRepository("foo-repo"); + BillOfMaterials bom = BillOfMaterials.create("com.example", "foo-bom", "1.0.0"); + bom.getRepositories().add("bar-repo"); + Dependency anotherDependency = Dependency.withId("bar"); + anotherDependency.setRepository("bar-repo"); + InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() + .addBom("foo-bom", bom) + .addRepository("foo-repo", "foo-repo", "http://example.com/foo", false) + .addRepository("bar-repo", "bar-repo", "http://example.com/bar", false) + .addDependencyGroup("test", dependency, anotherDependency).build(); + request.getStyle().addAll(Arrays.asList("foo", "bar")); + request.resolve(metadata); + assertEquals(2, request.getResolvedDependencies().size()); + assertEquals(1, request.getBoms().size()); + assertEquals(2, request.getRepositories().size()); + assertEquals( + metadata.getConfiguration().getEnv().getRepositories().get("foo-repo"), + request.getRepositories().get("foo-repo")); + assertEquals( + metadata.getConfiguration().getEnv().getRepositories().get("bar-repo"), + request.getRepositories().get("bar-repo")); + } + + private static void assertBootStarter(Dependency actual, String name) { + Dependency expected = new Dependency(); + expected.asSpringBootStarter(name); + assertDependency(actual, expected.getGroupId(), expected.getArtifactId(), + expected.getVersion()); + assertEquals(name, actual.getId()); + } + + private static Dependency createDependency(String groupId, String artifactId, + String version) { + return Dependency.create(groupId, artifactId, version, Dependency.SCOPE_COMPILE); + } + + private static void assertDependency(Dependency actual, String groupId, + String artifactId, String version) { + assertEquals(groupId, actual.getGroupId()); + assertEquals(artifactId, actual.getArtifactId()); + assertEquals(version, actual.getVersion()); + } +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/BillOfMaterialsTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/BillOfMaterialsTests.java new file mode 100644 index 00000000..2d2e2026 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/BillOfMaterialsTests.java @@ -0,0 +1,143 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.metadata; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import io.spring.initializr.metadata.BillOfMaterials.Mapping; +import io.spring.initializr.util.Version; +import io.spring.initializr.util.VersionParser; + +/** + * @author Stephane Nicoll + */ +public class BillOfMaterialsTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void resolveSimpleBom() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom", "1.0.0"); + bom.validate(); + BillOfMaterials resolved = bom.resolve(Version.parse("1.2.3.RELEASE")); + assertThat(bom, sameInstance(resolved)); + } + + @Test + public void resolveSimpleRange() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom", "1.0.0"); + bom.setVersionProperty("bom.version"); + bom.getRepositories().add("repo-main"); + bom.getAdditionalBoms().add("bom-main"); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.1.0")); + bom.validate(); + BillOfMaterials resolved = bom.resolve(Version.parse("1.2.3.RELEASE")); + assertThat(resolved.getGroupId(), equalTo("com.example")); + assertThat(resolved.getArtifactId(), equalTo("bom")); + assertThat(resolved.getVersion(), equalTo("1.1.0")); + assertThat(resolved.getVersionProperty(), equalTo("bom.version")); + assertThat(resolved.getRepositories().size(), equalTo(1)); + assertThat(resolved.getRepositories().get(0), equalTo("repo-main")); + assertThat(resolved.getAdditionalBoms().size(), equalTo(1)); + assertThat(resolved.getAdditionalBoms().get(0), equalTo("bom-main")); + } + + @Test + public void resolveRangeOverride() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom", "1.0.0"); + bom.getRepositories().add("repo-main"); + bom.getAdditionalBoms().add("bom-main"); + Mapping mapping = BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", + "1.1.0", "repo-foo"); + mapping.getAdditionalBoms().add("bom-foo"); + bom.getMappings().add(mapping); + bom.validate(); + BillOfMaterials resolved = bom.resolve(Version.parse("1.2.3.RELEASE")); + assertThat(resolved.getGroupId(), equalTo("com.example")); + assertThat(resolved.getArtifactId(), equalTo("bom")); + assertThat(resolved.getVersion(), equalTo("1.1.0")); + assertThat(resolved.getVersionProperty(), nullValue()); + assertThat(resolved.getRepositories().size(), equalTo(1)); + assertThat(resolved.getRepositories().get(0), equalTo("repo-foo")); + assertThat(resolved.getAdditionalBoms().size(), equalTo(1)); + assertThat(resolved.getAdditionalBoms().get(0), equalTo("bom-foo")); + } + + @Test + public void resolveRangeOverrideAndMapping() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom", "1.0.0"); + bom.setVersionProperty("example.version"); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.1.0")); + bom.validate(); + BillOfMaterials resolved = bom.resolve(Version.parse("1.2.3.RELEASE")); + assertThat(resolved.getGroupId(), equalTo("com.example")); + assertThat(resolved.getArtifactId(), equalTo("bom")); + assertThat(resolved.getVersion(), equalTo("1.1.0")); + assertThat(resolved.getVersionProperty(), equalTo("example.version")); + } + + @Test + public void noRangeAvailable() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom"); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.1.0")); + bom.getMappings() + .add(BillOfMaterials.Mapping.create("[1.3.0.M1, 1.4.0.M1)", "1.2.0")); + bom.validate(); + + thrown.expect(IllegalStateException.class); + thrown.expectMessage("1.4.1.RELEASE"); + bom.resolve(Version.parse("1.4.1.RELEASE")); + } + + @Test + public void resolveRangeWithVariablePatch() { + BillOfMaterials bom = BillOfMaterials.create("com.example", "bom", "1.0.0"); + bom.getMappings().add( + BillOfMaterials.Mapping.create("[1.3.0.RELEASE,1.3.x.RELEASE]", "1.1.0")); + bom.getMappings().add(BillOfMaterials.Mapping + .create("[1.3.x.BUILD-SNAPSHOT,1.4.0.RELEASE)", "1.1.1-SNAPSHOT")); + bom.validate(); + + bom.updateVersionRange(new VersionParser(Arrays.asList( + Version.parse("1.3.8.RELEASE"), Version.parse("1.3.9.BUILD-SNAPSHOT")))); + assertThat(bom.resolve(Version.parse("1.3.8.RELEASE")).getVersion(), + equalTo("1.1.0")); + assertThat(bom.resolve(Version.parse("1.3.9.RELEASE")).getVersion(), + equalTo("1.1.1-SNAPSHOT")); + + bom.updateVersionRange(new VersionParser(Arrays.asList( + Version.parse("1.3.9.RELEASE"), Version.parse("1.3.10.BUILD-SNAPSHOT")))); + assertThat(bom.resolve(Version.parse("1.3.8.RELEASE")).getVersion(), + equalTo("1.1.0")); + assertThat(bom.resolve(Version.parse("1.3.9.RELEASE")).getVersion(), + equalTo("1.1.0")); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/DependenciesCapabilityTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/DependenciesCapabilityTests.java new file mode 100644 index 00000000..3cfee0a6 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/DependenciesCapabilityTests.java @@ -0,0 +1,173 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.metadata; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +/** + * @author Stephane Nicoll + */ +public class DependenciesCapabilityTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void indexedDependencies() { + Dependency dependency = Dependency.withId("first"); + Dependency dependency2 = Dependency.withId("second"); + DependenciesCapability capability = createDependenciesCapability("foo", + dependency, dependency2); + capability.validate(); + + assertSame(dependency, capability.get("first")); + assertSame(dependency2, capability.get("second")); + assertNull(capability.get("anotherId")); + } + + @Test + public void addTwoDependenciesWithSameId() { + Dependency dependency = Dependency.withId("conflict"); + Dependency dependency2 = Dependency.withId("conflict"); + DependenciesCapability capability = createDependenciesCapability("foo", + dependency, dependency2); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("conflict"); + capability.validate(); + } + + @Test + public void addDependencyWithAliases() { + Dependency dependency = Dependency.withId("first"); + dependency.getAliases().add("alias1"); + dependency.getAliases().add("alias2"); + DependenciesCapability capability = createDependenciesCapability("foo", + dependency); + capability.validate(); + + assertSame(dependency, capability.get("first")); + assertSame(dependency, capability.get("alias1")); + assertSame(dependency, capability.get("alias2")); + } + + @Test + public void aliasClashWithAnotherDependency() { + Dependency dependency = Dependency.withId("first"); + dependency.getAliases().add("alias1"); + dependency.getAliases().add("alias2"); + Dependency dependency2 = Dependency.withId("alias2"); + + DependenciesCapability capability = new DependenciesCapability(); + capability.getContent().add(createDependencyGroup("foo", dependency)); + capability.getContent().add(createDependencyGroup("bar", dependency2)); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("alias2"); + capability.validate(); + } + + @Test + public void mergeAddEntry() { + DependenciesCapability capability = createDependenciesCapability("foo", + Dependency.withId("first"), Dependency.withId("second")); + + DependenciesCapability anotherCapability = createDependenciesCapability("foo", + Dependency.withId("bar"), Dependency.withId("biz")); + anotherCapability.getContent() + .add(createDependencyGroup("bar", Dependency.withId("third"))); + + capability.merge(anotherCapability); + assertEquals(2, capability.getContent().size()); + assertNotNull(capability.get("first")); + assertNotNull(capability.get("second")); + assertNotNull(capability.get("third")); + } + + @Test + public void addDefaultVersionRange() { + Dependency first = Dependency.withId("first"); + Dependency second = Dependency.withId("second"); + second.setVersionRange("1.2.3.RELEASE"); + DependencyGroup group = createDependencyGroup("test", first, second); + group.setVersionRange("1.2.0.RELEASE"); + + DependenciesCapability capability = new DependenciesCapability(); + capability.getContent().add(group); + capability.validate(); + + assertEquals("1.2.0.RELEASE", capability.get("first").getVersionRange()); + assertEquals("1.2.3.RELEASE", capability.get("second").getVersionRange()); + } + + @Test + public void addDefaultBom() { + Dependency first = Dependency.withId("first"); + Dependency second = Dependency.withId("second"); + second.setBom("da-bom"); + DependencyGroup group = createDependencyGroup("test", first, second); + group.setBom("test-bom"); + + DependenciesCapability capability = new DependenciesCapability(); + capability.getContent().add(group); + capability.validate(); + + assertEquals("test-bom", capability.get("first").getBom()); + assertEquals("da-bom", capability.get("second").getBom()); + } + + @Test + public void addDefaultRepository() { + Dependency first = Dependency.withId("first"); + Dependency second = Dependency.withId("second"); + second.setRepository("da-repo"); + DependencyGroup group = createDependencyGroup("test", first, second); + group.setRepository("test-repo"); + + DependenciesCapability capability = new DependenciesCapability(); + capability.getContent().add(group); + capability.validate(); + + assertEquals("test-repo", capability.get("first").getRepository()); + assertEquals("da-repo", capability.get("second").getRepository()); + } + + private static DependenciesCapability createDependenciesCapability(String groupName, + Dependency... dependencies) { + DependenciesCapability capability = new DependenciesCapability(); + DependencyGroup group = createDependencyGroup(groupName, dependencies); + capability.getContent().add(group); + return capability; + } + + private static DependencyGroup createDependencyGroup(String groupName, + Dependency... dependencies) { + DependencyGroup group = DependencyGroup.create(groupName); + for (Dependency dependency : dependencies) { + group.getContent().add(dependency); + } + return group; + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/DependencyTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/DependencyTests.java new file mode 100644 index 00000000..f90272a7 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/DependencyTests.java @@ -0,0 +1,270 @@ +/* + * 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 io.spring.initializr.metadata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import java.util.Arrays; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import io.spring.initializr.util.Version; +import io.spring.initializr.util.VersionParser; + +/** + * @author Stephane Nicoll + */ +public class DependencyTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void createRootSpringBootStarter() { + Dependency d = new Dependency(); + d.asSpringBootStarter(""); + assertEquals("org.springframework.boot", d.getGroupId()); + assertEquals("spring-boot-starter", d.getArtifactId()); + } + + @Test + public void setCoordinatesFromId() { + Dependency dependency = Dependency.withId("org.foo:bar:1.2.3"); + dependency.resolve(); + assertEquals("org.foo", dependency.getGroupId()); + assertEquals("bar", dependency.getArtifactId()); + assertEquals("1.2.3", dependency.getVersion()); + assertEquals("org.foo:bar:1.2.3", dependency.getId()); + } + + @Test + public void setCoordinatesFromIdNoVersion() { + Dependency dependency = Dependency.withId("org.foo:bar"); + dependency.resolve(); + assertEquals("org.foo", dependency.getGroupId()); + assertEquals("bar", dependency.getArtifactId()); + assertNull(dependency.getVersion()); + assertEquals("org.foo:bar", dependency.getId()); + } + + @Test + public void setIdFromCoordinates() { + Dependency dependency = new Dependency(); + dependency.setGroupId("org.foo"); + dependency.setArtifactId("bar"); + dependency.setVersion("1.0"); + dependency.resolve(); + assertEquals("org.foo:bar", dependency.getId()); + } + + @Test + public void setIdFromCoordinatesNoVersion() { + Dependency dependency = new Dependency(); + dependency.setGroupId("org.foo"); + dependency.setArtifactId("bar"); + dependency.resolve(); + assertEquals("org.foo:bar", dependency.getId()); + } + + @Test + public void setIdFromSimpleName() { + Dependency dependency = Dependency.withId("web"); + dependency.resolve(); + assertEquals("org.springframework.boot", dependency.getGroupId()); + assertEquals("spring-boot-starter-web", dependency.getArtifactId()); + assertNull(dependency.getVersion()); + assertEquals("web", dependency.getId()); + } + + @Test + public void invalidDependency() { + thrown.expect(InvalidInitializrMetadataException.class); + new Dependency().resolve(); + } + + @Test + public void invalidDependencyScope() { + Dependency dependency = Dependency.withId("web"); + + thrown.expect(InvalidInitializrMetadataException.class); + dependency.setScope("whatever"); + } + + @Test + public void invalidSpringBootRange() { + Dependency dependency = Dependency.withId("web"); + dependency.setVersionRange("A.B.C"); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("A.B.C"); + dependency.resolve(); + } + + @Test + public void invalidIdFormatTooManyColons() { + Dependency dependency = Dependency.withId("org.foo:bar:1.0:test:external"); + + thrown.expect(InvalidInitializrMetadataException.class); + dependency.resolve(); + } + + @Test + public void invalidLink() { + Dependency dependency = Dependency.withId("foo"); + dependency.getLinks().add(Link.create(null, "https://example.com")); + + thrown.expect(InvalidInitializrMetadataException.class); + dependency.resolve(); + } + + @Test + public void generateIdWithNoGroupId() { + Dependency dependency = new Dependency(); + dependency.setArtifactId("bar"); + thrown.expect(IllegalArgumentException.class); + dependency.generateId(); + } + + @Test + public void generateIdWithNoArtifactId() { + Dependency dependency = new Dependency(); + dependency.setGroupId("foo"); + thrown.expect(IllegalArgumentException.class); + dependency.generateId(); + } + + @Test + public void resolveNoMapping() { + Dependency dependency = Dependency.withId("web"); + dependency.resolve(); + assertSame(dependency, dependency.resolve(Version.parse("1.2.0.RELEASE"))); + } + + @Test + public void resolveInvalidMapping() { + Dependency dependency = Dependency.withId("web"); + dependency.getMappings() + .add(Dependency.Mapping.create("foo-bar", null, null, "0.1.0.RELEASE")); + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("foo-bar"); + dependency.resolve(); + } + + @Test + public void resolveVersionRequirement() { + Dependency dependency = Dependency.withId("web"); + dependency.getMappings().add(Dependency.Mapping + .create("[1.1.0.RELEASE, 1.2.0.RELEASE)", null, null, "0.1.0.RELEASE")); + dependency.resolve(); + Dependency resolved = dependency.resolve(Version.parse("1.1.5.RELEASE")); + assertEquals(">=1.1.0.RELEASE and <1.2.0.RELEASE", + resolved.getVersionRequirement()); + } + + @Test + public void resolveMatchingVersionMapping() { + Dependency dependency = Dependency.withId("web", null, null, "0.3.0.RELEASE"); + dependency.setDescription("A web dependency"); + dependency.getKeywords().addAll(Arrays.asList("foo", "bar")); + dependency.getAliases().add("the-web"); + dependency.getFacets().add("web"); + dependency.getMappings().add(Dependency.Mapping + .create("[1.1.0.RELEASE, 1.2.0.RELEASE)", null, null, "0.1.0.RELEASE")); + dependency.getMappings().add(Dependency.Mapping + .create("[1.2.0.RELEASE, 1.3.0.RELEASE)", null, null, "0.2.0.RELEASE")); + dependency.resolve(); + + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.5.RELEASE")), + "org.springframework.boot", "spring-boot-starter-web", "0.1.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.2.0.RELEASE")), + "org.springframework.boot", "spring-boot-starter-web", "0.2.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("2.1.3.M1")), + "org.springframework.boot", "spring-boot-starter-web", "0.3.0.RELEASE"); // default + } + + @Test + public void resolveMatchArtifactMapping() { + Dependency dependency = Dependency.withId("web", null, null, "0.3.0.RELEASE"); + dependency.setDescription("A web dependency"); + dependency.getKeywords().addAll(Arrays.asList("foo", "bar")); + dependency.getAliases().add("the-web"); + dependency.getFacets().add("web"); + dependency.getMappings().add(Dependency.Mapping + .create("[1.1.0.RELEASE, 1.2.0.RELEASE)", "org.spring.boot", null, null)); + dependency.getMappings().add(Dependency.Mapping + .create("[1.2.0.RELEASE, 1.3.0.RELEASE)", null, "starter-web", null)); + dependency.resolve(); + + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.5.RELEASE")), + "org.spring.boot", "spring-boot-starter-web", "0.3.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.2.0.RELEASE")), + "org.springframework.boot", "starter-web", "0.3.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("2.1.3.M1")), + "org.springframework.boot", "spring-boot-starter-web", "0.3.0.RELEASE"); // default + } + + @Test + public void resolveMatchingVersionWithVariablePatch() { + Dependency dependency = Dependency.withId("web", null, null, "0.3.0.RELEASE"); + dependency.setDescription("A web dependency"); + dependency.getKeywords().addAll(Arrays.asList("foo", "bar")); + dependency.getAliases().add("the-web"); + dependency.getFacets().add("web"); + dependency.getMappings().add(Dependency.Mapping + .create("[1.1.0.RELEASE, 1.1.x.RELEASE]", null, null, "0.1.0.RELEASE")); + dependency.getMappings().add(Dependency.Mapping + .create("[1.1.x.BUILD-SNAPSHOT, 1.2.0.RELEASE)", null, null, "0.2.0.RELEASE")); + dependency.resolve(); + + dependency.updateVersionRanges(new VersionParser(Arrays.asList( + Version.parse("1.1.5.RELEASE"), Version.parse("1.1.6.BUILD-SNAPSHOT")))); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.5.RELEASE")), + "org.springframework.boot", "spring-boot-starter-web", "0.1.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.6.BUILD-SNAPSHOT")), + "org.springframework.boot", "spring-boot-starter-web", "0.2.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("2.1.3.M1")), + "org.springframework.boot", "spring-boot-starter-web", "0.3.0.RELEASE"); // default + + dependency.updateVersionRanges(new VersionParser(Arrays.asList( + Version.parse("1.1.6.RELEASE"), Version.parse("1.1.7.BUILD-SNAPSHOT")))); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.5.RELEASE")), + "org.springframework.boot", "spring-boot-starter-web", "0.1.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.6.RELEASE")), + "org.springframework.boot", "spring-boot-starter-web", "0.1.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("1.1.7.BUILD-SNAPSHOT")), + "org.springframework.boot", "spring-boot-starter-web", "0.2.0.RELEASE"); + validateResolvedWebDependency(dependency.resolve(Version.parse("2.1.3.M1")), + "org.springframework.boot", "spring-boot-starter-web", "0.3.0.RELEASE"); // default + } + + private static void validateResolvedWebDependency(Dependency dependency, + String expectedGroupId, String expectedArtifactId, String expectedVersion) { + assertEquals(expectedVersion, dependency.getVersion()); + assertEquals("web", dependency.getId()); + assertEquals(expectedGroupId, dependency.getGroupId()); + assertEquals(expectedArtifactId, dependency.getArtifactId()); + assertEquals(2, dependency.getKeywords().size()); + assertEquals(1, dependency.getAliases().size()); + assertEquals(1, dependency.getFacets().size()); + + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrConfigurationTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrConfigurationTests.java new file mode 100644 index 00000000..4e753b9b --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrConfigurationTests.java @@ -0,0 +1,156 @@ +/* + * 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 io.spring.initializr.metadata; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Stephane Nicoll + */ +public class InitializrConfigurationTests { + + private final InitializrConfiguration properties = new InitializrConfiguration(); + + @Test + public void generateApplicationNameSimple() { + assertEquals("DemoApplication", this.properties.generateApplicationName("demo")); + } + + @Test + public void generateApplicationNameSimpleApplication() { + assertEquals("DemoApplication", this.properties.generateApplicationName("demoApplication")); + } + + @Test + public void generateApplicationNameSimpleCamelCase() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("myDemo")); + } + + @Test + public void generateApplicationNameSimpleUnderscore() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("my_demo")); + } + + @Test + public void generateApplicationNameSimpleColon() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("my:demo")); + } + + @Test + public void generateApplicationNameSimpleSpace() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("my demo")); + } + + @Test + public void generateApplicationNameSimpleDash() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("my-demo")); + } + + @Test + public void generateApplicationNameUpperCaseUnderscore() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("MY_DEMO")); + } + + @Test + public void generateApplicationNameUpperCaseDash() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName("MY-DEMO")); + } + + @Test + public void generateApplicationNameMultiSpaces() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName(" my demo ")); + } + + @Test + public void generateApplicationNameMultiSpacesUpperCase() { + assertEquals("MyDemoApplication", this.properties.generateApplicationName(" MY DEMO ")); + } + + @Test + public void generateApplicationNameNull() { + assertEquals(this.properties.getEnv().getFallbackApplicationName(), this.properties.generateApplicationName(null)); + } + + @Test + public void generateApplicationNameInvalidStartCharacter() { + assertEquals(this.properties.getEnv().getFallbackApplicationName(), this.properties.generateApplicationName("1MyDemo")); + } + + @Test + public void generateApplicationNameInvalidPartCharacter() { + assertEquals(this.properties.getEnv().getFallbackApplicationName(), this.properties.generateApplicationName("MyDe|mo")); + } + + @Test + public void generateApplicationNameInvalidApplicationName() { + assertEquals(this.properties.getEnv().getFallbackApplicationName(), this.properties.generateApplicationName("SpringBoot")); + } + + @Test + public void generateApplicationNameAnotherInvalidApplicationName() { + assertEquals(this.properties.getEnv().getFallbackApplicationName(), this.properties.generateApplicationName("Spring")); + } + + @Test + public void generatePackageNameSimple() { + assertEquals("com.foo", this.properties.cleanPackageName("com.foo", "com.example")); + } + + @Test + public void generatePackageNameSimpleUnderscore() { + assertEquals("com.my_foo", this.properties.cleanPackageName("com.my_foo", "com.example")); + } + + @Test + public void generatePackageNameSimpleColon() { + assertEquals("com.foo", this.properties.cleanPackageName("com:foo", "com.example")); + } + + @Test + public void generatePackageNameMultipleDashers() { + assertEquals("com.foo", this.properties.cleanPackageName("com--foo", "com.example")); + } + + @Test + public void generatePackageNameMultipleSpaces() { + assertEquals("com.foo", this.properties.cleanPackageName(" com foo ", "com.example")); + } + + @Test + public void generatePackageNameNull() { + assertEquals("com.example", this.properties.cleanPackageName(null, "com.example")); + } + + @Test + public void generatePackageNameInvalidStartCharacter() { + assertEquals("com.example", this.properties.cleanPackageName("0om.foo", "com.example")); + } + + @Test + public void generatePackageNameInvalidPackageName() { + assertEquals("com.example", this.properties.cleanPackageName("org.springframework", "com.example")); + } + + @Test + public void validateArtifactRepository() { + this.properties.getEnv().setArtifactRepository("http://foo/bar"); + assertEquals("http://foo/bar/", this.properties.getEnv().getArtifactRepository()); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataBuilderTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataBuilderTests.java new file mode 100644 index 00000000..d3013a37 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataBuilderTests.java @@ -0,0 +1,232 @@ +/* + * 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 io.spring.initializr.metadata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.net.URL; +import java.util.Map; +import java.util.Properties; + +import org.junit.Test; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.boot.bind.PropertiesConfigurationFactory; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +/** + * @author Stephane Nicoll + */ +public class InitializrMetadataBuilderTests { + + @Test + public void loadDefaultConfig() { + InitializrProperties bean = load( + new ClassPathResource("application-test-default.yml")); + InitializrMetadata metadata = InitializrMetadataBuilder + .fromInitializrProperties(bean).build(); + assertDefaultConfig(metadata); + } + + @Test + public void mergeIdenticalConfig() { + InitializrProperties bean = load( + new ClassPathResource("application-test-default.yml")); + InitializrMetadata metadata = InitializrMetadataBuilder + .fromInitializrProperties(bean).withInitializrProperties(bean, true) + .build(); + assertDefaultConfig(metadata); + } + + @Test + public void mergeConfig() { + InitializrProperties config = load( + new ClassPathResource("application-test-default.yml")); + InitializrProperties customDefaultsConfig = load( + new ClassPathResource("application-test-custom-defaults.yml")); + InitializrMetadata metadata = InitializrMetadataBuilder + .fromInitializrProperties(config) + .withInitializrProperties(customDefaultsConfig).build(); + assertDefaultConfig(metadata); + assertEquals("org.foo", metadata.getGroupId().getContent()); + assertEquals("foo-bar", metadata.getArtifactId().getContent()); + assertEquals("1.2.4-SNAPSHOT", metadata.getVersion().getContent()); + assertEquals("FooBar", metadata.getName().getContent()); + assertEquals("FooBar Project", metadata.getDescription().getContent()); + assertEquals("org.foo.demo", metadata.getPackageName().getContent()); + } + + @Test + public void mergeMetadata() { + InitializrMetadata metadata = InitializrMetadataBuilder.create() + .withInitializrMetadata( + new ClassPathResource("metadata/config/test-min.json")) + .build(); + assertEquals(false, metadata.getConfiguration().getEnv().isForceSsl()); + assertEquals(1, metadata.getDependencies().getContent().size()); + Dependency dependency = metadata.getDependencies().get("test"); + assertNotNull(dependency); + assertEquals("org.springframework.boot", dependency.getGroupId()); + assertEquals(1, metadata.getTypes().getContent().size()); + assertEquals(2, metadata.getBootVersions().getContent().size()); + assertEquals(2, metadata.getPackagings().getContent().size()); + assertEquals(1, metadata.getJavaVersions().getContent().size()); + assertEquals(3, metadata.getLanguages().getContent().size()); + assertEquals("metadata-merge", metadata.getName().getContent()); + assertEquals("Demo project for metadata merge", + metadata.getDescription().getContent()); + assertEquals("org.acme", metadata.getGroupId().getContent()); + assertEquals("metadata", metadata.getArtifactId().getContent()); + assertEquals("1.0.0-SNAPSHOT", metadata.getVersion().getContent()); + assertEquals("org.acme.demo", metadata.getPackageName().getContent()); + } + + @Test + public void mergeMetadataWithBom() { + InitializrMetadata metadata = InitializrMetadataBuilder.create() + .withInitializrMetadata( + new ClassPathResource("metadata/config/test-bom.json")) + .build(); + + Map boms = metadata.getConfiguration().getEnv() + .getBoms(); + assertEquals(2, boms.size()); + BillOfMaterials myBom = boms.get("my-bom"); + assertNotNull(myBom); + assertEquals("org.acme", myBom.getGroupId()); + assertEquals("my-bom", myBom.getArtifactId()); + assertEquals("1.2.3.RELEASE", myBom.getVersion()); + + BillOfMaterials anotherBom = boms.get("another-bom"); + assertNotNull(anotherBom); + assertEquals("org.acme", anotherBom.getGroupId()); + assertEquals("another-bom", anotherBom.getArtifactId()); + assertEquals("4.5.6.RELEASE", anotherBom.getVersion()); + } + + @Test + public void mergeMetadataWithRepository() throws Exception { + InitializrMetadata metadata = InitializrMetadataBuilder.create() + .withInitializrMetadata( + new ClassPathResource("metadata/config/test-repository.json")) + .build(); + + Map repositories = metadata.getConfiguration().getEnv() + .getRepositories(); + assertEquals(4, repositories.size()); // 2 standard repos + Repository myRepo = repositories.get("my-repo"); + assertNotNull(myRepo); + assertEquals("my repo", myRepo.getName()); + assertEquals(new URL("http://example.com/my"), myRepo.getUrl()); + assertEquals(true, myRepo.isSnapshotsEnabled()); + + Repository anotherRepo = repositories.get("another-repo"); + assertNotNull(anotherRepo); + assertEquals("another repo", anotherRepo.getName()); + assertEquals(new URL("http://example.com/another"), anotherRepo.getUrl()); + assertEquals(false, anotherRepo.isSnapshotsEnabled()); + } + + @Test + public void mergeConfigurationDisabledByDefault() { + InitializrProperties config = load( + new ClassPathResource("application-test-default.yml")); + InitializrProperties customDefaultsConfig = load( + new ClassPathResource("application-test-custom-env.yml")); + InitializrMetadata metadata = InitializrMetadataBuilder + .fromInitializrProperties(config) + .withInitializrProperties(customDefaultsConfig).build(); + InitializrConfiguration.Env defaultEnv = new InitializrConfiguration().getEnv(); + InitializrConfiguration.Env actualEnv = metadata.getConfiguration().getEnv(); + assertEquals(defaultEnv.getArtifactRepository(), + actualEnv.getArtifactRepository()); + assertEquals(defaultEnv.getSpringBootMetadataUrl(), + actualEnv.getSpringBootMetadataUrl()); + assertEquals(defaultEnv.getFallbackApplicationName(), + actualEnv.getFallbackApplicationName()); + assertEquals(defaultEnv.isForceSsl(), actualEnv.isForceSsl()); + assertEquals(defaultEnv.getKotlin().getVersion(), + actualEnv.getKotlin().getVersion()); + } + + @Test + public void mergeConfiguration() { + InitializrProperties config = load( + new ClassPathResource("application-test-default.yml")); + InitializrProperties customDefaultsConfig = load( + new ClassPathResource("application-test-custom-env.yml")); + InitializrMetadata metadata = InitializrMetadataBuilder + .fromInitializrProperties(config) + .withInitializrProperties(customDefaultsConfig, true).build(); + InitializrConfiguration.Env defaultEnv = new InitializrConfiguration().getEnv(); + InitializrConfiguration.Env actualEnv = metadata.getConfiguration().getEnv(); + assertEquals("https://repo.spring.io/lib-release/", + actualEnv.getArtifactRepository()); + assertEquals(defaultEnv.getSpringBootMetadataUrl(), + actualEnv.getSpringBootMetadataUrl()); + assertEquals("FooBarApplication", actualEnv.getFallbackApplicationName()); + assertEquals(false, actualEnv.isForceSsl()); + assertEquals("1.0.0-beta-2423", actualEnv.getKotlin().getVersion()); + } + + @Test + public void addDependencyInCustomizer() { + DependencyGroup group = DependencyGroup.create("Extra"); + Dependency dependency = Dependency.withId("com.foo:foo:1.0.0"); + group.getContent().add(dependency); + InitializrMetadata metadata = InitializrMetadataBuilder.create() + .withCustomizer(m -> m.getDependencies().getContent().add(group)).build(); + assertEquals(1, metadata.getDependencies().getContent().size()); + assertEquals(group, metadata.getDependencies().getContent().get(0)); + } + + private static void assertDefaultConfig(InitializrMetadata metadata) { + assertNotNull(metadata); + assertEquals("Wrong number of dependencies", 9, + metadata.getDependencies().getAll().size()); + assertEquals("Wrong number of dependency group", 2, + metadata.getDependencies().getContent().size()); + assertEquals("Wrong number of types", 4, metadata.getTypes().getContent().size()); + } + + private static InitializrProperties load(Resource resource) { + PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory<>( + InitializrProperties.class); + factory.setTargetName("initializr"); + MutablePropertySources sources = new MutablePropertySources(); + sources.addFirst(new PropertiesPropertySource("main", loadProperties(resource))); + factory.setPropertySources(sources); + try { + factory.afterPropertiesSet(); + return factory.getObject(); + } + catch (Exception e) { + throw new IllegalStateException("Could not create InitializrProperties", e); + } + } + + private static Properties loadProperties(Resource resource) { + YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + yamlFactory.setResources(resource); + yamlFactory.afterPropertiesSet(); + return yamlFactory.getObject(); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataTests.java new file mode 100644 index 00000000..3faf93dc --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/InitializrMetadataTests.java @@ -0,0 +1,203 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.metadata; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import io.spring.initializr.metadata.BillOfMaterials.Mapping; +import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder; +import io.spring.initializr.util.Version; + +/** + * @author Stephane Nicoll + */ +public class InitializrMetadataTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void invalidBom() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setBom("foo-bom"); + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("my-bom", "org.acme", "foo", "1.2.3") + .addDependencyGroup("test", foo); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("foo-bom"); + thrown.expectMessage("my-bom"); + builder.build(); + } + + @Test + public void invalidRepository() { + Dependency foo = Dependency.withId("foo", "org.acme", "foo"); + foo.setRepository("foo-repo"); + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults() + .addRepository("my-repo", "repo", "http://example.com/repo", true) + .addDependencyGroup("test", foo); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("foo-repo"); + thrown.expectMessage("my-repo"); + builder.build(); + } + + @Test + public void invalidBomNoVersion() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("No version"); + thrown.expectMessage("foo-bom"); + builder.build(); + } + + @Test + public void invalidBomUnknownRepository() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom", + "1.0.0.RELEASE"); + bom.getRepositories().add("foo-repo"); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("invalid repository id foo-repo"); + thrown.expectMessage("foo-bom"); + builder.build(); + } + + @Test + public void invalidBomUnknownAdditionalBom() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom", + "1.0.0.RELEASE"); + bom.getAdditionalBoms().addAll(Arrays.asList("bar-bom", "biz-bom")); + BillOfMaterials barBom = BillOfMaterials.create("org.acme", "bar-bom", + "1.0.0.RELEASE"); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom).addBom("bar-bom", barBom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("invalid additional bom"); + thrown.expectMessage("biz-bom"); + builder.build(); + } + + @Test + public void invalidBomVersionRangeMapping() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getMappings().add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.0.M1)", "1.0.0")); + bom.getMappings().add(BillOfMaterials.Mapping.create("FOO_BAR", "1.2.0")); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("FOO_BAR"); + thrown.expectMessage("foo-bom"); + builder.build(); + } + + @Test + public void invalidBomVersionRangeMappingUnknownRepo() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getMappings().add(BillOfMaterials.Mapping.create("[1.0.0.RELEASE,1.3.0.M1)", "1.0.0")); + Mapping mapping = BillOfMaterials.Mapping.create("1.3.0.M2", "1.2.0"); + mapping.getRepositories().add("foo-repo"); + bom.getMappings().add(mapping); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("invalid repository id foo-repo"); + thrown.expectMessage("1.3.0.M2"); + thrown.expectMessage("foo-bom"); + builder.build(); + } + + @Test + public void invalidBomVersionRangeMappingUnknownAdditionalBom() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getMappings().add(BillOfMaterials.Mapping.create("[1.0.0.RELEASE,1.3.0.M1)", "1.0.0")); + Mapping mapping = BillOfMaterials.Mapping.create("1.3.0.M2", "1.2.0"); + mapping.getAdditionalBoms().add("bar-bom"); + bom.getMappings().add(mapping); + + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().addBom("foo-bom", bom); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("invalid additional bom"); + thrown.expectMessage("1.3.0.M2"); + thrown.expectMessage("bar-bom"); + builder.build(); + } + + @Test + public void updateSpringBootVersions() { + BillOfMaterials bom = BillOfMaterials.create("org.acme", "foo-bom"); + bom.getMappings().add(BillOfMaterials.Mapping.create("[1.2.0.RELEASE,1.3.x.RELEASE]", "1.0.0")); + bom.getMappings().add(BillOfMaterials.Mapping.create("1.3.x.BUILD-SNAPSHOT", "1.1.0-BUILD-SNAPSHOT")); + Dependency dependency = Dependency.withId("bar"); + dependency.getMappings().add(Dependency.Mapping.create( + "[1.3.0.RELEASE, 1.3.x.RELEASE]", null, null, "0.1.0.RELEASE")); + dependency.getMappings().add(Dependency.Mapping.create( + "1.3.x.BUILD-SNAPSHOT", null, null, "0.2.0.RELEASE")); + InitializrMetadata metadata = InitializrMetadataTestBuilder + .withDefaults().addDependencyGroup("test", dependency) + .addBom("foo-bom", bom).build(); + + List bootVersions = Arrays.asList( + DefaultMetadataElement.create("1.3.6.RELEASE", "1.3.6", false), + DefaultMetadataElement.create("1.3.7.BUILD-SNAPSHOT", "1.3.7", false)); + metadata.updateSpringBootVersions(bootVersions); + assertThat(metadata.getConfiguration().getEnv().getBoms().get("foo-bom") + .resolve(Version.parse("1.3.6.RELEASE")).getVersion()).isEqualTo("1.0.0"); + assertThat(metadata.getConfiguration().getEnv().getBoms().get("foo-bom") + .resolve(Version.parse("1.3.7.BUILD-SNAPSHOT")).getVersion()).isEqualTo("1.1.0-BUILD-SNAPSHOT"); + assertThat(metadata.getDependencies().get("bar") + .resolve(Version.parse("1.3.6.RELEASE")).getVersion()).isEqualTo("0.1.0.RELEASE"); + assertThat(metadata.getDependencies().get("bar") + .resolve(Version.parse("1.3.7.BUILD-SNAPSHOT")).getVersion()).isEqualTo("0.2.0.RELEASE"); + } + + @Test + public void invalidParentMissingVersion() { + InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder + .withDefaults().setMavenParent("org.foo", "foo-parent", null, false); + + thrown.expect(InvalidInitializrMetadataException.class); + thrown.expectMessage("Custom maven pom requires groupId, artifactId and version"); + builder.build(); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/LinkTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/LinkTests.java new file mode 100644 index 00000000..d2b9452c --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/LinkTests.java @@ -0,0 +1,105 @@ +/* + * 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 io.spring.initializr.metadata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.net.URI; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * Tests for {@link Link}. + * + * @author Stephane Nicoll + */ +public class LinkTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void resolveInvalidLinkNoRel() { + Link link = new Link(); + link.setHref("https://example.com"); + thrown.expect(InvalidInitializrMetadataException.class); + link.resolve(); + } + + @Test + public void resolveInvalidLinkNoHref() { + Link link = Link.create("reference", null, "foo doc"); + thrown.expect(InvalidInitializrMetadataException.class); + link.resolve(); + } + + @Test + public void resolveLinkNoVariables() { + Link link = Link.create("reference", "https://example.com/2"); + link.resolve(); + assertFalse(link.isTemplated()); + assertEquals(0, link.getTemplateVariables().size()); + } + + @Test + public void resolveLinkWithVariables() { + Link link = Link.create("reference", "https://example.com/{a}/2/{b}"); + link.resolve(); + assertTrue(link.isTemplated()); + assertEquals(2, link.getTemplateVariables().size()); + assertTrue(link.getTemplateVariables().contains("a")); + assertTrue(link.getTemplateVariables().contains("b")); + } + + @Test + public void expandLink() throws Exception { + Link link = Link.create("reference", "https://example.com/{a}/2/{b}"); + link.resolve(); + Map map = new LinkedHashMap<>(); + map.put("a", "test"); + map.put("b", "another"); + assertEquals(new URI("https://example.com/test/2/another"), link.expand(map)); + } + + @Test + public void expandLinkWithSameAttributeAtTwoPlaces() throws Exception { + Link link = Link.create("reference", "https://example.com/{a}/2/{a}"); + link.resolve(); + Map map = new LinkedHashMap<>(); + map.put("a", "test"); + map.put("b", "another"); + assertEquals(new URI("https://example.com/test/2/test"), link.expand(map)); + } + + @Test + public void expandLinkMissingVariable() { + Link link = Link.create("reference", "https://example.com/{a}/2/{b}"); + link.resolve(); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("missing value for 'b'"); + link.expand(Collections.singletonMap("a", "test")); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/SingleSelectCapabilityTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/SingleSelectCapabilityTests.java new file mode 100644 index 00000000..65945dee --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/SingleSelectCapabilityTests.java @@ -0,0 +1,68 @@ +/* + * 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 io.spring.initializr.metadata; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * @author Stephane Nicoll + */ +public class SingleSelectCapabilityTests { + + @Test + public void defaultEmpty() { + SingleSelectCapability capability = new SingleSelectCapability("test"); + assertNull(capability.getDefault()); + } + + @Test + public void defaultNoDefault() { + SingleSelectCapability capability = new SingleSelectCapability("test"); + capability.getContent().add(DefaultMetadataElement.create("foo", false)); + capability.getContent().add(DefaultMetadataElement.create("bar",false)); + assertNull(capability.getDefault()); + } + + @Test + public void defaultType() { + SingleSelectCapability capability = new SingleSelectCapability("test"); + capability.getContent().add(DefaultMetadataElement.create("foo", false)); + DefaultMetadataElement second = DefaultMetadataElement.create("bar",true); + capability.getContent().add(second); + assertEquals(second, capability.getDefault()); + } + + @Test + public void mergeAddEntry() { + SingleSelectCapability capability = new SingleSelectCapability("test"); + DefaultMetadataElement foo = DefaultMetadataElement.create("foo", false); + capability.getContent().add(foo); + + SingleSelectCapability anotherCapability = new SingleSelectCapability("test"); + DefaultMetadataElement bar =DefaultMetadataElement.create("bar", false); + anotherCapability.getContent().add(bar); + + capability.merge(anotherCapability); + assertEquals(2, capability.getContent().size()); + assertEquals(foo, capability.get("foo")); + assertEquals(bar, capability.get("bar")); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/TextCapabilityTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/TextCapabilityTests.java new file mode 100644 index 00000000..b1f99e57 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/TextCapabilityTests.java @@ -0,0 +1,60 @@ +/* + * 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 io.spring.initializr.metadata; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * @author Stephane Nicoll + */ +public class TextCapabilityTests { + + @Test + public void mergeValue() { + TextCapability capability = new TextCapability("foo"); + capability.setContent("1234"); + TextCapability another = new TextCapability("foo"); + another.setContent("4567"); + capability.merge(another); + assertEquals("foo", capability.getId()); + assertEquals(ServiceCapabilityType.TEXT, capability.getType()); + assertEquals("4567", capability.getContent()); + } + + @Test + public void mergeTitle() { + TextCapability capability = new TextCapability("foo", "Foo", "my desc"); + capability.merge(new TextCapability("foo", "AnotherFoo", "")); + assertEquals("foo", capability.getId()); + assertEquals(ServiceCapabilityType.TEXT, capability.getType()); + assertEquals("AnotherFoo", capability.getTitle()); + assertEquals("my desc", capability.getDescription()); + } + + @Test + public void mergeDescription() { + TextCapability capability = new TextCapability("foo", "Foo", "my desc"); + capability.merge(new TextCapability("foo", "", "another desc")); + assertEquals("foo", capability.getId()); + assertEquals(ServiceCapabilityType.TEXT, capability.getType()); + assertEquals("Foo", capability.getTitle()); + assertEquals("another desc", capability.getDescription()); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/metadata/TypeCapabilityTests.java b/initializr-generator/src/test/java/io/spring/initializr/metadata/TypeCapabilityTests.java new file mode 100644 index 00000000..c885e03e --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/TypeCapabilityTests.java @@ -0,0 +1,88 @@ +/* + * 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 io.spring.initializr.metadata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +/** + * @author Stephane Nicoll + */ +public class TypeCapabilityTests { + + @Test + public void defaultEmpty() { + TypeCapability capability = new TypeCapability(); + assertNull(capability.getDefault()); + } + + @Test + public void defaultNoDefault() { + TypeCapability capability = new TypeCapability(); + Type first = new Type(); + first.setId("foo"); + first.setDefault(false); + Type second = new Type(); + second.setId("bar"); + second.setDefault(false); + capability.getContent().add(first); + capability.getContent().add(second); + assertNull(capability.getDefault()); + } + + @Test + public void defaultType() { + TypeCapability capability = new TypeCapability(); + Type first = new Type(); + first.setId("foo"); + first.setDefault(false); + Type second = new Type(); + second.setId("bar"); + second.setDefault(true); + capability.getContent().add(first); + capability.getContent().add(second); + assertEquals(second, capability.getDefault()); + } + + @Test + public void mergeAddEntry() { + TypeCapability capability = new TypeCapability(); + Type first = new Type(); + first.setId("foo"); + first.setDefault(false); + capability.getContent().add(first); + + TypeCapability anotherCapability = new TypeCapability(); + Type another = new Type(); + another.setId("foo"); + another.setDefault(false); + Type second = new Type(); + second.setId("bar"); + second.setDefault(true); + anotherCapability.getContent().add(another); + anotherCapability.getContent().add(second); + + capability.merge(anotherCapability); + assertEquals(2, capability.getContent().size()); + assertEquals(first, capability.get("foo")); + assertEquals(second, capability.get("bar")); + assertEquals(second, capability.getDefault()); + } + +} diff --git a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeTests.groovy b/initializr-generator/src/test/java/io/spring/initializr/metadata/TypeTests.java similarity index 69% rename from initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeTests.groovy rename to initializr-generator/src/test/java/io/spring/initializr/metadata/TypeTests.java index 46cbcc0d..ce7c07af 100644 --- a/initializr-generator/src/test/groovy/io/spring/initializr/metadata/TypeTests.groovy +++ b/initializr-generator/src/test/java/io/spring/initializr/metadata/TypeTests.java @@ -14,21 +14,23 @@ * limitations under the License. */ -package io.spring.initializr.metadata +package io.spring.initializr.metadata; -import org.junit.Test +import org.junit.Test; -import static org.junit.Assert.assertEquals +import static org.junit.Assert.assertEquals; /** * @author Stephane Nicoll */ -class TypeTests { +public class TypeTests { @Test - void parseAction() { - def type = new Type(id: 'foo', action: 'my-action.zip') - assertEquals '/my-action.zip', type.action + public void parseAction() { + Type type = new Type(); + type.setId("foo"); + type.setAction("my-action.zip"); + assertEquals("/my-action.zip", type.getAction()); } } diff --git a/initializr-generator/src/test/java/io/spring/initializr/test/generator/GradleBuildAssert.java b/initializr-generator/src/test/java/io/spring/initializr/test/generator/GradleBuildAssert.java new file mode 100644 index 00000000..85622804 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/test/generator/GradleBuildAssert.java @@ -0,0 +1,81 @@ +/* + * 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 io.spring.initializr.test.generator; + +import io.spring.initializr.generator.ProjectRequest; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Very simple assertions for the gradle build. + * + * @author Stephane Nicoll + */ +public class GradleBuildAssert { + + private final String content; + + public GradleBuildAssert(String content) { + this.content = content; + } + + /** + * Validate that this generated gradle build validates against its request. + */ + public GradleBuildAssert validateProjectRequest(ProjectRequest request) { + return hasArtifactId(request.getArtifactId()).hasVersion(request.getVersion()) + .hasBootVersion(request.getBootVersion()) + .hasJavaVersion(request.getJavaVersion()); + } + + public GradleBuildAssert hasArtifactId(String artifactId) { + return contains("baseName = '"+ artifactId+"'"); + } + + public GradleBuildAssert hasVersion(String version) { + return contains("version = '" + version + "'"); + } + + public GradleBuildAssert hasBootVersion(String bootVersion) { + return contains("springBootVersion = '" + bootVersion + "'"); + } + + public GradleBuildAssert hasJavaVersion(String javaVersion) { + return contains("sourceCompatibility = " + javaVersion); + } + + public GradleBuildAssert hasSnapshotRepository() { + return contains("https://repo.spring.io/snapshot"); + } + + public GradleBuildAssert hasRepository(String url) { + return contains("maven { url \"" + url + "\" }"); + } + + public GradleBuildAssert contains(String expression) { + assertTrue(expression + " has not been found in gradle build " + content, + content.contains(expression)); + return this; + } + + public GradleBuildAssert doesNotContain(String expression) { + assertFalse(expression + " is not expected in gradle build " + content, + content.contains(expression)); + return this; + } +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/test/generator/PomAssert.java b/initializr-generator/src/test/java/io/spring/initializr/test/generator/PomAssert.java new file mode 100644 index 00000000..66c4c1f4 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/test/generator/PomAssert.java @@ -0,0 +1,512 @@ +/* + * 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 io.spring.initializr.test.generator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.custommonkey.xmlunit.SimpleNamespaceContext; +import org.custommonkey.xmlunit.XMLUnit; +import org.custommonkey.xmlunit.XpathEngine; +import org.custommonkey.xmlunit.exceptions.XpathException; +import org.junit.Assert; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import io.spring.initializr.generator.ProjectRequest; +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom; +import io.spring.initializr.metadata.Repository; + +/** + * XPath assertions that are specific to a standard Maven POM. + * + * @author Stephane Nicoll + */ +public class PomAssert { + + private final XpathEngine eng; + private final Document doc; + private final ParentPom parentPom; + private final Map properties = new LinkedHashMap<>(); + private final Map dependencies = new LinkedHashMap<>(); + private final Map boms = new LinkedHashMap<>(); + private final Map repositories = new LinkedHashMap<>(); + + public PomAssert(String content) { + eng = XMLUnit.newXpathEngine(); + Map context = new LinkedHashMap<>(); + context.put("pom", "http://maven.apache.org/POM/4.0.0"); + SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext(context); + eng.setNamespaceContext(namespaceContext); + try { + doc = XMLUnit.buildControlDocument(content); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot parse XML", e); + } + this.parentPom = parseParent(); + parseProperties(); + parseDependencies(); + parseBoms(); + parseRepositories(); + } + + /** + * Validate that this generated pom validates against its request. + */ + public PomAssert validateProjectRequest(ProjectRequest request) { + return hasGroupId(request.getGroupId()).hasArtifactId(request.getArtifactId()) + .hasVersion(request.getVersion()).hasPackaging(request.getPackaging()) + .hasName(request.getName()).hasDescription(request.getDescription()) + .hasJavaVersion(request.getJavaVersion()); + } + + public PomAssert hasGroupId(String groupId) { + try { + assertEquals(groupId, eng.evaluate(createRootNodeXPath("groupId"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasArtifactId(String artifactId) { + try { + assertEquals(artifactId, + eng.evaluate(createRootNodeXPath("artifactId"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasVersion(String version) { + try { + assertEquals(version, eng.evaluate(createRootNodeXPath("version"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasPackaging(String packaging) { + try { + assertEquals(packaging, eng.evaluate(createRootNodeXPath("packaging"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasName(String name) { + try { + assertEquals(name, eng.evaluate(createRootNodeXPath("name"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasDescription(String description) { + try { + assertEquals(description, + eng.evaluate(createRootNodeXPath("description"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasJavaVersion(String javaVersion) { + try { + assertEquals(javaVersion, + eng.evaluate(createPropertyNodeXpath("java.version"), doc)); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasProperty(String name, String value) { + assertTrue("No property " + name + " found", properties.containsKey(name)); + assertEquals("Wrong value for property " + name, value, properties.get(name)); + return this; + } + + public PomAssert hasNoProperty(String name) { + assertFalse("No property " + name + " should have been found", + properties.containsKey(name)); + return this; + } + + public PomAssert hasDependenciesCount(int count) { + assertEquals("Wrong number of declared dependencies --> " + dependencies.keySet(), + count, dependencies.size()); + return this; + } + + public PomAssert hasSpringBootStarterTomcat() { + return hasDependency( + Dependency.withId("tomcat", "provided").asSpringBootStarter("tomcat")); + } + + public PomAssert hasSpringBootStarterTest() { + return hasDependency( + Dependency.withId("test", "test").asSpringBootStarter("test")); + } + + public PomAssert hasSpringBootStarterDependency(String dependency) { + return hasDependency("org.springframework.boot", + "spring-boot-starter-" + dependency); + } + + public PomAssert hasSpringBootStarterRootDependency() { + return hasDependency("org.springframework.boot", "spring-boot-starter"); + } + + public PomAssert hasDependency(String groupId, String artifactId) { + return hasDependency(groupId, artifactId, null); + } + + public PomAssert hasDependency(String groupId, String artifactId, String version) { + return hasDependency(Dependency.create(groupId, artifactId, version, "compile")); + } + + public PomAssert hasParent(String groupId, String artifactId, String version) { + assertEquals(groupId, this.parentPom.getGroupId()); + assertEquals(artifactId, this.parentPom.getArtifactId()); + assertEquals(version, this.parentPom.getVersion()); + return this; + } + + public PomAssert hasSpringBootParent(String version) { + return hasParent("org.springframework.boot", "spring-boot-starter-parent", + version); + } + + public PomAssert hasDependency(Dependency expected) { + String id = generateDependencyId(expected.getGroupId(), expected.getArtifactId()); + Dependency dependency = dependencies.get(id); + assertNotNull("No dependency found with '" + id + "' --> " + dependencies.keySet(), + dependency); + if (expected.getVersion() != null) { + assertEquals("Wrong version for " + dependency, expected.getVersion(), + dependency.getVersion()); + } + if (expected.getScope() != null) { + assertEquals("Wrong scope for " + dependency, expected.getScope(), + dependency.getScope()); + } + if (expected.getType() != null) { + assertEquals("Wrong type for "+ dependency, expected.getType(), + dependency.getType()); + } + return this; + } + + public PomAssert hasBom(String groupId, String artifactId, String version) { + String id = generateBomId(groupId, artifactId); + BillOfMaterials bom = boms.get(id); + assertNotNull("No BOM found with '" + id + "' --> " + boms.keySet(), bom); + assertEquals("Wrong version for " + bom, version, bom.getVersion()); + return this; + } + + public PomAssert hasBomsCount(int count) { + assertEquals("Wrong number of declared boms -->" + boms.keySet(), count, + boms.size()); + return this; + } + + public PomAssert hasNoRepository() { + try { + Assert.assertEquals(0, + eng.getMatchingNodes(createRootNodeXPath("repositories"), doc) + .getLength()); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + return this; + } + + public PomAssert hasSnapshotRepository() { + hasRepository("spring-snapshots", "Spring Snapshots", + "https://repo.spring.io/snapshot", true); + hasPluginRepository("spring-snapshots"); + return this; + } + + public PomAssert hasRepository(String id, String name, String url, + Boolean snapshotsEnabled) { + Repository repository = repositories.get(id); + assertNotNull( + "No repository found with '" + id + "' --> " + repositories.keySet(), + repository); + if (name != null) { + assertEquals("Wrong name for " + repository, name, repository.getName()); + } + if (url != null) { + try { + assertEquals("Wrong url for " + repository, new URL(url), + repository.getUrl()); + } + catch (MalformedURLException e) { + throw new IllegalArgumentException("Cannot parse URL", e); + } + } + if (snapshotsEnabled) { + assertEquals("Wrong snapshots enabled flag for " + repository, + snapshotsEnabled, repository.isSnapshotsEnabled()); + } + return this; + } + + public PomAssert hasRepositoriesCount(int count) { + assertEquals("Wrong number of declared repositories -->" + repositories.keySet(), + count, repositories.size()); + return this; + } + + private PomAssert hasPluginRepository(String name) { + NodeList nodes; + try { + nodes = eng.getMatchingNodes( + createRootNodeXPath("pluginRepositories/pom:pluginRepository/pom:id"), + doc); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + for (int i = 0; i < nodes.getLength(); i++) { + if (name.equals(nodes.item(i).getTextContent())) { + return this; + } + } + throw new IllegalArgumentException("No plugin repository found with id " + name); + } + + public static String createPropertyNodeXpath(String propertyName) { + return createRootNodeXPath("properties/pom:" + propertyName); + } + + public static String createRootNodeXPath(String node) { + return "/pom:project/pom:" + node; + } + + private ParentPom parseParent() { + ParentPom parent = new ParentPom(); + try { + parent.setGroupId( + eng.evaluate(createRootNodeXPath("parent/pom:groupId"), doc)); + parent.setArtifactId( + eng.evaluate(createRootNodeXPath("parent/pom:artifactId"), doc)); + parent.setVersion( + eng.evaluate(createRootNodeXPath("parent/pom:version"), doc)); + return parent; + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + } + + private void parseProperties() { + NodeList nodes; + try { + nodes = eng.getMatchingNodes(createRootNodeXPath("properties/*"), doc); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + for (int i = 0; i < nodes.getLength(); i++) { + Node item = nodes.item(i); + if (item instanceof Element) { + Element element = (Element) item; + properties.put(element.getTagName(), element.getTextContent()); + } + } + } + + private void parseDependencies() { + NodeList nodes; + try { + nodes = eng.getMatchingNodes( + createRootNodeXPath("dependencies/pom:dependency"), doc); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + for (int i = 0; i < nodes.getLength(); i++) { + Node item = nodes.item(i); + if (item instanceof Element) { + Dependency dependency = new Dependency(); + Element element = (Element) item; + NodeList groupId = element.getElementsByTagName("groupId"); + if (groupId.getLength() > 0) { + dependency.setGroupId(groupId.item(0).getTextContent()); + } + NodeList artifactId = element.getElementsByTagName("artifactId"); + if (artifactId.getLength() > 0) { + dependency.setArtifactId(artifactId.item(0).getTextContent()); + } + NodeList version = element.getElementsByTagName("version"); + if (version.getLength() > 0) { + dependency.setVersion(version.item(0).getTextContent()); + } + NodeList scope = element.getElementsByTagName("scope"); + if (scope.getLength() > 0) { + dependency.setScope(scope.item(0).getTextContent()); + } + NodeList type = element.getElementsByTagName("type"); + if (type.getLength() > 0) { + dependency.setType(type.item(0).getTextContent()); + } + String id = dependency.generateId(); + assertFalse("Duplicate dependency with id " + id, + dependencies.containsKey(id)); + dependencies.put(id, dependency); + } + } + } + + private void parseBoms() { + NodeList nodes; + try { + nodes = eng + .getMatchingNodes( + createRootNodeXPath( + "dependencyManagement/pom:dependencies/pom:dependency"), + doc); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + } + for (int i = 0; i < nodes.getLength(); i++) { + Node item = nodes.item(i); + if (item instanceof Element) { + Element element = (Element) item; + NodeList type = element.getElementsByTagName("type"); + NodeList scope = element.getElementsByTagName("scope"); + if (isBom(type, scope)) { + BillOfMaterials bom = new BillOfMaterials(); + NodeList groupId = element.getElementsByTagName("groupId"); + if (groupId.getLength() > 0) { + bom.setGroupId(groupId.item(0).getTextContent()); + } + NodeList artifactId = element.getElementsByTagName("artifactId"); + if (artifactId.getLength() > 0) { + bom.setArtifactId(artifactId.item(0).getTextContent()); + } + NodeList version = element.getElementsByTagName("version"); + if (version.getLength() > 0) { + bom.setVersion(version.item(0).getTextContent()); + } + String id = generateBomId(bom.getGroupId(), bom.getArtifactId()); + assertFalse("Duplicate BOM with id " + id, boms.containsKey(id)); + boms.put(id, bom); + } + } + } + } + + private void parseRepositories() { + NodeList nodes; + try { + nodes = eng.getMatchingNodes( + createRootNodeXPath("repositories/pom:repository"), doc); + } + catch (XpathException e) { + throw new IllegalStateException("Cannot find path", e); + + } + for (int i = 0; i < nodes.getLength(); i++) { + Node item = nodes.item(i); + if (item instanceof Element) { + Repository repository = new Repository(); + Element element = (Element) item; + NodeList type = element.getElementsByTagName("id"); + String id = type.item(0).getTextContent(); + NodeList name = element.getElementsByTagName("name"); + if (name.getLength() > 0) { + repository.setName(name.item(0).getTextContent()); + } + NodeList url = element.getElementsByTagName("url"); + if (url.getLength() > 0) { + try { + repository.setUrl(new URL(url.item(0).getTextContent())); + } + catch (MalformedURLException | DOMException e) { + throw new IllegalStateException("Cannot parse URL", e); + } + } + NodeList snapshots = element.getElementsByTagName("snapshots"); + if (snapshots.getLength() > 0) { + Element snapshotsElement = (Element) snapshots.item(0); + NodeList snapshotsEnabled = snapshotsElement + .getElementsByTagName("enabled"); + if (snapshotsEnabled.getLength() > 0) { + repository.setSnapshotsEnabled( + "true".equals(snapshotsEnabled.item(0).getTextContent())); + } + } + assertFalse("Duplicate Repository with id " + id, + repositories.containsKey(id)); + repositories.put(id, repository); + } + } + } + + private static boolean isBom(NodeList type, NodeList scope) { + if (type.getLength() == 0 || scope.getLength() == 0) { + return false; + } + String typeValue = type.item(0).getTextContent(); + String scopeValue = scope.item(0).getTextContent(); + return "pom".equals(typeValue) && "import".equals(scopeValue); + } + + private static String generateBomId(String groupId, String artifactId) { + return groupId + ":" + artifactId; + } + + private static String generateDependencyId(String groupId, String artifactId) { + Dependency dependency = new Dependency(); + dependency.setGroupId(groupId); + dependency.setArtifactId(artifactId); + return dependency.generateId(); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/test/generator/ProjectAssert.java b/initializr-generator/src/test/java/io/spring/initializr/test/generator/ProjectAssert.java new file mode 100644 index 00000000..5c4e3e6e --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/test/generator/ProjectAssert.java @@ -0,0 +1,248 @@ +/* + * 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 io.spring.initializr.test.generator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Properties; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.util.StreamUtils; +import org.springframework.util.StringUtils; + +/** + * Various project based assertions. + * + * @author Stephane Nicoll + */ +public class ProjectAssert { + + public static final String DEFAULT_PACKAGE_NAME = "com.example"; + + public static final String DEFAULT_APPLICATION_NAME = "DemoApplication"; + + private final File dir; + private Boolean mavenProject; + + public File getDir() { + return dir; + } + + public Boolean getMavenProject() { + return mavenProject; + } + + /** + * Create a new instance with the directory holding the generated project. + * @param dir + */ + public ProjectAssert(File dir) { + this.dir = dir; + } + + /** + * Validate that the project contains a base directory with the specified name. + *

+ * When extracting such archive, a directory with the specified {@code name} will be + * created with the content of the project instead of extracting it in the directory + * itself. + * @param name the expected name of the base directory + * @return an updated project assert on that base directory + */ + public ProjectAssert hasBaseDir(String name) { + File projectDir = file(name); + assertTrue("No directory " + name + " found in " + dir.getAbsolutePath(), + projectDir.exists()); + assertTrue(name + " is not a directory", projectDir.isDirectory()); + return new ProjectAssert(projectDir); // Replacing the root dir so that other + // assertions match the root + } + + /** + * Return a {@link PomAssert} for this project. + */ + public PomAssert pomAssert() { + try { + return new PomAssert(StreamUtils.copyToString( + new FileInputStream(file("pom.xml")), Charset.forName("UTF-8"))); + } + catch (IOException e) { + throw new IllegalArgumentException("Cannot resolve pom.xml", e); + } + } + + /** + * Return a {@link GradleBuildAssert} for this project. + */ + public GradleBuildAssert gradleBuildAssert() { + try { + return new GradleBuildAssert(StreamUtils.copyToString( + new FileInputStream(file("build.gradle")), Charset.forName("UTF-8"))); + } + catch (IOException e) { + throw new IllegalArgumentException("Cannot resolve build.gradle", e); + } + } + + /** + * Return a {@link SourceCodeAssert} for the specified source code. + */ + public SourceCodeAssert sourceCodeAssert(String sourceCodePath) { + hasFile(sourceCodePath); + try { + return new SourceCodeAssert(sourceCodePath, StreamUtils.copyToString( + new FileInputStream(file(sourceCodePath)), Charset.forName("UTF-8"))); + } + catch (IOException e) { + throw new IllegalArgumentException("Cannot resolve path: " + sourceCodePath, + e); + } + } + + public ProjectAssert isMavenProject() { + hasFile("pom.xml").hasNoFile("build.gradle"); + hasFile("mvnw", "mvnw.cmd", ".mvn/wrapper/maven-wrapper.properties", + ".mvn/wrapper/maven-wrapper.jar"); + mavenProject = true; + return this; + } + + public ProjectAssert isGradleProject(String version) { + hasFile("build.gradle").hasNoFile("pom.xml"); + hasFile("gradlew", "gradlew.bat", "gradle/wrapper/gradle-wrapper.properties", + "gradle/wrapper/gradle-wrapper.jar"); + mavenProject = false; + if (StringUtils.hasText(version)) { + Properties properties = properties( + "gradle/wrapper/gradle-wrapper.properties"); + String distributionUrl = properties.getProperty("distributionUrl"); + assertTrue("Wrong gradle version for project " + distributionUrl, + distributionUrl.contains(version)); + } + return this; + } + + public ProjectAssert isGradleProject() { + return isGradleProject(null); + } + + public ProjectAssert isJavaProject(String expectedPackageName, + String expectedApplicationName) { + return isGenericProject(expectedPackageName, expectedApplicationName, "java", + "java"); + } + + public ProjectAssert isJavaProject() { + return isJavaProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME); + } + + public ProjectAssert isGroovyProject(String expectedPackageName, + String expectedApplicationName) { + return isGenericProject(expectedPackageName, expectedApplicationName, "groovy", + "groovy"); + } + + public ProjectAssert isKotlinProject(String expectedPackageName, + String expectedApplicationName) { + return isGenericProject(expectedPackageName, expectedApplicationName, "kotlin", + "kt"); + } + + public ProjectAssert isGroovyProject() { + return isGroovyProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME); + } + + public ProjectAssert isKotlinProject() { + return isKotlinProject(DEFAULT_PACKAGE_NAME, DEFAULT_APPLICATION_NAME); + } + + public ProjectAssert isGenericProject(String expectedPackageName, + String expectedApplicationName, String codeLocation, String extension) { + String packageName = expectedPackageName.replace(".", "/"); + return hasFile( + "src/main/" + codeLocation + "/" + packageName + "/" + + expectedApplicationName + "." + extension, + "src/test/" + codeLocation + "/" + packageName + "/" + + expectedApplicationName + "Tests." + extension, + "src/main/resources/application.properties"); + } + + public ProjectAssert isJavaWarProject(String expectedApplicationName) { + return isGenericWarProject(DEFAULT_PACKAGE_NAME, expectedApplicationName, "java", + "java"); + } + + public ProjectAssert isJavaWarProject() { + return isJavaWarProject(DEFAULT_APPLICATION_NAME); + } + + public ProjectAssert isGenericWarProject(String expectedPackageName, + String expectedApplicationName, String codeLocation, String extension) { + String packageName = expectedPackageName.replace(".", "/"); + return isGenericProject(expectedPackageName, expectedApplicationName, + codeLocation, extension).hasStaticAndTemplatesResources(true) + .hasFile("src/main/" + codeLocation + "/" + packageName + + "/ServletInitializer." + extension); + } + + public ProjectAssert hasStaticAndTemplatesResources(boolean web) { + assertFile("src/main/resources/templates", web); + return assertFile("src/main/resources/static", web); + } + + public ProjectAssert hasFile(String... localPaths) { + for (String localPath : localPaths) { + assertFile(localPath, true); + } + return this; + } + + public ProjectAssert hasNoFile(String... localPaths) { + for (String localPath : localPaths) { + assertFile(localPath, false); + } + return this; + } + + public ProjectAssert assertFile(String localPath, boolean exist) { + File candidate = file(localPath); + assertEquals("Invalid presence (\"" + exist + "\") for " + localPath, exist, + candidate.exists()); + return this; + } + + private File file(String localPath) { + return new File(dir, localPath); + } + + private Properties properties(String localPath) { + File f = file(localPath); + try { + return PropertiesLoaderUtils.loadProperties(new FileSystemResource(f)); + } + catch (Exception e) { + throw new IllegalStateException("Cannot load Properties", e); + } + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/test/generator/SourceCodeAssert.java b/initializr-generator/src/test/java/io/spring/initializr/test/generator/SourceCodeAssert.java new file mode 100644 index 00000000..76d10dee --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/test/generator/SourceCodeAssert.java @@ -0,0 +1,88 @@ +/* + * 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 io.spring.initializr.test.generator; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Source code assertions. + * + * @author Stephane Nicoll + */ +public class SourceCodeAssert { + + private final String name; + private final String content; + + public SourceCodeAssert(String name, String content) { + this.name = name; + this.content = content.replaceAll("\r\n", "\n"); + } + + public SourceCodeAssert equalsTo(Resource expected) { + try (InputStream stream = expected.getInputStream()) { + String expectedContent = StreamUtils.copyToString(stream, + Charset.forName("UTF-8")); + assertEquals("Unexpected content for $name", + expectedContent.replaceAll("\r\n", "\n"), content); + } + catch (IOException e) { + throw new IllegalStateException("Cannot read file", e); + } + return this; + } + + public SourceCodeAssert hasImports(String... classNames) { + for (String className : classNames) { + contains("import " + className); + } + return this; + } + + public SourceCodeAssert doesNotHaveImports(String... classNames) { + for (String className : classNames) { + doesNotContain("import " + className); + } + return this; + } + + public SourceCodeAssert contains(String... expressions) { + for (String expression : expressions) { + assertTrue(expression + " has not been found in source code '" + name + "'", + content.contains(expression)); + } + return this; + } + + public SourceCodeAssert doesNotContain(String... expressions) { + for (String expression : expressions) { + assertFalse(expression + " should not have been found in source code '" + name + + "'", content.contains(expression)); + } + return this; + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.java b/initializr-generator/src/test/java/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.java new file mode 100644 index 00000000..cce06be7 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/test/metadata/InitializrMetadataTestBuilder.java @@ -0,0 +1,224 @@ +/* + * 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 io.spring.initializr.test.metadata; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; + +import org.springframework.util.StringUtils; + +import io.spring.initializr.metadata.BillOfMaterials; +import io.spring.initializr.metadata.DefaultMetadataElement; +import io.spring.initializr.metadata.Dependency; +import io.spring.initializr.metadata.DependencyGroup; +import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom; +import io.spring.initializr.metadata.InitializrMetadata; +import io.spring.initializr.metadata.InitializrMetadataBuilder; +import io.spring.initializr.metadata.Repository; +import io.spring.initializr.metadata.Type; + +/** + * Easily create a {@link InitializrMetadata} instance for testing purposes. + * + * @author Stephane Nicoll + */ +public class InitializrMetadataTestBuilder { + + private final InitializrMetadataBuilder builder = InitializrMetadataBuilder.create(); + + public static InitializrMetadataTestBuilder withDefaults() { + return new InitializrMetadataTestBuilder().addDefaults(); + } + + public InitializrMetadata build() { + return builder.build(); + } + + public InitializrMetadataTestBuilder addDependencyGroup(String name, String... ids) { + builder.withCustomizer(it -> { + DependencyGroup group = new DependencyGroup(); + group.setName(name); + for (String id : ids) { + Dependency dependency = new Dependency(); + dependency.setId(id); + group.getContent().add(dependency); + } + it.getDependencies().getContent().add(group); + }); + return this; + } + + public InitializrMetadataTestBuilder addDependencyGroup(String name, Dependency... dependencies) { + builder.withCustomizer(it -> { + DependencyGroup group = new DependencyGroup(); + group.setName(name); + group.getContent().addAll(Arrays.asList(dependencies)); + it.getDependencies().getContent().add(group); + }); + return this; + } + + public InitializrMetadataTestBuilder addDefaults() { + return addDefaultTypes().addDefaultPackagings().addDefaultJavaVersions() + .addDefaultLanguages().addDefaultBootVersions() + .setGradleEnv("0.5.1.RELEASE").setKotlinEnv("1.0.1"); + } + + public InitializrMetadataTestBuilder addDefaultTypes() { + return addType("maven-build", false, "/pom.xml", "maven", "build") + .addType("maven-project", true, "/starter.zip", "maven", "project") + .addType("gradle-build", false, "/build.gradle", "gradle", "build") + .addType("gradle-project", false, "/starter.zip", "gradle", "project"); + } + + public InitializrMetadataTestBuilder addType(String id, boolean defaultValue, String action, String build, String format) { + Type type = new Type(); + type.setId(id); + type.setName(id); + type.setDefault(defaultValue); + type.setAction(action); + if (StringUtils.hasText(build)) { + type.getTags().put("build", build); + } + if (StringUtils.hasText(format)) { + type.getTags().put("format", format); + } + return addType(type); + } + + public InitializrMetadataTestBuilder addType(Type type) { + builder.withCustomizer(it -> it.getTypes().getContent().add(type)); + return this; + } + + public InitializrMetadataTestBuilder addDefaultPackagings() { + return addPackaging("jar", true).addPackaging("war", false); + } + + public InitializrMetadataTestBuilder addPackaging(String id, boolean defaultValue) { + builder.withCustomizer(it -> { + DefaultMetadataElement packaging = new DefaultMetadataElement(); + packaging.setId(id); + packaging.setName(id); + packaging.setDefault(defaultValue); + it.getPackagings().getContent().add(packaging); + }); + return this; + } + + public InitializrMetadataTestBuilder addDefaultJavaVersions() { + return addJavaVersion("1.6", false).addJavaVersion("1.7", false).addJavaVersion("1.8", true); + } + + public InitializrMetadataTestBuilder addJavaVersion(String version, boolean defaultValue) { + builder.withCustomizer(it -> { + DefaultMetadataElement element = new DefaultMetadataElement(); + element.setId(version); + element.setName(version); + element.setDefault(defaultValue); + it.getJavaVersions().getContent().add(element); + }); + return this; + } + + public InitializrMetadataTestBuilder addDefaultLanguages() { + return addLanguage("java", true).addLanguage("groovy", false).addLanguage("kotlin", false); + } + + public InitializrMetadataTestBuilder addLanguage(String id, boolean defaultValue) { + builder.withCustomizer(it -> { + DefaultMetadataElement element = new DefaultMetadataElement(); + element.setId(id); + element.setName(id); + element.setDefault(defaultValue); + it.getLanguages().getContent().add(element); + }); + return this; + } + + public InitializrMetadataTestBuilder addDefaultBootVersions() { + return addBootVersion("1.1.2.RELEASE", false).addBootVersion("1.2.3.RELEASE", true) + .addBootVersion("1.3.0.BUILD-SNAPSHOT", false); + } + + public InitializrMetadataTestBuilder addBootVersion(String id, boolean defaultValue) { + builder.withCustomizer(it -> { + DefaultMetadataElement element = new DefaultMetadataElement(); + element.setId(id); + element.setName(id); + element.setDefault(defaultValue); + it.getBootVersions().getContent().add(element); + }); + return this; + } + + public InitializrMetadataTestBuilder addBom(String id, String groupId, String artifactId, String version) { + BillOfMaterials bom = BillOfMaterials.create(groupId, artifactId, version); + return addBom(id, bom); + } + + public InitializrMetadataTestBuilder addBom(String id, BillOfMaterials bom) { + builder.withCustomizer( it -> { + it.getConfiguration().getEnv().getBoms().put(id, bom); + }); + return this; + } + + public InitializrMetadataTestBuilder setGradleEnv(String dependencyManagementPluginVersion) { + builder.withCustomizer( it-> { + it.getConfiguration().getEnv().getGradle().setDependencyManagementPluginVersion(dependencyManagementPluginVersion); + }); + return this; + } + + public InitializrMetadataTestBuilder setKotlinEnv(String kotlinVersion) { + builder.withCustomizer( it-> { + it.getConfiguration().getEnv().getKotlin().setVersion(kotlinVersion); + }); + return this; + } + + public InitializrMetadataTestBuilder setMavenParent(String groupId, String artifactId, + String version, boolean includeSpringBootBom) { + builder.withCustomizer( it-> { + ParentPom parent = it.getConfiguration().getEnv().getMaven().getParent(); + parent.setGroupId(groupId); + parent.setArtifactId(artifactId); + parent.setVersion(version); + parent.setIncludeSpringBootBom(includeSpringBootBom); + }); + return this; + } + + public InitializrMetadataTestBuilder addRepository(String id, String name, String url, boolean snapshotsEnabled) { + builder.withCustomizer( it-> { + Repository repo = new Repository(); + repo.setName(name); + try { + repo.setUrl(new URL(url)); + } + catch (MalformedURLException e) { + throw new IllegalArgumentException("Cannot create URL", e); + } + repo.setSnapshotsEnabled(snapshotsEnabled); + it.getConfiguration().getEnv().getRepositories().put(id, repo); + }); + return this; + } + +} \ No newline at end of file diff --git a/initializr-generator/src/test/java/io/spring/initializr/util/AgentTests.java b/initializr-generator/src/test/java/io/spring/initializr/util/AgentTests.java new file mode 100644 index 00000000..a59f4679 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/util/AgentTests.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.util; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +/** + * Tests for {@link Agent}. + * + * @author Stephane Nicoll + */ +public class AgentTests { + + @Test + public void checkCurl() { + Agent agent = Agent.fromUserAgent("curl/1.2.4"); + assertThat(agent.getId(), equalTo(Agent.AgentId.CURL)); + assertThat(agent.getVersion(), equalTo("1.2.4")); + } + + @Test + public void checkHttpie() { + Agent agent = Agent.fromUserAgent("HTTPie/0.8.0"); + assertThat(agent.getId(), equalTo(Agent.AgentId.HTTPIE)); + assertThat(agent.getVersion(), equalTo("0.8.0")); + } + + @Test + public void checkSpringBootCli() { + Agent agent = Agent.fromUserAgent("SpringBootCli/1.3.1.RELEASE"); + assertThat(agent.getId(), equalTo(Agent.AgentId.SPRING_BOOT_CLI)); + assertThat(agent.getVersion(), equalTo("1.3.1.RELEASE")); + } + + @Test + public void checkSts() { + Agent agent = Agent.fromUserAgent("STS 3.7.0.201506251244-RELEASE"); + assertThat(agent.getId(), equalTo(Agent.AgentId.STS)); + assertThat(agent.getVersion(), equalTo("3.7.0.201506251244-RELEASE")); + } + + @Test + public void checkIntelliJIDEA() { + Agent agent = Agent.fromUserAgent("IntelliJ IDEA"); + assertThat(agent.getId(), equalTo(Agent.AgentId.INTELLIJ_IDEA)); + assertThat(agent.getVersion(), is(nullValue())); + } + + @Test + public void checkIntelliJIDEAWithVersion() { + Agent agent = Agent.fromUserAgent("IntelliJ IDEA/144.2 (Community edition; en-us)"); + assertThat(agent.getId(), equalTo(Agent.AgentId.INTELLIJ_IDEA)); + assertThat(agent.getVersion(), is("144.2")); + } + + @Test + public void checkNetBeans() { + Agent agent = Agent.fromUserAgent("nb-springboot-plugin/0.1"); + assertThat(agent.getId(), equalTo(Agent.AgentId.NETBEANS)); + assertThat(agent.getVersion(), is("0.1")); + } + + @Test + public void checkGenericBrowser() { + Agent agent = Agent.fromUserAgent( + "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MMB29K) "); + assertThat(agent.getId(), equalTo(Agent.AgentId.BROWSER)); + assertThat(agent.getVersion(), is(nullValue())); + } + + @Test + public void checkRobot() { + Agent agent = Agent.fromUserAgent("Googlebot-Mobile"); + assertThat(agent, is(nullValue())); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/util/VersionParserTests.java b/initializr-generator/src/test/java/io/spring/initializr/util/VersionParserTests.java new file mode 100644 index 00000000..eb87e6ce --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/util/VersionParserTests.java @@ -0,0 +1,138 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * Tests for {@link VersionParser}. + * + * @author Stephane Nicoll + */ +public class VersionParserTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + private VersionParser parser = new VersionParser(Collections.emptyList()); + + @Test + public void noQualifierString() { + Version version = parser.parse("1.2.0"); + assertThat(version.toString(), equalTo("1.2.0")); + } + + @Test + public void withQualifierString() { + Version version = parser.parse("1.2.0.RELEASE"); + assertThat(version.toString(), equalTo("1.2.0.RELEASE")); + } + + @Test + public void withQualifierAndVersionString() { + Version version = parser.parse("1.2.0.RC2"); + assertThat(version.toString(), equalTo("1.2.0.RC2")); + } + + @Test + public void parseInvalidVersion() { + thrown.expect(InvalidVersionException.class); + parser.parse("foo"); + } + + @Test + public void safeParseInvalidVersion() { + assertNull(parser.safeParse("foo")); + } + + @Test + public void parseVersionWithSpaces() { + assertThat(parser.parse(" 1.2.0.RC3 "), + lessThan(parser.parse("1.3.0.RELEASE"))); + } + + @Test + public void parseVariableVersionMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.3.9.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("1.3.x.BUILD-SNAPSHOT").toString(), + equalTo("1.3.9.BUILD-SNAPSHOT")); + } + + @Test + public void parseVariableVersionNoPatchMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.3.9.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("1.x.x.RELEASE").toString(), + equalTo("1.3.8.RELEASE")); + } + + @Test + public void parseVariableVersionNoQualifierMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.4.0.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("1.4.x").toString(), + equalTo("1.4.0.BUILD-SNAPSHOT")); + } + + @Test + public void parseVariableVersionNoMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.3.9.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("1.4.x.BUILD-SNAPSHOT").toString(), + equalTo("1.4.999.BUILD-SNAPSHOT")); + } + + @Test + public void parseVariableVersionNoPatchNoMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.3.9.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("2.x.x.RELEASE").toString(), + equalTo("2.999.999.RELEASE")); + } + + @Test + public void parseVariableVersionNoQualifierNoMatch() { + List currentVersions = Arrays.asList(parser.parse("1.3.8.RELEASE"), + parser.parse("1.4.0.BUILD-SNAPSHOT")); + parser = new VersionParser(currentVersions); + assertThat(parser.parse("1.2.x").toString(), equalTo("1.2.999")); + } + + @Test + public void invalidRange() { + thrown.expect(InvalidVersionException.class); + parser.parseRange("foo-bar"); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/util/VersionRangeTests.java b/initializr-generator/src/test/java/io/spring/initializr/util/VersionRangeTests.java new file mode 100644 index 00000000..a36c1f18 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/util/VersionRangeTests.java @@ -0,0 +1,153 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.util; + +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; +import java.util.Collections; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * @author Stephane Nicoll + */ +public class VersionRangeTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void matchSimpleRange() { + assertThat("1.2.0.RC3", match("[1.2.0.RC1,1.2.0.RC5]")); + } + + @Test + public void matchSimpleRangeBefore() { + assertThat("1.1.9.RC3", not(match("[1.2.0.RC1,1.2.0.RC5]"))); + } + + @Test + public void matchSimpleRangeAfter() { + assertThat("1.2.0.RC6", not(match("[1.2.0.RC1,1.2.0.RC5]"))); + } + + @Test + public void matchInclusiveLowerRange() { + assertThat("1.2.0.RC1", match("[1.2.0.RC1,1.2.0.RC5]")); + } + + @Test + public void matchInclusiveHigherRange() { + assertThat("1.2.0.RC5", match("[1.2.0.RC1,1.2.0.RC5]")); + } + + @Test + public void matchExclusiveLowerRange() { + assertThat("1.2.0.RC1", not(match("(1.2.0.RC1,1.2.0.RC5)"))); + } + + @Test + public void matchExclusiveHigherRange() { + assertThat("1.2.0.RC5", not(match("[1.2.0.RC1,1.2.0.RC5)"))); + } + + @Test + public void matchUnboundedRangeEqual() { + assertThat("1.2.0.RELEASE", match("1.2.0.RELEASE")); + } + + @Test + public void matchUnboundedRangeAfter() { + assertThat("2.2.0.RELEASE", match("1.2.0.RELEASE")); + } + + @Test + public void matchUnboundedRangeBefore() { + assertThat("1.1.9.RELEASE", not(match("1.2.0.RELEASE"))); + } + + @Test + public void rangeWithSpaces() { + assertThat("1.2.0.RC3", match("[ 1.2.0.RC1 , 1.2.0.RC5]")); + } + + @Test + public void matchLatestVersion() { + assertThat("1.2.8.RELEASE", match("[1.2.0.RELEASE,1.2.x.BUILD-SNAPSHOT]", + new VersionParser(Arrays.asList(Version.parse("1.2.9.BUILD-SNAPSHOT"))))); + } + + @Test + public void matchOverLatestVersion() { + assertThat("1.2.10.RELEASE", not(match("[1.2.0.RELEASE,1.2.x.BUILD-SNAPSHOT]", + new VersionParser(Arrays.asList(Version.parse("1.2.9.BUILD-SNAPSHOT")))))); + } + + @Test + public void matchAsOfCurrentVersion() { + assertThat("1.3.5.RELEASE", match("[1.3.x.RELEASE,1.3.x.BUILD-SNAPSHOT]", + new VersionParser(Arrays.asList(Version.parse("1.3.4.RELEASE"), + Version.parse("1.3.6.BUILD-SNAPSHOT"))))); + } + + @Test + public void matchOverAsOfCurrentVersion() { + assertThat("1.3.5.RELEASE", not(match("[1.3.x.RELEASE,1.3.x.BUILD-SNAPSHOT]", + new VersionParser(Arrays.asList(Version.parse("1.3.7.RELEASE"), + Version.parse("1.3.6.BUILD-SNAPSHOT")))))); + } + + private static VersionRangeMatcher match(String range) { + return new VersionRangeMatcher(range, new VersionParser(Collections.emptyList())); + } + + private static VersionRangeMatcher match(String range, VersionParser parser) { + return new VersionRangeMatcher(range, parser); + } + + + static class VersionRangeMatcher extends BaseMatcher { + + private final VersionRange range; + private final VersionParser parser; + + VersionRangeMatcher(String text, VersionParser parser) { + this.parser = parser; + this.range = parser.parseRange(text); + } + + @Override + public boolean matches(Object item) { + if (!(item instanceof String)) { + return false; + } + return this.range.match(this.parser.parse((String) item)); + } + + @Override + public void describeTo(Description description) { + description.appendText(range.toString()); + } + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/util/VersionTests.java b/initializr-generator/src/test/java/io/spring/initializr/util/VersionTests.java new file mode 100644 index 00000000..aab52804 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/util/VersionTests.java @@ -0,0 +1,135 @@ +/* + * Copyright 2012-2016 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 io.spring.initializr.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.comparesEqualTo; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.lessThan; + +import java.util.Collections; + +import org.junit.Test; + +/** + * @author Stephane Nicoll + */ +public class VersionTests { + + private static final VersionParser parser = new VersionParser(Collections.emptyList()); + + @Test + public void equalNoQualifier() { + Version first = parse("1.2.0"); + Version second = parse("1.2.0"); + assertThat(first, comparesEqualTo(second)); + assertThat(first, equalTo(second)); + } + + @Test + public void equalQualifierNoVersion() { + Version first = parse("1.2.0.RELEASE"); + Version second = parse("1.2.0.RELEASE"); + assertThat(first, comparesEqualTo(second)); + assertThat(first, equalTo(second)); + } + + @Test + public void equalQualifierVersion() { + Version first = parse("1.2.0.RC1"); + Version second = parse("1.2.0.RC1"); + assertThat(first, comparesEqualTo(second)); + assertThat(first, equalTo(second)); + } + + @Test + public void compareMajorOnly() { + assertThat(parse("2.2.0"), greaterThan(parse("1.8.0"))); + } + + @Test + public void compareMinorOnly() { + assertThat(parse("2.2.0"), greaterThan(parse("2.1.9"))); + } + + @Test + public void comparePatchOnly() { + assertThat(parse("2.2.4"), greaterThan(parse("2.2.3"))); + } + + @Test + public void compareHigherVersion() { + assertThat(parse("1.2.0.RELEASE"), greaterThan(parse("1.1.9.RELEASE"))); + } + + @Test + public void compareHigherQualifier() { + assertThat(parse("1.2.0.RC1"), greaterThan(parse("1.2.0.M1"))); + } + + @Test + public void compareHigherQualifierVersion() { + assertThat(parse("1.2.0.RC2"), greaterThan(parse("1.2.0.RC1"))); + } + + @Test + public void compareLowerVersion() { + assertThat(parse("1.0.5.RELEASE"), lessThan(parse("1.1.9.RELEASE"))); + } + + @Test + public void compareLowerQualifier() { + assertThat(parse("1.2.0.RC1"), lessThan(parse("1.2.0.RELEASE"))); + } + + @Test + public void compareLessQualifierVersion() { + assertThat(parse("1.2.0.RC2"), lessThan(parse("1.2.0.RC3"))); + } + + @Test + public void compareWithNull() { + assertThat(parse("1.2.0.RC2"), greaterThan(null)); + } + + @Test + public void compareUnknownQualifier() { + assertThat(parse("1.2.0.Beta"), lessThan(parse("1.2.0.CR"))); + } + + @Test + public void compareUnknownQualifierVersion() { + assertThat(parse("1.2.0.Beta1"), lessThan(parse("1.2.0.Beta2"))); + } + + @Test + public void snapshotGreaterThanRC() { + assertThat(parse("1.2.0.BUILD-SNAPSHOT"), greaterThan(parse("1.2.0.RC1"))); + } + + @Test + public void snapshotLowerThanRelease() { + assertThat(parse("1.2.0.BUILD-SNAPSHOT"), lessThan(parse("1.2.0.RELEASE"))); + } + + private static Version parse(String text) { + Version version = parser.parse(text); + return version; + } + +} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/support/DefaultDependencyMetadataProviderTests.java b/initializr-web/src/test/java/io/spring/initializr/web/support/DefaultDependencyMetadataProviderTests.java index 6dc26c9d..87f7593e 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/support/DefaultDependencyMetadataProviderTests.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/support/DefaultDependencyMetadataProviderTests.java @@ -37,11 +37,11 @@ public class DefaultDependencyMetadataProviderTests { @Test public void filterDependencies() { - Dependency first = Dependency.withId("first", "org.foo", "first", - "1.1.4.RELEASE"); + Dependency first = Dependency.withId("first", "org.foo", "first"); + first.setVersionRange("1.1.4.RELEASE"); Dependency second = Dependency.withId("second", "org.foo", "second"); - Dependency third = Dependency.withId("third", "org.foo", "third", - "1.1.8.RELEASE"); + Dependency third = Dependency.withId("third", "org.foo", "third"); + third.setVersionRange("1.1.8.RELEASE"); InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() .addDependencyGroup("test", first, second, third).build(); DependencyMetadata dependencyMetadata = provider.get(metadata, diff --git a/pom.xml b/pom.xml index 44a51cfa..91ab792e 100644 --- a/pom.xml +++ b/pom.xml @@ -172,21 +172,6 @@ build-helper-maven-plugin 1.10 - - org.codehaus.gmavenplus - gmavenplus-plugin - 1.5 - - - - addSources - addTestSources - compile - testCompile - - - - org.apache.maven.plugins maven-source-plugin