Add utility command to get the launch command length (#254)
Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
This commit is contained in:
Родитель
d3b8b3a630
Коммит
ee889d9fbc
|
@ -12,6 +12,8 @@
|
|||
package com.microsoft.java.debug.core.adapter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
|
@ -25,11 +27,17 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.microsoft.java.debug.core.DebugException;
|
||||
|
@ -287,4 +295,52 @@ public class AdapterUtils {
|
|||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the classpath parameters to a temporary classpath.jar.
|
||||
* @param classPaths - the classpath parameters
|
||||
* @return the file path of the generate classpath.jar
|
||||
* @throws IOException Some errors occur during generating the classpath.jar
|
||||
*/
|
||||
public static Path generateClasspathJar(String[] classPaths) throws IOException {
|
||||
List<String> classpathUrls = new ArrayList<>();
|
||||
for (String classpath : classPaths) {
|
||||
classpathUrls.add(AdapterUtils.toUrl(classpath));
|
||||
}
|
||||
|
||||
Manifest manifest = new Manifest();
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
// In jar manifest, the absolute path C:\a.jar should be converted to the url style file:///C:/a.jar
|
||||
attributes.put(Attributes.Name.CLASS_PATH, String.join(" ", classpathUrls));
|
||||
Path tempfile = Files.createTempFile("classpath_", ".jar");
|
||||
JarOutputStream jar = new JarOutputStream(new FileOutputStream(tempfile.toFile()), manifest);
|
||||
jar.close();
|
||||
|
||||
return tempfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the classpath parameters to a temporary argfile file.
|
||||
* @param classPaths - the classpath parameters
|
||||
* @param modulePaths - the modulepath parameters
|
||||
* @return the file path of the generated argfile
|
||||
* @throws IOException Some errors occur during generating the argfile
|
||||
*/
|
||||
public static Path generateArgfile(String[] classPaths, String[] modulePaths) throws IOException {
|
||||
String argfile = "";
|
||||
if (ArrayUtils.isNotEmpty(classPaths)) {
|
||||
argfile = "-classpath \"" + String.join(File.pathSeparator, classPaths) + "\"";
|
||||
}
|
||||
|
||||
if (ArrayUtils.isNotEmpty(modulePaths)) {
|
||||
argfile = " --module-path \"" + String.join(File.pathSeparator, modulePaths) + "\"";
|
||||
}
|
||||
|
||||
argfile = argfile.replace("\\", "\\\\");
|
||||
Path tempfile = Files.createTempFile("java_", ".argfile");
|
||||
Files.write(tempfile, argfile.getBytes());
|
||||
|
||||
return tempfile;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.nio.file.Files;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -86,7 +87,7 @@ public abstract class AbstractDisconnectRequestHandler implements IDebugRequestH
|
|||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing.
|
||||
}
|
||||
|
|
|
@ -12,12 +12,10 @@
|
|||
package com.microsoft.java.debug.core.adapter.handler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -26,9 +24,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -97,59 +92,31 @@ public class LaunchRequestHandler implements IDebugRequestHandler {
|
|||
|
||||
activeLaunchHandler.preLaunch(launchArguments, context);
|
||||
|
||||
Path tempfile = null;
|
||||
// Use the specified cli style to launch the program.
|
||||
if (launchArguments.shortenCommandLine == ShortenApproach.JARMANIFEST) {
|
||||
if (ArrayUtils.isNotEmpty(launchArguments.classPaths)) {
|
||||
List<String> classpathUrls = new ArrayList<>();
|
||||
for (String classpath : launchArguments.classPaths) {
|
||||
try {
|
||||
classpathUrls.add(AdapterUtils.toUrl(classpath));
|
||||
} catch (IllegalArgumentException | MalformedURLException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to launch the program with jarmanifest style: %s", ex.toString(), ex));
|
||||
throw AdapterUtils.createCompletionException("Failed to launch the program with jarmanifest style: " + ex.toString(),
|
||||
ErrorCode.LAUNCH_FAILURE, ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
tempfile = Files.createTempFile("classpath_", ".jar");
|
||||
Manifest manifest = new Manifest();
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
// In jar manifest, the absolute path C:\a.jar should be converted to the url style file:///C:/a.jar
|
||||
attributes.put(Attributes.Name.CLASS_PATH, String.join(" ", classpathUrls));
|
||||
JarOutputStream jar = new JarOutputStream(new FileOutputStream(tempfile.toFile()), manifest);
|
||||
jar.close();
|
||||
Path tempfile = AdapterUtils.generateClasspathJar(launchArguments.classPaths);
|
||||
launchArguments.vmArgs += " -cp \"" + tempfile.toAbsolutePath().toString() + "\"";
|
||||
launchArguments.classPaths = new String[0];
|
||||
context.setClasspathJar(tempfile);
|
||||
} catch (IllegalArgumentException | MalformedURLException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to launch the program with jarmanifest style: %s", ex.toString(), ex));
|
||||
throw AdapterUtils.createCompletionException("Failed to launch the program with jarmanifest style: " + ex.toString(),
|
||||
ErrorCode.LAUNCH_FAILURE, ex);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to create a temp classpath.jar: %s", e.toString()), e);
|
||||
tempfile = null;
|
||||
}
|
||||
}
|
||||
} else if (launchArguments.shortenCommandLine == ShortenApproach.ARGFILE) {
|
||||
try {
|
||||
tempfile = Files.createTempFile("java_", ".argfile");
|
||||
String argfile = "";
|
||||
if (ArrayUtils.isNotEmpty(launchArguments.classPaths)) {
|
||||
argfile = "-classpath \"" + String.join(File.pathSeparator, launchArguments.classPaths) + "\"";
|
||||
}
|
||||
|
||||
if (ArrayUtils.isNotEmpty(launchArguments.modulePaths)) {
|
||||
argfile = " --module-path \"" + String.join(File.pathSeparator, launchArguments.modulePaths) + "\"";
|
||||
}
|
||||
|
||||
argfile = argfile.replace("\\", "\\\\");
|
||||
Files.write(tempfile, argfile.getBytes());
|
||||
Path tempfile = AdapterUtils.generateArgfile(launchArguments.classPaths, launchArguments.modulePaths);
|
||||
launchArguments.vmArgs += " @" + tempfile.toAbsolutePath().toString();
|
||||
launchArguments.classPaths = new String[0];
|
||||
launchArguments.modulePaths = new String[0];
|
||||
context.setArgsfile(tempfile);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to create a temp argfile: %s", e.toString()), e);
|
||||
tempfile = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +128,14 @@ public class LaunchRequestHandler implements IDebugRequestHandler {
|
|||
});
|
||||
}
|
||||
|
||||
protected static String[] constructLaunchCommands(LaunchArguments launchArguments, boolean serverMode, String address) {
|
||||
/**
|
||||
* Construct the Java command lines based on the given launch arguments.
|
||||
* @param launchArguments - The launch arguments
|
||||
* @param serverMode - whether to enable the debug port with server mode
|
||||
* @param address - the debug port
|
||||
* @return the command arrays
|
||||
*/
|
||||
public static String[] constructLaunchCommands(LaunchArguments launchArguments, boolean serverMode, String address) {
|
||||
String slash = System.getProperty("file.separator");
|
||||
|
||||
List<String> launchCmds = new ArrayList<>();
|
||||
|
|
|
@ -9,12 +9,9 @@
|
|||
<command id="vscode.java.buildWorkspace"/>
|
||||
<command id="vscode.java.fetchUsageData"/>
|
||||
<command id="vscode.java.updateDebugSettings"/>
|
||||
<command
|
||||
id="vscode.java.validateLaunchConfig">
|
||||
</command>
|
||||
<command
|
||||
id="vscode.java.resolveMainMethod">
|
||||
</command>
|
||||
<command id="vscode.java.validateLaunchConfig"/>
|
||||
<command id="vscode.java.resolveMainMethod"/>
|
||||
<command id="vscode.java.inferLaunchCommandLength"/>
|
||||
</delegateCommandHandler>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -17,47 +17,48 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
|||
import org.eclipse.jdt.ls.core.internal.IDelegateCommandHandler;
|
||||
|
||||
import com.microsoft.java.debug.core.UsageDataStore;
|
||||
import com.microsoft.java.debug.core.protocol.JsonUtils;
|
||||
import com.microsoft.java.debug.core.protocol.Requests.LaunchArguments;
|
||||
|
||||
public class JavaDebugDelegateCommandHandler implements IDelegateCommandHandler {
|
||||
|
||||
public static String FETCH_USER_DATA = "vscode.java.fetchUsageData";
|
||||
|
||||
public static String DEBUG_STARTSESSION = "vscode.java.startDebugSession";
|
||||
|
||||
public static String RESOLVE_CLASSPATH = "vscode.java.resolveClasspath";
|
||||
|
||||
public static String RESOLVE_MAINCLASS = "vscode.java.resolveMainClass";
|
||||
|
||||
public static String BUILD_WORKSPACE = "vscode.java.buildWorkspace";
|
||||
|
||||
public static String UPDATE_DEBUG_SETTINGS = "vscode.java.updateDebugSettings";
|
||||
|
||||
public static String VALIDATE_LAUNCHCONFIG = "vscode.java.validateLaunchConfig";
|
||||
|
||||
public static String RESOLVE_MAINMETHOD = "vscode.java.resolveMainMethod";
|
||||
public static final String FETCH_USER_DATA = "vscode.java.fetchUsageData";
|
||||
public static final String DEBUG_STARTSESSION = "vscode.java.startDebugSession";
|
||||
public static final String RESOLVE_CLASSPATH = "vscode.java.resolveClasspath";
|
||||
public static final String RESOLVE_MAINCLASS = "vscode.java.resolveMainClass";
|
||||
public static final String BUILD_WORKSPACE = "vscode.java.buildWorkspace";
|
||||
public static final String UPDATE_DEBUG_SETTINGS = "vscode.java.updateDebugSettings";
|
||||
public static final String VALIDATE_LAUNCHCONFIG = "vscode.java.validateLaunchConfig";
|
||||
public static final String RESOLVE_MAINMETHOD = "vscode.java.resolveMainMethod";
|
||||
public static final String INFER_LAUNCH_COMMAND_LENGTH = "vscode.java.inferLaunchCommandLength";
|
||||
|
||||
@Override
|
||||
public Object executeCommand(String commandId, List<Object> arguments, IProgressMonitor progress) throws Exception {
|
||||
if (DEBUG_STARTSESSION.equals(commandId)) {
|
||||
IDebugServer debugServer = JavaDebugServer.getInstance();
|
||||
debugServer.start();
|
||||
return debugServer.getPort();
|
||||
} else if (RESOLVE_CLASSPATH.equals(commandId)) {
|
||||
ResolveClasspathsHandler handler = new ResolveClasspathsHandler();
|
||||
return handler.resolveClasspaths(arguments);
|
||||
} else if (RESOLVE_MAINCLASS.equals(commandId)) {
|
||||
ResolveMainClassHandler handler = new ResolveMainClassHandler();
|
||||
return handler.resolveMainClass(arguments);
|
||||
} else if (BUILD_WORKSPACE.equals(commandId)) {
|
||||
// TODO
|
||||
} else if (FETCH_USER_DATA.equals(commandId)) {
|
||||
return UsageDataStore.getInstance().fetchAll();
|
||||
} else if (UPDATE_DEBUG_SETTINGS.equals(commandId)) {
|
||||
return DebugSettingUtils.configDebugSettings(arguments);
|
||||
} else if (VALIDATE_LAUNCHCONFIG.equals(commandId)) {
|
||||
return new ResolveMainClassHandler().validateLaunchConfig(arguments);
|
||||
} else if (RESOLVE_MAINMETHOD.equals(commandId)) {
|
||||
return ResolveMainMethodHandler.resolveMainMethods(arguments);
|
||||
switch (commandId) {
|
||||
case DEBUG_STARTSESSION:
|
||||
IDebugServer debugServer = JavaDebugServer.getInstance();
|
||||
debugServer.start();
|
||||
return debugServer.getPort();
|
||||
case RESOLVE_CLASSPATH:
|
||||
ResolveClasspathsHandler handler = new ResolveClasspathsHandler();
|
||||
return handler.resolveClasspaths(arguments);
|
||||
case RESOLVE_MAINCLASS:
|
||||
ResolveMainClassHandler resolveMainClassHandler = new ResolveMainClassHandler();
|
||||
return resolveMainClassHandler.resolveMainClass(arguments);
|
||||
case BUILD_WORKSPACE:
|
||||
// TODO
|
||||
break;
|
||||
case FETCH_USER_DATA:
|
||||
return UsageDataStore.getInstance().fetchAll();
|
||||
case UPDATE_DEBUG_SETTINGS:
|
||||
return DebugSettingUtils.configDebugSettings(arguments);
|
||||
case VALIDATE_LAUNCHCONFIG:
|
||||
return new ResolveMainClassHandler().validateLaunchConfig(arguments);
|
||||
case RESOLVE_MAINMETHOD:
|
||||
return ResolveMainMethodHandler.resolveMainMethods(arguments);
|
||||
case INFER_LAUNCH_COMMAND_LENGTH:
|
||||
return LaunchCommandHandler.getLaunchCommandLength(JsonUtils.fromJson((String) arguments.get(0), LaunchArguments.class));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(String.format("Java debug plugin doesn't support the command '%s'.", commandId));
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Microsoft Corporation and others.
|
||||
* 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:
|
||||
* Microsoft Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.microsoft.java.debug.plugin.internal;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.microsoft.java.debug.core.adapter.handler.LaunchRequestHandler;
|
||||
import com.microsoft.java.debug.core.protocol.Requests.CONSOLE;
|
||||
import com.microsoft.java.debug.core.protocol.Requests.LaunchArguments;
|
||||
|
||||
public class LaunchCommandHandler {
|
||||
|
||||
/**
|
||||
* Get the approximate command line length based on the launch arguments.
|
||||
* @param launchArguments - the launch arguments
|
||||
* @return the approximate command line length
|
||||
*/
|
||||
public static int getLaunchCommandLength(LaunchArguments launchArguments) {
|
||||
String encoding = StringUtils.isBlank(launchArguments.encoding) ? StandardCharsets.UTF_8.name() : launchArguments.encoding;
|
||||
launchArguments.vmArgs += String.format(" -Dfile.encoding=%s", encoding);
|
||||
String address = launchArguments.noDebug ? "" : "888888";
|
||||
String[] commands = LaunchRequestHandler.constructLaunchCommands(launchArguments, false, address);
|
||||
int cwdLength = launchArguments.console == CONSOLE.internalConsole ? 0 : StringUtils.length("cd " + launchArguments.cwd + " && ");
|
||||
return cwdLength + String.join(" ", commands).length();
|
||||
}
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче