mirror of
https://gitee.com/dcren/initializr.git
synced 2025-09-18 09:44:47 +08:00
Switch project structure to use the new generator
This commit removes the former `ProjectGenerator` api based on mustache template in favour of a new DSL infrastructure to be detailed in further commits. Event handling is now web-specific with a `ProjectRequest` and a `WebProjectRequest` that gathers the base input from the request and some additional web-specific metadata, respectively. As a consequence the `initializr-actuator` module has now a dependency on the `initializr-web` module. See gh-340 Co-authored-by: Stephane Nicoll <snicoll@pivotal.io>
This commit is contained in:

committed by
Stephane Nicoll

parent
0628829cd3
commit
e281480426
@@ -79,6 +79,18 @@
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.initializr.experimental</groupId>
|
||||
<artifactId>initializr-generator</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.initializr.experimental</groupId>
|
||||
<artifactId>initializr-generator-spring</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web;
|
||||
|
||||
import io.spring.initializr.InitializrException;
|
||||
|
||||
/**
|
||||
* Thrown when a {@link ProjectRequest} is invalid.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InvalidProjectRequestException extends InitializrException {
|
||||
|
||||
public InvalidProjectRequestException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidProjectRequestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* Locate project resources.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ProjectResourceLocator {
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
/**
|
||||
* Return the binary content of the resource at the specified location.
|
||||
* @param location a resource location
|
||||
* @return the content of the resource
|
||||
*/
|
||||
@Cacheable("initializr.project-resources")
|
||||
public byte[] getBinaryResource(String location) {
|
||||
try (InputStream stream = getInputStream(location)) {
|
||||
return StreamUtils.copyToByteArray(stream);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot get resource", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the textual content of the resource at the specified location.
|
||||
* @param location a resource location
|
||||
* @return the content of the resource
|
||||
*/
|
||||
@Cacheable("initializr.project-resources")
|
||||
public String getTextResource(String location) {
|
||||
try (InputStream stream = getInputStream(location)) {
|
||||
return StreamUtils.copyToString(stream, UTF_8);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot get resource", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getInputStream(String location) throws IOException {
|
||||
URL url = ResourceUtils.getURL(location);
|
||||
return url.openStream();
|
||||
}
|
||||
|
||||
}
|
@@ -16,30 +16,30 @@
|
||||
|
||||
package io.spring.initializr.web.autoconfigure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import javax.cache.configuration.MutableConfiguration;
|
||||
import javax.cache.expiry.CreatedExpiryPolicy;
|
||||
import javax.cache.expiry.Duration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.spring.initializr.generator.ProjectGenerator;
|
||||
import io.spring.initializr.generator.ProjectRequestPostProcessor;
|
||||
import io.spring.initializr.generator.ProjectRequestResolver;
|
||||
import io.spring.initializr.generator.ProjectResourceLocator;
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.project.ProjectDirectoryFactory;
|
||||
import io.spring.initializr.metadata.DependencyMetadataProvider;
|
||||
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.util.TemplateRenderer;
|
||||
import io.spring.initializr.web.ProjectResourceLocator;
|
||||
import io.spring.initializr.web.project.MainController;
|
||||
import io.spring.initializr.web.project.ProjectGenerationInvoker;
|
||||
import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter;
|
||||
import io.spring.initializr.web.support.DefaultDependencyMetadataProvider;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
|
||||
import io.spring.initializr.web.ui.UiController;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -50,6 +50,8 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -60,9 +62,6 @@ import org.springframework.web.servlet.resource.ResourceUrlProvider;
|
||||
* Auto-configuration} to configure Spring initializr. In a web environment, configures
|
||||
* the necessary controller to serve the applications from the root context.
|
||||
*
|
||||
* <p>
|
||||
* Project generation can be customized by defining a custom {@link ProjectGenerator}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration
|
||||
@@ -71,18 +70,16 @@ import org.springframework.web.servlet.resource.ResourceUrlProvider;
|
||||
RestTemplateAutoConfiguration.class })
|
||||
public class InitializrAutoConfiguration {
|
||||
|
||||
private final List<ProjectRequestPostProcessor> postProcessors;
|
||||
|
||||
public InitializrAutoConfiguration(
|
||||
ObjectProvider<List<ProjectRequestPostProcessor>> postProcessors) {
|
||||
List<ProjectRequestPostProcessor> list = postProcessors.getIfAvailable();
|
||||
this.postProcessors = (list != null) ? list : new ArrayList<>();
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ProjectDirectoryFactory projectDirectoryFactory() {
|
||||
return (description) -> Files.createTempDirectory("project-");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ProjectGenerator projectGenerator() {
|
||||
return new ProjectGenerator();
|
||||
public IndentingWriterFactory indentingWriterFactory() {
|
||||
return IndentingWriterFactory.create(new SimpleIndentStrategy("\t"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -95,12 +92,6 @@ public class InitializrAutoConfiguration {
|
||||
return templateRenderer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ProjectRequestResolver projectRequestResolver() {
|
||||
return new ProjectRequestResolver(this.postProcessors);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ProjectResourceLocator projectResourceLocator() {
|
||||
@@ -142,10 +133,26 @@ public class InitializrAutoConfiguration {
|
||||
InitializrMetadataProvider metadataProvider,
|
||||
TemplateRenderer templateRenderer,
|
||||
ResourceUrlProvider resourceUrlProvider,
|
||||
ProjectGenerator projectGenerator,
|
||||
DependencyMetadataProvider dependencyMetadataProvider) {
|
||||
DependencyMetadataProvider dependencyMetadataProvider,
|
||||
ProjectGenerationInvoker projectGenerationInvoker) {
|
||||
return new MainController(metadataProvider, templateRenderer,
|
||||
resourceUrlProvider, projectGenerator, dependencyMetadataProvider);
|
||||
resourceUrlProvider, dependencyMetadataProvider,
|
||||
projectGenerationInvoker);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ProjectGenerationInvoker projectGenerationInvoker(
|
||||
ApplicationContext applicationContext,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
ProjectRequestToDescriptionConverter projectRequestToDescriptionConverter) {
|
||||
return new ProjectGenerationInvoker(applicationContext, eventPublisher,
|
||||
projectRequestToDescriptionConverter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProjectRequestToDescriptionConverter projectRequestToDescriptionConverter() {
|
||||
return new ProjectRequestToDescriptionConverter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -177,6 +184,7 @@ public class InitializrAutoConfiguration {
|
||||
CreatedExpiryPolicy.factoryOf(Duration.TEN_MINUTES)));
|
||||
cacheManager.createCache("initializr.dependency-metadata", config());
|
||||
cacheManager.createCache("initializr.project-resources", config());
|
||||
cacheManager.createCache("initializr.templates", config());
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -23,10 +23,10 @@ import java.util.function.Function;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import io.spring.initializr.generator.InvalidProjectRequestException;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.metadata.InitializrMetadataProvider;
|
||||
import io.spring.initializr.metadata.TypeCapability;
|
||||
import io.spring.initializr.web.InvalidProjectRequestException;
|
||||
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
@@ -28,9 +28,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import io.spring.initializr.generator.BasicProjectRequest;
|
||||
import io.spring.initializr.generator.ProjectGenerator;
|
||||
import io.spring.initializr.generator.ProjectRequest;
|
||||
import io.spring.initializr.metadata.DependencyMetadata;
|
||||
import io.spring.initializr.metadata.DependencyMetadataProvider;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
@@ -87,26 +84,25 @@ public class MainController extends AbstractInitializrController {
|
||||
public static final MediaType HAL_JSON_CONTENT_TYPE = MediaType
|
||||
.parseMediaType("application/hal+json");
|
||||
|
||||
private final ProjectGenerator projectGenerator;
|
||||
|
||||
private final DependencyMetadataProvider dependencyMetadataProvider;
|
||||
|
||||
private final CommandLineHelpGenerator commandLineHelpGenerator;
|
||||
|
||||
private final ProjectGenerationInvoker projectGenerationInvoker;
|
||||
|
||||
public MainController(InitializrMetadataProvider metadataProvider,
|
||||
TemplateRenderer templateRenderer, ResourceUrlProvider resourceUrlProvider,
|
||||
ProjectGenerator projectGenerator,
|
||||
DependencyMetadataProvider dependencyMetadataProvider) {
|
||||
DependencyMetadataProvider dependencyMetadataProvider,
|
||||
ProjectGenerationInvoker projectGenerationInvoker) {
|
||||
super(metadataProvider, resourceUrlProvider);
|
||||
this.projectGenerator = projectGenerator;
|
||||
this.dependencyMetadataProvider = dependencyMetadataProvider;
|
||||
this.commandLineHelpGenerator = new CommandLineHelpGenerator(templateRenderer);
|
||||
this.projectGenerationInvoker = projectGenerationInvoker;
|
||||
}
|
||||
|
||||
@ModelAttribute
|
||||
public BasicProjectRequest projectRequest(
|
||||
@RequestHeader Map<String, String> headers) {
|
||||
ProjectRequest request = new ProjectRequest();
|
||||
public ProjectRequest projectRequest(@RequestHeader Map<String, String> headers) {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.getParameters().putAll(headers);
|
||||
request.initialize(this.metadataProvider.get());
|
||||
return request;
|
||||
@@ -246,32 +242,27 @@ public class MainController extends AbstractInitializrController {
|
||||
|
||||
@RequestMapping(path = { "/pom", "/pom.xml" })
|
||||
@ResponseBody
|
||||
public ResponseEntity<byte[]> pom(BasicProjectRequest request) {
|
||||
public ResponseEntity<byte[]> pom(ProjectRequest request) {
|
||||
request.setType("maven-build");
|
||||
byte[] mavenPom = this.projectGenerator
|
||||
.generateMavenPom((ProjectRequest) request);
|
||||
byte[] mavenPom = this.projectGenerationInvoker.invokeBuildGeneration(request);
|
||||
return createResponseEntity(mavenPom, "application/octet-stream", "pom.xml");
|
||||
}
|
||||
|
||||
@RequestMapping(path = { "/build", "/build.gradle" })
|
||||
@ResponseBody
|
||||
public ResponseEntity<byte[]> gradle(BasicProjectRequest request) {
|
||||
public ResponseEntity<byte[]> gradle(ProjectRequest request) {
|
||||
request.setType("gradle-build");
|
||||
byte[] gradleBuild = this.projectGenerator
|
||||
.generateGradleBuild((ProjectRequest) request);
|
||||
byte[] gradleBuild = this.projectGenerationInvoker.invokeBuildGeneration(request);
|
||||
return createResponseEntity(gradleBuild, "application/octet-stream",
|
||||
"build.gradle");
|
||||
}
|
||||
|
||||
@RequestMapping("/starter.zip")
|
||||
@ResponseBody
|
||||
public ResponseEntity<byte[]> springZip(BasicProjectRequest basicRequest)
|
||||
throws IOException {
|
||||
ProjectRequest request = (ProjectRequest) basicRequest;
|
||||
File dir = this.projectGenerator.generateProjectStructure(request);
|
||||
|
||||
File download = this.projectGenerator.createDistributionFile(dir, ".zip");
|
||||
|
||||
public ResponseEntity<byte[]> springZip(ProjectRequest request) throws IOException {
|
||||
File dir = this.projectGenerationInvoker
|
||||
.invokeProjectStructureGeneration(request);
|
||||
File download = this.projectGenerationInvoker.createDistributionFile(dir, ".zip");
|
||||
String wrapperScript = getWrapperScript(request);
|
||||
new File(dir, wrapperScript).setExecutable(true);
|
||||
Zip zip = new Zip();
|
||||
@@ -296,13 +287,11 @@ public class MainController extends AbstractInitializrController {
|
||||
|
||||
@RequestMapping(path = "/starter.tgz", produces = "application/x-compress")
|
||||
@ResponseBody
|
||||
public ResponseEntity<byte[]> springTgz(BasicProjectRequest basicRequest)
|
||||
throws IOException {
|
||||
ProjectRequest request = (ProjectRequest) basicRequest;
|
||||
File dir = this.projectGenerator.generateProjectStructure(request);
|
||||
|
||||
File download = this.projectGenerator.createDistributionFile(dir, ".tar.gz");
|
||||
|
||||
public ResponseEntity<byte[]> springTgz(ProjectRequest request) throws IOException {
|
||||
File dir = this.projectGenerationInvoker
|
||||
.invokeProjectStructureGeneration(request);
|
||||
File download = this.projectGenerationInvoker.createDistributionFile(dir,
|
||||
".tar.gz");
|
||||
String wrapperScript = getWrapperScript(request);
|
||||
new File(dir, wrapperScript).setExecutable(true);
|
||||
Tar zip = new Tar();
|
||||
@@ -338,7 +327,8 @@ public class MainController extends AbstractInitializrController {
|
||||
}
|
||||
|
||||
private static String getWrapperScript(ProjectRequest request) {
|
||||
String script = ("gradle".equals(request.getBuild()) ? "gradlew" : "mvnw");
|
||||
String script = (request.getType() != null
|
||||
&& request.getType().startsWith("gradle")) ? "gradlew" : "mvnw";
|
||||
return (request.getBaseDir() != null) ? request.getBaseDir() + "/" + script
|
||||
: script;
|
||||
}
|
||||
@@ -349,7 +339,7 @@ public class MainController extends AbstractInitializrController {
|
||||
log.info("Uploading: {} ({} bytes)", download, bytes.length);
|
||||
ResponseEntity<byte[]> result = createResponseEntity(bytes, contentType,
|
||||
fileName);
|
||||
this.projectGenerator.cleanTempFiles(dir);
|
||||
this.projectGenerationInvoker.cleanTempFiles(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
/**
|
||||
* Event published when an error occurred trying to generate a project.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ProjectFailedEvent extends ProjectRequestEvent {
|
||||
|
||||
private final Exception cause;
|
||||
|
||||
public ProjectFailedEvent(ProjectRequest request, InitializrMetadata metadata,
|
||||
Exception cause) {
|
||||
super(request, metadata);
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cause of the failure.
|
||||
* @return the cause of the failure
|
||||
*/
|
||||
public Exception getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
/**
|
||||
* Event published when a new project has been generated successfully.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ProjectGeneratedEvent extends ProjectRequestEvent {
|
||||
|
||||
public ProjectGeneratedEvent(ProjectRequest request, InitializrMetadata metadata) {
|
||||
super(request, metadata);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.InitializrException;
|
||||
import io.spring.initializr.generator.buildsystem.Build;
|
||||
import io.spring.initializr.generator.buildsystem.BuildItemResolver;
|
||||
import io.spring.initializr.generator.project.DefaultProjectAssetGenerator;
|
||||
import io.spring.initializr.generator.project.ProjectAssetGenerator;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.project.ProjectGenerationContext;
|
||||
import io.spring.initializr.generator.project.ProjectGenerationException;
|
||||
import io.spring.initializr.generator.project.ProjectGenerator;
|
||||
import io.spring.initializr.generator.project.ResolvedProjectDescription;
|
||||
import io.spring.initializr.generator.spring.build.BuildWriter;
|
||||
import io.spring.initializr.generator.spring.build.MetadataBuildItemResolver;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.metadata.InitializrMetadataProvider;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
/**
|
||||
* Invokes the project generation API. This is an intermediate layer that can consume a
|
||||
* {@link ProjectRequest} and trigger project generation based on the request.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ProjectGenerationInvoker {
|
||||
|
||||
private final ApplicationContext parentApplicationContext;
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
private final ProjectRequestToDescriptionConverter converter;
|
||||
|
||||
private transient Map<String, List<File>> temporaryFiles = new LinkedHashMap<>();
|
||||
|
||||
public ProjectGenerationInvoker(ApplicationContext parentApplicationContext,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
ProjectRequestToDescriptionConverter converter) {
|
||||
this.parentApplicationContext = parentApplicationContext;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the project generation API that generates the entire project structure for
|
||||
* the specified {@link WebProjectRequest}. Returns a directory containing the
|
||||
* project.
|
||||
* @param request the project request
|
||||
* @return the generated project structure
|
||||
*/
|
||||
public File invokeProjectStructureGeneration(ProjectRequest request) {
|
||||
InitializrMetadata metadata = this.parentApplicationContext
|
||||
.getBean(InitializrMetadataProvider.class).get();
|
||||
try {
|
||||
ProjectDescription projectDescription = this.converter.convert(request,
|
||||
metadata);
|
||||
ProjectGenerator projectGenerator = new ProjectGenerator(
|
||||
(projectGenerationContext) -> customizeProjectGenerationContext(
|
||||
projectGenerationContext, metadata));
|
||||
Path path = projectGenerator.generate(projectDescription,
|
||||
generateProject(request));
|
||||
File file = path.toFile();
|
||||
String name = file.getName();
|
||||
addTempFile(name, file);
|
||||
return file;
|
||||
}
|
||||
catch (ProjectGenerationException | InitializrException ex) {
|
||||
publishProjectFailedEvent(request, metadata, ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private ProjectAssetGenerator<Path> generateProject(ProjectRequest request) {
|
||||
return (context) -> {
|
||||
Path projectDir = new DefaultProjectAssetGenerator().generate(context);
|
||||
publishProjectGeneratedEvent(request, context);
|
||||
return projectDir;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the project generation API that knows how to just write the build file.
|
||||
* Returns a directory containing the project for the specified
|
||||
* {@link WebProjectRequest}.
|
||||
* @param request the project request
|
||||
* @return the generated build content
|
||||
*/
|
||||
public byte[] invokeBuildGeneration(ProjectRequest request) {
|
||||
InitializrMetadata metadata = this.parentApplicationContext
|
||||
.getBean(InitializrMetadataProvider.class).get();
|
||||
try {
|
||||
ProjectDescription projectDescription = this.converter.convert(request,
|
||||
metadata);
|
||||
ProjectGenerator projectGenerator = new ProjectGenerator(
|
||||
(projectGenerationContext) -> customizeProjectGenerationContext(
|
||||
projectGenerationContext, metadata));
|
||||
return projectGenerator.generate(projectDescription, generateBuild(request));
|
||||
}
|
||||
catch (ProjectGenerationException | InitializrException ex) {
|
||||
publishProjectFailedEvent(request, metadata, ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private ProjectAssetGenerator<byte[]> generateBuild(ProjectRequest request) {
|
||||
return (context) -> {
|
||||
byte[] content = generateBuild(context);
|
||||
publishProjectGeneratedEvent(request, context);
|
||||
return content;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in the same directory as the given directory using the directory name
|
||||
* and extension.
|
||||
* @param dir the directory used to determine the path and name of the new file
|
||||
* @param extension the extension to use for the new file
|
||||
* @return the newly created file
|
||||
*/
|
||||
public File createDistributionFile(File dir, String extension) {
|
||||
File download = new File(dir.getParent(), dir.getName() + extension);
|
||||
addTempFile(dir.getName(), download);
|
||||
return download;
|
||||
}
|
||||
|
||||
private void addTempFile(String group, File file) {
|
||||
this.temporaryFiles.computeIfAbsent(group, (key) -> new ArrayList<>()).add(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean all the temporary files that are related to this root directory.
|
||||
* @param dir the directory to clean
|
||||
* @see #createDistributionFile
|
||||
*/
|
||||
public void cleanTempFiles(File dir) {
|
||||
List<File> tempFiles = this.temporaryFiles.remove(dir.getName());
|
||||
if (!tempFiles.isEmpty()) {
|
||||
tempFiles.forEach((File file) -> {
|
||||
if (file.isDirectory()) {
|
||||
FileSystemUtils.deleteRecursively(file);
|
||||
}
|
||||
else if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] generateBuild(ProjectGenerationContext context) throws IOException {
|
||||
ResolvedProjectDescription projectDescription = context
|
||||
.getBean(ResolvedProjectDescription.class);
|
||||
StringWriter out = new StringWriter();
|
||||
BuildWriter buildWriter = context.getBeanProvider(BuildWriter.class)
|
||||
.getIfAvailable();
|
||||
if (buildWriter != null) {
|
||||
buildWriter.writeBuild(out);
|
||||
return out.toString().getBytes();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("No BuildWriter implementation found for "
|
||||
+ projectDescription.getLanguage());
|
||||
}
|
||||
}
|
||||
|
||||
private void customizeProjectGenerationContext(
|
||||
AnnotationConfigApplicationContext context, InitializrMetadata metadata) {
|
||||
context.setParent(this.parentApplicationContext);
|
||||
context.registerBean(InitializrMetadata.class, () -> metadata);
|
||||
context.registerBean(BuildItemResolver.class,
|
||||
() -> new MetadataBuildItemResolver(metadata));
|
||||
}
|
||||
|
||||
private void publishProjectGeneratedEvent(ProjectRequest request,
|
||||
ProjectGenerationContext context) {
|
||||
Build build = context.getBeanProvider(Build.class).getIfAvailable();
|
||||
InitializrMetadata metadata = context.getBean(InitializrMetadata.class);
|
||||
ProjectGeneratedEvent event = new ProjectGeneratedEvent(request, metadata);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
}
|
||||
|
||||
private void publishProjectFailedEvent(ProjectRequest request,
|
||||
InitializrMetadata metadata, Exception cause) {
|
||||
ProjectFailedEvent event = new ProjectFailedEvent(request, metadata, cause);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The base settings of a project request. Only these can be bound by user's input.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ProjectRequest {
|
||||
|
||||
private List<String> style = new ArrayList<>();
|
||||
|
||||
private List<String> dependencies = new ArrayList<>();
|
||||
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
||||
private String description;
|
||||
|
||||
private String groupId;
|
||||
|
||||
private String artifactId;
|
||||
|
||||
private String version;
|
||||
|
||||
private String bootVersion;
|
||||
|
||||
private String packaging;
|
||||
|
||||
private String applicationName;
|
||||
|
||||
private String language;
|
||||
|
||||
private String packageName;
|
||||
|
||||
private String javaVersion;
|
||||
|
||||
// The base directory to create in the archive - no baseDir by default
|
||||
private String baseDir;
|
||||
|
||||
public List<String> getStyle() {
|
||||
return this.style;
|
||||
}
|
||||
|
||||
public void setStyle(List<String> style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public List<String> getDependencies() {
|
||||
return this.dependencies;
|
||||
}
|
||||
|
||||
public void setDependencies(List<String> dependencies) {
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return this.groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(String groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return this.artifactId;
|
||||
}
|
||||
|
||||
public void setArtifactId(String artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getBootVersion() {
|
||||
return this.bootVersion;
|
||||
}
|
||||
|
||||
public void setBootVersion(String bootVersion) {
|
||||
this.bootVersion = bootVersion;
|
||||
}
|
||||
|
||||
public String getPackaging() {
|
||||
return this.packaging;
|
||||
}
|
||||
|
||||
public void setPackaging(String packaging) {
|
||||
this.packaging = packaging;
|
||||
}
|
||||
|
||||
public String getApplicationName() {
|
||||
return this.applicationName;
|
||||
}
|
||||
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return this.language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
if (StringUtils.hasText(this.packageName)) {
|
||||
return this.packageName;
|
||||
}
|
||||
if (StringUtils.hasText(this.groupId) && StringUtils.hasText(this.artifactId)) {
|
||||
return getGroupId() + "." + getArtifactId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public String getJavaVersion() {
|
||||
return this.javaVersion;
|
||||
}
|
||||
|
||||
public void setJavaVersion(String javaVersion) {
|
||||
this.javaVersion = javaVersion;
|
||||
}
|
||||
|
||||
public String getBaseDir() {
|
||||
return this.baseDir;
|
||||
}
|
||||
|
||||
public void setBaseDir(String baseDir) {
|
||||
this.baseDir = baseDir;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
/**
|
||||
* Event published when a {@link ProjectRequest} has been processed.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @see ProjectGeneratedEvent
|
||||
* @see ProjectFailedEvent
|
||||
*/
|
||||
public abstract class ProjectRequestEvent {
|
||||
|
||||
private final ProjectRequest request;
|
||||
|
||||
private final InitializrMetadata metadata;
|
||||
|
||||
private final long timestamp;
|
||||
|
||||
protected ProjectRequestEvent(ProjectRequest request, InitializrMetadata metadata) {
|
||||
this.request = request;
|
||||
this.metadata = metadata;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link ProjectRequest} used to generate the project.
|
||||
* @return the project request
|
||||
*/
|
||||
public ProjectRequest getProjectRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp at which the request was processed.
|
||||
* @return the timestamp that the request was processed
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the metadata that was used to generate the project.
|
||||
* @return the metadata
|
||||
*/
|
||||
public InitializrMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.spring.initializr.generator.buildsystem.BuildSystem;
|
||||
import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem;
|
||||
import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
|
||||
import io.spring.initializr.generator.language.Language;
|
||||
import io.spring.initializr.generator.packaging.Packaging;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.spring.build.MetadataBuildItemMapper;
|
||||
import io.spring.initializr.metadata.DefaultMetadataElement;
|
||||
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.web.InvalidProjectRequestException;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Validates a {@link ProjectRequest} and creates a {@link ProjectDescription} from it.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ProjectRequestToDescriptionConverter {
|
||||
|
||||
private static final Version VERSION_1_5_0 = Version.parse("1.5.0.RELEASE");
|
||||
|
||||
public ProjectDescription convert(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
validate(request, metadata);
|
||||
ProjectDescription description = new ProjectDescription();
|
||||
description.setApplicationName(getApplicationName(request, metadata));
|
||||
description.setArtifactId(request.getArtifactId());
|
||||
description.setBaseDirectory(request.getBaseDir());
|
||||
description.setBuildSystem(getBuildSystem(request));
|
||||
description.setDescription(request.getDescription());
|
||||
description.setGroupId(request.getGroupId());
|
||||
description.setLanguage(
|
||||
Language.forId(request.getLanguage(), request.getJavaVersion()));
|
||||
description.setName(request.getName());
|
||||
description.setPackageName(getPackageName(request, metadata));
|
||||
description.setPackaging(Packaging.forId(request.getPackaging()));
|
||||
String springBootVersion = getSpringBootVersion(request, metadata);
|
||||
description
|
||||
.setPlatformVersion(MetadataBuildItemMapper.toVersion(springBootVersion));
|
||||
getResolvedDependencies(request, springBootVersion, metadata)
|
||||
.forEach((dependency) -> description.addDependency(dependency.getId(),
|
||||
MetadataBuildItemMapper.toDependency(dependency)));
|
||||
return description;
|
||||
}
|
||||
|
||||
private void validate(ProjectRequest request, InitializrMetadata metadata) {
|
||||
validateSpringBootVersion(request);
|
||||
validateType(request.getType(), metadata);
|
||||
validateLanguage(request.getLanguage(), metadata);
|
||||
validatePackaging(request.getPackaging(), metadata);
|
||||
validateDependencies(request, metadata);
|
||||
}
|
||||
|
||||
private void validateSpringBootVersion(ProjectRequest request) {
|
||||
Version bootVersion = Version.safeParse(request.getBootVersion());
|
||||
if (bootVersion != null && bootVersion.compareTo(VERSION_1_5_0) < 0) {
|
||||
throw new InvalidProjectRequestException("Invalid Spring Boot version "
|
||||
+ bootVersion + " must be 1.5.0 or higher");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateType(String type, InitializrMetadata metadata) {
|
||||
if (type != null) {
|
||||
Type typeFromMetadata = metadata.getTypes().get(type);
|
||||
if (typeFromMetadata == null) {
|
||||
throw new InvalidProjectRequestException(
|
||||
"Unknown type '" + type + "' check project metadata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLanguage(String language, InitializrMetadata metadata) {
|
||||
if (language != null) {
|
||||
DefaultMetadataElement languageFromMetadata = metadata.getLanguages()
|
||||
.get(language);
|
||||
if (languageFromMetadata == null) {
|
||||
throw new InvalidProjectRequestException(
|
||||
"Unknown language '" + language + "' check project metadata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePackaging(String packaging, InitializrMetadata metadata) {
|
||||
if (packaging != null) {
|
||||
DefaultMetadataElement packagingFromMetadata = metadata.getPackagings()
|
||||
.get(packaging);
|
||||
if (packagingFromMetadata == null) {
|
||||
throw new InvalidProjectRequestException(
|
||||
"Unknown packaging '" + packaging + "' check project metadata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDependencies(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
List<String> dependencies = (!request.getStyle().isEmpty() ? request.getStyle()
|
||||
: request.getDependencies());
|
||||
dependencies.forEach((dep) -> {
|
||||
Dependency dependency = metadata.getDependencies().get(dep);
|
||||
if (dependency == null) {
|
||||
throw new InvalidProjectRequestException(
|
||||
"Unknown dependency '" + dep + "' check project metadata");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BuildSystem getBuildSystem(ProjectRequest request) {
|
||||
return (request.getType().startsWith("gradle")) ? new GradleBuildSystem()
|
||||
: new MavenBuildSystem();
|
||||
}
|
||||
|
||||
private String getPackageName(ProjectRequest request, InitializrMetadata metadata) {
|
||||
return metadata.getConfiguration().cleanPackageName(request.getPackageName(),
|
||||
metadata.getPackageName().getContent());
|
||||
}
|
||||
|
||||
private String getApplicationName(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
if (!StringUtils.hasText(request.getApplicationName())) {
|
||||
return metadata.getConfiguration().generateApplicationName(request.getName());
|
||||
}
|
||||
return request.getApplicationName();
|
||||
}
|
||||
|
||||
private String getSpringBootVersion(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
return (request.getBootVersion() != null) ? request.getBootVersion()
|
||||
: metadata.getBootVersions().getDefault().getId();
|
||||
}
|
||||
|
||||
private List<Dependency> getResolvedDependencies(ProjectRequest request,
|
||||
String springBootVersion, InitializrMetadata metadata) {
|
||||
List<String> depIds = (!request.getStyle().isEmpty() ? request.getStyle()
|
||||
: request.getDependencies());
|
||||
Version requestedVersion = Version.parse(springBootVersion);
|
||||
return depIds.stream().map((it) -> {
|
||||
Dependency dependency = metadata.getDependencies().get(it);
|
||||
return dependency.resolve(requestedVersion);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
|
||||
/**
|
||||
* A {@link ProjectRequest} with some additional information to identify the request.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class WebProjectRequest extends ProjectRequest {
|
||||
|
||||
private final Map<String, Object> parameters = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Return the additional parameters that can be used to further identify the request.
|
||||
* @return the parameters
|
||||
*/
|
||||
public Map<String, Object> getParameters() {
|
||||
return this.parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the state of this request with defaults defined in the
|
||||
* {@link InitializrMetadata metadata}.
|
||||
* @param metadata the metadata to use
|
||||
*/
|
||||
public void initialize(InitializrMetadata metadata) {
|
||||
BeanWrapperImpl bean = new BeanWrapperImpl(this);
|
||||
metadata.defaults().forEach((key, value) -> {
|
||||
if (bean.isWritableProperty(key)) {
|
||||
// We want to be able to infer a package name if none has been
|
||||
// explicitly set
|
||||
if (!key.equals("packageName")) {
|
||||
bean.setPropertyValue(key, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@@ -28,11 +28,11 @@ import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.spring.initializr.generator.spring.test.ProjectAssert;
|
||||
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.test.generator.ProjectAssert;
|
||||
import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
|
||||
|
@@ -16,13 +16,13 @@
|
||||
|
||||
package io.spring.initializr.web.autoconfigure;
|
||||
|
||||
import io.spring.initializr.generator.ProjectGenerator;
|
||||
import io.spring.initializr.generator.ProjectRequestResolver;
|
||||
import io.spring.initializr.generator.ProjectResourceLocator;
|
||||
import io.spring.initializr.metadata.DependencyMetadataProvider;
|
||||
import io.spring.initializr.metadata.InitializrMetadataProvider;
|
||||
import io.spring.initializr.util.TemplateRenderer;
|
||||
import io.spring.initializr.web.ProjectResourceLocator;
|
||||
import io.spring.initializr.web.project.MainController;
|
||||
import io.spring.initializr.web.project.ProjectGenerationInvoker;
|
||||
import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter;
|
||||
import io.spring.initializr.web.ui.UiController;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -58,22 +58,6 @@ class InitializrAutoConfigurationTests {
|
||||
.withConfiguration(AutoConfigurations.of(RestTemplateAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, InitializrAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void autoConfigRegistersProjectGenerator() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(ProjectGenerator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigWhenProjectGeneratorBeanPresentDoesNotRegisterProjectGenerator() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomProjectGeneratorConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ProjectGenerator.class);
|
||||
assertThat(context).hasBean("testProjectGenerator");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigRegistersTemplateRenderer() {
|
||||
this.contextRunner.run(
|
||||
@@ -90,22 +74,6 @@ class InitializrAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigRegistersProjectRequestResolver() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ProjectRequestResolver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigWhenProjectRequestResolverBeanPresentDoesNotRegisterProjectRequestResolver() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomProjectRequestResolverConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ProjectRequestResolver.class);
|
||||
assertThat(context).hasBean("testProjectRequestResolver");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigRegistersProjectResourceLocator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
@@ -180,6 +148,8 @@ class InitializrAutoConfigurationTests {
|
||||
InitializrAutoConfiguration.class));
|
||||
webContextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(InitializrWebConfig.class);
|
||||
assertThat(context).hasSingleBean(ProjectGenerationInvoker.class);
|
||||
assertThat(context).hasSingleBean(ProjectRequestToDescriptionConverter.class);
|
||||
assertThat(context).hasSingleBean(MainController.class);
|
||||
assertThat(context).hasSingleBean(UiController.class);
|
||||
});
|
||||
@@ -221,16 +191,6 @@ class InitializrAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomProjectGeneratorConfiguration {
|
||||
|
||||
@Bean
|
||||
public ProjectGenerator testProjectGenerator() {
|
||||
return Mockito.mock(ProjectGenerator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomTemplateRendererConfiguration {
|
||||
|
||||
@@ -241,16 +201,6 @@ class InitializrAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomProjectRequestResolverConfiguration {
|
||||
|
||||
@Bean
|
||||
public ProjectRequestResolver testProjectRequestResolver() {
|
||||
return Mockito.mock(ProjectRequestResolver.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomProjectResourceLocatorConfiguration {
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
package io.spring.initializr.web.project;
|
||||
|
||||
import io.spring.initializr.test.generator.PomAssert;
|
||||
import io.spring.initializr.generator.spring.test.build.PomAssert;
|
||||
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
package io.spring.initializr.web.project;
|
||||
|
||||
import io.spring.initializr.test.generator.PomAssert;
|
||||
import io.spring.initializr.generator.spring.test.build.PomAssert;
|
||||
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -39,8 +39,8 @@ class MainControllerDefaultsIntegrationTests
|
||||
String.class);
|
||||
PomAssert pomAssert = new PomAssert(content);
|
||||
pomAssert.hasGroupId("org.foo").hasArtifactId("foo-bar")
|
||||
.hasVersion("1.2.4-SNAPSHOT").hasPackaging("jar").hasName("FooBar")
|
||||
.hasDescription("FooBar Project");
|
||||
.hasVersion("1.2.4-SNAPSHOT").doesNotHaveNode("/project/packaging")
|
||||
.hasName("FooBar").hasDescription("FooBar Project");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -18,7 +18,7 @@ package io.spring.initializr.web.project;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import io.spring.initializr.test.generator.ProjectAssert;
|
||||
import io.spring.initializr.generator.spring.test.ProjectAssert;
|
||||
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@@ -69,7 +69,7 @@ class MainControllerIntegrationTests
|
||||
Dependency biz = Dependency.create("org.acme", "biz", "1.3.5", "runtime");
|
||||
downloadTgz("/starter.tgz?style=org.acme:biz&bootVersion=2.2.1.RELEASE")
|
||||
.isJavaProject().isMavenProject().hasStaticAndTemplatesResources(false)
|
||||
.pomAssert().hasDependenciesCount(2).hasDependency(biz);
|
||||
.pomAssert().hasDependenciesCount(3).hasDependency(biz);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -16,55 +16,61 @@
|
||||
|
||||
package io.spring.initializr.web.project;
|
||||
|
||||
import io.spring.initializr.generator.ProjectRequest;
|
||||
import io.spring.initializr.generator.ProjectRequestPostProcessor;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.generator.language.java.JavaLanguage;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.project.ProjectDescriptionCustomizer;
|
||||
import io.spring.initializr.generator.version.Version;
|
||||
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests;
|
||||
import io.spring.initializr.web.project.ProjectGenerationPostProcessorTests.ProjectRequestPostProcessorConfiguration;
|
||||
import io.spring.initializr.web.project.ProjectGenerationDescriptionCustomizerTests.ProjectDescriptionCustomizerConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@ActiveProfiles("test-default")
|
||||
@Import(ProjectRequestPostProcessorConfiguration.class)
|
||||
class ProjectGenerationPostProcessorTests
|
||||
@Import(ProjectDescriptionCustomizerConfiguration.class)
|
||||
class ProjectGenerationDescriptionCustomizerTests
|
||||
extends AbstractInitializrControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
void postProcessorsInvoked() {
|
||||
void projectDescriptionCustomizersAreInvoked() {
|
||||
downloadZip("/starter.zip?bootVersion=2.0.4.RELEASE&javaVersion=1.8")
|
||||
.isJavaProject().isMavenProject().pomAssert()
|
||||
.hasSpringBootParent("2.2.3.RELEASE").hasProperty("java.version", "1.7");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ProjectRequestPostProcessorConfiguration {
|
||||
static class ProjectDescriptionCustomizerConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
ProjectRequestPostProcessor secondPostProcessor() {
|
||||
return new ProjectRequestPostProcessor() {
|
||||
public ProjectDescriptionCustomizer secondPostProcessor() {
|
||||
return new ProjectDescriptionCustomizer() {
|
||||
@Override
|
||||
public void postProcessBeforeResolution(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
request.setJavaVersion("1.7");
|
||||
public void customize(ProjectDescription description) {
|
||||
description.setLanguage(new JavaLanguage("1.7"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
ProjectRequestPostProcessor firstPostProcessor() {
|
||||
return new ProjectRequestPostProcessor() {
|
||||
public ProjectDescriptionCustomizer firstPostProcessor() {
|
||||
return new ProjectDescriptionCustomizer() {
|
||||
@Override
|
||||
public void postProcessBeforeResolution(ProjectRequest request,
|
||||
InitializrMetadata metadata) {
|
||||
request.setJavaVersion("1.2");
|
||||
request.setBootVersion("2.2.3.RELEASE");
|
||||
public void customize(ProjectDescription description) {
|
||||
description.setLanguage(new JavaLanguage("1.2"));
|
||||
description.setPlatformVersion(Version.parse("2.2.3.RELEASE"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.project.ProjectDirectoryFactory;
|
||||
import io.spring.initializr.generator.spring.test.ProjectAssert;
|
||||
import io.spring.initializr.generator.spring.test.build.GradleBuildAssert;
|
||||
import io.spring.initializr.generator.spring.test.build.PomAssert;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.metadata.InitializrMetadataProvider;
|
||||
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link ProjectGenerationInvoker}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ProjectGenerationInvokerTests {
|
||||
|
||||
private static final InitializrMetadata metadata = InitializrMetadataTestBuilder
|
||||
.withDefaults().build();
|
||||
|
||||
private ProjectGenerationInvoker invoker;
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher = mock(
|
||||
ApplicationEventPublisher.class);
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
setupContext();
|
||||
ProjectRequestToDescriptionConverter converter = new ProjectRequestToDescriptionConverter();
|
||||
this.invoker = new ProjectGenerationInvoker(this.context, this.eventPublisher,
|
||||
converter);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void invokeProjectStructureGeneration() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.setType("maven-project");
|
||||
request.initialize(metadata);
|
||||
File file = this.invoker.invokeProjectStructureGeneration(request);
|
||||
new ProjectAssert(file).isJavaProject();
|
||||
Map<String, List<File>> tempFiles = (Map<String, List<File>>) ReflectionTestUtils
|
||||
.getField(this.invoker, "temporaryFiles");
|
||||
assertThat(tempFiles.get(file.getName())).contains(file);
|
||||
verifyProjectSuccessfulEventFor(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeProjectStructureGenerationFailureShouldPublishFailureEvent() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.initialize(metadata);
|
||||
request.setType("foo-bar");
|
||||
try {
|
||||
this.invoker.invokeProjectStructureGeneration(request);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
verifyProjectFailedEventFor(request, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeBuildGenerationForMavenBuild() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.setType("maven-project");
|
||||
request.initialize(metadata);
|
||||
byte[] bytes = this.invoker.invokeBuildGeneration(request);
|
||||
String content = new String(bytes);
|
||||
new PomAssert(content).hasGroupId(request.getGroupId())
|
||||
.hasArtifactId(request.getArtifactId()).hasVersion(request.getVersion())
|
||||
.doesNotHaveNode("/project/packaging").hasName(request.getName())
|
||||
.hasDescription(request.getDescription())
|
||||
.hasJavaVersion(request.getJavaVersion())
|
||||
.hasSpringBootParent(request.getBootVersion());
|
||||
verifyProjectSuccessfulEventFor(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeBuildGenerationForGradleBuild() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.initialize(metadata);
|
||||
request.setType("gradle-project");
|
||||
byte[] bytes = this.invoker.invokeBuildGeneration(request);
|
||||
String content = new String(bytes);
|
||||
new GradleBuildAssert(content).hasVersion(request.getVersion())
|
||||
.hasSpringBootPlugin(request.getBootVersion())
|
||||
.hasJavaVersion(request.getJavaVersion());
|
||||
verifyProjectSuccessfulEventFor(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeBuildGenerationFailureShouldPublishFailureEvent() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.initialize(metadata);
|
||||
request.setType("foo-bar");
|
||||
try {
|
||||
this.invoker.invokeBuildGeneration(request);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
verifyProjectFailedEventFor(request, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void createDistributionDirectory(@TempDir Path tempDir) {
|
||||
ProjectRequest request = new ProjectRequest();
|
||||
request.setType("gradle-project");
|
||||
File dir = tempDir.toFile();
|
||||
File distributionFile = this.invoker.createDistributionFile(dir, ".zip");
|
||||
assertThat(distributionFile.toString()).isEqualTo(dir.toString() + ".zip");
|
||||
Map<String, List<File>> tempFiles = (Map<String, List<File>>) ReflectionTestUtils
|
||||
.getField(this.invoker, "temporaryFiles");
|
||||
assertThat(tempFiles.get(dir.getName())).contains(distributionFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
void cleanupTempFilesShouldOnlyCleanupSpecifiedDir() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.initialize(metadata);
|
||||
request.setType("gradle-project");
|
||||
File file = this.invoker.invokeProjectStructureGeneration(request);
|
||||
this.invoker.cleanTempFiles(file);
|
||||
assertThat(file.listFiles()).isNull();
|
||||
}
|
||||
|
||||
private void setupContext() {
|
||||
InitializrMetadataProvider metadataProvider = mock(
|
||||
InitializrMetadataProvider.class);
|
||||
given(metadataProvider.get())
|
||||
.willReturn(InitializrMetadataTestBuilder.withDefaults().build());
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
}
|
||||
|
||||
protected void verifyProjectSuccessfulEventFor(ProjectRequest request) {
|
||||
verify(this.eventPublisher, times(1))
|
||||
.publishEvent(argThat(new ProjectGeneratedEventMatcher(request)));
|
||||
}
|
||||
|
||||
protected void verifyProjectFailedEventFor(ProjectRequest request, Exception ex) {
|
||||
verify(this.eventPublisher, times(1))
|
||||
.publishEvent(argThat(new ProjectFailedEventMatcher(request, ex)));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public IndentingWriterFactory factory() {
|
||||
return IndentingWriterFactory.create(new SimpleIndentStrategy("\t"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProjectDirectoryFactory projectDirectoryFactory() {
|
||||
return (description) -> Files.createTempDirectory("project-");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InitializrMetadataProvider initializrMetadataProvider() {
|
||||
return () -> metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ProjectFailedEventMatcher
|
||||
implements ArgumentMatcher<ProjectFailedEvent> {
|
||||
|
||||
private final ProjectRequest request;
|
||||
|
||||
private final Exception cause;
|
||||
|
||||
ProjectFailedEventMatcher(ProjectRequest request, Exception cause) {
|
||||
this.request = request;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ProjectFailedEvent event) {
|
||||
return this.request.equals(event.getProjectRequest())
|
||||
&& this.cause.equals(event.getCause());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ProjectGeneratedEventMatcher
|
||||
implements ArgumentMatcher<ProjectGeneratedEvent> {
|
||||
|
||||
private final ProjectRequest request;
|
||||
|
||||
ProjectGeneratedEventMatcher(ProjectRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ProjectGeneratedEvent event) {
|
||||
return this.request.equals(event.getProjectRequest());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -21,7 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import io.spring.initializr.test.generator.ProjectAssert;
|
||||
import io.spring.initializr.generator.spring.test.ProjectAssert;
|
||||
import io.spring.initializr.web.AbstractFullStackInitializrIntegrationTests;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
@@ -208,7 +208,7 @@ class ProjectGenerationSmokeTests extends AbstractFullStackInitializrIntegration
|
||||
projectAssert.hasBaseDir("demo").isMavenProject().isJavaWarProject().pomAssert()
|
||||
.hasPackaging("war").hasDependenciesCount(3)
|
||||
.hasSpringBootStarterDependency("web") // Added with war packaging
|
||||
.hasSpringBootStarterTomcat().hasSpringBootStarterTest();
|
||||
.hasSpringBootStarterDependency("tomcat").hasSpringBootStarterTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.web.project;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
import io.spring.initializr.generator.version.Version;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.web.InvalidProjectRequestException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link ProjectRequestToDescriptionConverter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ProjectRequestToDescriptionConverterTests {
|
||||
|
||||
private InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||
.build();
|
||||
|
||||
private final ProjectRequestToDescriptionConverter converter = new ProjectRequestToDescriptionConverter();
|
||||
|
||||
@Test
|
||||
public void convertWhenTypeIsInvalidShouldThrowException() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setType("foo-build");
|
||||
assertThatExceptionOfType(InvalidProjectRequestException.class)
|
||||
.isThrownBy(() -> this.converter.convert(request, this.metadata))
|
||||
.withMessage("Unknown type 'foo-build' check project metadata");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertWhenSpringBootVersionInvalidShouldThrowException() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setBootVersion("1.2.3.M4");
|
||||
assertThatExceptionOfType(InvalidProjectRequestException.class)
|
||||
.isThrownBy(() -> this.converter.convert(request, this.metadata))
|
||||
.withMessage(
|
||||
"Invalid Spring Boot version 1.2.3.M4 must be 1.5.0 or higher");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenPackagingIsInvalidShouldThrowException() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setPackaging("star");
|
||||
assertThatExceptionOfType(InvalidProjectRequestException.class)
|
||||
.isThrownBy(() -> this.converter.convert(request, this.metadata))
|
||||
.withMessage("Unknown packaging 'star' check project metadata");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenLanguageIsInvalidShouldThrowException() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setLanguage("english");
|
||||
assertThatExceptionOfType(InvalidProjectRequestException.class)
|
||||
.isThrownBy(() -> this.converter.convert(request, this.metadata))
|
||||
.withMessage("Unknown language 'english' check project metadata");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertWhenDependencyNotPresentShouldThrowException() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setDependencies(Collections.singletonList("invalid"));
|
||||
assertThatExceptionOfType(InvalidProjectRequestException.class)
|
||||
.isThrownBy(() -> this.converter.convert(request, this.metadata))
|
||||
.withMessage("Unknown dependency 'invalid' check project metadata");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetApplicationNameForProjectDescriptionFromRequestWhenPresent() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setApplicationName("MyApplication");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getApplicationName()).isEqualTo("MyApplication");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetApplicationNameForProjectDescriptionUsingNameWhenAbsentFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getApplicationName()).isEqualTo("DemoApplication");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetGroupIdAndArtifactIdFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setArtifactId("foo");
|
||||
request.setGroupId("com.example");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getGroupId()).isEqualTo("com.example");
|
||||
assertThat(description.getArtifactId()).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetBaseDirectoryFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setBaseDir("my-path");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getBaseDirectory()).isEqualTo("my-path");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetBuildSystemFromRequestType() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setType("gradle-build");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getBuildSystem().id()).isEqualTo("gradle");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetDescriptionFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setDescription("This is my demo project");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getDescription()).isEqualTo("This is my demo project");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetPackagingFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setPackaging("war");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getPackaging().id()).isEqualTo("war");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetPlatformVersionFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setBootVersion("2.0.3");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getPlatformVersion()).isEqualTo(Version.parse("2.0.3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldUseDefaultPlatformVersionFromMetadata() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getPlatformVersion())
|
||||
.isEqualTo(Version.parse("2.1.1.RELEASE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertShouldSetLanguageForProjectDescriptionFromRequest() {
|
||||
ProjectRequest request = getProjectRequest();
|
||||
request.setJavaVersion("1.8");
|
||||
ProjectDescription description = this.converter.convert(request, this.metadata);
|
||||
assertThat(description.getLanguage().id()).isEqualTo("java");
|
||||
assertThat(description.getLanguage().jvmVersion()).isEqualTo("1.8");
|
||||
}
|
||||
|
||||
private ProjectRequest getProjectRequest() {
|
||||
WebProjectRequest request = new WebProjectRequest();
|
||||
request.initialize(this.metadata);
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user