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  import org.apache.commons.io.IOUtils;
14  import org.apache.commons.lang.Validate;
15  import org.dom4j.DocumentException;
16  
17  import java.io.FileInputStream;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.HashSet;
23  import java.util.Set;
24  
25  /**
26   * Deploys plugins that consist of an XML descriptor file.
27   *
28   * @since 2.1.0
29   */
30  public class XmlDynamicPluginFactory implements PluginFactory
31  {
32      private final DescriptorParserFactory descriptorParserFactory;
33      private final Set<String> applicationKeys;
34  
35      /**
36       * @deprecated Since 2.2.0, use {@link XmlDynamicPluginFactory(String)} instead
37       */
38      @Deprecated
39      public XmlDynamicPluginFactory()
40      {
41          this(Collections.<String> emptySet());
42      }
43  
44      /**
45       * @param applicationKey The application key to use to choose modules
46       * @since 2.2.0
47       */
48      public XmlDynamicPluginFactory(final String applicationKey)
49      {
50          this(new HashSet<String>(Arrays.asList(applicationKey)));
51      }
52  
53      /**
54       * @param applicationKeys The application key to use to choose modules
55       * @since 2.2.0
56       */
57      public XmlDynamicPluginFactory(final Set<String> applicationKeys)
58      {
59          descriptorParserFactory = new XmlDescriptorParserFactory();
60          Validate.notNull(applicationKeys, "applicationKeys");
61          this.applicationKeys = applicationKeys;
62      }
63  
64      /**
65       * @deprecated Since 2.2.0, use {@link #create(PluginArtifact,ModuleDescriptorFactory)} instead
66       */
67      @Deprecated
68      public Plugin create(final DeploymentUnit deploymentUnit, final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
69      {
70          return create(new XmlPluginArtifact(deploymentUnit.getPath()), moduleDescriptorFactory);
71      }
72  
73      /**
74       * Deploys the plugin artifact
75       * @param pluginArtifact the plugin artifact to deploy
76       * @param moduleDescriptorFactory The factory for plugin modules
77       * @return The instantiated and populated plugin
78       * @throws PluginParseException If the descriptor cannot be parsed
79       * @since 2.2.0
80       */
81      public Plugin create(final PluginArtifact pluginArtifact, final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
82      {
83          Validate.notNull(pluginArtifact, "The plugin artifact must not be null");
84          Validate.notNull(moduleDescriptorFactory, "The module descriptor factory must not be null");
85  
86          InputStream pluginDescriptor = null;
87          try
88          {
89              pluginDescriptor = new FileInputStream(pluginArtifact.toFile());
90              // 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
91              final DescriptorParser parser = descriptorParserFactory.getInstance(pluginDescriptor,
92                  applicationKeys.toArray(new String[applicationKeys.size()]));
93              return parser.configurePlugin(moduleDescriptorFactory, new XmlDynamicPlugin(pluginArtifact));
94          }
95          catch (final RuntimeException e)
96          {
97              throw new PluginParseException(e);
98          }
99          catch (final IOException e)
100         {
101             throw new PluginParseException();
102         }
103         finally
104         {
105             IOUtils.closeQuietly(pluginDescriptor);
106         }
107     }
108 
109     /**
110      * Determines if this deployer can handle this artifact by looking for the plugin descriptor
111      *
112      * @param pluginArtifact The artifact to test
113      * @return The plugin key, null if it cannot load the plugin
114      * @throws com.atlassian.plugin.PluginParseException If there are exceptions parsing the plugin configuration
115      */
116     public String canCreate(final PluginArtifact pluginArtifact) throws PluginParseException
117     {
118         Validate.notNull(pluginArtifact, "The plugin artifact must not be null");
119         InputStream descriptorStream = null;
120         try
121         {
122             descriptorStream = pluginArtifact.getInputStream();
123             if (descriptorStream == null)
124             {
125                 return null;
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 }