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
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
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 }