diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 45e5e9af..8995a729 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -7,6 +7,7 @@ order. === Release 1.0.0 (In progress) +* https://github.com/spring-io/initializr/issues/114[#114]: clean package name if necessary * https://github.com/spring-io/initializr/issues/90[#90]: migrate Groovy maven-based builds to GMavenPlus * https://github.com/spring-io/initializr/issues/140[#140]: expose dependencies meta-data * https://github.com/spring-io/initializr/issues/168[#168]: support for dependency versions mapping diff --git a/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy index 327af8a5..45658d03 100644 --- a/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy @@ -141,6 +141,7 @@ class ProjectRequest { if (!applicationName) { this.applicationName = metadata.configuration.generateApplicationName(this.name) } + packageName = metadata.configuration.cleanPackageName(this.packageName, metadata.packageName.content) initializeRepositories(metadata, requestedVersion) diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy index 6358aeca..f0c9063a 100644 --- a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy @@ -65,6 +65,27 @@ class InitializrConfiguration { } } + /** + * 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('(? invalidPackageNames = [ + 'org.springframework' + ] + /** * Force SSL support. When enabled, any access using http generate https links. */ diff --git a/initializr/src/main/resources/META-INF/spring-configuration-metadata.json b/initializr/src/main/resources/META-INF/spring-configuration-metadata.json index d2d29da8..c17f7030 100644 --- a/initializr/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/initializr/src/main/resources/META-INF/spring-configuration-metadata.json @@ -133,6 +133,13 @@ "sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env", "defaultValue": ["SpringApplication", "SpringBootApplication"] }, + { + "name": "initializr.env.invalid-package-names", + "type": "java.util.List", + "description": "The list of invalid package names. If such name is chosen or generated, the default package name should be used instead.", + "sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env", + "defaultValue": ["org.springframework"] + }, { "name": "initializr.env.repositories", "type": "java.util.Map", diff --git a/initializr/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy b/initializr/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy index f866e09c..5ee14e3b 100644 --- a/initializr/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy +++ b/initializr/src/test/groovy/io/spring/initializr/generator/ProjectRequestTests.groovy @@ -239,6 +239,24 @@ class ProjectRequestTests { 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 + } private static void assertBootStarter(Dependency actual, String name) { def expected = new Dependency() diff --git a/initializr/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy b/initializr/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy index 366a809d..dca1d5b0 100644 --- a/initializr/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy +++ b/initializr/src/test/groovy/io/spring/initializr/metadata/InitializrConfigurationTests.groovy @@ -16,7 +16,6 @@ package io.spring.initializr.metadata -import io.spring.initializr.metadata.InitializrConfiguration import org.junit.Test import static org.junit.Assert.assertEquals @@ -59,7 +58,7 @@ class InitializrConfigurationTests { } @Test - void generateApplicationNamSsimpleDash() { + void generateApplicationNamSimpleDash() { assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my-demo') } @@ -108,6 +107,46 @@ class InitializrConfigurationTests { 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' diff --git a/initializr/src/test/resources/metadata/config/test-default.json b/initializr/src/test/resources/metadata/config/test-default.json index f3d694b2..d4a6df23 100644 --- a/initializr/src/test/resources/metadata/config/test-default.json +++ b/initializr/src/test/resources/metadata/config/test-default.json @@ -37,6 +37,9 @@ "SpringApplication", "SpringBootApplication" ], + "invalidPackageNames": [ + "org.springframework" + ], "repositories": { "my-api-repo-1": { "name": "repo1",