View Javadoc

1   package com.atlassian.plugin.osgi.util;
2   
3   import com.atlassian.plugin.util.resource.AlternativeResourceLoader;
4   import com.atlassian.plugin.util.resource.NoOpAlternativeResourceLoader;
5   
6   import org.apache.commons.collections.iterators.IteratorEnumeration;
7   import org.apache.commons.lang.Validate;
8   import org.osgi.framework.Bundle;
9   
10  import java.io.IOException;
11  import java.net.URL;
12  import java.util.Arrays;
13  import java.util.Enumeration;
14  import java.util.Collections;
15  
16  /**
17   * Utility methods for accessing a bundle as if it was a classloader.
18   *
19   * @since 2.3.0
20   */
21  public class BundleClassLoaderAccessor
22  {
23      /**
24       * Creates a classloader that delegates to the bundle
25       * @param bundle The bundle to delegate to
26       * @param alternativeResourceLoader An alternative resource loader to bypass bundle, can be null
27       * @return A new classloader instance
28       */
29      public static ClassLoader getClassLoader(final Bundle bundle, final AlternativeResourceLoader alternativeResourceLoader)
30      {
31          return new BundleClassLoader(bundle, alternativeResourceLoader);
32      }
33  
34      /**
35       * Loads a class from the bundle
36       * @param bundle The bundle
37       * @param name The name of the class to load
38       * @param <T> The type of the class
39       * @return The class instance
40       * @throws ClassNotFoundException If the class cannot be found in the bundle
41       */
42      public static <T> Class<T> loadClass(final Bundle bundle, final String name) throws ClassNotFoundException
43      {
44          Validate.notNull(bundle, "The bundle is required");
45          @SuppressWarnings ({ "unchecked", "UnnecessaryLocalVariable" })
46          final Class<T> loadedClass = (Class<T>) bundle.loadClass(name);
47          return loadedClass;
48      }
49  
50      ///CLOVER:OFF
51      /**
52       * Fake classloader that delegates to a bundle
53       */
54      private static class BundleClassLoader extends ClassLoader
55      {
56          private final Bundle bundle;
57          private final AlternativeResourceLoader altResourceLoader;
58  
59          public BundleClassLoader(final Bundle bundle, AlternativeResourceLoader altResourceLoader)
60          {
61              super(null);
62              Validate.notNull(bundle, "The bundle must not be null");
63              if (altResourceLoader == null)
64              {
65                  altResourceLoader = new NoOpAlternativeResourceLoader();
66              }
67              this.altResourceLoader = altResourceLoader;
68              this.bundle = bundle;
69  
70          }
71  
72          @Override
73          public Class<?> findClass(final String name) throws ClassNotFoundException
74          {
75              return bundle.loadClass(name);
76          }
77  
78          @SuppressWarnings("unchecked")
79          @Override
80          public Enumeration<URL> findResources(final String name) throws IOException
81          {
82              Enumeration<URL> e = bundle.getResources(name);
83  
84              if (e == null)
85              {
86                  e = new IteratorEnumeration(Collections.emptyList().iterator());
87              }
88              else
89              {
90                  // For some reason, getResources() sometimes returns nothing, yet getResource() will return one.  This code
91                  // handles that strange case
92                  if (!e.hasMoreElements())
93                  {
94                      final URL resource = findResource(name);
95                      if (resource != null)
96                      {
97                          e = new IteratorEnumeration(Arrays.asList(resource).iterator());
98                      }
99                  }
100             }
101             return e;
102         }
103 
104         @Override
105         public URL findResource(final String name)
106         {
107             URL url = altResourceLoader.getResource(name);
108             if (url == null)
109             {
110                 url = bundle.getResource(name);
111             }
112             return url;
113         }
114     }
115 
116 }