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 aaffbac289 Add missing plugin functionality back, fixes #6944 (#6945)
aaffbac289 is described below

commit aaffbac2893629ff3d01193d605bca0c9a3cbe00
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Fri Apr 3 12:47:33 2026 +0200

    Add missing plugin functionality back, fixes #6944 (#6945)
---
 .../metadata/serializer/xml/XmlMetadataUtil.java   |  44 +++++++
 .../transforms/missing/MissingTransform.java       |  28 ++++-
 .../delegates/HopGuiPipelineTransformDelegate.java |  11 ++
 .../delegates/HopGuiWorkflowActionDelegate.java    |   2 +-
 .../perspective/explorer/ExplorerPerspective.java  |  20 ----
 .../transforms/missing/MissingPipelineDialog.java  | 130 +++++++++------------
 .../actions/missing/MissingActionDialog.java       | 124 ++++++++------------
 .../missing/messages/messages_de_DE.properties     |   7 --
 .../missing/messages/messages_en_US.properties     |   5 +-
 .../missing/messages/messages_es_ES.properties     |   7 --
 .../missing/messages/messages_it_IT.properties     |   7 --
 .../missing/messages/messages_pt_BR.properties     |   7 +-
 .../missing/messages/messages_zh_CN.properties     |   7 --
 .../missing/messages/messages_de_DE.properties     |   7 --
 .../missing/messages/messages_en_US.properties     |   5 +-
 .../missing/messages/messages_es_ES.properties     |   8 +-
 .../missing/messages/messages_it_IT.properties     |   7 --
 .../missing/messages/messages_pt_BR.properties     |   7 --
 .../missing/messages/messages_zh_CN.properties     |   7 --
 19 files changed, 189 insertions(+), 251 deletions(-)

diff --git 
a/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
 
