1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.*;
4   import com.atlassian.plugin.event.PluginEventManager;
5   import com.atlassian.plugin.impl.UnloadablePlugin;
6   import com.atlassian.plugin.factories.PluginFactory;
7   import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
8   import com.atlassian.plugin.osgi.container.OsgiContainerException;
9   import com.atlassian.plugin.osgi.container.OsgiContainerManager;
10  import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  import org.apache.commons.lang.Validate;
14  import org.apache.commons.io.IOUtils;
15  import org.osgi.framework.Constants;
16  import org.osgi.framework.Bundle;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.jar.Manifest;
22  import java.util.HashMap;
23  import java.util.Hashtable;
24  
25  /**
26   * Plugin deployer that deploys OSGi bundles that don't contain XML descriptor files
27   */
28  public class OsgiBundleFactory implements PluginFactory
29  {
30      private static final Log log = LogFactory.getLog(OsgiBundleFactory.class);
31  
32      private final OsgiContainerManager osgi;
33      private final PluginEventManager pluginEventManager;
34  
35      public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
36      {
37          Validate.notNull(osgi, "The osgi container is required");
38          Validate.notNull(pluginEventManager, "The plugin event manager is required");
39          this.osgi = osgi;
40          this.pluginEventManager = pluginEventManager;
41      }
42  
43      public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException {
44          Validate.notNull(pluginArtifact, "The plugin artifact is required");
45          String pluginKey = null;
46          InputStream manifestStream = null;
47  
48          try
49          {
50              manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
51              if (manifestStream != null)
52              {
53                  Manifest mf;
54                  try {
55                      mf = new Manifest(manifestStream);
56                  } catch (IOException e) {
57                      throw new PluginParseException("Unable to parse manifest", e);
58                  }
59                  String symName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
60                  if (symName != null)
61                  {
62                      pluginKey = OsgiHeaderUtil.getPluginKey(mf);
63                  }
64              }
65              return pluginKey;
66          }
67          finally
68          {
69              IOUtils.closeQuietly(manifestStream);
70          }
71      }
72  
73      /**
74       * @deprecated Since 2.2.0, use {@link #create(PluginArtifact,ModuleDescriptorFactory)} instead
75       */
76      public Plugin create(DeploymentUnit deploymentUnit, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
77      {
78          Validate.notNull(deploymentUnit, "The deployment unit is required");
79          return create(new JarPluginArtifact(deploymentUnit.getPath()), moduleDescriptorFactory);
80      }
81      /**
82       * Deploys the plugin artifact
83       * @param pluginArtifact the plugin artifact to deploy
84       * @param moduleDescriptorFactory The factory for plugin modules
85       * @return The instantiated and populated plugin
86       * @throws PluginParseException If the descriptor cannot be parsed
87       * @since 2.2.0
88       */
89      public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
90      {
91          Validate.notNull(pluginArtifact, "The plugin artifact is required");
92          Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
93  
94          File file = pluginArtifact.toFile();
95          Bundle bundle;
96          try
97          {
98              bundle = osgi.installBundle(file);
99          } catch (OsgiContainerException ex)
100         {
101             return reportUnloadablePlugin(file, ex);
102         }
103         String key = OsgiHeaderUtil.getPluginKey(bundle);
104         return new OsgiBundlePlugin(bundle, key, pluginEventManager);
105     }
106 
107     private Plugin reportUnloadablePlugin(File file, Exception e)
108     {
109         log.error("Unable to load plugin: "+file, e);
110 
111         UnloadablePlugin plugin = new UnloadablePlugin();
112         plugin.setErrorText("Unable to load plugin: "+e.getMessage());
113         return plugin;
114     }
115 }