]> git.basschouten.com Git - openhab-addons.git/blob
805951f6a4bbaefd3c3c22908f96477c7441e3a2
[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.util.ArrayList;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.function.Consumer;
21
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;
28
29 /**
30  * Tracks Ruby dependencies
31  *
32  * @author Cody Cutrer - Initial contribution
33  */
34 @NonNullByDefault
35 public class JRubyDependencyTracker implements ScriptDependencyTracker {
36     private final Logger logger = LoggerFactory.getLogger(JRubyDependencyTracker.class);
37
38     private final Set<ScriptDependencyTracker.Listener> dependencyChangeListeners = ConcurrentHashMap.newKeySet();
39
40     private final BidiSetBag<String, String> scriptToLibs = new BidiSetBag<>();
41
42     private final JRubyScriptEngineFactory scriptEngineFactory;
43     private final List<AbstractWatchService> dependencyWatchServices = new ArrayList<>();
44
45     public JRubyDependencyTracker(final JRubyScriptEngineFactory scriptEngineFactory) {
46         this.scriptEngineFactory = scriptEngineFactory;
47     }
48
49     public void activate() {
50         String gemHome = scriptEngineFactory.getGemHome();
51         if (!gemHome.isEmpty()) {
52             dependencyWatchServices.add(new JRubyGemWatchService(gemHome, this));
53         }
54         for (String libPath : scriptEngineFactory.getRubyLibPaths()) {
55             dependencyWatchServices.add(new JRubyLibWatchService(libPath, this));
56         }
57         for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
58             dependencyWatchService.activate();
59         }
60     }
61
62     public void deactivate() {
63         for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
64             dependencyWatchService.deactivate();
65         }
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 }