View Javadoc

1   package com.atlassian.plugin.main;
2   
3   import com.atlassian.plugin.Application;
4   import com.atlassian.plugin.PluginAccessor;
5   import com.atlassian.plugin.PluginController;
6   import com.atlassian.plugin.PluginParseException;
7   import com.atlassian.plugin.event.PluginEventManager;
8   import com.atlassian.plugin.event.impl.DefaultPluginEventManager;
9   import com.atlassian.plugin.factories.LegacyDynamicPluginFactory;
10  import com.atlassian.plugin.factories.PluginFactory;
11  import com.atlassian.plugin.loaders.BundledPluginLoader;
12  import com.atlassian.plugin.loaders.ClassPathPluginLoader;
13  import com.atlassian.plugin.loaders.DirectoryPluginLoader;
14  import com.atlassian.plugin.loaders.PluginLoader;
15  import com.atlassian.plugin.manager.DefaultPluginManager;
16  import com.atlassian.plugin.osgi.container.OsgiContainerManager;
17  import com.atlassian.plugin.osgi.container.felix.FelixOsgiContainerManager;
18  import com.atlassian.plugin.osgi.factory.OsgiBundleFactory;
19  import com.atlassian.plugin.osgi.factory.OsgiPluginFactory;
20  import com.atlassian.plugin.osgi.factory.RemotablePluginFactory;
21  import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
22  import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
23  import com.atlassian.plugin.repositories.FilePluginInstaller;
24  import com.google.common.collect.ImmutableSet;
25  import com.google.common.collect.Sets;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Set;
34  import java.util.concurrent.atomic.AtomicReference;
35  
36  /**
37   * Facade interface to the Atlassian Plugins framework.  See the package Javadocs for usage information.
38   */
39  public class AtlassianPlugins
40  {
41      private OsgiContainerManager osgiContainerManager;
42      private PluginEventManager pluginEventManager;
43      private DefaultPluginManager pluginManager;
44      private HotDeployer hotDeployer;
45  
46      private static final Logger log = LoggerFactory.getLogger(AtlassianPlugins.class);
47  
48      /**
49       * Suffix for temporary directories which will be removed on shutdown
50       */
51      public static final String TEMP_DIRECTORY_SUFFIX = ".tmp";
52  
53      /**
54       * Constructs an instance of the plugin framework with the specified config.  No additional validation is performed
55       * on the configuration, so it is recommended you use the {@link PluginsConfigurationBuilder} class to create
56       * a configuration instance.
57       * @param config The plugins configuration to use
58       */
59      public AtlassianPlugins(PluginsConfiguration config)
60      {
61          pluginEventManager = new DefaultPluginEventManager();
62  
63          AtomicReference<PluginAccessor> pluginManagerRef = new AtomicReference<PluginAccessor>();
64          osgiContainerManager = new FelixOsgiContainerManager(
65                  config.getOsgiPersistentCache(),
66                  config.getPackageScannerConfiguration(),
67                  new CriticalHostComponentProvider(config.getHostComponentProvider(), pluginEventManager, pluginManagerRef),
68                  pluginEventManager);
69  
70          final Set<Application> applications = config.getApplication() != null ?
71                  Sets.newHashSet(config.getApplication()) : ImmutableSet.<Application>of();
72  
73          // plugin factories/deployers
74          final OsgiPluginFactory osgiPluginDeployer = new OsgiPluginFactory(
75                  config.getPluginDescriptorFilename(),
76                  applications,
77                  config.getOsgiPersistentCache(),
78                  osgiContainerManager,
79                  pluginEventManager);
80  
81          final OsgiBundleFactory osgiBundleDeployer = new OsgiBundleFactory(osgiContainerManager, pluginEventManager);
82  
83          final RemotablePluginFactory remotablePluginFactory = new RemotablePluginFactory(
84                  config.getPluginDescriptorFilename(),
85                  applications,
86                  osgiContainerManager,
87                  pluginEventManager);
88  
89          final List<PluginFactory> pluginDeployers = new LinkedList<PluginFactory>(Arrays.asList(osgiPluginDeployer, osgiBundleDeployer, remotablePluginFactory));
90          if (config.isUseLegacyDynamicPluginDeployer())
91          {
92              pluginDeployers.add(new LegacyDynamicPluginFactory(config.getPluginDescriptorFilename()));
93          }
94  
95          final List<PluginLoader> pluginLoaders = new ArrayList<PluginLoader>();
96  
97          // classpath plugins
98          pluginLoaders.add(new ClassPathPluginLoader());
99  
100         // bundled plugins
101         if (config.getBundledPluginUrl() != null)
102         {
103             pluginLoaders.add(new BundledPluginLoader(config.getBundledPluginUrl(), config.getBundledPluginCacheDirectory(), pluginDeployers, pluginEventManager));
104         }
105 
106         // osgi/v2 and v3 plugins
107         pluginLoaders.add(new DirectoryPluginLoader(config.getPluginDirectory(), pluginDeployers, pluginEventManager));
108 
109         pluginManager = new DefaultPluginManager(
110                 config.getPluginStateStore(),
111                 pluginLoaders,
112                 config.getModuleDescriptorFactory(),
113                 pluginEventManager);
114         pluginManagerRef.set(pluginManager);
115 
116         pluginManager.setPluginInstaller(new FilePluginInstaller(config.getPluginDirectory()));
117 
118         if (config.getHotDeployPollingPeriod() > 0)
119         {
120             hotDeployer = new HotDeployer(pluginManager, config.getHotDeployPollingPeriod());
121         }
122     }
123 
124     /**
125      * Starts the plugins framework.  Will return once the plugins have all been loaded and started.  Should only be
126      * called once.
127      * @throws PluginParseException If there was any problems parsing any of the plugins
128      */
129     public void start() throws PluginParseException
130     {
131         pluginManager.init();
132         if (hotDeployer != null && !hotDeployer.isRunning())
133         {
134             hotDeployer.start();
135         }
136     }
137 
138     /**
139      * Stops the framework.
140      */
141     public void stop()
142     {
143         if (hotDeployer != null && hotDeployer.isRunning())
144         {
145             hotDeployer.stop();
146         }
147         pluginManager.shutdown();
148     }
149 
150     /**
151      * @return the underlying OSGi container manager
152      */
153     public OsgiContainerManager getOsgiContainerManager()
154     {
155         return osgiContainerManager;
156     }
157 
158     /**
159      * @return the plugin event manager
160      */
161     public PluginEventManager getPluginEventManager()
162     {
163         return pluginEventManager;
164     }
165 
166     /**
167      * @return the plugin controller for manipulating plugins
168      */
169     public PluginController getPluginController()
170     {
171         return pluginManager;
172     }
173 
174     /**
175      * @return the plugin accessor for accessing plugins
176      */
177     public PluginAccessor getPluginAccessor()
178     {
179         return pluginManager;
180     }
181 
182     private static class CriticalHostComponentProvider implements HostComponentProvider
183     {
184         private final HostComponentProvider delegate;
185         private final PluginEventManager pluginEventManager;
186         private final AtomicReference<PluginAccessor> pluginManagerRef;
187 
188         public CriticalHostComponentProvider(HostComponentProvider delegate, PluginEventManager pluginEventManager, AtomicReference<PluginAccessor> pluginManagerRef)
189         {
190             this.delegate = delegate;
191             this.pluginEventManager = pluginEventManager;
192             this.pluginManagerRef = pluginManagerRef;
193         }
194 
195         public void provide(ComponentRegistrar registrar)
196         {
197             registrar.register(PluginEventManager.class).forInstance(pluginEventManager);
198             registrar.register(PluginAccessor.class).forInstance(pluginManagerRef.get());
199             delegate.provide(registrar);
200         }
201     }
202 }