Polish contribution

Closes gh-223
This commit is contained in:
Stephane Nicoll 2016-07-08 17:05:31 +02:00
parent 625d5bee15
commit f45228376f
11 changed files with 219 additions and 67 deletions

View File

@ -18,7 +18,6 @@ package io.spring.initializr.generator
import groovy.util.logging.Slf4j
import io.spring.initializr.InitializrException
import io.spring.initializr.metadata.BillOfMaterials
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.util.Version
@ -28,6 +27,7 @@ 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
import static io.spring.initializr.util.GroovyTemplate.template
/**
@ -201,16 +201,11 @@ class ProjectGenerator {
Assert.notNull request.bootVersion, 'boot version must not be null'
def model = [:]
def metadata = metadataProvider.get()
def useCustomParent = metadata.configuration.env.customParentPomGAV
model['useCustomParentPom'] = useCustomParent != null
if (useCustomParent) {
def gavParts = useCustomParent.split(':')
model['customParentPomGroup'] = gavParts[0]
model['customParentPomArtifact'] = gavParts[1]
model['customParentPomVersion'] = gavParts[2]
request.boms.put("spring-boot", new BillOfMaterials(groupId: "org.springframework.boot", artifactId: "spring-boot-dependencies", version: request.bootVersion))
ParentPom parentPom = metadata.configuration.env.maven.resolveParentPom(request.bootVersion)
if (parentPom.includeSpringBootBom && !request.boms['spring-boot']) {
request.boms['spring-boot'] = metadata.createSpringBootBom('${spring-boot.version}')
}
request.resolve(metadata)
// request resolved so we can log what has been requested
@ -220,6 +215,11 @@ class ProjectGenerator {
request.properties.each { model[it.key] = it.value }
model['mavenParentGroupId'] = parentPom.groupId
model['mavenParentArtifactId'] = parentPom.artifactId
model['mavenParentVersion'] = parentPom.version
model['includeSpringBootBom'] = parentPom.includeSpringBootBom
model['compileDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_COMPILE)
model['runtimeDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_RUNTIME)
model['providedDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_PROVIDED)

View File

@ -80,8 +80,7 @@ class InitializrConfiguration {
String candidate = packageName.trim().split('\\W+').join('.')
if (hasInvalidChar(candidate.replace('.', '')) || env.invalidPackageNames.contains(candidate)) {
return defaultPackageName
}
else {
} else {
candidate
}
}
@ -122,14 +121,6 @@ class InitializrConfiguration {
*/
String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot'
/**
* The group / artifact / version of a custom parent pom to use for generated projects.
* This is only enabled if a value is expliclty provided.
*
* The value must be specified in "groupid:artifactId:versionNumber" format
*/
String customParentPomGAV
/**
* Tracking code for Google Analytics. Only enabled if a value is explicitly provided.
*/
@ -179,6 +170,11 @@ class InitializrConfiguration {
*/
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)
@ -194,31 +190,21 @@ class InitializrConfiguration {
}
void validate() {
if (customParentPomGAV) {
validateGAV(customParentPomGAV);
}
maven.parent.validate()
boms.each {
it.value.validate()
}
}
/**
* validate that the GAV has 3 components in the format expected
*/
void validateGAV(String gav) {
if (gav.split(':').length != 3)
throw new InvalidInitializrMetadataException("The group:artifact:version of ${gav} is not a valid GAV (does not have exactly 3 components")
}
void merge(Env other) {
artifactRepository = other.artifactRepository
springBootMetadataUrl = other.springBootMetadataUrl
googleAnalyticsTrackingCode = other.googleAnalyticsTrackingCode
customParentPomGAV = other.customParentPomGAV
fallbackApplicationName = other.fallbackApplicationName
invalidApplicationNames = other.invalidApplicationNames
forceSsl = other.forceSsl
kotlin.version = other.kotlin.version
maven.merge(other.maven)
other.boms.each { id, bom ->
if (!boms[id]) {
boms[id] = bom
@ -239,6 +225,65 @@ class InitializrConfiguration {
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")
}
}
}
}
}
}

View File

