This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 40b8574209 Add support to extra annotations for disabledGuiElements, 
fixes #6660 (#6661)
40b8574209 is described below

commit 40b857420964a5e2ff96a22111f4f1cbfd31956c
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Feb 26 13:33:55 2026 +0100

    Add support to extra annotations for disabledGuiElements, fixes #6660 
(#6661)
---
 .../hop/core/extension/ExtensionPointMap.java      |  4 ++
 .../apache/hop/core/gui/plugin/GuiRegistry.java    | 70 ++++++++++++++++++++++
 .../metadata/serializer/BaseMetadataProvider.java  |  5 ++
 .../modules/ROOT/pages/disable-ui-elements.adoc    | 13 +++-
 .../main/java/org/apache/hop/ui/hopgui/HopGui.java | 44 +-------------
 .../apache/hop/ui/hopgui/HopGuiEnvironment.java    | 67 +++++++--------------
 .../configuration/tabs/ConfigPluginOptionsTab.java |  6 ++
 7 files changed, 118 insertions(+), 91 deletions(-)

diff --git 
a/core/src/main/java/org/apache/hop/core/extension/ExtensionPointMap.java 
b/core/src/main/java/org/apache/hop/core/extension/ExtensionPointMap.java
index 34f2b78a12..41b0cf9ac7 100644
--- a/core/src/main/java/org/apache/hop/core/extension/ExtensionPointMap.java
+++ b/core/src/main/java/org/apache/hop/core/extension/ExtensionPointMap.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Table;
 import java.util.List;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.gui.plugin.GuiRegistry;
 import org.apache.hop.core.logging.ILogChannel;
 import org.apache.hop.core.logging.LogChannel;
 import org.apache.hop.core.plugins.IPlugin;
@@ -82,6 +83,9 @@ public class ExtensionPointMap {
    * @param extensionPointPlugin
    */
   public void addExtensionPoint(IPlugin extensionPointPlugin) {
+    if 
(GuiRegistry.getDisabledGuiElements().contains(extensionPointPlugin.getIds()[0]))
 {
+      return;
+    }
     lock.writeLock().lock();
     try {
       for (String id : extensionPointPlugin.getIds()) {
diff --git a/core/src/main/java/org/apache/hop/core/gui/plugin/GuiRegistry.java 
b/core/src/main/java/org/apache/hop/core/gui/plugin/GuiRegistry.java
index de98795e97..ba83c60b93 100644
--- a/core/src/main/java/org/apache/hop/core/gui/plugin/GuiRegistry.java
+++ b/core/src/main/java/org/apache/hop/core/gui/plugin/GuiRegistry.java
@@ -17,6 +17,7 @@
 
 package org.apache.hop.core.gui.plugin;
 
+import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -29,8 +30,13 @@ import java.util.Set;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.hop.core.Const;
 import org.apache.hop.core.action.GuiContextAction;
 import org.apache.hop.core.action.GuiContextActionFilter;
+import org.apache.hop.core.exception.HopFileException;
+import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.gui.plugin.action.GuiAction;
 import org.apache.hop.core.gui.plugin.action.GuiActionFilter;
 import org.apache.hop.core.gui.plugin.callback.GuiCallback;
@@ -47,6 +53,10 @@ import 
org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElementFilter;
 import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItem;
 import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItemFilter;
 import org.apache.hop.core.util.TranslateUtil;
+import org.apache.hop.core.vfs.HopVfs;
+import org.apache.hop.core.xml.XmlHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 
 /**
  * This singleton keeps track of the various GUI elements that are made 
plug-able by the developers.
@@ -104,6 +114,66 @@ public class GuiRegistry {
     return guiRegistry;
   }
 
+  private static List<String> disabledGuiElements;
+
+  /**
+   * Returns the list of GUI element IDs that should be disabled (excluded 
from the UI). Loaded from
+   * disabledGuiElements.xml in the application folder and/or config folder. 
Used
+   * by @GuiWidgetElement, @GuiToolbarElement, @GuiContextAction, 
@HopPerspectivePlugin, @GuiMenuElement, @GuiTab, @GuiKeyboardShortcut, 
@HopMetadata, @ExtensionPoint
+   * and @ConfigPlugin.
+   *
+   * @return List of exclusion IDs (never null)
+   */
+  public static List<String> getDisabledGuiElements() {
+    if (disabledGuiElements == null) {
+      disabledGuiElements = loadDisabledGuiElements();
+    }
+    return disabledGuiElements;
+  }
+
+  private static List<String> loadDisabledGuiElements() {
+    List<String> excluded = new ArrayList<>();
+    try {
+      FileObject applicationFolderFile = 
HopVfs.getFileObject("./disabledGuiElements.xml");
+      FileObject configFolderFile =
+          HopVfs.getFileObject(
+              Const.HOP_CONFIG_FOLDER + File.separator + 
"disabledGuiElements.xml");
+
+      if (applicationFolderFile.exists()) {
+        String path = 
applicationFolderFile.getPath().toAbsolutePath().toString();
+        Document document = XmlHandler.loadXmlFile(path);
+        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
+        if (exclusionsNode != null) {
+          List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
+          for (Node exclusionNode : exclusionNodes) {
+            String text = exclusionNode.getTextContent();
+            if (text != null && !text.isBlank()) {
+              excluded.add(text.trim());
+            }
+          }
+        }
+      }
+
+      if (configFolderFile.exists()) {
+        String path = configFolderFile.getPath().toAbsolutePath().toString();
+        Document document = XmlHandler.loadXmlFile(path);
+        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
+        if (exclusionsNode != null) {
+          List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
+          for (Node exclusionNode : exclusionNodes) {
+            String text = exclusionNode.getTextContent();
+            if (text != null && !text.isBlank()) {
+              excluded.add(text.trim());
+            }
+          }
+        }
+      }
+    } catch (HopXmlException | FileSystemException | HopFileException e) {
+      // ignore - file may not exist
+    }
+    return excluded;
+  }
+
   /**
    * Add GUI Menu elements under a particular gui root (example: 
HopGui-MainMenu) under a particular
    * parent element ID
diff --git 
a/core/src/main/java/org/apache/hop/metadata/serializer/BaseMetadataProvider.java
 
b/core/src/main/java/org/apache/hop/metadata/serializer/BaseMetadataProvider.java
index 8dab58efdb..6d49df7b28 100644
--- 
a/core/src/main/java/org/apache/hop/metadata/serializer/BaseMetadataProvider.java
+++ 
b/core/src/main/java/org/apache/hop/metadata/serializer/BaseMetadataProvider.java
@@ -20,6 +20,7 @@ package org.apache.hop.metadata.serializer;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.gui.plugin.GuiRegistry;
 import org.apache.hop.core.plugins.IPlugin;
 import org.apache.hop.core.plugins.PluginRegistry;
 import org.apache.hop.core.variables.IVariables;
@@ -41,8 +42,12 @@ public class BaseMetadataProvider {
   public <T extends IHopMetadata> List<Class<T>> getMetadataClasses() {
     try {
       PluginRegistry registry = PluginRegistry.getInstance();
+      List<String> disabledIds = GuiRegistry.getDisabledGuiElements();
       List<Class<T>> classes = new ArrayList<>();
       for (IPlugin plugin : registry.getPlugins(MetadataPluginType.class)) {
+        if (disabledIds.contains(plugin.getIds()[0])) {
+          continue;
+        }
         String className = plugin.getClassMap().get(plugin.getMainType());
         Class<?> pluginClass = 
registry.getClassLoader(plugin).loadClass(className);
         classes.add((Class<T>) pluginClass);
diff --git a/docs/hop-tech-manual/modules/ROOT/pages/disable-ui-elements.adoc 
b/docs/hop-tech-manual/modules/ROOT/pages/disable-ui-elements.adoc
index d47b0c0935..db45096fbb 100644
--- a/docs/hop-tech-manual/modules/ROOT/pages/disable-ui-elements.adoc
+++ b/docs/hop-tech-manual/modules/ROOT/pages/disable-ui-elements.adoc
@@ -62,6 +62,17 @@ Example to block calls using any System. methods:
 </exclusions>
 ----
 
-For each element that needs to be disabled, you can add an extra `<exclusion>` 
line. The value equals the ID element used in `@GuiWidgetElement`, 
`@GuiToolbarElement` , `@GuiContextAction` or `@HopPerspectivePlugin` 
+For each element that needs to be disabled, you can add an extra `<exclusion>` 
line. The value equals the ID element used in:
+
+* `@GuiWidgetElement` – use the element's `id`
+* `@GuiToolbarElement` – use the element's `id`
+* `@GuiContextAction` – use the action's `id`
+* `@HopPerspectivePlugin` – use the perspective plugin's `id`
+* `@GuiMenuElement` – use the menu element's `id`
+* `@GuiTab` – use the tab's `id`, or `className#methodName` when `id` is empty
+* `@GuiKeyboardShortcut` – use the shortcut's `className#methodName`
+* `@HopMetadata` – use the metadata plugin id (from `key` or `name` in the 
annotation)
+* `@ExtensionPoint` – use the extension point plugin's `id`
+* `@ConfigPlugin` – use the config plugin's `id` 
 
 
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
index e87f98b96f..5c7d919cb9 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
@@ -19,7 +19,6 @@ package org.apache.hop.ui.hopgui;
 
 import static org.apache.hop.core.Const.getDocUrl;
 
-import java.io.File;
 import java.io.FileOutputStream;
 import java.io.PrintStream;
 import java.nio.file.Files;
@@ -36,8 +35,6 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.io.output.TeeOutputStream;
 import org.apache.commons.lang.StringUtils;
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemException;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.DbCache;
 import org.apache.hop.core.HopEnvironment;
@@ -46,8 +43,6 @@ import 
org.apache.hop.core.config.DescribedVariablesConfigFile;
 import org.apache.hop.core.config.HopConfig;
 import org.apache.hop.core.database.DatabaseMeta;
 import org.apache.hop.core.exception.HopException;
-import org.apache.hop.core.exception.HopFileException;
-import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.extension.ExtensionPointHandler;
 import org.apache.hop.core.extension.HopExtensionPoint;
 import org.apache.hop.core.gui.IUndo;
@@ -74,8 +69,6 @@ import org.apache.hop.core.util.TranslateUtil;
 import org.apache.hop.core.variables.DescribedVariable;
 import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.core.variables.Variables;
-import org.apache.hop.core.vfs.HopVfs;
-import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.i18n.BaseMessages;
 import org.apache.hop.i18n.LanguageChoice;
 import org.apache.hop.metadata.api.IHasHopMetadataProvider;
@@ -157,8 +150,6 @@ import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
 
 @GuiPlugin(name = "Hop Gui", description = "The main hop graphical user 
interface")
 @SuppressWarnings("java:S1104")
@@ -564,40 +555,7 @@ public class HopGui
   }
 
   private void loadPerspectives() {
-    List<String> excludedGuiElements = new ArrayList<>();
-
-    // Try loading code exclusions
-    try {
-      FileObject applicationFolderFile = 
HopVfs.getFileObject("./disabledGuiElements.xml");
-      FileObject configFolderFile =
-          HopVfs.getFileObject(
-              Const.HOP_CONFIG_FOLDER + File.separator + 
"disabledGuiElements.xml");
-      String path = null;
-
-      if (applicationFolderFile.exists()) {
-        path = applicationFolderFile.getPath().toAbsolutePath().toString();
-        Document document = XmlHandler.loadXmlFile(path);
-        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
-        List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
-
-        for (Node exclusionNode : exclusionNodes) {
-          excludedGuiElements.add(exclusionNode.getTextContent());
-        }
-      }
-
-      if (configFolderFile.exists()) {
-        path = configFolderFile.getPath().toAbsolutePath().toString();
-        Document document = XmlHandler.loadXmlFile(path);
-        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
-        List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
-
-        for (Node exclusionNode : exclusionNodes) {
-          excludedGuiElements.add(exclusionNode.getTextContent());
-        }
-      }
-    } catch (HopXmlException | FileSystemException | HopFileException e) {
-      // ignore
-    }
+    List<String> excludedGuiElements = GuiRegistry.getDisabledGuiElements();
 
     try {
       // Preload the perspectives and store them in the manager as well as the 
GuiRegistry
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiEnvironment.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiEnvironment.java
index d9e6887d7f..222f7ea71e 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiEnvironment.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiEnvironment.java
@@ -17,20 +17,14 @@
 
 package org.apache.hop.ui.hopgui;
 
-import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemException;
-import org.apache.hop.core.Const;
 import org.apache.hop.core.HopClientEnvironment;
 import org.apache.hop.core.action.GuiContextAction;
 import org.apache.hop.core.action.GuiContextActionFilter;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.exception.HopPluginException;
-import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.gui.plugin.GuiElementType;
 import org.apache.hop.core.gui.plugin.GuiPluginType;
 import org.apache.hop.core.gui.plugin.GuiRegistry;
@@ -46,16 +40,12 @@ import org.apache.hop.core.plugins.IPlugin;
 import org.apache.hop.core.plugins.IPluginType;
 import org.apache.hop.core.plugins.PluginRegistry;
 import org.apache.hop.core.search.SearchableAnalyserPluginType;
-import org.apache.hop.core.vfs.HopVfs;
-import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.ui.hopgui.file.HopFileTypePluginType;
 import org.apache.hop.ui.hopgui.file.HopFileTypeRegistry;
 import org.apache.hop.ui.hopgui.file.IHopFileType;
 import org.apache.hop.ui.hopgui.perspective.HopPerspectivePluginType;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.eclipse.swt.SWT;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
 
 public class HopGuiEnvironment extends HopClientEnvironment {
 
@@ -84,40 +74,7 @@ public class HopGuiEnvironment extends HopClientEnvironment {
    * @throws HopException
    */
   public static void initGuiPlugins() throws HopException {
-    List<String> excludedGuiElements = new ArrayList<>();
-
-    // Try loading code exclusions
-    try {
-      FileObject applicationFolderFile = 
HopVfs.getFileObject("./disabledGuiElements.xml");
-      FileObject configFolderFile =
-          HopVfs.getFileObject(
-              Const.HOP_CONFIG_FOLDER + File.separator + 
"disabledGuiElements.xml");
-      String path;
-
-      if (applicationFolderFile.exists()) {
-        path = applicationFolderFile.getPath().toAbsolutePath().toString();
-        Document document = XmlHandler.loadXmlFile(path);
-        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
-        List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
-
-        for (Node exclusionNode : exclusionNodes) {
-          excludedGuiElements.add(exclusionNode.getTextContent());
-        }
-      }
-
-      if (configFolderFile.exists()) {
-        path = configFolderFile.getPath().toAbsolutePath().toString();
-        Document document = XmlHandler.loadXmlFile(path);
-        Node exclusionsNode = XmlHandler.getSubNode(document, "exclusions");
-        List<Node> exclusionNodes = XmlHandler.getNodes(exclusionsNode, 
"exclusion");
-
-        for (Node exclusionNode : exclusionNodes) {
-          excludedGuiElements.add(exclusionNode.getTextContent());
-        }
-      }
-    } catch (HopXmlException | FileSystemException e) {
-      // ignore
-    }
+    List<String> excludedGuiElements = GuiRegistry.getDisabledGuiElements();
 
     try {
       GuiRegistry guiRegistry = GuiRegistry.getInstance();
@@ -148,7 +105,7 @@ public class HopGuiEnvironment extends HopClientEnvironment 
{
         List<Method> methods = findDeclaredMethods(guiPluginClass);
         for (Method method : methods) {
           GuiMenuElement menuElement = 
method.getAnnotation(GuiMenuElement.class);
-          if (menuElement != null) {
+          if (menuElement != null && 
!excludedGuiElements.contains(menuElement.id())) {
             guiRegistry.addGuiMenuElement(guiPluginClassName, menuElement, 
method, classLoader);
           }
           GuiToolbarElement toolbarElement = 
method.getAnnotation(GuiToolbarElement.class);
@@ -168,6 +125,11 @@ public class HopGuiEnvironment extends 
HopClientEnvironment {
             if (EnvironmentUtils.getInstance().isWeb() && shortcut.key() == 
SWT.ESC) {
               continue;
             }
+            // Use id() if set, otherwise className#methodName for 
disabledGuiElements.xml
+            String shortcutId = guiPluginClassName + "#" + method.getName();
+            if (excludedGuiElements.contains(shortcutId)) {
+              continue; // Skip: disabled in disabledGuiElements.xml
+            }
             guiRegistry.addKeyboardShortcut(guiPluginClassName, method, 
shortcut);
           }
           GuiOsxKeyboardShortcut osxShortcut = 
method.getAnnotation(GuiOsxKeyboardShortcut.class);
@@ -176,6 +138,11 @@ public class HopGuiEnvironment extends 
HopClientEnvironment {
             if (EnvironmentUtils.getInstance().isWeb() && osxShortcut.key() == 
SWT.ESC) {
               continue;
             }
+            // Osx shortcut has no id(); use className#methodName for 
disabledGuiElements.xml
+            String osxShortcutId = guiPluginClassName + "#" + method.getName();
+            if (excludedGuiElements.contains(osxShortcutId)) {
+              continue; // Skip: disabled in disabledGuiElements.xml
+            }
             guiRegistry.addKeyboardShortcut(guiPluginClassName, method, 
osxShortcut);
           }
           GuiContextAction contextAction = 
method.getAnnotation(GuiContextAction.class);
@@ -204,8 +171,14 @@ public class HopGuiEnvironment extends 
HopClientEnvironment {
           }
 
           GuiTab guiTab = method.getAnnotation(GuiTab.class);
-          if (guiTab != null && !excludedGuiElements.contains(guiTab.id())) {
-            guiRegistry.addGuiTab(guiPluginClassName, method, guiTab, 
classLoader);
+          if (guiTab != null) {
+            String tabId =
+                (guiTab.id() != null && !guiTab.id().isBlank())
+                    ? guiTab.id()
+                    : guiPluginClassName + "#" + method.getName();
+            if (!excludedGuiElements.contains(tabId)) {
+              guiRegistry.addGuiTab(guiPluginClassName, method, guiTab, 
classLoader);
+            }
           }
         }
       }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/configuration/tabs/ConfigPluginOptionsTab.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/configuration/tabs/ConfigPluginOptionsTab.java
index 90726fbfd9..93991041b4 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/configuration/tabs/ConfigPluginOptionsTab.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/configuration/tabs/ConfigPluginOptionsTab.java
@@ -20,10 +20,12 @@ package 
org.apache.hop.ui.hopgui.perspective.configuration.tabs;
 
 import java.lang.reflect.Method;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.config.plugin.ConfigPluginType;
 import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiRegistry;
 import org.apache.hop.core.gui.plugin.tab.GuiTab;
 import org.apache.hop.core.plugins.IPlugin;
 import org.apache.hop.core.plugins.PluginRegistry;
@@ -96,8 +98,12 @@ public class ConfigPluginOptionsTab {
     //
     pluginDataMap.clear();
     PluginRegistry pluginRegistry = PluginRegistry.getInstance();
+    List<String> disabledIds = GuiRegistry.getDisabledGuiElements();
     java.util.List<IPlugin> configPlugins = 
pluginRegistry.getPlugins(ConfigPluginType.class);
     for (IPlugin configPlugin : configPlugins) {
+      if (disabledIds.contains(configPlugin.getIds()[0])) {
+        continue;
+      }
       try {
         Object emptySourceData = pluginRegistry.loadClass(configPlugin);
         GuiPlugin annotation = 
emptySourceData.getClass().getAnnotation(GuiPlugin.class);

Reply via email to