1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.JarPluginArtifact;
4   import com.atlassian.plugin.ModuleDescriptorFactory;
5   import com.atlassian.plugin.Plugin;
6   import com.atlassian.plugin.PluginArtifact;
7   import com.atlassian.plugin.PluginParseException;
8   import com.atlassian.plugin.factories.PluginFactory;
9   import com.atlassian.plugin.impl.UnloadablePlugin;
10  import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
11  import com.atlassian.plugin.parsers.DescriptorParser;
12  import com.atlassian.plugin.parsers.XmlDescriptorParserFactory;
13  import org.apache.commons.io.IOUtils;
14  import org.apache.commons.lang.Validate;
15  
16  import java.io.InputStream;
17  
18  /**
19   * Creates unloadable plugins from static plugins.  Used to handle when a static plugin (version 1) is deployed
20   * to a directory that only accepts OSGi plugins.  This should be placed last in the chain of plugin factories and
21   * only if {@link com.atlassian.plugin.factories.LegacyDynamicPluginFactory} is not used.
22   *
23   * @since 2.2.3
24   */
25  public class UnloadableStaticPluginFactory implements PluginFactory
26  {
27  
28      private final String pluginDescriptorFileName;
29      private final XmlDescriptorParserFactory descriptorParserFactory;
30  
31      public UnloadableStaticPluginFactory(String pluginDescriptorFileName)
32      {
33          this.pluginDescriptorFileName = pluginDescriptorFileName;
34          this.descriptorParserFactory = new XmlDescriptorParserFactory();
35      }
36  
37      public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException
38      {
39          Validate.notNull(pluginArtifact, "The plugin artifact is required");
40  
41          InputStream descriptorStream = null;
42          try
43          {
44              descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
45  
46              if (descriptorStream != null)
47              {
48                  final DescriptorParser descriptorParser = descriptorParserFactory.getInstance(descriptorStream);
49                  if (descriptorParser.getPluginsVersion() == 1)
50                  {
51                      // This is a version 1 plugin inside the version 2 plugin directory - we want to create an
52                      // UnloadablePlugin with appropriate error message.
53                      return descriptorParser.getKey();
54                  }
55              }
56          }
57          finally
58          {
59              IOUtils.closeQuietly(descriptorStream);
60          }
61          return null;
62      }
63  
64      /**
65       * @deprecated Since 2.2.0, use {@link #create(PluginArtifact,ModuleDescriptorFactory)} instead
66       */
67      public Plugin create(DeploymentUnit deploymentUnit, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
68      {
69          Validate.notNull(deploymentUnit, "The deployment unit is required");
70          return create(new JarPluginArtifact(deploymentUnit.getPath()), moduleDescriptorFactory);
71      }
72  
73      /**
74       * Creates an unloadable plugin
75       *
76       * @param pluginArtifact          the plugin artifact to deploy
77       * @param moduleDescriptorFactory The factory for plugin modules
78       * @return The instantiated and populated plugin
79       * @throws PluginParseException If the descriptor cannot be parsed
80       */
81      public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
82      {
83          Validate.notNull(pluginArtifact, "The plugin deployment unit is required");
84          Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
85  
86          UnloadablePlugin plugin = null;
87          InputStream pluginDescriptor = null;
88          try
89          {
90              pluginDescriptor = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
91              if (pluginDescriptor == null)
92              {
93                  throw new PluginParseException("No descriptor found in classloader for : " + pluginArtifact);
94              }
95  
96              DescriptorParser parser = descriptorParserFactory.getInstance(pluginDescriptor);
97  
98              plugin = new UnloadablePlugin();
99              // This should be a valid plugin, it just got put in the wrong directory.
100             // We'll try to do a full configure because it looks more user-friendly.
101             try
102             {
103                 parser.configurePlugin(moduleDescriptorFactory, plugin);
104             }
105             catch (Exception ex)
106             {
107                 // Error on full configure - we'll just set the key as this is an UnloadablePlugin anyway.
108                 plugin.setKey(parser.getKey());   
109             }
110             plugin.setErrorText("Unable to load the static '" + pluginArtifact + "' plugin from the plugins directory.  Please " +
111                                 "copy this file into WEB-INF/lib and restart.");
112         }
113         finally
114         {
115             IOUtils.closeQuietly(pluginDescriptor);
116         }
117         return plugin;
118     }
119 }