Skip to content

Commit b2c5204

Browse files
authored
Merge branch 'openhab:main' into worlfown-markdownlinter
2 parents 01ecdf5 + f871501 commit b2c5204

File tree

136 files changed

+4099
-2136
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+4099
-2136
lines changed

.github/scripts/maven-build

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function mvnp() {
1818
set -o pipefail # exit build with error when pipes fail
1919
local reactor_size=$(find -name "pom.xml" | grep -vE '/src/|/target/' | wc -l)
2020
local padding=$(bc -l <<< "scale=0;2*(l($reactor_size)/l(10)+1)")
21-
local command=(mvn $@)
21+
local command=(./mvnw $@)
2222
exec "${command[@]}" 2>&1 | # execute, redirect stderr to stdout
2323
tee "$BUILD_LOG" | # write output to log
2424
stdbuf -oL grep -aE '^\[INFO\] Building .+ \[.+\]$' | # filter progress
@@ -30,7 +30,7 @@ function build_all() {
3030
echo
3131
echo "Building all projects"
3232
echo
33-
echo "+ mvn $ARGUMENTS"
33+
echo "+ ./mvnw $ARGUMENTS"
3434
echo
3535

3636
mvnp $ARGUMENTS
@@ -79,16 +79,16 @@ function addon_projects() {
7979

8080
function build_addon() {
8181
local addon="$1"
82-
local mvn_command="mvn $ARGUMENTS -am -amd -pl $(addon_projects $addon)"
82+
local command="./mvnw $ARGUMENTS -am -amd -pl $(addon_projects $addon)"
8383

8484
echo
8585
echo "Building add-on: $addon"
8686
echo
87-
echo "+ $mvn_command"
87+
echo "+ $command"
8888
echo
8989

9090
set -o pipefail # exit build with error when pipes fail
91-
$mvn_command 2>&1 | tee "$BUILD_LOG"
91+
$command 2>&1 | tee "$BUILD_LOG"
9292
exit $?
9393
}
9494

@@ -104,5 +104,5 @@ function build_based_on_changes() {
104104
fi
105105
}
106106

107-
mvn -v
107+
./mvnw -v
108108
build_based_on_changes

.github/workflows/ci-build.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ jobs:
1919
fail-fast: false
2020
matrix:
2121
java: [ '21' ]
22-
maven: [ '3.9.10' ]
2322
os: [ 'ubuntu-24.04' ]
2423
name: Build (Java ${{ matrix.java }}, ${{ matrix.os }})
2524
runs-on: ${{ matrix.os }}
@@ -52,12 +51,6 @@ jobs:
5251
distribution: 'temurin'
5352
java-version: ${{ matrix.java }}
5453

55-
# pinning to SHA to mitigate possible supply chain attacks
56-
- name: Set up Maven ${{ matrix.maven }}
57-
uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5
58-
with:
59-
maven-version: ${{ matrix.maven }}
60-
6154
- name: Register Problem Matchers
6255
if: ${{ matrix.java == '21' }}
6356
id: problem_matchers
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
wrapperVersion=3.3.2
18+
distributionType=only-script
19+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
20+
distributionSha256Sum=0d7125e8c91097b36edb990ea5934e6c68b4440eef4ea96510a0f6815e7eeadb

bundles/org.openhab.automation.groovyscripting/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Groovy Scripting
22

3-
This add-on provides support for [Groovy](https://groovy-lang.org/) 4.0.27 that can be used as a scripting language within automation rules and which eliminates the need to manually install Groovy.
3+
This add-on provides support for [Groovy](https://groovy-lang.org/) 4.0.28 that can be used as a scripting language within automation rules.
44

55
## Creating Groovy Scripts
66

bundles/org.openhab.automation.groovyscripting/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
<properties>
1818
<bnd.importpackage>com.ibm.icu.*;resolution:=optional,groovy.runtime.metaclass;resolution:=optional,groovyjarjarantlr4.stringtemplate;resolution:=optional,org.abego.treelayout.*;resolution:=optional,org.apache.ivy.*;resolution:=optional,org.fusesource.jansi.*;resolution:=optional,org.stringtemplate.v4.*;resolution:=optional</bnd.importpackage>
19-
<groovy.version>4.0.27</groovy.version>
19+
<groovy.version>4.0.28</groovy.version>
2020
</properties>
2121

2222
<dependencies>

bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/DebuggingGraalScriptEngine.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,22 @@ public Exception afterThrowsInvocation(Exception e) {
7373
// OPS4J Pax Logging holds a reference to the exception, which causes the OpenhabGraalJSScriptEngine to not be
7474
// removed from heap by garbage collection and causing a memory leak.
7575
// Therefore, don't pass the exceptions itself to the logger, but only their message!
76-
if (cause instanceof IllegalArgumentException) {
77-
logger.error("Failed to execute script: {}", stringifyThrowable(cause));
78-
} else if (cause instanceof PolyglotException) {
79-
logger.error("Failed to execute script: {}", stringifyThrowable(cause));
76+
if (cause instanceof IllegalArgumentException || cause instanceof PolyglotException) {
77+
String strT = stringifyThrowable(cause);
78+
logger.error("Failed to execute script: {}", strT);
8079
}
8180
return e;
8281
}
8382

83+
@Override
84+
public void close() {
85+
try {
86+
super.close();
87+
} catch (Exception e) {
88+
logger.warn("Ignorable exception during close: {}", stringifyThrowable(e));
89+
}
90+
}
91+
8492
private String stringifyThrowable(Throwable throwable) {
8593
String message = throwable.getMessage();
8694
StackTraceElement[] stackTraceElements = throwable.getStackTrace();
@@ -106,10 +114,9 @@ private void initializeLogger() {
106114
identifier = fileName.toString().replaceAll("^.*[/\\\\]", "");
107115
} else if (ruleUID != null) {
108116
identifier = ruleUID.toString();
109-
} else if (ohEngineIdentifier != null) {
110-
if (ohEngineIdentifier.toString().startsWith(OPENHAB_TRANSFORMATION_SCRIPT)) {
111-
identifier = ohEngineIdentifier.toString().replaceAll(OPENHAB_TRANSFORMATION_SCRIPT, "transformation.");
112-
}
117+
} else if (ohEngineIdentifier != null
118+
&& ohEngineIdentifier.toString().startsWith(OPENHAB_TRANSFORMATION_SCRIPT)) {
119+
identifier = ohEngineIdentifier.toString().replaceAll(OPENHAB_TRANSFORMATION_SCRIPT, "transformation.");
113120
}
114121

115122
logger = LoggerFactory.getLogger("org.openhab.automation.script.javascript." + identifier);

bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.openhab.automation.jsscripting.internal.fs.ReadOnlySeekableByteArrayChannel;
5555
import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker;
5656
import org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndCompilableAndAutoCloseable;
57+
import org.openhab.automation.jsscripting.internal.scriptengine.helper.LifecycleTracker;
5758
import org.openhab.core.automation.module.script.ScriptExtensionAccessor;
5859
import org.openhab.core.items.Item;
5960
import org.openhab.core.library.types.QuantityType;
@@ -138,13 +139,15 @@ public class OpenhabGraalJSScriptEngine
138139
/** {@link Lock} synchronization of multi-thread access */
139140
private final Lock lock = new ReentrantLock();
140141
private final JSRuntimeFeatures jsRuntimeFeatures;
142+
private final LifecycleTracker lifecycleTracker = new LifecycleTracker();
141143
private final GraalJSScriptEngineConfiguration configuration;
142144

143145
// these fields start as null because they are populated on first use
144146
private @Nullable Consumer<String> scriptDependencyListener;
145147
private String engineIdentifier = "<uninitialized>";
146148

147149
private boolean initialized = false;
150+
private boolean closed = false;
148151

149152
/**
150153
* Creates an implementation of ScriptEngine {@code (& Invocable)}, wrapping the contained engine,
@@ -283,7 +286,7 @@ protected void beforeInvocation() {
283286
scriptDependencyListener = localScriptDependencyListener;
284287

285288
ScriptExtensionModuleProvider scriptExtensionModuleProvider = new ScriptExtensionModuleProvider(
286-
scriptExtensionAccessor, lock);
289+
scriptExtensionAccessor, lock, lifecycleTracker);
287290

288291
// Wrap the "require" function to also allow loading modules from the ScriptExtensionModuleProvider
289292
Function<Function<Object[], Object>, Function<String, Object>> wrapRequireFn = originalRequireFn -> moduleName -> scriptExtensionModuleProvider
@@ -326,7 +329,7 @@ protected void beforeInvocation() {
326329
protected String onScript(String script) {
327330
if (isUiBasedScript() && configuration.isWrapperEnabled()) {
328331
logger.debug("Wrapping script for engine '{}' ...", engineIdentifier);
329-
return "(function() {" + script + "})()";
332+
return "(function() {" + System.lineSeparator() + script + System.lineSeparator() + "})()";
330333
}
331334
return super.onScript(script);
332335
}
@@ -345,8 +348,26 @@ protected Exception afterThrowsInvocation(Exception e) {
345348
}
346349

347350
@Override
348-
public void close() {
349-
jsRuntimeFeatures.close();
351+
public void close() throws Exception {
352+
if (closed) {
353+
logger.debug("Engine '{}' is already disposed and closed.", engineIdentifier);
354+
return;
355+
}
356+
357+
lock.lock();
358+
try {
359+
try {
360+
jsRuntimeFeatures.close();
361+
this.lifecycleTracker.dispose();
362+
} finally {
363+
logger.debug("Engine '{}' disposed.", engineIdentifier);
364+
super.close();
365+
logger.debug("Engine '{}' closed.", engineIdentifier);
366+
}
367+
} finally {
368+
closed = true;
369+
lock.unlock();
370+
}
350371
}
351372

352373
/**

bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/ScriptExtensionModuleProvider.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.graalvm.polyglot.Context;
2323
import org.graalvm.polyglot.Source;
2424
import org.graalvm.polyglot.Value;
25+
import org.openhab.automation.jsscripting.internal.scriptengine.helper.LifecycleTracker;
2526
import org.openhab.automation.jsscripting.internal.threading.ThreadsafeWrappingScriptedAutomationManagerDelegate;
2627
import org.openhab.core.automation.module.script.ScriptExtensionAccessor;
2728
import org.openhab.core.automation.module.script.rulesupport.shared.ScriptedAutomationManager;
@@ -30,22 +31,25 @@
3031
* Class providing script extensions via CommonJS modules (with module name `@runtime`).
3132
*
3233
* @author Jonathan Gilbert - Initial contribution
33-
* @author Florian Hotze - Pass in lock object for multi-thread synchronization; Switch to {@link Lock} for multi-thread
34-
* synchronization
34+
* @author Florian Hotze - Pass in a lock object for multi-thread synchronisation
35+
* @author Florian Hotze - Switch to {@link Lock} for multi-thread synchronisation
36+
* @author Florian Hotze - Overwrite lifecycleTracker with our own implementation
3537
*/
36-
3738
@NonNullByDefault
3839
public class ScriptExtensionModuleProvider {
3940

4041
private static final String RUNTIME_MODULE_PREFIX = "@runtime";
4142
private static final String DEFAULT_MODULE_NAME = "Defaults";
4243
private final Lock lock;
44+
private final LifecycleTracker lifecycleTracker;
4345

4446
private final ScriptExtensionAccessor scriptExtensionAccessor;
4547

46-
public ScriptExtensionModuleProvider(ScriptExtensionAccessor scriptExtensionAccessor, Lock lock) {
48+
public ScriptExtensionModuleProvider(ScriptExtensionAccessor scriptExtensionAccessor, Lock lock,
49+
LifecycleTracker lifecycleTracker) {
4750
this.scriptExtensionAccessor = scriptExtensionAccessor;
4851
this.lock = lock;
52+
this.lifecycleTracker = lifecycleTracker;
4953
}
5054

5155
public ModuleLocator locatorFor(Context ctx, String engineIdentifier) {
@@ -68,6 +72,7 @@ private Optional<Value> runtimeModule(String name, String scriptIdentifier, Cont
6872

6973
if (DEFAULT_MODULE_NAME.equals(name)) {
7074
symbols = scriptExtensionAccessor.findDefaultPresets(scriptIdentifier);
75+
symbols.put("lifecycleTracker", lifecycleTracker);
7176
} else {
7277
symbols = scriptExtensionAccessor.findPreset(name, scriptIdentifier);
7378
}
@@ -102,9 +107,9 @@ private Map<String, Object> processValues(Map<String, Object> values) {
102107
Map<String, Object> rv = new HashMap<>(values);
103108

104109
for (Map.Entry<String, Object> entry : rv.entrySet()) {
105-
if (entry.getValue() instanceof ScriptedAutomationManager) {
106-
entry.setValue(new ThreadsafeWrappingScriptedAutomationManagerDelegate(
107-
(ScriptedAutomationManager) entry.getValue(), lock));
110+
if (entry.getValue() instanceof ScriptedAutomationManager scriptedAutomationManager) {
111+
entry.setValue(
112+
new ThreadsafeWrappingScriptedAutomationManagerDelegate(scriptedAutomationManager, lock));
108113
}
109114
}
110115

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2010-2025 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.automation.jsscripting.internal.scriptengine.helper;
14+
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
18+
import org.eclipse.jdt.annotation.NonNullByDefault;
19+
20+
/**
21+
* LifecycleTracker implementation
22+
*
23+
* <p>
24+
* We can't use core's lifecycle tracker for JS Scripting, because its dispose hooks are called after the engine has
25+
* been closed (which will not work).
26+
*
27+
* @author Florian Hotze - Initial contribution
28+
*/
29+
@NonNullByDefault
30+
public class LifecycleTracker {
31+
private List<Runnable> disposables = new ArrayList<>();
32+
33+
public void addDisposeHook(Runnable disposable) {
34+
disposables.add(disposable);
35+
}
36+
37+
public void dispose() {
38+
for (Runnable disposable : disposables) {
39+
disposable.run();
40+
}
41+
}
42+
}

bundles/org.openhab.automation.jsscriptingnashorn/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
<properties>
1818
<bnd.importpackage>jdk.dynalink.*;resolution:=optional</bnd.importpackage>
19-
<asm.version>9.7.1</asm.version>
19+
<asm.version>9.8</asm.version>
2020
</properties>
2121

2222
<dependencies>

0 commit comments

Comments
 (0)