blob: eb7d64716c57264c9b07b7173e71a7d09efb508a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 IBM 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.core.breakpoints;
import java.util.ArrayList;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.wst.jsdt.debug.core.breakpoints.IJavaScriptBreakpointParticipant;
import org.eclipse.wst.jsdt.debug.core.breakpoints.IJavaScriptLoadBreakpoint;
import org.eclipse.wst.jsdt.debug.core.jsdi.ScriptReference;
import org.eclipse.wst.jsdt.debug.core.jsdi.event.Event;
import org.eclipse.wst.jsdt.debug.core.jsdi.event.EventSet;
import org.eclipse.wst.jsdt.debug.core.jsdi.event.ScriptLoadEvent;
import org.eclipse.wst.jsdt.debug.core.jsdi.request.EventRequest;
import org.eclipse.wst.jsdt.debug.core.jsdi.request.ScriptLoadRequest;
import org.eclipse.wst.jsdt.debug.internal.core.JavaScriptDebugPlugin;
import org.eclipse.wst.jsdt.debug.internal.core.JavaScriptPreferencesManager;
import org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget;
import org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptThread;
/**
* Breakpoint that suspends on {@link ScriptLoadEvent}s
*
* @since 1.0
*/
public class JavaScriptLoadBreakpoint extends JavaScriptLineBreakpoint implements IJavaScriptLoadBreakpoint {
/**
* Attribute flag to tag a script load breakpoint as a global suspend load breakpoint
*/
public static final String GLOBAL_SUSPEND = JavaScriptDebugPlugin.PLUGIN_ID + ".global_suspend"; //$NON-NLS-1$
/**
* Constructor
*/
public JavaScriptLoadBreakpoint() {
// used for persistence / restoration
}
/**
* Constructor
*
* @param resource
* @param charstart
* @param charend
* @param attributes
* @param register
* @throws DebugException
*/
public JavaScriptLoadBreakpoint(final IResource resource, final int charstart, final int charend, final Map attributes, final boolean register) throws DebugException {
IWorkspaceRunnable wr = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IMarker marker = null;
if(resource == null) {
marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaScriptLoadBreakpoint.MARKER_ID);
}
else {
marker = resource.createMarker(IJavaScriptLoadBreakpoint.MARKER_ID);
}
// create the marker
setMarker(marker);
// add attributes
attributes.put(IBreakpoint.ID, getModelIdentifier());
attributes.put(IBreakpoint.ENABLED, Boolean.valueOf(true));
attributes.put(IMarker.CHAR_START, new Integer(charstart));
attributes.put(IMarker.CHAR_END, new Integer(charend));
ensureMarker().setAttributes(attributes);
// add to breakpoint manager if requested
register(register);
}
};
run(getMarkerRule(ResourcesPlugin.getWorkspace().getRoot()), wr);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptBreakpoint#handleEvent(org.eclipse.wst.jsdt.debug.core.jsdi.event.Event, org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget, boolean, org.eclipse.wst.jsdt.debug.core.jsdi.event.EventSet)
*/
public boolean handleEvent(Event event, JavaScriptDebugTarget target, boolean suspendVote, EventSet eventSet) {
if (event instanceof ScriptLoadEvent) {
ScriptLoadEvent sevent = (ScriptLoadEvent) event;
ScriptReference script = sevent.script();
JavaScriptThread thread = target.findThread((sevent).thread());
if (thread != null) {
if(isGlobalLoadSuspend()) {
JavaScriptPreferencesManager.setGlobalSuspendOn(script.sourceURI().toString());
thread.addBreakpoint(this);
return false;
} else if(isMatchedScriptLoadSuspend(script, thread, suspendVote)){
thread.addBreakpoint(this);
return false;
}
}
}
return true;
}
/**
* Returns if this breakpoint matches this script and should suspend
*
* @param script
* @param thread
* @param suspendVote
*
* @return <code>true</code> if we should suspend on this script load <code>false</code> otherwise
*/
private boolean isMatchedScriptLoadSuspend(ScriptReference script, JavaScriptThread thread, boolean suspendVote) {
try {
if (scriptPathMatches(script)) {
int vote = thread.suspendForScriptLoad(this, script, suspendVote);
return (vote & IJavaScriptBreakpointParticipant.SUSPEND) > 0 || vote == IJavaScriptBreakpointParticipant.DONT_CARE;
}
}
catch(CoreException ce) {
JavaScriptDebugPlugin.log(ce);
}
return false;
}
/**
* Returns if this breakpoint supports global suspend
*
* @return <code>true</code> if we should suspend on all script loads <code>false</code> otherwise
*/
private boolean isGlobalLoadSuspend() {
try {
return ensureMarker().getAttribute(GLOBAL_SUSPEND, false);
}
catch(CoreException ce) {
JavaScriptDebugPlugin.log(ce);
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptBreakpoint#registerRequest(org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget, org.eclipse.wst.jsdt.debug.core.jsdi.request.EventRequest)
*/
protected void registerRequest(JavaScriptDebugTarget target, EventRequest request) {
ArrayList requests = getRequests(target);
if (requests == null || requests.isEmpty()) {
// only add it once per target
addRequestForTarget(target, request);
try {
if (isRegistered()) {
incrementInstallCount();
}
} catch (CoreException ce) {
JavaScriptDebugPlugin.log(ce);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptBreakpoint#deregisterRequest(org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget, org.eclipse.wst.jsdt.debug.core.jsdi.request.EventRequest)
*/
protected void deregisterRequest(JavaScriptDebugTarget target, EventRequest request) {
target.removeJSDIEventListener(this, request);
try {
decrementInstallCount();
} catch (CoreException ce) {
JavaScriptDebugPlugin.log(ce);
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptBreakpoint#eventSetComplete(org.eclipse.wst.jsdt.debug.core.jsdi.event.Event, org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget, boolean, org.eclipse.wst.jsdt.debug.core.jsdi.event.EventSet)
*/
public void eventSetComplete(Event event, JavaScriptDebugTarget target, boolean suspend, EventSet eventSet) {
if (event instanceof ScriptLoadEvent) {
JavaScriptThread thread = target.findThread(((ScriptLoadEvent) event).thread());
if (thread != null) {
ScriptLoadEvent sevent = (ScriptLoadEvent) event;
thread.suspendForScriptLoadComplete(this, sevent.script(), suspend, eventSet);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptLineBreakpoint#createRequest(org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptDebugTarget, org.eclipse.wst.jsdt.debug.core.jsdi.ScriptReference)
*/
protected boolean createRequest(JavaScriptDebugTarget target, ScriptReference script) throws CoreException {
ScriptLoadRequest request = target.getEventRequestManager().createScriptLoadRequest();
registerRequest(target, request);
request.setEnabled(isEnabled());
return false;
}
}