From 998ef92c86551576eaca1fc8e2f005a67fb8c18d Mon Sep 17 00:00:00 2001 From: diiinesh <63147290+diiinesh@users.noreply.github.com> Date: Mon, 27 May 2024 09:40:54 +0200 Subject: [PATCH] devonfw/ide#1309: Improve plugin managment (#229) --- .../tools/ide/tool/PluginBasedCommandlet.java | 38 +++------- .../devonfw/tools/ide/tool/PluginMaps.java | 75 +++++++++++++++++++ .../ide/tool/PluginBasedCommandletTest.java | 13 ++-- 3 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 cli/src/main/java/com/devonfw/tools/ide/tool/PluginMaps.java diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/PluginBasedCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/PluginBasedCommandlet.java index 41b7b5df7..6f59024dc 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/PluginBasedCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/PluginBasedCommandlet.java @@ -10,11 +10,7 @@ import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -23,9 +19,7 @@ */ public abstract class PluginBasedCommandlet extends LocalToolCommandlet { - private Map pluginsMap; - - private Collection configuredPlugins; + private PluginMaps pluginsMap; /** * The constructor. @@ -40,10 +34,10 @@ public PluginBasedCommandlet(IdeContext context, String tool, Set tags) { super(context, tool, tags); } - protected Map getPluginsMap() { + protected PluginMaps getPluginsMap() { if (this.pluginsMap == null) { - Map map = new HashMap<>(); + PluginMaps map = new PluginMaps(context); // Load project-specific plugins Path pluginsPath = getPluginsConfigPath(); @@ -60,16 +54,13 @@ protected Map getPluginsMap() { return this.pluginsMap; } - private void loadPluginsFromDirectory(Map map, Path pluginsPath) { + private void loadPluginsFromDirectory(PluginMaps map, Path pluginsPath) { List children = this.context.getFileAccess() .listChildren(pluginsPath, p -> p.getFileName().toString().endsWith(IdeContext.EXT_PROPERTIES)); for (Path child : children) { PluginDescriptor descriptor = PluginDescriptorImpl.of(child, this.context, isPluginUrlNeeded()); - PluginDescriptor duplicate = map.put(descriptor.getName(), descriptor); - if (duplicate != null) { - this.context.info("Plugin {} from project is overridden by {}", descriptor.getName(), child); - } + map.add(descriptor); } } @@ -94,17 +85,6 @@ private Path getUserHomePluginsConfigPath() { return this.context.getUserHomeIde().resolve("settings").resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS); } - /** - * @return the immutable {@link Collection} of {@link PluginDescriptor}s configured for this IDE tool. - */ - public Collection getConfiguredPlugins() { - - if (this.configuredPlugins == null) { - this.configuredPlugins = Collections.unmodifiableCollection(getPluginsMap().values()); - } - return this.configuredPlugins; - } - /** * @return the {@link Path} where the plugins of this {@link IdeToolCommandlet} shall be installed. */ @@ -152,7 +132,9 @@ public PluginDescriptor getPlugin(String key) { if (key.endsWith(IdeContext.EXT_PROPERTIES)) { key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length()); } - PluginDescriptor pluginDescriptor = getPluginsMap().get(key); + + PluginMaps pluginMaps = getPluginsMap(); + PluginDescriptor pluginDescriptor = pluginMaps.getByName(key); if (pluginDescriptor == null) { throw new CliException( "Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties"); @@ -160,6 +142,7 @@ public PluginDescriptor getPlugin(String key) { return pluginDescriptor; } + @Override protected boolean doInstall(boolean silent) { @@ -173,7 +156,8 @@ protected boolean doInstall(boolean silent) { installPlugins = true; } if (installPlugins) { - for (PluginDescriptor plugin : getPluginsMap().values()) { + PluginMaps pluginMaps = getPluginsMap(); + for (PluginDescriptor plugin : pluginMaps.getPlugins()) { if (plugin.isActive()) { installPlugin(plugin); } else { diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/PluginMaps.java b/cli/src/main/java/com/devonfw/tools/ide/tool/PluginMaps.java new file mode 100644 index 000000000..dcd728c5d --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/PluginMaps.java @@ -0,0 +1,75 @@ +package com.devonfw.tools.ide.tool; + +import com.devonfw.tools.ide.context.IdeContext; +import com.devonfw.tools.ide.tool.ide.PluginDescriptor; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * A wrapper class for holding two maps of plugin descriptors: one keyed by plugin ID and the other keyed by plugin name. + */ +public class PluginMaps { + private final Map mapById; + private final Map mapByName; + + + private final IdeContext context; + + /** + * The constructor. + * @param context the {@link IdeContext}. + */ + public PluginMaps(IdeContext context) { + super(); + this.context = context; + this.mapById = new HashMap<>(); + this.mapByName = new HashMap<>(); + } + + /** + * @return the {@link PluginDescriptor} for the given {@link PluginDescriptor#getId() ID} or {@code null} if not found. + */ + public PluginDescriptor getById(String id) { + return this.mapById.get(id); + } + + /** + * @return the {@link PluginDescriptor} for the given {@link PluginDescriptor#getName() name} or {@code null} if not found. + */ + public PluginDescriptor getByName(String name) { + return this.mapByName.get(name); + } + + /** + * @return the immutable {@link Collection} of {@link PluginDescriptor}s configured for this IDE tool. + */ + public Collection getPlugins() { + + Map map = this.mapById; + if (map.isEmpty()) { + map = this.mapByName; // potentially plugins for this tool have no ID + } + return Collections.unmodifiableCollection(map.values()); + } + + /** + * Registers a {@link PluginDescriptor} to this map. + */ + protected void add(PluginDescriptor descriptor) { + put(descriptor.getName(), descriptor, this.mapByName); + String id = descriptor.getId(); + if ((id != null) && !id.isEmpty()) { + put(id, descriptor, this.mapById); + } + } + + public void put(String key, PluginDescriptor descriptor, Map map) { + PluginDescriptor duplicate = map.put(key, descriptor); + if (duplicate != null) { + this.context.info("Plugin with key {} was {} but got overridden by {}", key, duplicate, descriptor); + } + } +} diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/PluginBasedCommandletTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/PluginBasedCommandletTest.java index 6e3ae03b1..a41bdab28 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/PluginBasedCommandletTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/PluginBasedCommandletTest.java @@ -6,7 +6,6 @@ import com.devonfw.tools.ide.tool.ide.PluginDescriptor; import org.junit.jupiter.api.Test; -import java.util.Map; import java.util.Set; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -24,21 +23,21 @@ void testGetPluginsMap() { Set tags = null; ExamplePluginBasedCommandlet pluginBasedCommandlet = new ExamplePluginBasedCommandlet(context, tool, tags); - Map pluginsMap = pluginBasedCommandlet.getPluginsMap(); + PluginMaps pluginsMap = pluginBasedCommandlet.getPluginsMap(); assertThat(pluginsMap).isNotNull(); - assertThat(pluginsMap.containsKey("checkstyle")).isTrue(); - assertThat(pluginsMap.containsKey("anyedit")).isTrue(); + assertThat(pluginsMap.getByName("checkstyle")).isNotNull(); + assertThat(pluginsMap.getByName("anyedit")).isNotNull(); - PluginDescriptor plugin1 = pluginsMap.get("checkstyle"); + PluginDescriptor plugin1 = pluginsMap.getByName("checkstyle"); assertNotNull(plugin1); assertThat(plugin1.getName()).isEqualTo("checkstyle"); - PluginDescriptor plugin2 = pluginsMap.get("anyedit"); + PluginDescriptor plugin2 = pluginsMap.getByName("anyedit"); assertNotNull(plugin2); assertThat(plugin2.getName()).isEqualTo("anyedit"); // Check if anyedit plugin has value "false" --> value from user directory assertThat(plugin2.isActive()).isFalse(); } -} +} \ No newline at end of file