@ -144,6 +144,14 @@ class InitializrMetadata {
"$bootVersion/spring-boot-cli-$bootVersion-bin.$extension"
}
/**
* Create a {@link BillOfMaterials} for the spring boot BOM.
*/
BillOfMaterials createSpringBootBom(String bootVersion) {
new BillOfMaterials(groupId: 'org.springframework.boot', artifactId: 'spring-boot-dependencies',
version: bootVersion)
}
/**
* Return the defaults for the capabilities defined on this instance.
*/

View File

@ -29,6 +29,18 @@
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env",
"sourceMethod": "getKotlin()"
},
{
"name": "initializr.env.maven",
"type": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env",
"sourceMethod": "getMaven()"
},
{
"name": "initializr.env.maven.parent",
"type": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven$ParentPom",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven",
"sourceMethod": "getParent()"
},
{
"name": "initializr.group-id",
"type": "io.spring.initializr.metadata.InitializrProperties$SimpleElement",
@ -169,6 +181,31 @@
"description": "Kotlin version to use.",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Kotlin"
},
{
"name": "initializr.env.maven.parent.artifact-id",
"type": "java.lang.String",
"description": "Parent pom artifactId.",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven$ParentPom"
},
{
"name": "initializr.env.maven.parent.include-spring-boot-bom",
"type": "java.lang.Boolean",
"description": "Add the \"spring-boot-dependencies\" BOM to the project.",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven$ParentPom",
"defaultValue": false
},
{
"name": "initializr.env.maven.parent.group-id",
"type": "java.lang.String",
"description": "Parent pom groupId.",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven$ParentPom"
},
{
"name": "initializr.env.maven.parent.version",
"type": "java.lang.String",
"description": "Parent pom version.",
"sourceType": "io.spring.initializr.metadata.InitializrConfiguration$Env$Maven$ParentPom"
},
{
"name": "initializr.env.repositories",
"type": "java.util.Map<java.lang.String,io.spring.initializr.metadata.Repository>",

View File

@ -12,22 +12,16 @@
<description>${description}</description>
<parent>
<% if (useCustomParentPom) { %>
<groupId>${customParentPomGroup}</groupId>
<artifactId>${customParentPomArtifact}</artifactId>
<version>${customParentPomVersion}</version>
<% } else { %>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${bootVersion}</version>
<% } %>
<groupId>${mavenParentGroupId}</groupId>
<artifactId>${mavenParentArtifactId}</artifactId>
<version>${mavenParentVersion}</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>${javaVersion}</java.version><% if (language=='kotlin') { %>
<kotlin.version>${kotlinVersion}</kotlin.version><% } %><% if (useCustomParentPom) { %>
<kotlin.version>${kotlinVersion}</kotlin.version><% } %><% if (includeSpringBootBom) { %>
<spring-boot.version>${bootVersion}</spring-boot.version><%}%>
</properties>

View File

@ -72,6 +72,7 @@ class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
def request = createProjectRequest('web')
request.bootVersion = '1.0.1.BUILD-SNAPSHOT'
generateMavenPom(request).hasSnapshotRepository()
.hasSpringBootParent('1.0.1.BUILD-SNAPSHOT')
.hasSpringBootStarterDependency('web')
}
@ -311,20 +312,37 @@ class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
@Test
void defaultMavenPomHasSpringBootParent() {
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
applyMetadata(metadata)
def request = createProjectRequest('whatever', 'web')
generateMavenPom(request).hasParent("org.springframework.boot", "spring-boot-starter-parent", request.bootVersion)
def request = createProjectRequest('web')
generateMavenPom(request).hasSpringBootParent(request.bootVersion)
}
@Test
void mavenPomWithCustomParentPom() {
def customGAV = "com.foo:foo-parent:1.0.0-SNAPSHOT"
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addCustomParentPomGAV(customGAV).build()
.addDependencyGroup('core', 'web', 'security', 'data-jpa')
.setMavenParent('com.foo', 'foo-parent', '1.0.0-SNAPSHOT', false)
.build()
applyMetadata(metadata)
def request = createProjectRequest('whatever', 'web')
generateMavenPom(request).hasParent("com.foo", "foo-parent", "1.0.0-SNAPSHOT")
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
@ -454,12 +472,14 @@ class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
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')
}
@ -480,6 +500,7 @@ class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
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)

View File

