Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import { URI } from 'vscode-uri';
import { prepareAndGenerateConfig, cleanAndValidateProject } from '../config-generator/configGenerator';
import { extension } from '../../BalExtensionContext';
import * as fs from 'fs';
import { findHighestVersionJdk } from '../../utils/server/server';
import { findJdkInDirectory, findSystemJdk } from '../../utils/server/server';
import { PlatformExtRpcManager } from '../../rpc-managers/platform-ext/rpc-manager';

const BALLERINA_COMMAND = "ballerina.command";
Expand Down Expand Up @@ -788,13 +788,14 @@ function getJavaCommand(): string {
? ballerinaHome.substring(0, ballerinaHome.indexOf('distributions'))
: ballerinaHome;

// Find any JDK in the dependencies directory
const dependenciesDir = join(baseHome, 'dependencies');
const jdkDir = findHighestVersionJdk(dependenciesDir);
// Find any JDK: check ballerinaHome/dependencies first, then baseHome/dependencies, then fall back to system JDK
const jdkDir = findJdkInDirectory(join(ballerinaHome, 'dependencies'))
?? findJdkInDirectory(join(baseHome, 'dependencies'))
?? findSystemJdk();

if (!jdkDir) {
log(`No JDK found in dependencies directory: ${dependenciesDir}`);
throw new Error(`JDK not found in ${dependenciesDir}`);
log(`No JDK found in ballerinaHome/dependencies, baseHome/dependencies, or system JAVA_HOME`);
throw new Error(`JDK not found. Please set JAVA_HOME or install a JDK in the Ballerina dependencies directory.`);
}

const jdkVersionMatch = jdkDir.match(/jdk-(.+)-jre/);
Expand Down
170 changes: 89 additions & 81 deletions workspaces/ballerina/ballerina-extension/src/utils/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function extractJdkInfo(fileName: string, directory: string): JdkInfo | null {
};
}

