/******************************************************************************* * Copyright (c) 2005 Vlad Dumitrescu 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: Vlad Dumitrescu Jakob Cederlund *******************************************************************************/ package org.erlide.backend.launch; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.LaunchConfigurationDelegate; import org.erlide.backend.BackendCore; import org.erlide.backend.api.BackendData; import org.erlide.backend.api.ErlRuntimeAttributes; import org.erlide.backend.api.IBackend; import org.erlide.backend.api.ICodeBundle.CodeContext; import org.erlide.engine.ErlangEngine; import org.erlide.engine.model.root.IBeamLocator; import org.erlide.runtime.api.IOtpNodeProxy; import org.erlide.runtime.epmd.EpmdWatcher; import org.erlide.runtime.runtimeinfo.RuntimeInfo; import org.erlide.util.ErlLogger; import org.erlide.util.HostnameChecker; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; public class ErlangLaunchDelegate extends LaunchConfigurationDelegate { protected IBackend backend; @Override public void launch(final ILaunchConfiguration config, final String mode, final ILaunch launch, final IProgressMonitor monitor) throws CoreException { final BackendData data = getBackendData(config, mode, launch); if (data == null) { return; } if (data.isManaged()) { setCaptureOutput(launch); } IOtpNodeProxy runtime; if (!isErlangInternalLaunch(launch)) { backend = BackendCore.getBackendManager().createExecutionBackend(data); runtime = backend.getRuntime(); } else { runtime = BackendCore.getBackendManager().getFactory().createNodeProxy(data); } if (data.isManaged()) { startErtsProcess(launch, data, runtime.getProcess()); } } private BackendData getBackendData(final ILaunchConfiguration config, final String mode, final ILaunch launch) throws CoreException { if (config == null) { throw new IllegalArgumentException(); } RuntimeInfo runtimeInfo = BackendCore.getRuntimeInfoCatalog() .getRuntime(config.getAttribute(ErlRuntimeAttributes.RUNTIME_NAME, "")); if (runtimeInfo == null || !runtimeInfo.isValid()) { runtimeInfo = BackendCore.getRuntimeInfoCatalog().getDefaultRuntime(); } if (runtimeInfo == null) { ErlLogger.error("Can't create backend without a runtime defined!"); return null; } final String nodeName = config.getAttribute(ErlRuntimeAttributes.NODE_NAME, ""); final boolean managed = shouldManageNode(nodeName, BackendCore.getEpmdWatcher()); BackendData data = new BackendData(runtimeInfo, config, mode, managed); data = configureBackend(data, mode, launch); return data; } /* * Child classes override this to set specific information */ protected BackendData configureBackend(final BackendData data, final String mode, final ILaunch launch) { data.setLaunch(launch); data.setBeamLocator(ErlangEngine.getInstance().getService(IBeamLocator.class)); if (mode.equals("debug")) { data.setContext(CodeContext.DEBUGGER); } return data; } private void startErtsProcess(final ILaunch launch, final BackendData data, final Process process) { Preconditions.checkArgument(process != null); data.setLaunch(launch); final Map<String, String> map = Maps.newHashMap(); final IProcess erts = DebugPlugin.newProcess(launch, process, data.getNodeName(), map); ErlLogger.debug("Started erts: %s >> %s", erts.getLabel(), data.getNodeName()); } private void setCaptureOutput(final ILaunch launch) { // important, we don't want the "normal" console for the erlide backend final String captureOutput = System.getProperty("erlide.console.stdout", "false"); launch.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, captureOutput); } public static boolean isErlangLaunch(final ILaunch aLaunch) { try { final ILaunchConfiguration cfg = aLaunch.getLaunchConfiguration(); final ILaunchConfigurationType type = cfg.getType(); final String id = type.getIdentifier(); return IErlangLaunchDelegateConstants.CONFIGURATION_TYPE.equals(id) || IErlangLaunchDelegateConstants.CONFIGURATION_TYPE_INTERNAL .equals(id); } catch (final CoreException e) { ErlLogger.warn(e); return false; } } public static boolean isErlangInternalLaunch(final ILaunch aLaunch) { try { final ILaunchConfiguration cfg = aLaunch.getLaunchConfiguration(); final ILaunchConfigurationType type = cfg.getType(); final String id = type.getIdentifier(); return IErlangLaunchDelegateConstants.CONFIGURATION_TYPE_INTERNAL.equals(id); } catch (final CoreException e) { ErlLogger.warn(e); return false; } } private static boolean shouldManageNode(final String name, final EpmdWatcher epmdWatcher) { final int atSignIndex = name.indexOf('@'); String shortName = name; if (atSignIndex > 0) { shortName = name.substring(0, atSignIndex); } boolean isLocal = atSignIndex < 0; if (atSignIndex > 0) { final String hostname = name.substring(atSignIndex + 1); if (HostnameChecker.getInstance().isThisHost(hostname)) { isLocal = true; } } final boolean isRunning = epmdWatcher.hasLocalNode(shortName); final boolean result = isLocal && !isRunning; return result; } }