]> git.basschouten.com Git - openhab-addons.git/blob
97a8e8f9119e8caeb3dc09937613026f0dc6c856
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.jrubyscripting.internal.watch;
14
15 import java.nio.file.Path;
16 import java.util.ArrayList;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.function.Consumer;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.openhab.automation.jrubyscripting.internal.JRubyScriptEngineFactory;
25 import org.openhab.core.automation.module.script.ScriptDependencyTracker;
26 import org.openhab.core.service.WatchService;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Tracks Ruby dependencies
32  *
33  * @author Cody Cutrer - Initial contribution
34  * @author Jan N. Klug - Refactored to new WatchService
35  */
36 @NonNullByDefault
37 public class JRubyDependencyTracker implements ScriptDependencyTracker {
38     private final Logger logger = LoggerFactory.getLogger(JRubyDependencyTracker.class);
39
40     private final Set<ScriptDependencyTracker.Listener> dependencyChangeListeners = ConcurrentHashMap.newKeySet();
41
42     private final BidiSetBag<String, String> scriptToLibs = new BidiSetBag<>();
43
44     private final JRubyScriptEngineFactory scriptEngineFactory;
45     private final List<JRubyWatchService> dependencyWatchServices = new ArrayList<>();
46     private final WatchService watchService;
47
48     public JRubyDependencyTracker(final WatchService watchService, final JRubyScriptEngineFactory scriptEngineFactory) {
49         this.watchService = watchService;
50         this.scriptEngineFactory = scriptEngineFactory;
51     }
52
53     public void activate() {
54         String gemHome = scriptEngineFactory.getGemHome();
55         if (!gemHome.isEmpty()) {
56             dependencyWatchServices.add(new JRubyGemWatchService(watchService, gemHome, this));
57         }
58         List<Path> libPaths = scriptEngineFactory.getRubyLibPaths().stream().map(Path::of).toList();
59         dependencyWatchServices.add(new JRubyLibWatchService(watchService, libPaths, this));
60
61         dependencyWatchServices.forEach(JRubyWatchService::activate);
62     }
63
64     public void deactivate() {
65         dependencyWatchServices.forEach(JRubyWatchService::deactivate);
66         dependencyWatchServices.clear();
67     }
68
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) {
74                 try {
75                     listener.onDependencyChange(scriptUrl);
76                 } catch (Exception e) {
77                     logger.warn("Failed to notify tracker of dependency change: {}: {}", e.getClass(), e.getMessage());
78                 }
79             }
80         }
81     }
82
83     @Override
84     public Consumer<String> getTracker(String scriptId) {
85         return dependencyPath -> startTracking(scriptId, dependencyPath);
86     }
87
88     @Override
89     public void removeTracking(String scriptId) {
90         scriptToLibs.removeKey(scriptId);
91     }
92
93     protected void startTracking(String scriptId, String libPath) {
94         scriptToLibs.put(scriptId, libPath);
95     }
96
97     public void addChangeTracker(ScriptDependencyTracker.Listener listener) {
98         logger.trace("adding change tracker listener {}", listener);
99         dependencyChangeListeners.add(listener);
100     }
101
102     public void removeChangeTracker(ScriptDependencyTracker.Listener listener) {
103         logger.trace("removing change tracker listener {}", listener);
104         dependencyChangeListeners.remove(listener);
105     }
106 }