1 package com.atlassian.plugin.osgi.factory;
2
3 import com.atlassian.plugin.IllegalPluginStateException;
4 import com.atlassian.plugin.PluginDependencies;
5 import com.atlassian.plugin.module.ContainerAccessor;
6 import com.atlassian.plugin.osgi.container.OsgiContainerException;
7 import com.atlassian.plugin.osgi.spring.DefaultSpringContainerAccessor;
8 import com.atlassian.plugin.osgi.util.BundleClassLoaderAccessor;
9 import com.atlassian.plugin.osgi.util.OsgiPluginUtil;
10 import com.atlassian.plugin.util.resource.AlternativeDirectoryResourceLoader;
11 import org.osgi.framework.Bundle;
12 import org.osgi.service.packageadmin.PackageAdmin;
13 import org.osgi.util.tracker.ServiceTracker;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import javax.annotation.Nonnull;
18 import java.io.InputStream;
19 import java.net.URL;
20
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static java.util.Optional.ofNullable;
23
24
25
26
27
28
29 final class OsgiPluginInstalledHelper implements OsgiPluginHelper {
30 private static final Logger logger = LoggerFactory.getLogger(OsgiPluginInstalledHelper.class);
31 private final ClassLoader bundleClassLoader;
32 private final Bundle bundle;
33 private final PackageAdmin packageAdmin;
34 private volatile ContainerAccessor containerAccessor;
35 private volatile ServiceTracker[] serviceTrackers;
36
37
38
39
40
41 public OsgiPluginInstalledHelper(final Bundle bundle, final PackageAdmin packageAdmin) {
42 this.bundle = checkNotNull(bundle);
43 this.packageAdmin = checkNotNull(packageAdmin);
44 bundleClassLoader = BundleClassLoaderAccessor.getClassLoader(bundle, new AlternativeDirectoryResourceLoader());
45 }
46
47 public Bundle getBundle() {
48 return bundle;
49 }
50
51 public <T> Class<T> loadClass(final String clazz, final Class<?> callingClass) throws ClassNotFoundException {
52 return BundleClassLoaderAccessor.loadClass(getBundle(), clazz);
53 }
54
55 public URL getResource(final String name) {
56 return bundleClassLoader.getResource(name);
57 }
58
59 public InputStream getResourceAsStream(final String name) {
60 return bundleClassLoader.getResourceAsStream(name);
61 }
62
63 public ClassLoader getClassLoader() {
64 return bundleClassLoader;
65 }
66
67 public Bundle install() {
68 logger.debug("Not installing OSGi plugin '{}' since it's already installed.", bundle.getSymbolicName());
69 throw new IllegalPluginStateException("Plugin '" + bundle.getSymbolicName() + "' has already been installed");
70 }
71
72 public void onEnable(final ServiceTracker... serviceTrackers) throws OsgiContainerException {
73 for (final ServiceTracker svc : checkNotNull(serviceTrackers)) {
74 svc.open();
75 }
76
77 this.serviceTrackers = serviceTrackers;
78 }
79
80 public void onDisable() throws OsgiContainerException {
81 final ServiceTracker[] serviceTrackers = this.serviceTrackers;
82 if (serviceTrackers != null) {
83 for (final ServiceTracker svc : serviceTrackers) {
84 svc.close();
85 }
86 this.serviceTrackers = null;
87 }
88 setPluginContainer(null);
89 }
90
91 public void onUninstall() throws OsgiContainerException {
92 }
93
94 @Nonnull
95 @Override
96 public PluginDependencies getDependencies() {
97 if (availableForTraversal()) {
98 return OsgiPluginUtil.getDependencies(bundle);
99 } else {
100 return new PluginDependencies(null, null, null);
101 }
102 }
103
104 @Deprecated
105
106
107
108
109
110
111 private boolean availableForTraversal() {
112
113 if (bundle.getState() == Bundle.INSTALLED) {
114 logger.debug("Bundle is in INSTALLED for {}", bundle.getSymbolicName());
115 if (!packageAdmin.resolveBundles(new Bundle[]{bundle})) {
116
117 logger.error("Cannot determine required plugins, cannot resolve bundle '{}'", bundle.getSymbolicName());
118 return false;
119 }
120 logger.debug("Bundle state is now {}", bundle.getState());
121 }
122 return true;
123 }
124
125 public void setPluginContainer(final Object container) {
126 if (container == null) {
127 containerAccessor = null;
128 } else if (container instanceof ContainerAccessor) {
129 containerAccessor = (ContainerAccessor) container;
130 } else {
131 containerAccessor = new DefaultSpringContainerAccessor(container);
132 }
133 }
134
135 public ContainerAccessor getContainerAccessor() {
136 return containerAccessor;
137 }
138
139
140
141
142 public ContainerAccessor getRequiredContainerAccessor() throws IllegalPluginStateException {
143 if (containerAccessor == null) {
144 throw new IllegalStateException("Cannot create object because the plugin container is unavailable for bundle '"
145 + bundle.getSymbolicName() + "'");
146 }
147 return containerAccessor;
148 }
149
150 public boolean isRemotePlugin() {
151 return ofNullable(getBundle().getHeaders())
152 .map(headers -> headers.get(OsgiPlugin.REMOTE_PLUGIN_KEY) != null)
153 .orElse(false);
154 }
155 }