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 98a913079a Import of generic database connection does not include jdbc
connection string, fixes #5383 (#7622)
98a913079a is described below
commit 98a913079a2b0c6806ba2668347f8e5cf422a2a8
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Fri Jul 24 17:25:07 2026 +0200
Import of generic database connection does not include jdbc connection
string, fixes #5383 (#7622)
---
plugins/misc/import/pom.xml | 9 ++
.../apache/hop/imports/kettle/KettleImport.java | 9 ++
.../hop/imports/kettle/KettleImportTest.java | 135 +++++++++++++++++++++
3 files changed, 153 insertions(+)
diff --git a/plugins/misc/import/pom.xml b/plugins/misc/import/pom.xml
index b2de36598a..9f5e04d076 100644
--- a/plugins/misc/import/pom.xml
+++ b/plugins/misc/import/pom.xml
@@ -28,4 +28,13 @@
<packaging>jar</packaging>
<name>Hop Plugins Miscellaneous Import</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-databases-generic</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
</project>
diff --git
a/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
b/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
index 09a1246981..76e1de076c 100644
---
a/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
+++
b/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
@@ -467,6 +467,15 @@ public class KettleImport extends HopImportBase implements
IHopImport {
}
databaseMeta.getIDatabase().setAttributes(attributesMap);
+
+ // Kettle stores the JDBC connection string of a generic database
connection in a
+ // CUSTOM_URL attribute, but Hop's GenericDatabaseMeta reads its URL
from the manualUrl
+ // field. Map it across so the imported connection keeps its URL
(#5383). The driver
+ // class is preserved automatically because both use the
CUSTOM_DRIVER_CLASS attribute.
+ if ("GENERIC".equals(databaseType) &&
attributesMap.containsKey("CUSTOM_URL")) {
+
databaseMeta.getIDatabase().setManualUrl(attributesMap.get("CUSTOM_URL"));
+ }
+
addDatabaseMeta(kettleFile.getName().getURI(), databaseMeta);
} catch (Exception e) {
diff --git
a/plugins/misc/import/src/test/java/org/apache/hop/imports/kettle/KettleImportTest.java
b/plugins/misc/import/src/test/java/org/apache/hop/imports/kettle/KettleImportTest.java
new file mode 100644
index 0000000000..6cdf534503
--- /dev/null
+++
b/plugins/misc/import/src/test/java/org/apache/hop/imports/kettle/KettleImportTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.imports.kettle;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.apache.commons.vfs2.FileName;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.core.database.DatabaseMeta;
+import org.apache.hop.core.xml.XmlParserFactoryProducer;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Document;
+
+class KettleImportTest {
+
+ @BeforeAll
+ static void setUpBeforeClass() throws Exception {
+ // Registers the DatabasePluginType so the "GENERIC" connection type can
be resolved.
+ HopClientEnvironment.init();
+ }
+
+ /**
+ * Kettle/PDI stores the JDBC connection string of a generic database
connection in a CUSTOM_URL
+ * attribute, while Hop's GenericDatabaseMeta exposes it through the
manualUrl field. Verify the
+ * importer bridges the two so the URL (and driver class) survive the import
(#5383).
+ */
+ @Test
+ void testGenericConnectionKeepsJdbcUrlAndDriver() throws Exception {
+ String xml =
+ "<transformation>"
+ + "<connection>"
+ + "<name>My Generic DB</name>"
+ + "<server/>"
+ + "<type>GENERIC</type>"
+ + "<access>Native</access>"
+ + "<database/>"
+ + "<port/>"
+ + "<username>myuser</username>"
+ + "<password>mypass</password>"
+ + "<attributes>"
+ + "<attribute><code>CUSTOM_URL</code>"
+ +
"<attribute>jdbc:generic://myhost:1234/mydb</attribute></attribute>"
+ + "<attribute><code>CUSTOM_DRIVER_CLASS</code>"
+ + "<attribute>com.example.MyDriver</attribute></attribute>"
+ + "</attributes>"
+ + "</connection>"
+ + "</transformation>";
+
+ KettleImport kettleImport = new KettleImport();
+ invokeImportDbConnections(kettleImport, parse(xml));
+
+ List<DatabaseMeta> connections = kettleImport.getConnectionsList();
+ assertEquals(1, connections.size());
+
+ DatabaseMeta databaseMeta = connections.get(0);
+ assertEquals("My Generic DB", databaseMeta.getName());
+ // The URL from the CUSTOM_URL attribute must be carried over to
manualUrl...
+ assertEquals("jdbc:generic://myhost:1234/mydb",
databaseMeta.getIDatabase().getManualUrl());
+ // ...and therefore be returned by getURL() for a generic connection.
+ assertEquals("jdbc:generic://myhost:1234/mydb",
databaseMeta.getIDatabase().getURL("", "", ""));
+ // The driver class rides along unchanged because Kettle and Hop share the
attribute name.
+ assertEquals(
+ "com.example.MyDriver",
+
databaseMeta.getIDatabase().getAttributes().get("CUSTOM_DRIVER_CLASS"));
+ }
+
+ /** A generic connection without a CUSTOM_URL attribute must not gain a
manual URL. */
+ @Test
+ void testGenericConnectionWithoutCustomUrlHasNoManualUrl() throws Exception {
+ String xml =
+ "<transformation>"
+ + "<connection>"
+ + "<name>No URL DB</name>"
+ + "<type>GENERIC</type>"
+ + "<access>Native</access>"
+ + "<attributes>"
+ + "<attribute><code>CUSTOM_DRIVER_CLASS</code>"
+ + "<attribute>com.example.MyDriver</attribute></attribute>"
+ + "</attributes>"
+ + "</connection>"
+ + "</transformation>";
+
+ KettleImport kettleImport = new KettleImport();
+ invokeImportDbConnections(kettleImport, parse(xml));
+
+ DatabaseMeta databaseMeta = kettleImport.getConnectionsList().get(0);
+ assertNull(databaseMeta.getIDatabase().getManualUrl());
+ }
+
+ private static Document parse(String xml) throws Exception {
+ try (ByteArrayInputStream in = new
ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
+ return XmlParserFactoryProducer.createSecureDocBuilderFactory()
+ .newDocumentBuilder()
+ .parse(in);
+ }
+ }
+
+ private static void invokeImportDbConnections(KettleImport kettleImport,
Document doc)
+ throws Exception {
+ FileObject kettleFile = mock(FileObject.class);
+ FileName fileName = mock(FileName.class);
+ when(kettleFile.getName()).thenReturn(fileName);
+ when(fileName.getURI()).thenReturn("file:///tmp/test.ktr");
+
+ Method method =
+ KettleImport.class.getDeclaredMethod(
+ "importDbConnections", Document.class, FileObject.class);
+ method.setAccessible(true);
+ method.invoke(kettleImport, doc, kettleFile);
+ }
+}