/******************************************************************************* * Copyright (c) 2000, 2015 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.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(); } }