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