View Javadoc

1   package com.atlassian.plugin.osgi.loader;
2   
3   import com.atlassian.plugin.ModuleDescriptorFactory;
4   import com.atlassian.plugin.Plugin;
5   import com.atlassian.plugin.PluginJar;
6   import com.atlassian.plugin.PluginParseException;
7   import com.atlassian.plugin.classloader.PluginClassLoader;
8   import com.atlassian.plugin.impl.UnloadablePlugin;
9   import com.atlassian.plugin.loaders.ClassLoadingPluginLoader;
10  import com.atlassian.plugin.loaders.PluginFactory;
11  import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
12  import com.atlassian.plugin.osgi.container.OsgiContainerException;
13  import com.atlassian.plugin.osgi.container.OsgiContainerManager;
14  import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
15  import com.atlassian.plugin.osgi.loader.transform.DefaultPluginTransformer;
16  import com.atlassian.plugin.osgi.loader.transform.PluginTransformationException;
17  import com.atlassian.plugin.osgi.loader.transform.PluginTransformer;
18  import com.atlassian.plugin.parsers.DescriptorParser;
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.osgi.framework.Constants;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.util.Collection;
26  import java.util.jar.Attributes;
27  import java.util.jar.JarFile;
28  import java.util.jar.Manifest;
29  
30  /**
31   * Plugin loader that starts an OSGi container and loads plugins into it, wrapped as OSGi bundles.
32   */
33  public class OsgiPluginLoader extends ClassLoadingPluginLoader
34  {
35      private static final Log log = LogFactory.getLog(OsgiPluginLoader.class);
36  
37      private OsgiContainerManager osgi;
38      private HostComponentProvider hostComponentProvider;
39      private PluginTransformer pluginTransformer;
40      private final String pluginDescriptorFileName;
41  
42  
43      public OsgiPluginLoader(File pluginPath, String pluginDescriptorFileName, PluginFactory pluginFactory, OsgiContainerManager osgi,
44                              HostComponentProvider provider)
45      {
46          super(pluginPath, pluginDescriptorFileName, pluginFactory);
47          this.hostComponentProvider = provider;
48          pluginTransformer = new DefaultPluginTransformer();
49          this.osgi = osgi;
50          this.pluginDescriptorFileName = pluginDescriptorFileName;
51          setDescriptorParserFactory(new ComponentFilteringXmlDescriptorParserFactory());
52      }
53  
54      public void setPluginTransformer(PluginTransformer trans)
55      {
56          this.pluginTransformer = trans;
57      }
58  
59      @Override
60      public void shutDown()
61      {
62          super.shutDown();
63          osgi.stop();
64      }
65  
66      @Override
67      public synchronized Collection loadAllPlugins(ModuleDescriptorFactory moduleDescriptorFactory)
68      {
69          if (!osgi.isRunning())
70          {
71              osgi.start(hostComponentProvider);
72          }
73          Collection<Plugin> plugins = super.loadAllPlugins(moduleDescriptorFactory);
74          for (Plugin plugin : plugins)
75          {
76              plugin.setEnabled(true);
77          }
78          return plugins;
79      }
80  
81      @Override
82      public Collection addFoundPlugins(ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
83      {
84          Collection<Plugin> plugins = super.addFoundPlugins(moduleDescriptorFactory);
85          for (Plugin plugin : plugins)
86          {
87              plugin.setEnabled(true);
88          }
89          return plugins;
90      }
91  
92      @Override
93      protected Plugin createPlugin(DescriptorParser parser, DeploymentUnit unit, PluginClassLoader loader) {
94          Plugin plugin;
95          switch (parser.getPluginsVersion()) {
96              case 2  : plugin = createOsgiPlugin(unit.getPath(), false);
97                        break;
98              default : plugin = super.createPlugin(parser, unit, loader);
99          }
100         return plugin;
101     }
102 
103     @Override
104     protected Plugin handleNoDescriptor(DeploymentUnit deploymentUnit) throws PluginParseException
105     {
106         try
107         {
108             JarFile jar = new JarFile(deploymentUnit.getPath());
109             Attributes attrs = jar.getManifest().getMainAttributes();
110             String name = attrs.getValue(Constants.BUNDLE_SYMBOLICNAME);
111             if (name != null) {
112                 return createOsgiPlugin(deploymentUnit.getPath(), true);
113             }
114         } catch (IOException e)
115         {
116             throw new PluginParseException("Unable to load jar", e);
117         }
118 
119         throw new PluginParseException("No descriptor found in classloader for : " + deploymentUnit);
120     }
121 
122     @Override
123     public String canLoad(PluginJar pluginJar) throws PluginParseException
124     {
125         String key = super.canLoad(pluginJar);
126 
127         if (key != null)
128         {
129             return key;
130         }
131 
132         // no traditional atlassian-plugins.xml found
133         try
134         {
135             Manifest mf = new Manifest(pluginJar.getFile("META-INF/MANIFEST.MF"));
136             return mf.getMainAttributes().getValue("Bundle-SymbolicName");
137         }
138         catch (IOException e)
139         {
140             throw new PluginParseException("Unable to parse manifest in " + pluginDescriptorFileName, e);
141         }
142     }
143 
144     Plugin createOsgiPlugin(File file, boolean bundle)
145     {
146         try
147         {
148             if (bundle)
149                 return new OsgiBundlePlugin(osgi.installBundle(file));
150             else
151             {
152                 File transformedFile = pluginTransformer.transform(file, osgi.getHostComponentRegistrations());
153                 return new OsgiPlugin(osgi.installBundle(transformedFile));
154             }
155         } catch (OsgiContainerException e)
156         {
157             return reportUnloadablePlugin(file, e);
158         } catch (PluginTransformationException ex)
159         {
160             return reportUnloadablePlugin(file, ex);
161         }
162     }
163 
164     private Plugin reportUnloadablePlugin(File file, Exception e)
165     {
166         log.error("Unable to load plugin: "+file, e);
167 
168         UnloadablePlugin plugin = new UnloadablePlugin();
169         plugin.setErrorText("Unable to load plugin: "+e.getMessage());
170         return plugin;
171     }
172 
173 
174 }