1 package com.atlassian.plugin.loaders;
2
3 import com.atlassian.plugin.ModuleDescriptor;
4 import com.atlassian.plugin.ModuleDescriptorFactory;
5 import com.atlassian.plugin.Permissions;
6 import com.atlassian.plugin.Plugin;
7 import com.atlassian.plugin.PluginArtifact;
8 import com.atlassian.plugin.PluginException;
9 import com.atlassian.plugin.PluginInternal;
10 import com.atlassian.plugin.PluginParseException;
11 import com.atlassian.plugin.impl.UnloadablePlugin;
12 import com.google.common.base.Function;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import static com.google.common.collect.ImmutableList.copyOf;
17 import static com.google.common.collect.Iterables.transform;
18
19 public final class PermissionCheckingPluginLoader extends ForwardingPluginLoader {
20 private static final Logger logger = LoggerFactory.getLogger(PermissionCheckingPluginLoader.class);
21
22 public PermissionCheckingPluginLoader(PluginLoader delegate) {
23 super(delegate);
24 }
25
26 @Override
27 public Iterable<Plugin> loadAllPlugins(ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException {
28 return copyOf(transform(delegate().loadAllPlugins(moduleDescriptorFactory), new CheckPluginPermissionFunction()));
29 }
30
31 @Override
32 public Iterable<Plugin> loadFoundPlugins(ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException {
33 return copyOf(transform(delegate().loadFoundPlugins(moduleDescriptorFactory), new CheckPluginPermissionFunction()));
34 }
35
36 @Override
37 public void removePlugin(Plugin plugin) throws PluginException {
38 if (!(plugin instanceof UnloadablePlugin)) {
39 super.removePlugin(plugin);
40 } else {
41 logger.debug("Detected an unloadable plugin '{}', so skipping removal", plugin.getKey());
42 }
43 }
44
45 @Override
46 public void discardPlugin(Plugin plugin) throws PluginException {
47 if (!(plugin instanceof UnloadablePlugin)) {
48 super.discardPlugin(plugin);
49 } else {
50 logger.debug("Detected an unloadable plugin '{}', so skipping discard", plugin.getKey());
51 }
52 }
53
54 private final class CheckPluginPermissionFunction implements Function<Plugin, Plugin> {
55 @Override
56 public Plugin apply(Plugin p) {
57
58 if (p.hasAllPermissions()) {
59 return p;
60 }
61
62 if (p instanceof PluginInternal) {
63 return checkPlugin((PluginInternal) p);
64 }
65 return p;
66 }
67
68 private Plugin checkPlugin(PluginInternal p) {
69 final PluginArtifact pluginArtifact = p.getPluginArtifact();
70 if (pluginArtifact != null) {
71
72 if (pluginArtifact.containsJavaExecutableCode() && !p.getActivePermissions().contains(Permissions.EXECUTE_JAVA)) {
73 UnloadablePlugin unloadablePlugin = new UnloadablePlugin(
74 "Plugin doesn't require '" + Permissions.EXECUTE_JAVA + "' permission yet references some java executable code. " +
75 "This could be either embedded java classes, embedded java libraries, spring context files or bundle activator.");
76 unloadablePlugin.setKey(p.getKey());
77 unloadablePlugin.setName(p.getName());
78
79 logger.warn("Plugin '{}' only requires permission {} which doesn't include '{}', yet has some java code " +
80 "(classes, libs, spring context, etc), making it un-loadable.",
81 p.getKey(), p.getActivePermissions(), Permissions.EXECUTE_JAVA);
82
83
84 discardPlugin(p);
85
86 return unloadablePlugin;
87 } else if (hasSystemModules(p) && !p.getActivePermissions().contains(Permissions.CREATE_SYSTEM_MODULES)) {
88 UnloadablePlugin unloadablePlugin = new UnloadablePlugin(
89 "Plugin doesn't require '" + Permissions.CREATE_SYSTEM_MODULES + "' permission yet declared " +
90 "modules use the 'system' attribute. ");
91 unloadablePlugin.setKey(p.getKey());
92 unloadablePlugin.setName(p.getName());
93
94 logger.warn("Plugin '{}' only requires permission {} which doesn't include '{}', yet has system modules " +
95 ", making it un-loadable.",
96 p.getKey(), p.getActivePermissions(), Permissions.CREATE_SYSTEM_MODULES);
97
98
99 discardPlugin(p);
100
101 return unloadablePlugin;
102 }
103 }
104 return p;
105 }
106
107 private boolean hasSystemModules(Plugin plugin) {
108 for (ModuleDescriptor descriptor : plugin.getModuleDescriptors()) {
109 if (descriptor.isSystemModule()) {
110 return true;
111 }
112 }
113 return false;
114 }
115 }
116 }