1 package com.atlassian.plugin.manager;
2
3 import com.atlassian.plugin.ModuleCompleteKey;
4 import com.atlassian.plugin.ModuleDescriptor;
5 import com.atlassian.plugin.ModuleDescriptorFactory;
6 import com.atlassian.plugin.Plugin;
7 import com.atlassian.plugin.PluginAccessor;
8 import com.atlassian.plugin.PluginInternal;
9 import com.atlassian.plugin.PluginParseException;
10 import com.atlassian.plugin.PluginRegistry;
11 import com.atlassian.plugin.PluginRestartState;
12 import com.atlassian.plugin.PluginState;
13 import com.atlassian.plugin.classloader.PluginsClassLoader;
14 import com.atlassian.plugin.event.PluginEventManager;
15 import com.atlassian.plugin.predicate.EnabledModulePredicate;
16 import com.atlassian.plugin.predicate.ModuleDescriptorOfClassPredicate;
17 import com.atlassian.plugin.predicate.ModuleDescriptorOfTypePredicate;
18 import com.atlassian.plugin.predicate.ModuleDescriptorPredicate;
19 import com.atlassian.plugin.predicate.ModuleOfClassPredicate;
20 import com.atlassian.plugin.predicate.PluginPredicate;
21 import com.atlassian.plugin.scope.EverythingIsActiveScopeManager;
22 import com.atlassian.plugin.scope.ScopeManager;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import javax.annotation.Nullable;
27 import java.io.InputStream;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Objects;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33
34 import static com.atlassian.plugin.util.Assertions.notNull;
35
36 public class ProductPluginAccessorBase implements PluginAccessor {
37 private static final Logger log = LoggerFactory.getLogger(ProductPluginAccessorBase.class);
38
39 private final PluginRegistry.ReadOnly pluginRegistry;
40 private final ModuleDescriptorFactory moduleDescriptorFactory;
41 private final ClassLoader classLoader;
42 private final PluginPersistentStateStore store;
43 private final ScopeManager scopeManager;
44
45
46
47
48 @Deprecated
49 public ProductPluginAccessorBase(final PluginRegistry.ReadOnly pluginRegistry,
50 final PluginPersistentStateStore store,
51 final ModuleDescriptorFactory moduleDescriptorFactory,
52 final PluginEventManager pluginEventManager) {
53 this(pluginRegistry, store, moduleDescriptorFactory, pluginEventManager, new EverythingIsActiveScopeManager());
54 }
55
56 public ProductPluginAccessorBase(final PluginRegistry.ReadOnly pluginRegistry,
57 final PluginPersistentStateStore store,
58 final ModuleDescriptorFactory moduleDescriptorFactory,
59 final PluginEventManager pluginEventManager,
60 final ScopeManager scopeManager) {
61 this.pluginRegistry = pluginRegistry;
62 this.moduleDescriptorFactory = notNull("ModuleDescriptorFactory", moduleDescriptorFactory);
63 this.classLoader = new PluginsClassLoader(null, this, pluginEventManager);
64 this.store = notNull("PluginPersistentStateStore", store);
65 this.scopeManager = notNull("ScopeManager", scopeManager);
66 }
67
68 @Override
69 public Collection<Plugin> getPlugins() {
70 return pluginRegistry.getAll();
71 }
72
73 @Override
74 public Collection<Plugin> getPlugins(final PluginPredicate pluginPredicate) {
75 notNull("pluginPredicate", pluginPredicate);
76 return getPlugins().stream()
77 .filter(pluginPredicate::matches)
78 .collect(Collectors.toList());
79 }
80
81 @Override
82 public Collection<Plugin> getEnabledPlugins() {
83 return getPlugins(p -> PluginState.ENABLED.equals(p.getPluginState()));
84 }
85
86
87
88
89
90
91
92
93
94 private <M> Stream<M> getModules(final Stream<ModuleDescriptor<M>> moduleDescriptors) {
95 return moduleDescriptors
96 .filter(Objects::nonNull)
97 .map(md -> {
98 try {
99 return md.getModule();
100 } catch (final RuntimeException ex) {
101 log.error("Exception when retrieving plugin module {}", md.getCompleteKey(), ex);
102 md.setBroken();
103 return null;
104 }
105 })
106 .filter(Objects::nonNull);
107 }
108
109
110
111
112
113
114
115
116
117
118 private <M> Stream<ModuleDescriptor<M>> getModuleDescriptors(final Collection<Plugin> plugins, final ModuleDescriptorPredicate<M> predicate) {
119 return plugins.stream()
120 .flatMap(p -> p.getModuleDescriptors().stream())
121 .map(m -> {
122
123
124 @SuppressWarnings("unchecked")
125 final ModuleDescriptor<M> cast = (ModuleDescriptor<M>) m;
126 return cast;
127 })
128 .filter(predicate::matches);
129 }
130
131 @Override
132 public <M> Collection<M> getModules(final ModuleDescriptorPredicate<M> moduleDescriptorPredicate) {
133 notNull("moduleDescriptorPredicate", moduleDescriptorPredicate);
134 return getModules(getModuleDescriptors(getPlugins(), moduleDescriptorPredicate))
135 .collect(Collectors.toList());
136 }
137
138 @Override
139 public <M> Collection<ModuleDescriptor<M>> getModuleDescriptors(final ModuleDescriptorPredicate<M> moduleDescriptorPredicate) {
140 notNull("moduleDescriptorPredicate", moduleDescriptorPredicate);
141 return getModuleDescriptors(getPlugins(), moduleDescriptorPredicate).collect(Collectors.toList());
142 }
143
144 @Override
145 public Plugin getPlugin(final String key) {
146 return pluginRegistry.get(notNull("Plugin key ", key));
147 }
148
149 @Override
150 public Plugin getEnabledPlugin(final String pluginKey) {
151 if (!isPluginEnabled(pluginKey)) {
152 return null;
153 }
154 return getPlugin(pluginKey);
155 }
156
157 private ModuleDescriptor<?> getPluginModule(final ModuleCompleteKey key) {
158 final Plugin plugin = getPlugin(key.getPluginKey());
159 if (plugin == null) {
160 return null;
161 }
162 return plugin.getModuleDescriptor(key.getModuleKey());
163 }
164
165 @Override
166 public ModuleDescriptor<?> getPluginModule(@Nullable final String completeKey) {
167 return getPluginModule(new ModuleCompleteKey(completeKey));
168 }
169
170 private boolean isPluginModuleEnabled(final ModuleCompleteKey key) {
171 if (!isPluginEnabled(key.getPluginKey())) {
172 return false;
173 }
174 final ModuleDescriptor<?> pluginModule = getPluginModule(key);
175 return (pluginModule != null) && pluginModule.isEnabled();
176 }
177
178 @Override
179 public ModuleDescriptor<?> getEnabledPluginModule(@Nullable final String completeKey) {
180 final ModuleCompleteKey key = new ModuleCompleteKey(completeKey);
181
182
183 if (!isPluginModuleEnabled(key)) {
184 return null;
185 }
186
187 return getEnabledPlugin(key.getPluginKey()).getModuleDescriptor(key.getModuleKey());
188 }
189
190 @Override
191 public boolean isPluginEnabled(final String key) throws IllegalArgumentException {
192 final Plugin plugin = pluginRegistry.get(notNull("Plugin key", key));
193
194 return plugin != null && plugin.getPluginState() == PluginState.ENABLED;
195 }
196
197 @Override
198 public boolean isPluginModuleEnabled(@Nullable final String completeKey) {
199 return (completeKey != null) && isPluginModuleEnabled(new ModuleCompleteKey(completeKey));
200 }
201
202
203
204
205
206
207
208 private <M> Stream<ModuleDescriptor<M>> getEnabledModuleDescriptorsByModuleClass(final Class<M> moduleClass) {
209 final ModuleOfClassPredicate<M> ofType = new ModuleOfClassPredicate<>(moduleClass);
210 final EnabledModulePredicate<M> enabled = new EnabledModulePredicate<>();
211 return getModuleDescriptors(getEnabledPlugins(), (ModuleDescriptor<? extends M> md) -> ofType.matches(md) && enabled.matches(md));
212 }
213
214 @Override
215 public <M> List<M> getEnabledModulesByClass(final Class<M> moduleClass) {
216 return getModules(getEnabledModuleDescriptorsByModuleClass(moduleClass))
217 .collect(Collectors.toList());
218 }
219
220 private <M> List<M> getEnabledModulesByClassAndPredicate(final Class<M> moduleClass, final ModuleDescriptorPredicate<M> predicate) {
221 return getModules(getEnabledModuleDescriptorsByModuleClass(moduleClass).filter(predicate::matches))
222 .collect(Collectors.toList());
223 }
224
225 @Override
226 public <M> List<M> getEnabledModulesByClassAndDescriptor(final Class<ModuleDescriptor<M>>[] descriptorClazz, final Class<M> moduleClass) {
227 return getEnabledModulesByClassAndPredicate(moduleClass, new ModuleDescriptorOfClassPredicate<>(descriptorClazz));
228 }
229
230 @Override
231 public <M> List<M> getEnabledModulesByClassAndDescriptor(final Class<ModuleDescriptor<M>> moduleDescriptorClass, final Class<M> moduleClass) {
232 return getEnabledModulesByClassAndPredicate(moduleClass, new ModuleDescriptorOfClassPredicate<>(moduleDescriptorClass));
233 }
234
235 @Override
236 public <D extends ModuleDescriptor<?>> List<D> getEnabledModuleDescriptorsByClass(final Class<D> descriptorClazz) {
237 notNull("Descriptor class", descriptorClazz);
238 return getEnabledPlugins().stream()
239 .flatMap(p -> p.getModuleDescriptors().stream())
240 .filter(descriptorClazz::isInstance)
241 .filter((new EnabledModulePredicate<>())::matches)
242 .map(descriptorClazz::cast)
243 .collect(Collectors.toList());
244 }
245
246 @Override
247 public <D extends ModuleDescriptor<?>> List<D> getActiveModuleDescriptorsByClass(Class<D> descriptorClazz) {
248 return getEnabledModuleDescriptorsByClass(descriptorClazz)
249 .stream()
250 .filter(m -> ScopeManager.isActive(scopeManager, m))
251 .collect(Collectors.toList());
252 }
253
254 @Override
255 public <D extends ModuleDescriptor<?>> List<D> getEnabledModuleDescriptorsByClass(final Class<D> descriptorClazz, final boolean verbose) {
256 return getEnabledModuleDescriptorsByClass(descriptorClazz);
257 }
258
259 @Override
260 public <M> List<ModuleDescriptor<M>> getEnabledModuleDescriptorsByType(final String type)
261 throws PluginParseException {
262 final ModuleDescriptorOfTypePredicate<M> ofType = new ModuleDescriptorOfTypePredicate<>(moduleDescriptorFactory, type);
263 final EnabledModulePredicate<M> enabled = new EnabledModulePredicate<>();
264 return getModuleDescriptors(getEnabledPlugins(), (ModuleDescriptor<? extends M> md) -> ofType.matches(md) && enabled.matches(md))
265 .collect(Collectors.toList());
266 }
267
268 @Override
269 public InputStream getDynamicResourceAsStream(final String resourcePath) {
270 return getClassLoader().getResourceAsStream(resourcePath);
271 }
272
273 @Override
274 public InputStream getPluginResourceAsStream(final String pluginKey, final String resourcePath) {
275 final Plugin plugin = getEnabledPlugin(pluginKey);
276 if (plugin == null) {
277 log.error("Attempted to retreive resource " + resourcePath + " for non-existent or inactive plugin " + pluginKey);
278 return null;
279 }
280
281 return plugin.getResourceAsStream(resourcePath);
282 }
283
284 @Override
285 public Class<?> getDynamicPluginClass(final String className) throws ClassNotFoundException {
286 return getClassLoader().loadClass(className);
287 }
288
289 @Override
290 public ClassLoader getClassLoader() {
291 return classLoader;
292 }
293
294 @Override
295 public boolean isSystemPlugin(final String key) {
296 final Plugin plugin = getPlugin(key);
297 return (plugin != null) && plugin.isSystemPlugin();
298 }
299
300 @Override
301 public PluginRestartState getPluginRestartState(final String key) {
302 return store.load().getPluginRestartState(key);
303 }
304
305 @Override
306 public Iterable<ModuleDescriptor<?>> getDynamicModules(final Plugin plugin) {
307
308 if (plugin instanceof PluginInternal) {
309 return ((PluginInternal) plugin).getDynamicModuleDescriptors();
310 }
311 throw new IllegalArgumentException(plugin + " does not implement com.atlassian.plugin.PluginInternal it is a " + plugin.getClass().getCanonicalName());
312 }
313 }