PT 173730396 - Further changes for project version validation
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018, 2020 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2021 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -15,8 +15,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
@@ -45,10 +43,11 @@ import org.springframework.ide.vscode.boot.metadata.ClassReferenceProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.LoggerNameProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndex;
|
||||
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
|
||||
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
|
||||
import org.springframework.ide.vscode.boot.properties.completions.SpringPropertiesCompletionEngine;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SampleProjectsProvider;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SpringIoProjectsProvider;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsValidations;
|
||||
import org.springframework.ide.vscode.boot.xml.SpringXMLCompletionEngine;
|
||||
import org.springframework.ide.vscode.boot.yaml.completions.ApplicationYamlAssistContext;
|
||||
import org.springframework.ide.vscode.boot.yaml.completions.SpringYamlCompletionEngine;
|
||||
@@ -72,6 +71,8 @@ import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoC
|
||||
import org.springframework.ide.vscode.languageserver.starter.LanguageServerRunnerAutoConf;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.publisher.Hooks;
|
||||
|
||||
@SpringBootConfiguration(proxyBeanMethods = false)
|
||||
@@ -215,5 +216,11 @@ public class BootLanguagServerBootApp {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Bean SpringProjectsValidations springProjectsValidations(SimpleLanguageServer server) {
|
||||
return new SpringProjectsValidations(server, ImmutableList.of(
|
||||
new SpringIoProjectsProvider(),
|
||||
new SampleProjectsProvider()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2021 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.app;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.lsp4j.MessageType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -26,7 +27,11 @@ import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SymbolCache;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.ProjectValidation;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsValidations;
|
||||
import org.springframework.ide.vscode.boot.xml.SpringXMLLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.DiagnosticService;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.CompositeCompletionEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
|
||||
@@ -34,6 +39,7 @@ import org.springframework.ide.vscode.commons.languageserver.composable.Composit
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -59,6 +65,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
@Autowired BootJavaConfig config;
|
||||
@Autowired SpringSymbolIndex springIndexer;
|
||||
@Autowired(required = false) List<ICompletionEngine> completionEngines;
|
||||
@Autowired SpringProjectsValidations springProjectsValidations;
|
||||
|
||||
@Qualifier("adHocProperties") @Autowired ProjectBasedPropertyIndexProvider adHocProperties;
|
||||
|
||||
@@ -120,6 +127,8 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
addSpringProjectsVersionValidation(params);
|
||||
}
|
||||
|
||||
public CompositeLanguageServerComponents getComponents() {
|
||||
@@ -132,5 +141,50 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
completionEngineAdapter.setMaxCompletions(number);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSpringProjectsVersionValidation(BootLanguageServerParams params2) {
|
||||
params.projectObserver.addListener(
|
||||
new ProjectObserver.Listener() {
|
||||
|
||||
@Override
|
||||
public void deleted(IJavaProject project) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void created(IJavaProject project) {
|
||||
|
||||
// TODO: PT 173730396 - As of 4.9.1, Spring Project Version validation is not yet
|
||||
// available from https://spring.io/api/projects
|
||||
// Commented out to disable this feature. Uncomment to test if necessary
|
||||
// validateProjectVersion(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(IJavaProject project) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
private void validateProjectVersion(IJavaProject project) {
|
||||
try {
|
||||
ProjectValidation validation = springProjectsValidations.validateVersion(project);
|
||||
if (validation != null && validation.getMessageType() == MessageType.Warning) {
|
||||
|
||||
// TODO: replace this with a diagnostic message that has project-scope.
|
||||
// At the moment of implementing this, it doesnt look like sending a diagnostic
|
||||
// message to LSP4E without a resource context is possible.
|
||||
DiagnosticService diagnosticService = server.getDiagnosticService();
|
||||
if (diagnosticService != null) {
|
||||
diagnosticService.diagnosticEvent(
|
||||
ShowMessageException.warning(validation.getMessage(), null));
|
||||
}
|
||||
log.warn(validation.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed validating Spring Project version", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2021 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.validation.generations;
|
||||
|
||||
import org.eclipse.lsp4j.MessageType;
|
||||
|
||||
public class ProjectValidation {
|
||||
|
||||
public static ProjectValidation OK = new ProjectValidation("", MessageType.Info);
|
||||
|
||||
private final MessageType messageType;
|
||||
private final String message;
|
||||
|
||||
public ProjectValidation(String message, MessageType messageType) {
|
||||
this.messageType = messageType;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public MessageType getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,14 @@ import com.google.common.collect.ImmutableMap.Builder;
|
||||
/**
|
||||
* Provides Spring project definitions from a source like "https://spring.io/api/projects"
|
||||
* <p/>
|
||||
* If a client is not provider that can fetch information from a source, a default client
|
||||
* If a client is not provided, a default client
|
||||
* will be used instead that will point to "https://spring.io/api/projects"
|
||||
*
|
||||
*/
|
||||
public class SpringIoProjectsProvider implements SpringProjectsProvider {
|
||||
|
||||
private final SpringProjectsClient client;
|
||||
private Map<String, SpringProject> cache;
|
||||
private Map<String, SpringIoProject> cache;
|
||||
|
||||
public SpringIoProjectsProvider(SpringProjectsClient client) {
|
||||
this.client = client;
|
||||
@@ -50,25 +50,20 @@ public class SpringIoProjectsProvider implements SpringProjectsProvider {
|
||||
*/
|
||||
@Override
|
||||
public SpringProject getProject(String projectSlug) throws Exception {
|
||||
return cache().get(projectSlug);
|
||||
SpringIoProject prj = cache().get(projectSlug);
|
||||
return prj != null ? prj.getProject() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Generations getGenerations(String projectSlug) throws Exception {
|
||||
SpringProject project = getProject(projectSlug);
|
||||
SpringIoProject project = cache().get(projectSlug);
|
||||
if (project != null) {
|
||||
Links _links = project.get_links();
|
||||
if (_links != null) {
|
||||
Link genLink = _links.getGenerations();
|
||||
if (genLink != null) {
|
||||
return client.getGenerations(genLink.getHref());
|
||||
}
|
||||
}
|
||||
return project.getGenerations();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, SpringProject> cache() throws Exception {
|
||||
private Map<String, SpringIoProject> cache() throws Exception {
|
||||
if (cache == null) {
|
||||
SpringProjects springProjects = client.getSpringProjects();
|
||||
cache = asMap(springProjects);
|
||||
@@ -76,14 +71,14 @@ public class SpringIoProjectsProvider implements SpringProjectsProvider {
|
||||
return cache != null ? cache : ImmutableMap.of();
|
||||
}
|
||||
|
||||
private Map<String, SpringProject> asMap(SpringProjects springProjects) {
|
||||
Builder<String, SpringProject> builder = ImmutableMap.builder();
|
||||
private Map<String, SpringIoProject> asMap(SpringProjects springProjects) {
|
||||
Builder<String, SpringIoProject> builder = ImmutableMap.builder();
|
||||
|
||||
if (springProjects != null) {
|
||||
List<SpringProject> projects = springProjects.getProjects();
|
||||
if (projects != null) {
|
||||
for (SpringProject project : projects) {
|
||||
builder.put(project.getSlug(), project);
|
||||
builder.put(project.getSlug(), new SpringIoProject(project, this.client));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,4 +89,39 @@ public class SpringIoProjectsProvider implements SpringProjectsProvider {
|
||||
String url = "https://spring.io/api/projects";
|
||||
return new SpringProjectsClient(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around the JSON SpringProject that also contains its generations
|
||||
*
|
||||
*/
|
||||
private final static class SpringIoProject {
|
||||
|
||||
private final SpringProject project;
|
||||
private final SpringProjectsClient client;
|
||||
private Generations generations;
|
||||
|
||||
|
||||
public SpringIoProject(SpringProject project, SpringProjectsClient client) {
|
||||
this.project = project;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public SpringProject getProject() {
|
||||
return this.project;
|
||||
}
|
||||
|
||||
public Generations getGenerations() throws Exception {
|
||||
// cache the generations to prevent frequent calls to the client
|
||||
if (this.generations == null) {
|
||||
Links _links = project.get_links();
|
||||
if (_links != null) {
|
||||
Link genLink = _links.getGenerations();
|
||||
if (genLink != null) {
|
||||
this.generations = client.getGenerations(genLink.getHref());
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.generations;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,26 +12,17 @@ package org.springframework.ide.vscode.boot.validation.generations;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Date;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.lsp4j.MessageType;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.json.Generation;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.json.Generations;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.AsyncRunner;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class SpringProjectsValidations {
|
||||
|
||||
private static final long TIMEOUT_SECS = 30;
|
||||
|
||||
private final List<SpringProjectsProvider> projectsProviders;
|
||||
private final SimpleLanguageServer server;
|
||||
|
||||
@@ -39,22 +30,9 @@ public class SpringProjectsValidations {
|
||||
this.projectsProviders = projectsProviders;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public CompletableFuture<List<String>> getValidationMessagesAsync(IJavaProject jp) {
|
||||
AsyncRunner async = this.server.getAsync();
|
||||
if (async != null) {
|
||||
return async.invoke(Duration.ofSeconds(TIMEOUT_SECS), () -> {
|
||||
return getWarningMessages(jp);
|
||||
});
|
||||
} else {
|
||||
return Mono.fromCallable(() -> getWarningMessages(jp)).timeout(Duration.ofSeconds(TIMEOUT_SECS))
|
||||
.toFuture();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getWarningMessages(IJavaProject jp) throws Exception {
|
||||
ImmutableList.Builder<String> messages = ImmutableList.builder();
|
||||
|
||||
|
||||
public ProjectValidation validateVersion(IJavaProject jp) throws Exception {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (jp != null) {
|
||||
List<File> librariesOnClasspath = SpringProjectUtil.getLibrariesOnClasspath(jp, "spring");
|
||||
if (librariesOnClasspath != null) {
|
||||
@@ -66,7 +44,7 @@ public class SpringProjectsValidations {
|
||||
List<Generation> gens = generations.getGenerations();
|
||||
if (gens != null) {
|
||||
for (Generation gen : gens) {
|
||||
resolveWarnings(gen, messages, versionInfo);
|
||||
resolveWarnings(gen, builder, versionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,32 +52,31 @@ public class SpringProjectsValidations {
|
||||
}
|
||||
}
|
||||
}
|
||||
return messages.build();
|
||||
|
||||
return builder.length() > 0 ?
|
||||
new ProjectValidation(builder.toString(), MessageType.Warning)
|
||||
: ProjectValidation.OK;
|
||||
}
|
||||
|
||||
private void resolveWarnings(Generation gen, Builder<String> messages, SpringVersionInfo versionInfo) {
|
||||
private void resolveWarnings(Generation gen, StringBuilder messages, SpringVersionInfo versionInfo) {
|
||||
if (isInGeneration(versionInfo.getMajMin(), gen)) {
|
||||
Date currentDate = new Date(System.currentTimeMillis());
|
||||
Date ossEndDate = Date.valueOf(gen.getOssSupportEndDate());
|
||||
Date commercialEndDate = Date.valueOf(gen.getCommercialSupportEndDate());
|
||||
|
||||
StringBuilder msg = new StringBuilder();
|
||||
|
||||
msg.append("Using ");
|
||||
msg.append(versionInfo.getSlug());
|
||||
msg.append(" version: ");
|
||||
msg.append(versionInfo.getFullVersion());
|
||||
|
||||
messages.append("Using ");
|
||||
messages.append(versionInfo.getSlug());
|
||||
messages.append(" version: ");
|
||||
messages.append(versionInfo.getFullVersion());
|
||||
|
||||
if (currentDate.after(ossEndDate)) {
|
||||
msg.append(" - OSS has ended on: ");
|
||||
msg.append(gen.getOssSupportEndDate());
|
||||
messages.append(" - OSS has ended on: ");
|
||||
messages.append(gen.getOssSupportEndDate());
|
||||
}
|
||||
if (currentDate.after(commercialEndDate)) {
|
||||
msg.append(" - Commercial support has ended on: ");
|
||||
msg.append(gen.getCommercialSupportEndDate());
|
||||
messages.append(" - Commercial support has ended on: ");
|
||||
messages.append(gen.getCommercialSupportEndDate());
|
||||
}
|
||||
|
||||
messages.add(msg.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.io.File;
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.MessageType;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -26,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
|
||||
import org.springframework.ide.vscode.boot.bootiful.HoverTestConf;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.ProjectValidation;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SampleProjectsProvider;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SpringIoProjectsProvider;
|
||||
import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsClient;
|
||||
@@ -198,11 +200,11 @@ public class ProjectGenerationsValidationTest {
|
||||
ImmutableList.of( new SampleProjectsProvider())
|
||||
);
|
||||
|
||||
List<String> messages = validation.getWarningMessages(jp);
|
||||
assertTrue(messages != null && messages.size() > 0);
|
||||
String msg = messages.get(0);
|
||||
ProjectValidation versionValidation = validation.validateVersion(jp);
|
||||
assertNotNull(versionValidation != null);
|
||||
assertEquals(versionValidation.getMessageType(), MessageType.Warning);
|
||||
// Check that the message mentions the boot version of the project and the OSS support end date
|
||||
assertEquals("Using spring-boot version: 1.3.2 - OSS has ended on: 2020-01-01 - Commercial support has ended on: 2021-01-01", msg);
|
||||
assertEquals("Using spring-boot version: 1.3.2 - OSS has ended on: 2020-01-01 - Commercial support has ended on: 2021-01-01", versionValidation.getMessage());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user