Avoid caching maven projects in the maven classpath.
Instead extract all the required information into classpath data and cache that instead.
This commit is contained in:
@@ -25,6 +25,7 @@ import org.gradle.tooling.model.build.BuildEnvironment;
|
||||
import org.gradle.tooling.model.eclipse.EclipseProject;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexClasspath;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.java.parser.ParserJavadocProvider;
|
||||
@@ -241,5 +242,10 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return ImmutableList.copyOf(project.getSourceDirectories().stream()
|
||||
.map(dir -> dir.getDirectory().toPath().toString()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
return ClasspathData.from(getName(), getClasspathEntries(), getClasspathResources(), getOutputFolder());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,12 +57,17 @@ public abstract class JandexClasspath implements IClasspath {
|
||||
Log.log(e);
|
||||
}
|
||||
return new JandexIndex(classpathEntries.map(p -> p.toFile()).collect(Collectors.toList()), jarFile -> findIndexFile(jarFile), classpathResource -> {
|
||||
switch (providerType) {
|
||||
case JAVA_PARSER:
|
||||
return createParserJavadocProvider(classpathResource);
|
||||
default:
|
||||
return createHtmlJavdocProvider(classpathResource);
|
||||
try {
|
||||
switch (providerType) {
|
||||
case JAVA_PARSER:
|
||||
return createParserJavadocProvider(classpathResource);
|
||||
default:
|
||||
return createHtmlJavdocProvider(classpathResource);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}, getBaseIndices());
|
||||
}
|
||||
|
||||
@@ -103,8 +108,8 @@ public abstract class JandexClasspath implements IClasspath {
|
||||
return javaIndex.get().findClasspathResourceForType(fqName);
|
||||
}
|
||||
|
||||
abstract protected IJavadocProvider createParserJavadocProvider(File classpathResource);
|
||||
abstract protected IJavadocProvider createParserJavadocProvider(File classpathResource) throws Exception;
|
||||
|
||||
abstract protected IJavadocProvider createHtmlJavdocProvider(File classpathResource);
|
||||
abstract protected IJavadocProvider createHtmlJavdocProvider(File classpathResource) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
@@ -55,45 +54,11 @@ import reactor.util.function.Tuple2;
|
||||
public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspath {
|
||||
|
||||
public static final String CLASSPATH_DATA_CACHE_FILE = "classpath-data.json";
|
||||
private static final ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(),
|
||||
Collections.emptySet(), null);
|
||||
|
||||
private static final String OUTPUT_FOLDER_PROPERTY = "outputFolder";
|
||||
private static final String CLASSPATH_RESOURCES_PROPERTY = "classpathResources";
|
||||
private static final String CLASSPATH_ENTRIES_PROPERTY = "classpathEntries";
|
||||
private static final String NAME_PROPERTY = "name";
|
||||
|
||||
protected static class ClasspathData {
|
||||
|
||||
final public String name;
|
||||
final public Set<Path> classpathEntries;
|
||||
final public Set<String> classpathResources;
|
||||
final public Path outputFolder;
|
||||
|
||||
public ClasspathData(String name, Set<Path> classpathEntries, Set<String> classpathResources, Path outputFolder) {
|
||||
this.name = name;
|
||||
this.classpathEntries = classpathEntries;
|
||||
this.classpathResources = classpathResources;
|
||||
this.outputFolder = outputFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ClasspathData) {
|
||||
ClasspathData other = (ClasspathData) obj;
|
||||
try {
|
||||
return Objects.equal(name, other.name)
|
||||
&& Objects.equal(classpathEntries, other.classpathEntries)
|
||||
&& Objects.equal(classpathResources, other.classpathResources)
|
||||
&& Objects.equal(outputFolder, outputFolder);
|
||||
} catch (Throwable t) {
|
||||
Log.log(t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AtomicReference<ClasspathData> cachedData;
|
||||
private Callable<T> delegateCreator;
|
||||
@@ -245,16 +210,17 @@ public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspa
|
||||
return t == null ? Flux.empty() : t.allSubtypesOf(type);
|
||||
}
|
||||
|
||||
protected ClasspathData createClasspathData() throws Exception {
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
T newDelegate = delegateCreator.call();
|
||||
cachedDelegate.set(newDelegate);
|
||||
if (newDelegate == null) {
|
||||
return EMPTY_CLASSPATH_DATA;
|
||||
} else {
|
||||
LinkedHashSet<Path> classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries());
|
||||
return new ClasspathData(newDelegate.getName(), classpathEntries,
|
||||
new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder());
|
||||
}
|
||||
if (newDelegate != null) {
|
||||
ClasspathData data = newDelegate.createClasspathData();
|
||||
if (data != null) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return EMPTY_CLASSPATH_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -60,5 +61,10 @@ public interface IClasspath {
|
||||
ImmutableList<String> getSourceFolders();
|
||||
|
||||
Optional<File> findClasspathResourceContainer(String fqName);
|
||||
|
||||
ClasspathData createClasspathData() throws Exception;
|
||||
|
||||
public static final ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(),
|
||||
Collections.emptySet(), null);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,19 @@ import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.artifact.repository.ArtifactRepository;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.util.DirectoryScanner;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexClasspath;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.java.parser.ParserJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
|
||||
@@ -48,13 +50,13 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
|
||||
private MavenCore maven;
|
||||
private File pom;
|
||||
private MavenProject project;
|
||||
private MavenClasspathData cachedData;
|
||||
|
||||
MavenProjectClasspath(MavenCore maven, File pom) throws MavenException {
|
||||
MavenProjectClasspath(MavenCore maven, File pom) throws Exception {
|
||||
super();
|
||||
this.maven = maven;
|
||||
this.pom = pom;
|
||||
this.project = createMavenProject();
|
||||
this.cachedData = createClasspathData();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,24 +87,28 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return project == null ? null : project.getArtifact().getArtifactId();
|
||||
return cachedData != null ? cachedData.name : null;
|
||||
}
|
||||
|
||||
private ImmutableList<Path> resolveClasspathEntries(MavenProject project) throws Exception {
|
||||
// return Stream.concat(maven.resolveDependencies(project, null).stream().map(artifact -> {
|
||||
// return artifact.getFile().toPath();
|
||||
// }), projectResolvedOutput());
|
||||
ImmutableList<Path> classpathEntries = ImmutableList.copyOf(Stream.concat(projectDependencies(project).stream().map(a -> a.getFile().toPath()),
|
||||
projectOutput(project).stream().map(f -> f.toPath())).collect(Collectors.toList()));
|
||||
return classpathEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<Path> getClasspathEntries() throws Exception {
|
||||
// return Stream.concat(maven.resolveDependencies(project, null).stream().map(artifact -> {
|
||||
// return artifact.getFile().toPath();
|
||||
// }), projectResolvedOutput());
|
||||
ImmutableList<Path> classpathEntries = ImmutableList.copyOf(Stream.concat(projectDependencies().stream().map(a -> a.getFile().toPath()),
|
||||
projectOutput().stream().map(f -> f.toPath())).collect(Collectors.toList()));
|
||||
return classpathEntries;
|
||||
return cachedData != null ? ImmutableList.copyOf(cachedData.classpathEntries) : ImmutableList.of();
|
||||
}
|
||||
|
||||
private Set<Artifact> projectDependencies() {
|
||||
private Set<Artifact> projectDependencies(MavenProject project) {
|
||||
return project == null ? Collections.emptySet() : project.getArtifacts();
|
||||
}
|
||||
|
||||
private List<File> projectOutput() {
|
||||
private List<File> projectOutput(MavenProject project) {
|
||||
if (project == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
@@ -110,16 +116,15 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
}
|
||||
}
|
||||
|
||||
public Path getOutputFolder() {
|
||||
private Path resolveOutputFolder(MavenProject project) {
|
||||
return project == null ? null : new File(project.getBuild().getOutputDirectory()).toPath();
|
||||
}
|
||||
|
||||
private Optional<Artifact> getArtifactFromJarFile(File file) throws MavenException {
|
||||
return project.getArtifacts().stream().filter(a -> file.equals(a.getFile())).findFirst();
|
||||
public Path getOutputFolder() {
|
||||
return cachedData != null ? cachedData.outputFolder : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
private ImmutableList<String> resolveClasspathResources(MavenProject project) {
|
||||
if (project == null) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
@@ -137,6 +142,11 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
return Arrays.stream(scanner.getIncludedFiles());
|
||||
}).toArray(String[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
return cachedData != null ? ImmutableList.copyOf(cachedData.classpathResources) : ImmutableList.of();
|
||||
}
|
||||
|
||||
/*
|
||||
* Roaster lib is experiment to generate javadoc from source. Commented out for now since roaster lib is taken out
|
||||
@@ -174,20 +184,21 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected IJavadocProvider createParserJavadocProvider(File classpathResource) {
|
||||
if (project == null) {
|
||||
if (cachedData == null) {
|
||||
return null;
|
||||
}
|
||||
if (classpathResource.isDirectory()) {
|
||||
if (classpathResource.toString().startsWith(project.getBuild().getOutputDirectory())) {
|
||||
if (classpathResource.toString().startsWith(cachedData.outputDirectory)) {
|
||||
return new ParserJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(project.getBuild().getSourceDirectory()).toURI().toURL(), type);
|
||||
.sourceUrl(new File(cachedData.sourceDirectory).toURI().toURL(), type);
|
||||
});
|
||||
} else if (classpathResource.toString().startsWith(project.getBuild().getTestOutputDirectory())) {
|
||||
} else if (classpathResource.toString().startsWith(cachedData.testOutputDirectory)) {
|
||||
return new ParserJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(project.getBuild().getTestSourceDirectory()).toURI().toURL(), type);
|
||||
.sourceUrl(new File(cachedData.testSourceDirectory).toURI().toURL(), type);
|
||||
});
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot find source folder for " + classpathResource);
|
||||
@@ -196,8 +207,8 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
// Assume it's a JAR file
|
||||
return new ParserJavadocProvider(type -> {
|
||||
try {
|
||||
Artifact artifact = getArtifactFromJarFile(classpathResource).get();
|
||||
URL sourceContainer = maven.getSources(artifact, project.getRemoteArtifactRepositories()).getFile().toURI().toURL();
|
||||
Artifact artifact = cachedData.artifacts.stream().filter(a -> classpathResource.equals(a.getFile())).findFirst().get();
|
||||
URL sourceContainer = maven.getSources(artifact, cachedData.remoteArtifactRepositories).getFile().toURI().toURL();
|
||||
return SourceUrlProviderFromSourceContainer.JAR_SOURCE_URL_PROVIDER.sourceUrl(sourceContainer,
|
||||
type);
|
||||
} catch (MavenException e) {
|
||||
@@ -210,20 +221,21 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJavadocProvider createHtmlJavdocProvider(File classpathResource) {
|
||||
if (project == null) {
|
||||
if (cachedData == null) {
|
||||
return null;
|
||||
}
|
||||
if (classpathResource.isDirectory()) {
|
||||
if (classpathResource.toString().startsWith(project.getBuild().getOutputDirectory())) {
|
||||
if (classpathResource.toString().startsWith(cachedData.outputDirectory)) {
|
||||
return new HtmlJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(project.getModel().getReporting().getOutputDirectory(), "apidocs").toURI().toURL(), type);
|
||||
.sourceUrl(new File(cachedData.reportingOutputDirectory, "apidocs").toURI().toURL(), type);
|
||||
});
|
||||
} else if (classpathResource.toString().startsWith(project.getBuild().getTestOutputDirectory())) {
|
||||
} else if (classpathResource.toString().startsWith(cachedData.testOutputDirectory)) {
|
||||
return new ParserJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(project.getModel().getReporting().getOutputDirectory(), "apidocs").toURI().toURL(), type);
|
||||
.sourceUrl(new File(cachedData.reportingOutputDirectory, "apidocs").toURI().toURL(), type);
|
||||
});
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot find source folder for " + classpathResource);
|
||||
@@ -232,8 +244,8 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
// Assume it's a JAR file
|
||||
return new HtmlJavadocProvider(type -> {
|
||||
try {
|
||||
Artifact artifact = getArtifactFromJarFile(classpathResource).get();
|
||||
URL sourceContainer = maven.getJavadoc(artifact, project.getRemoteArtifactRepositories()).getFile().toURI().toURL();
|
||||
Artifact artifact = cachedData.artifacts.stream().filter(a -> classpathResource.equals(a.getFile())).findFirst().get();
|
||||
URL sourceContainer = maven.getJavadoc(artifact, cachedData.remoteArtifactRepositories).getFile().toURI().toURL();
|
||||
return SourceUrlProviderFromSourceContainer.JAR_JAVADOC_URL_PROVIDER.sourceUrl(sourceContainer,
|
||||
type);
|
||||
} catch (MavenException e) {
|
||||
@@ -252,7 +264,7 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
MavenProjectClasspath other = (MavenProjectClasspath) obj;
|
||||
try {
|
||||
if (pom.equals(other.pom)
|
||||
&& Objects.equal(project, other.project)) {
|
||||
&& Objects.equal(cachedData, other.cachedData)) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
@@ -264,7 +276,46 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getSourceFolders() {
|
||||
return ImmutableList.of(project.getBuild().getSourceDirectory());
|
||||
return cachedData != null ? ImmutableList.of(cachedData.sourceDirectory) : ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MavenClasspathData createClasspathData() throws Exception {
|
||||
MavenProject project = createMavenProject();
|
||||
|
||||
ImmutableList<Path> entries = resolveClasspathEntries(project);
|
||||
String name = project.getArtifact().getArtifactId();
|
||||
ImmutableList<String> resources = resolveClasspathResources(project);
|
||||
Path outputFolder = resolveOutputFolder(project);
|
||||
|
||||
MavenClasspathData data = new MavenClasspathData(name, new LinkedHashSet<>(entries),
|
||||
new LinkedHashSet<>(resources), outputFolder);
|
||||
|
||||
data.outputDirectory = project.getBuild().getOutputDirectory();
|
||||
data.reportingOutputDirectory = project.getModel().getReporting().getOutputDirectory();
|
||||
data.testOutputDirectory = project.getBuild().getTestOutputDirectory();
|
||||
data.testSourceDirectory = project.getBuild().getTestSourceDirectory();
|
||||
data.artifacts = project.getArtifacts();
|
||||
data.remoteArtifactRepositories = project.getRemoteArtifactRepositories();
|
||||
data.sourceDirectory = project.getBuild().getSourceDirectory();
|
||||
return data;
|
||||
}
|
||||
|
||||
class MavenClasspathData extends ClasspathData {
|
||||
|
||||
private String testSourceDirectory;
|
||||
private List<ArtifactRepository> remoteArtifactRepositories;
|
||||
private Set<Artifact> artifacts;
|
||||
private String testOutputDirectory;
|
||||
private String reportingOutputDirectory;
|
||||
private String outputDirectory;
|
||||
private String sourceDirectory;
|
||||
|
||||
|
||||
public MavenClasspathData(String name, Set<Path> classpathEntries, Set<String> classpathResources,
|
||||
Path outputFolder) {
|
||||
super(name, classpathEntries, classpathResources, outputFolder);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IType;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
@@ -99,4 +100,8 @@ public class FileClasspath implements IClasspath {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
return ClasspathData.from(getName(), getClasspathEntries(), getClasspathResources(), getOutputFolder());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user