| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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.jdt.internal.debug.core.model; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.model.DebugElement; |
| import org.eclipse.debug.core.model.IDebugElement; |
| import org.eclipse.debug.core.model.IDebugTarget; |
| import org.eclipse.debug.core.model.IDisconnect; |
| import org.eclipse.debug.core.model.IStepFilters; |
| import org.eclipse.debug.core.model.ITerminate; |
| |
| import org.eclipse.jdi.TimeoutException; |
| import org.eclipse.jdt.debug.core.IJavaDebugTarget; |
| import org.eclipse.jdt.debug.core.JDIDebugModel; |
| |
| import org.eclipse.jdt.internal.debug.core.EventDispatcher; |
| import org.eclipse.jdt.internal.debug.core.IJDIEventListener; |
| import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; |
| |
| import com.sun.jdi.VMDisconnectedException; |
| import com.sun.jdi.VirtualMachine; |
| import com.sun.jdi.event.EventSet; |
| import com.sun.jdi.request.EventRequest; |
| import com.sun.jdi.request.EventRequestManager; |
| |
| public abstract class JDIDebugElement extends DebugElement implements |
| IDisconnect { |
| |
| /** |
| * Creates a JDI debug element associated with the specified debug target. |
| * |
| * @param target |
| * The associated debug target |
| */ |
| public JDIDebugElement(JDIDebugTarget target) { |
| super(target); |
| } |
| |
| /** |
| * Convenience method to log errors |
| */ |
| protected void logError(Exception e) { |
| if (!((JDIDebugTarget) getDebugTarget()).isAvailable()) { |
| // Don't log VMDisconnectedExceptions that occur |
| // when the VM is unavailable. |
| if (e instanceof VMDisconnectedException |
| || (e instanceof CoreException && ((CoreException) e) |
| .getStatus().getException() instanceof VMDisconnectedException)) { |
| return; |
| } |
| } |
| JDIDebugPlugin.log(e); |
| } |
| |
| /** |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| if (adapter == IDebugElement.class) { |
| return (T) this; |
| } |
| if (adapter == IStepFilters.class) { |
| return (T) getDebugTarget(); |
| } |
| if (adapter == IDebugTarget.class) { |
| return (T) getDebugTarget(); |
| } |
| if (adapter == ITerminate.class) { |
| return (T) getDebugTarget(); |
| } |
| if (adapter == IJavaDebugTarget.class) { |
| return (T) getJavaDebugTarget(); |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * @see org.eclipse.debug.core.model.IDebugElement#getModelIdentifier() |
| */ |
| @Override |
| public String getModelIdentifier() { |
| return JDIDebugModel.getPluginIdentifier(); |
| } |
| |
| /** |
| * Queues a debug event with the event dispatcher to be fired as an event |
| * set when all event processing is complete. |
| * |
| * @param event |
| * the event to queue |
| * @param set |
| * the event set the event is associated with |
| */ |
| public void queueEvent(DebugEvent event, EventSet set) { |
| EventDispatcher dispatcher = ((JDIDebugTarget) getDebugTarget()) |
| .getEventDispatcher(); |
| if (dispatcher != null) { |
| dispatcher.queue(event, set); |
| } |
| } |
| |
| /** |
| * Fires a debug event marking the SUSPEND of this element with the |
| * associated detail. |
| * |
| * @param detail |
| * The int detail of the event |
| * @see org.eclipse.debug.core.DebugEvent |
| */ |
| @Override |
| public void fireSuspendEvent(int detail) { |
| getJavaDebugTarget().incrementSuspendCount(detail); |
| super.fireSuspendEvent(detail); |
| } |
| |
| /** |
| * Queues a debug event marking the SUSPEND of this element with the |
| * associated detail. |
| * |
| * @param detail |
| * The int detail of the event |
| * @param set |
| * the event set the event is associated with |
| * @see org.eclipse.debug.core.DebugEvent |
| */ |
| public void queueSuspendEvent(int detail, EventSet set) { |
| getJavaDebugTarget().incrementSuspendCount(detail); |
| queueEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail), set); |
| } |
| |
| /** |
| * Throws a new debug exception with a status code of |
| * <code>REQUEST_FAILED</code>. |
| * |
| * @param message |
| * Failure message |
| * @param e |
| * Exception that has occurred (<code>can be null</code>) |
| * @throws DebugException |
| * The exception with a status code of |
| * <code>REQUEST_FAILED</code> |
| */ |
| public void requestFailed(String message, Exception e) |
| throws DebugException { |
| requestFailed(message, e, DebugException.REQUEST_FAILED); |
| } |
| |
| /** |
| * Throws a new debug exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code> with the given underlying exception. |
| * If the underlying exception is not a JDI exception, the original |
| * exception is thrown. |
| * |
| * @param message |
| * Failure message |
| * @param e |
| * underlying exception that has occurred |
| * @throws DebugException |
| * The exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code> |
| */ |
| public void targetRequestFailed(String message, RuntimeException e) |
| throws DebugException { |
| if (e == null |
| || e.getClass().getName().startsWith("com.sun.jdi") || e instanceof TimeoutException) { //$NON-NLS-1$ |
| requestFailed(message, e, DebugException.TARGET_REQUEST_FAILED); |
| } else { |
| throw e; |
| } |
| } |
| |
| /** |
| * Throws a new debug exception with the given status code. |
| * |
| * @param message |
| * Failure message |
| * @param e |
| * Exception that has occurred (<code>can be null</code>) |
| * @param code |
| * status code |
| * @throws DebugException |
| * a new exception with given status code |
| */ |
| public void requestFailed(String message, Throwable e, int code) |
| throws DebugException { |
| throwDebugException(message, code, e); |
| } |
| |
| /** |
| * Throws a new debug exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code>. |
| * |
| * @param message |
| * Failure message |
| * @param e |
| * Throwable that has occurred |
| * @throws DebugException |
| * The exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code> |
| */ |
| public void targetRequestFailed(String message, Throwable e) |
| throws DebugException { |
| throwDebugException(message, DebugException.TARGET_REQUEST_FAILED, e); |
| } |
| |
| /** |
| * Throws a new debug exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code> with the given underlying exception. |
| * The underlying exception is an exception thrown by a JDI request. |
| * |
| * @param message |
| * Failure message |
| * @param e |
| * throwable exception that has occurred |
| * @throws DebugException |
| * the exception with a status code of |
| * <code>TARGET_REQUEST_FAILED</code> |
| */ |
| public void jdiRequestFailed(String message, Throwable e) |
| throws DebugException { |
| throwDebugException(message, DebugException.TARGET_REQUEST_FAILED, e); |
| } |
| |
| /** |
| * Throws a new debug exception with a status code of |
| * <code>NOT_SUPPORTED</code>. |
| * |
| * @param message |
| * Failure message |
| * @throws DebugException |
| * The exception with a status code of |
| * <code>NOT_SUPPORTED</code>. |
| */ |
| public void notSupported(String message) throws DebugException { |
| throwDebugException(message, DebugException.NOT_SUPPORTED, null); |
| } |
| |
| /** |
| * Throws a debug exception with the given message, error code, and |
| * underlying exception. |
| */ |
| protected void throwDebugException(String message, int code, |
| Throwable exception) throws DebugException { |
| if (exception instanceof VMDisconnectedException) { |
| disconnected(); |
| } |
| throw new DebugException(new Status(IStatus.ERROR, |
| JDIDebugModel.getPluginIdentifier(), code, message, exception)); |
| } |
| |
| /** |
| * Logs the given exception if it is a JDI exception, otherwise throws the |
| * runtime exception. |
| * |
| * @param e |
| * The internal runtime exception |
| */ |
| public void internalError(RuntimeException e) { |
| if (e.getClass().getName().startsWith("com.sun.jdi") || e instanceof TimeoutException) { //$NON-NLS-1$ |
| logError(e); |
| } else { |
| throw e; |
| } |
| } |
| |
| /** |
| * Logs a debug exception with the given message, with a status code of |
| * <code>INTERNAL_ERROR</code>. |
| * |
| * @param message |
| * The internal error message |
| */ |
| protected void internalError(String message) { |
| logError(new DebugException(new Status(IStatus.ERROR, |
| JDIDebugModel.getPluginIdentifier(), |
| DebugException.INTERNAL_ERROR, message, null))); |
| } |
| |
| /** |
| * Returns the common "<unknown>" message. |
| * |
| * @return the unknown String |
| */ |
| protected String getUnknownMessage() { |
| return JDIDebugModelMessages.JDIDebugElement_unknown; |
| } |
| |
| /** |
| * Returns this elements debug target as its implementation class. |
| * |
| * @return Java debug target |
| */ |
| public JDIDebugTarget getJavaDebugTarget() { |
| return (JDIDebugTarget) getDebugTarget(); |
| } |
| |
| /** |
| * Returns the target VM associated with this element, or <code>null</code> |
| * if none. |
| * |
| * @return target VM or <code>null</code> if none |
| */ |
| protected VirtualMachine getVM() { |
| return ((JDIDebugTarget) getDebugTarget()).getVM(); |
| } |
| |
| /** |
| * Returns the underlying VM's event request manager, or <code>null</code> |
| * if none (disconnected/terminated) |
| * |
| * @return event request manager or <code>null</code> |
| */ |
| public EventRequestManager getEventRequestManager() { |
| VirtualMachine vm = getVM(); |
| if (vm == null) { |
| return null; |
| } |
| return vm.eventRequestManager(); |
| } |
| |
| /** |
| * Adds the given listener to this target's event dispatcher's table of |
| * listeners for the specified event request. The listener will be notified |
| * each time the event occurs. |
| * |
| * @param listener |
| * the listener to register |
| * @param request |
| * the event request |
| */ |
| public void addJDIEventListener(IJDIEventListener listener, |
| EventRequest request) { |
| EventDispatcher dispatcher = ((JDIDebugTarget) getDebugTarget()) |
| .getEventDispatcher(); |
| if (dispatcher != null) { |
| dispatcher.addJDIEventListener(listener, request); |
| } |
| } |
| |
| /** |
| * Removes the given listener from this target's event dispatcher's table of |
| * listeners for the specifed event request. The listener will no longer be |
| * notified when the event occurs. Listeners are responsible for deleting |
| * the event request if desired. |
| * |
| * @param listener |
| * the listener to remove |
| * @param request |
| * the event request |
| */ |
| public void removeJDIEventListener(IJDIEventListener listener, |
| EventRequest request) { |
| EventDispatcher dispatcher = ((JDIDebugTarget) getDebugTarget()) |
| .getEventDispatcher(); |
| if (dispatcher != null) { |
| dispatcher.removeJDIEventListener(listener, request); |
| } |
| } |
| |
| /** |
| * The VM has disconnected. Notify the target. |
| */ |
| protected void disconnected() { |
| if (getDebugTarget() != null) { |
| getJavaDebugTarget().disconnected(); |
| } |
| } |
| |
| /** |
| * @see IJavaDebugTarget#setRequestTimeout(int) |
| */ |
| public void setRequestTimeout(int timeout) { |
| if (supportsRequestTimeout()) { |
| VirtualMachine vm = getVM(); |
| if (vm != null) { |
| ((org.eclipse.jdi.VirtualMachine) vm) |
| .setRequestTimeout(timeout); |
| } |
| } |
| } |
| |
| /** |
| * @see IJavaDebugTarget#getRequestTimeout() |
| */ |
| public int getRequestTimeout() { |
| if (supportsRequestTimeout()) { |
| VirtualMachine vm = getVM(); |
| if (vm != null) { |
| return ((org.eclipse.jdi.VirtualMachine) vm) |
| .getRequestTimeout(); |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * @see IJavaDebugTarget#supportsRequestTimeout() |
| */ |
| public boolean supportsRequestTimeout() { |
| return getJavaDebugTarget().isAvailable() |
| && getVM() instanceof org.eclipse.jdi.VirtualMachine; |
| } |
| |
| /** |
| * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect() |
| */ |
| @Override |
| public boolean canDisconnect() { |
| return getDebugTarget().canDisconnect(); |
| } |
| |
| /** |
| * @see org.eclipse.debug.core.model.IDisconnect#disconnect() |
| */ |
| @Override |
| public void disconnect() throws DebugException { |
| getDebugTarget().disconnect(); |
| } |
| |
| /** |
| * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected() |
| */ |
| @Override |
| public boolean isDisconnected() { |
| return getDebugTarget().isDisconnected(); |
| } |
| |
| /** |
| * @see org.eclipse.debug.core.model.IStepFilters#isStepFiltersEnabled() |
| */ |
| public boolean isStepFiltersEnabled() { |
| return getJavaDebugTarget().isStepFiltersEnabled(); |
| } |
| } |