View Javadoc

1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.PluginArtifact;
4   import com.atlassian.plugin.PluginArtifactBackedPlugin;
5   import com.atlassian.plugin.PluginException;
6   import com.atlassian.plugin.PluginInformation;
7   import com.atlassian.plugin.PluginPermission;
8   import com.atlassian.plugin.PluginState;
9   import com.atlassian.plugin.impl.AbstractPlugin;
10  import com.atlassian.plugin.osgi.util.BundleClassLoaderAccessor;
11  import com.atlassian.plugin.util.resource.AlternativeDirectoryResourceLoader;
12  import com.google.common.collect.ImmutableSet;
13  import org.osgi.framework.Bundle;
14  import org.osgi.framework.BundleEvent;
15  import org.osgi.framework.BundleException;
16  import org.osgi.framework.Constants;
17  import org.osgi.framework.SynchronousBundleListener;
18  
19  import java.io.InputStream;
20  import java.net.URL;
21  import java.util.Date;
22  
23  import static com.google.common.base.Preconditions.checkNotNull;
24  
25  /**
26   * Plugin that wraps an OSGi bundle that has no plugin descriptor.
27   */
28  public final class OsgiBundlePlugin extends AbstractPlugin implements PluginArtifactBackedPlugin
29  {
30  
31      private final Bundle bundle;
32      private final Date dateLoaded;
33      private final ClassLoader bundleClassLoader;
34      private final SynchronousBundleListener bundleStartStopListener;
35      private final PluginArtifact pluginArtifact;
36  
37      public OsgiBundlePlugin(final Bundle bundle, final String key, final PluginArtifact pluginArtifact)
38      {
39          this.bundle = checkNotNull(bundle);
40          this.pluginArtifact = checkNotNull(pluginArtifact);
41          this.bundleClassLoader = BundleClassLoaderAccessor.getClassLoader(bundle, new AlternativeDirectoryResourceLoader());
42          bundleStartStopListener = new SynchronousBundleListener()
43          {
44              public void bundleChanged(final BundleEvent bundleEvent)
45              {
46                  if (bundleEvent.getBundle() == bundle)
47                  {
48                      if (bundleEvent.getType() == BundleEvent.STOPPING)
49                      {
50                          setPluginState(PluginState.DISABLED);
51                      }
52                      else if (bundleEvent.getType() == BundleEvent.STARTED)
53                      {
54                          setPluginState(PluginState.ENABLED);
55                      }
56                  }
57              }
58          };
59          PluginInformation pluginInformation = new PluginInformation();
60          pluginInformation.setDescription((String) bundle.getHeaders().get(Constants.BUNDLE_DESCRIPTION));
61          pluginInformation.setVersion((String) bundle.getHeaders().get(Constants.BUNDLE_VERSION));
62          pluginInformation.setVendorName((String) bundle.getHeaders().get(Constants.BUNDLE_VENDOR));
63          pluginInformation.setPermissions(ImmutableSet.of(PluginPermission.EXECUTE_JAVA));
64          
65          dateLoaded = new Date();
66          setPluginsVersion(2);
67          setName((String) bundle.getHeaders().get(Constants.BUNDLE_NAME));
68          setKey(key);
69          setPluginInformation(pluginInformation);
70          setSystemPlugin(false);
71      }
72  
73  
74      @Override
75      public Date getDateLoaded()
76      {
77          return dateLoaded;
78      }
79  
80      @Override
81      public Date getDateInstalled()
82      {
83          long date = getPluginArtifact().toFile().lastModified();
84          if (date == 0)
85          {
86              date = getDateLoaded().getTime();
87          }
88          return new Date(date);
89      }
90  
91      public boolean isUninstallable()
92      {
93          return true;
94      }
95  
96      public boolean isDeleteable()
97      {
98          return true;
99      }
100 
101     public boolean isDynamicallyLoaded()
102     {
103         return true;
104     }
105 
106     public <T> Class<T> loadClass(final String clazz, final Class<?> callingClass) throws ClassNotFoundException
107     {
108         return BundleClassLoaderAccessor.loadClass(bundle, clazz);
109     }
110 
111     public URL getResource(final String name)
112     {
113         return bundleClassLoader.getResource(name);
114     }
115 
116     public InputStream getResourceAsStream(final String name)
117     {
118         return bundleClassLoader.getResourceAsStream(name);
119     }
120 
121     @Override
122     protected void uninstallInternal()
123     {
124         try
125         {
126             if (bundle.getState() != Bundle.UNINSTALLED)
127             {
128                 bundle.uninstall();
129             }
130         }
131         catch (final BundleException e)
132         {
133             throw new PluginException(e);
134         }
135     }
136 
137     @Override
138     protected PluginState enableInternal()
139     {
140         getLog().debug("Enabling OSGi bundled plugin '{}'", getKey());
141         try
142         {
143             if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
144             {
145                 getLog().debug("Plugin '{}' bundle is NOT a fragment, starting.", getKey());
146                 bundle.start();
147                 bundle.getBundleContext().addBundleListener(bundleStartStopListener);
148             }
149             else
150             {
151                 getLog().debug("Plugin '{}' bundle is a fragment, not doing anything.", getKey());
152             }
153             return PluginState.ENABLED;
154         }
155         catch (final BundleException e)
156         {
157             throw new PluginException(e);
158         }
159     }
160 
161     @Override
162     protected void disableInternal()
163     {
164         try
165         {
166             if (bundle.getState() == Bundle.ACTIVE)
167             {
168                 bundle.stop();
169             }
170         }
171         catch (final BundleException e)
172         {
173             throw new PluginException(e);
174         }
175     }
176 
177     public ClassLoader getClassLoader()
178     {
179         return bundleClassLoader;
180     }
181 
182     public PluginArtifact getPluginArtifact()
183     {
184         return pluginArtifact;
185     }
186 }