View Javadoc

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