@ -146,4 +146,15 @@ class InitializrMetadataTests {
builder.build()
}
@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()
}
}

View File

@ -19,6 +19,7 @@ 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
@ -30,6 +31,7 @@ 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.
@ -41,6 +43,8 @@ class PomAssert {
final XpathEngine eng
final Document doc
final ParentPom parentPom
final Map<String, String> properties = [:]
final Map<String, Dependency> dependencies = [:]
final Map<String, BillOfMaterials> boms = [:]
final Map<String, Repository> repositories = [:]
@ -52,6 +56,8 @@ class PomAssert {
def namespaceContext = new SimpleNamespaceContext(context)
eng.namespaceContext = namespaceContext
doc = XMLUnit.buildControlDocument(content)
this.parentPom = parseParent()
parseProperties()
parseDependencies()
parseBoms()
parseRepositories()
@ -63,7 +69,7 @@ class PomAssert {
PomAssert validateProjectRequest(ProjectRequest request) {
hasGroupId(request.groupId).hasArtifactId(request.artifactId).hasVersion(request.version).
hasPackaging(request.packaging).hasName(request.name).hasDescription(request.description).
hasBootVersion(request.bootVersion).hasJavaVersion(request.javaVersion)
hasJavaVersion(request.javaVersion)
}
PomAssert hasGroupId(String groupId) {
@ -96,18 +102,14 @@ class PomAssert {
this
}
PomAssert hasBootVersion(String bootVersion) {
// when using a custom parent, the bootVersion comes from a bom entry and not the parent pom version
if (!eng.evaluate(createRootNodeXPath('parent/pom:artifactId'), doc).equals("spring-boot-starter-parent")) {
hasBom("org.springframework.boot", "spring-boot-dependencies", bootVersion)
} else {
assertEquals bootVersion, eng.evaluate(createRootNodeXPath('parent/pom:version'), doc)
}
PomAssert hasJavaVersion(String javaVersion) {
assertEquals javaVersion, eng.evaluate(createPropertyNodeXpath('java.version'), doc)
this
}
PomAssert hasJavaVersion(String javaVersion) {
assertEquals javaVersion, eng.evaluate(createPropertyNodeXpath('java.version'), doc)
PomAssert hasProperty(String name, String value) {
assertTrue "No property $name found", properties.containsKey(name)
assertEquals "Wrong value for property $name", value, properties[name]
this
}
@ -142,12 +144,16 @@ class PomAssert {
}
PomAssert hasParent(String groupId, String artifactId, String version) {
assertEquals version, eng.evaluate(createRootNodeXPath('parent/pom:version'), doc)
assertEquals groupId, eng.evaluate(createRootNodeXPath('parent/pom:groupId'), doc)
assertEquals artifactId, eng.evaluate(createRootNodeXPath('parent/pom:artifactId'), doc)
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]
@ -230,6 +236,24 @@ class PomAssert {
"/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++) {

View File

@ -152,9 +152,14 @@ class InitializrMetadataTestBuilder {
this
}
InitializrMetadataTestBuilder addCustomParentPomGAV(String customGAV) {
InitializrMetadataTestBuilder setMavenParent(String groupId, String artifactId,
String version, boolean includeSpringBootBom) {
builder.withCustomizer {
it.configuration.env.customParentPomGAV = customGAV
def parent = it.configuration.env.maven.parent
parent.groupId = groupId
parent.artifactId = artifactId
parent.version = version
parent.includeSpringBootBom = includeSpringBootBom
}
this
}

View File

@ -111,7 +111,7 @@ class ProjectGenerationSmokeTests extends AbstractInitializrControllerIntegratio
assertSimpleProject()
.isMavenProject()
.pomAssert()
.hasBootVersion('1.0.2.RELEASE')
.hasSpringBootParent('1.0.2.RELEASE')
.hasDependenciesCount(2)
.hasSpringBootStarterRootDependency()
.hasSpringBootStarterTest()

View File

@ -36,7 +36,14 @@
"kotlin": {
"version": null
},
"customParentPomGAV": null,
"maven": {
"parent": {
"groupId": null,
"artifactId": null,
"version": null,
"includeSpringBootBom": false
}
},
"googleAnalyticsTrackingCode": null,
"invalidApplicationNames": [
"SpringApplication",