--- /dev/null
+package com.intellij.execution.configuration;
+
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.ModuleBasedConfiguration;
+import com.intellij.execution.configurations.RunConfigurationModule;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author traff
+ */
+public abstract class AbstractRunConfiguration extends ModuleBasedConfiguration<RunConfigurationModule> {
+ private Map<String, String> myEnvs = new LinkedHashMap<String, String>();
+ private boolean myPassParentEnvs = true;
+
+ public AbstractRunConfiguration(String name, RunConfigurationModule configurationModule, ConfigurationFactory factory) {
+ super(name, configurationModule, factory);
+ }
+
+ public Map<String, String> getEnvs() {
+ return myEnvs;
+ }
+
+ public void setEnvs(final Map<String, String> envs) {
+ myEnvs = envs;
+ }
+
+ public boolean isPassParentEnvs() {
+ return myPassParentEnvs;
+ }
+
+ public void setPassParentEnvs(final boolean passParentEnvs) {
+ myPassParentEnvs = passParentEnvs;
+ }
+
+ public enum RunnerType {
+ RUN,
+ DEBUG
+ }
+}
--- /dev/null
+package com.intellij.execution.configuration;
+
+import com.intellij.execution.Location;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author traff
+ */
+public abstract class RunConfigurationExtension<T extends AbstractRunConfiguration> {
+ @NotNull
+ protected abstract String getSerializationId();
+
+ protected abstract void readExternal(@NotNull final T runConfiguration,
+ @NotNull final Element element) throws InvalidDataException;
+
+ protected abstract void writeExternal(@NotNull final T runConfiguration,
+ @NotNull final Element element) throws WriteExternalException;
+
+ @Nullable
+ protected abstract Icon getIcon(@NotNull final T configuration);
+
+ @Nullable
+ protected abstract <P extends T> SettingsEditor<P> createEditor(@NotNull final P configuration);
+
+ @Nullable
+ protected abstract String getEditorTitle();
+
+ /**
+ * @param configuration Run configuration
+ * @return True if extension in general applicable to given run configuration - just to attach settings tab, etc. But extension may be
+ * turned off in it's settings. E.g. RCov in general available for given run configuration, but may be turned off.
+ */
+ protected abstract boolean isApplicableFor(@NotNull final T configuration);
+
+ /**
+ * @param applicableConfiguration Applicable run configuration
+ * @return True if extension is tuned on in configuration extension settings.
+ * E.g. RCov is turned on for given run configuration.
+ */
+ protected abstract boolean isEnabledFor(@NotNull final T applicableConfiguration);
+
+ protected abstract void patchCommandLine(@NotNull final T configuration,
+ @NotNull final GeneralCommandLine cmdLine,
+ @NotNull final AbstractRunConfiguration.RunnerType type);
+
+ /**
+ * Validate extensions after general configuration validation passed
+ * @param configuration
+ * @param isExecution
+ * @param <T>
+ * @throws com.intellij.execution.ExecutionException
+ */
+ protected abstract void validateConfiguration(@NotNull final T configuration,
+ final boolean isExecution) throws Exception;
+
+ /**
+ * Setup extension settings for created run configuration
+ * @param configuration Configuration
+ * @param location
+ */
+ protected abstract void extendCreatedConfiguration(@NotNull final T configuration,
+ @NotNull final Location location);
+
+ protected abstract void extendTemplateConfiguration(@NotNull final T configuration);
+
+ protected abstract void attachToProcess(@NotNull final T configuration,
+ @NotNull final ProcessHandler handler,
+ @NotNull final AbstractRunConfiguration.RunnerType type);
+}
--- /dev/null
+package com.intellij.execution.configuration;
+
+import com.google.common.collect.Maps;
+import com.intellij.execution.Location;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.options.SettingsEditorGroup;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.ui.LayeredIcon;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author traff
+ */
+public class RunConfigurationExtensionsManager<U extends AbstractRunConfiguration, T extends RunConfigurationExtension<U>> {
+ public static final Key<List<Element>> RUN_EXTENSIONS = Key.create("run.extension.elements");
+ private static final String EXT_ID_ATTR = "ID";
+ private static final String EXTENSION_ROOT_ATTR = "EXTENSION";
+ protected final ExtensionPointName<T> myExtensionPointName;
+
+ public RunConfigurationExtensionsManager(ExtensionPointName<T> extensionPointName) {
+ myExtensionPointName = extensionPointName;
+ }
+
+ public void readExternal(@NotNull final U configuration,
+ @NotNull final Element parentNode) throws InvalidDataException {
+ final List<Element> children = parentNode.getChildren(EXTENSION_ROOT_ATTR);
+ final Map<String, T> extensions = Maps.newHashMap();
+ for (T extension : getApplicableExtensions(configuration)) {
+ extensions.put(extension.getSerializationId(), extension);
+ }
+
+ // if some of extensions settings weren't found we should just keep it because some plugin with extension
+ // may be turned off
+ boolean found = true;
+ for (Object o : children) {
+ final Element element = (Element)o;
+ final String extensionName = element.getAttributeValue(EXT_ID_ATTR);
+ final T extension = extensions.remove(extensionName);
+ if (extension != null) {
+ extension.readExternal(configuration, element);
+ }
+ else {
+ found = false;
+ }
+ }
+ if (!found) {
+ configuration.putCopyableUserData(RUN_EXTENSIONS, children);
+ }
+ }
+
+ public void writeExternal(@NotNull final U configuration,
+ @NotNull final Element parentNode) throws WriteExternalException {
+ final TreeMap<String, Element> map = Maps.newTreeMap();
+ final List<Element> elements = configuration.getCopyableUserData(RUN_EXTENSIONS);
+ if (elements != null) {
+ for (Element el : elements) {
+ final String name = el.getAttributeValue(EXT_ID_ATTR);
+ map.put(name, (Element)el.clone());
+ }
+ }
+
+ for (T extension : getApplicableExtensions(configuration)) {
+ Element el = new Element(EXTENSION_ROOT_ATTR);
+ el.setAttribute(EXT_ID_ATTR, extension.getSerializationId());
+ extension.writeExternal(configuration, el);
+ map.put(extension.getSerializationId(), el);
+ }
+
+ for (Element val : map.values()) {
+ parentNode.addContent(val);
+ }
+ }
+
+ public Icon getIcon(@NotNull final U configuration, @NotNull final Icon icon) {
+ for (T extension : getApplicableExtensions(configuration)) {
+ final Icon extIcon = extension.getIcon(configuration);
+ if (extIcon != null) {
+ return LayeredIcon.create(icon, extIcon);
+ }
+ }
+ return icon;
+ }
+
+ public <V extends U> void appendEditors(@NotNull final U configuration,
+ @NotNull final SettingsEditorGroup<V> group) {
+ for (T extension : getApplicableExtensions(configuration)) {
+ @SuppressWarnings("unchecked")
+ final SettingsEditor<V> editor = extension.createEditor((V)configuration);
+ if (editor != null) {
+ group.addEditor(extension.getEditorTitle(), editor);
+ }
+ }
+ }
+
+ public void validateConfiguration(@NotNull final U configuration,
+ final boolean isExecution) throws Exception {
+ // only for enabled extensions
+ for (T extension : getEnabledExtensions(configuration)) {
+ extension.validateConfiguration(configuration, isExecution);
+ }
+ }
+
+ public void extendCreatedConfiguration(@NotNull final U configuration,
+ @NotNull final Location location) {
+ for (T extension : getApplicableExtensions(configuration)) {
+ extension.extendCreatedConfiguration(configuration, location);
+ }
+ }
+
+ public void extendTemplateConfiguration(@NotNull final U configuration) {
+ for (T extension : getApplicableExtensions(configuration)) {
+ extension.extendTemplateConfiguration(configuration);
+ }
+ }
+
+ public void patchCommandLine(@NotNull final U configuration,
+ @NotNull final GeneralCommandLine cmdLine,
+ @NotNull final AbstractRunConfiguration.RunnerType type) {
+ // only for enabled extensions
+ for (T extension : getEnabledExtensions(configuration)) {
+ extension.patchCommandLine(configuration, cmdLine, type);
+ }
+ }
+
+ public void attachExtensionsToProcess(@NotNull final U configuration,
+ @NotNull final ProcessHandler handler,
+ @NotNull final AbstractRunConfiguration.RunnerType type) {
+ // only for enabled extensions
+ for (T extension : getEnabledExtensions(configuration)) {
+ extension.attachToProcess(configuration, handler, type);
+ }
+ }
+
+ private List<T> getApplicableExtensions(@NotNull final U configuration) {
+ final List<T> extensions = new ArrayList<T>();
+ for (T extension : Extensions.getExtensions(myExtensionPointName)) {
+ if (extension.isApplicableFor(configuration)) {
+ extensions.add(extension);
+ }
+ }
+ return extensions;
+ }
+
+ private List<T> getEnabledExtensions(@NotNull final U configuration) {
+ final List<T> extensions = new ArrayList<T>();
+ for (T extension : Extensions.getExtensions(myExtensionPointName)) {
+ if (extension.isApplicableFor(configuration) && extension.isEnabledFor(configuration)) {
+ extensions.add(extension);
+ }
+ }
+ return extensions;
+ }
+}
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Mocks" level="project" />
+ <orderEntry type="library" name="Guava" level="project" />
</component>
</module>
return Collections.unmodifiableList(params);
}
+ public void clearAll() {
+ myParameters.clear();
+ myGroups.clear();
+ }
+
public void prepend(@NonNls final String parameter) {
addAt(0, parameter);
}
+ public void prependAll(@NonNls final String... parameter) {
+ for (int i = parameter.length - 1; i >= 0; i--) {
+ addAt(0, parameter[i]);
+ }
+ }
+
public void addParametersString(final String parameters) {
if (parameters != null) {
final String[] split = parse(parameters);
}
private void replaceOrAdd(final @NonNls String parameterPrefix, final @NonNls String replacement, final int position) {
- for (ListIterator<String> iterator = myParameters.listIterator(); iterator.hasNext();) {
+ for (ListIterator<String> iterator = myParameters.listIterator(); iterator.hasNext(); ) {
final String param = iterator.next();
if (param.startsWith(parameterPrefix)) {
if ("".equals(replacement)) {
return;
}
}
- if(!"".equals(replacement)) {
+ if (!"".equals(replacement)) {
myParameters.add(position, replacement);
}
}
/**
* <p>Joins list of parameters into single string, which may be then parsed back into list by {@link #parse(String)}.</p>
- *
+ * <p/>
* <p>
- * <strong>Conversion rules:</strong>
- * <ul>
- * <li>double quotes are escaped by backslash (<code>\</code>);</li>
- * <li>empty parameters parameters and parameters with spaces inside are surrounded with double quotes (<code>"</code>);</li>
- * <li>parameters are separated by single whitespace.</li>
- * </ul>
+ * <strong>Conversion rules:</strong>
+ * <ul>
+ * <li>double quotes are escaped by backslash (<code>\</code>);</li>
+ * <li>empty parameters parameters and parameters with spaces inside are surrounded with double quotes (<code>"</code>);</li>
+ * <li>parameters are separated by single whitespace.</li>
+ * </ul>
* </p>
- *
+ * <p/>
* <p><strong>Examples:</strong></p>
* <p>
- * <code>['a', 'b'] => 'a b'</code><br/>
- * <code>['a="1 2"', 'b'] => '"a \"1 2\"" b'</code>
+ * <code>['a', 'b'] => 'a b'</code><br/>
+ * <code>['a="1 2"', 'b'] => '"a \"1 2\"" b'</code>
* </p>
*
* @param parameters a list of parameters to join.
/**
* <p>Converts single parameter string (as created by {@link #join(java.util.List)}) into list of parameters.</p>
- *
+ * <p/>
* <p>
- * <strong>Conversion rules:</strong>
- * <ul>
- * <li>starting/whitespaces are trimmed;</li>
- * <li>parameters are split by whitespaces, whitespaces itself are dropped</li>
- * <li>parameters inside double quotes (<code>"a b"</code>) are kept as single one;</li>
- * <li>double quotes are dropped, escaped double quotes (<code>\"</code>) are un-escaped.</li>
- * </ul>
+ * <strong>Conversion rules:</strong>
+ * <ul>
+ * <li>starting/whitespaces are trimmed;</li>
+ * <li>parameters are split by whitespaces, whitespaces itself are dropped</li>
+ * <li>parameters inside double quotes (<code>"a b"</code>) are kept as single one;</li>
+ * <li>double quotes are dropped, escaped double quotes (<code>\"</code>) are un-escaped.</li>
+ * </ul>
* </p>
- *
+ * <p/>
* <p><strong>Examples:</strong></p>
* <p>
- * <code>' a b ' => ['a', 'b']</code><br/>
- * <code>'a="1 2" b' => ['a=1 2', 'b']</code><br/>
- * <code>'a " " b' => ['a', ' ', 'b']</code><br/>
- * <code>'"a \"1 2\"" b' => ['a="1 2"', 'b']</code>
+ * <code>' a b ' => ['a', 'b']</code><br/>
+ * <code>'a="1 2" b' => ['a=1 2', 'b']</code><br/>
+ * <code>'a " " b' => ['a', ' ', 'b']</code><br/>
+ * <code>'"a \"1 2\"" b' => ['a="1 2"', 'b']</code>
* </p>
*
* @param string parameter string to split.
public String expandMacros(String text) {
final Map<String, String> macroMap = getMacroMap();
- final Set<String> set = macroMap.keySet();
- for (final String from : set) {
- final String to = macroMap.get(from);
- text = StringUtil.replace(text, from, to, true);
- }
+ final Set<String> set = macroMap.keySet();
+ for (final String from : set) {
+ final String to = macroMap.get(from);
+ text = StringUtil.replace(text, from, to, true);
+ }
return text;
}
final PathMacros pathMacros = PathMacros.getInstance();
final Set<String> names = pathMacros.getAllMacroNames();
for (String name : names) {
- myMacroMap.put("${" + name + "}", pathMacros.getValue(name));
+ myMacroMap.put("${" + name + "}", pathMacros.getValue(name));
}
final Map<String, String> env = EnvironmentUtil.getEnviromentProperties();
for (String name : env.keySet()) {
}
private static class ParametersTokenizer {
- private ParametersTokenizer() { }
+ private ParametersTokenizer() {
+ }
@NotNull
public static String encode(@NotNull final List<String> parameters) {