|
4 | 4 | * you may not use this file except in compliance with the Elastic License. |
5 | 5 | */ |
6 | 6 |
|
7 | | -import { spawn } from 'child_process'; |
8 | | -import { chmodSync } from 'fs'; |
| 7 | +import { execFile, spawn } from 'child_process'; |
| 8 | +import { chmodSync, existsSync } from 'fs'; |
9 | 9 | import getPort from 'get-port'; |
10 | 10 | import * as glob from 'glob'; |
11 | 11 | import { platform as getOsPlatform } from 'os'; |
@@ -94,28 +94,40 @@ export class JavaLauncher implements ILanguageServerLauncher { |
94 | 94 | } |
95 | 95 |
|
96 | 96 | let config = 'config_mac'; |
| 97 | + let bundledJavaHome = `${findJDK('osx')}/Contents/Home`; |
97 | 98 | let javaPath = 'java'; |
98 | 99 | let javaHomePath = ''; |
99 | 100 | // detect platform |
100 | 101 | switch (getOsPlatform()) { |
101 | 102 | case 'darwin': |
102 | | - javaHomePath = `${findJDK('osx')}/Contents/Home`; |
103 | | - javaPath = path.resolve(`${javaHomePath}`, 'bin', 'java'); |
104 | 103 | break; |
105 | 104 | case 'win32': |
106 | | - javaHomePath = `${findJDK('windows')}`; |
107 | | - javaPath = path.resolve(`${javaHomePath}`, 'bin', 'java.exe'); |
| 105 | + bundledJavaHome = `${findJDK('windows')}`; |
108 | 106 | config = 'config_win'; |
109 | 107 | break; |
110 | 108 | case 'linux': |
111 | | - javaHomePath = `${findJDK('linux')}`; |
112 | | - javaPath = path.resolve(`${javaHomePath}`, 'bin', 'java'); |
| 109 | + bundledJavaHome = `${findJDK('linux')}`; |
113 | 110 | config = 'config_linux'; |
114 | 111 | break; |
115 | 112 | default: |
116 | 113 | log.error('Unable to find platform for this os'); |
117 | 114 | } |
118 | 115 |
|
| 116 | + if (this.getSystemJavaHome()) { |
| 117 | + javaHomePath = this.getSystemJavaHome(); |
| 118 | + if (!this.checkJavaVersion(javaHomePath)) { |
| 119 | + javaHomePath = ''; |
| 120 | + } |
| 121 | + } |
| 122 | + if (javaHomePath === '') { |
| 123 | + javaHomePath = bundledJavaHome; |
| 124 | + } |
| 125 | + javaPath = path.resolve( |
| 126 | + javaHomePath, |
| 127 | + 'bin', |
| 128 | + process.platform === 'win32' ? 'java.exe' : 'java' |
| 129 | + ); |
| 130 | + |
119 | 131 | chmodSync(path.dirname(javaPath), '755'); |
120 | 132 |
|
121 | 133 | const p = spawn( |
@@ -155,4 +167,71 @@ export class JavaLauncher implements ILanguageServerLauncher { |
155 | 167 | ); |
156 | 168 | return p; |
157 | 169 | } |
| 170 | + |
| 171 | + // TODO(pcxu): run /usr/libexec/java_home to get all java homes for macOS |
| 172 | + private getSystemJavaHome(): string { |
| 173 | + let javaHome = process.env.JDK_HOME; |
| 174 | + if (!javaHome) { |
| 175 | + javaHome = process.env.JAVA_HOME; |
| 176 | + } |
| 177 | + if (javaHome) { |
| 178 | + javaHome = this.expandHomeDir(javaHome); |
| 179 | + const JAVAC_FILENAME = 'javac' + (process.platform === 'win32' ? '.exe' : ''); |
| 180 | + if (existsSync(javaHome) && existsSync(path.resolve(javaHome, 'bin', JAVAC_FILENAME))) { |
| 181 | + return javaHome; |
| 182 | + } |
| 183 | + } |
| 184 | + return ''; |
| 185 | + } |
| 186 | + |
| 187 | + private checkJavaVersion(javaHome: string): boolean { |
| 188 | + execFile( |
| 189 | + path.resolve(javaHome, 'bin', process.platform === 'win32' ? 'java.exe' : 'java'), |
| 190 | + ['-version'], |
| 191 | + {}, |
| 192 | + (error, stdout, stderr) => { |
| 193 | + const javaVersion = this.parseMajorVersion(stderr); |
| 194 | + if (javaVersion < 8) { |
| 195 | + return false; |
| 196 | + } else { |
| 197 | + return true; |
| 198 | + } |
| 199 | + } |
| 200 | + ); |
| 201 | + return false; |
| 202 | + } |
| 203 | + |
| 204 | + private parseMajorVersion(content: string): number { |
| 205 | + let regexp = /version "(.*)"/g; |
| 206 | + let match = regexp.exec(content); |
| 207 | + if (!match) { |
| 208 | + return 0; |
| 209 | + } |
| 210 | + let version = match[1]; |
| 211 | + if (version.startsWith('1.')) { |
| 212 | + version = version.substring(2); |
| 213 | + } |
| 214 | + |
| 215 | + regexp = /\d+/g; |
| 216 | + match = regexp.exec(version); |
| 217 | + let javaVersion = 0; |
| 218 | + if (match) { |
| 219 | + javaVersion = parseInt(match[0], 10); |
| 220 | + } |
| 221 | + return javaVersion; |
| 222 | + } |
| 223 | + |
| 224 | + private expandHomeDir(javaHome: string): string { |
| 225 | + const homeDir = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME']; |
| 226 | + if (!javaHome) { |
| 227 | + return javaHome; |
| 228 | + } |
| 229 | + if (javaHome === '~') { |
| 230 | + return homeDir!; |
| 231 | + } |
| 232 | + if (javaHome.slice(0, 2) !== '~/') { |
| 233 | + return javaHome; |
| 234 | + } |
| 235 | + return path.join(homeDir!, javaHome.slice(2)); |
| 236 | + } |
158 | 237 | } |
0 commit comments