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 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 final class OsgiBundleFactory extends AbstractPluginFactory
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 String pluginDescriptorFileName;
39  
40      public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
41      {
42          this(PluginAccessor.Descriptor.FILENAME, osgi, pluginEventManager);
43      }
44  
45      public OsgiBundleFactory(String pluginDescriptorFileName, OsgiContainerManager osgi, PluginEventManager pluginEventManager)
46      {
47          super(new OsgiPluginXmlDescriptorParserFactory(), ImmutableSet.<Application>of());
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      }
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 new Predicate<Integer>()
65          {
66              @Override
67              public boolean apply(Integer version)
68              {
69                  return version >= 2;
70              }
71          };
72      }
73  
74      public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException
75      {
76          Validate.notNull(pluginArtifact, "The plugin artifact is required");
77  
78          InputStream manifestStream = null;
79          InputStream descriptorStream = null;
80  
81          try
82          {
83              descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
84              manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
85  
86              final String pluginKey;
87              if (descriptorStream == null && manifestStream != null)
88              {
89                  final Manifest mf = loadManifest(manifestStream);
90                  final String bundleSymbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
91                  pluginKey = bundleSymbolicName == null ? null : OsgiHeaderUtil.getPluginKey(mf);
92              }
93              else // it's not a bundle
94              {
95                  pluginKey = null;
96              }
97              return pluginKey;
98          }
99          finally
100         {
101             IOUtils.closeQuietly(manifestStream);
102             IOUtils.closeQuietly(descriptorStream);
103         }
104     }
105 
106     private Manifest loadManifest(InputStream manifestStream)
107     {
108         try
109         {
110             return new Manifest(manifestStream);
111         }
112         catch (IOException e)
113         {
114             throw new PluginParseException("Unable to parse manifest", e);
115         }
116     }
117 
118     /**
119      * Deploys the plugin artifact
120      * @param pluginArtifact the plugin artifact to deploy
121      * @param moduleDescriptorFactory The factory for plugin modules
122      * @return The instantiated and populated plugin
123      * @throws PluginParseException If the descriptor cannot be parsed
124      * @since 2.2.0
125      */
126     public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
127     {
128         Validate.notNull(pluginArtifact, "The plugin artifact is required");
129         Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
130 
131         File file = pluginArtifact.toFile();
132         Bundle bundle;
133         try
134         {
135             bundle = osgi.installBundle(file);
136         } catch (OsgiContainerException ex)
137         {
138             return reportUnloadablePlugin(file, ex);
139         }
140         String key = OsgiHeaderUtil.getPluginKey(bundle);
141         return new OsgiBundlePlugin(bundle, key, pluginArtifact, pluginEventManager);
142     }
143 
144     private Plugin reportUnloadablePlugin(File file, Exception e)
145     {
146         log.error("Unable to load plugin: "+file, e);
147 
148         UnloadablePlugin plugin = new UnloadablePlugin();
149         plugin.setErrorText("Unable to load plugin: "+e.getMessage());
150         return plugin;
151     }
152 }