diff --git a/backend/managers/javaManager.js b/backend/managers/javaManager.js index c2ebf85..48e34b2 100644 --- a/backend/managers/javaManager.js +++ b/backend/managers/javaManager.js @@ -106,6 +106,23 @@ function getBundledJavaPath(jreDir = JRE_DIR) { } } + // Fallback: check for nested JRE directory (e.g. jdk-25.0.2+10-jre/bin/java) + // This happens when flattenJREDir fails due to EPERM/EACCES on Windows + try { + if (fs.existsSync(jreDir)) { + const entries = fs.readdirSync(jreDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'lib') { + const nestedCandidate = path.join(jreDir, entry.name, 'bin', JAVA_EXECUTABLE); + if (fs.existsSync(nestedCandidate)) { + console.log(`[JRE] Using nested Java path: ${nestedCandidate}`); + return nestedCandidate; + } + } + } + } + } catch (_) { /* ignore */ } + return null; } @@ -409,7 +426,7 @@ function extractTarGz(tarGzPath, dest) { function flattenJREDir(jreLatest) { try { const entries = fs.readdirSync(jreLatest, { withFileTypes: true }); - + if (entries.length !== 1 || !entries[0].isDirectory()) { return; } @@ -420,12 +437,48 @@ function flattenJREDir(jreLatest) { for (const file of files) { const oldPath = path.join(nested, file.name); const newPath = path.join(jreLatest, file.name); - fs.renameSync(oldPath, newPath); + try { + fs.renameSync(oldPath, newPath); + } catch (renameErr) { + if (renameErr.code === 'EPERM' || renameErr.code === 'EACCES' || renameErr.code === 'EBUSY') { + console.log(`[JRE] Rename failed for ${file.name} (${renameErr.code}), using copy fallback`); + copyRecursiveSync(oldPath, newPath); + } else { + throw renameErr; + } + } } - fs.rmSync(nested, { recursive: true, force: true }); + try { + fs.rmSync(nested, { recursive: true, force: true }); + } catch (rmErr) { + console.log('[JRE] Could not remove nested JRE dir (non-critical):', rmErr.message); + } } catch (err) { - console.log('Notice: could not restructure Java directory:', err.message); + console.error('[JRE] Failed to restructure Java directory:', err.message); + // Last resort: check if java exists in a nested subdir and skip flatten + try { + const entries = fs.readdirSync(jreLatest, { withFileTypes: true }); + const nestedDir = entries.find(e => e.isDirectory() && e.name !== 'bin' && e.name !== 'lib'); + if (nestedDir) { + const nestedBin = path.join(jreLatest, nestedDir.name, 'bin', process.platform === 'win32' ? 'java.exe' : 'java'); + if (fs.existsSync(nestedBin)) { + console.log(`[JRE] Java found in nested dir: ${nestedDir.name}, leaving structure as-is`); + } + } + } catch (_) { /* ignore */ } + } +} + +function copyRecursiveSync(src, dest) { + const stat = fs.statSync(src); + if (stat.isDirectory()) { + fs.mkdirSync(dest, { recursive: true }); + for (const child of fs.readdirSync(src)) { + copyRecursiveSync(path.join(src, child), path.join(dest, child)); + } + } else { + fs.copyFileSync(src, dest); } }