Skip to content
Merged
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 @@ -36,6 +36,7 @@ public class Breakpoint implements IBreakpoint {
private int lineNumber = 0;
private int hitCount = 0;
private String condition = null;
private String logMessage = null;
private HashMap<Object, Object> propertyMap = new HashMap<>();

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber) {
Expand All @@ -55,6 +56,11 @@ public class Breakpoint implements IBreakpoint {
this.condition = condition;
}

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition, String logMessage) {
this(vm, eventHub, className, lineNumber, hitCount, condition);
this.logMessage = logMessage;
}

// IDebugResource
private List<EventRequest> requests = new ArrayList<>();
private List<Disposable> subscriptions = new ArrayList<>();
Expand Down Expand Up @@ -132,6 +138,16 @@ public void setCondition(String condition) {
this.condition = condition;
}

@Override
public void setLogMessage(String logMessage) {
this.logMessage = logMessage;
}

@Override
public String getLogMessage() {
return this.logMessage;
}

@Override
public CompletableFuture<IBreakpoint> install() {
// It's possible that different class loaders create new class with the same name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ public void terminate() {
}

@Override
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition) {
return new Breakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition);
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage) {
return new EvaluatableBreakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition, logMessage);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2018 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 org.apache.commons.lang3.StringUtils;

import com.sun.jdi.VirtualMachine;

public class EvaluatableBreakpoint extends Breakpoint implements IEvaluatableBreakpoint {
private Object compiledConditionalExpression = null;
private Object compiledLogpointExpression = null;

EvaluatableBreakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber) {
super(vm, eventHub, className, lineNumber, 0, null);
}

EvaluatableBreakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount) {
super(vm, eventHub, className, lineNumber, hitCount, null);
}

EvaluatableBreakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition) {
super(vm, eventHub, className, lineNumber, hitCount, condition);
}

EvaluatableBreakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition, String logMessage) {
super(vm, eventHub, className, lineNumber, hitCount, condition, logMessage);
}

@Override
public boolean containsEvaluatableExpression() {
return containsConditionalExpression() || containsLogpointExpression();
}

@Override
public boolean containsConditionalExpression() {
return StringUtils.isNotBlank(getCondition());
}

@Override
public boolean containsLogpointExpression() {
return StringUtils.isNotBlank(getLogMessage());
}

@Override
public void setCompiledConditionalExpression(Object compiledExpression) {
this.compiledConditionalExpression = compiledExpression;
}

@Override
public Object getCompiledConditionalExpression() {
return compiledConditionalExpression;
}

@Override
public void setCompiledLogpointExpression(Object compiledExpression) {
this.compiledLogpointExpression = compiledExpression;
}

@Override
public Object getCompiledLogpointExpression() {
return compiledLogpointExpression;
}

@Override
public void setCondition(String condition) {
super.setCondition(condition);
setCompiledConditionalExpression(null);
}

