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.PluginAccessor;
7 import com.atlassian.plugin.PluginArtifact;
8 import com.atlassian.plugin.PluginParseException;
9 import com.atlassian.plugin.event.PluginEventManager;
10 import com.atlassian.plugin.factories.AbstractPluginFactory;
11 import com.atlassian.plugin.impl.UnloadablePlugin;
12 import com.atlassian.plugin.osgi.container.OsgiContainerException;
13 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
14 import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
15 import com.google.common.base.Predicate;
16 import com.google.common.collect.ImmutableSet;
17 import com.google.common.collect.Ranges;
18 import org.apache.commons.io.IOUtils;
19 import org.osgi.framework.Bundle;
20 import org.osgi.framework.Constants;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.jar.Manifest;
28
29 import static com.google.common.base.Preconditions.checkNotNull;
30
31
32
33
34 public final class OsgiBundleFactory extends AbstractPluginFactory
35 {
36 private static final Logger log = LoggerFactory.getLogger(OsgiBundleFactory.class);
37
38 private final OsgiContainerManager osgi;
39 private final PluginEventManager pluginEventManager;
40 private final String pluginDescriptorFileName;
41
42 public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
43 {
44 this(PluginAccessor.Descriptor.FILENAME, osgi, pluginEventManager);
45 }
46
47 public OsgiBundleFactory(String pluginDescriptorFileName, OsgiContainerManager osgi, PluginEventManager pluginEventManager)
48 {
49 super(new OsgiPluginXmlDescriptorParserFactory(), ImmutableSet.<Application>of());
50 this.pluginDescriptorFileName = checkNotNull(pluginDescriptorFileName);
51 this.osgi = checkNotNull(osgi, "The osgi container is required");
52 this.pluginEventManager = checkNotNull(pluginEventManager, "The plugin event manager is required");
53 }
54
55 @Override
56 protected InputStream getDescriptorInputStream(PluginArtifact pluginArtifact)
57 {
58 return pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
59 }
60
61 @Override
62 protected Predicate<Integer> isValidPluginsVersion()
63 {
64 return Ranges.atLeast(Plugin.VERSION_2);
65 }
66
67 public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException
68 {
69 checkNotNull(pluginArtifact, "The plugin artifact is required");
70
71 InputStream manifestStream = null;
72 InputStream descriptorStream = null;
73
74 try
75 {
76 descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
77 manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
78
79 final String pluginKey;
80 if (descriptorStream == null && manifestStream != null)
81 {
82 final Manifest mf = loadManifest(manifestStream);
83 final String bundleSymbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
84 pluginKey = bundleSymbolicName == null ? null : OsgiHeaderUtil.getPluginKey(mf);
85 }
86 else
87 {
88 pluginKey = null;
89 }
90 return pluginKey;
91 }
92 finally
93 {
94 IOUtils.closeQuietly(manifestStream);
95 IOUtils.closeQuietly(descriptorStream);
96 }
97 }
98
99 private Manifest loadManifest(InputStream manifestStream)
100 {
101 try
102 {
103 return new Manifest(manifestStream);
104 }
105 catch (IOException e)
106 {
107 throw new PluginParseException("Unable to parse manifest", e);
108 }
109 }
110
111
112
113
114
115
116
117
118
119 public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
120 {
121 checkNotNull(pluginArtifact, "The plugin artifact is required");
122 checkNotNull(moduleDescriptorFactory, "The module descriptor factory is required");
123
124 File file = pluginArtifact.toFile();
125 boolean allowReference = PluginArtifact.AllowsReference.Default.allowsReference(pluginArtifact);
126 Bundle bundle;
127 try
128 {
129 bundle = OsgiContainerManager.AllowsReferenceInstall.Default.installBundle(osgi, file, allowReference);
130
131 } catch (OsgiContainerException ex)
132 {
133 return reportUnloadablePlugin(file, ex);
134 }
135 String key = OsgiHeaderUtil.getPluginKey(bundle);
136 return new OsgiBundlePlugin(bundle, key, pluginArtifact);
137 }
138
139 private Plugin reportUnloadablePlugin(File file, Exception e)
140 {
141 log.error("Unable to load plugin: "+file, e);
142
143 UnloadablePlugin plugin = new UnloadablePlugin();
144 plugin.setErrorText("Unable to load plugin: "+e.getMessage());
145 return plugin;
146 }
147 }