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