1 package com.atlassian.plugin.osgi.factory;
2
3 import java.io.InputStream;
4 import java.net.URL;
5 import java.util.HashSet;
6 import java.util.Set;
7
8 import com.atlassian.plugin.AutowireCapablePlugin;
9 import com.atlassian.plugin.IllegalPluginStateException;
10 import com.atlassian.plugin.module.ContainerAccessor;
11 import com.atlassian.plugin.osgi.container.OsgiContainerException;
12 import com.atlassian.plugin.osgi.spring.DefaultSpringContainerAccessor;
13 import com.atlassian.plugin.osgi.util.BundleClassLoaderAccessor;
14 import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
15 import com.atlassian.plugin.util.resource.AlternativeDirectoryResourceLoader;
16
17 import org.apache.commons.lang.Validate;
18 import org.osgi.framework.Bundle;
19 import org.osgi.framework.Constants;
20 import org.osgi.service.packageadmin.ExportedPackage;
21 import org.osgi.service.packageadmin.PackageAdmin;
22 import org.osgi.util.tracker.ServiceTracker;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26
27
28
29
30
31 class OsgiPluginInstalledHelper implements OsgiPluginHelper
32 {
33 private static final Logger log = LoggerFactory.getLogger(OsgiPluginInstalledHelper.class);
34
35 private final ClassLoader bundleClassLoader;
36 private final Bundle bundle;
37 private final PackageAdmin packageAdmin;
38
39 private volatile ContainerAccessor containerAccessor;
40 private volatile ServiceTracker[] serviceTrackers;
41
42
43
44
45
46 public OsgiPluginInstalledHelper(final Bundle bundle, final PackageAdmin packageAdmin)
47 {
48 Validate.notNull(bundle);
49 Validate.notNull(packageAdmin);
50 this.bundle = bundle;
51 bundleClassLoader = BundleClassLoaderAccessor.getClassLoader(bundle, new AlternativeDirectoryResourceLoader());
52 this.packageAdmin = packageAdmin;
53 }
54
55 public Bundle getBundle()
56 {
57 return bundle;
58 }
59
60 public <T> Class<T> loadClass(final String clazz, final Class<?> callingClass) throws ClassNotFoundException
61 {
62 return BundleClassLoaderAccessor.loadClass(getBundle(), clazz);
63 }
64
65 public URL getResource(final String name)
66 {
67 return bundleClassLoader.getResource(name);
68 }
69
70 public InputStream getResourceAsStream(final String name)
71 {
72 return bundleClassLoader.getResourceAsStream(name);
73 }
74
75 public ClassLoader getClassLoader()
76 {
77 return bundleClassLoader;
78 }
79
80 public Bundle install()
81 {
82 throw new IllegalPluginStateException("Plugin '" + bundle.getSymbolicName() + "' has already been installed");
83 }
84
85 public void onEnable(final ServiceTracker... serviceTrackers) throws OsgiContainerException
86 {
87 Validate.notNull(serviceTrackers);
88
89 for (final ServiceTracker svc : serviceTrackers)
90 {
91 svc.open();
92 }
93
94 this.serviceTrackers = serviceTrackers;
95 }
96
97 public void onDisable() throws OsgiContainerException
98 {
99 final ServiceTracker[] serviceTrackers = this.serviceTrackers;
100 if(serviceTrackers != null)
101 {
102 for (final ServiceTracker svc : serviceTrackers)
103 {
104 svc.close();
105 }
106 this.serviceTrackers = null;
107 }
108 setPluginContainer(null);
109 }
110
111 public void onUninstall() throws OsgiContainerException
112 {
113 }
114
115 public <T> T autowire(final Class<T> clazz, final AutowireCapablePlugin.AutowireStrategy autowireStrategy) throws IllegalPluginStateException
116 {
117 assertPluginContainerIsAvailable();
118 return containerAccessor.createBean(clazz);
119 }
120
121
122
123
124
125
126
127
128
129
130
131 public void autowire(final Object instance, final AutowireCapablePlugin.AutowireStrategy autowireStrategy) throws IllegalPluginStateException
132 {
133 assertPluginContainerIsAvailable();
134 containerAccessor.injectBean(instance);
135 }
136
137 public Set<String> getRequiredPlugins()
138 {
139
140 if (bundle.getState() == Bundle.INSTALLED)
141 {
142 log.debug("Bundle is in INSTALLED for {}", bundle.getSymbolicName());
143 packageAdmin.resolveBundles(new Bundle[]{bundle});
144 log.debug("Bundle state is now {}", bundle.getState());
145 }
146
147 final Set<String> keys = new HashSet<String>();
148 getRequiredPluginsFromExports(keys);
149
150
151
152 return keys;
153 }
154
155 private void getRequiredPluginsFromExports(Set<String> keys)
156 {
157
158 final Set<String> imports = new HashSet<String>(OsgiHeaderUtil.parseHeader((String) getBundle().getHeaders().get(Constants.IMPORT_PACKAGE)).keySet());
159
160
161 imports.addAll(OsgiHeaderUtil.parseHeader((String) getBundle().getHeaders().get(Constants.DYNAMICIMPORT_PACKAGE)).keySet());
162
163
164 for (final String imp : imports)
165 {
166
167 final ExportedPackage[] exports = packageAdmin.getExportedPackages(imp);
168 if (exports != null)
169 {
170
171 for (final ExportedPackage export : exports)
172 {
173
174 final Bundle[] importingBundles = export.getImportingBundles();
175 if (importingBundles != null)
176 {
177
178 for (final Bundle importingBundle : importingBundles)
179 {
180
181 if (getBundle() == importingBundle)
182 {
183 keys.add(OsgiHeaderUtil.getPluginKey(export.getExportingBundle()));
184 break;
185 }
186 }
187 }
188 }
189 }
190 }
191 }
192
193 public void setPluginContainer(final Object container)
194 {
195 if (container == null)
196 {
197 containerAccessor = null;
198 }
199 else if (container instanceof ContainerAccessor)
200 {
201 containerAccessor = (ContainerAccessor) container;
202 }
203 else
204 {
205 containerAccessor = new DefaultSpringContainerAccessor(container);
206 }
207 }
208
209 public ContainerAccessor getContainerAccessor()
210 {
211 return containerAccessor;
212 }
213
214
215
216
217 private void assertPluginContainerIsAvailable() throws IllegalPluginStateException
218 {
219 if (containerAccessor == null)
220 {
221 throw new IllegalStateException("Cannot autowire object because the plugin container is unavailable.");
222 }
223 }
224
225 }