View Javadoc

1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.Application;
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.AbstractPluginFactory;
11  import com.atlassian.plugin.impl.UnloadablePlugin;
12  import com.atlassian.plugin.osgi.container.OsgiContainerException;
13  import com.atlassian.plugin.osgi.container.OsgiContainerManager;
14  import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
15  import com.google.common.base.Predicate;
16  import com.google.common.collect.ImmutableSet;
17  import com.google.common.collect.Ranges;
18  import org.apache.commons.io.IOUtils;
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  import static com.google.common.base.Preconditions.checkNotNull;
30  
31  /**
32   * Plugin deployer that deploys OSGi bundles that don't contain XML descriptor files
33   */
34  public final class OsgiBundleFactory extends AbstractPluginFactory
35  {
36      private static final Logger log = LoggerFactory.getLogger(OsgiBundleFactory.class);
37  
38      private final OsgiContainerManager osgi;
39      private final PluginEventManager pluginEventManager;
40      private final String pluginDescriptorFileName;
41  
42      public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
43      {
44          this(PluginAccessor.Descriptor.FILENAME, osgi, pluginEventManager);
45      }
46  
47      public OsgiBundleFactory(String pluginDescriptorFileName, OsgiContainerManager osgi, PluginEventManager pluginEventManager)
48      {
49          super(new OsgiPluginXmlDescriptorParserFactory(), ImmutableSet.<Application>of());
50          this.pluginDescriptorFileName = checkNotNull(pluginDescriptorFileName);
51          this.osgi = checkNotNull(osgi, "The osgi container is required");
52          this.pluginEventManager = checkNotNull(pluginEventManager, "The plugin event manager is required");
53      }
54  
55      @Override
56      protected InputStream getDescriptorInputStream(PluginArtifact pluginArtifact)
57      {
58          return pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
59      }
60  
61      @Override
62      protected Predicate<Integer> isValidPluginsVersion()
63      {
64          return Ranges.atLeast(Plugin.VERSION_2);
65      }
66  
67      public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException
68      {
69          checkNotNull(pluginArtifact, "The plugin artifact is required");
70  
71          InputStream manifestStream = null;
72          InputStream descriptorStream = null;
73  
74          try
75          {
76              descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
77              manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
78  
79              final String pluginKey;
80              if (descriptorStream == null && manifestStream != null)
81              {
82                  final Manifest mf = loadManifest(manifestStream);
83                  final String bundleSymbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
84                  pluginKey = bundleSymbolicName == null ? null : OsgiHeaderUtil.getPluginKey(mf);
85              }
86              else // it's not a bundle
87              {
88                  pluginKey = null;
89              }
90              return pluginKey;
91          }
92          finally
93          {
94              IOUtils.closeQuietly(manifestStream);
95              IOUtils.closeQuietly(descriptorStream);
96          }
97      }
98  
99      private Manifest loadManifest(InputStream manifestStream)
100     {
101         try
102         {
103             return new Manifest(manifestStream);
104         }
105         catch (IOException e)
106         {
107             throw new PluginParseException("Unable to parse manifest", e);
108         }
109     }
110 
111     /**
112      * Deploys the plugin artifact
113      * @param pluginArtifact the plugin artifact to deploy
114      * @param moduleDescriptorFactory The factory for plugin modules
115      * @return The instantiated and populated plugin
116      * @throws PluginParseException If the descriptor cannot be parsed
117      * @since 2.2.0
118      */
119     public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
120     {
121         checkNotNull(pluginArtifact, "The plugin artifact is required");
122         checkNotNull(moduleDescriptorFactory, "The module descriptor factory is required");
123 
124         File file = pluginArtifact.toFile();
125         boolean allowReference = PluginArtifact.AllowsReference.Default.allowsReference(pluginArtifact);
126         Bundle bundle;
127         try
128         {
129             bundle = OsgiContainerManager.AllowsReferenceInstall.Default.installBundle(osgi, file, allowReference);
130 
131         } catch (OsgiContainerException ex)
132         {
133             return reportUnloadablePlugin(file, ex);
134         }
135         String key = OsgiHeaderUtil.getPluginKey(bundle);
136         return new OsgiBundlePlugin(bundle, key, pluginArtifact);
137     }
138 
139     private Plugin reportUnloadablePlugin(File file, Exception e)
140     {
141         log.error("Unable to load plugin: "+file, e);
142 
143         UnloadablePlugin plugin = new UnloadablePlugin();
144         plugin.setErrorText("Unable to load plugin: "+e.getMessage());
145         return plugin;
146     }
147 }