// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.nodeclipse.debug.model;
import org.chromium.debug.core.ChromiumDebugPlugin;
import org.chromium.debug.core.model.BreakpointSynchronizer;
import org.chromium.debug.core.model.ConnectedTargetData;
import org.chromium.debug.core.model.DebugTargetImpl;
import org.chromium.debug.core.model.LaunchParams;
import org.chromium.debug.core.model.Messages;
import org.chromium.debug.core.util.ProgressUtil;
import org.chromium.debug.core.util.ProgressUtil.MonitorWrapper;
import org.chromium.debug.core.util.ProgressUtil.Stage;
import org.chromium.sdk.CallbackSemaphore;
import org.chromium.sdk.RelayOk;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.osgi.util.NLS;
/**
* Does several things we need on debug session start. This procedure works asynchronously while
* user may already start his debug activity.
*/
class LaunchInitializationProcedure {
static void startAsync(VProjectWorkspaceBridge workspaceBridge,
BreakpointSynchronizer.Direction presetDirection) {
final LaunchInitializationProcedure procedure =
new LaunchInitializationProcedure(workspaceBridge, presetDirection);
ILaunch launch = workspaceBridge.getConnectedTargetData().getDebugTarget().getLaunch();
final String jobName = NLS.bind(Messages.LaunchInitializationProcedure_JOB_NAME,
launch.getLaunchConfiguration().getName());
Job job = new Job(jobName) {
@Override
protected IStatus run(IProgressMonitor monitor) {
return procedure.execute(monitor);
}
};
job.schedule();
}
private final VProjectWorkspaceBridge workspaceBridge;
private final BreakpointSynchronizer.Direction presetDirection;
private LaunchInitializationProcedure(VProjectWorkspaceBridge workspaceBridge,
BreakpointSynchronizer.Direction presetDirection) {
this.workspaceBridge = workspaceBridge;
this.presetDirection = presetDirection;
}
/**
* A list of tasks for progress monitor.
*/
private interface WorkPlan {
Stage PREINIT = new Stage(Messages.LaunchInitializationProcedure_UPDATE_DEBUGGER_STATE, 0.1f);
Stage SET_OPTIONS = new Stage(Messages.LaunchInitializationProcedure_SET_OPTIONS, 1f);
Stage LOAD_SCRIPTS = new Stage(Messages.LaunchInitializationProcedure_LOAD_SCRIPTS, 1f);
Stage SYNCHRONIZE_BREAKPOINTS =
new Stage(Messages.LaunchInitializationProcedure_SYNCHRONIZE_BREAKPOINTS, 1f);
boolean IS_INITIZALIZED = ProgressUtil.layoutProgressPlan(PREINIT, SET_OPTIONS, LOAD_SCRIPTS,
SYNCHRONIZE_BREAKPOINTS);
}
private IStatus execute(IProgressMonitor monitor) {
ConnectedTargetData connectedTargetData = workspaceBridge.getConnectedTargetData();
MonitorWrapper monitorWrapper = new MonitorWrapper(monitor, ""); //$NON-NLS-1$
monitorWrapper.beginTask();
try {
WorkPlan.PREINIT.start(monitorWrapper);
// Nothing here right now.
WorkPlan.PREINIT.finish(monitorWrapper);
checkIsCanceled(monitorWrapper);
WorkPlan.SET_OPTIONS.start(monitorWrapper);
// Not implemented yet
WorkPlan.SET_OPTIONS.finish(monitorWrapper);
checkIsCanceled(monitorWrapper);
WorkPlan.LOAD_SCRIPTS.start(monitorWrapper);
workspaceBridge.reloadScriptsAtStart();
WorkPlan.LOAD_SCRIPTS.finish(monitorWrapper);
checkIsCanceled(monitorWrapper);
synchronizeBreakpoints(
WorkPlan.SYNCHRONIZE_BREAKPOINTS.createSubMonitorWrapper(monitorWrapper));
} finally {
monitorWrapper.done();
}
return Status.OK_STATUS;
}
/**
* A list of tasks for breakpoint synchronization subprocess.
*/
private interface BreakpointsWorkPlan {
Stage ANALYZE = new Stage(null, 1f);
Stage REMOTE_CHANGES = new Stage(null, 1f);
boolean IS_LAYOUTED = ProgressUtil.layoutProgressPlan(ANALYZE, REMOTE_CHANGES);
}
private void synchronizeBreakpoints(MonitorWrapper monitor) {
monitor.beginTask();
try {
BreakpointsWorkPlan.ANALYZE.start(monitor);
DebugTargetImpl debugTarget = workspaceBridge.getConnectedTargetData().getDebugTarget();
ILaunchConfiguration launchConfiguration = debugTarget.getLaunch().getLaunchConfiguration();
BreakpointSynchronizer.Direction direction;
if (presetDirection == null) {
try {
direction = LaunchParams.readBreakpointSyncDirection(launchConfiguration);
} catch (CoreException e) {
ChromiumDebugPlugin.log(
new Exception("Failed to read breakpoint synchronization direction " + //$NON-NLS-1$
"from launch configuration " + launchConfiguration.getName(), e)); //$NON-NLS-1$
direction = null;
}
} else {
direction = presetDirection;
}
if (direction == null) {
return;
}
final CallbackSemaphore callbackSemaphore = new CallbackSemaphore();
BreakpointSynchronizer.Callback callback = new BreakpointSynchronizer.Callback() {
public void onDone(IStatus status) {
callbackSemaphore.callbackDone(null);
}
};
workspaceBridge.getBreakpointSynchronizer().syncBreakpoints(direction, callback);
RelayOk relayOk = SYNCHRONIZER_MUST_RELAY_OK;
checkIsCanceled(monitor);
BreakpointsWorkPlan.ANALYZE.finish(monitor);
BreakpointsWorkPlan.REMOTE_CHANGES.start(monitor);
callbackSemaphore.tryAcquireDefault(relayOk);
BreakpointsWorkPlan.REMOTE_CHANGES.finish(monitor);
} finally {
monitor.done();
}
}
private static void checkIsCanceled(MonitorWrapper monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
private static final RelayOk SYNCHRONIZER_MUST_RELAY_OK = new RelayOk() {};
}