b/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
index 08cc3ad946..12c8a2694c 100644
--- 
a/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
+++ 
b/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.MissingResourceException;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hop.core.Const;
@@ -51,10 +52,42 @@ import org.apache.hop.metadata.util.ReflectionUtil;
 import org.w3c.dom.Node;
 
 public class XmlMetadataUtil {
+
+  private static final String FQN_TRANSFORM_FACTORY =
+      "org.apache.hop.pipeline.transform.ITransformMeta$TransformFactory";
+  private static final String FQN_ACTION_FACTORY =
+      "org.apache.hop.workflow.action.IAction$ActionFactory";
+
   private XmlMetadataUtil() {
     // Hides the public constructor
   }
 
+  /**
+   * {@link MissingResourceException} from transform/action factories: 
substitute {@code Missing} /
+   * {@code MissingAction} via reflection (no core → engine compile 
dependency).
+   */
+  private static Object newMissingPluginPlaceholder(
+      HopMetadataObject metadataObject, Node node, String pluginId) {
+    String factoryName = metadataObject.objectFactory().getName();
+    String name = node != null ? XmlHandler.getTagValue(node, "name") : null;
+    try {
+      if (FQN_TRANSFORM_FACTORY.equals(factoryName)) {
+        Class<?> c = 
Class.forName("org.apache.hop.pipeline.transforms.missing.Missing");
+        return c.getDeclaredConstructor(String.class, String.class)
+            .newInstance(Const.NVL(name, ""), pluginId);
+      }
+      if (FQN_ACTION_FACTORY.equals(factoryName)) {
+        Class<?> c = 
Class.forName("org.apache.hop.workflow.actions.missing.MissingAction");
+        String actionName = (name == null || name.isEmpty()) ? null : name;
+        return c.getDeclaredConstructor(String.class, String.class)
+            .newInstance(actionName, pluginId);
+      }
+    } catch (Exception ignored) {
+      return null;
+    }
+    return null;
+  }
+
   /**
    * This method looks at the fields in the class of the provided 
parentObject. It then sees which
    * fields have annotation HopMetadataProperty and proceeds to serialize the 
values of those fields
@@ -816,6 +849,17 @@ public class XmlMetadataUtil {
             IHopMetadataObjectFactory factory =
                 metadataObject.objectFactory().getConstructor().newInstance();
             object = (T) factory.createObject(objectId, parentObject);
+          } catch (MissingResourceException e) {
+            Object placeholder = newMissingPluginPlaceholder(metadataObject, 
node, objectId);
+            if (placeholder == null) {
+              throw new HopXmlException(
+                  "Unable to create a new instance of class "
+                      + clazz.getName()
+                      + " while de-serializing XML: "
+                      + e.getMessage(),
+                  e);
+            }
+            object = (T) placeholder;
           } catch (HopMissingPluginsException e) {
             throw new HopXmlException(
                 "The plugin for class "
diff --git 
a/engine/src/main/java/org/apache/hop/pipeline/transforms/missing/MissingTransform.java
 
b/engine/src/main/java/org/apache/hop/pipeline/transforms/missing/MissingTransform.java
index 021f4faff1..70c4aa6903 100644
--- 
a/engine/src/main/java/org/apache/hop/pipeline/transforms/missing/MissingTransform.java
+++ 
b/engine/src/main/java/org/apache/hop/pipeline/transforms/missing/MissingTransform.java
@@ -17,21 +17,26 @@
 
 package org.apache.hop.pipeline.transforms.missing;
 
+import org.apache.hop.core.exception.HopException;
 import org.apache.hop.i18n.BaseMessages;
 import org.apache.hop.pipeline.Pipeline;
 import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
 import org.apache.hop.pipeline.transform.TransformMeta;
-import org.apache.hop.pipeline.transforms.dummy.Dummy;
-import org.apache.hop.pipeline.transforms.dummy.DummyData;
-import org.apache.hop.pipeline.transforms.dummy.DummyMeta;
 
-public class MissingTransform extends Dummy {
+/**
+ * Runtime stand-in for a transform whose plugin is not installed. {@link 
Missing} declares {@code
+ * BaseTransformMeta<MissingTransform, MissingData>}, so {@link
+ * org.apache.hop.pipeline.transform.BaseTransformMeta#createTransform} must 
find a constructor
+ * {@code (TransformMeta, Missing, MissingData, int, PipelineMeta, Pipeline)}.
+ */
+public class MissingTransform extends BaseTransform<Missing, MissingData> {
   private static final Class<?> PKG = MissingTransform.class;
 
   public MissingTransform(
       TransformMeta transformMeta,
-      DummyMeta meta,
-      DummyData data,
+      Missing meta,
+      MissingData data,
       int copyNr,
       PipelineMeta pipelineMeta,
       Pipeline pipeline) {
@@ -45,4 +50,15 @@ public class MissingTransform extends Dummy {
     }
     return false;
   }
+
+  @Override
+  public boolean processRow() throws HopException {
+    Object[] r = getRow();
+    if (r == null) {
+      setOutputDone();
+      return false;
+    }
+    putRow(getInputRowMeta(), r);
+    return true;
+  }
 }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
index f962e743b0..3cb0647a62 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
@@ -49,6 +49,7 @@ import org.apache.hop.pipeline.transform.TransformErrorMeta;
 import org.apache.hop.pipeline.transform.TransformMeta;
 import org.apache.hop.pipeline.transform.TransformPartitioningMeta;
 import org.apache.hop.pipeline.transform.stream.IStream;
+import org.apache.hop.pipeline.transforms.missing.Missing;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.MessageBox;
@@ -61,6 +62,7 @@ import org.apache.hop.ui.hopgui.partition.PartitionSettings;
 import org.apache.hop.ui.hopgui.partition.processor.IMethodProcessor;
 import org.apache.hop.ui.hopgui.partition.processor.MethodProcessorFactory;
 import org.apache.hop.ui.pipeline.transform.TransformErrorMetaDialog;
+import org.apache.hop.ui.pipeline.transforms.missing.MissingPipelineDialog;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Shell;
 
@@ -82,6 +84,15 @@ public class HopGuiPipelineTransformDelegate {
       ITransformMeta transformMeta, PipelineMeta pipelineMeta, String 
transformName)
       throws HopException {
 
+    if (transformMeta instanceof Missing) {
+      return new MissingPipelineDialog(
+          hopGui.getShell(),
+          pipelineGraph.getVariables(),
+          transformMeta,
+          pipelineMeta,
+          transformName);
+    }
+
     PluginRegistry registry = PluginRegistry.getInstance();
     IPlugin plugin = registry.getPlugin(TransformPluginType.class, 
transformMeta);
     if (plugin == null) {
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowActionDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowActionDelegate.java
index 5f578c5f6f..ae49b5c824 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowActionDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowActionDelegate.java
@@ -199,7 +199,7 @@ public class HopGuiWorkflowActionDelegate {
     Object[] arguments =
         new Object[] {hopGui.getShell(), action, workflowMeta, 
workflowGraph.getVariables()};
 
-    if (MissingAction.ID.equals(action.getPluginId())) {
+    if (action instanceof MissingAction) {
       return new MissingActionDialog(
           hopGui.getActiveShell(), action, workflowMeta, 
workflowGraph.getVariables());
     }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index fd45b5d200..df3e70caf1 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -135,7 +135,6 @@ import org.eclipse.swt.dnd.DropTargetAdapter;
 import org.eclipse.swt.dnd.DropTargetEvent;
 import org.eclipse.swt.dnd.FileTransfer;
 import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.Point;
@@ -569,7 +568,6 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable, IFileD
     tree.addListener(SWT.Selection, event -> updateSelection());
     tree.addListener(SWT.DefaultSelection, this::openFile);
     PropsUi.setLook(tree);
-    logFileExplorerFont("tree", tree.getFont());
 
     FormData treeFormData = new FormData();
     treeFormData.left = new FormAttachment(0, 0);
@@ -641,24 +639,6 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable, IFileD
     
GuiRegistry.getInstance().executeCallbackMethods(GUI_CONTEXT_MENU_CREATED_CALLBACK_ID);
   }
 
-  private void logFileExplorerFont(String widget, Font font) {
-    if (font == null || font.isDisposed()) {
-      return;
-    }
-    FontData[] fda = font.getFontData();
-    if (fda != null && fda.length > 0) {
-      hopGui
-          .getLog()
-          .logBasic(
-              "File explorer "
-                  + widget
-                  + " font: family="
-                  + fda[0].getName()
-                  + ", size="
-                  + fda[0].getHeight());
-    }
-  }
-
   /**
    * Creates the Drag & Drop DragSource for items being dragged from the tree.
    *
diff --git 
a/ui/src/main/java/org/apache/hop/ui/pipeline/transforms/missing/MissingPipelineDialog.java
 
b/ui/src/main/java/org/apache/hop/ui/pipeline/transforms/missing/MissingPipelineDialog.java
index 7b62fb0013..86a285619e 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/pipeline/transforms/missing/MissingPipelineDialog.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/pipeline/transforms/missing/MissingPipelineDialog.java
@@ -43,7 +43,6 @@ public class MissingPipelineDialog extends 
BaseTransformDialog {
 
   private static final Class<?> PKG = MissingPipelineDialog.class;
 
-  private Shell shell;
   private Shell shellParent;
   private List<Missing> missingPipeline;
   private int mode;
@@ -75,53 +74,59 @@ public class MissingPipelineDialog extends 
BaseTransformDialog {
     this.mode = MISSING_PIPELINE_TRANSFORM_ID;
   }
 
-  private String getErrorMessage(List<Missing> missingPipeline, int mode) {
-    String message = "";
-    if (mode == MISSING_PIPELINE_TRANSFORMS) {
-      StringBuilder entries = new StringBuilder();
-      for (Missing entry : missingPipeline) {
-        if (missingPipeline.indexOf(entry) == missingPipeline.size() - 1) {
-          entries.append(
-              "- " + entry.getTransformName() + " - " + 
entry.getMissingPluginId() + "\n\n");
-        } else {
-          entries.append(
-              "- " + entry.getTransformName() + " - " + 
entry.getMissingPluginId() + "\n");
-        }
+  private static String formatMissingEntries(List<Missing> items) {
+    StringBuilder entries = new StringBuilder();
+    for (int i = 0; i < items.size(); i++) {
+      Missing item = items.get(i);
+      entries
+          .append("- ")
+          .append(item.getTransformName())
+          .append(" - ")
+          .append(item.getMissingPluginId());
+      if (i < items.size() - 1) {
+        entries.append("\n");
+      } else {
+        entries.append("\n\n");
       }
-      message =
-          BaseMessages.getString(
-              PKG, "MissingPipelineDialog.MissingPipelineTransforms", 
entries.toString());
     }
+    return entries.toString();
+  }
 
-    if (mode == MISSING_PIPELINE_TRANSFORM_ID) {
-      message =
-          BaseMessages.getString(
-              PKG,
-              "MissingPipelineDialog.MissingPipelineTransformId",
-              transformName + " - " + ((Missing) 
baseTransformMeta).getMissingPluginId());
+  private String buildMessage() {
+    if (mode == MISSING_PIPELINE_TRANSFORMS) {
+      return BaseMessages.getString(
+          PKG,
+          "MissingPipelineDialog.MissingPipelineTransforms",
+          formatMissingEntries(missingPipeline));
     }
-    return message;
+    return BaseMessages.getString(
+        PKG,
+        "MissingPipelineDialog.MissingPipelineTransformId",
+        ((Missing) baseTransformMeta).getMissingPluginId());
   }
 
   @Override
   public String open() {
-    PropsUi props = PropsUi.getInstance();
-    Display display = shellParent.getDisplay();
+    String message = buildMessage();
+    boolean showOpenFile = mode == MISSING_PIPELINE_TRANSFORMS;
 
-    shell = new Shell(shellParent, SWT.DIALOG_TRIM | SWT.CLOSE | SWT.ICON | 
SWT.APPLICATION_MODAL);
+    Display display = shellParent.getDisplay();
+    Shell dialogShell =
+        new Shell(shellParent, SWT.DIALOG_TRIM | SWT.CLOSE | SWT.ICON | 
SWT.APPLICATION_MODAL);
+    this.shell = dialogShell;
 
-    PropsUi.setLook(shell);
-    shell.setImage(GuiResource.getInstance().getImageHopUi());
+    PropsUi.setLook(dialogShell);
+    dialogShell.setImage(GuiResource.getInstance().getImageHopUi());
 
     FormLayout formLayout = new FormLayout();
     formLayout.marginWidth = PropsUi.getFormMargin();
     formLayout.marginLeft = PropsUi.getFormMargin();
     formLayout.marginHeight = PropsUi.getFormMargin();
 
-    shell.setText(BaseMessages.getString(PKG, 
"MissingPipelineDialog.MissingPlugins"));
-    shell.setLayout(formLayout);
+    dialogShell.setText(BaseMessages.getString(PKG, 
"MissingPipelineDialog.MissingPlugins"));
+    dialogShell.setLayout(formLayout);
 
-    Label image = new Label(shell, SWT.NONE);
+    Label image = new Label(dialogShell, SWT.NONE);
     PropsUi.setLook(image);
     Image icon = display.getSystemImage(SWT.ICON_QUESTION);
     image.setImage(icon);
@@ -131,22 +136,33 @@ public class MissingPipelineDialog extends 
BaseTransformDialog {
     imageData.top = new FormAttachment(0, 10);
     image.setLayoutData(imageData);
 
-    Label error = new Label(shell, SWT.WRAP);
+    Label error = new Label(dialogShell, SWT.WRAP);
     PropsUi.setLook(error);
-    error.setText(getErrorMessage(missingPipeline, mode));
+    error.setText(message);
     FormData errorData = new FormData();
     errorData.left = new FormAttachment(image, 5);
     errorData.right = new FormAttachment(100, -5);
     errorData.top = new FormAttachment(0, 10);
     error.setLayoutData(errorData);
 
-    Label separator = new Label(shell, SWT.WRAP);
+    Label separator = new Label(dialogShell, SWT.WRAP);
     PropsUi.setLook(separator);
     FormData separatorData = new FormData();
     separatorData.top = new FormAttachment(error, 10);
     separator.setLayoutData(separatorData);
 
-    Button closeButton = new Button(shell, SWT.PUSH);
+    Runnable confirm =
+        () -> {
+          dialogShell.dispose();
+          transformResult = transformName;
+        };
+    Runnable cancel =
+        () -> {
+          dialogShell.dispose();
+          transformResult = null;
+        };
+
+    Button closeButton = new Button(dialogShell, SWT.PUSH);
     PropsUi.setLook(closeButton);
     FormData fdClose = new FormData();
     fdClose.right = new FormAttachment(98);
@@ -157,13 +173,12 @@ public class MissingPipelineDialog extends 
BaseTransformDialog {
         new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
-            cancel();
+            cancel.run();
           }
         });
 
-    FormData fdSearch = new FormData();
-    if (this.mode == MISSING_PIPELINE_TRANSFORMS) {
-      Button openButton = new Button(shell, SWT.PUSH);
+    if (showOpenFile) {
+      Button openButton = new Button(dialogShell, SWT.PUSH);
       PropsUi.setLook(openButton);
       FormData fdOpen = new FormData();
       fdOpen.right = new FormAttachment(closeButton, -5);
@@ -174,45 +189,12 @@ public class MissingPipelineDialog extends 
BaseTransformDialog {
           new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
-              ok();
+              confirm.run();
             }
           });
-      fdSearch.right = new FormAttachment(openButton, -5);
-      fdSearch.bottom = new FormAttachment(openButton, 0, SWT.BOTTOM);
-    } else {
-      fdSearch.right = new FormAttachment(closeButton, -5);
-      fdSearch.bottom = new FormAttachment(closeButton, 0, SWT.BOTTOM);
     }
 
-    Button searchButton = new Button(shell, SWT.PUSH);
-    PropsUi.setLook(searchButton);
-    searchButton.setText(BaseMessages.getString(PKG, 
"MissingPipelineDialog.SearchMarketplace"));
-    searchButton.setLayoutData(fdSearch);
-    searchButton.addSelectionListener(
-        new SelectionAdapter() {
-          @Override
-          public void widgetSelected(SelectionEvent e) {
-            try {
-              shell.dispose();
-              // HopGui.getInstance().openMarketplace();  TODO: implement 
marketplace
-            } catch (Exception ex) {
-              ex.printStackTrace();
-            }
-          }
-        });
-
-    BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
-
+    BaseDialog.defaultShellHandling(dialogShell, v -> confirm.run(), v -> 
cancel.run());
     return transformResult;
   }
-
-  private void ok() {
-    shell.dispose();
-    transformResult = transformName;
-  }
-
-  private void cancel() {
-    shell.dispose();
-    transformResult = null;
-  }
 }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/workflow/actions/missing/MissingActionDialog.java
 
b/ui/src/main/java/org/apache/hop/ui/workflow/actions/missing/MissingActionDialog.java
index da6676e220..e43290b271 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/workflow/actions/missing/MissingActionDialog.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/workflow/actions/missing/MissingActionDialog.java
@@ -41,6 +41,7 @@ import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 
 public class MissingActionDialog extends ActionDialog {
+
   private static final Class<?> PKG = MissingActionDialog.class;
 
   private List<MissingAction> missingActions;
@@ -66,51 +67,52 @@ public class MissingActionDialog extends ActionDialog {
     this.mode = MISSING_ACTION_ID;
   }
 
-  private String getErrorMessage(List<MissingAction> missingEntries, int mode) 
{
-    String message = "";
-    if (mode == MISSING_ACTIONS) {
-      StringBuilder entries = new StringBuilder();
-      for (MissingAction action : missingEntries) {
-        if (missingEntries.indexOf(action) == missingEntries.size() - 1) {
-          entries.append("- " + action.getName() + " - " + 
action.getMissingPluginId() + "\n\n");
-        } else {
-          entries.append("- " + action.getName() + " - " + 
action.getMissingPluginId() + "\n");
-        }
+  private static String formatMissingEntries(List<MissingAction> items) {
+    StringBuilder entries = new StringBuilder();
+    for (int i = 0; i < items.size(); i++) {
+      MissingAction item = items.get(i);
+      entries.append("- ").append(item.getName()).append(" - 
").append(item.getMissingPluginId());
+      if (i < items.size() - 1) {
+        entries.append("\n");
+      } else {
+        entries.append("\n\n");
       }
-      message =
-          BaseMessages.getString(PKG, "MissingActionDialog.MissingActions", 
entries.toString());
     }
+    return entries.toString();
+  }
 
-    if (mode == MISSING_ACTION_ID) {
-      message =
-          BaseMessages.getString(
-              PKG,
-              "MissingActionDialog.MissingActionId",
-              action.getName() + " - " + ((MissingAction) 
action).getMissingPluginId());
+  private String buildMessage() {
+    if (mode == MISSING_ACTIONS) {
+      return BaseMessages.getString(
+          PKG, "MissingActionDialog.MissingActions", 
formatMissingEntries(missingActions));
     }
-    return message;
+    return BaseMessages.getString(
+        PKG, "MissingActionDialog.MissingActionId", ((MissingAction) 
action).getMissingPluginId());
   }
 
   @Override
   public IAction open() {
+    Shell parent = getParent();
+    String message = buildMessage();
+    boolean showOpenFile = mode == MISSING_ACTIONS;
 
-    Shell parent = this.getParent();
     Display display = parent.getDisplay();
+    Shell dialogShell =
+        new Shell(parent, SWT.DIALOG_TRIM | SWT.CLOSE | SWT.ICON | 
SWT.APPLICATION_MODAL);
+    this.shell = dialogShell;
 
-    shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.CLOSE | SWT.ICON | 
SWT.APPLICATION_MODAL);
-
-    PropsUi.setLook(shell);
-    shell.setImage(GuiResource.getInstance().getImageHopUi());
+    PropsUi.setLook(dialogShell);
+    dialogShell.setImage(GuiResource.getInstance().getImageHopUi());
 
     FormLayout formLayout = new FormLayout();
     formLayout.marginWidth = PropsUi.getFormMargin();
     formLayout.marginLeft = PropsUi.getFormMargin();
     formLayout.marginHeight = PropsUi.getFormMargin();
 
-    shell.setText(BaseMessages.getString(PKG, 
"MissingActionDialog.MissingPlugins"));
-    shell.setLayout(formLayout);
+    dialogShell.setText(BaseMessages.getString(PKG, 
"MissingActionDialog.MissingPlugins"));
+    dialogShell.setLayout(formLayout);
 
-    Label image = new Label(shell, SWT.NONE);
+    Label image = new Label(dialogShell, SWT.NONE);
     PropsUi.setLook(image);
     Image icon = display.getSystemImage(SWT.ICON_QUESTION);
     image.setImage(icon);
@@ -120,22 +122,33 @@ public class MissingActionDialog extends ActionDialog {
     imageData.top = new FormAttachment(0, 10);
     image.setLayoutData(imageData);
 
-    Label error = new Label(shell, SWT.WRAP);
+    Label error = new Label(dialogShell, SWT.WRAP);
     PropsUi.setLook(error);
-    error.setText(getErrorMessage(missingActions, mode));
+    error.setText(message);
     FormData errorData = new FormData();
     errorData.left = new FormAttachment(image, 5);
     errorData.right = new FormAttachment(100, -5);
     errorData.top = new FormAttachment(0, 10);
     error.setLayoutData(errorData);
 
-    Label separator = new Label(shell, SWT.WRAP);
+    Label separator = new Label(dialogShell, SWT.WRAP);
     PropsUi.setLook(separator);
     FormData separatorData = new FormData();
     separatorData.top = new FormAttachment(error, 10);
     separator.setLayoutData(separatorData);
 
-    Button closeButton = new Button(shell, SWT.PUSH);
+    Runnable confirm =
+        () -> {
+          dialogShell.dispose();
+          action = new MissingAction();
+        };
+    Runnable cancel =
+        () -> {
+          dialogShell.dispose();
+          action = null;
+        };
+
+    Button closeButton = new Button(dialogShell, SWT.PUSH);
     PropsUi.setLook(closeButton);
     FormData fdClose = new FormData();
     fdClose.right = new FormAttachment(98);
@@ -146,13 +159,12 @@ public class MissingActionDialog extends ActionDialog {
         new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
-            close();
+            cancel.run();
           }
         });
 
-    FormData fdSearch = new FormData();
-    if (this.mode == MISSING_ACTIONS) {
-      Button openButton = new Button(shell, SWT.PUSH);
+    if (showOpenFile) {
+      Button openButton = new Button(dialogShell, SWT.PUSH);
       PropsUi.setLook(openButton);
       FormData fdOpen = new FormData();
       fdOpen.right = new FormAttachment(closeButton, -5);
@@ -163,50 +175,12 @@ public class MissingActionDialog extends ActionDialog {
           new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
-              openFile();
+              confirm.run();
             }
           });
-      fdSearch.right = new FormAttachment(openButton, -5);
-      fdSearch.bottom = new FormAttachment(openButton, 0, SWT.BOTTOM);
-    } else {
-      fdSearch.right = new FormAttachment(closeButton, -5);
-      fdSearch.bottom = new FormAttachment(closeButton, 0, SWT.BOTTOM);
     }
 
-    Button searchButton = new Button(shell, SWT.PUSH);
-    PropsUi.setLook(searchButton);
-    searchButton.setText(BaseMessages.getString(PKG, 
"MissingActionDialog.SearchMarketplace"));
-    searchButton.setLayoutData(fdSearch);
-    searchButton.setEnabled(false);
-    searchButton.addSelectionListener(
-        new SelectionAdapter() {
-          @Override
-          public void widgetSelected(SelectionEvent e) {
-            searchMarketplace();
-          }
-        });
-
-    BaseDialog.defaultShellHandling(shell, c -> openFile(), c -> close());
-
+    BaseDialog.defaultShellHandling(dialogShell, v -> confirm.run(), v -> 
cancel.run());
     return action;
   }
-
-  private void searchMarketplace() {
-    try {
-      shell.dispose();
-      // HopGui.getInstance().openMarketplace(); TODO : implement or replace 
marketplace
-    } catch (Exception ex) {
-      ex.printStackTrace();
-    }
-  }
-
-  private void openFile() {
-    shell.dispose();
-    action = new MissingAction();
-  }
-
-  private void close() {
-    shell.dispose();
-    action = null;
-  }
 }
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_de_DE.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_de_DE.properties
index c3b72d3cd8..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_de_DE.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_de_DE.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingPipelineDialog.Close=Schliessen
-MissingPipelineDialog.MissingPipelineTransformId=Das {0} Plugin 
fehlt.\nEntferne die zugeh\u00F6rige Transform oder f\u00FCge das Plugin hinzu.
-MissingPipelineDialog.MissingPipelineTransforms=Die Datei hat fehlende Plugins 
und wird nicht erfolgreich laufen.\nDie Datei kann ge\u00F6ffnet und die 
fehlenden Transforms ersetzt werden:\n\n{0} Evtl. k\u00F6nnen die fehlenden 
Plugins \u00FCber den Marktplatz erg\u00E4nzt werden.
-MissingPipelineDialog.MissingPlugins=fehlende Plugins
-MissingPipelineDialog.OpenFile=Datei \u00F6ffnen
-MissingPipelineDialog.SearchMarketplace=Durchsuche den Marktplatz
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_en_US.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_en_US.properties
index 5806716d83..55afd8cfd6 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_en_US.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_en_US.properties
@@ -17,8 +17,7 @@
 #
 
 MissingPipelineDialog.Close=Close
-MissingPipelineDialog.MissingPipelineTransformId=The {0} plugin is 
missing.\nRemove this transform or try adding the plugin by searching 
the\nMarketplace.
-MissingPipelineDialog.MissingPipelineTransforms=This file has missing plugins 
and will not succesfully run.\nYou can open the file and replace the missing 
transform(s):\n\n{0}Or try adding the plugin(s) by searching the Marketplace.
+MissingPipelineDialog.MissingPipelineTransformId=The {0} plugin is 
missing.\nRemove this transform or install the missing plugin.
+MissingPipelineDialog.MissingPipelineTransforms=This file has missing plugins 
and will not succesfully run.\nYou can open the file and replace the missing 
transform(s):\n\n{0}Or install the missing plugin(s).
 MissingPipelineDialog.MissingPlugins=Missing Plugins
 MissingPipelineDialog.OpenFile=Open the File
-MissingPipelineDialog.SearchMarketplace=Search the Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_es_ES.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_es_ES.properties
index c8da4cb327..df0a65dc07 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_es_ES.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_es_ES.properties
@@ -14,11 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingPipelineDialog.Close=cerrar
-MissingPipelineDialog.MissingPipelineTransformId=Falta el plugin {0}.\nElimine 
esta transformaci\u00F3n o intente a\u00F1adir el plugin buscando en 
el\nMarketplace.
-MissingPipelineDialog.MissingPipelineTransforms=A este archivo le faltan 
plugins y no se ejecutar\u00E1 correctamente.\nPuede abrir el archivo y 
reemplazar la(s) transformaci\u00F3n(es) faltante(s)\:\n\n{0}O intente 
a\u00F1adir el plugin(s) buscando en el Marketplace.
-MissingPipelineDialog.MissingPlugins=Faltan Plugins
-MissingPipelineDialog.OpenFile=Abrir el archivo
-MissingPipelineDialog.SearchMarketplace=Buscar en el Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_it_IT.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_it_IT.properties
index 3a272a45a2..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_it_IT.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_it_IT.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingPipelineDialog.Close=Chiudi
-MissingPipelineDialog.MissingPipelineTransformId=Il plugin {0} � 
mancante.\nRimuovete questo transform o provate ad aggiungere il plugin 
cercando nel Marketplace.
-MissingPipelineDialog.MissingPipelineTransforms=Questo file ha dei plugin 
mancanti e non pu� essere eseguito con successo. Puoi aprire il file e 
sostituire le trasformazioni mancanti:\n\n{0} o provare ad aggiungere i plugin 
cercando nel Marketplace.
-MissingPipelineDialog.MissingPlugins=Plugins mancanti
-MissingPipelineDialog.OpenFile=Apri il file
-MissingPipelineDialog.SearchMarketplace=Cerca nel marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_pt_BR.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_pt_BR.properties
index 19971824a0..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_pt_BR.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_pt_BR.properties
@@ -1,4 +1,5 @@
 #
+#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -15,9 +16,3 @@
 # limitations under the License.
 #
 
-MissingPipelineDialog.Close=Fechar
-MissingPipelineDialog.MissingPipelineTransformId=O plug-in {0} est\u00E1 
ausente.\nRemova esta transforma\u00E7\u00E3o ou tente adicionar o plug-in 
pesquisando no\nMarketplace.
-MissingPipelineDialog.MissingPipelineTransforms=Este arquivo tem plugins 
ausentes e n\u00E3o ser\u00E1 executado com sucesso.\nVoc\u00EA pode abrir o 
arquivo e substituir as transforma\u00E7\u00F5es ausentes\:\n\n{0}Ou tente 
adicionar os plug-ins pesquisando no Marketplace.
-MissingPipelineDialog.MissingPlugins=Plugins ausentes
-MissingPipelineDialog.OpenFile=Abra o arquivo
-MissingPipelineDialog.SearchMarketplace=Pesquise no Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_zh_CN.properties
 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_zh_CN.properties
index 63917551e6..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_zh_CN.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/pipeline/transforms/missing/messages/messages_zh_CN.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingPipelineDialog.Close=\u5173\u95ED
-MissingPipelineDialog.MissingPipelineTransformId=\u7F3A\u5931 {0} 
\u63D2\u4EF6. \n\u5220\u9664\u6B64 Pipeline 
\u6216\u5C1D\u8BD5\u901A\u8FC7\u641C\u7D22\u63D2\u4EF6\u5E02\u573A\u6765\u6DFB\u52A0\u63D2\u4EF6.
-MissingPipelineDialog.MissingPipelineTransforms=\u8BE5\u6587\u4EF6\u7F3A\u5C11\u63D2\u4EF6,
 \u65E0\u6CD5\u6210\u529F\u8FD0\u884C. 
\n\u60A8\u53EF\u4EE5\u6253\u5F00\u6587\u4EF6\u5E76\u66FF\u6362\u7F3A\u5C11\u7684\u8F6C\u6362\:
 
\n\n{0}\u6216\u8005\u5C1D\u8BD5\u901A\u8FC7\u641C\u7D22\u63D2\u4EF6\u5E02\u573A\u6765\u6DFB\u52A0\u8BE5\u63D2\u4EF6.
-MissingPipelineDialog.MissingPlugins=\u7F3A\u5931\u63D2\u4EF6
-MissingPipelineDialog.OpenFile=\u6253\u5F00\u6587\u4EF6
-MissingPipelineDialog.SearchMarketplace=\u641C\u7D22\u63D2\u4EF6\u5E02\u573A
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_de_DE.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_de_DE.properties
index 36bca0c24c..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_de_DE.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_de_DE.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingActionDialog.Close=Schliessen
-MissingActionDialog.MissingActionId=Das {0} Plugin fehlt.\nEntferne die 
zugeh\u00F6rige Action oder f\u00FCge das fehlende Plugin hinzu.
-MissingActionDialog.MissingActions=Die Datei hat fehlende Plugins und wird 
nicht erfolgreich laufen.\nDie Datei kann ge\u00F6ffnet und die fehlenden 
Actions ersetzt werden.\n\n{0} Evtl. k\u00F6nnen die fehlenden Plugins 
\u00FCber den Marktplatz eingef\u00FCgt werden.
-MissingActionDialog.MissingPlugins=fehlende Plugins
-MissingActionDialog.OpenFile=Datei \u00F6ffnen
-MissingActionDialog.SearchMarketplace=Durchsuche den Marktplatz
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_en_US.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_en_US.properties
index c80a16918c..2e5a3afe0e 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_en_US.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_en_US.properties
@@ -17,8 +17,7 @@
 #
 
 MissingActionDialog.Close=Close
-MissingActionDialog.MissingActionId=The {0} plugin is missing.\nRemove this 
action or try adding the plugin by searching the\nMarketplace.
-MissingActionDialog.MissingActions=This file has missing plugins and will not 
succesfully run.\nYou can open the file and replace the missing 
actions:\n\n{0}Or try adding the plugin(s) by searching the Marketplace.
+MissingActionDialog.MissingActionId=The {0} plugin is missing.\nRemove this 
action or install the missing plugin.
+MissingActionDialog.MissingActions=This file has missing plugins and will not 
succesfully run.\nYou can open the file and replace the missing 
actions:\n\n{0}Or install the missing plugin(s).
 MissingActionDialog.MissingPlugins=Missing Plugins
 MissingActionDialog.OpenFile=Open the File
-MissingActionDialog.SearchMarketplace=Search the Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_es_ES.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_es_ES.properties
index 7d9a89d30a..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_es_ES.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_es_ES.properties
@@ -1,4 +1,5 @@
 #
+#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -14,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingActionDialog.Close=Cerrar
-MissingActionDialog.MissingActionId=Falta el plugin {0}.\nElimine esta 
acci\u00F3n o intente a\u00F1adir el plugin buscando en el\nMarketplace.
-MissingActionDialog.MissingActions=A este archivo le faltan plugins y no se 
ejecutar\u00E1 correctamente.\nPuede abrir el archivo y reemplazar las acciones 
que faltan\:\n\n{0}O intentar a\u00F1adir el/los plugin(s) buscando en el 
Marketplace.
-MissingActionDialog.MissingPlugins=Faltan Plugins
-MissingActionDialog.OpenFile=Abrir el archivo
-MissingActionDialog.SearchMarketplace=Buscar en el Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_it_IT.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_it_IT.properties
index 4dcb4e935f..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_it_IT.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_it_IT.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingActionDialog.Close=Chiudi
-MissingActionDialog.MissingActionId=Il plugin {0} \u00E8 mancante.\nRimuovi 
questa action o prova ad aggiungere il plugin cercandolo nel\nMarketplace
-MissingActionDialog.MissingActions=Questo file ha dei plugin mandanci e non si 
eseguir\u00E0 con successo.\nPuoi aprire il file e sostituire le action 
mancanti:\n\n{0}Oppure prova ad aggiungere il plugin(s) cercandolo nel 
Marketplace.
-MissingActionDialog.MissingPlugins=Plugins mancanti
-MissingActionDialog.OpenFile=Apri il file
-MissingActionDialog.SearchMarketplace=Cerca nel MArketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_pt_BR.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_pt_BR.properties
index 3b87f23e05..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_pt_BR.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_pt_BR.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingActionDialog.Close=Fechar
-MissingActionDialog.MissingActionId=O plugin {0} est\u00E1 ausente.\nRemove 
esta a\u00E7\u00E3o ou tenta adicionar o plugin pelo\nMarketplace.
-MissingActionDialog.MissingActions=Este arquivo tem plugins ausentes e 
n\u00E3o executar\u00E1 com sucesso.\nPodes abrir o arquivo e substituir as 
a\u00E7\u00F5es ausentes:\n\n{0}ou tentar adicionar os plugin(s) pelo 
Marketplace.
-MissingActionDialog.MissingPlugins=Plugins ausentes
-MissingActionDialog.OpenFile=Abra o arquivo
-MissingActionDialog.SearchMarketplace=Pesquise no Marketplace
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_zh_CN.properties
 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_zh_CN.properties
index 76e79a0b6f..b9f6ef0ea8 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_zh_CN.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/workflow/actions/missing/messages/messages_zh_CN.properties
@@ -15,11 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#
 
-MissingActionDialog.Close=\u5173\u95ED
-MissingActionDialog.MissingActionId=\u7F3A\u5931 {0} \u63D2\u4EF6. 
\n\u5220\u9664\u8BE5 Action 
\u6216\u5C1D\u8BD5\u901A\u8FC7\u641C\u7D22\u63D2\u4EF6\u5E02\u573A\u6765\u6DFB\u52A0\u5B83.
-MissingActionDialog.MissingActions=\u65E0\u6CD5\u542F\u52A8 Workflow, 
\u7F3A\u5931\u63D2\u4EF6. \n\u60A8\u53EF\u4EE5\u6253\u5F00\u8BE5 Workflow 
\u6587\u4EF6\u5E76\u66FF\u6362\u7F3A\u5931\u7684 Action\: \n\n{0} 
\u6216\u8005\u5C1D\u8BD5\u901A\u8FC7\u641C\u7D22\u63D2\u4EF6\u5E02\u573A\u6765\u6DFB\u52A0\u5B83.
-MissingActionDialog.MissingPlugins=\u7F3A\u5931\u63D2\u4EF6
-MissingActionDialog.OpenFile=\u6253\u5F00\u6587\u4EF6
-MissingActionDialog.SearchMarketplace=\u641C\u7D22\u63D2\u4EF6\u5E02\u573A


Reply via email to