diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/InitializrConfiguration.groovy new file mode 100644 index 00000000..8e538181 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/InitializrConfiguration.groovy @@ -0,0 +1,120 @@ +/* + * 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 + +/** + * Various configuration options used by the service. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class InitializrConfiguration { + + final Env env = new Env() + + /** + * Generate a suitable application mame 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 + } + } + + 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 meta-data url of the Spring Boot project + */ + String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot' + + /** + * 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 {@link #fallbackApplicationName} should be used instead. + */ + List invalidApplicationNames = [ + 'SpringApplication', + 'SpringBootApplication' + ] + + /** + * Force SSL support. When enabled, any access using http generate https links. + */ + boolean forceSsl = true + + void setArtifactRepository(String artifactRepository) { + if (!artifactRepository.endsWith('/')) { + artifactRepository = artifactRepository + '/' + } + this.artifactRepository = artifactRepository + } + + } +} diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadata.groovy b/initializr/src/main/groovy/io/spring/initializr/InitializrMetadata.groovy deleted file mode 100644 index 5d2e4d34..00000000 --- a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadata.groovy +++ /dev/null @@ -1,480 +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 - -import javax.annotation.PostConstruct - -import groovy.transform.ToString -import groovy.util.logging.Slf4j -import io.spring.initializr.mapper.InitializrMetadataJsonMapper -import io.spring.initializr.mapper.InitializrMetadataV21JsonMapper -import io.spring.initializr.mapper.InitializrMetadataV2JsonMapper -import io.spring.initializr.support.InvalidVersionException -import io.spring.initializr.support.VersionRange - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties - -/** - * The metadata using by the initializr, that is: - * - *

