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 org.apache.commons.io.IOUtils;
18 import org.apache.commons.lang.Validate;
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
30
31
32 public final class OsgiBundleFactory extends AbstractPluginFactory
33 {
34 private static final Logger log = LoggerFactory.getLogger(OsgiBundleFactory.class);
35
36 private final OsgiContainerManager osgi;
37 private final PluginEventManager pluginEventManager;
38 private final String pluginDescriptorFileName;
39
40 public OsgiBundleFactory(OsgiContainerManager osgi, PluginEventManager pluginEventManager)
41 {
42 this(PluginAccessor.Descriptor.FILENAME, osgi, pluginEventManager);
43 }
44
45 public OsgiBundleFactory(String pluginDescriptorFileName, OsgiContainerManager osgi, PluginEventManager pluginEventManager)
46 {
47 super(new OsgiPluginXmlDescriptorParserFactory(), ImmutableSet.<Application>of());
48 this.pluginDescriptorFileName = pluginDescriptorFileName;
49 Validate.notNull(osgi, "The osgi container is required");
50 Validate.notNull(pluginEventManager, "The plugin event manager is required");
51 this.osgi = osgi;
52 this.pluginEventManager = pluginEventManager;
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 new Predicate<Integer>()
65 {
66 @Override
67 public boolean apply(Integer version)
68 {
69 return version >= 2;
70 }
71 };
72 }
73
74 public String canCreate(PluginArtifact pluginArtifact) throws PluginParseException
75 {
76 Validate.notNull(pluginArtifact, "The plugin artifact is required");
77
78 InputStream manifestStream = null;
79 InputStream descriptorStream = null;
80
81 try
82 {
83 descriptorStream = pluginArtifact.getResourceAsStream(pluginDescriptorFileName);
84 manifestStream = pluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
85
86 final String pluginKey;
87 if (descriptorStream == null && manifestStream != null)
88 {
89 final Manifest mf = loadManifest(manifestStream);
90 final String bundleSymbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
91 pluginKey = bundleSymbolicName == null ? null : OsgiHeaderUtil.getPluginKey(mf);
92 }
93 else
94 {
95 pluginKey = null;
96 }
97 return pluginKey;
98 }
99 finally
100 {
101 IOUtils.closeQuietly(manifestStream);
102 IOUtils.closeQuietly(descriptorStream);
103 }
104 }
105
106 private Manifest loadManifest(InputStream manifestStream)
107 {
108 try
109 {
110 return new Manifest(manifestStream);
111 }
112 catch (IOException e)
113 {
114 throw new PluginParseException("Unable to parse manifest", e);
115 }
116 }
117
118
119
120
121
122
123
124
125
126 public Plugin create(PluginArtifact pluginArtifact, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
127 {
128 Validate.notNull(pluginArtifact, "The plugin artifact is required");
129 Validate.notNull(moduleDescriptorFactory, "The module descriptor factory is required");
130
131 File file = pluginArtifact.toFile();
132 Bundle bundle;
133 try
134 {
135 bundle = osgi.installBundle(file);
136 } catch (OsgiContainerException ex)
137 {
138 return reportUnloadablePlugin(file, ex);
139 }
140 String key = OsgiHeaderUtil.getPluginKey(bundle);
141 return new OsgiBundlePlugin(bundle, key, pluginArtifact, pluginEventManager);
142 }
143
144 private Plugin reportUnloadablePlugin(File file, Exception e)
145 {
146 log.error("Unable to load plugin: "+file, e);
147
148 UnloadablePlugin plugin = new UnloadablePlugin();
149 plugin.setErrorText("Unable to load plugin: "+e.getMessage());
150 return plugin;
151 }
152 }