View Javadoc

1   package com.atlassian.plugin.factories;
2   
3   import com.atlassian.plugin.ModuleDescriptorFactory;
4   import com.atlassian.plugin.Plugin;
5   import com.atlassian.plugin.PluginArtifact;
6   import com.atlassian.plugin.PluginParseException;
7   import com.atlassian.plugin.XmlPluginArtifact;
8   import com.atlassian.plugin.impl.XmlDynamicPlugin;
9   import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
10  import com.atlassian.plugin.parsers.DescriptorParser;
11  import com.atlassian.plugin.parsers.DescriptorParserFactory;
12  import com.atlassian.plugin.parsers.XmlDescriptorParserFactory;
13  
14  import org.apache.commons.io.IOUtils;
15  import org.apache.commons.lang.Validate;
16  import org.dom4j.DocumentException;
17  
18  import java.io.FileInputStream;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  /**
27   * Deploys plugins that consist of an XML descriptor file.
28   *
29   * @since 2.1.0
30   */
31  public class XmlDynamicPluginFactory implements PluginFactory
32  {
33      private final DescriptorParserFactory descriptorParserFactory;
34      private final Set<String> applicationKeys;
35  
36      /**
37       * @deprecated Since 2.2.0, use {@link XmlDynamicPluginFactory(String)} instead
38       */
39      @Deprecated
40      public XmlDynamicPluginFactory()
41      {
42          this(Collections.<String> emptySet());
43      }
44  
45      /**
46       * @param applicationKey The application key to use to choose modules
47       * @since 2.2.0
48       */
49      public XmlDynamicPluginFactory(final String applicationKey)
50      {
51          this(new HashSet<String>(Arrays.asList(applicationKey)));
52      }
53  
54      /**
55       * @param applicationKeys The application key to use to choose modules
56       * @since 2.2.0
57       */
58      public XmlDynamicPluginFactory(final Set<String> applicationKeys)
59      {
60          descriptorParserFactory = new XmlDescriptorParserFactory();
61          Validate.notNull(applicationKeys, "applicationKeys");
62          this.applicationKeys = applicationKeys;
63      }
64  
65      /**
66       * @deprecated Since 2.2.0, use {@link #create(PluginArtifact,ModuleDescriptorFactory)} instead
67       */
68      @Deprecated
69      public Plugin create(final DeploymentUnit deploymentUnit, final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
70      {
71          return create(new XmlPluginArtifact(deploymentUnit.getPath()), moduleDescriptorFactory);
72      }
73  
74      /**
75       * Deploys the plugin artifact
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       * @since 2.2.0
81       */
82      public Plugin create(final PluginArtifact pluginArtifact, final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
83      {
84          Validate.notNull(pluginArtifact, "The plugin artifact must not be null");
85          Validate.notNull(moduleDescriptorFactory, "The module descriptor factory must not be null");
86  
87          InputStream pluginDescriptor = null;
88          try
89          {
90              pluginDescriptor = new FileInputStream(pluginArtifact.toFile());
91              // The plugin we get back may not be the same (in the case of an UnloadablePlugin), so add what gets returned, rather than the original
92              final DescriptorParser parser = descriptorParserFactory.getInstance(pluginDescriptor,
93                  applicationKeys.toArray(new String[applicationKeys.size()]));
94              return parser.configurePlugin(moduleDescriptorFactory, new XmlDynamicPlugin());
95          }
96          catch (final RuntimeException e)
97          {
98              throw new PluginParseException(e);
99          }
100         catch (final IOException e)
101         {
102             throw new PluginParseException();
103         }
104         finally
105         {
106             IOUtils.closeQuietly(pluginDescriptor);
107         }
108     }
109 
110     /**
111      * Determines if this deployer can handle this artifact by looking for the plugin descriptor
112      *
113      * @param pluginArtifact The artifact to test
114      * @return The plugin key, null if it cannot load the plugin
115      * @throws com.atlassian.plugin.PluginParseException If there are exceptions parsing the plugin configuration
116      */
117     public String canCreate(final PluginArtifact pluginArtifact) throws PluginParseException
118     {
119         Validate.notNull(pluginArtifact, "The plugin artifact must not be null");
120         final InputStream descriptorStream = pluginArtifact.getInputStream();
121         if (descriptorStream == null)
122         {
123             return null;
124         }
125         try
126         {
127             final DescriptorParser descriptorParser = descriptorParserFactory.getInstance(descriptorStream,
128                 applicationKeys.toArray(new String[applicationKeys.size()]));
129             return descriptorParser.getKey();
130         }
131         catch (final PluginParseException ex)
132         {
133             if (!(ex.getCause() instanceof DocumentException))
134             {
135                 throw ex;
136             }
137             return null;
138         }
139         finally
140         {
141             IOUtils.closeQuietly(descriptorStream);
142         }
143     }
144 }