View Javadoc

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