View Javadoc

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.PluginAccessor;
7   import com.atlassian.plugin.PluginArtifact;
8   import com.atlassian.plugin.PluginParseException;
9   import com.atlassian.plugin.event.PluginEventManager;
10  import com.atlassian.plugin.factories.PluginFactory;
11  import com.atlassian.plugin.impl.UnloadablePlugin;
12  import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
13  import com.atlassian.plugin.osgi.container.OsgiContainerException;
14  import com.atlassian.plugin.osgi.container.OsgiContainerManager;
15  import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
16  import com.atlassian.plugin.parsers.DescriptorParser;
17  import org.apache.commons.io.IOUtils;
18  import org.apache.commons.lang.Validate;
19  import org.osgi.framework.Bundle;
20  import org.osgi.framework.Constants;
21  import org.slf4j.Logger;
22  import org.slf4j.LoggerFactory;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.util.jar.Manifest;
28  
29  /**
30   * Plugin deployer that deploys OSGi bundles that don't contain XML descriptor files
31   */
32  public class OsgiBundleFactory implements PluginFactory
33  {
34      private static final Logger log = LoggerFactory.getLogger(OsgiBundleFactory.class);
35  
36      private final OsgiContainerManager osgi;
37      private final PluginEventManager pluginEventManager;
38      private final OsgiPluginXmlDescriptorParserFactory descriptorParserFactory;
39      private final String pluginDescriptorFileName;
40  
41      public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
42      {
43          this(PluginAccessor.Descriptor.FILENAME, osgi, pluginEventManager);
44      }
45  
46      public OsgiBundleFactory(String pluginDescriptorFileName, OsgiContainerManager osgi, PluginEventManager pluginEventManager)
47      {
48          this.pluginDescriptorFileName = pluginDescriptorFileName;
49          Validate.notNull(osgi, "The osgi container is required");
50          Validate.notNull(pluginEventManager, "The plugin event manager is required");
51          this.osgi = osgi;
52          this.pluginEventManager = pluginEventManager;
53          this.descriptorParserFactory = new OsgiPluginXmlDescriptorParserFactory();
54      }
55  
56      public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException {
57          Validate.notNull(pluginArtifact, "The plugin artifact is required");
58          String pluginKey = null;
59          InputStream manifestStream = null;
60          InputStream descriptorStream = null;
61  
62          try
63          {
64              manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
65              if (manifestStream != null)
66              {
67                  Manifest mf;
68                  try {
69                      mf = new Manifest(manifestStream);
70                  } catch (IOException e) {
71                      throw new PluginParseException("Unable to parse manifest", e);
72                  }
73                  String symName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
74                  if (symName != null)
75                  {
76                      pluginKey = OsgiHeaderUtil.getPluginKey(mf);
77  
78                      // Check for a descriptor in case it really is a version 1 plugin
79                      descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
80                      if (descriptorStream != null)
81                      {
82                          final DescriptorParser descriptorParser = descriptorParserFactory.getInstance(descriptorStream);
83                          if (descriptorParser.getPluginsVersion() == 1)
84                          {
85                              // Nope, it isn't a bundle
86                              pluginKey = null;
87                          }
88                      }
89  
90                  }
91              }
92              return pluginKey;
93          }
94          finally
95          {
96              IOUtils.closeQuietly(manifestStream);
97              IOUtils.closeQuietly(descriptorStream);
98          }
99      }
100 
101     /**
102      * @deprecated Since 2.2.0, use {@link #create(PluginArtifact,ModuleDescriptorFactory)} instead
103      */
104     public Plugin create(DeploymentUnit deploymentUnit, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
105     {
106         Validate.notNull(deploymentUnit, "The deployment unit is required");
107         return create(new JarPluginArtifact(deploymentUnit.getPath()), moduleDescriptorFactory);
108     }
109     /**
110      * Deploys the plugin artifact
111      * @param pluginArtifact the plugin artifact to deploy
112      * @param moduleDescriptorFactory The factory for plugin modules
113      * @return The instantiated and populated plugin
114      * @throws PluginParseException If the descriptor cannot be parsed
115      * @since 2.2.0
116      */
117     public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
118     {
119         Validate.notNull(pluginArtifact, "The plugin artifact is required");
120         Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
121 
122         File file = pluginArtifact.toFile();
123         Bundle bundle;
124         try
125         {
126             bundle = osgi.installBundle(file);
127         } catch (OsgiContainerException ex)
128         {
129             return reportUnloadablePlugin(file, ex);
130         }
131         String key = OsgiHeaderUtil.getPluginKey(bundle);
132         return new OsgiBundlePlugin(bundle, key, pluginArtifact, pluginEventManager);
133     }
134 
135     private Plugin reportUnloadablePlugin(File file, Exception e)
136     {
137         log.error("Unable to load plugin: "+file, e);
138 
139         UnloadablePlugin plugin = new UnloadablePlugin();
140         plugin.setErrorText("Unable to load plugin: "+e.getMessage());
141         return plugin;
142     }
143 }