blob: 06371bdf1fdf3e72b725f060167ea0052afc6653 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ant.internal.launching.runtime.logger;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.Location;
import org.eclipse.ant.internal.launching.debug.AntDebugState;
import org.eclipse.ant.internal.launching.debug.IAntDebugController;
import org.eclipse.ant.internal.launching.debug.IDebugBuildLogger;
import org.eclipse.ant.internal.launching.debug.model.AntDebugTarget;
import org.eclipse.ant.internal.launching.debug.model.AntThread;
import org.eclipse.ant.internal.launching.launchConfigurations.AntProcess;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.debug.core.model.IProcess;
public class AntProcessDebugBuildLogger extends AntProcessBuildLogger implements IAntDebugController, IDebugBuildLogger {
private AntDebugState fDebugState = null;
private List<IBreakpoint> fBreakpoints = null;
private AntDebugTarget fAntDebugTarget;
private boolean fResumed = false;
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.BuildListener#buildStarted(org.apache.tools.ant.BuildEvent)
*/
@Override
public void buildStarted(BuildEvent event) {
fDebugState = new AntDebugState(this);
super.buildStarted(event);
IProcess process = getAntProcess(fProcessId);
ILaunch launch = process.getLaunch();
fAntDebugTarget = new AntDebugTarget(launch, process, this);
launch.addDebugTarget(fAntDebugTarget);
fAntDebugTarget.buildStarted();
fDebugState.buildStarted();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.launching.runtime.logger.AntProcessBuildLogger#buildFinished(org.apache.tools.ant.BuildEvent)
*/
@Override
public void buildFinished(BuildEvent event) {
super.buildFinished(event);
cleanup();
}
/**
* Cleans up all held memory. <br>
* <br>
* Called from {@link #buildFinished(BuildEvent)} and {@link #terminate()}
*
* @since 1.0.1
*/
void cleanup() {
if (fAntDebugTarget != null) {
IProcess process = getAntProcess(fProcessId);
if (process != null) {
ILaunch launch = process.getLaunch();
launch.removeDebugTarget(fAntDebugTarget);
}
}
if (fDebugState != null) {
fDebugState.buildFinished();
}
if (fBreakpoints != null) {
fBreakpoints.clear();
}
}
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.BuildListener#taskFinished(org.apache.tools.ant.BuildEvent)
*/
@Override
public void taskFinished(BuildEvent event) {
super.taskFinished(event);
fDebugState.taskFinished();
}
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.BuildListener#taskStarted(org.apache.tools.ant.BuildEvent)
*/
@Override
public void taskStarted(BuildEvent event) {
super.taskStarted(event);
fDebugState.taskStarted(event);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.antsupport.logger.util.IDebugBuildLogger#waitIfSuspended()
*/
@Override
public synchronized void waitIfSuspended() {
fResumed = false;
IBreakpoint breakpoint = breakpointAtLineNumber(fDebugState.getBreakpointLocation());
if (breakpoint != null) {
fAntDebugTarget.breakpointHit(breakpoint);
try {
while (!fResumed) {
wait(500);
checkCancelled();
}
}
catch (InterruptedException e) {
// do nothing
}
} else if (fDebugState.getCurrentTask() != null) {
int detail = -1;
boolean shouldSuspend = true;
if (fDebugState.isStepIntoSuspend()) {
detail = DebugEvent.STEP_END;
fDebugState.setStepIntoSuspend(false);
} else if ((fDebugState.getLastTaskFinished() != null && fDebugState.getLastTaskFinished() == fDebugState.getStepOverTask())
|| fDebugState.shouldSuspend()) {
detail = DebugEvent.STEP_END;
fDebugState.setShouldSuspend(false);
fDebugState.setStepOverTask(null);
} else if (fDebugState.isClientSuspend()) {
detail = DebugEvent.CLIENT_REQUEST;
fDebugState.setClientSuspend(false);
} else {
shouldSuspend = false;
}
if (shouldSuspend) {
fAntDebugTarget.suspended(detail);
try {
while (!fResumed) {
wait(500);
checkCancelled();
}
}
catch (InterruptedException e) {
// do nothing
}
}
}
}
private void checkCancelled() {
AntProcess process = getAntProcess(fProcessId);
if (process != null && process.isCanceled()) {
throw new OperationCanceledException(RuntimeMessages.AntProcessDebugBuildLogger_1);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#resume()
*/
@Override
public synchronized void resume() {
fResumed = true;
notifyAll();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#suspend()
*/
@Override
public synchronized void suspend() {
fDebugState.setClientSuspend(true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#stepInto()
*/
@Override
public synchronized void stepInto() {
fDebugState.setStepIntoSuspend(true);
fResumed = true;
notifyAll();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.launching.debug.IAntDebugController#terminate()
*/
@Override
public void terminate() {
cleanup();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#stepOver()
*/
@Override
public synchronized void stepOver() {
fResumed = true;
fDebugState.stepOver();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#handleBreakpoint(org.eclipse.debug.core.model.IBreakpoint, boolean)
*/
@Override
public void handleBreakpoint(IBreakpoint breakpoint, boolean added) {
if (added) {
if (fBreakpoints == null) {
fBreakpoints = new ArrayList<>();
}
if (!fBreakpoints.contains(breakpoint)) {
fBreakpoints.add(breakpoint);
}
} else {
if (fBreakpoints != null) {
fBreakpoints.remove(breakpoint);
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#getProperties()
*/
@Override
public void getProperties() {
if (fAntDebugTarget == null || !fAntDebugTarget.isSuspended()) {
return;
}
StringBuffer propertiesRepresentation = new StringBuffer();
fDebugState.marshallProperties(propertiesRepresentation, false);
if (fAntDebugTarget.getThreads().length > 0) {
((AntThread) fAntDebugTarget.getThreads()[0]).newProperties(propertiesRepresentation.toString());
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#getStackFrames()
*/
@Override
public void getStackFrames() {
StringBuffer stackRepresentation = new StringBuffer();
fDebugState.marshalStack(stackRepresentation);
((AntThread) fAntDebugTarget.getThreads()[0]).buildStack(stackRepresentation.toString());
}
private IBreakpoint breakpointAtLineNumber(Location location) {
if (fBreakpoints == null || location == null || location == Location.UNKNOWN_LOCATION) {
return null;
}
int lineNumber = fDebugState.getLineNumber(location);
File locationFile = new File(fDebugState.getFileName(location));
for (int i = 0; i < fBreakpoints.size(); i++) {
ILineBreakpoint breakpoint = (ILineBreakpoint) fBreakpoints.get(i);
int breakpointLineNumber;
try {
if (!breakpoint.isEnabled()) {
continue;
}
breakpointLineNumber = breakpoint.getLineNumber();
}
catch (CoreException e) {
return null;
}
IFile resource = (IFile) breakpoint.getMarker().getResource();
if (breakpointLineNumber == lineNumber && resource.getLocation().toFile().equals(locationFile)) {
return breakpoint;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.BuildListener#targetStarted(org.apache.tools.ant.BuildEvent)
*/
@Override
public void targetStarted(BuildEvent event) {
fDebugState.targetStarted(event);
waitIfSuspended();
super.targetStarted(event);
}
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.BuildListener#targetFinished(org.apache.tools.ant.BuildEvent)
*/
@Override
public void targetFinished(BuildEvent event) {
super.targetFinished(event);
if (fDebugState != null) {
fDebugState.setTargetExecuting(null);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ant.internal.ui.debug.IAntDebugController#unescapeString(java.lang.StringBuffer)
*/
@Override
public StringBuffer unescapeString(StringBuffer propertyValue) {
return propertyValue;
}
}