import * as path from "path" ; import * as vscode from "vscode" ; import { IDebugProvider , PortInfo , Cancellable } from "./debugProvider" ; import * as debugUtils from "./debugUtils" ; import * as extensionUtils from "../extensionUtils" ; import { Kubectl } from "../kubectl" ; import { IDockerfile } from "../docker/parser" ; import { Dictionary } from "../utils/dictionary" ; const defaultJavaDebuggerExtensionId = "vscjava.vscode-java-debug" ; const defaultJavaDebuggerExtension = "Debugger for Java" ; const defaultJavaDebuggerConfigType = "java" ; const defaultJavaDebugPort = "50005" ; const defaultJavaAppPort = "8080" ; const defaultJavaDebugOpts = `-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${ defaultJavaDebugPort },quiet=y` ; const javaDebugOptsRegExp = /(-agentlib|-Xrunjdwp):\S*(address=[^\s,]+)/i ; const fullJavaDebugOptsRegExp = /^java\s+.*(-agentlib|-Xrunjdwp):\S*(address=[^\s,]+)\S*/i ; export class JavaDebugProvider implements IDebugProvider { public getDebuggerType ( ) { return defaultJavaDebuggerConfigType ; } public async isDebuggerInstalled ( ) { if ( vscode . extensions . getExtension ( defaultJavaDebuggerExtensionId ) ) { return true ; } const answer = await vscode . window . showInformationMessage ( `Java debugging requires the '${ defaultJavaDebuggerExtension }' extension. Would you like to install it now?` , "Install Now" ) ; if ( answer === "Install Now" ) { return await extensionUtils . installVscodeExtension ( defaultJavaDebuggerExtensionId ) ; } return false ; } public async startDebugging ( workspaceFolder , sessionName , port , _pod , _pidToDebug ) { const debugConfiguration = { type : "java" , request : "attach" , name : sessionName , hostName : "localhost" , port } ; const currentFolder = ( vscode . workspace . workspaceFolders || [ ] ) . find ( ( folder ) => folder . name === path . basename ( workspaceFolder ) ) ; if ( ! currentFolder ) { return false ; } return await vscode . debug . startDebugging ( currentFolder , debugConfiguration ) ; } public isSupportedImage ( baseImage ) { if ( ! baseImage ) { return false ; } return baseImage . indexOf ( "java" ) >= 0 || baseImage . indexOf ( "openjdk" ) >= 0 || baseImage . indexOf ( "oracle" ) >= 0 ; } public async resolvePortsFromFile ( dockerfile , env ) { let rawDebugPortInfo ; const matches = dockerfile . searchLaunchArgs ( javaDebugOptsRegExp ) ; if ( extensionUtils . isNonEmptyArray ( matches ) ) { const addresses = matches [ 2 ] . split ( "=" ) [ 1 ] . split ( ":" ) ; rawDebugPortInfo = addresses [ addresses . length - 1 ] ; } else if ( extensionUtils . isNonEmptyArray ( dockerfile . searchLaunchArgs ( /\$\{?JAVA_OPTS\}?/ ) ) ) { env [ "JAVA_OPTS" ] = defaultJavaDebugOpts ; rawDebugPortInfo = defaultJavaDebugPort ; } else { env [ "JAVA_TOOL_OPTIONS" ] = defaultJavaDebugOpts ; rawDebugPortInfo = defaultJavaDebugPort ; } const exposedPorts = dockerfile . getExposedPorts ( ) ; const possiblePorts = exposedPorts . length ? exposedPorts . filter ( ( port ) => port !== rawDebugPortInfo ) : [ ] ; const rawAppPortInfo = await debugUtils . promptForAppPort ( possiblePorts , defaultJavaAppPort , env ) ; return { debugPort : Number ( rawDebugPortInfo ) , appPort : Number ( rawAppPortInfo ) } ; } public async resolvePortsFromContainer ( kubectl , pod , podNamespace , container ) { let rawDebugPortInfo ; const processes = await debugUtils . getProcesses ( kubectl , pod , podNamespace , container ) ; const commandLines = processes ? processes . map ( ( { command } ) => command ) : undefined ; if ( commandLines ) { for ( const commandLine of commandLines ) { const matches = commandLine . match ( fullJavaDebugOptsRegExp ) ; if ( matches && matches . length > 0 ) { const addresses = matches [ 2 ] . split ( "=" ) [ 1 ] . split ( ":" ) ; rawDebugPortInfo = addresses [ addresses . length - 1 ] ; break ; } } } if ( ! rawDebugPortInfo ) { rawDebugPortInfo = await debugUtils . promptForDebugPort ( defaultJavaDebugPort ) ; } if ( ! rawDebugPortInfo ) { return undefined ; } return { debugPort : Number ( rawDebugPortInfo ) } ; } public filterSupportedProcesses ( _processes ) { return undefined ; } public isPortRequired ( ) { return true ; } public async getDebugArgs ( ) { return { cancelled : false } ; } }