| /******************************************************************************* |
| * 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; |
| } |
| } |