1 package com.atlassian.plugin.osgi.factory;
2
3 import com.atlassian.plugin.Permissions;
4 import com.atlassian.plugin.PluginArtifact;
5 import com.atlassian.plugin.PluginArtifactBackedPlugin;
6 import com.atlassian.plugin.PluginException;
7 import com.atlassian.plugin.PluginInformation;
8 import com.atlassian.plugin.PluginPermission;
9 import com.atlassian.plugin.PluginState;
10 import com.atlassian.plugin.impl.AbstractPlugin;
11 import com.atlassian.plugin.osgi.util.BundleClassLoaderAccessor;
12 import com.atlassian.plugin.osgi.util.OsgiSystemBundleUtil;
13 import com.atlassian.plugin.util.resource.AlternativeDirectoryResourceLoader;
14 import com.google.common.collect.ImmutableSet;
15 import org.osgi.framework.Bundle;
16 import org.osgi.framework.BundleEvent;
17 import org.osgi.framework.BundleException;
18 import org.osgi.framework.Constants;
19 import org.osgi.framework.SynchronousBundleListener;
20
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.util.Date;
24
25 import static com.google.common.base.Preconditions.checkNotNull;
26
27
28
29
30 public final class OsgiBundlePlugin extends AbstractPlugin implements PluginArtifactBackedPlugin
31 {
32
33 private final Bundle bundle;
34 private final Date dateLoaded;
35 private final ClassLoader bundleClassLoader;
36 private final SynchronousBundleListener bundleStartStopListener;
37 private final PluginArtifact pluginArtifact;
38
39 public OsgiBundlePlugin(final Bundle bundle, final String key, final PluginArtifact pluginArtifact)
40 {
41 this.bundle = checkNotNull(bundle);
42 this.pluginArtifact = checkNotNull(pluginArtifact);
43 this.bundleClassLoader = BundleClassLoaderAccessor.getClassLoader(bundle, new AlternativeDirectoryResourceLoader());
44 bundleStartStopListener = new SynchronousBundleListener()
45 {
46 public void bundleChanged(final BundleEvent bundleEvent)
47 {
48 if (bundleEvent.getBundle() == bundle)
49 {
50 if (bundleEvent.getType() == BundleEvent.STOPPING)
51 {
52 setPluginState(PluginState.DISABLED);
53 }
54 else if (bundleEvent.getType() == BundleEvent.STARTED)
55 {
56 setPluginState(PluginState.ENABLED);
57 }
58 }
59 }
60 };
61 PluginInformation pluginInformation = new PluginInformation();
62 pluginInformation.setDescription((String) bundle.getHeaders().get(Constants.BUNDLE_DESCRIPTION));
63 pluginInformation.setVersion((String) bundle.getHeaders().get(Constants.BUNDLE_VERSION));
64 pluginInformation.setVendorName((String) bundle.getHeaders().get(Constants.BUNDLE_VENDOR));
65 pluginInformation.setPermissions(ImmutableSet.of(PluginPermission.EXECUTE_JAVA));
66
67 dateLoaded = new Date();
68 setPluginsVersion(2);
69 setName((String) bundle.getHeaders().get(Constants.BUNDLE_NAME));
70 setKey(key);
71 setPluginInformation(pluginInformation);
72 setSystemPlugin(false);
73 }
74
75
76 @Override
77 public Date getDateLoaded()
78 {
79 return dateLoaded;
80 }
81
82 public boolean isUninstallable()
83 {
84 return true;
85 }
86
87 public boolean isDeleteable()
88 {
89 return true;
90 }
91
92 public boolean isDynamicallyLoaded()
93 {
94 return true;
95 }
96
97 public <T> Class<T> loadClass(final String clazz, final Class<?> callingClass) throws ClassNotFoundException
98 {
99 return BundleClassLoaderAccessor.loadClass(bundle, clazz);
100 }
101
102 public URL getResource(final String name)
103 {
104 return bundleClassLoader.getResource(name);
105 }
106
107 public InputStream getResourceAsStream(final String name)
108 {
109 return bundleClassLoader.getResourceAsStream(name);
110 }
111
112 @Override
113 protected void uninstallInternal()
114 {
115 try
116 {
117 if (bundle.getState() != Bundle.UNINSTALLED)
118 {
119 bundle.uninstall();
120 }
121 }
122 catch (final BundleException e)
123 {
124 throw new PluginException(e);
125 }
126 }
127
128 @Override
129 protected PluginState enableInternal()
130 {
131 getLog().debug("Enabling OSGi bundled plugin '{}'", getKey());
132 try
133 {
134 if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
135 {
136 getLog().debug("Plugin '{}' bundle is NOT a fragment, starting.", getKey());
137 bundle.start();
138 OsgiSystemBundleUtil.getSystemBundleContext(bundle).addBundleListener(bundleStartStopListener);
139 }
140 else
141 {
142 getLog().debug("Plugin '{}' bundle is a fragment, not doing anything.", getKey());
143 }
144 return PluginState.ENABLED;
145 }
146 catch (final BundleException e)
147 {
148 throw new PluginException(e);
149 }
150 }
151
152 @Override
153 protected void disableInternal()
154 {
155 try
156 {
157 if (bundle.getState() == Bundle.ACTIVE)
158 {
159 OsgiSystemBundleUtil.getSystemBundleContext(bundle).removeBundleListener(bundleStartStopListener);
160 bundle.stop();
161 }
162 }
163 catch (final BundleException e)
164 {
165 throw new PluginException(e);
166 }
167 }
168
169 public ClassLoader getClassLoader()
170 {
171 return bundleClassLoader;
172 }
173
174 public PluginArtifact getPluginArtifact()
175 {
176 return pluginArtifact;
177 }
178 }