Merge pull request #35 from spring-projects/reduce-memory-footprint-maven-projects

Reduce memory footprint maven projects
This commit is contained in:
nierajsingh
2018-01-24 16:26:09 -08:00
committed by GitHub
6 changed files with 219 additions and 77 deletions

View File

@@ -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());
}
}

View File

@@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2018 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.java;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.base.Objects;
public class ClasspathData {
final public static ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(),
Collections.emptySet(), null);
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;
}
public static ClasspathData from(String name, Collection<Path> classpathEntries,
Collection<String> classpathResources, Path outputFolder) {
return new ClasspathData(name, new LinkedHashSet<>(classpathEntries), new LinkedHashSet<>(classpathResources),
outputFolder);
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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,94 @@ 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);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
MavenClasspathData other = (MavenClasspathData) obj;
if (artifacts == null) {
if (other.artifacts != null)
return false;
} else if (!artifacts.equals(other.artifacts))
return false;
if (outputDirectory == null) {
if (other.outputDirectory != null)
return false;
} else if (!outputDirectory.equals(other.outputDirectory))
return false;
if (remoteArtifactRepositories == null) {
if (other.remoteArtifactRepositories != null)
return false;
} else if (!remoteArtifactRepositories.equals(other.remoteArtifactRepositories))
return false;
if (reportingOutputDirectory == null) {
if (other.reportingOutputDirectory != null)
return false;
} else if (!reportingOutputDirectory.equals(other.reportingOutputDirectory))
return false;
if (sourceDirectory == null) {
if (other.sourceDirectory != null)
return false;
} else if (!sourceDirectory.equals(other.sourceDirectory))
return false;
if (testOutputDirectory == null) {
if (other.testOutputDirectory != null)
return false;
} else if (!testOutputDirectory.equals(other.testOutputDirectory))
return false;
if (testSourceDirectory == null) {
if (other.testSourceDirectory != null)
return false;
} else if (!testSourceDirectory.equals(other.testSourceDirectory))
return false;
return true;
}
}
}

View File

@@ -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());
}
}