try to auto-connect to processes only if the corresponding project is known and has actuators in the classpath

This commit is contained in:
Martin Lippert
2020-05-04 16:04:34 +02:00
parent 40e4885bda
commit 67c4e44e63
4 changed files with 31 additions and 39 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2018 Pivotal, Inc.
* Copyright (c) 2017, 2020 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
@@ -20,18 +20,22 @@ public class SpringProjectUtil {
public static final Logger log = LoggerFactory.getLogger(SpringProjectUtil.class);
public static boolean isSpringProject(IJavaProject jp) {
return hasSpecificLibraryOnClasspath(jp, "spring-core");
return hasSpecificLibraryOnClasspath(jp, "spring-core", true);
}
public static boolean isBootProject(IJavaProject jp) {
return hasSpecificLibraryOnClasspath(jp, "spring-boot");
return hasSpecificLibraryOnClasspath(jp, "spring-boot", true);
}
private static boolean hasSpecificLibraryOnClasspath(IJavaProject jp, String libraryNamePrefix) {
public static boolean hasBootActuators(IJavaProject jp) {
return hasSpecificLibraryOnClasspath(jp, "spring-boot-actuator-", true);
}
private static boolean hasSpecificLibraryOnClasspath(IJavaProject jp, String libraryNamePrefix, boolean onlyLibs) {
try {
IClasspath cp = jp.getClasspath();
if (cp!=null) {
return IClasspathUtil.getBinaryRoots(cp, (cpe) -> !cpe.isSystem()).stream().anyMatch(cpe -> isEntry(cpe, libraryNamePrefix));
return IClasspathUtil.getBinaryRoots(cp, (cpe) -> !cpe.isSystem()).stream().anyMatch(cpe -> isEntry(cpe, libraryNamePrefix, onlyLibs));
}
} catch (Exception e) {
log.error("Failed to determine whether '" + jp.getElementName() + "' is Spring Boot project", e);
@@ -39,8 +43,8 @@ public class SpringProjectUtil {
return false;
}
private static boolean isEntry(File cpe, String libNamePrefix) {
private static boolean isEntry(File cpe, String libNamePrefix, boolean onlyLibs) {
String name = cpe.getName();
return name.endsWith(".jar") && name.startsWith(libNamePrefix);
return name.startsWith(libNamePrefix) && (!onlyLibs || name.endsWith(".jar"));
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2019 Pivotal, Inc.
* Copyright (c) 2017, 2020 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
@@ -39,9 +39,8 @@ import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyA
import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveData;
import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveDataProvider;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
@@ -292,7 +291,7 @@ public class BootJavaHoverProvider implements HoverHandler {
}
//Only reaching here if we didn't get a hover.
if (!hasActuatorDependency(project)) {
if (!SpringProjectUtil.hasBootActuators(project)) {
DocumentRegion region = ASTUtils.nameRegion(doc, annotation);
if (region.containsOffset(offset)) {
return liveHoverWarning(project);
@@ -328,21 +327,6 @@ public class BootJavaHoverProvider implements HoverHandler {
return new Hover(ImmutableList.of(Either.forLeft(hoverText)));
}
private boolean hasActuatorDependency(IJavaProject project) {
try {
IClasspath classpath = project.getClasspath();
if (classpath != null) {
return IClasspathUtil.getBinaryRoots(classpath, (cpe) -> !cpe.isSystem()).stream().anyMatch(cpe -> {
String name = cpe.getName();
return name.startsWith("spring-boot-actuator-");
});
}
} catch (Exception e) {
logger.error("error identifying actuator dependency on project '" + project.getElementName() + "'", e);
}
return false;
}
private Optional<IJavaProject> getProject(IDocument doc) {
return this.projectFinder.find(new TextDocumentIdentifier(doc.getUri()));
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal, Inc.
* Copyright (c) 2019, 2020 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
@@ -12,18 +12,20 @@ package org.springframework.ide.vscode.boot.java.livehover.v2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import com.sun.tools.attach.VirtualMachine;
@@ -41,7 +43,7 @@ public class SpringProcessConnectorLocal {
private static final String LOCAL_CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress";
private final Collection<String> projects;
private final Map<String, Boolean> projects;
private final Set<SpringProcessDescriptor> processes;
private final SpringProcessConnectorService processConnectorService;
@@ -49,7 +51,7 @@ public class SpringProcessConnectorLocal {
private boolean projectsChanged;
public SpringProcessConnectorLocal(SpringProcessConnectorService processConnector, ProjectObserver projectObserver) {
this.projects = Collections.synchronizedCollection(new HashSet<>());
this.projects = new ConcurrentHashMap<>();
this.processes = Collections.synchronizedSet(new HashSet<>());
this.projectsChanged = false;
@@ -58,7 +60,8 @@ public class SpringProcessConnectorLocal {
projectObserver.addListener(new ProjectObserver.Listener() {
@Override
public void created(IJavaProject project) {
projects.add(project.getElementName());
boolean hasActuators = SpringProjectUtil.hasBootActuators(project);
projects.put(project.getElementName(), hasActuators);
projectsChanged = true;
}
@Override
@@ -157,7 +160,7 @@ public class SpringProcessConnectorLocal {
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (SpringProcessDescriptor process : processes) {
futures.add(process.updateStatus(projects::contains));
futures.add(process.updateStatus(projects::containsKey, projects::get));
}
CompletableFuture<Void> allStatusUpdates = CompletableFuture.allOf((CompletableFuture[]) futures.toArray(new CompletableFuture[futures.size()]));

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal, Inc.
* Copyright (c) 2019, 2020 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
@@ -109,21 +109,21 @@ public class SpringProcessDescriptor {
return true;
}
public CompletableFuture<Void> updateStatus(Predicate<String> projectIsKnown) {
public CompletableFuture<Void> updateStatus(Predicate<String> projectIsKnown, Predicate<String> projectHasActuators) {
return CompletableFuture.supplyAsync(() -> {
this.status = checkStatus(projectIsKnown);
this.status = checkStatus(projectIsKnown, projectHasActuators);
return null;
});
}
private SpringProcessStatus checkStatus(Predicate<String> projectIsKnown) {
private SpringProcessStatus checkStatus(Predicate<String> projectIsKnown, Predicate<String> projectHasActuators) {
VirtualMachine vm = null;
try {
vm = VirtualMachine.attach(this.getVm());
if (shouldIgnore(this.getVm(), vm)) {
return SpringProcessStatus.IGNORE;
}
if (shouldAutoConnect(this.getVm(), vm, projectIsKnown)) {
if (shouldAutoConnect(this.getVm(), vm, projectIsKnown, projectHasActuators)) {
return SpringProcessStatus.AUTO_CONNECT;
}
@@ -168,7 +168,7 @@ public class SpringProcessDescriptor {
return false;
}
private boolean shouldAutoConnect(VirtualMachineDescriptor vmDescriptor, VirtualMachine vm, Predicate<String> projectIsKnown) {
private boolean shouldAutoConnect(VirtualMachineDescriptor vmDescriptor, VirtualMachine vm, Predicate<String> projectIsKnown, Predicate<String> projectHasActuators) {
try {
Properties systemProperties = vm.getSystemProperties();
@@ -176,7 +176,8 @@ public class SpringProcessDescriptor {
if (projectName instanceof String) {
log.info("Spring boot process found: " + projectName);
this.projectName = (String) projectName;
return projectIsKnown.test((String) projectName);
return projectIsKnown.test((String) projectName) && projectHasActuators.test((String)projectName);
}
}
catch (Exception e) {