This is an automated email from the ASF dual-hosted git repository.
bamaer 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 162362a306 early start log4j2 and minor improvement in the scripts,
fixes #9150 (#9151)
162362a306 is described below
commit 162362a306abae9ac519179c954184c3350eceef
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Oct 29 21:01:07 2026 +0100
early start log4j2 and minor improvement in the scripts, fixes #9150 (#9151)
---
assemblies/static/src/main/resources/hop | 9 ++-
assemblies/static/src/main/resources/hop-conf.sh | 9 ++-
.../static/src/main/resources/hop-encrypt.sh | 9 ++-
assemblies/static/src/main/resources/hop-export.sh | 9 ++-
assemblies/static/src/main/resources/hop-gui.sh | 6 +-
assemblies/static/src/main/resources/hop-import.sh | 9 ++-
assemblies/static/src/main/resources/hop-run.sh | 9 ++-
assemblies/static/src/main/resources/hop-search.sh | 9 ++-
assemblies/static/src/main/resources/hop-server.sh | 9 ++-
.../java/org/apache/hop/core/HopEnvironment.java | 76 +++++++++++++++++++++-
engine/src/main/java/org/apache/hop/hop/Hop.java | 2 +
.../src/main/java/org/apache/hop/run/HopRun.java | 1 +
.../main/java/org/apache/hop/www/HopServer.java | 2 +
.../HopEnvironmentSystemPropertiesArgsTest.java | 44 +++++++++++++
14 files changed, 161 insertions(+), 42 deletions(-)
diff --git a/assemblies/static/src/main/resources/hop
b/assemblies/static/src/main/resources/hop
index 4581032399..573fa25c6c 100755
--- a/assemblies/static/src/main/resources/hop
+++ b/assemblies/static/src/main/resources/hop
@@ -92,11 +92,10 @@ Linux)
if [ "${XDG_SESSION_TYPE}" = "wayland" ]; then
export GDK_BACKEND=x11
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-conf.sh
b/assemblies/static/src/main/resources/hop-conf.sh
index b37f14c4ff..92d238d360 100755
--- a/assemblies/static/src/main/resources/hop-conf.sh
+++ b/assemblies/static/src/main/resources/hop-conf.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-encrypt.sh
b/assemblies/static/src/main/resources/hop-encrypt.sh
index 0e5f3d40cf..f78a1bda91 100755
--- a/assemblies/static/src/main/resources/hop-encrypt.sh
+++ b/assemblies/static/src/main/resources/hop-encrypt.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-export.sh
b/assemblies/static/src/main/resources/hop-export.sh
index a93c3c3ca8..b9b2c77b0b 100755
--- a/assemblies/static/src/main/resources/hop-export.sh
+++ b/assemblies/static/src/main/resources/hop-export.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-gui.sh
b/assemblies/static/src/main/resources/hop-gui.sh
index c833874a6e..bb0aab7e7a 100755
--- a/assemblies/static/src/main/resources/hop-gui.sh
+++ b/assemblies/static/src/main/resources/hop-gui.sh
@@ -80,7 +80,11 @@ fi
HOP_OPTIONS="${HOP_OPTIONS} -DHOP_PLATFORM_RUNTIME=GUI
-DHOP_AUTO_CREATE_CONFIG=Y -DHOP_PLATFORM_OS="$(uname -s)
HOP_OPTIONS="${HOP_OPTIONS} --add-opens java.xml/jdk.xml.internal=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens
java.base/java.lang.invoke=ALL-UNNAMED --add-opens
java.base/java.lang.reflect=ALL-UNNAMED --add-opens
java.base/java.io=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.base/java.nio=ALL-UNNAMED --add-opens
java.base/java.util=ALL-UNNAMED --add-opens
java.base/java.util.concurrent=ALL-UNNAMED --add-opens
java.base/java.util.concurre [...]
-os_arch="$(${_HOP_JAVA} -XshowSettings:properties -version 2>&1 | grep
"os.arch" | awk -F= '{print $2}' | xargs)"
+if [ "$(uname -s)" = "Linux" ]; then
+ os_arch="$(uname -m)"
+else
+ os_arch="$(${_HOP_JAVA} -XshowSettings:properties -version 2>&1 | grep
"os.arch" | awk -F= '{print $2}' | xargs)"
+fi
arch_path="$(echo "$os_arch" | sed 's/aarch/arm/g' | sed 's/amd/x86_/g')"
case $(uname -s) in
Linux)
diff --git a/assemblies/static/src/main/resources/hop-import.sh
b/assemblies/static/src/main/resources/hop-import.sh
index b7af9463a6..c0775f61e5 100755
--- a/assemblies/static/src/main/resources/hop-import.sh
+++ b/assemblies/static/src/main/resources/hop-import.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-run.sh
b/assemblies/static/src/main/resources/hop-run.sh
index 38f353a421..456372fc56 100755
--- a/assemblies/static/src/main/resources/hop-run.sh
+++ b/assemblies/static/src/main/resources/hop-run.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-search.sh
b/assemblies/static/src/main/resources/hop-search.sh
index 265d53bf1c..4d96caa44e 100755
--- a/assemblies/static/src/main/resources/hop-search.sh
+++ b/assemblies/static/src/main/resources/hop-search.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/assemblies/static/src/main/resources/hop-server.sh
b/assemblies/static/src/main/resources/hop-server.sh
index d363b2fb43..16fc1a62e1 100755
--- a/assemblies/static/src/main/resources/hop-server.sh
+++ b/assemblies/static/src/main/resources/hop-server.sh
@@ -87,11 +87,10 @@ Linux)
fi
- if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*"
- else
- CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*"
- fi
+ case "$(uname -m)" in
+ aarch64 | arm64)
CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/arm64/*" ;;
+ *) CLASSPATH="lib/core/*:lib/spark-client/*:lib/swt/linux/$(uname -m)/*" ;;
+ esac
;;
Darwin)
if "${_HOP_JAVA}" -XshowSettings:properties -version 2>&1 | grep -q "os.arch
= aarch64"; then
diff --git a/engine/src/main/java/org/apache/hop/core/HopEnvironment.java
b/engine/src/main/java/org/apache/hop/core/HopEnvironment.java
index 9498a3d730..7898d31eaf 100644
--- a/engine/src/main/java/org/apache/hop/core/HopEnvironment.java
+++ b/engine/src/main/java/org/apache/hop/core/HopEnvironment.java
@@ -80,6 +80,9 @@ public class HopEnvironment {
*/
private static final ThreadLocal<Boolean> initializing = new ThreadLocal<>();
+ /** Starts Log4j2 while the plugins are registered, see {@link
#startLoggingBackend()}. */
+ private static final AtomicReference<Thread> loggingBackendStart = new
AtomicReference<>();
+
/**
* Initializes the Hop environment. This method performs the following
operations:
*
@@ -90,6 +93,11 @@ public class HopEnvironment {
* @throws HopException Any errors that occur during initialization will
throw a HopException.
*/
public static void init() throws HopException {
+ if (initialized.get() == null) {
+ // Building the plugin types below already reads the Hop configuration,
and with it the
+ // logging back end starts
+ startLoggingBackend();
+ }
init(getStandardPluginTypes());
}
@@ -133,7 +141,7 @@ public class HopEnvironment {
System.setProperties(ConcurrentMapProperties.convertProperties(System.getProperties()));
try {
- silenceVerboseThirdPartyLoggers();
+ startLoggingBackend();
// This creates .hop and hop.properties...
//
@@ -209,6 +217,7 @@ public class HopEnvironment {
// If it's a HopException, throw it, otherwise wrap it in a
HopException
throw ((t instanceof HopException hopException) ? hopException : new
HopException(t));
} finally {
+ awaitLoggingBackend();
initializing.remove();
}
@@ -303,6 +312,71 @@ public class HopEnvironment {
java.util.logging.Logger.getLogger("org.apache.hc.client5.http.wire"),
java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc"));
+ /**
+ * Starting Log4j2 loads several hundred classes and parses its
configuration, a few hundred
+ * milliseconds that do not depend on the plugins. It runs in the background
while they are
+ * registered. Loggers handed out before it is done switch to the configured
back end once it is;
+ * {@link #awaitLoggingBackend()} makes sure it is done when init() returns.
+ *
+ * <p>A command line tool can call this before it parses its arguments, when
nothing in them can
+ * change the system properties the logging back end reads. init() starts it
otherwise.
+ */
+ public static void startLoggingBackend() {
+ Thread thread =
+ new Thread(
+ () -> {
+ try {
+ // The same path as the first library that logs:
commons-logging, then SLF4J
+
org.apache.commons.logging.LogFactory.getLog(HopEnvironment.class);
+ } catch (LinkageError | Exception ignored) {
+ // Logging falls back to whatever the libraries find themselves
+ }
+ silenceVerboseThirdPartyLoggers();
+ },
+ "Hop logging back end start");
+ thread.setDaemon(true);
+ if (loggingBackendStart.compareAndSet(null, thread)) {
+ thread.start();
+ }
+ }
+
+ /**
+ * Starts the logging back end for a command line tool before it parses its
arguments, unless the
+ * arguments may set system properties: those must be applied first, as the
logging back end reads
+ * them.
+ */
+ public static void startLoggingBackend(String[] args) {
+ if (!maySetSystemProperties(args)) {
+ startLoggingBackend();
+ }
+ }
+
+ /**
+ * Whether the arguments may hold system properties: -s or
--system-properties, possibly in a
+ * group of short options, or an argument file that picocli expands.
+ */
+ static boolean maySetSystemProperties(String[] args) {
+ for (String arg : args) {
+ if (arg.startsWith("--system-properties")
+ || arg.startsWith("@")
+ || (arg.startsWith("-") && !arg.startsWith("--") && arg.indexOf('s')
> 0)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void awaitLoggingBackend() {
+ Thread thread = loggingBackendStart.getAndSet(null);
+ if (thread != null) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
/**
* Default verbose third-party loggers to a non-debug level to prevent
dumping raw network bytes
* or driver chatter to the console while preserving explicitly configured
levels.
diff --git a/engine/src/main/java/org/apache/hop/hop/Hop.java
b/engine/src/main/java/org/apache/hop/hop/Hop.java
index 3e40715280..77441a793c 100644
--- a/engine/src/main/java/org/apache/hop/hop/Hop.java
+++ b/engine/src/main/java/org/apache/hop/hop/Hop.java
@@ -78,6 +78,8 @@ public class Hop {
}
public static void main(String[] args) throws Exception {
+ HopEnvironment.startLoggingBackend(args);
+
Hop hop = new Hop();
hop.cmd = new CommandLine(hop);
diff --git a/engine/src/main/java/org/apache/hop/run/HopRun.java
b/engine/src/main/java/org/apache/hop/run/HopRun.java
index a45003a9f3..314a62e223 100644
--- a/engine/src/main/java/org/apache/hop/run/HopRun.java
+++ b/engine/src/main/java/org/apache/hop/run/HopRun.java
@@ -46,6 +46,7 @@ public class HopRun extends HopRunBase implements Runnable,
IHasHopMetadataProvi
}
public static void main(String[] args) {
+ HopEnvironment.startLoggingBackend(args);
HopRun hopRun = new HopRun();
diff --git a/engine/src/main/java/org/apache/hop/www/HopServer.java
b/engine/src/main/java/org/apache/hop/www/HopServer.java
index b3edd91734..1900085e71 100644
--- a/engine/src/main/java/org/apache/hop/www/HopServer.java
+++ b/engine/src/main/java/org/apache/hop/www/HopServer.java
@@ -694,6 +694,8 @@ public class HopServer implements Runnable,
IHasHopMetadataProvider, IHopCommand
}
public static void main(String[] args) {
+ HopEnvironment.startLoggingBackend(args);
+
String[] arguments =
Stream.of(args)
.flatMap(a -> Stream.of(a.split("(?=--)")))
diff --git
a/engine/src/test/java/org/apache/hop/core/HopEnvironmentSystemPropertiesArgsTest.java
b/engine/src/test/java/org/apache/hop/core/HopEnvironmentSystemPropertiesArgsTest.java
new file mode 100644
index 0000000000..a8bd7a0971
--- /dev/null
+++
b/engine/src/test/java/org/apache/hop/core/HopEnvironmentSystemPropertiesArgsTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.core;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class HopEnvironmentSystemPropertiesArgsTest {
+
+ @Test
+ void argumentsWithoutSystemProperties() {
+ assertFalse(HopEnvironment.maySetSystemProperties(new String[0]));
+ assertFalse(
+ HopEnvironment.maySetSystemProperties(
+ new String[] {"-j", "project", "-r", "local", "-f",
"/a/sales/pipeline.hpl"}));
+ assertFalse(
+ HopEnvironment.maySetSystemProperties(new String[] {"--level=Basic",
"--file=x.hpl"}));
+ }
+
+ @Test
+ void argumentsThatMaySetSystemProperties() {
+ assertTrue(HopEnvironment.maySetSystemProperties(new String[] {"-s",
"A=1"}));
+ assertTrue(HopEnvironment.maySetSystemProperties(new String[]
{"-sA=1,B=2"}));
+ assertTrue(HopEnvironment.maySetSystemProperties(new String[]
{"--system-properties=A=1"}));
+ assertTrue(HopEnvironment.maySetSystemProperties(new String[] {"-f",
"x.hpl", "@options.txt"}));
+ }
+}