From ce01bae6f9e5e9771c48d5c913ab5529f9522685 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:46:13 +0000 Subject: [PATCH 1/2] Initial plan From 99eec31db3e156534fe2d564fbf0d76c252a4a65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 07:01:40 +0000 Subject: [PATCH 2/2] Fix Java detection to check multiple dependency dirs and fall back to JAVA_HOME Co-authored-by: kanushka <24244523+kanushka@users.noreply.github.com> --- .../src/features/debugger/config-provider.ts | 13 +- .../src/utils/server/server.ts | 170 +++++++++--------- 2 files changed, 96 insertions(+), 87 deletions(-) diff --git a/workspaces/ballerina/ballerina-extension/src/features/debugger/config-provider.ts b/workspaces/ballerina/ballerina-extension/src/features/debugger/config-provider.ts index 03941c2a0d3..3755348e305 100644 --- a/workspaces/ballerina/ballerina-extension/src/features/debugger/config-provider.ts +++ b/workspaces/ballerina/ballerina-extension/src/features/debugger/config-provider.ts @@ -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"; @@ -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/); diff --git a/workspaces/ballerina/ballerina-extension/src/utils/server/server.ts b/workspaces/ballerina/ballerina-extension/src/utils/server/server.ts index 5aff49ba8f0..26cc48ba507 100644 --- a/workspaces/ballerina/ballerina-extension/src/utils/server/server.ts +++ b/workspaces/ballerina/ballerina-extension/src/utils/server/server.ts @@ -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}`); @@ -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; } @@ -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 @@ -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';