forked from microsoft/vscode-java-debug
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlaunchCommand.ts
More file actions
106 lines (93 loc) · 4.15 KB
/
launchCommand.ts
File metadata and controls
106 lines (93 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as cp from "child_process";
import * as _ from "lodash";
import * as path from "path";
import * as vscode from "vscode";
import { inferLaunchCommandLength } from "./languageServerPlugin";
import { getJavaHome } from "./utility";
enum shortenApproach {
none = "none",
jarmanifest = "jarmanifest",
argfile = "argfile",
}
export async function detectLaunchCommandStyle(config: vscode.DebugConfiguration): Promise<shortenApproach> {
const javaHome = await getJavaHome();
const javaVersion = await checkJavaVersion(javaHome);
const recommendedShortenApproach = javaVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile;
return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none;
}
function checkJavaVersion(javaHome: string): Promise<number> {
return new Promise((resolve, reject) => {
cp.execFile(javaHome + "/bin/java", ["-version"], {}, (error, stdout, stderr) => {
const javaVersion = parseMajorVersion(stderr);
resolve(javaVersion);
});
});
}
function parseMajorVersion(content: string): number {
let regexp = /version "(.*)"/g;
let match = regexp.exec(content);
if (!match) {
return 0;
}
let version = match[1];
// Ignore '1.' prefix for legacy Java versions
if (version.startsWith("1.")) {
version = version.substring(2);
}
// look into the interesting bits now
regexp = /\d+/g;
match = regexp.exec(version);
let javaVersion = 0;
if (match) {
javaVersion = parseInt(match[0], 10);
}
return javaVersion;
}
async function shouldShortenIfNecessary(config: vscode.DebugConfiguration): Promise<boolean> {
const cliLength = await inferLaunchCommandLength(config);
const classPaths = config.classPaths || [];
const modulePaths = config.modulePaths || [];
const classPathLength = classPaths.join(path.delimiter).length;
const modulePathLength = modulePaths.join(path.delimiter).length;
if (!config.console || config.console === "internalConsole") {
return cliLength >= getMaxProcessCommandLineLength(config) || classPathLength >= getMaxArgLength() || modulePathLength >= getMaxArgLength();
} else {
return classPaths.length > 1 || modulePaths.length > 1;
}
}
function getMaxProcessCommandLineLength(config: vscode.DebugConfiguration): number {
const ARG_MAX_WINDOWS = 32768;
const ARG_MAX_MACOS = 262144;
const ARG_MAX_LINUX = 2097152;
// for Posix systems, ARG_MAX is the maximum length of argument to the exec functions including environment data.
// POSIX suggests to subtract 2048 additionally so that the process may safely modify its environment.
// see https://www.in-ulm.de/~mascheck/various/argmax/
if (process.platform === "win32") {
// https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553/
// On windows, the max process commmand line length is 32k (32768) characters.
return ARG_MAX_WINDOWS - 2048;
} else if (process.platform === "darwin") {
return ARG_MAX_MACOS - getEnvironmentLength(config) - 2048;
} else if (process.platform === "linux") {
return ARG_MAX_LINUX - getEnvironmentLength(config) - 2048;
}
return Number.MAX_SAFE_INTEGER;
}
function getEnvironmentLength(config: vscode.DebugConfiguration): number {
const env = config.env || {};
return _.isEmpty(env) ? 0 : Object.keys(env).map((key) => strlen(key) + strlen(env[key]) + 1).reduce((a, b) => a + b);
}
function strlen(str: string): number {
return str ? str.length : 0;
}
function getMaxArgLength(): number {
const MAX_ARG_STRLEN_LINUX = 131072;
if (process.platform === "linux") {
// On Linux, MAX_ARG_STRLEN (kernel >= 2.6.23) is the maximum length of a command line argument (or environment variable). Its value
// cannot be changed without recompiling the kernel.
return MAX_ARG_STRLEN_LINUX - 2048;
}
return Number.MAX_SAFE_INTEGER;
}