1 package com.atlassian.plugin.main;
2
3 import com.atlassian.event.api.EventPublisher;
4 import com.atlassian.plugin.Application;
5 import com.atlassian.plugin.PluginAccessor;
6 import com.atlassian.plugin.PluginController;
7 import com.atlassian.plugin.PluginParseException;
8 import com.atlassian.plugin.PluginRegistry;
9 import com.atlassian.plugin.SplitStartupPluginSystemLifecycle;
10 import com.atlassian.plugin.event.PluginEventListener;
11 import com.atlassian.plugin.event.PluginEventManager;
12 import com.atlassian.plugin.event.events.PluginFrameworkShutdownEvent;
13 import com.atlassian.plugin.event.events.PluginFrameworkStartedEvent;
14 import com.atlassian.plugin.event.impl.DefaultPluginEventManager;
15 import com.atlassian.plugin.factories.LegacyDynamicPluginFactory;
16 import com.atlassian.plugin.factories.PluginFactory;
17 import com.atlassian.plugin.loaders.BundledPluginLoader;
18 import com.atlassian.plugin.loaders.ClassPathPluginLoader;
19 import com.atlassian.plugin.loaders.DirectoryPluginLoader;
20 import com.atlassian.plugin.loaders.PluginLoader;
21 import com.atlassian.plugin.manager.DefaultPluginManager;
22 import com.atlassian.plugin.manager.PluginRegistryImpl;
23 import com.atlassian.plugin.manager.ProductPluginAccessor;
24 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
25 import com.atlassian.plugin.osgi.container.felix.FelixOsgiContainerManager;
26 import com.atlassian.plugin.osgi.factory.OsgiBundleFactory;
27 import com.atlassian.plugin.osgi.factory.OsgiPluginFactory;
28 import com.atlassian.plugin.osgi.factory.RemotablePluginFactory;
29 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
30 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
31 import com.atlassian.plugin.repositories.FilePluginInstaller;
32 import com.google.common.collect.Sets;
33
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.Set;
40 import java.util.concurrent.atomic.AtomicReference;
41
42
43
44
45 public class AtlassianPlugins {
46
47 private OsgiContainerManager osgiContainerManager;
48 private DefaultPluginEventManager pluginEventManager;
49 private PluginAccessor pluginAccessor;
50 private PluginController pluginController;
51 private SplitStartupPluginSystemLifecycle pluginSystemLifecycle;
52 private HotDeployer hotDeployer;
53 private EventPublisher eventPublisher;
54
55
56
57
58 public static final String TEMP_DIRECTORY_SUFFIX = ".tmp";
59
60
61
62
63
64
65
66
67 public AtlassianPlugins(final PluginsConfiguration config) {
68 pluginEventManager = new DefaultPluginEventManager(config.getScopeManager());
69 eventPublisher = pluginEventManager.getEventPublisher();
70
71 final AtomicReference<PluginAccessor> pluginAccessorRef = new AtomicReference<>();
72 osgiContainerManager = new FelixOsgiContainerManager(
73 config.getFrameworkBundleDirectory(),
74 config.getOsgiPersistentCache(),
75 config.getPackageScannerConfiguration(),
76 new CriticalHostComponentProvider(config.getHostComponentProvider(), pluginEventManager, pluginAccessorRef),
77 pluginEventManager);
78
79 final Set<Application> applications = config.getApplication() != null ?
80 Sets.newHashSet(config.getApplication()) : Collections.emptySet();
81
82
83 final OsgiPluginFactory osgiPluginDeployer = new OsgiPluginFactory(
84 config.getPluginDescriptorFilename(),
85 applications,
86 config.getOsgiPersistentCache(),
87 osgiContainerManager,
88 pluginEventManager);
89
90 final OsgiBundleFactory osgiBundleDeployer = new OsgiBundleFactory(osgiContainerManager);
91
92 final RemotablePluginFactory remotablePluginFactory = new RemotablePluginFactory(
93 config.getPluginDescriptorFilename(),
94 applications,
95 osgiContainerManager,
96 pluginEventManager);
97
98 final List<PluginFactory> pluginDeployers = new LinkedList<>(Arrays.asList(osgiPluginDeployer, osgiBundleDeployer, remotablePluginFactory));
99 if (config.isUseLegacyDynamicPluginDeployer()) {
100 pluginDeployers.add(new LegacyDynamicPluginFactory(config.getPluginDescriptorFilename()));
101 }
102
103 final List<PluginLoader> pluginLoaders = new ArrayList<>();
104
105
106 pluginLoaders.add(new ClassPathPluginLoader());
107
108
109 if (config.getBundledPluginUrl() != null) {
110 pluginLoaders.add(new BundledPluginLoader(config.getBundledPluginUrl(), config.getBundledPluginCacheDirectory(), pluginDeployers, pluginEventManager));
111 }
112
113
114 pluginLoaders.add(new DirectoryPluginLoader(config.getPluginDirectory(), pluginDeployers, pluginEventManager));
115
116 PluginRegistry.ReadWrite pluginRegistry = new PluginRegistryImpl();
117 pluginAccessor = new ProductPluginAccessor(pluginRegistry,
118 config.getPluginStateStore(),
119 config.getModuleDescriptorFactory(),
120 pluginEventManager,
121 config.getScopeManager());
122
123 DefaultPluginManager defaultPluginManager = DefaultPluginManager.newBuilder()
124 .withPluginRegistry(pluginRegistry)
125 .withStore(config.getPluginStateStore())
126 .withPluginLoaders(pluginLoaders)
127 .withModuleDescriptorFactory(config.getModuleDescriptorFactory())
128 .withPluginEventManager(pluginEventManager)
129 .withPluginAccessor(pluginAccessor)
130 .build();
131
132 pluginController = defaultPluginManager;
133 pluginSystemLifecycle = defaultPluginManager;
134
135 pluginAccessorRef.set(pluginAccessor);
136
137 defaultPluginManager.setPluginInstaller(new FilePluginInstaller(config.getPluginDirectory()));
138
139 if (config.getHotDeployPollingPeriod() > 0) {
140 hotDeployer = new HotDeployer(pluginController, config.getHotDeployPollingPeriod());
141 }
142 }
143
144 public void afterPropertiesSet() {
145 pluginEventManager.register(this);
146 }
147
148 public void destroy() {
149 pluginEventManager.unregister(this);
150 }
151
152
153
154
155 public OsgiContainerManager getOsgiContainerManager() {
156 return osgiContainerManager;
157 }
158
159
160
161
162 public PluginEventManager getPluginEventManager() {
163 return pluginEventManager;
164 }
165
166
167
168
169 public EventPublisher getEventPublisher() {
170 return eventPublisher;
171 }
172
173
174
175
176 public PluginController getPluginController() {
177 return pluginController;
178 }
179
180
181
182
183 public PluginAccessor getPluginAccessor() {
184 return pluginAccessor;
185 }
186
187
188
189
190 public SplitStartupPluginSystemLifecycle getPluginSystemLifecycle() {
191 return pluginSystemLifecycle;
192 }
193
194
195 @PluginEventListener
196 public void onPluginFrameworkStartedEvent(final PluginFrameworkStartedEvent event) {
197 if (hotDeployer != null && !hotDeployer.isRunning()) {
198 hotDeployer.start();
199 }
200 }
201
202 @PluginEventListener
203 public void onPluginFrameworkShutdownEvent(final PluginFrameworkShutdownEvent event) {
204 if (hotDeployer != null && hotDeployer.isRunning()) {
205 hotDeployer.stop();
206 }
207 }
208
209 private static class CriticalHostComponentProvider implements HostComponentProvider {
210 private final HostComponentProvider delegate;
211 private final PluginEventManager pluginEventManager;
212 private final AtomicReference<PluginAccessor> pluginManagerRef;
213
214 CriticalHostComponentProvider(final HostComponentProvider delegate,
215 final PluginEventManager pluginEventManager,
216 final AtomicReference<PluginAccessor> pluginManagerRef) {
217 this.delegate = delegate;
218 this.pluginEventManager = pluginEventManager;
219 this.pluginManagerRef = pluginManagerRef;
220 }
221
222 public void provide(final ComponentRegistrar registrar) {
223 registrar.register(PluginEventManager.class).forInstance(pluginEventManager);
224 registrar.register(PluginAccessor.class).forInstance(pluginManagerRef.get());
225 delegate.provide(registrar);
226 }
227 }
228 }