/*******************************************************************************
* Copyright (c) 2008 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
*******************************************************************************/
package org.erlide.backend.api;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jdt.annotation.NonNull;
import org.erlide.backend.api.ICodeBundle.CodeContext;
import org.erlide.backend.debug.ErlDebugConstants;
import org.erlide.backend.launch.IErlangLaunchDelegateConstants;
import org.erlide.engine.model.erlang.SourceKind;
import org.erlide.engine.model.root.IBeamLocator;
import org.erlide.runtime.api.ErlDebugFlags;
import org.erlide.runtime.api.RuntimeData;
import org.erlide.runtime.runtimeinfo.RuntimeInfo;
import org.erlide.runtime.runtimeinfo.RuntimeVersion;
import org.erlide.util.ErlLogger;
import org.erlide.util.ErlangFunctionCall;
import org.erlide.util.HostnameChecker;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
public final class BackendData extends RuntimeData {
public static final String PROJECT_NAME_SEPARATOR = ";";
private IBeamLocator beamLocator;
protected ILaunch launch;
private Collection<IProject> projects;
private CodeContext context = CodeContext.COMMON;
@SuppressWarnings("unchecked")
public BackendData(@NonNull final RuntimeInfo info,
@NonNull final ILaunchConfiguration config, final String mode,
final boolean toBeManaged) {
super(info, mode);
projects = Lists.newArrayList();
try {
cookie = config.getAttribute(ErlRuntimeAttributes.COOKIE, cookie);
managed = config.getAttribute(ErlRuntimeAttributes.MANAGED, managed);
restartable = config.getAttribute(ErlRuntimeAttributes.RESTARTABLE,
restartable);
startShell = config.getAttribute(ErlRuntimeAttributes.SHELL, startShell);
console = config.getAttribute(ErlRuntimeAttributes.CONSOLE, console);
nodeName = config.getAttribute(ErlRuntimeAttributes.NODE_NAME, nodeName);
longName = config.getAttribute(ErlRuntimeAttributes.USE_LONG_NAME, longName);
extraArgs = config.getAttribute(ErlRuntimeAttributes.EXTRA_ARGS, extraArgs);
workingDir = config.getAttribute(ErlRuntimeAttributes.WORKING_DIR,
workingDir);
env = config.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, env);
initialCall = createInitialCall(config);
debugFlags = ErlDebugFlags.makeSet(config.getAttribute(
ErlRuntimeAttributes.DEBUG_FLAGS, ErlDebugFlags.getFlag(debugFlags)));
loadOnAllNodes = config.getAttribute(ErlRuntimeAttributes.LOAD_ALL_NODES,
loadOnAllNodes);
internal = config.getAttribute(ErlRuntimeAttributes.INTERNAL, internal);
projects = getProjects(config);
final List<String> defList = Lists.newArrayList();
final List<String> intMods = config
.getAttribute(ErlRuntimeAttributes.DEBUG_INTERPRET_MODULES, defList);
initialInterpretedModules = addBreakpointProjectsAndModules(getProjects(),
intMods);
} catch (final CoreException e1) {
ErlLogger.warn(e1);
}
if (extraArgs != null) {
runtimeInfo = new RuntimeInfo.Builder(info).withArgs(extraArgs).build();
}
try {
if (config.getAttribute(ErlRuntimeAttributes.EXTRA_ARGS, "").equals("")) {
setExtraArgs(info.getArgs());
}
} catch (final CoreException e) {
}
setManaged(toBeManaged);
}
public BackendData(final RuntimeInfo info) {
super(info, "run", getDefaultWorkingDir());
projects = Lists.newArrayList();
}
private static String getDefaultWorkingDir() {
final IWorkspaceRoot wroot = ResourcesPlugin.getWorkspace().getRoot();
return wroot.getLocation().toPortableString();
}
private List<IProject> gatherProjects(final String[] projectNames) {
final List<IProject> myProjects = Lists.newArrayList();
for (final String s : projectNames) {
final IProject project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(s);
if (project == null) {
ErlLogger.error("Launch: project not found: '%s'!", s);
continue;
}
myProjects.add(project);
}
return myProjects;
}
public static Set<String> addBreakpointProjectsAndModules(
final Collection<IProject> projects, final List<String> interpretedModules) {
final IBreakpointManager bpm = DebugPlugin.getDefault().getBreakpointManager();
final Set<String> result = new HashSet<>(interpretedModules);
for (final IBreakpoint bp : bpm
.getBreakpoints(ErlDebugConstants.ID_ERLANG_DEBUG_MODEL)) {
final IMarker m = bp.getMarker();
final IResource r = m.getResource();
final String name = r.getName();
if (SourceKind.hasErlExtension(name)) {
final IProject p = r.getProject();
if (projects == null || projects.contains(p)) {
final String s = p.getName() + ":" + name;
result.add(s);
}
}
}
return result;
}
public ILaunch getLaunch() {
return launch;
}
public void setLaunch(final ILaunch launch) {
this.launch = launch;
}
public ILaunchConfiguration asLaunchConfiguration() {
final ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
final ILaunchConfigurationType type = manager.getLaunchConfigurationType(
IErlangLaunchDelegateConstants.CONFIGURATION_TYPE_INTERNAL);
ILaunchConfigurationWorkingCopy workingCopy;
try {
final RuntimeInfo info = getRuntimeInfo();
final String name = getNodeName();
workingCopy = type.newInstance(null, name);
if (info.getVersion().isReleaseCompatible(new RuntimeVersion(17))) {
workingCopy.setAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING,
Charsets.UTF_8.name());
} else {
workingCopy.setAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING,
Charsets.ISO_8859_1.name());
}
workingCopy.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID,
"org.erlide.backend.ertsProcessFactory");
workingCopy.setAttribute(ErlRuntimeAttributes.NODE_NAME, getNodeName());
workingCopy.setAttribute(ErlRuntimeAttributes.RUNTIME_NAME, info.getName());
workingCopy.setAttribute(ErlRuntimeAttributes.COOKIE, getCookie());
// workingCopy.setAttribute(ErlLaunchAttributes.CONSOLE,
// !options.contains(BackendOptions.NO_CONSOLE));
workingCopy.setAttribute(ErlRuntimeAttributes.USE_LONG_NAME, hasLongName());
workingCopy.setAttribute(ErlRuntimeAttributes.INTERNAL, isInternal());
return workingCopy;
} catch (final CoreException e) {
ErlLogger.error(e);
return null;
}
}
public Collection<IProject> getProjects() {
return projects;
}
private Collection<IProject> getProjects(final ILaunchConfiguration config)
throws CoreException {
String prjs;
prjs = config.getAttribute(ErlRuntimeAttributes.PROJECTS, "");
final String[] projectNames = prjs.length() == 0 ? new String[] {}
: prjs.split(PROJECT_NAME_SEPARATOR);
return gatherProjects(projectNames);
}
public void setBeamLocator(final IBeamLocator beamLocator) {
this.beamLocator = beamLocator;
}
public IBeamLocator getBeamLocator() {
return beamLocator;
}
@Override
public String getQualifiedNodeName() {
final String erlangHostName = HostnameChecker.getInstance()
.getErlangHostName(hasLongName());
final String name = getNodeName();
final boolean hasHost = name.contains("@");
return hasHost ? name : name + "@" + erlangHostName;
}
private ErlangFunctionCall createInitialCall(final ILaunchConfiguration config)
throws CoreException {
final String module = config.getAttribute(ErlRuntimeAttributes.MODULE, "");
final String function = config.getAttribute(ErlRuntimeAttributes.FUNCTION, "");
final String args = config.getAttribute(ErlRuntimeAttributes.ARGUMENTS, "");
return new ErlangFunctionCall(module, function, args);
}
public CodeContext getContext() {
return context;
}
public void setContext(final CodeContext context) {
this.context = context;
}
}