package org.erlide.debug.ui.model; import java.text.MessageFormat; import java.util.EnumSet; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.erlide.backend.api.ErlRuntimeAttributes; import org.erlide.backend.api.IBackend; import org.erlide.backend.api.IBackendListener; import org.erlide.backend.debug.ErlideDebug; import org.erlide.backend.debug.model.ErlangDebugTarget; import org.erlide.core.ErlangCore; import org.erlide.runtime.api.ErlDebugFlags; import org.erlide.runtime.rpc.IOtpRpc; import org.erlide.ui.internal.ErlideUIPlugin; import org.erlide.util.ErlLogger; import com.ericsson.otp.erlang.OtpErlangPid; public class ErlangDebuggerBackendListener implements IBackendListener { @Override public void runtimeRemoved(final IBackend backend) { } @Override public void runtimeAdded(final IBackend backend) { } @Override public void moduleLoaded(final IBackend backend, final IProject project, final String moduleName) { try { final ErlangDebugTarget erlangDebugTarget = debugTargetOfBackend( backend.getOtpRpc()); if (erlangDebugTarget != null && erlangDebugTarget.getInterpretedModules().contains(moduleName)) { if (isModuleRunningInInterpreter(erlangDebugTarget, backend.getOtpRpc(), moduleName)) { abortContinueDialog(erlangDebugTarget); } else { final ILaunchConfiguration launchConfiguration = erlangDebugTarget .getLaunch().getLaunchConfiguration(); final EnumSet<ErlDebugFlags> debugFlags = ErlDebugFlags .makeSet(launchConfiguration.getAttribute( ErlRuntimeAttributes.DEBUG_FLAGS, ErlDebugFlags .getFlag(ErlDebugFlags.DEFAULT_DEBUG_FLAGS))); final boolean distributed = debugFlags .contains(ErlDebugFlags.DISTRIBUTED_DEBUG); erlangDebugTarget.interpret(project, moduleName, distributed, true); } } } catch (final CoreException e) { ErlLogger.error(e); } } private ErlangDebugTarget debugTargetOfBackend(final IOtpRpc backend) { final IDebugTarget[] debugTargets = DebugPlugin.getDefault().getLaunchManager() .getDebugTargets(); for (final IDebugTarget debugTarget : debugTargets) { if (debugTarget instanceof ErlangDebugTarget) { final ErlangDebugTarget erlangDebugTarget = (ErlangDebugTarget) debugTarget; if (erlangDebugTarget.getBackend().getOtpRpc().equals(backend)) { return erlangDebugTarget; } } } return null; } private void abortContinueDialog(final IDebugTarget target) { // do not report errors for snippet editor targets // that do not support HCR. HCR is simulated by using // a new class loader for each evaluation // final ILaunch launch = target.getLaunch(); // if (launch.getAttribute(ScrapbookLauncher.SCRAPBOOK_LAUNCH) != null) // { // if (!target.supportsHotCodeReplace()) { // return; // } // } final Display display = ErlideUIPlugin.getStandardDisplay(); if (display.isDisposed()) { return; } String name = null; try { name = target.getName(); } catch (final DebugException e) { name = ""; // never happens, ErlangDebugTarget doesn't throw this... } final String vmName = name; final ILaunchConfiguration config = target.getLaunch().getLaunchConfiguration(); final String launchName = config != null ? config.getName() : "<unknown>"; final IStatus status = new Status(IStatus.ERROR, ErlangCore.PLUGIN_ID, IStatus.ERROR, "Can't replace code", null); final String title = "Code Replace Failed"; final String message = MessageFormat.format( "Some code changes cannot be replaced when being debugged.", new Object[] { vmName, launchName }); display.asyncExec(new Runnable() { @Override public void run() { if (display.isDisposed()) { return; } final Shell shell = ErlideUIPlugin.getActiveWorkbenchShell(); final HotCodeReplaceErrorDialog dialog = new HotCodeReplaceErrorDialog( shell, title, message, status, target); dialog.setBlockOnOpen(false); dialog.open(); } }); } private boolean isModuleRunningInInterpreter( final ErlangDebugTarget erlangDebugTarget, final IOtpRpc backend, final String moduleName) { for (final OtpErlangPid metaPid : erlangDebugTarget.getAllMetaPids()) { final List<String> allModulesOnStack = ErlideDebug .getAllModulesOnStack(backend, metaPid); if (allModulesOnStack != null) { for (final String m : allModulesOnStack) { if (m.equals(moduleName)) { return true; } } } } return false; } }