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",