• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 8111080112

01 Mar 2024 12:07PM UTC coverage: 58.254% (+1.1%) from 57.131%
8111080112

push

github

web-flow
#9: background process (#200)

1519 of 2867 branches covered (52.98%)

Branch coverage included in aggregate %.

3954 of 6528 relevant lines covered (60.57%)

2.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

7.3
cli/src/main/java/com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java
1
package com.devonfw.tools.ide.tool.ide;
2

3
import java.io.IOException;
4
import java.nio.file.Files;
5
import java.nio.file.Path;
6
import java.util.Collection;
7
import java.util.Collections;
8
import java.util.HashMap;
9
import java.util.Iterator;
10
import java.util.Map;
11
import java.util.Set;
12
import java.util.stream.Stream;
13

14
import com.devonfw.tools.ide.cli.CliException;
15
import com.devonfw.tools.ide.common.Tag;
16
import com.devonfw.tools.ide.context.IdeContext;
17
import com.devonfw.tools.ide.io.FileAccess;
18
import com.devonfw.tools.ide.process.ProcessMode;
19
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
20
import com.devonfw.tools.ide.tool.ToolCommandlet;
21
import com.devonfw.tools.ide.tool.eclipse.Eclipse;
22
import com.devonfw.tools.ide.tool.intellij.Intellij;
23
import com.devonfw.tools.ide.tool.vscode.Vscode;
24

25
/**
26
 * {@link ToolCommandlet} for an IDE (integrated development environment) such as {@link Eclipse}, {@link Vscode}, or
27
 * {@link Intellij}.
28
 */
29
public abstract class IdeToolCommandlet extends LocalToolCommandlet {
1✔
30

31
  private Map<String, PluginDescriptor> pluginsMap;
32

33
  private Collection<PluginDescriptor> configuredPlugins;
34

35
  /**
36
   * The constructor.
37
   *
38
   * @param context the {@link IdeContext}.
39
   * @param tool the {@link #getName() tool name}.
40
   * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of}
41
   *        method.
42
   */
43
  public IdeToolCommandlet(IdeContext context, String tool, Set<Tag> tags) {
44

45
    super(context, tool, tags);
5✔
46
    assert (hasIde(tags));
5!
47
  }
1✔
48

49
  private boolean hasIde(Set<Tag> tags) {
50

51
    for (Tag tag : tags) {
10!
52
      if (tag.isAncestorOf(Tag.IDE)) {
4!
53
        return true;
2✔
54
      }
55
    }
×
56
    throw new IllegalStateException("Tags of IdeTool hat to be connected with tag IDE: " + tags);
×
57
  }
58

59
  private Map<String, PluginDescriptor> getPluginsMap() {
60

61
    if (this.pluginsMap == null) {
×
62
      Map<String, PluginDescriptor> map = new HashMap<>();
×
63
      Path pluginsPath = getPluginsConfigPath();
×
64
      if (Files.isDirectory(pluginsPath)) {
×
65
        try (Stream<Path> childStream = Files.list(pluginsPath)) {
×
66
          Iterator<Path> iterator = childStream.iterator();
×
67
          while (iterator.hasNext()) {
×
68
            Path child = iterator.next();
×
69
            String filename = child.getFileName().toString();
×
70
            if (filename.endsWith(IdeContext.EXT_PROPERTIES) && Files.exists(child)) {
×
71
              PluginDescriptor descriptor = PluginDescriptorImpl.of(child, this.context, isPluginUrlNeeded());
×
72
              map.put(descriptor.getName(), descriptor);
×
73
            }
74
          }
×
75
        } catch (IOException e) {
×
76
          throw new IllegalStateException("Failed to list children of directory " + pluginsPath, e);
×
77
        }
×
78
      }
79
      this.pluginsMap = map;
×
80
    }
81
    return this.pluginsMap;
×
82
  }
83

84
  private Path getPluginsConfigPath() {
85

86
    return this.context.getSettingsPath().resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS);
×
87
  }
88

89
  /**
90
   * @return {@code true} if {@link PluginDescriptor#getUrl() plugin URL} property is needed, {@code false} otherwise.
91
   */
92
  protected boolean isPluginUrlNeeded() {
93

94
    return false;
×
95
  }
96

97
  /**
98
   * @return the immutable {@link Collection} of {@link PluginDescriptor}s configured for this IDE tool.
99
   */
100
  public Collection<PluginDescriptor> getConfiguredPlugins() {
101

102
    if (this.configuredPlugins == null) {
×
103
      this.configuredPlugins = Collections.unmodifiableCollection(getPluginsMap().values());
×
104
    }
105
    return this.configuredPlugins;
×
106
  }
107

108
  /**
109
   * @return the {@link Path} where the plugins of this {@link IdeToolCommandlet} shall be installed.
110
   */
111
  public Path getPluginsInstallationPath() {
112

113
    // TODO add edition???
114
    return this.context.getPluginsPath().resolve(this.tool);
×
115
  }
116