export function findHighestVersionJdk(directory: string): string | null {
export function findJdkInDirectory(directory: string): string | null {
try {
if (!fs.existsSync(directory)) {
debug(`Dependencies directory not found: ${directory}`);
Expand All @@ -122,81 +122,6 @@ export function findHighestVersionJdk(directory: string): string | null {

if (jdkInfos.length === 0) {
debug(`No JDK directories found matching pattern in: ${directory}`);
// If no JDK directories found, check for system set jdk version by using JAVA_HOME environment variable
// Try to find JAVA_HOME using environment variables on Windows, WSL, Ubuntu, or Mac
let javaHome = process.env.JAVA_HOME;

// For WSL, try to detect Linux JAVA_HOME if not found or is a windows path
if ((!javaHome || javaHome.includes('\\')) && isWSL()) {
try {
// Try to run 'bash -c "echo $JAVA_HOME"' to get the Linux side JAVA_HOME
const wslJavaHome = require('child_process').execSync('bash -c "echo $JAVA_HOME"', { encoding: 'utf8' }).trim();
if (wslJavaHome) {
debug(`Using WSL system set JDK from Linux environment: ${wslJavaHome}`);
return wslJavaHome;
}
} catch (e) {
debug(`Could not get JAVA_HOME from WSL Linux environment: ${e}`);
}
}

if (javaHome) {
debug(`Using system set JDK: ${javaHome}`);
return javaHome;
}

// Try some common fallback locations for Ubuntu / Mac
const platform = process.platform;
let commonJavaDirs: string[] = [];
debug(`Detecting platform-specific common Java directories for platform: ${platform}`);

if (platform === 'darwin') { // macOS
debug('Platform is macOS. Checking default Java and SDKMAN directories.');
commonJavaDirs = [
'/Library/Java/JavaVirtualMachines',
process.env.HOME ? `${process.env.HOME}/.sdkman/candidates/java/current` : ''
];
debug(`Common Java directories for macOS: ${JSON.stringify(commonJavaDirs)}`);
} else if (platform === 'linux' || isWSL()) { // Linux, also WSL
debug('Platform is Linux or WSL. Checking standard Java and SDKMAN directories.');
commonJavaDirs = [
'/usr/lib/jvm',
'/usr/java',
process.env.HOME ? `${process.env.HOME}/.sdkman/candidates/java/current` : ''
];
debug(`Common Java directories for Linux/WSL: ${JSON.stringify(commonJavaDirs)}`);
} else if (platform === 'win32') { // Windows
debug('Platform is Windows. Checking ProgramFiles Java directories.');
if (process.env['ProgramFiles']) {
debug(`Adding Java directory from ProgramFiles: ${process.env['ProgramFiles']}\\Java`);
commonJavaDirs.push(`${process.env['ProgramFiles']}\\Java`);
}
if (process.env['ProgramFiles(x86)']) {
debug(`Adding Java directory from ProgramFiles(x86): ${process.env['ProgramFiles(x86)']}\\Java`);
commonJavaDirs.push(`${process.env['ProgramFiles(x86)']}\\Java`);
}
debug(`Common Java directories for Windows: ${JSON.stringify(commonJavaDirs)}`);
} else {
debug(`Unknown or unsupported platform for Java directory detection: ${platform}`);
}

for (const dir of commonJavaDirs) {
if (dir && fs.existsSync(dir)) {
// Check for JDK subdirectories
const subDirs = fs.readdirSync(dir);
for (const sub of subDirs) {
// JDK dir must contain bin/java[.exe]
const javaBin = platform === 'win32'
? path.join(dir, sub, 'bin', 'java.exe')
: path.join(dir, sub, 'bin', 'java');
if (fs.existsSync(javaBin)) {
debug(`Found JDK in fallback directory: ${path.join(dir, sub)}`);
return path.join(dir, sub);
}
}
}
}
debug(`No system set JDK found, returning null`);
return null;
}

Expand All @@ -222,6 +147,88 @@ export function findHighestVersionJdk(directory: string): string | null {
}
}

export function findSystemJdk(): string | null {
// Try to find JAVA_HOME using environment variables on Windows, WSL, Ubuntu, or Mac
let javaHome = process.env.JAVA_HOME;

// For WSL, try to detect Linux JAVA_HOME if not found or is a windows path
if ((!javaHome || javaHome.includes('\\')) && isWSL()) {
try {
// Try to run 'bash -c "echo $JAVA_HOME"' to get the Linux side JAVA_HOME
const wslJavaHome = require('child_process').execSync('bash -c "echo $JAVA_HOME"', { encoding: 'utf8' }).trim();
if (wslJavaHome) {
debug(`Using WSL system set JDK from Linux environment: ${wslJavaHome}`);
return wslJavaHome;
}
} catch (e) {
debug(`Could not get JAVA_HOME from WSL Linux environment: ${e}`);
}
}

if (javaHome) {
debug(`Using system set JDK: ${javaHome}`);
return javaHome;
}

// Try some common fallback locations for Ubuntu / Mac
const platform = process.platform;
let commonJavaDirs: string[] = [];
debug(`Detecting platform-specific common Java directories for platform: ${platform}`);

if (platform === 'darwin') { // macOS
debug('Platform is macOS. Checking default Java and SDKMAN directories.');
commonJavaDirs = [
'/Library/Java/JavaVirtualMachines',
process.env.HOME ? `${process.env.HOME}/.sdkman/candidates/java/current` : ''
];
debug(`Common Java directories for macOS: ${JSON.stringify(commonJavaDirs)}`);
} else if (platform === 'linux' || isWSL()) { // Linux, also WSL
debug('Platform is Linux or WSL. Checking standard Java and SDKMAN directories.');
commonJavaDirs = [
'/usr/lib/jvm',
'/usr/java',
process.env.HOME ? `${process.env.HOME}/.sdkman/candidates/java/current` : ''
];
debug(`Common Java directories for Linux/WSL: ${JSON.stringify(commonJavaDirs)}`);
} else if (platform === 'win32') { // Windows
debug('Platform is Windows. Checking ProgramFiles Java directories.');
if (process.env['ProgramFiles']) {
debug(`Adding Java directory from ProgramFiles: ${process.env['ProgramFiles']}\\Java`);
commonJavaDirs.push(`${process.env['ProgramFiles']}\\Java`);
}
if (process.env['ProgramFiles(x86)']) {
debug(`Adding Java directory from ProgramFiles(x86): ${process.env['ProgramFiles(x86)']}\\Java`);
commonJavaDirs.push(`${process.env['ProgramFiles(x86)']}\\Java`);
}
debug(`Common Java directories for Windows: ${JSON.stringify(commonJavaDirs)}`);
} else {
debug(`Unknown or unsupported platform for Java directory detection: ${platform}`);
}

for (const dir of commonJavaDirs) {
if (dir && fs.existsSync(dir)) {
// Check for JDK subdirectories
const subDirs = fs.readdirSync(dir);
for (const sub of subDirs) {
// JDK dir must contain bin/java[.exe]
const javaBin = platform === 'win32'
? path.join(dir, sub, 'bin', 'java.exe')
: path.join(dir, sub, 'bin', 'java');
if (fs.existsSync(javaBin)) {
debug(`Found JDK in fallback directory: ${path.join(dir, sub)}`);
return path.join(dir, sub);
}
}
}
}
debug(`No system set JDK found, returning null`);
return null;
}

export function findHighestVersionJdk(directory: string): string | null {
return findJdkInDirectory(directory) ?? findSystemJdk();
}

export function getServerOptions(extension: BallerinaExtension): ServerOptions {
debug('Getting server options.');
// Check if user wants to use Ballerina CLI language server or if version requires it
Expand Down Expand Up @@ -382,13 +389,14 @@ function getServerOptionsUsingJava(extension: BallerinaExtension): ServerOptions

const classpath = customPaths.join(delimiter);

// Find any JDK in the dependencies directory
const dependenciesDir = join(baseHome, 'dependencies');
const jdkDir = findHighestVersionJdk(dependenciesDir);
// Find any JDK: check ballerinaHome/dependencies first, then baseHome/dependencies, then fall back to system JDK
const jdkDir = findJdkInDirectory(join(ballerinaHome, 'dependencies'))
?? findJdkInDirectory(join(baseHome, 'dependencies'))
?? findSystemJdk();
debug(`JDK Directory: ${jdkDir}`);
if (!jdkDir) {
debug(`No JDK found in dependencies directory: ${dependenciesDir}`);
throw new Error(`JDK not found in ${dependenciesDir}`);
debug(`No JDK found in ballerinaHome/dependencies, baseHome/dependencies, or system JAVA_HOME`);
throw new Error(`JDK not found. Please set JAVA_HOME or install a JDK in the Ballerina dependencies directory.`);
}

const javaExecutable = isWindows() ? 'java.exe' : 'java';
Expand Down
Loading