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