@Override
public void setLogMessage(String logMessage) {
super.setLogMessage(logMessage);
setCompiledLogpointExpression(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ public interface IBreakpoint extends IDebugResource {
String getCondition();

void setCondition(String condition);

String getLogMessage();

void setLogMessage(String logMessage);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public interface IDebugSession {
void terminate();

// breakpoints
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition);
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage);

void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2018 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;

public interface IEvaluatableBreakpoint extends IBreakpoint {
boolean containsEvaluatableExpression();

boolean containsConditionalExpression();

boolean containsLogpointExpression();

void setCompiledConditionalExpression(Object compiledExpression);

Object getCompiledConditionalExpression();

void setCompiledLogpointExpression(Object compiledExpression);

Object getCompiledLogpointExpression();
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ public class BreakpointManager {
private List<IBreakpoint> breakpoints;
private HashMap<String, HashMap<String, IBreakpoint>> sourceToBreakpoints;
private AtomicInteger nextBreakpointId = new AtomicInteger(1);
// BreakpointManager is the owner class of the breakpoint to compiled expression map, it will remove
// the breakpoint from this map if the breakpoint is removed or its condition is changed
private Map<IBreakpoint, Object> breakpointExpressionMap = new HashMap<>();

/**
* Constructor.
Expand Down Expand Up @@ -80,7 +77,6 @@ public IBreakpoint[] setBreakpoints(String source, IBreakpoint[] breakpoints, bo
} catch (Exception e) {
logger.log(Level.SEVERE, String.format("Remove breakpoint exception: %s", e.toString()), e);
}
breakpointExpressionMap.remove(bp);
this.breakpoints.remove(bp);
}
this.sourceToBreakpoints.put(source, null);
Expand Down Expand Up @@ -147,7 +143,6 @@ private void removeBreakpointsInternally(String source, IBreakpoint[] breakpoint
// Destroy the breakpoint on the debugee VM.
breakpoint.close();
this.breakpoints.remove(breakpoint);
breakpointExpressionMap.remove(breakpoint);
breakpointMap.remove(String.valueOf(breakpoint.getLineNumber()));
} catch (Exception e) {
logger.log(Level.SEVERE, String.format("Remove breakpoint exception: %s", e.toString()), e);
Expand All @@ -171,28 +166,6 @@ public IBreakpoint[] getBreakpoints(String source) {
return breakpointMap.values().toArray(new IBreakpoint[0]);
}


/**
* Get the compiled expression map with breakpoint, it will be used in JdtEvaluationProvider#evaluateForBreakpoint for storing
* the compiled expression when the first time this conditional breakpoint is hit.
*
* @return the compiled expression map
*/
public Map<IBreakpoint, Object> getBreakpointExpressionMap() {
return breakpointExpressionMap;
}

/**
* Update the condition for the specified breakpoint, and clear the compiled expression for the breakpoint.
*
* @param breakpoint the conditional breakpoint
* @param newCondition the new condition to be used.
*/
public void updateConditionCompiledExpression(IBreakpoint breakpoint, String newCondition) {
breakpoint.setCondition(newCondition);
breakpointExpressionMap.remove(breakpoint);
}

/**
* Cleanup all breakpoints and reset the breakpoint id counter.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@

package com.microsoft.java.debug.core.adapter;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

import com.microsoft.java.debug.core.IBreakpoint;
import com.microsoft.java.debug.core.IEvaluatableBreakpoint;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;

Expand Down Expand Up @@ -43,18 +42,14 @@ public interface IEvaluationProvider extends IProvider {
CompletableFuture<Value> evaluate(String expression, ThreadReference thread, int depth);

/**
* Evaluate the conditional breakpoint at the given thread and return the promise which is to be resolved/rejected when
* the evaluation finishes. The breakpointExpressionMap value should be managed by this IEvaluationProvider, avoid duplicate compilation
* on the same query when the conditional breakpoint is set inside a large loop, when the breakpoint is removed or the condition is changed,
* the external owner of breakpointExpressionMap must remove the related map entry.
* Evaluate the conditional breakpoint or logpoint at the given thread and return the promise which is to be resolved/rejected when
* the evaluation finishes.
*
* @param breakpoint The conditional breakpoint
* @param breakpoint The evaluatable breakpoint
* @param thread The jdi thread to the expression will be executed at
* @param breakpointExpressionMap The map has breakpoint as the key and the compiled expression object for next evaluation use.
* @return the evaluation result future
*/
CompletableFuture<Value> evaluateForBreakpoint(IBreakpoint breakpoint, ThreadReference thread, Map<IBreakpoint, Object> breakpointExpressionMap);

CompletableFuture<Value> evaluateForBreakpoint(IEvaluatableBreakpoint breakpoint, ThreadReference thread);

/**
* Call this method when the thread is to be resumed by user, it will first cancel ongoing evaluation tasks on specified thread and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public CompletableFuture<Messages.Response> handle(Requests.Command command, Req
caps.supportTerminateDebuggee = true;
caps.supportsCompletionsRequest = true;
caps.supportsRestartFrame = true;
caps.supportsLogPoints = true;
Types.ExceptionBreakpointFilter[] exceptionFilters = {
Types.ExceptionBreakpointFilter.UNCAUGHT_EXCEPTION_FILTER,
Types.ExceptionBreakpointFilter.CAUGHT_EXCEPTION_FILTER,
Expand Down
Loading