1 package com.atlassian.plugin.osgi.factory;
2
3 import com.atlassian.plugin.ModuleDescriptorFactory;
4 import com.atlassian.plugin.Plugin;
5 import com.atlassian.plugin.PluginArtifact;
6 import com.atlassian.plugin.PluginParseException;
7 import com.atlassian.plugin.classloader.PluginClassLoader;
8 import com.atlassian.plugin.descriptors.ChainModuleDescriptorFactory;
9 import com.atlassian.plugin.factories.PluginFactory;
10 import com.atlassian.plugin.impl.UnloadablePlugin;
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.factory.transform.DefaultPluginTransformer;
15 import com.atlassian.plugin.osgi.factory.transform.PluginTransformationException;
16 import com.atlassian.plugin.osgi.factory.transform.PluginTransformer;
17 import com.atlassian.plugin.parsers.DescriptorParser;
18 import com.atlassian.plugin.parsers.DescriptorParserFactory;
19 import org.apache.commons.io.IOUtils;
20 import org.apache.commons.lang.Validate;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.osgi.util.tracker.ServiceTracker;
24
25 import java.io.File;
26 import java.io.InputStream;
27
28
29
30
31 public class OsgiPluginFactory implements PluginFactory
32 {
33 private static final Log log = LogFactory.getLog(OsgiPluginFactory.class);
34
35 private final OsgiContainerManager osgi;
36 private final PluginTransformer pluginTransformer;
37 private final String pluginDescriptorFileName;
38 private final DescriptorParserFactory descriptorParserFactory;
39
40 private ServiceTracker moduleDescriptorFactoryTracker;
41
42 public OsgiPluginFactory(String pluginDescriptorFileName, OsgiContainerManager osgi)
43 {
44 Validate.notNull(pluginDescriptorFileName, "Plugin descriptor is required");
45 Validate.notNull(osgi, "The OSGi container is required");
46
47 pluginTransformer = new DefaultPluginTransformer();
48 this.osgi = osgi;
49 this.pluginDescriptorFileName = pluginDescriptorFileName;
50 this.descriptorParserFactory = new ComponentFilteringXmlDescriptorParserFactory();
51 }
52
53 public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException {
54 Validate.notNull(pluginArtifact, "The plugin artifact is required");
55
56 String pluginKey = null;
57 InputStream descriptorStream = null;
58 try
59 {
60 descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
61
62 if (descriptorStream != null)
63 {
64 final DescriptorParser descriptorParser = descriptorParserFactory.getInstance(descriptorStream);
65 if (descriptorParser.getPluginsVersion() == 2)
66 pluginKey = descriptorParser.getKey();
67 }
68 }
69 finally
70 {
71 IOUtils.closeQuietly(descriptorStream);
72 }
73 return pluginKey;
74 }
75
76 public Plugin create(DeploymentUnit deploymentUnit, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException {
77 Validate.notNull(deploymentUnit, "The plugin deployment unit is required");
78 Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
79
80 Plugin plugin = null;
81 InputStream pluginDescriptor = null;
82 PluginClassLoader loader = new PluginClassLoader(deploymentUnit.getPath());
83
84 if (loader.getResource(pluginDescriptorFileName) == null)
85 throw new PluginParseException("No descriptor found in classloader for : " + deploymentUnit);
86
87 try
88 {
89 Plugin osgiPlugin = createOsgiPlugin(deploymentUnit.getPath());
90 ModuleDescriptorFactory combinedFactory = getChainedModuleDescriptorFactory(moduleDescriptorFactory);
91 pluginDescriptor = loader.getResourceAsStream(pluginDescriptorFileName);
92
93 DescriptorParser parser = descriptorParserFactory.getInstance(pluginDescriptor);
94 plugin = parser.configurePlugin(combinedFactory, osgiPlugin);
95 }
96 finally
97 {
98 IOUtils.closeQuietly(pluginDescriptor);
99 }
100 return plugin;
101 }
102
103
104
105
106
107
108
109 private ModuleDescriptorFactory getChainedModuleDescriptorFactory(ModuleDescriptorFactory originalFactory)
110 {
111
112 synchronized(this)
113 {
114 if (moduleDescriptorFactoryTracker == null)
115 moduleDescriptorFactoryTracker = osgi.getServiceTracker(ModuleDescriptorFactory.class.getName());
116 }
117
118
119 if (moduleDescriptorFactoryTracker != null)
120 {
121 Object[] serviceObjs = moduleDescriptorFactoryTracker.getServices();
122 ModuleDescriptorFactory[] dynamicFactories;
123 if (serviceObjs != null && serviceObjs.length > 0)
124 {
125 dynamicFactories = new ModuleDescriptorFactory[serviceObjs.length + 1];
126 System.arraycopy(serviceObjs, 0, dynamicFactories, 1, serviceObjs.length);
127 }
128 else
129 {
130 dynamicFactories = new ModuleDescriptorFactory[1];
131 }
132 dynamicFactories[0] = originalFactory;
133
134 return new ChainModuleDescriptorFactory(dynamicFactories);
135 }
136 else
137 return originalFactory;
138
139
140 }
141
142 private Plugin createOsgiPlugin(File file)
143 {
144 try
145 {
146 File transformedFile = pluginTransformer.transform(file, osgi.getHostComponentRegistrations());
147 return new OsgiPlugin(osgi.installBundle(transformedFile));
148 } catch (OsgiContainerException e)
149 {
150 return reportUnloadablePlugin(file, e);
151 } catch (PluginTransformationException ex)
152 {
153 return reportUnloadablePlugin(file, ex);
154 }
155 }
156
157 private Plugin reportUnloadablePlugin(File file, Exception e)
158 {
159 log.error("Unable to load plugin: "+file, e);
160
161 UnloadablePlugin plugin = new UnloadablePlugin();
162 plugin.setErrorText("Unable to load plugin: "+e.getMessage());
163 return plugin;
164 }
165 }