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.PluginArtifact;
7 import com.atlassian.plugin.PluginParseException;
8 import com.atlassian.plugin.event.PluginEventManager;
9 import com.atlassian.plugin.factories.AbstractPluginFactory;
10 import com.atlassian.plugin.impl.UnloadablePlugin;
11 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
12 import com.atlassian.plugin.osgi.factory.transform.PluginTransformationException;
13 import com.atlassian.plugin.parsers.DescriptorParser;
14 import com.google.common.base.Predicate;
15 import com.google.common.collect.Ranges;
16 import org.apache.commons.io.IOUtils;
17 import org.osgi.util.tracker.ServiceTracker;
18
19 import java.io.File;
20 import java.io.InputStream;
21 import java.util.Set;
22
23 import static com.google.common.base.Preconditions.checkNotNull;
24
25
26
27
28
29
30
31
32
33
34
35 public final class RemotablePluginFactory extends AbstractPluginFactory
36 {
37 private final OsgiContainerManager osgi;
38 private final String pluginDescriptorFileName;
39 private final PluginEventManager pluginEventManager;
40
41 private final OsgiChainedModuleDescriptorFactoryCreator osgiChainedModuleDescriptorFactoryCreator;
42
43
44
45
46 public RemotablePluginFactory(String pluginDescriptorFileName, Set<Application> applications, final OsgiContainerManager osgi, PluginEventManager pluginEventManager)
47 {
48 super(new OsgiPluginXmlDescriptorParserFactory(), applications);
49 this.pluginDescriptorFileName = checkNotNull(pluginDescriptorFileName, "Plugin descriptor is required");
50 this.osgi = checkNotNull(osgi, "The OSGi container is required");
51 this.pluginEventManager = checkNotNull(pluginEventManager, "The plugin event manager is required");
52 this.osgiChainedModuleDescriptorFactoryCreator = new OsgiChainedModuleDescriptorFactoryCreator(new OsgiChainedModuleDescriptorFactoryCreator.ServiceTrackerFactory()
53 {
54 public ServiceTracker create(String className)
55 {
56 return osgi.getServiceTracker(className);
57 }
58 });
59 }
60
61 @Override
62 protected InputStream getDescriptorInputStream(PluginArtifact pluginArtifact)
63 {
64 return pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
65 }
66
67 @Override
68 protected Predicate<Integer> isValidPluginsVersion()
69 {
70 return Ranges.singleton(Plugin.VERSION_3);
71 }
72
73
74
75
76
77
78
79
80
81
82
83 public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
84 {
85 checkNotNull(pluginArtifact, "The plugin deployment unit is required");
86 checkNotNull(moduleDescriptorFactory, "The module descriptor factory is required");
87
88 Plugin plugin = null;
89 InputStream pluginDescriptor = null;
90 try
91 {
92 pluginDescriptor = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
93 if (pluginDescriptor != null)
94 {
95 final ModuleDescriptorFactory combinedFactory = getChainedModuleDescriptorFactory(moduleDescriptorFactory, pluginArtifact);
96 final DescriptorParser parser = descriptorParserFactory.getInstance(pluginDescriptor, applications);
97
98 final String pluginKey = parser.getKey();
99 final Plugin osgiPlugin = new OsgiPlugin(pluginKey, osgi, pluginArtifact, pluginArtifact, pluginEventManager);
100
101
102 plugin = parser.configurePlugin(combinedFactory, osgiPlugin);
103 }
104 else
105 {
106 throw new PluginParseException("Attempt to create Remotable plugin without a plugin descriptor!");
107 }
108 }
109 catch (PluginTransformationException ex)
110 {
111 return reportUnloadablePlugin(pluginArtifact.toFile(), ex);
112 }
113 finally
114 {
115 IOUtils.closeQuietly(pluginDescriptor);
116 }
117 return plugin;
118 }
119
120
121
122
123
124
125
126
127 private ModuleDescriptorFactory getChainedModuleDescriptorFactory(ModuleDescriptorFactory originalFactory, final PluginArtifact pluginArtifact)
128 {
129 return osgiChainedModuleDescriptorFactoryCreator.create(new OsgiChainedModuleDescriptorFactoryCreator.ResourceLocator()
130 {
131 public boolean doesResourceExist(String name)
132 {
133 return pluginArtifact.doesResourceExist(name);
134 }
135 }, originalFactory);
136 }
137
138 private Plugin reportUnloadablePlugin(File file, Exception e)
139 {
140 log.error("Unable to load plugin: " + file, e);
141
142 UnloadablePlugin plugin = new UnloadablePlugin();
143 plugin.setErrorText("Unable to load plugin: " + e.getMessage());
144 return plugin;
145 }
146 }