Skip to content

Commit 2e0b242

Browse files
authored
Fix rules stay uninitialized when using Java 17 (#2787)
On Java 17 there is no Nashorn scripting engine so it takes a bit longer before ScriptEngines are available. Rules would stay uninitialized forever because the ScriptModuleTypeProvider did not notify its listeners whenever script.ScriptAction, script.ScriptCondition became available. Signed-off-by: Wouter Born <github@maindrain.net>
1 parent 5e33cfc commit 2e0b242

File tree

1 file changed

+42
-34
lines changed
  • bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/provider

1 file changed

+42
-34
lines changed

bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/provider/ScriptModuleTypeProvider.java

+42-34
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717
import java.util.List;
1818
import java.util.Locale;
1919
import java.util.Map;
20-
import java.util.Optional;
2120
import java.util.TreeMap;
22-
import java.util.stream.Collectors;
23-
import java.util.stream.Stream;
2421

2522
import javax.script.ScriptEngine;
2623

@@ -36,12 +33,13 @@
3633
import org.openhab.core.automation.type.ModuleType;
3734
import org.openhab.core.automation.type.ModuleTypeProvider;
3835
import org.openhab.core.automation.type.Output;
39-
import org.openhab.core.common.registry.ProviderChangeListener;
36+
import org.openhab.core.common.registry.AbstractProvider;
4037
import org.openhab.core.config.core.ConfigDescriptionParameter;
4138
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
4239
import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
4340
import org.openhab.core.config.core.ParameterOption;
4441
import org.osgi.service.component.annotations.Component;
42+
import org.osgi.service.component.annotations.Deactivate;
4543
import org.osgi.service.component.annotations.Reference;
4644
import org.osgi.service.component.annotations.ReferenceCardinality;
4745
import org.osgi.service.component.annotations.ReferencePolicy;
@@ -56,15 +54,23 @@
5654
*/
5755
@NonNullByDefault
5856
@Component
59-
public class ScriptModuleTypeProvider implements ModuleTypeProvider {
57+
public class ScriptModuleTypeProvider extends AbstractProvider<ModuleType> implements ModuleTypeProvider {
6058

6159
private final Logger logger = LoggerFactory.getLogger(ScriptModuleTypeProvider.class);
6260
private final Map<String, String> parameterOptions = new TreeMap<>();
6361

62+
@Deactivate
63+
public void deactivate() {
64+
listeners.clear();
65+
parameterOptions.clear();
66+
}
67+
6468
@SuppressWarnings("unchecked")
6569
@Override
6670
public @Nullable ModuleType getModuleType(String UID, @Nullable Locale locale) {
67-
if (ScriptActionHandler.TYPE_ID.equals(UID)) {
71+
if (parameterOptions.isEmpty()) {
72+
return null;
73+
} else if (ScriptActionHandler.TYPE_ID.equals(UID)) {
6874
return getScriptActionType(locale);
6975
} else if (ScriptConditionHandler.TYPE_ID.equals(UID)) {
7076
return getScriptConditionType(locale);
@@ -73,26 +79,22 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
7379
}
7480
}
7581

76-
private @Nullable ModuleType getScriptActionType(@Nullable Locale locale) {
77-
if (parameterOptions.isEmpty()) {
78-
return null;
79-
} else {
80-
List<Output> outputs = new ArrayList<>();
81-
Output result = new Output("result", "java.lang.Object", "result", "the script result", null, null, null);
82-
outputs.add(result);
83-
return new ActionType(ScriptActionHandler.TYPE_ID, getConfigDescriptions(locale), "execute a given script",
84-
"Allows the execution of a user-defined script.", null, Visibility.VISIBLE, null, outputs);
85-
}
82+
private ModuleType getScriptActionType(@Nullable Locale locale) {
83+
List<Output> outputs = new ArrayList<>();
84+
Output result = new Output("result", "java.lang.Object", "result", "the script result", null, null, null);
85+
outputs.add(result);
86+
return new ActionType(ScriptActionHandler.TYPE_ID, getConfigDescriptions(locale), "execute a given script",
87+
"Allows the execution of a user-defined script.", null, Visibility.VISIBLE, null, outputs);
8688
}
8789

88-
private @Nullable ModuleType getScriptConditionType(@Nullable Locale locale) {
89-
if (parameterOptions.isEmpty()) {
90-
return null;
91-
} else {
92-
return new ConditionType(ScriptConditionHandler.TYPE_ID, getConfigDescriptions(locale),
93-
"a given script evaluates to true", "Allows the definition of a condition through a script.", null,
94-
Visibility.VISIBLE, null);
95-
}
90+
private ModuleType getScriptConditionType(@Nullable Locale locale) {
91+
return new ConditionType(ScriptConditionHandler.TYPE_ID, getConfigDescriptions(locale),
92+
"a given script evaluates to true", "Allows the definition of a condition through a script.", null,
93+
Visibility.VISIBLE, null);
94+
}
95+
96+
private List<ModuleType> getModuleTypesUnconditionally(@Nullable Locale locale) {
97+
return List.of(getScriptActionType(locale), getScriptConditionType(locale));
9698
}
9799

98100
/**
@@ -118,25 +120,24 @@ private List<ConfigDescriptionParameter> getConfigDescriptions(@Nullable Locale
118120

119121
@Override
120122
public Collection<ModuleType> getModuleTypes(@Nullable Locale locale) {
121-
return Stream
122-
.of(Optional.ofNullable(getScriptActionType(locale)),
123-
Optional.ofNullable(getScriptConditionType(locale)))
124-
.filter(Optional::isPresent).map(Optional::get).collect(Collectors.toUnmodifiableList());
123+
return parameterOptions.isEmpty() ? List.of() : getModuleTypesUnconditionally(locale);
125124
}
126125

127126
@Override
128127
public Collection<ModuleType> getAll() {
129128
return getModuleTypes(null);
130129
}
131130

132-
@Override
133-
public void addProviderChangeListener(ProviderChangeListener<ModuleType> listener) {
134-
// does nothing because this provider does not change
131+
private void notifyModuleTypesAdded() {
132+
for (ModuleType moduleType : getModuleTypesUnconditionally(null)) {
133+
notifyListenersAboutAddedElement(moduleType);
134+
}
135135
}
136136

137-
@Override
138-
public void removeProviderChangeListener(ProviderChangeListener<ModuleType> listener) {
139-
// does nothing because this provider does not change
137+
private void notifyModuleTypesRemoved() {
138+
for (ModuleType moduleType : getModuleTypesUnconditionally(null)) {
139+
notifyListenersAboutRemovedElement(moduleType);
140+
}
140141
}
141142

142143
/**
@@ -149,8 +150,12 @@ public void setScriptEngineFactory(ScriptEngineFactory engineFactory) {
149150
if (!scriptTypes.isEmpty()) {
150151
ScriptEngine scriptEngine = engineFactory.createScriptEngine(scriptTypes.get(0));
151152
if (scriptEngine != null) {
153+
boolean notifyListeners = parameterOptions.isEmpty();
152154
parameterOptions.put(getPreferredMimeType(engineFactory), getLanguageName(scriptEngine.getFactory()));
153155
logger.trace("ParameterOptions: {}", parameterOptions);
156+
if (notifyListeners) {
157+
notifyModuleTypesAdded();
158+
}
154159
} else {
155160
logger.trace("setScriptEngineFactory: engine was null");
156161
}
@@ -166,6 +171,9 @@ public void unsetScriptEngineFactory(ScriptEngineFactory engineFactory) {
166171
if (scriptEngine != null) {
167172
parameterOptions.remove(getPreferredMimeType(engineFactory));
168173
logger.trace("ParameterOptions: {}", parameterOptions);
174+
if (parameterOptions.isEmpty()) {
175+
notifyModuleTypesRemoved();
176+
}
169177
} else {
170178
logger.trace("unsetScriptEngineFactory: engine was null");
171179
}

0 commit comments

Comments
 (0)