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.PluginRegistry;
10 import com.atlassian.plugin.PluginRestartState;
11 import com.atlassian.plugin.PluginState;
12 import com.atlassian.plugin.classloader.PluginsClassLoader;
13 import com.atlassian.plugin.event.PluginEventManager;
14 import com.atlassian.plugin.predicate.EnabledModulePredicate;
15 import com.atlassian.plugin.predicate.ModuleOfClassPredicate;
16 import com.atlassian.plugin.scope.ScopeManager;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import javax.annotation.Nullable;
21 import java.io.InputStream;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.function.Predicate;
26 import java.util.stream.Collectors;
27 import java.util.stream.Stream;
28
29 import static com.atlassian.plugin.util.Assertions.notNull;
30
31 public class ProductPluginAccessorBase implements PluginAccessor {
32 private static final Logger log = LoggerFactory.getLogger(ProductPluginAccessorBase.class);
33
34 private final PluginRegistry.ReadOnly pluginRegistry;
35 private final ModuleDescriptorFactory moduleDescriptorFactory;
36 private final ClassLoader classLoader;
37 private final PluginPersistentStateStore store;
38
39 public ProductPluginAccessorBase(final PluginRegistry.ReadOnly pluginRegistry,
40 final PluginPersistentStateStore store,
41 final ModuleDescriptorFactory moduleDescriptorFactory,
42 final PluginEventManager pluginEventManager) {
43 this.pluginRegistry = pluginRegistry;
44 this.moduleDescriptorFactory = notNull("ModuleDescriptorFactory", moduleDescriptorFactory);
45 this.classLoader = new PluginsClassLoader(null, this, pluginEventManager);
46 this.store = notNull("PluginPersistentStateStore", store);
47 }
48
49
50
51
52
53
54 @Deprecated
55 public ProductPluginAccessorBase(final PluginRegistry.ReadOnly pluginRegistry,
56 final PluginPersistentStateStore store,
57 final ModuleDescriptorFactory moduleDescriptorFactory,
58 final PluginEventManager pluginEventManager,
59 final ScopeManager ignored) {
60 this(pluginRegistry, store, moduleDescriptorFactory, pluginEventManager);
61 }
62
63 @Override
64 public Collection<Plugin> getPlugins() {
65 return pluginRegistry.getAll();
66 }
67
68 @Override
69 public Collection<Plugin> getPlugins(final Predicate<Plugin> pluginPredicate) {
70 notNull("pluginPredicate", pluginPredicate);
71 return getPlugins().stream()
72 .filter(pluginPredicate)
73 .collect(Collectors.toList());
74 }
75
76 @Override
77 public Collection<Plugin> getEnabledPlugins() {
78 return getPlugins((Predicate<Plugin>) p -> PluginState.ENABLED.equals(p.getPluginState()));
79 }
80
81
82
83
84
85
86
87
88
89 private <M> Stream<M> getModules(final Stream<ModuleDescriptor<M>> moduleDescriptors) {
90 return moduleDescriptors
91 .filter(Objects::nonNull)
92 .map(md -> {
93 try {
94 return md.getModule();
95 } catch (final RuntimeException ex) {
96 log.error("Exception when retrieving plugin module {}", md.getCompleteKey(), ex);
97 md.setBroken();
98 return null;
99 }
100 })
101 .filter(Objects::nonNull);
102 }
103
104
105
106
107
108
109
110
111
112
113 private <M> Stream<ModuleDescriptor<M>> getModuleDescriptors(final Collection<Plugin> plugins,
114 final Predicate<ModuleDescriptor<M>> predicate) {
115 return plugins.stream()
116 .flatMap(p -> p.getModuleDescriptors().stream())
117 .map(m -> {
118
119
120 @SuppressWarnings("unchecked")
121 final ModuleDescriptor<M> cast = (ModuleDescriptor<M>) m;
122 return cast;
123 })
124 .filter(predicate);
125 }
126
127 @Override
128 public <M> Collection<M> getModules(final Predicate<ModuleDescriptor<M>> predicate) {
129 notNull("moduleDescriptorPredicate", predicate);
130 return getModules(getModuleDescriptors(getPlugins(), predicate))
131 .collect(Collectors.toList());
132 }
133
134 @Override
135 public <M> Collection<ModuleDescriptor<M>> getModuleDescriptors(final Predicate<ModuleDescriptor<M>> predicate) {
136 notNull("moduleDescriptorPredicate", predicate);
137 return getModuleDescriptors(getPlugins(), predicate).collect(Collectors.toList());
138 }
139
140 @Override
141 public Plugin getPlugin(final String key) {
142 return pluginRegistry.get(notNull("Plugin key ", key));
143 }
144
145 @Override
146 public Plugin getEnabledPlugin(final String pluginKey) {
147 if (!isPluginEnabled(pluginKey)) {
148 return null;
149 }
150 return getPlugin(pluginKey);
151 }
152
153 private ModuleDescriptor<?> getPluginModule(final ModuleCompleteKey key) {
154 final Plugin plugin = getPlugin(key.getPluginKey());
155 if (plugin == null) {
156 return null;
157 }
158 return plugin.getModuleDescriptor(key.getModuleKey());
159 }
160
161 @Override
162 public ModuleDescriptor<?> getPluginModule(@Nullable final String completeKey) {
163 return getPluginModule(new ModuleCompleteKey(completeKey));
164 }
165
166 private boolean isPluginModuleEnabled(final ModuleCompleteKey key) {
167 if (!isPluginEnabled(key.getPluginKey())) {
168 return false;
169 }
170 final ModuleDescriptor<?> pluginModule = getPluginModule(key);
171 return (pluginModule != null) && pluginModule.isEnabled();
172 }
173
174 @Override
175 public ModuleDescriptor<?> getEnabledPluginModule(@Nullable final String completeKey) {
176 final ModuleCompleteKey key = new ModuleCompleteKey(completeKey);
177
178
179 if (!isPluginModuleEnabled(key)) {
180 return null;
181 }
182
183 return getEnabledPlugin(key.getPluginKey()).getModuleDescriptor(key.getModuleKey());
184 }
185
186 @Override
187 public boolean isPluginEnabled(final String key) throws IllegalArgumentException {
188 final Plugin plugin = pluginRegistry.get(notNull("Plugin key", key));
189
190 return plugin != null && plugin.getPluginState() == PluginState.ENABLED;
191 }
192
193 @Override
194 public boolean isPluginModuleEnabled(@Nullable final String completeKey) {
195 return (completeKey != null) && isPluginModuleEnabled(new ModuleCompleteKey(completeKey));
196 }
197
198
199
200
201
202
203
204 private <M> Stream<ModuleDescriptor<M>> getEnabledModuleDescriptorsByModuleClass(final Class<M> moduleClass) {
205 final ModuleOfClassPredicate<M> ofType = new ModuleOfClassPredicate<>(moduleClass);
206 final EnabledModulePredicate enabled = new EnabledModulePredicate();
207 return getModuleDescriptors(getEnabledPlugins(), ofType.and(enabled));
208 }
209
210 @Override
211 public <M> List<M> getEnabledModulesByClass(final Class<M> moduleClass) {
212 return getModules(getEnabledModuleDescriptorsByModuleClass(moduleClass))
213 .collect(Collectors.toList());
214 }
215
216 @Override
217 public <D extends ModuleDescriptor<?>> List<D> getEnabledModuleDescriptorsByClass(final Class<D> descriptorClazz) {
218 notNull("Descriptor class", descriptorClazz);
219 return getEnabledPlugins().stream()
220 .flatMap(p -> p.getModuleDescriptors().stream())
221 .filter(descriptorClazz::isInstance)
222 .filter(new EnabledModulePredicate())
223 .map(descriptorClazz::cast)
224 .collect(Collectors.toList());
225 }
226
227 @Override
228 public InputStream getDynamicResourceAsStream(final String resourcePath) {
229 return getClassLoader().getResourceAsStream(resourcePath);
230 }
231
232 @Override
233 public ClassLoader getClassLoader() {
234 return classLoader;
235 }
236
237 @Override
238 public boolean isSystemPlugin(final String key) {
239 final Plugin plugin = getPlugin(key);
240 return (plugin != null) && plugin.isSystemPlugin();
241 }
242
243 @Override
244 public PluginRestartState getPluginRestartState(final String key) {
245 return store.load().getPluginRestartState(key);
246 }
247
248 @Override
249 public Iterable<ModuleDescriptor<?>> getDynamicModules(final Plugin plugin) {
250
251 if (plugin instanceof PluginInternal) {
252 return ((PluginInternal) plugin).getDynamicModuleDescriptors();
253 }
254 throw new IllegalArgumentException(plugin + " does not implement com.atlassian.plugin.PluginInternal it is a " + plugin.getClass().getCanonicalName());
255 }
256 }