package org.eclipse.jdi.internal.request; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import com.sun.jdi.*; | |
import com.sun.jdi.request.*; | |
import com.sun.jdi.connect.*; | |
import com.sun.jdi.event.*; | |
import java.util.*; | |
import org.eclipse.jdi.internal.*; | |
import org.eclipse.jdi.internal.jdwp.*; | |
import org.eclipse.jdi.internal.connect.*; | |
import org.eclipse.jdi.internal.event.*; | |
import java.io.*; | |
/** | |
* this class implements the corresponding interfaces | |
* declared by the JDI specification. See the com.sun.jdi package | |
* for more information. | |
* | |
*/ | |
public class EventRequestManagerImpl extends MirrorImpl implements EventRequestManager, org.eclipse.jdi.hcr.EventRequestManager { | |
/** Indexes used in arrays of request types. */ | |
private static final int ACCESS_WATCHPOINT_INDEX = 0; | |
private static final int BREAKPOINT_INDEX = 1; | |
private static final int CLASS_PREPARE_INDEX = 2; | |
private static final int CLASS_UNLOAD_INDEX = 3; | |
private static final int EXCEPTION_INDEX = 4; | |
private static final int METHOD_ENTRY_INDEX = 5; | |
private static final int METHOD_EXIT_INDEX = 6; | |
private static final int MODIFICATION_WATCHPOINT_INDEX = 7; | |
private static final int STEP_INDEX = 8; | |
private static final int THREAD_DEATH_INDEX = 9; | |
private static final int THREAD_START_INDEX = 10; | |
/** Set of all existing requests per request type. */ | |
private HashSet[] fRequests; | |
/** Maps per request type of requestIDs to enabled requests. */ | |
private Hashtable[] fEnabledRequests; | |
/** | |
* Creates new EventRequestManager. | |
*/ | |
public EventRequestManagerImpl(VirtualMachineImpl vmImpl) { | |
super("EventRequestManager", vmImpl); | |
// Initialize list of requests. | |
fRequests = new HashSet[THREAD_START_INDEX + 1]; | |
for (int i = 0; i < fRequests.length; i++) | |
fRequests[i] = new HashSet(); | |
// Initialize map of request IDs to enabled requests. | |
fEnabledRequests = new Hashtable[THREAD_START_INDEX + 1]; | |
for (int i = 0; i < fEnabledRequests.length; i++) | |
fEnabledRequests[i] = new Hashtable(); | |
} | |
/** | |
* Creates AccessWatchpointRequest. | |
*/ | |
public AccessWatchpointRequest createAccessWatchpointRequest(Field field) { | |
FieldImpl fieldImpl = (FieldImpl)field; | |
AccessWatchpointRequestImpl req = new AccessWatchpointRequestImpl(virtualMachineImpl()); | |
req.addFieldFilter(fieldImpl); | |
addEventRequest(ACCESS_WATCHPOINT_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates BreakpointRequest. | |
*/ | |
public BreakpointRequest createBreakpointRequest(Location location) throws VMMismatchException { | |
LocationImpl locImpl = (LocationImpl)location; | |
BreakpointRequestImpl req = new BreakpointRequestImpl(virtualMachineImpl()); | |
req.addLocationFilter(locImpl); | |
addEventRequest(BREAKPOINT_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ClassPrepareRequest. | |
*/ | |
public ClassPrepareRequest createClassPrepareRequest() { | |
ClassPrepareRequestImpl req = new ClassPrepareRequestImpl(virtualMachineImpl()); | |
addEventRequest(CLASS_PREPARE_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ClassUnloadRequest. | |
*/ | |
public ClassUnloadRequest createClassUnloadRequest() { | |
ClassUnloadRequestImpl req = new ClassUnloadRequestImpl(virtualMachineImpl()); | |
addEventRequest(CLASS_UNLOAD_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ExceptionRequest. | |
*/ | |
public ExceptionRequest createExceptionRequest(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught) { | |
ReferenceTypeImpl refTypeImpl = (ReferenceTypeImpl)refType; | |
ExceptionRequestImpl req = new ExceptionRequestImpl(virtualMachineImpl()); | |
req.addExceptionFilter(refTypeImpl, notifyCaught, notifyUncaught); | |
addEventRequest(EXCEPTION_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates MethodEntryRequest. | |
*/ | |
public MethodEntryRequest createMethodEntryRequest() { | |
MethodEntryRequestImpl req = new MethodEntryRequestImpl(virtualMachineImpl()); | |
addEventRequest(METHOD_ENTRY_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates MethodExitRequest. | |
*/ | |
public MethodExitRequest createMethodExitRequest() { | |
MethodExitRequestImpl req = new MethodExitRequestImpl(virtualMachineImpl()); | |
addEventRequest(METHOD_EXIT_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ModificationWatchpointRequest. | |
*/ | |
public ModificationWatchpointRequest createModificationWatchpointRequest(Field field) { | |
FieldImpl fieldImpl = (FieldImpl)field; | |
ModificationWatchpointRequestImpl req = new ModificationWatchpointRequestImpl(virtualMachineImpl()); | |
req.addFieldFilter(fieldImpl); | |
addEventRequest(MODIFICATION_WATCHPOINT_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates StepRequest. | |
*/ | |
public StepRequest createStepRequest(ThreadReference thread, int size, int depth) throws DuplicateRequestException, ObjectCollectedException { | |
ThreadReferenceImpl threadImpl = (ThreadReferenceImpl)thread; | |
StepRequestImpl req = new StepRequestImpl(virtualMachineImpl()); | |
req.addStepFilter(threadImpl, size, depth); | |
addEventRequest(STEP_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ThreadDeathRequest. | |
*/ | |
public ThreadDeathRequest createThreadDeathRequest() { | |
ThreadDeathRequestImpl req = new ThreadDeathRequestImpl(virtualMachineImpl()); | |
addEventRequest(THREAD_DEATH_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ThreadStartRequest. | |
*/ | |
public ThreadStartRequest createThreadStartRequest() { | |
ThreadStartRequestImpl req = new ThreadStartRequestImpl(virtualMachineImpl()); | |
addEventRequest(THREAD_START_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ReenterStepRequest (for OTI specific Hot Code Replacement). | |
*/ | |
public org.eclipse.jdi.hcr.ReenterStepRequest createReenterStepRequest(ThreadReference thread) { | |
virtualMachineImpl().checkHCRSupported(); | |
ThreadReferenceImpl threadImpl = (ThreadReferenceImpl)thread; | |
ReenterStepRequestImpl req = new ReenterStepRequestImpl(virtualMachineImpl()); | |
// Note that the StepFilter is only used to specify the thread. | |
// The size is ignored and the depth will always be writter as HCR_STEP_DEPTH_REENTER_JDWP. | |
req.addStepFilter(threadImpl, StepRequest.STEP_MIN, 0); | |
// Since this is a special case of a step request, we use the same request list. | |
addEventRequest(STEP_INDEX, req); | |
return req; | |
} | |
/** | |
* Creates ClassUnloadRequest for maintaining class information for within JDI. | |
* Needed to known when to flush the cache. | |
*/ | |
public void enableInternalClasUnloadEvent(/* tbd: ReferenceTypeImpl refType*/) { | |
// Note that these requests are not stored in the set of outstanding requests because | |
// they must be invisible from outside. | |
ClassUnloadRequestImpl reqUnload = new ClassUnloadRequestImpl(virtualMachineImpl()); | |
reqUnload.setGeneratedInside(); | |
// tbd: It is now yet possible to only ask for unload events for | |
// classes that we know of due to a limitation in the J9 VM. | |
// reqUnload.addClassFilter(refType.name()); | |
reqUnload.setSuspendPolicy(ClassPrepareRequest.SUSPEND_NONE); | |
reqUnload.enable(); | |
} | |
/** | |
* Checks if a steprequest is for the given thread is already enabled. | |
*/ | |
boolean existsEnabledStepRequest(ThreadReferenceImpl threadImpl) { | |
Enumeration enum = fEnabledRequests[STEP_INDEX].elements(); | |
StepRequestImpl step; | |
while (enum.hasMoreElements()) { | |
step = (StepRequestImpl)enum.nextElement(); | |
if (step.thread() == threadImpl) | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Deletes all Breakpoints. | |
*/ | |
public void deleteAllBreakpoints() { | |
EventRequestImpl.clearAllBreakpoints(this); | |
fRequests[BREAKPOINT_INDEX].clear(); | |
fEnabledRequests[BREAKPOINT_INDEX].clear(); | |
} | |
/** | |
* Adds an EventRequests to the given list. | |
*/ | |
public void addEventRequest(int index, EventRequest req) { | |
fRequests[index].add(req); | |
} | |
/** | |
* Deletes an EventRequest. | |
*/ | |
private void deleteEventRequest(int index, EventRequest req) throws VMMismatchException { | |
// Remove request from list of requests and from the mapping of requestIDs to requests. | |
checkVM(req); | |
EventRequestImpl requestImpl = (EventRequestImpl)req; | |
fRequests[index].remove(requestImpl); | |
if (requestImpl.requestID() != null) | |
fEnabledRequests[index].remove(requestImpl.requestID()); | |
} | |
/** | |
* Deletes an EventRequest. | |
*/ | |
public void deleteEventRequest(EventRequest req) { | |
// Disable request, note that this also causes the event request to be removed from fEnabledRequests. | |
req.disable(); | |
// Remove request from list. | |
if (req instanceof AccessWatchpointRequestImpl) | |
deleteEventRequest(ACCESS_WATCHPOINT_INDEX, req); | |
else if (req instanceof BreakpointRequestImpl) | |
deleteEventRequest(BREAKPOINT_INDEX, req); | |
else if (req instanceof ClassPrepareRequestImpl) | |
deleteEventRequest(CLASS_PREPARE_INDEX, req); | |
else if (req instanceof ClassUnloadRequestImpl) | |
deleteEventRequest(CLASS_UNLOAD_INDEX, req); | |
else if (req instanceof ExceptionRequestImpl) | |
deleteEventRequest(EXCEPTION_INDEX, req); | |
else if (req instanceof MethodEntryRequestImpl) | |
deleteEventRequest(METHOD_ENTRY_INDEX, req); | |
else if (req instanceof MethodExitRequestImpl) | |
deleteEventRequest(METHOD_EXIT_INDEX, req); | |
else if (req instanceof ModificationWatchpointRequestImpl) | |
deleteEventRequest(MODIFICATION_WATCHPOINT_INDEX, req); | |
else if (req instanceof StepRequestImpl) | |
deleteEventRequest(STEP_INDEX, req); | |
else if (req instanceof ThreadDeathRequestImpl) | |
deleteEventRequest(THREAD_DEATH_INDEX, req); | |
else if (req instanceof ThreadStartRequestImpl) | |
deleteEventRequest(THREAD_START_INDEX, req); | |
else | |
throw new InternalError("EventRequest type of " + req + " is unknown."); | |
} | |
/** | |
* Deletes all EventRequests from the given list. | |
*/ | |
public void deleteEventRequests(List requests) throws VMMismatchException { | |
Iterator iter = requests.iterator(); | |
while(iter.hasNext()) { | |
Object obj = iter.next(); | |
deleteEventRequest((EventRequest)obj); | |
} | |
} | |
/** | |
* @return Returns list of AccessWatchpointRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List accessWatchpointRequests() { | |
return new ArrayList(fRequests[ACCESS_WATCHPOINT_INDEX]); | |
} | |
/** | |
* @return Returns list of BreakpointRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List breakpointRequests() { | |
return new ArrayList(fRequests[BREAKPOINT_INDEX]); | |
} | |
/** | |
* @return Returns list of ClassPrepareRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List classPrepareRequests() { | |
return new ArrayList(fRequests[CLASS_PREPARE_INDEX]); | |
} | |
/** | |
* @return Returns list of ClassUnloadRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List classUnloadRequests() { | |
return new ArrayList(fRequests[CLASS_UNLOAD_INDEX]); | |
} | |
/** | |
* @return Returns list of ExceptionRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List exceptionRequests() { | |
return new ArrayList(fRequests[EXCEPTION_INDEX]); | |
} | |
/** | |
* @return Returns list of MethodEntryRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List methodEntryRequests() { | |
return new ArrayList(fRequests[METHOD_ENTRY_INDEX]); | |
} | |
/** | |
* @return Returns list of MethodExitRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List methodExitRequests() { | |
return new ArrayList(fRequests[METHOD_EXIT_INDEX]); | |
} | |
/** | |
* @return Returns list of ModificationWatchpointRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List modificationWatchpointRequests() { | |
return new ArrayList(fRequests[MODIFICATION_WATCHPOINT_INDEX]); | |
} | |
/** | |
* @return Returns list of StepRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List stepRequests() { | |
return new ArrayList(fRequests[STEP_INDEX]); | |
} | |
/** | |
* @return Returns list of ThreadDeathRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List threadDeathRequests() { | |
return new ArrayList(fRequests[THREAD_DEATH_INDEX]); | |
} | |
/** | |
* @return Returns list of ThreadStartRequests. | |
* For changes, the appropriate EventRequestManager methods should be used. | |
*/ | |
public List threadStartRequests() { | |
return new ArrayList(fRequests[THREAD_START_INDEX]); | |
} | |
/** | |
* Maps a reuqest ID to requests. | |
*/ | |
public void addRequestIDMapping(EventRequestImpl req) { | |
if (req instanceof AccessWatchpointRequestImpl) | |
fEnabledRequests[ACCESS_WATCHPOINT_INDEX].put(req.requestID(), req); | |
else if (req instanceof BreakpointRequestImpl) | |
fEnabledRequests[BREAKPOINT_INDEX].put(req.requestID(), req); | |
else if (req instanceof ClassPrepareRequestImpl) | |
fEnabledRequests[CLASS_PREPARE_INDEX].put(req.requestID(), req); | |
else if (req instanceof ClassUnloadRequestImpl) | |
fEnabledRequests[CLASS_UNLOAD_INDEX].put(req.requestID(), req); | |
else if (req instanceof ExceptionRequestImpl) | |
fEnabledRequests[EXCEPTION_INDEX].put(req.requestID(), req); | |
else if (req instanceof MethodEntryRequestImpl) | |
fEnabledRequests[METHOD_ENTRY_INDEX].put(req.requestID(), req); | |
else if (req instanceof MethodExitRequestImpl) | |
fEnabledRequests[METHOD_EXIT_INDEX].put(req.requestID(), req); | |
else if (req instanceof ModificationWatchpointRequestImpl) | |
fEnabledRequests[MODIFICATION_WATCHPOINT_INDEX].put(req.requestID(), req); | |
else if (req instanceof StepRequestImpl) | |
fEnabledRequests[STEP_INDEX].put(req.requestID(), req); | |
else if (req instanceof ThreadDeathRequestImpl) | |
fEnabledRequests[THREAD_DEATH_INDEX].put(req.requestID(), req); | |
else if (req instanceof ThreadStartRequestImpl) | |
fEnabledRequests[THREAD_START_INDEX].put(req.requestID(), req); | |
} | |
/** | |
* Find Request that matches event. | |
*/ | |
public EventRequestImpl findRequest(EventImpl event) { | |
if (event instanceof AccessWatchpointEventImpl) | |
return (EventRequestImpl)fEnabledRequests[ACCESS_WATCHPOINT_INDEX].get(event.requestID()); | |
else if (event instanceof BreakpointEventImpl) | |
return (EventRequestImpl)fEnabledRequests[BREAKPOINT_INDEX].get(event.requestID()); | |
else if (event instanceof ClassPrepareEventImpl) | |
return (ClassPrepareRequestImpl)fEnabledRequests[CLASS_PREPARE_INDEX].get(event.requestID()); | |
else if (event instanceof ClassUnloadEventImpl) | |
return (EventRequestImpl)fEnabledRequests[CLASS_UNLOAD_INDEX].get(event.requestID()); | |
else if (event instanceof ExceptionEventImpl) | |
return (EventRequestImpl)fEnabledRequests[EXCEPTION_INDEX].get(event.requestID()); | |
else if (event instanceof MethodEntryEventImpl) | |
return (EventRequestImpl)fEnabledRequests[METHOD_ENTRY_INDEX].get(event.requestID()); | |
else if (event instanceof MethodExitEventImpl) | |
return (EventRequestImpl)fEnabledRequests[METHOD_EXIT_INDEX].get(event.requestID()); | |
else if (event instanceof ModificationWatchpointEventImpl) | |
return (EventRequestImpl)fEnabledRequests[MODIFICATION_WATCHPOINT_INDEX].get(event.requestID()); | |
else if (event instanceof StepEventImpl) | |
return (EventRequestImpl)fEnabledRequests[STEP_INDEX].get(event.requestID()); | |
else if (event instanceof ThreadDeathEventImpl) | |
return (EventRequestImpl)fEnabledRequests[THREAD_DEATH_INDEX].get(event.requestID()); | |
else if (event instanceof ThreadStartEventImpl) | |
return (EventRequestImpl)fEnabledRequests[THREAD_START_INDEX].get(event.requestID()); | |
else | |
throw new InternalError("Got event of unknown type."); | |
} | |
} |