2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.automation.jrubyscripting.internal.watch;
15 import java.util.ArrayList;
16 import java.util.HashSet;
17 import java.util.List;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.function.Consumer;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.openhab.automation.jrubyscripting.internal.JRubyScriptEngineFactory;
24 import org.openhab.core.automation.module.script.ScriptDependencyTracker;
25 import org.openhab.core.service.AbstractWatchService;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Tracks Ruby dependencies
32 * @author Cody Cutrer - Initial contribution
35 public class JRubyDependencyTracker implements ScriptDependencyTracker {
36 private final Logger logger = LoggerFactory.getLogger(JRubyDependencyTracker.class);
38 private final Set<ScriptDependencyTracker.Listener> dependencyChangeListeners = ConcurrentHashMap.newKeySet();
40 private final BidiSetBag<String, String> scriptToLibs = new BidiSetBag<>();
42 private final JRubyScriptEngineFactory scriptEngineFactory;
43 private final List<AbstractWatchService> dependencyWatchServices = new ArrayList<>();
45 public JRubyDependencyTracker(final JRubyScriptEngineFactory scriptEngineFactory) {
46 this.scriptEngineFactory = scriptEngineFactory;
49 public void activate() {
50 String gemHome = scriptEngineFactory.getGemHome();
51 if (!gemHome.isEmpty()) {
52 dependencyWatchServices.add(new JRubyGemWatchService(gemHome, this));
54 for (String libPath : scriptEngineFactory.getRubyLibPaths()) {
55 dependencyWatchServices.add(new JRubyLibWatchService(libPath, this));
57 for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
58 dependencyWatchService.activate();
62 public void deactivate() {
63 for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
64 dependencyWatchService.deactivate();
66 dependencyWatchServices.clear();
69 void dependencyChanged(String dependency) {
70 Set<String> scripts = new HashSet<>(scriptToLibs.getKeys(dependency)); // take a copy as it will change as we
71 logger.debug("{} changed; reimporting {} scripts...", dependency, scripts.size());
72 for (String scriptUrl : scripts) {
73 for (ScriptDependencyTracker.Listener listener : dependencyChangeListeners) {
75 listener.onDependencyChange(scriptUrl);
76 } catch (Exception e) {
77 logger.warn("Failed to notify tracker of dependency change: {}: {}", e.getClass(), e.getMessage());
84 public Consumer<String> getTracker(String scriptId) {
85 return dependencyPath -> startTracking(scriptId, dependencyPath);
89 public void removeTracking(String scriptId) {
90 scriptToLibs.removeKey(scriptId);
93 protected void startTracking(String scriptId, String libPath) {
94 scriptToLibs.put(scriptId, libPath);
97 public void addChangeTracker(ScriptDependencyTracker.Listener listener) {
98 logger.trace("adding change tracker listener {}", listener);
99 dependencyChangeListeners.add(listener);
102 public void removeChangeTracker(ScriptDependencyTracker.Listener listener) {
103 logger.trace("removing change tracker listener {}", listener);
104 dependencyChangeListeners.remove(listener);