117
  /**
118
   * @param key the filename of the properties file configuring the requested plugin (typically excluding the
119
   *        ".properties" extension).
120
   * @return the {@link PluginDescriptor} for the given {@code key}.
121
   */
122
  public PluginDescriptor getPlugin(String key) {
123

124
    if (key == null) {
×
125
      return null;
×
126
    }
127
    if (key.endsWith(IdeContext.EXT_PROPERTIES)) {
×
128
      key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length());
×
129
    }
130
    PluginDescriptor pluginDescriptor = getPluginsMap().get(key);
×
131
    if (pluginDescriptor == null) {
×
132
      throw new CliException(
×
133
          "Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties");
×
134
    }
135
    return pluginDescriptor;
×
136
  }
137

138
  @Override
139
  protected boolean doInstall(boolean silent) {
140

141
    boolean newlyInstalled = super.doInstall(silent);
×
142
    // post installation...
143
    boolean installPlugins = newlyInstalled;
×
144
    Path pluginsInstallationPath = getPluginsInstallationPath();
×
145
    if (newlyInstalled) {
×
146
      this.context.getFileAccess().delete(pluginsInstallationPath);
×
147
    } else if (!Files.isDirectory(pluginsInstallationPath)) {
×
148
      installPlugins = true;
×
149
    }
150
    if (installPlugins) {
×
151
      for (PluginDescriptor plugin : getPluginsMap().values()) {
×
152
        if (plugin.isActive()) {
×
153
          installPlugin(plugin);
×
154
        } else {
155
          handleInstall4InactivePlugin(plugin);
×
156
        }
157
      }
×
158
    }
159
    return newlyInstalled;
×
160
  }
161

162
  /**
163
   * @param plugin the in{@link PluginDescriptor#isActive() active} {@link PluginDescriptor} that is skipped for regular
164
   *        plugin installation.
165
   */
166
  protected void handleInstall4InactivePlugin(PluginDescriptor plugin) {
167

168
    this.context.debug("Omitting installation of inactive plugin {} ({}).", plugin.getName(), plugin.getId());
×
169
  }
×
170

171
  /**
172
   * @param plugin the {@link PluginDescriptor} to install.
173
   */
174
  public abstract void installPlugin(PluginDescriptor plugin);
175

176
  /**
177
   * @param plugin the {@link PluginDescriptor} to uninstall.
178
   */
179
  public void uninstallPlugin(PluginDescriptor plugin) {
180

181
    Path pluginsPath = getPluginsInstallationPath();
×
182
    if (!Files.isDirectory(pluginsPath)) {
×
183
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not exist at {}",
×
184
          plugin.getName(), plugin.getId(), pluginsPath);
×
185
      return;
×
186
    }
187
    FileAccess fileAccess = this.context.getFileAccess();
×
188
    Path match = fileAccess.findFirst(pluginsPath, p -> p.getFileName().toString().startsWith(plugin.getId()), false);
×
189
    if (match == null) {
×
190
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not contain a match at {}",
×
191
          plugin.getName(), plugin.getId(), pluginsPath);
×
192
      return;
×
193
    }
194
    fileAccess.delete(match);
×
195
  }
×
196

197
  @Override
198
  public void run() {
199

200
    configureWorkspace();
×
201
    runIde(this.arguments.asArray());
×
202
  }
×
203

204
  /**
205
   * Run the actual IDE.
206
   *
207
   * @param args the additional arguments to pass to the IDE.
208
   */
209
  protected void runIde(String... args) {
210

211
    runTool(ProcessMode.DEFAULT, null, args);
×
212
  }
×
213

214
  /**
215
   * Configure the workspace for this IDE using the templates from the settings.
216
   */
217
  protected void configureWorkspace() {
218

219
    Path settingsWorkspaceFolder = this.context.getSettingsPath().resolve(this.tool)
×
220
        .resolve(IdeContext.FOLDER_WORKSPACE);
×
221
    FileAccess fileAccess = this.context.getFileAccess();
×
222
    if (!fileAccess.isExpectedFolder(settingsWorkspaceFolder)) {
×
223
      return;
×
224
    }
225
    Path setupFolder = settingsWorkspaceFolder.resolve(IdeContext.FOLDER_SETUP);
×
226
    Path updateFolder = settingsWorkspaceFolder.resolve(IdeContext.FOLDER_UPDATE);
×
227
    if (!fileAccess.isExpectedFolder(setupFolder) && !fileAccess.isExpectedFolder(updateFolder)) {
×
228
      return;
×
229
    }
230
    Path ideWorkspacePath = this.context.getWorkspacePath();
×
231
    if (!fileAccess.isExpectedFolder(ideWorkspacePath)) {
×
232
      return; // should actually never happen...
×
233
    }
234
    this.context.step("Configuring workspace {} for IDE {}", ideWorkspacePath.getFileName(), this.tool);
×
235
    this.context.getWorkspaceMerger().merge(setupFolder, updateFolder, this.context.getVariables(), ideWorkspacePath);
×
236
  }
×
237

238
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc