1 package com.atlassian.plugin.tracker;
2
3 import com.atlassian.plugin.ModuleDescriptor;
4 import com.atlassian.plugin.PluginAccessor;
5 import com.atlassian.plugin.event.PluginEventListener;
6 import com.atlassian.plugin.event.PluginEventManager;
7 import com.atlassian.plugin.event.events.PluginDisabledEvent;
8 import com.atlassian.plugin.event.events.PluginModuleDisabledEvent;
9 import com.atlassian.plugin.event.events.PluginModuleEnabledEvent;
10 import com.google.common.base.Function;
11
12 import java.util.concurrent.CopyOnWriteArraySet;
13
14 import static com.google.common.collect.Iterables.filter;
15 import static com.google.common.collect.Iterables.transform;
16 import static com.google.common.collect.Iterables.unmodifiableIterable;
17 import static java.util.Collections.singleton;
18
19
20
21
22
23
24 public class DefaultPluginModuleTracker<M, T extends ModuleDescriptor<M>> implements PluginModuleTracker<M, T> {
25 private final PluginEventManager pluginEventManager;
26 private final Class<T> moduleDescriptorClass;
27 private final Customizer<M, T> pluginModuleTrackerCustomizer;
28 private final CopyOnWriteArraySet<T> moduleDescriptors = new CopyOnWriteArraySet<>();
29 private final ModuleTransformer<M, T> moduleTransformer = new ModuleTransformer<>();
30
31
32
33
34
35 public DefaultPluginModuleTracker(final PluginAccessor pluginAccessor, final PluginEventManager pluginEventManager,
36 final Class<T> moduleDescriptorClass) {
37 this(pluginAccessor, pluginEventManager, moduleDescriptorClass, new NoOpPluginModuleTrackerCustomizer<>());
38 }
39
40 public DefaultPluginModuleTracker(final PluginAccessor pluginAccessor, final PluginEventManager pluginEventManager,
41 final Class<T> moduleDescriptorClass,
42 final Customizer<M, T> pluginModuleTrackerCustomizer) {
43 this.pluginEventManager = pluginEventManager;
44 this.moduleDescriptorClass = moduleDescriptorClass;
45 this.pluginModuleTrackerCustomizer = pluginModuleTrackerCustomizer;
46
47
48
49
50
51 pluginEventManager.register(this);
52
53 addDescriptors(pluginAccessor.getEnabledModuleDescriptorsByClass(moduleDescriptorClass));
54 }
55
56
57
58
59
60 public Iterable<T> getModuleDescriptors() {
61 return unmodifiableIterable(moduleDescriptors);
62 }
63
64 public Iterable<M> getModules() {
65 return transform(getModuleDescriptors(), moduleTransformer);
66 }
67
68 public int size() {
69 return moduleDescriptors.size();
70 }
71
72 public void close() {
73 pluginEventManager.unregister(this);
74 }
75
76
77
78
79
80 @PluginEventListener
81 public void onPluginModuleEnabled(final PluginModuleEnabledEvent event) {
82 addDescriptors(singleton((ModuleDescriptor<?>) event.getModule()));
83 }
84
85 @PluginEventListener
86 public void onPluginModuleDisabled(final PluginModuleDisabledEvent event) {
87 removeDescriptors(singleton((ModuleDescriptor<?>) event.getModule()));
88 }
89
90 @PluginEventListener
91 public void onPluginDisabled(final PluginDisabledEvent event) {
92 removeDescriptors(event.getPlugin().getModuleDescriptors());
93 }
94
95
96
97
98
99 private void addDescriptors(final Iterable<? extends ModuleDescriptor<?>> descriptors) {
100 for (final T descriptor : filtered(descriptors)) {
101 final T customized = pluginModuleTrackerCustomizer.adding(descriptor);
102 if (customized != null) {
103 moduleDescriptors.add(customized);
104 }
105 }
106 }
107
108 private void removeDescriptors(final Iterable<? extends ModuleDescriptor<?>> descriptors) {
109 for (final T descriptor : filtered(descriptors)) {
110 if (moduleDescriptors.remove(descriptor)) {
111 pluginModuleTrackerCustomizer.removed(descriptor);
112 }
113 }
114 }
115
116
117
118
119 private Iterable<T> filtered(final Iterable<? extends ModuleDescriptor<?>> descriptors) {
120 return filter(descriptors, moduleDescriptorClass);
121 }
122
123
124
125
126
127 private static class NoOpPluginModuleTrackerCustomizer<M, T extends ModuleDescriptor<M>> implements PluginModuleTracker.Customizer<M, T> {
128 public T adding(final T descriptor) {
129 return descriptor;
130 }
131
132 public void removed(final T descriptor) {
133 }
134 }
135
136
137
138
139 private static class ModuleTransformer<M, T extends ModuleDescriptor<M>> implements Function<T, M> {
140 public M apply(final T from) {
141 return from.getModule();
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156 public static <M, T extends ModuleDescriptor<M>> PluginModuleTracker<M, T> create(final PluginAccessor pluginAccessor,
157 final PluginEventManager pluginEventManager,
158 final Class<? extends ModuleDescriptor<?>> moduleDescriptorClass) {
159 @SuppressWarnings("unchecked")
160 final Class<T> klass = (Class<T>) moduleDescriptorClass;
161 return new DefaultPluginModuleTracker<>(pluginAccessor, pluginEventManager, klass);
162 }
163 }