summaryrefslogtreecommitdiff
path: root/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java
blob: c52f6c9da729d7f7962bc01bfe9af065119857d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package com.intellij.execution.configuration;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.Location;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RunnerSettings;
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.JDOMUtil;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.StringInterner;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author traff
 */
public class RunConfigurationExtensionsManager<U extends RunConfigurationBase, T extends RunConfigurationExtensionBase<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;
  private final StringInterner myInterner = new StringInterner();

  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(getExtensionRootAttr());
    final Map<String, T> extensions = ContainerUtil.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(getIdAttrName());
      final T extension = extensions.remove(extensionName);
      if (extension != null) {
        extension.readExternal(configuration, element);
      }
      else {
        found = false;
      }
    }
    if (!found) {
      List<Element> copy = new ArrayList<Element>(children.size());
      for (Element child : children) {
        Element clone = (Element)child.clone();
        JDOMUtil.internElement(clone, myInterner);
        copy.add(clone);
      }
      configuration.putCopyableUserData(RUN_EXTENSIONS, copy);
    }
  }

  protected String getIdAttrName() {
    return EXT_ID_ATTR;
  }

  protected String getExtensionRootAttr() {
    return EXTENSION_ROOT_ATTR;
  }

  public void writeExternal(@NotNull final U configuration,
                            @NotNull final Element parentNode) throws WriteExternalException {
    final TreeMap<String, Element> map = ContainerUtil.newTreeMap();
    final List<Element> elements = configuration.getCopyableUserData(RUN_EXTENSIONS);
    if (elements != null) {
      for (Element el : elements) {
        final String name = el.getAttributeValue(getIdAttrName());
        map.put(name, (Element)el.clone());
      }
    }

    for (T extension : getApplicableExtensions(configuration)) {
      Element el = new Element(getExtensionRootAttr());
      el.setAttribute(getIdAttrName(), extension.getSerializationId());
      try {
        extension.writeExternal(configuration, el);
      }
      catch (WriteExternalException e) {
        map.remove(extension.getSerializationId());
        continue;
      }
      map.put(extension.getSerializationId(), el);
    }

    for (Element val : map.values()) {
      parentNode.addContent(val);
    }
  }

  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, null)) {
      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,
                               final RunnerSettings runnerSettings,
                               @NotNull final GeneralCommandLine cmdLine,
                               @NotNull final String runnerId) throws ExecutionException {
    // only for enabled extensions
    for (T extension : getEnabledExtensions(configuration, runnerSettings)) {
      extension.patchCommandLine(configuration, runnerSettings, cmdLine, runnerId);
    }
  }

  public void attachExtensionsToProcess(@NotNull final U configuration,
                                        @NotNull final ProcessHandler handler,
                                        RunnerSettings runnerSettings) {
    // only for enabled extensions
    for (T extension : getEnabledExtensions(configuration, runnerSettings)) {
      extension.attachToProcess(configuration, handler, runnerSettings);
    }
  }

  protected 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;
  }

  protected List<T> getEnabledExtensions(@NotNull final U configuration, @Nullable RunnerSettings runnerSettings) {
    final List<T> extensions = new ArrayList<T>();
    for (T extension : Extensions.getExtensions(myExtensionPointName)) {
      if (extension.isApplicableFor(configuration) && extension.isEnabledFor(configuration, runnerSettings)) {
        extensions.add(extension);
      }
    }
    return extensions;
  }
}