forked from finos/legend-engine-ide-lsp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reduce shaded jar size by managing runtime dependencies using maven (f…
…inos#123) * Reduce shaded jar size by managing runtime dependencies using maven * Incorporate review feedback: restrict catch block and explicitly set charset
- Loading branch information
Showing
17 changed files
with
949 additions
and
276 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
...-lsp-server/src/main/java/org/finos/legend/engine/ide/lsp/classpath/ClasspathFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2024 Goldman Sachs | ||
// | ||
// 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 org.finos.legend.engine.ide.lsp.classpath; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import org.finos.legend.engine.ide.lsp.server.LegendLanguageServer; | ||
|
||
public interface ClasspathFactory | ||
{ | ||
CompletableFuture<ClassLoader> create(LegendLanguageServer server, Iterable<String> folders); | ||
} |
187 changes: 187 additions & 0 deletions
187
...r/src/main/java/org/finos/legend/engine/ide/lsp/classpath/ClasspathUsingMavenFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// Copyright 2024 Goldman Sachs | ||
// | ||
// 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 org.finos.legend.engine.ide.lsp.classpath; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.File; | ||
import java.io.PrintStream; | ||
import java.net.URL; | ||
import java.net.URLClassLoader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.Optional; | ||
import java.util.Properties; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.TimeUnit; | ||
import org.apache.maven.shared.invoker.DefaultInvocationRequest; | ||
import org.apache.maven.shared.invoker.DefaultInvoker; | ||
import org.apache.maven.shared.invoker.InvocationRequest; | ||
import org.apache.maven.shared.invoker.InvocationResult; | ||
import org.apache.maven.shared.invoker.Invoker; | ||
import org.apache.maven.shared.invoker.InvokerLogger; | ||
import org.apache.maven.shared.invoker.PrintStreamHandler; | ||
import org.apache.maven.shared.invoker.PrintStreamLogger; | ||
import org.apache.maven.shared.utils.Os; | ||
import org.apache.maven.shared.utils.cli.CommandLineUtils; | ||
import org.apache.maven.shared.utils.cli.Commandline; | ||
import org.eclipse.lsp4j.ConfigurationItem; | ||
import org.eclipse.lsp4j.ConfigurationParams; | ||
import org.finos.legend.engine.ide.lsp.server.LegendLanguageServer; | ||
|
||
public class ClasspathUsingMavenFactory implements ClasspathFactory | ||
{ | ||
private final Invoker invoker; | ||
private final File defaultPom; | ||
private final ByteArrayOutputStream outputStream; | ||
|
||
public ClasspathUsingMavenFactory(File defaultPom) | ||
{ | ||
this.defaultPom = defaultPom; | ||
this.invoker = new DefaultInvoker(); | ||
this.outputStream = new ByteArrayOutputStream(); | ||
this.invoker.setLogger(new PrintStreamLogger(new PrintStream(this.outputStream, true), InvokerLogger.INFO)); | ||
} | ||
|
||
private static File getMavenExecLocation(String mavenHome) throws Exception | ||
{ | ||
if (mavenHome == null || mavenHome.isEmpty()) | ||
{ | ||
Commandline commandline = new Commandline(); | ||
|
||
if (Os.isFamily(Os.FAMILY_WINDOWS)) | ||
{ | ||
commandline.setExecutable("where"); | ||
commandline.addArguments("mvn"); | ||
} | ||
else if (Os.isFamily(Os.FAMILY_UNIX)) | ||
{ | ||
commandline.setExecutable("which"); | ||
commandline.addArguments("mvn"); | ||
} | ||
else | ||
{ | ||
throw new UnsupportedOperationException("OS not supported"); | ||
} | ||
|
||
CommandLineUtils.StringStreamConsumer systemOut = new CommandLineUtils.StringStreamConsumer(); | ||
CommandLineUtils.StringStreamConsumer systemErr = new CommandLineUtils.StringStreamConsumer(); | ||
int result = CommandLineUtils.executeCommandLine(commandline, systemOut, systemErr, 2); | ||
|
||
if (result == 0) | ||
{ | ||
String[] split = systemOut.getOutput().split(System.lineSeparator()); | ||
if (split.length == 0) | ||
{ | ||
return null; | ||
} | ||
String location = split[0]; | ||
return new File(location); | ||
} | ||
else | ||
{ | ||
throw new RuntimeException("Error finding mvn executable: " + systemErr.getOutput()); | ||
} | ||
} | ||
else | ||
{ | ||
return new File(mavenHome); | ||
} | ||
} | ||
|
||
@Override | ||
public CompletableFuture<ClassLoader> create(LegendLanguageServer server, Iterable<String> folders) | ||
{ | ||
server.logInfoToClient("Discovering classpath using maven"); | ||
|
||
ConfigurationItem mavenExecPathConfig = new ConfigurationItem(); | ||
mavenExecPathConfig.setSection("maven.executable.path"); | ||
|
||
ConfigurationItem defaultPomConfig = new ConfigurationItem(); | ||
defaultPomConfig.setSection("legend.extensions.dependencies.pom"); | ||
|
||
ConfigurationParams configurationParams = new ConfigurationParams(Arrays.asList(mavenExecPathConfig, defaultPomConfig)); | ||
return server.getLanguageClient().configuration(configurationParams).thenApply(x -> | ||
{ | ||
String mavenExecPath = server.extractValueAs(x.get(0), String.class); | ||
String overrideDefaultPom = server.extractValueAs(x.get(1), String.class); | ||
|
||
try | ||
{ | ||
File maven = getMavenExecLocation(mavenExecPath); | ||
server.logInfoToClient("Maven path: " + maven); | ||
|
||
File pom = (overrideDefaultPom == null || overrideDefaultPom.isEmpty()) ? this.defaultPom : new File(overrideDefaultPom); | ||
|
||
// todo apply properties from /project.json is this exists... | ||
// todo if project.json exists, use pom from a sub-module | ||
// todo otherwise, check if pom exists on root | ||
// todo last, use a default pom... | ||
|
||
server.logInfoToClient("Dependencies loaded from POM: " + pom); | ||
|
||
File legendLspClasspath = File.createTempFile("legend_lsp_classpath", ".txt"); | ||
legendLspClasspath.deleteOnExit(); | ||
|
||
Properties properties = new Properties(); | ||
properties.setProperty("mdep.outputFile", legendLspClasspath.getAbsolutePath()); | ||
|
||
InvocationRequest request = new DefaultInvocationRequest(); | ||
request.setPomFile(pom); | ||
request.setOutputHandler(new PrintStreamHandler(new PrintStream(this.outputStream, true), true)); | ||
request.setGoals(Collections.singletonList("dependency:build-classpath")); | ||
request.setProperties(properties); | ||
request.setTimeoutInSeconds((int) TimeUnit.MINUTES.toSeconds(5)); | ||
request.setJavaHome(Optional.ofNullable(System.getProperty("java.home")).map(File::new).orElse(null)); | ||
request.setMavenHome(maven); | ||
|
||
InvocationResult result = this.invoker.execute(request); | ||
if (result.getExitCode() != 0) | ||
{ | ||
String output = this.outputStream.toString(StandardCharsets.UTF_8); | ||
throw new IllegalStateException("Maven invoker failed\n\n" + output, result.getExecutionException()); | ||
} | ||
|
||
String classpath = Files.readString(legendLspClasspath.toPath(), StandardCharsets.UTF_8); | ||
|
||
server.logInfoToClient("Classpath used: " + classpath); | ||
|
||
String[] classpathEntries = classpath.split(";"); | ||
URL[] urls = new URL[classpathEntries.length]; | ||
|
||
for (int i = 0; i < urls.length; i++) | ||
{ | ||
urls[i] = new File(classpathEntries[i]).toURI().toURL(); | ||
} | ||
|
||
ClassLoader parentClassloader = ClasspathUsingMavenFactory.class.getClassLoader(); | ||
return new URLClassLoader("legend-lsp", urls, parentClassloader); | ||
} | ||
catch (RuntimeException e) | ||
{ | ||
throw e; | ||
} | ||
catch (Exception e) | ||
{ | ||
throw new RuntimeException(e); | ||
} | ||
finally | ||
{ | ||
this.outputStream.reset(); | ||
} | ||
}); | ||
} | ||
} |
Oops, something went wrong.