- * - * @author Stephane Nicoll - * @since 1.0 - */ -@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false) -@Slf4j -class InitializrMetadata { - - final List dependencies = [] - - final List types = [] - - final List packagings = [] - - final List javaVersions = [] - - final List languages = [] - - final List bootVersions = [] - - final Defaults defaults = new Defaults() - - final Env env = new Env() - - private final Map indexedDependencies = [:] - - @Autowired(required = false) - List customizers = [] - - /** - * Return the {@link Dependency} with the specified id or {@code null} if - * no such dependency exists. - */ - Dependency getDependency(String id) { - indexedDependencies[id] - } - - /** - * Return all dependencies as a flat collection - */ - Collection getAllDependencies() { - indexedDependencies.values() - } - - /** - * Return the {@link Type} with the specified id or {@code null} if no - * such type exists. - */ - Type getType(String id) { - for (it in this.types) { - if (id.equals(it.id) || id.equals(it.stsId)) { - return it - } - } - return null - } - - /** - * Create an URL suitable to download Spring Boot cli for the specified version and extension. - */ - String createCliDistributionURl(String extension) { - env.artifactRepository + "org/springframework/boot/spring-boot-cli/" + - "$defaults.bootVersion/spring-boot-cli-$defaults.bootVersion-bin.$extension" - } - - /** - * Generate a suitable application mame 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 - } - } - - /** - * Initializes a {@link ProjectRequest} instance with the defaults - * defined in this instance. - */ - void initializeProjectRequest(ProjectRequest request) { - defaults.properties.each { key, value -> - if (request.hasProperty(key) && !(key in ['class', 'metaClass'])) { - request[key] = value - } - } - request - } - - /** - * Merge this instance with the specified content. - */ - void merge(List bootVersions) { - if (bootVersions) { - synchronized (this.bootVersions) { - this.bootVersions.clear() - this.bootVersions.addAll(bootVersions) - } - } - refreshDefaults() - } - - /** - * Generate a JSON representation of the current metadata - * @param version the meta-data version - * @param appUrl the application url - */ - String generateJson(InitializrMetadataVersion version, String appUrl) { - getJsonMapper(version).write(this, appUrl) - } - - /** - * Initialize and validate the configuration. - */ - @PostConstruct - void validate() { - - customizers.each { customizer -> - customizer.customize(this) - } - - dependencies.each { group -> - group.content.each { dependency -> - validateDependency(dependency) - indexDependency(dependency.id, dependency) - for (String alias : dependency.aliases) { - indexDependency(alias, dependency) - } - } - } - env.validate() - - refreshDefaults() - } - - private void refreshDefaults() { - defaults.type = getDefault(types) - defaults.packaging = getDefault(packagings) - defaults.javaVersion = getDefault(javaVersions) - defaults.language = getDefault(languages) - defaults.bootVersion = getDefault(bootVersions) - } - - 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 - } - - static void validateDependency(Dependency dependency) { - def id = dependency.id - if (id == null) { - if (!dependency.hasCoordinates()) { - throw new InvalidInitializrMetadataException( - 'Invalid dependency, should have at least an id or a groupId/artifactId pair.') - } - dependency.generateId() - } else if (!dependency.hasCoordinates()) { - // Let's build the coordinates from the id - def st = new StringTokenizer(id, ':') - if (st.countTokens() == 1) { // assume spring-boot-starter - dependency.asSpringBootStarter(id) - } else if (st.countTokens() == 2 || st.countTokens() == 3) { - dependency.groupId = st.nextToken() - dependency.artifactId = st.nextToken() - if (st.hasMoreTokens()) { - dependency.version = st.nextToken() - } - } else { - throw new InvalidInitializrMetadataException( - "Invalid dependency, id should have the form groupId:artifactId[:version] but got $id") - } - } - if (dependency.versionRange) { - try { - VersionRange.parse(dependency.versionRange) - } catch (InvalidVersionException ex) { - throw new InvalidInitializrMetadataException("Invalid version range '$dependency.versionRange' for " + - "dependency with id '$dependency.id'") - } - } - } - - static def getDefault(List elements) { - for (DefaultIdentifiableElement element : elements) { - if (element.default) { - return element.id - } - } - log.warn("No default found amongst $elements") - return (elements.isEmpty() ? null : elements.get(0).id) - } - - private static InitializrMetadataJsonMapper getJsonMapper(InitializrMetadataVersion version) { - switch(version) { - case InitializrMetadataVersion.V2: return new InitializrMetadataV2JsonMapper(); - default: return new InitializrMetadataV21JsonMapper(); - } - } - - 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 - } - - static class DependencyGroup { - - String name - - final List content = [] - - } - - @ToString(ignoreNulls = true, includePackage = false) - static class Dependency extends IdentifiableElement { - - static final String SCOPE_COMPILE = 'compile' - 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_PROVIDED, SCOPE_TEST] - - List aliases = [] - - List facets = [] - - String groupId - - String artifactId - - String version - - String scope = SCOPE_COMPILE - - String description - - String versionRange - - 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 - } - - /** - * 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() - } - } - - static class Type extends DefaultIdentifiableElement { - - String description - - @Deprecated - String stsId - - String action - - void setAction(String action) { - String actionToUse = action - if (!actionToUse.startsWith("/")) { - actionToUse = "/" + actionToUse - } - this.action = actionToUse - } - - final Map tags = [:] - } - - static class Packaging extends DefaultIdentifiableElement { - } - - static class JavaVersion extends DefaultIdentifiableElement { - } - - static class Language extends DefaultIdentifiableElement { - } - - static class BootVersion extends DefaultIdentifiableElement { - } - - static class Defaults { - - static final String DEFAULT_NAME = 'demo' - - String groupId = 'org.test' - String artifactId - String version = '0.0.1-SNAPSHOT' - String name = DEFAULT_NAME - String description = 'Demo project for Spring Boot' - String packageName - String type - String packaging - String javaVersion - String language - String bootVersion - - /** - * Return the artifactId or the name of the project if none is set. - */ - String getArtifactId() { - artifactId == null ? name : artifactId - } - - /** - * Return the package name or the name of the project if none is set - */ - String getPackageName() { - packageName == null ? name.replace('-', '.') : packageName - } - - } - - /** - * Defines additional environment settings - */ - static class Env { - - String artifactRepository = 'https://repo.spring.io/release/' - - String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot' - - /** - * 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 {@link #fallbackApplicationName} should be used instead. - */ - List invalidApplicationNames = ['SpringApplication', 'SpringBootApplication'] - - boolean forceSsl = true - - void validate() { - if (!artifactRepository.endsWith('/')) { - artifactRepository = artifactRepository + '/' - } - } - - } - - static class DefaultIdentifiableElement extends IdentifiableElement { - - private boolean defaultValue - - void setDefault(boolean defaultValue) { - this.defaultValue = defaultValue - } - - boolean isDefault() { - this.defaultValue - } - } - - static class IdentifiableElement { - - String name - - String id - - String getName() { - (name ?: id) - } - } -} diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrAutoConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/config/InitializrAutoConfiguration.groovy similarity index 81% rename from initializr/src/main/groovy/io/spring/initializr/InitializrAutoConfiguration.groovy rename to initializr/src/main/groovy/io/spring/initializr/config/InitializrAutoConfiguration.groovy index 0bc64123..2b2c000e 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InitializrAutoConfiguration.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/config/InitializrAutoConfiguration.groovy @@ -14,11 +14,18 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.config import java.util.concurrent.TimeUnit import com.google.common.cache.CacheBuilder +import io.spring.initializr.generator.ProjectGenerationMetricsListener +import io.spring.initializr.generator.ProjectGenerator +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.InitializrMetadataBuilder +import io.spring.initializr.metadata.InitializrMetadataProvider +import io.spring.initializr.metadata.InitializrProperties +import io.spring.initializr.support.DefaultInitializrMetadataProvider import io.spring.initializr.web.MainController import io.spring.initializr.web.WebConfig @@ -47,7 +54,7 @@ import org.springframework.context.annotation.Configuration */ @Configuration @EnableCaching -@EnableConfigurationProperties(InitializrMetadata) +@EnableConfigurationProperties(InitializrProperties) class InitializrAutoConfiguration { @Autowired @@ -72,6 +79,12 @@ class InitializrAutoConfiguration { generator } + @Bean + @ConditionalOnMissingBean + InitializrMetadata initializrMetadata(InitializrProperties properties) { + new InitializrMetadataBuilder().fromConfiguration(properties).build() + } + @Bean @ConditionalOnMissingBean(InitializrMetadataProvider) InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) { diff --git a/initializr/src/main/groovy/io/spring/initializr/CommandLineHelpGenerator.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy similarity index 88% rename from initializr/src/main/groovy/io/spring/initializr/CommandLineHelpGenerator.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy index 008d6f36..21202ea2 100644 --- a/initializr/src/main/groovy/io/spring/initializr/CommandLineHelpGenerator.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/CommandLineHelpGenerator.groovy @@ -14,11 +14,13 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator -import io.spring.initializr.support.VersionRange +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.Type +import io.spring.initializr.util.VersionRange -import static io.spring.initializr.support.GroovyTemplate.template +import static io.spring.initializr.util.GroovyTemplate.template /** * Generate help pages for command-line clients. @@ -86,13 +88,8 @@ class CommandLineHelpGenerator { model['dependencies'] = generateDependencyTable(metadata) model['types'] = generateTypeTable(metadata, 'Rel', false) - Map defaults = [:] - metadata.defaults.properties.each { - if (!(it.key in ['class', 'metaClass', 'DEFAULT_NAME'])) { - defaults[it.key] = it.value - } - } - defaults['applicationName'] = metadata.generateApplicationName(metadata.defaults.name) + Map defaults = metadata.defaults() + defaults['applicationName'] = metadata.configuration.generateApplicationName(metadata.name.content) defaults['baseDir'] = 'no base dir' defaults['dependencies'] = 'none' @@ -119,12 +116,7 @@ class CommandLineHelpGenerator { model['types'] = generateTypeTable(metadata, 'Id', true) - Map defaults = [:] - metadata.defaults.properties.sort().each { - if (!(it.key in ['class', 'metaClass', 'DEFAULT_NAME'])) { - defaults[it.key] = it.value - } - } + Map defaults = metadata.defaults() Map parametersDescription = buildParametersDescription() String[][] parameterTable = new String[defaults.size() + 1][]; parameterTable[0] = ["Id", "Description", "Default value"] @@ -140,9 +132,9 @@ class CommandLineHelpGenerator { } protected String generateDependencyTable(InitializrMetadata metadata) { - String[][] dependencyTable = new String[metadata.allDependencies.size() + 1][]; + String[][] dependencyTable = new String[metadata.dependencies.all.size() + 1][]; dependencyTable[0] = ["Id", "Description", "Required version"] - new ArrayList(metadata.allDependencies).sort { a, b -> a.id <=> b.id } + new ArrayList(metadata.dependencies.all).sort { a, b -> a.id <=> b.id } .eachWithIndex { dep, i -> String[] data = new String[3] data[0] = dep.id @@ -154,16 +146,16 @@ class CommandLineHelpGenerator { } protected String generateTypeTable(InitializrMetadata metadata, String linkHeader, boolean addTags) { - String[][] typeTable = new String[metadata.types.size() + 1][]; + 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).sort { a, b -> a.id <=> b.id }.eachWithIndex { type, i -> + new ArrayList<>(metadata.types.content).sort { a, b -> a.id <=> b.id }.eachWithIndex { type, i -> String[] data = new String[typeTable[0].length] - data[0] = (metadata.defaults.type.equals(type.id) ? type.id + " *" : type.id) + data[0] = (type.default ? type.id + " *" : type.id) data[1] = type.description ?: type.name if (addTags) { data[2] = buildTagRepresentation(type) @@ -205,7 +197,7 @@ class CommandLineHelpGenerator { } } - private static String buildTagRepresentation(InitializrMetadata.Type type) { + private static String buildTagRepresentation(Type type) { if (type.tags.isEmpty()) { return ""; } diff --git a/initializr/src/main/groovy/io/spring/initializr/InvalidProjectRequestException.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy similarity index 87% rename from initializr/src/main/groovy/io/spring/initializr/InvalidProjectRequestException.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy index 2c3d4370..ff3ab2ce 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InvalidProjectRequestException.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/InvalidProjectRequestException.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,9 +14,10 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator import groovy.transform.InheritConstructors +import io.spring.initializr.InitializrException import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.ResponseStatus diff --git a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerationListener.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationListener.groovy similarity index 90% rename from initializr/src/main/groovy/io/spring/initializr/ProjectGenerationListener.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationListener.groovy index 1b4d4ae5..23d80c8b 100644 --- a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerationListener.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationListener.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator /** * Interface to be implemented by components that need to be aware of project generation diff --git a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerationMetricsListener.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationMetricsListener.groovy similarity index 96% rename from initializr/src/main/groovy/io/spring/initializr/ProjectGenerationMetricsListener.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationMetricsListener.groovy index 2c42ca1a..0d58d064 100644 --- a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerationMetricsListener.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerationMetricsListener.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.actuate.metrics.CounterService diff --git a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerator.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy similarity index 93% rename from initializr/src/main/groovy/io/spring/initializr/ProjectGenerator.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy index 412c0a30..6cef4709 100644 --- a/initializr/src/main/groovy/io/spring/initializr/ProjectGenerator.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectGenerator.groovy @@ -14,17 +14,18 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator import groovy.util.logging.Slf4j -import io.spring.initializr.support.Version +import io.spring.initializr.metadata.Dependency +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.util.Version import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.util.Assert -import static io.spring.initializr.InitializrMetadata.Dependency.* -import static io.spring.initializr.support.GroovyTemplate.template +import static io.spring.initializr.util.GroovyTemplate.template /** * Generate a project based on the configured metadata. @@ -174,10 +175,10 @@ class ProjectGenerator { request.properties.each { model[it.key] = it.value } - model['compileDependencies'] = filterDependencies(dependencies, SCOPE_COMPILE) - model['runtimeDependencies'] = filterDependencies(dependencies, SCOPE_RUNTIME) - model['providedDependencies'] = filterDependencies(dependencies, SCOPE_PROVIDED) - model['testDependencies'] = filterDependencies(dependencies, SCOPE_TEST) + model['compileDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_COMPILE) + model['runtimeDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_RUNTIME) + model['providedDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_PROVIDED) + model['testDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_TEST) // @SpringBootApplication available as from 1.2.0.RC1 model['useSpringBootApplication'] = VERSION_1_2_0_RC1 diff --git a/initializr/src/main/groovy/io/spring/initializr/ProjectRequest.groovy b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy similarity index 78% rename from initializr/src/main/groovy/io/spring/initializr/ProjectRequest.groovy rename to initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy index 101b20c4..23ab8309 100644 --- a/initializr/src/main/groovy/io/spring/initializr/ProjectRequest.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/generator/ProjectRequest.groovy @@ -14,11 +14,14 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.generator import groovy.util.logging.Slf4j -import io.spring.initializr.support.Version -import io.spring.initializr.support.VersionRange +import io.spring.initializr.metadata.Dependency +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.Type +import io.spring.initializr.util.Version +import io.spring.initializr.util.VersionRange /** * A request to generate a project. @@ -54,29 +57,40 @@ class ProjectRequest { String baseDir // Resolved dependencies based on the ids provided by either "style" or "dependencies" - List resolvedDependencies + List resolvedDependencies def facets = [] def build + /** + * Initializes this instance with the defaults defined in the specified {@link InitializrMetadata}. + */ + void initialize(InitializrMetadata metadata) { + metadata.defaults().forEach { 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 resolvedDependencies = depIds.collect { - def dependency = metadata.getDependency(it) + def dependency = metadata.dependencies.get(it) if (dependency == null) { if (it.contains(':')) { throw new InvalidProjectRequestException("Unknown dependency '$it' check project metadata") } log.warn("No known dependency for style '$it' assuming spring-boot-starter") - dependency = new InitializrMetadata.Dependency() + dependency = new Dependency() dependency.asSpringBootStarter(it) } dependency } - String actualBootVersion = bootVersion ?: metadata.defaults.bootVersion + String actualBootVersion = bootVersion ?: metadata.bootVersions.default.id Version requestedVersion = Version.parse(actualBootVersion) resolvedDependencies.each { it.facets.each { @@ -94,7 +108,7 @@ class ProjectRequest { } if (this.type) { - InitializrMetadata.Type type = metadata.getType(this.type) + Type type = metadata.types.get(this.type) if (!type) { throw new InvalidProjectRequestException("Unknown type '${this.type}' check project metadata") } @@ -105,7 +119,7 @@ class ProjectRequest { } if (!applicationName) { - this.applicationName = metadata.generateApplicationName(this.name) + this.applicationName = metadata.configuration.generateApplicationName(this.name) } afterResolution(metadata) @@ -117,7 +131,7 @@ class ProjectRequest { protected afterResolution(InitializrMetadata metadata) { if (packaging == 'war' && !hasWebFacet()) { // Need to be able to bootstrap the web app - resolvedDependencies << metadata.getDependency('web') + resolvedDependencies << metadata.dependencies.get('web') facets << 'web' } if (resolvedDependencies.isEmpty()) { @@ -130,7 +144,7 @@ class ProjectRequest { * dependency */ protected addDefaultDependency() { - def root = new InitializrMetadata.Dependency() + def root = new Dependency() root.id = DEFAULT_STARTER root.asSpringBootStarter('') resolvedDependencies << root diff --git a/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataJsonMapper.groovy b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataJsonMapper.groovy index 280c46f7..52d7964b 100644 --- a/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataJsonMapper.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataJsonMapper.groovy @@ -16,7 +16,7 @@ package io.spring.initializr.mapper -import io.spring.initializr.InitializrMetadata +import io.spring.initializr.metadata.InitializrMetadata /** * Generate a JSON representation of the metadata. diff --git a/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataV2JsonMapper.groovy b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataV2JsonMapper.groovy index 93ee7e5b..01a679e7 100644 --- a/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataV2JsonMapper.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataV2JsonMapper.groovy @@ -1,14 +1,14 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the 'License'); + * 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, + * 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. @@ -17,12 +17,12 @@ package io.spring.initializr.mapper import groovy.json.JsonBuilder -import io.spring.initializr.InitializrMetadata +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.SingleSelectCapability import org.springframework.hateoas.TemplateVariable import org.springframework.hateoas.TemplateVariables import org.springframework.hateoas.UriTemplate -import org.springframework.util.StringUtils /** * A {@link InitializrMetadataJsonMapper} handling the meta-data format for v2. @@ -54,19 +54,19 @@ class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMapper { String write(InitializrMetadata metadata, String appUrl) { JsonBuilder json = new JsonBuilder() json { - links(delegate, metadata.types, appUrl) + links(delegate, metadata.types.content, appUrl) dependencies(delegate, metadata.dependencies) - type(delegate, metadata.defaults.type, metadata.types) - singleSelect(delegate, 'packaging', metadata.defaults.packaging, metadata.packagings) - singleSelect(delegate, 'javaVersion', metadata.defaults.javaVersion, metadata.javaVersions) - singleSelect(delegate, 'language', metadata.defaults.language, metadata.languages) - singleSelect(delegate, 'bootVersion', metadata.defaults.bootVersion, metadata.bootVersions) - text(delegate, 'groupId', metadata.defaults.groupId) - text(delegate, 'artifactId', metadata.defaults.artifactId) - text(delegate, 'version', metadata.defaults.version) - text(delegate, 'name', metadata.defaults.name) - text(delegate, 'description', metadata.defaults.description) - text(delegate, 'packageName', metadata.defaults.packageName) + type(delegate, metadata.types) + singleSelect(delegate, metadata.packagings) + singleSelect(delegate, metadata.javaVersions) + singleSelect(delegate, metadata.languages) + singleSelect(delegate, metadata.bootVersions) + text(delegate, metadata.groupId) + text(delegate, metadata.artifactId) + text(delegate, metadata.version) + text(delegate, metadata.name) + text(delegate, metadata.description) + text(delegate, metadata.packageName) } json.toString() } @@ -94,44 +94,47 @@ class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMapper { } - protected dependencies(parent, groups) { - parent.dependencies { - type 'hierarchical-multi-select' - values groups.collect { + protected dependencies(parent, capability) { + parent."$capability.id" { + type "$capability.type.name" + values capability.content.collect { mapDependencyGroup(it) } } } - protected type(parent, defaultValue, dependencies) { + protected type(parent, capability) { parent.type { type 'action' - if (defaultValue) { - 'default' defaultValue + def defaultType = capability.default + if (defaultType) { + 'default' defaultType.id } - values dependencies.collect { + values capability.content.collect { mapType(it) } } } - protected singleSelect(parent, name, defaultValue, itemValues) { - parent."$name" { - type 'single-select' + protected singleSelect(parent, SingleSelectCapability capability) { + parent."$capability.id" { + type "$capability.type.name" + def defaultValue = capability.default if (defaultValue) { - 'default' defaultValue + 'default' defaultValue.id } - values itemValues.collect { + values capability.content.collect { mapValue(it) } } } - protected text(parent, name, value) { - parent."$name" { - type 'text' - if (value) { - 'default' value + protected text(parent, capability) { + parent."$capability.id" { + type "$capability.type.name" + def defaultValue = capability.content + if (defaultValue) { + 'default' defaultValue } } } diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataVersion.groovy b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataVersion.groovy similarity index 97% rename from initializr/src/main/groovy/io/spring/initializr/InitializrMetadataVersion.groovy rename to initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataVersion.groovy index 0ec58f5e..dfe8bbef 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataVersion.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/mapper/InitializrMetadataVersion.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.mapper import org.springframework.http.MediaType diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy new file mode 100644 index 00000000..0d9e4578 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/DefaultMetadataElement.groovy @@ -0,0 +1,37 @@ +/* + * 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 + +/** + * A {@link MetadataElement} that specifies if its + * the default for a given capability. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class DefaultMetadataElement extends MetadataElement { + + private boolean defaultValue + + void setDefault(boolean defaultValue) { + this.defaultValue = defaultValue + } + + boolean isDefault() { + this.defaultValue + } +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy new file mode 100644 index 00000000..fcedeee9 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/DependenciesCapability.groovy @@ -0,0 +1,73 @@ +/* + * 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 + +/** + * A {@link ServiceCapability} listing the available dependencies defined as a + * {@link ServiceCapabilityType#HIERARCHICAL_MULTI_SELECT} capability. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class DependenciesCapability extends ServiceCapability> { + + final List content = [] + + private final Map indexedDependencies = [:] + + DependenciesCapability() { + super('dependencies', ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT) + } + + /** + * 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() { + indexedDependencies.clear() + content.each { group -> + group.content.each { dependency -> + 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/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy new file mode 100644 index 00000000..2c6118e5 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/Dependency.groovy @@ -0,0 +1,142 @@ +/* + * 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 groovy.transform.ToString +import io.spring.initializr.util.InvalidVersionException +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 + * @since 1.0 + */ +@ToString(ignoreNulls = true, includePackage = false) +class Dependency extends MetadataElement { + + static final String SCOPE_COMPILE = 'compile' + 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_PROVIDED, + SCOPE_TEST + ] + + List aliases = [] + + List facets = [] + + String groupId + + String artifactId + + String version + + String scope = SCOPE_COMPILE + + String description + + String versionRange + + 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") + } + } + if (versionRange) { + try { + VersionRange.parse(versionRange) + } catch (InvalidVersionException ex) { + throw new InvalidInitializrMetadataException("Invalid version range '$versionRange' for " + + "dependency with id '$id'") + } + } + } + + /** + * 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() + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy new file mode 100644 index 00000000..8537f888 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/DependencyGroup.groovy @@ -0,0 +1,31 @@ +/* + * 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 + +/** + * A group of {@link Dependency} instances identified by a name. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class DependencyGroup { + + String name + + final List content = [] + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy new file mode 100644 index 00000000..a192aa28 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadata.groovy @@ -0,0 +1,130 @@ +/* + * 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 io.spring.initializr.InitializrConfiguration + +/** + * Meta-data used to generate a project. + * + * @author Stephane Nicoll + * @since 1.0 + * @see ServiceCapability + */ +class InitializrMetadata { + + final InitializrConfiguration configuration + + final DependenciesCapability dependencies = new DependenciesCapability() + + final TypeCapability types = new TypeCapability() + + final SingleSelectCapability bootVersions = new SingleSelectCapability('bootVersion') + + final SingleSelectCapability packagings = new SingleSelectCapability('packaging') + + final SingleSelectCapability javaVersions = new SingleSelectCapability('javaVersion') + + final SingleSelectCapability languages = new SingleSelectCapability('language') + + final TextCapability name = new TextCapability('name', 'demo') + + final TextCapability description = new TextCapability('description', 'Demo project for Spring Boot') + + final TextCapability groupId = new TextCapability('groupId', 'org.test') + + final TextCapability artifactId = new ArtifactIdCapability(name) + + final TextCapability version = new TextCapability('version', '0.0.1-SNAPSHOT') + + final TextCapability packageName = new PackageCapability(name) + + InitializrMetadata(InitializrConfiguration configuration) { + this.configuration = configuration + } + + /** + * Validate the meta-data. + */ + void validate() { + dependencies.validate() + } + + /** + * 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" + } + + /** + * 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') + 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') + this.nameCapability = nameCapability + } + + @Override + String getContent() { + String value = super.getContent() + value == null ? nameCapability.content.replace('-', '.') : value + } + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy new file mode 100644 index 00000000..2a7de551 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataBuilder.groovy @@ -0,0 +1,98 @@ +/* + * 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 io.spring.initializr.InitializrConfiguration + +/** + * Builder for {@link InitializrMetadata}. + * + * @author Stephane Nicoll + * @since 1.0 + * @see InitializrMetadataCustomizer + */ +class InitializrMetadataBuilder { + + private final List customizers = [] + private InitializrConfiguration configuration + + /** + * Adds the specified configuration. + * @see InitializrProperties + */ + InitializrMetadataBuilder fromConfiguration(InitializrProperties configuration) { + this.configuration = configuration + withCustomizer(new InitializerPropertiesCustomizer(configuration)) + } + + /** + * Adds a {@link InitializrMetadataCustomizer}. customizers are invoked in their + * order of addition. + * @see InitializrMetadataCustomizer + */ + InitializrMetadataBuilder withCustomizer(InitializrMetadataCustomizer customizer) { + customizers << customizer + this + } + + /** + * Build a {@link InitializrMetadata} baed on the state of this builder. + */ + InitializrMetadata build() { + InitializrConfiguration config = this.configuration ?: new InitializrConfiguration() + InitializrMetadata instance = createInstance(config) + for (InitializrMetadataCustomizer customizer : customizers) { + customizer.customize(instance) + } + instance.validate() + instance + } + + /** + * Creates an empty instance based on the specified {@link InitializrConfiguration} + */ + protected InitializrMetadata createInstance(InitializrConfiguration configuration) { + new InitializrMetadata(configuration) + } + + static class InitializerPropertiesCustomizer implements InitializrMetadataCustomizer { + + private final InitializrProperties properties + + InitializerPropertiesCustomizer(InitializrProperties properties) { + this.properties = properties + } + + @Override + void customize(InitializrMetadata metadata) { // NICE: merge + metadata.dependencies.content.addAll(properties.dependencies) + metadata.types.content.addAll(properties.types) + metadata.bootVersions.content.addAll(properties.bootVersions) + metadata.packagings.content.addAll(properties.packagings) + metadata.javaVersions.content.addAll(properties.javaVersions) + metadata.languages.content.addAll(properties.languages) + metadata.groupId.content = properties.defaults.groupId + metadata.artifactId.content = properties.defaults.artifactId + metadata.version.content = properties.defaults.version + metadata.name.content = properties.defaults.name + metadata.description.content = properties.defaults.description + metadata.packageName.content = properties.defaults.packageName + } + } + + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataCustomizer.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy similarity index 69% rename from initializr/src/main/groovy/io/spring/initializr/InitializrMetadataCustomizer.groovy rename to initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy index e6aaadfe..d4cb142b 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataCustomizer.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataCustomizer.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015 the original author or authors. + * 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. @@ -14,12 +14,20 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.metadata /** - * @author Dave Syer + * Strategy interface used to customize the {@link InitializrMetadata}. * + * @author Dave Syer + * @since 1.0 */ interface InitializrMetadataCustomizer { + + /** + * Customize the {@link InitializrMetadata}, updating or moving around + * capabilities before they are validated. + */ void customize(InitializrMetadata metadata) + } diff --git a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataProvider.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy similarity index 90% rename from initializr/src/main/groovy/io/spring/initializr/InitializrMetadataProvider.groovy rename to initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy index 2e4da27a..b0bfb2af 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InitializrMetadataProvider.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrMetadataProvider.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.metadata /** * Provide the {@link InitializrMetadata} to use. diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy new file mode 100644 index 00000000..a6cc6edc --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy @@ -0,0 +1,57 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.metadata + +import io.spring.initializr.InitializrConfiguration + +import org.springframework.boot.context.properties.ConfigurationProperties + +/** + * Configuration of the initializr service. + * + * @author Stephane Nicoll + * @since 1.0 + */ +@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false) +class InitializrProperties extends InitializrConfiguration { + + final List dependencies = [] + + final List types = [] + + final List packagings = [] + + final List javaVersions = [] + + final List languages = [] + + final List bootVersions = [] + + final Defaults defaults = new Defaults() + + static class Defaults { + + String groupId = 'org.test' + String artifactId + String version = '0.0.1-SNAPSHOT' + String name = 'demo' + String description = 'Demo project for Spring Boot' + String packageName + + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/InvalidInitializrMetadataException.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy similarity index 85% rename from initializr/src/main/groovy/io/spring/initializr/InvalidInitializrMetadataException.groovy rename to initializr/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy index ca5b6b11..e6ae863a 100644 --- a/initializr/src/main/groovy/io/spring/initializr/InvalidInitializrMetadataException.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InvalidInitializrMetadataException.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,9 +14,10 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.metadata import groovy.transform.InheritConstructors +import io.spring.initializr.InitializrException /** * Thrown when the configuration defines invalid metadata. diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy new file mode 100644 index 00000000..e80c4365 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/MetadataElement.groovy @@ -0,0 +1,40 @@ +/* + * 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 + +/** + * A basic meta-data element + * + * @author Stephane Nicoll + * @since 1.0 + */ +class MetadataElement { + + /** + * A visual representation of this element. + */ + String name + + /** + * The unique id of this element for a given capability. + */ + String id + + String getName() { + (name ?: id) + } +} \ No newline at end of file diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy new file mode 100644 index 00000000..e8dda105 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapability.groovy @@ -0,0 +1,46 @@ +/* + * 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 + +/** + * Defines a capability of the initializr service. Each capability + * is defined by a id and a {@link ServiceCapabilityType type}. + * + * @author Stephane Nicoll + * @since 1.0 + */ +abstract class ServiceCapability { + + final String id + + final ServiceCapabilityType type + + String description + + protected ServiceCapability(String id, ServiceCapabilityType type) { + this.id = id + this.type = type + } + + /** + * Return the "content" of this capability. The structure of the content + * vastly depends on the {@link ServiceCapability type} of the capability. + */ + abstract T getContent() + +} + diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy new file mode 100644 index 00000000..c0fe83ef --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/ServiceCapabilityType.groovy @@ -0,0 +1,54 @@ +/* + * 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 + +/** + * Defines the supported service capability type. + * + * @author Stephane Nicoll + * @since 1.0 + */ +enum ServiceCapabilityType { + + /** + * A special type that defines the action to use. + */ + ACTION('action'), + + /** + * A simple text value with no option. + */ + TEXT('text'), + + /** + * A simple value to be chosen amongst the specified options. + */ + 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') + + final String name + + ServiceCapabilityType(String name) { + this.name = name + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy new file mode 100644 index 00000000..37ffb5c0 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/SingleSelectCapability.groovy @@ -0,0 +1,40 @@ +/* + * 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 + +/** + * A {@link ServiceCapabilityType#SINGLE_SELECT single select} capability. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class SingleSelectCapability extends ServiceCapability> { + + final List content = [] + + SingleSelectCapability(String id) { + super(id, ServiceCapabilityType.SINGLE_SELECT) + } + + /** + * Return the default element of this capability. + */ + DefaultMetadataElement getDefault() { + return content.find { it.default } + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy new file mode 100644 index 00000000..7a96ee07 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/TextCapability.groovy @@ -0,0 +1,39 @@ +/* + * 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 + +/** + * A {@link ServiceCapabilityType#TEXT text} capability. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class TextCapability extends ServiceCapability { + + String content + + TextCapability(String id) { + super(id, ServiceCapabilityType.TEXT); + } + + TextCapability(String id, String content) { + this(id) + this.content = content + } + +} + diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/Type.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/Type.groovy new file mode 100644 index 00000000..564011c1 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/Type.groovy @@ -0,0 +1,45 @@ +/* + * 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 + +/** + * 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 + * @since 1.0 + */ +class Type extends DefaultMetadataElement { + + 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/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy new file mode 100644 index 00000000..e8dadf80 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/TypeCapability.groovy @@ -0,0 +1,48 @@ +/* + * 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 + +/** + * An {@link ServiceCapabilityType#ACTION action} capability. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class TypeCapability extends ServiceCapability> { + + final List content = [] + + TypeCapability() { + super('type', ServiceCapabilityType.ACTION) + } + + /** + * 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) } + } + + /** + * Return the default {@link Type}. + */ + Type getDefault() { + return content.find { it.default } + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/DefaultInitializrMetadataProvider.groovy b/initializr/src/main/groovy/io/spring/initializr/support/DefaultInitializrMetadataProvider.groovy similarity index 73% rename from initializr/src/main/groovy/io/spring/initializr/DefaultInitializrMetadataProvider.groovy rename to initializr/src/main/groovy/io/spring/initializr/support/DefaultInitializrMetadataProvider.groovy index 6f1bf01f..b8363eed 100644 --- a/initializr/src/main/groovy/io/spring/initializr/DefaultInitializrMetadataProvider.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/support/DefaultInitializrMetadataProvider.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,9 +14,12 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.support import groovy.util.logging.Slf4j +import io.spring.initializr.metadata.DefaultMetadataElement +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.metadata.InitializrMetadataProvider import org.springframework.beans.factory.annotation.Autowired import org.springframework.cache.annotation.Cacheable @@ -43,17 +46,18 @@ class DefaultInitializrMetadataProvider implements InitializrMetadataProvider { InitializrMetadata get() { def bootVersions = fetchBootVersions() if (bootVersions) { - metadata.merge(bootVersions) + metadata.bootVersions.content.clear() + metadata.bootVersions.content.addAll(bootVersions) } metadata } - protected List fetchBootVersions() { - def url = metadata.env.springBootMetadataUrl + protected List fetchBootVersions() { + def url = metadata.configuration.env.springBootMetadataUrl if (url) { try { log.info("Fetching boot metadata from $url") - return new SpringBootMetadataReader(url).getBootVersions() + return new SpringBootMetadataReader(url).bootVersions } catch (Exception e) { log.warn('Failed to fetch spring boot metadata', e) } diff --git a/initializr/src/main/groovy/io/spring/initializr/SpringBootMetadataReader.groovy b/initializr/src/main/groovy/io/spring/initializr/support/SpringBootMetadataReader.groovy similarity index 85% rename from initializr/src/main/groovy/io/spring/initializr/SpringBootMetadataReader.groovy rename to initializr/src/main/groovy/io/spring/initializr/support/SpringBootMetadataReader.groovy index b5e46302..8f3a3466 100644 --- a/initializr/src/main/groovy/io/spring/initializr/SpringBootMetadataReader.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/support/SpringBootMetadataReader.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,9 +14,10 @@ * limitations under the License. */ -package io.spring.initializr +package io.spring.initializr.support import groovy.json.JsonSlurper +import io.spring.initializr.metadata.DefaultMetadataElement import org.springframework.web.client.RestTemplate @@ -44,9 +45,9 @@ class SpringBootMetadataReader { /** * Return the boot versions parsed by this instance. */ - List getBootVersions() { + List getBootVersions() { content.projectReleases.collect { - def version = new InitializrMetadata.BootVersion() + def version = new DefaultMetadataElement() version.id = it.version def name = it.versionDisplayName version.name = (it.snapshot ? name + ' (SNAPSHOT)' : name) diff --git a/initializr/src/main/groovy/io/spring/initializr/support/GroovyTemplate.groovy b/initializr/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy similarity index 95% rename from initializr/src/main/groovy/io/spring/initializr/support/GroovyTemplate.groovy rename to initializr/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy index 1e5b941f..d54271e3 100644 --- a/initializr/src/main/groovy/io/spring/initializr/support/GroovyTemplate.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/util/GroovyTemplate.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.support +package io.spring.initializr.util import groovy.text.GStringTemplateEngine import groovy.text.Template diff --git a/initializr/src/main/groovy/io/spring/initializr/support/InvalidVersionException.groovy b/initializr/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy similarity index 95% rename from initializr/src/main/groovy/io/spring/initializr/support/InvalidVersionException.groovy rename to initializr/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy index 8ec74daa..1d5b174e 100644 --- a/initializr/src/main/groovy/io/spring/initializr/support/InvalidVersionException.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/util/InvalidVersionException.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.support +package io.spring.initializr.util import groovy.transform.InheritConstructors diff --git a/initializr/src/main/groovy/io/spring/initializr/support/Version.groovy b/initializr/src/main/groovy/io/spring/initializr/util/Version.groovy similarity index 99% rename from initializr/src/main/groovy/io/spring/initializr/support/Version.groovy rename to initializr/src/main/groovy/io/spring/initializr/util/Version.groovy index 83b7c80a..58515bb2 100644 --- a/initializr/src/main/groovy/io/spring/initializr/support/Version.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/util/Version.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.support +package io.spring.initializr.util import groovy.transform.EqualsAndHashCode import groovy.transform.ToString diff --git a/initializr/src/main/groovy/io/spring/initializr/support/VersionRange.groovy b/initializr/src/main/groovy/io/spring/initializr/util/VersionRange.groovy similarity index 98% rename from initializr/src/main/groovy/io/spring/initializr/support/VersionRange.groovy rename to initializr/src/main/groovy/io/spring/initializr/util/VersionRange.groovy index a5e6c6ea..2f05d2da 100644 --- a/initializr/src/main/groovy/io/spring/initializr/support/VersionRange.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/util/VersionRange.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.support +package io.spring.initializr.util import groovy.transform.EqualsAndHashCode import groovy.transform.ToString diff --git a/initializr/src/main/groovy/io/spring/initializr/web/AbstractInitializrController.groovy b/initializr/src/main/groovy/io/spring/initializr/web/AbstractInitializrController.groovy index 07dcecf9..7467c10d 100644 --- a/initializr/src/main/groovy/io/spring/initializr/web/AbstractInitializrController.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/web/AbstractInitializrController.groovy @@ -18,12 +18,12 @@ package io.spring.initializr.web import javax.annotation.PostConstruct -import io.spring.initializr.InitializrMetadataProvider +import io.spring.initializr.metadata.InitializrMetadataProvider import org.springframework.beans.factory.annotation.Autowired import org.springframework.web.servlet.support.ServletUriComponentsBuilder -import static io.spring.initializr.support.GroovyTemplate.template +import static io.spring.initializr.util.GroovyTemplate.template /** * A base controller that uses a {@link InitializrMetadataProvider} @@ -40,7 +40,7 @@ abstract class AbstractInitializrController { @PostConstruct void initialize() { - forceSsl = metadataProvider.get().env.forceSsl + forceSsl = metadataProvider.get().configuration.env.forceSsl } /** @@ -55,7 +55,7 @@ abstract class AbstractInitializrController { /** * Generate a full URL of the service, mostly for use in templates. - * @see io.spring.initializr.InitializrMetadata.Env#forceSsl + * @see io.spring.initializr.InitializrConfiguration.Env#forceSsl */ protected String generateAppUrl() { def builder = ServletUriComponentsBuilder.fromCurrentServletMapping() diff --git a/initializr/src/main/groovy/io/spring/initializr/web/MainController.groovy b/initializr/src/main/groovy/io/spring/initializr/web/MainController.groovy index 1b9ea7c9..e1c835fa 100644 --- a/initializr/src/main/groovy/io/spring/initializr/web/MainController.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/web/MainController.groovy @@ -17,10 +17,13 @@ package io.spring.initializr.web import groovy.util.logging.Slf4j -import io.spring.initializr.CommandLineHelpGenerator -import io.spring.initializr.InitializrMetadataVersion -import io.spring.initializr.ProjectGenerator -import io.spring.initializr.ProjectRequest +import io.spring.initializr.generator.CommandLineHelpGenerator +import io.spring.initializr.mapper.InitializrMetadataJsonMapper +import io.spring.initializr.mapper.InitializrMetadataV21JsonMapper +import io.spring.initializr.mapper.InitializrMetadataV2JsonMapper +import io.spring.initializr.mapper.InitializrMetadataVersion +import io.spring.initializr.generator.ProjectGenerator +import io.spring.initializr.generator.ProjectRequest import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpHeaders @@ -55,7 +58,7 @@ class MainController extends AbstractInitializrController { @ModelAttribute ProjectRequest projectRequest() { def request = new ProjectRequest() - metadataProvider.get().initializeProjectRequest(request) + request.initialize(metadataProvider.get()) request } @@ -92,10 +95,17 @@ class MainController extends AbstractInitializrController { private ResponseEntity serviceCapabilitiesFor(InitializrMetadataVersion version) { String appUrl = generateAppUrl() - def content = metadataProvider.get().generateJson(version, appUrl) + def content = getJsonMapper(version).write(metadataProvider.get(), appUrl) return ResponseEntity.ok().contentType(version.mediaType).body(content) } + private static InitializrMetadataJsonMapper getJsonMapper(InitializrMetadataVersion version) { + switch(version) { + case InitializrMetadataVersion.V2: return new InitializrMetadataV2JsonMapper(); + default: return new InitializrMetadataV21JsonMapper(); + } + } + @RequestMapping(value = '/', produces = 'text/html') @ResponseBody String home() { diff --git a/initializr/src/main/resources/META-INF/spring.factories b/initializr/src/main/resources/META-INF/spring.factories index 8726d25e..a6629e17 100644 --- a/initializr/src/main/resources/META-INF/spring.factories +++ b/initializr/src/main/resources/META-INF/spring.factories @@ -1 +1 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.spring.initializr.InitializrAutoConfiguration \ No newline at end of file +org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.spring.initializr.config.InitializrAutoConfiguration \ No newline at end of file diff --git a/initializr/src/main/resources/templates/home.html b/initializr/src/main/resources/templates/home.html index 2515795e..52ed94bc 100644 --- a/initializr/src/main/resources/templates/home.html +++ b/initializr/src/main/resources/templates/home.html @@ -26,45 +26,45 @@

- +

Project metadata

- +
- +
- +
- +
- +
@@ -74,7 +74,7 @@
@@ -84,7 +84,7 @@
@@ -94,7 +94,7 @@
@@ -104,7 +104,7 @@
@@ -113,7 +113,7 @@

Project dependencies

- <% dependencies.each { %> + <% dependencies.content.each { %>

${it.name}

<% it.content.each { %> diff --git a/initializr/src/main/resources/templates/sts-home.html b/initializr/src/main/resources/templates/sts-home.html index c2034560..ece87961 100644 --- a/initializr/src/main/resources/templates/sts-home.html +++ b/initializr/src/main/resources/templates/sts-home.html @@ -35,44 +35,44 @@

Spring Initializr

- - - - - + + + + + - <% dependencies.each { %> + <% dependencies.content.each { %> <% it.content.each { %> <% } } %> - <% types.each { %> + <% types.content.each { %> <% } %> - <% packagings.each { %> + <% packagings.content.each { %> <% } %> - <% javaVersions.each { %> + <% javaVersions.content.each { %> <% } %> - <% languages.each { %> + <% languages.content.each { %> <% } %> - <% bootVersions.each { %> + <% bootVersions.content.each { %>