diff --git a/com.microsoft.java.debug.core/mvnw b/com.microsoft.java.debug.core/mvnw new file mode 100755 index 000000000..e96ccd5fb --- /dev/null +++ b/com.microsoft.java.debug.core/mvnw @@ -0,0 +1,227 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/com.microsoft.java.debug.core/mvnw.cmd b/com.microsoft.java.debug.core/mvnw.cmd new file mode 100644 index 000000000..019bd74d7 --- /dev/null +++ b/com.microsoft.java.debug.core/mvnw.cmd @@ -0,0 +1,143 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/com.microsoft.java.debug.core/pom.xml b/com.microsoft.java.debug.core/pom.xml index c9610d0a5..d187a136d 100644 --- a/com.microsoft.java.debug.core/pom.xml +++ b/com.microsoft.java.debug.core/pom.xml @@ -2,16 +2,47 @@ 4.0.0 - - com.microsoft.java - java-debug-parent - 0.33.0 - - com.microsoft.java.debug.core - jar + ch.epfl.scala + com-microsoft-java-debug-core ${base.name} :: Debugger Core + The Java Debug Server is an implementation of Visual Studio Code (VSCode) Debug Protocol. It can be used in Visual Studio Code to debug Java programs. + https://github.com/Microsoft/java-debug + 0.32.0+1-SNAPSHOT + jar + Java Debug Server for Visual Studio Code + UTF-8 + ${basedir}/../ + + + + Eclipse Public License 1.0 + https://github.com/Microsoft/java-debug/blob/master/LICENSE.txt + repo + + + + + + adpi2 + Adrien Piquerez + adrien.piquerez@gmail.com + "https://github.com/adpi2/" + + + + + ch.epfl.scaal + https://scala.epfl.ch/ + + + + scm:git:git://github.com/scalacenter/java-debug.git + scm:git:ssh://github.com:scalacenter/java-debug.git + https://github.com/scalacenter/java-debug/tree/main + + target target/classes @@ -22,6 +53,26 @@ org.apache.maven.plugins maven-failsafe-plugin + 2.15 + + + + integration-tests + + integration-test + verify + + + + ${failsafeArgLine} + + ${skip.integration.tests} + + + org.apache.maven.plugins @@ -35,6 +86,34 @@ org.apache.maven.plugins maven-checkstyle-plugin + 3.1.0 + + + com.puppycrawl.tools + checkstyle + 8.29 + + + com.github.sevntu-checkstyle + sevntu-checkstyle-maven-plugin + 1.24.1 + + + + ${checkstyleDir}/check_style.xml + true + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + @@ -79,7 +158,7 @@ - + default-tools.jar (,9) @@ -94,5 +173,61 @@ + + release + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + + attach-javadocs + + jar + + + + + none + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java index a56eaf695..8b9db7301 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; import com.sun.jdi.ThreadReference; import com.sun.jdi.VirtualMachine; @@ -22,10 +23,11 @@ public class DebugSession implements IDebugSession { private VirtualMachine vm; - private EventHub eventHub = new EventHub(); + private EventHub eventHub; - public DebugSession(VirtualMachine virtualMachine) { + public DebugSession(VirtualMachine virtualMachine, Logger logger) { vm = virtualMachine; + eventHub = new EventHub(logger); } @Override diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSettings.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSettings.java index e3c928332..988a2c388 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSettings.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSettings.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; import com.google.gson.JsonSyntaxException; import com.google.gson.annotations.SerializedName; @@ -23,7 +22,6 @@ import com.microsoft.java.debug.core.protocol.Requests.StepFilters; public final class DebugSettings { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); private static Set listeners = Collections.newSetFromMap(new ConcurrentHashMap()); private static DebugSettings current = new DebugSettings(); @@ -54,15 +52,11 @@ public static DebugSettings getCurrent() { * @param jsonSettings * the new settings represents in json format. */ - public void updateSettings(String jsonSettings) { - try { - DebugSettings oldSettings = current; - current = JsonUtils.fromJson(jsonSettings, DebugSettings.class); - for (IDebugSettingChangeListener listener : listeners) { - listener.update(oldSettings, current); - } - } catch (JsonSyntaxException ex) { - logger.severe(String.format("Invalid json for debugSettings: %s, %s", jsonSettings, ex.getMessage())); + public void updateSettings(String jsonSettings) throws JsonSyntaxException { + DebugSettings oldSettings = current; + current = JsonUtils.fromJson(jsonSettings, DebugSettings.class); + for (IDebugSettingChangeListener listener : listeners) { + listener.update(oldSettings, current); } } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugUtility.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugUtility.java index 1202a30f3..641765ee4 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugUtility.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugUtility.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; import org.apache.commons.lang3.StringUtils; @@ -59,7 +60,7 @@ public class DebugUtility { /** * Launch a debuggee in suspend mode. - * @see #launch(VirtualMachineManager, String, String, String, String, String, String, String[]) + * @see #launch(VirtualMachineManager, String, String, String, String, String, String, String[], Logger) */ public static IDebugSession launch(VirtualMachineManager vmManager, String mainClass, @@ -68,7 +69,8 @@ public static IDebugSession launch(VirtualMachineManager vmManager, List modulePaths, List classPaths, String cwd, - String[] envVars) + String[] envVars, + Logger logger) throws IOException, IllegalConnectorArgumentsException, VMStartException { return DebugUtility.launch(vmManager, mainClass, @@ -77,12 +79,13 @@ public static IDebugSession launch(VirtualMachineManager vmManager, String.join(File.pathSeparator, modulePaths), String.join(File.pathSeparator, classPaths), cwd, - envVars); + envVars, + logger); } /** * Launch a debuggee in suspend mode. - * @see #launch(VirtualMachineManager, String, String, String, String, String, String, String[], String) + * @see #launch(VirtualMachineManager, String, String, String, String, String, String, String[], String, Logger) */ public static IDebugSession launch(VirtualMachineManager vmManager, String mainClass, @@ -92,7 +95,8 @@ public static IDebugSession launch(VirtualMachineManager vmManager, List classPaths, String cwd, String[] envVars, - String javaExec) + String javaExec, + Logger logger) throws IOException, IllegalConnectorArgumentsException, VMStartException { return DebugUtility.launch(vmManager, mainClass, @@ -102,7 +106,8 @@ public static IDebugSession launch(VirtualMachineManager vmManager, String.join(File.pathSeparator, classPaths), cwd, envVars, - javaExec); + javaExec, + logger); } /** @@ -141,9 +146,10 @@ public static IDebugSession launch(VirtualMachineManager vmManager, String modulePaths, String classPaths, String cwd, - String[] envVars) + String[] envVars, + Logger logger) throws IOException, IllegalConnectorArgumentsException, VMStartException { - return launch(vmManager, mainClass, programArguments, vmArguments, modulePaths, classPaths, cwd, envVars, null); + return launch(vmManager, mainClass, programArguments, vmArguments, modulePaths, classPaths, cwd, envVars, null, logger); } /** @@ -185,7 +191,8 @@ public static IDebugSession launch(VirtualMachineManager vmManager, String classPaths, String cwd, String[] envVars, - String javaExec) + String javaExec, + Logger logger) throws IOException, IllegalConnectorArgumentsException, VMStartException { List connectors = vmManager.launchingConnectors(); LaunchingConnector connector = connectors.get(0); @@ -252,7 +259,7 @@ public static IDebugSession launch(VirtualMachineManager vmManager, // Without this line, it throws ObjectCollectedException in ExceptionRequest.enable(). // See https://github.com/Microsoft/java-debug/issues/23 vm.version(); - return new DebugSession(vm); + return new DebugSession(vm, logger); } private static boolean isValidJavaExec(String javaExec) { @@ -285,7 +292,7 @@ private static boolean isValidJavaExec(String javaExec) { * @throws IllegalConnectorArgumentsException * when one of the connector arguments is invalid. */ - public static IDebugSession attach(VirtualMachineManager vmManager, String hostName, int port, int attachTimeout) + public static IDebugSession attach(VirtualMachineManager vmManager, String hostName, int port, int attachTimeout, Logger logger) throws IOException, IllegalConnectorArgumentsException { List connectors = vmManager.attachingConnectors(); AttachingConnector connector = connectors.get(0); @@ -301,7 +308,7 @@ public static IDebugSession attach(VirtualMachineManager vmManager, String hostN arguments.get(HOSTNAME).setValue(hostName); arguments.get(PORT).setValue(String.valueOf(port)); arguments.get(TIMEOUT).setValue(String.valueOf(attachTimeout)); - return new DebugSession(connector.attach(arguments)); + return new DebugSession(connector.attach(arguments), logger); } /** @@ -678,8 +685,7 @@ private static List parseArgumentsNonWindows(String args) { * This piece of code is mainly copied from * https://github.com/eclipse/eclipse.platform.debug/blob/master/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java#L1264 * - * @param args - * the command line arguments as a single string. + * @param args the command line arguments as a single string. * @return the individual arguments */ private static List parseArgumentsWindows(String args) { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/EventHub.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/EventHub.java index 712ed03ba..a16f3f667 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/EventHub.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/EventHub.java @@ -31,9 +31,13 @@ import io.reactivex.subjects.PublishSubject; public class EventHub implements IEventHub { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; private PublishSubject subject = PublishSubject.create(); + public EventHub(Logger logger) { + this.logger = logger; + } + @Override public Observable events() { return subject; diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/LoggerFactory.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/LoggerFactory.java new file mode 100644 index 000000000..8d75df046 --- /dev/null +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/LoggerFactory.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2017 Microsoft Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Microsoft Corporation - initial API and implementation + *******************************************************************************/ + +package com.microsoft.java.debug.core; + +import java.util.logging.Logger; + +@FunctionalInterface +public interface LoggerFactory { + Logger create(String name); +} diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/UsageDataSession.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/UsageDataSession.java index e54727b66..77c371434 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/UsageDataSession.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/UsageDataSession.java @@ -1,13 +1,13 @@ /******************************************************************************* -* Copyright (c) 2017 Microsoft Corporation and others. -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* Microsoft Corporation - initial API and implementation -*******************************************************************************/ + * Copyright (c) 2017 Microsoft Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Microsoft Corporation - initial API and implementation + *******************************************************************************/ package com.microsoft.java.debug.core; @@ -28,8 +28,8 @@ import com.sun.jdi.event.Event; public class UsageDataSession { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); - private static final Logger usageDataLogger = Logger.getLogger(Configuration.USAGE_DATA_LOGGER_NAME); + private final Logger logger; + private final Logger usageDataLogger; private static final long RESPONSE_MAX_DELAY_MS = 1000; private static final ThreadLocal threadLocal = new InheritableThreadLocal<>(); @@ -48,7 +48,16 @@ public static String getSessionGuid() { return threadLocal.get() == null ? "" : threadLocal.get().sessionGuid; } - public UsageDataSession() { + public static UsageDataSession currentSession() { + return threadLocal.get(); + } + + /** + * Constructor. + */ + public UsageDataSession(Logger logger, LoggerFactory factory) { + this.logger = logger; + this.usageDataLogger = factory.create(Configuration.USAGE_DATA_LOGGER_NAME); threadLocal.set(this); } @@ -153,16 +162,13 @@ public void submitUsageData() { /** * Record JDI event. */ - public static void recordEvent(Event event) { + public void recordEvent(Event event) { try { - UsageDataSession currentSession = threadLocal.get(); - if (currentSession != null) { - Map eventEntry = new HashMap<>(); - eventEntry.put("timestamp", String.valueOf(System.currentTimeMillis())); - eventEntry.put("event", event.toString()); - synchronized (currentSession.eventList) { - currentSession.eventList.add(JsonUtils.toJson(eventEntry)); - } + Map eventEntry = new HashMap<>(); + eventEntry.put("timestamp", String.valueOf(System.currentTimeMillis())); + eventEntry.put("event", event.toString()); + synchronized (eventList) { + eventList.add(JsonUtils.toJson(eventEntry)); } } catch (Exception e) { logger.log(Level.SEVERE, String.format("Exception on recording event: %s.", e.toString()), e); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java index 78898df73..bc6297b73 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java @@ -23,12 +23,11 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.IBreakpoint; import com.microsoft.java.debug.core.IWatchpoint; public class BreakpointManager implements IBreakpointManager { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; /** * A collection of breakpoints registered with this manager. */ @@ -40,7 +39,8 @@ public class BreakpointManager implements IBreakpointManager { /** * Constructor. */ - public BreakpointManager() { + public BreakpointManager(Logger logger) { + this.logger = logger; this.breakpoints = Collections.synchronizedList(new ArrayList<>(5)); this.sourceToBreakpoints = new HashMap<>(); this.watchpoints = new HashMap<>(); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java index 4342c48d3..5bdd5eef7 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java @@ -19,7 +19,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.adapter.handler.AttachRequestHandler; import com.microsoft.java.debug.core.adapter.handler.CompletionsHandler; import com.microsoft.java.debug.core.adapter.handler.ConfigurationDoneRequestHandler; @@ -51,7 +50,7 @@ import com.microsoft.java.debug.core.protocol.Requests.Command; public class DebugAdapter implements IDebugAdapter { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; private IDebugAdapterContext debugContext = null; private Map> requestHandlersForDebug = null; @@ -60,8 +59,9 @@ public class DebugAdapter implements IDebugAdapter { /** * Constructor. */ - public DebugAdapter(IProtocolServer server, IProviderContext providerContext) { - this.debugContext = new DebugAdapterContext(server, providerContext); + public DebugAdapter(IProtocolServer server, IProviderContext providerContext, Logger logger) { + this.logger = logger; + this.debugContext = new DebugAdapterContext(server, providerContext, logger); requestHandlersForDebug = new HashMap<>(); requestHandlersForNoDebug = new HashMap<>(); initialize(); @@ -101,33 +101,33 @@ private void initialize() { // Register request handlers. // When there are multiple handlers registered for the same request, follow the rule "first register, first execute". registerHandler(new InitializeRequestHandler()); - registerHandler(new LaunchRequestHandler()); + registerHandler(new LaunchRequestHandler(logger)); // DEBUG node only - registerHandlerForDebug(new AttachRequestHandler()); - registerHandlerForDebug(new ConfigurationDoneRequestHandler()); - registerHandlerForDebug(new DisconnectRequestHandler()); - registerHandlerForDebug(new SetBreakpointsRequestHandler()); + registerHandlerForDebug(new AttachRequestHandler(logger)); + registerHandlerForDebug(new ConfigurationDoneRequestHandler(logger)); + registerHandlerForDebug(new DisconnectRequestHandler(logger)); + registerHandlerForDebug(new SetBreakpointsRequestHandler(logger)); registerHandlerForDebug(new SetExceptionBreakpointsRequestHandler()); registerHandlerForDebug(new SourceRequestHandler()); registerHandlerForDebug(new ThreadsRequestHandler()); registerHandlerForDebug(new StepRequestHandler()); registerHandlerForDebug(new StackTraceRequestHandler()); registerHandlerForDebug(new ScopesRequestHandler()); - registerHandlerForDebug(new VariablesRequestHandler()); + registerHandlerForDebug(new VariablesRequestHandler(logger)); registerHandlerForDebug(new SetVariableRequestHandler()); - registerHandlerForDebug(new EvaluateRequestHandler()); + registerHandlerForDebug(new EvaluateRequestHandler(logger)); registerHandlerForDebug(new HotCodeReplaceHandler()); registerHandlerForDebug(new RestartFrameHandler()); registerHandlerForDebug(new CompletionsHandler()); - registerHandlerForDebug(new ExceptionInfoRequestHandler()); + registerHandlerForDebug(new ExceptionInfoRequestHandler(logger)); registerHandlerForDebug(new DataBreakpointInfoRequestHandler()); - registerHandlerForDebug(new SetDataBreakpointsRequestHandler()); - registerHandlerForDebug(new InlineValuesRequestHandler()); + registerHandlerForDebug(new SetDataBreakpointsRequestHandler(logger)); + registerHandlerForDebug(new InlineValuesRequestHandler(logger)); registerHandlerForDebug(new RefreshVariablesHandler()); // NO_DEBUG mode only - registerHandlerForNoDebug(new DisconnectRequestWithoutDebuggingHandler()); + registerHandlerForNoDebug(new DisconnectRequestWithoutDebuggingHandler(logger)); } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapterContext.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapterContext.java index 395d39ec6..a014f04d6 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapterContext.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapterContext.java @@ -18,6 +18,7 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.IDebugSession; @@ -60,12 +61,14 @@ public class DebugAdapterContext implements IDebugAdapterContext { private IStackFrameManager stackFrameManager = new StackFrameManager(); private IExceptionManager exceptionManager = new ExceptionManager(); - private IBreakpointManager breakpointManager = new BreakpointManager(); + private IBreakpointManager breakpointManager; private IStepResultManager stepResultManager = new StepResultManager(); - public DebugAdapterContext(IProtocolServer server, IProviderContext providerContext) { + public DebugAdapterContext(IProtocolServer server, IProviderContext providerContext, Logger logger) { this.providerContext = providerContext; this.server = server; + this.breakpointManager = new BreakpointManager(logger); + } @Override diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ProtocolServer.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ProtocolServer.java index 0526293b9..ac51d1979 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ProtocolServer.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ProtocolServer.java @@ -21,6 +21,7 @@ import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; +import com.microsoft.java.debug.core.LoggerFactory; import com.microsoft.java.debug.core.UsageDataSession; import com.microsoft.java.debug.core.protocol.AbstractProtocolServer; import com.microsoft.java.debug.core.protocol.Events.DebugEvent; @@ -29,15 +30,23 @@ import com.sun.jdi.VMDisconnectedException; public class ProtocolServer extends AbstractProtocolServer { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); - private IDebugAdapter debugAdapter; - private UsageDataSession usageDataSession = new UsageDataSession(); + private UsageDataSession usageDataSession; private Object lock = new Object(); private boolean isDispatchingRequest = false; private ConcurrentLinkedQueue eventQueue = new ConcurrentLinkedQueue<>(); + + /** + * Constructor. + */ + public ProtocolServer(InputStream input, OutputStream output, IProviderContext context, LoggerFactory factory) { + super(input, output, factory.create(Configuration.LOGGER_NAME)); + debugAdapter = new DebugAdapter(this, context, logger); + usageDataSession = new UsageDataSession(logger, factory); + } + /** * Constructs a protocol server instance based on the given input stream and output stream. * @param input @@ -48,8 +57,7 @@ public class ProtocolServer extends AbstractProtocolServer { * provider context for a series of provider implementation */ public ProtocolServer(InputStream input, OutputStream output, IProviderContext context) { - super(input, output); - debugAdapter = new DebugAdapter(this, context); + this(input, output, context, Logger::getLogger); } /** diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractDisconnectRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractDisconnectRequestHandler.java index fd5c68d6c..44d8045ee 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractDisconnectRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractDisconnectRequestHandler.java @@ -20,7 +20,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; import com.microsoft.java.debug.core.adapter.IDebugRequestHandler; import com.microsoft.java.debug.core.adapter.IHotCodeReplaceProvider; @@ -30,7 +29,11 @@ import com.microsoft.java.debug.core.protocol.Requests.Command; public abstract class AbstractDisconnectRequestHandler implements IDebugRequestHandler { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; + + public AbstractDisconnectRequestHandler(Logger logger) { + this.logger = logger; + } @Override public List getTargetCommands() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractLaunchDelegate.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractLaunchDelegate.java new file mode 100644 index 000000000..e35a779ee --- /dev/null +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AbstractLaunchDelegate.java @@ -0,0 +1,54 @@ +/******************************************************************************* +* Copyright (c) 2017 Microsoft Corporation and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Microsoft Corporation - initial API and implementation +*******************************************************************************/ + +package com.microsoft.java.debug.core.adapter.handler; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import com.microsoft.java.debug.core.protocol.Requests; + +abstract class AbstractLaunchDelegate implements ILaunchDelegate { + protected final Logger logger; + + protected AbstractLaunchDelegate(Logger logger) { + this.logger = logger; + } + + protected String[] constructEnvironmentVariables(Requests.LaunchArguments launchArguments) { + String[] envVars = null; + if (launchArguments.env != null && !launchArguments.env.isEmpty()) { + Map environment = new HashMap<>(System.getenv()); + List duplicated = new ArrayList<>(); + for (Map.Entry entry : launchArguments.env.entrySet()) { + if (environment.containsKey(entry.getKey())) { + duplicated.add(entry.getKey()); + } + environment.put(entry.getKey(), entry.getValue()); + } + // For duplicated variables, show a warning message. + if (!duplicated.isEmpty()) { + logger.warning(String.format("There are duplicated environment variables. The values specified in launch.json will be used. " + + "Here are the duplicated entries: %s.", String.join(",", duplicated))); + } + + envVars = new String[environment.size()]; + int i = 0; + for (Map.Entry entry : environment.entrySet()) { + envVars[i++] = entry.getKey() + "=" + entry.getValue(); + } + } + return envVars; + } +} diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java index 7069bc39e..006973f6e 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java @@ -20,7 +20,6 @@ import java.util.concurrent.CompletableFuture; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugUtility; import com.microsoft.java.debug.core.IDebugSession; import com.microsoft.java.debug.core.adapter.AdapterUtils; @@ -43,9 +42,13 @@ import org.apache.commons.lang3.StringUtils; public class AttachRequestHandler implements IDebugRequestHandler { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; private VMHandler vmHandler = new VMHandler(); + public AttachRequestHandler(Logger logger) { + this.logger = logger; + } + @Override public List getTargetCommands() { return Arrays.asList(Command.ATTACH); @@ -65,7 +68,7 @@ public CompletableFuture handle(Command command, Arguments arguments, try { logger.info(String.format("Trying to attach to remote debuggee VM %s:%d .", attachArguments.hostName, attachArguments.port)); debugSession = DebugUtility.attach(vmProvider.getVirtualMachineManager(), attachArguments.hostName, attachArguments.port, - attachArguments.timeout); + attachArguments.timeout, logger); context.setDebugSession(debugSession); vmHandler.connectVirtualMachine(debugSession.getVM()); logger.info("Attaching to debuggee VM succeeded."); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ConfigurationDoneRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ConfigurationDoneRequestHandler.java index 9cd3aa446..050e37db8 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ConfigurationDoneRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ConfigurationDoneRequestHandler.java @@ -16,7 +16,6 @@ import java.util.concurrent.CompletableFuture; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugEvent; import com.microsoft.java.debug.core.DebugUtility; import com.microsoft.java.debug.core.IDebugSession; @@ -43,9 +42,13 @@ import com.sun.jdi.event.VMStartEvent; public class ConfigurationDoneRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; private VMHandler vmHandler = new VMHandler(); + public ConfigurationDoneRequestHandler(Logger logger) { + this.logger = logger; + } + @Override public List getTargetCommands() { return Arrays.asList(Command.CONFIGURATIONDONE); @@ -125,7 +128,10 @@ private void handleDebugEvent(DebugEvent debugEvent, IDebugSession debugSession, // record events of important types only, to get rid of noises. if (isImportantEvent) { - UsageDataSession.recordEvent(event); + UsageDataSession session = UsageDataSession.currentSession(); + if (session != null) { + session.recordEvent(event); + } } } } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestHandler.java index a615e8963..bd42e8a50 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestHandler.java @@ -11,6 +11,8 @@ package com.microsoft.java.debug.core.adapter.handler; +import java.util.logging.Logger; + import com.microsoft.java.debug.core.IDebugSession; import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; import com.microsoft.java.debug.core.protocol.Messages.Response; @@ -18,8 +20,13 @@ import com.microsoft.java.debug.core.protocol.Requests.Command; import com.microsoft.java.debug.core.protocol.Requests.DisconnectArguments; + public class DisconnectRequestHandler extends AbstractDisconnectRequestHandler { + public DisconnectRequestHandler(Logger logger) { + super(logger); + } + @Override public void destroyDebugSession(Command command, Arguments arguments, Response response, IDebugAdapterContext context) { DisconnectArguments disconnectArguments = (DisconnectArguments) arguments; diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestWithoutDebuggingHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestWithoutDebuggingHandler.java index bb56d4052..8d33d04bd 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestWithoutDebuggingHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/DisconnectRequestWithoutDebuggingHandler.java @@ -11,14 +11,21 @@ package com.microsoft.java.debug.core.adapter.handler; +import java.util.logging.Logger; + import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; import com.microsoft.java.debug.core.protocol.Messages.Response; import com.microsoft.java.debug.core.protocol.Requests.Arguments; import com.microsoft.java.debug.core.protocol.Requests.Command; import com.microsoft.java.debug.core.protocol.Requests.DisconnectArguments; + public class DisconnectRequestWithoutDebuggingHandler extends AbstractDisconnectRequestHandler { + public DisconnectRequestWithoutDebuggingHandler(Logger logger) { + super(logger); + } + @Override public void destroyDebugSession(Command command, Arguments arguments, Response response, IDebugAdapterContext context) { DisconnectArguments disconnectArguments = (DisconnectArguments) arguments; diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/EvaluateRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/EvaluateRequestHandler.java index 9cf99742d..bd0930931 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/EvaluateRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/EvaluateRequestHandler.java @@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.adapter.AdapterUtils; @@ -49,7 +48,11 @@ import com.sun.jdi.VoidValue; public class EvaluateRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; + + public EvaluateRequestHandler(Logger logger) { + this.logger = logger; + } @Override public List getTargetCommands() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ExceptionInfoRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ExceptionInfoRequestHandler.java index 13456029d..e1b3f97ee 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ExceptionInfoRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ExceptionInfoRequestHandler.java @@ -19,7 +19,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugUtility; import com.microsoft.java.debug.core.JdiExceptionReference; import com.microsoft.java.debug.core.adapter.AdapterUtils; @@ -42,7 +41,11 @@ import com.sun.jdi.Value; public class ExceptionInfoRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; + + public ExceptionInfoRequestHandler(Logger logger) { + this.logger = logger; + } @Override public List getTargetCommands() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InlineValuesRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InlineValuesRequestHandler.java index e9697f899..653210c5f 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InlineValuesRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InlineValuesRequestHandler.java @@ -22,7 +22,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; import com.microsoft.java.debug.core.adapter.IDebugRequestHandler; @@ -53,7 +52,11 @@ import org.apache.commons.lang3.math.NumberUtils; public class InlineValuesRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; + + public InlineValuesRequestHandler(Logger logger) { + this.logger = logger; + } @Override public List getTargetCommands() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchRequestHandler.java index 7d76e1ffd..c5f6bd611 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchRequestHandler.java @@ -21,10 +21,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -37,7 +34,6 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.DebugUtility; @@ -63,11 +59,15 @@ import com.sun.jdi.event.VMDisconnectEvent; public class LaunchRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; protected static final long RUNINTERMINAL_TIMEOUT = 10 * 1000; protected ILaunchDelegate activeLaunchHandler; private CompletableFuture waitForDebuggeeConsole = new CompletableFuture<>(); + public LaunchRequestHandler(Logger logger) { + this.logger = logger; + } + @Override public List getTargetCommands() { return Arrays.asList(Command.LAUNCH); @@ -76,8 +76,9 @@ public List getTargetCommands() { @Override public CompletableFuture handle(Command command, Arguments arguments, Response response, IDebugAdapterContext context) { LaunchArguments launchArguments = (LaunchArguments) arguments; - activeLaunchHandler = launchArguments.noDebug ? new LaunchWithoutDebuggingDelegate((daContext) -> handleTerminatedEvent(daContext)) - : new LaunchWithDebuggingDelegate(); + activeLaunchHandler = launchArguments.noDebug + ? new LaunchWithoutDebuggingDelegate(this::handleTerminatedEvent, logger) + : new LaunchWithDebuggingDelegate(logger); return handleLaunchCommand(arguments, response, context); } @@ -287,32 +288,6 @@ private static OutputEvent convertToOutputEvent(String message, Category categor return new OutputEvent(category, message); } - protected static String[] constructEnvironmentVariables(LaunchArguments launchArguments) { - String[] envVars = null; - if (launchArguments.env != null && !launchArguments.env.isEmpty()) { - Map environment = new HashMap<>(System.getenv()); - List duplicated = new ArrayList<>(); - for (Entry entry : launchArguments.env.entrySet()) { - if (environment.containsKey(entry.getKey())) { - duplicated.add(entry.getKey()); - } - environment.put(entry.getKey(), entry.getValue()); - } - // For duplicated variables, show a warning message. - if (!duplicated.isEmpty()) { - logger.warning(String.format("There are duplicated environment variables. The values specified in launch.json will be used. " - + "Here are the duplicated entries: %s.", String.join(",", duplicated))); - } - - envVars = new String[environment.size()]; - int i = 0; - for (Entry entry : environment.entrySet()) { - envVars[i++] = entry.getKey() + "=" + entry.getValue(); - } - } - return envVars; - } - public static String parseMainClassWithoutModuleName(String mainClass) { int index = mainClass.indexOf('/'); return mainClass.substring(index + 1); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithDebuggingDelegate.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithDebuggingDelegate.java index 138455025..3ebcadd4b 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithDebuggingDelegate.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithDebuggingDelegate.java @@ -24,7 +24,6 @@ import org.apache.commons.lang3.SystemUtils; import com.google.gson.JsonObject; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; import com.microsoft.java.debug.core.DebugSession; import com.microsoft.java.debug.core.DebugUtility; @@ -52,14 +51,16 @@ import com.sun.jdi.connect.TransportTimeoutException; import com.sun.jdi.connect.VMStartException; -public class LaunchWithDebuggingDelegate implements ILaunchDelegate { - - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); +public class LaunchWithDebuggingDelegate extends AbstractLaunchDelegate { private static final int ATTACH_TERMINAL_TIMEOUT = 20 * 1000; private static final String TERMINAL_TITLE = "Java Debug Console"; protected static final long RUNINTERMINAL_TIMEOUT = 10 * 1000; private VMHandler vmHandler = new VMHandler(); + public LaunchWithDebuggingDelegate(Logger logger) { + super(logger); + } + @Override public CompletableFuture launchInTerminal(LaunchArguments launchArguments, Response response, IDebugAdapterContext context) { CompletableFuture resultFuture = new CompletableFuture<>(); @@ -104,7 +105,7 @@ public CompletableFuture launchInTerminal(LaunchArguments launchArgume try { VirtualMachine vm = listenConnector.accept(args); vmHandler.connectVirtualMachine(vm); - context.setDebugSession(new DebugSession(vm)); + context.setDebugSession(new DebugSession(vm, logger)); logger.info("Launching debuggee in terminal console succeeded."); resultFuture.complete(response); } catch (TransportTimeoutException e) { @@ -185,8 +186,9 @@ public Process launch(LaunchArguments launchArguments, IDebugAdapterContext cont Arrays.asList(launchArguments.modulePaths), Arrays.asList(launchArguments.classPaths), launchArguments.cwd, - LaunchRequestHandler.constructEnvironmentVariables(launchArguments), - launchArguments.javaExec); + constructEnvironmentVariables(launchArguments), + launchArguments.javaExec, + logger); context.setDebugSession(debugSession); vmHandler.connectVirtualMachine(debugSession.getVM()); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithoutDebuggingDelegate.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithoutDebuggingDelegate.java index c993dc5f1..55cf2a7f9 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithoutDebuggingDelegate.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchWithoutDebuggingDelegate.java @@ -21,7 +21,6 @@ import java.util.logging.Logger; import com.google.gson.JsonObject; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; import com.microsoft.java.debug.core.adapter.ErrorCode; import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; @@ -36,13 +35,13 @@ import com.sun.jdi.connect.IllegalConnectorArgumentsException; import com.sun.jdi.connect.VMStartException; -public class LaunchWithoutDebuggingDelegate implements ILaunchDelegate { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); +public class LaunchWithoutDebuggingDelegate extends AbstractLaunchDelegate { protected static final String TERMINAL_TITLE = "Java Process Console"; protected static final long RUNINTERMINAL_TIMEOUT = 10 * 1000; private Consumer terminateHandler; - public LaunchWithoutDebuggingDelegate(Consumer terminateHandler) { + public LaunchWithoutDebuggingDelegate(Consumer terminateHandler, Logger logger) { + super(logger); this.terminateHandler = terminateHandler; } @@ -54,7 +53,7 @@ public Process launch(LaunchArguments launchArguments, IDebugAdapterContext cont if (launchArguments.cwd != null && Files.isDirectory(Paths.get(launchArguments.cwd))) { workingDir = new File(launchArguments.cwd); } - Process debuggeeProcess = Runtime.getRuntime().exec(cmds, LaunchRequestHandler.constructEnvironmentVariables(launchArguments), + Process debuggeeProcess = Runtime.getRuntime().exec(cmds, constructEnvironmentVariables(launchArguments), workingDir); new Thread() { public void run() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java index fe246a61e..29f4b697f 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java @@ -21,7 +21,6 @@ import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugException; import com.microsoft.java.debug.core.IBreakpoint; import com.microsoft.java.debug.core.IDebugSession; @@ -53,11 +52,14 @@ import com.sun.jdi.event.StepEvent; public class SetBreakpointsRequestHandler implements IDebugRequestHandler { - - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + private final Logger logger; private boolean registered = false; + public SetBreakpointsRequestHandler(Logger logger) { + this.logger = logger; + } + @Override public List getTargetCommands() { return Arrays.asList(Command.SETBREAKPOINTS); @@ -191,7 +193,7 @@ private void registerBreakpointHandler(IDebugAdapterContext context) { if (expressionBP != null) { CompletableFuture.runAsync(() -> { engine.evaluateForBreakpoint((IEvaluatableBreakpoint) expressionBP, bpThread).whenComplete((value, ex) -> { - boolean resume = handleEvaluationResult(context, bpThread, (IEvaluatableBreakpoint) expressionBP, value, ex); + boolean resume = handleEvaluationResult(context, bpThread, (IEvaluatableBreakpoint) expressionBP, value, ex, logger); // Clear the evaluation environment caused by above evaluation. engine.clearState(bpThread); @@ -215,7 +217,7 @@ private void registerBreakpointHandler(IDebugAdapterContext context) { * Check whether the condition expression is satisfied, and return a boolean value to determine to resume the thread or not. */ public static boolean handleEvaluationResult(IDebugAdapterContext context, ThreadReference bpThread, IEvaluatableBreakpoint breakpoint, - Value value, Throwable ex) { + Value value, Throwable ex, Logger logger) { if (StringUtils.isNotBlank(breakpoint.getLogMessage())) { if (ex != null) { logger.log(Level.SEVERE, String.format("[Logpoint]: %s", ex.getMessage() != null ? ex.getMessage() : ex.toString()), ex); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetDataBreakpointsRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetDataBreakpointsRequestHandler.java index be15852e4..49f69129f 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetDataBreakpointsRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetDataBreakpointsRequestHandler.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; @@ -43,8 +44,14 @@ import com.sun.jdi.event.WatchpointEvent; public class SetDataBreakpointsRequestHandler implements IDebugRequestHandler { + private final Logger logger; + private boolean registered = false; + public SetDataBreakpointsRequestHandler(Logger logger) { + this.logger = logger; + } + @Override public List getTargetCommands() { return Arrays.asList(Command.SETDATABREAKPOINTS); @@ -144,7 +151,7 @@ private void registerWatchpointHandler(IDebugAdapterContext context) { CompletableFuture.runAsync(() -> { engine.evaluateForBreakpoint((IEvaluatableBreakpoint) watchpoint, bpThread).whenComplete((value, ex) -> { boolean resume = SetBreakpointsRequestHandler.handleEvaluationResult( - context, bpThread, (IEvaluatableBreakpoint) watchpoint, value, ex); + context, bpThread, (IEvaluatableBreakpoint) watchpoint, value, ex, logger); // Clear the evaluation environment caused by above evaluation. engine.clearState(bpThread); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/VariablesRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/VariablesRequestHandler.java index 26a0f7124..d6f9f1ca4 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/VariablesRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/VariablesRequestHandler.java @@ -24,7 +24,6 @@ import java.util.logging.Logger; import java.util.stream.Collectors; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.JdiMethodResult; import com.microsoft.java.debug.core.adapter.AdapterUtils; @@ -60,7 +59,11 @@ import com.sun.jdi.Value; public class VariablesRequestHandler implements IDebugRequestHandler { - protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); + protected final Logger logger; + + public VariablesRequestHandler(Logger logger) { + this.logger = logger; + } @Override public List getTargetCommands() { diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/variables/VariableUtils.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/variables/VariableUtils.java index d53e2705c..3d161decc 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/variables/VariableUtils.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/variables/VariableUtils.java @@ -16,11 +16,8 @@ import java.util.Map; import java.util.Objects; import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; -import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.DebugSettings; import com.microsoft.java.debug.core.adapter.formatter.NumericFormatEnum; import com.microsoft.java.debug.core.adapter.formatter.NumericFormatter; @@ -41,8 +38,6 @@ import com.sun.jdi.Value; public abstract class VariableUtils { - private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); - /** * Test whether the value has referenced objects. * @@ -98,7 +93,6 @@ public static List listFieldVariables(ObjectReference obj, boolean inc } return a.name().compareToIgnoreCase(b.name()); } catch (Exception e) { - logger.log(Level.SEVERE, String.format("Cannot sort fields: %s", e), e); return -1; } }).collect(Collectors.toList()); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/AbstractProtocolServer.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/AbstractProtocolServer.java index 9bec3c228..aa6fc7c69 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/AbstractProtocolServer.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/AbstractProtocolServer.java @@ -40,7 +40,7 @@ import io.reactivex.subjects.PublishSubject; public abstract class AbstractProtocolServer implements IProtocolServer { - private static final Logger logger = Logger.getLogger("java-debug"); + protected final Logger logger; private static final int BUFFER_SIZE = 4096; private static final String TWO_CRLF = "\r\n\r\n"; private static final Pattern CONTENT_LENGTH_MATCHER = Pattern.compile("Content-Length: (\\d+)"); @@ -67,7 +67,8 @@ public abstract class AbstractProtocolServer implements IProtocolServer { * @param output * the output stream */ - public AbstractProtocolServer(InputStream input, OutputStream output) { + public AbstractProtocolServer(InputStream input, OutputStream output, Logger logger) { + this.logger = logger; this.reader = new BufferedReader(new InputStreamReader(input, PROTOCOL_ENCODING)); this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, PROTOCOL_ENCODING))); this.contentLength = -1; diff --git a/com.microsoft.java.debug.core/src/test/java/com/microsoft/java/debug/core/DebugSessionFactory.java b/com.microsoft.java.debug.core/src/test/java/com/microsoft/java/debug/core/DebugSessionFactory.java index 9589c9bdc..96156e8bf 100644 --- a/com.microsoft.java.debug.core/src/test/java/com/microsoft/java/debug/core/DebugSessionFactory.java +++ b/com.microsoft.java.debug.core/src/test/java/com/microsoft/java/debug/core/DebugSessionFactory.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; import org.apache.commons.io.FileUtils; @@ -27,6 +28,7 @@ import com.sun.jdi.event.VMDisconnectEvent; public class DebugSessionFactory { + private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME); private static final String TEST_ROOT = "../com.microsoft.java.debug.test/project"; private static String rootPath = new File(TEST_ROOT).getAbsolutePath(); private static Set readyForLaunchProjects = new HashSet<>(); @@ -52,7 +54,7 @@ public static IDebugSession getDebugSession(String projectName, String mainClass String projectRoot = new File(rootPath, name).getAbsolutePath(); try { final IDebugSession debugSession = DebugUtility.launch(Bootstrap.virtualMachineManager(), mainClass, "", "", - null, new File(projectRoot, "bin").getAbsolutePath(), null, null); + null, new File(projectRoot, "bin").getAbsolutePath(), null, null, logger); debugSession.getEventHub().events().subscribe(debugEvent -> { if (debugEvent.event instanceof VMDisconnectEvent) { try {