View Javadoc

1   // ========================================================================
2   // Copyright (c) 2009 Intalio, Inc.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  package org.eclipse.jetty.osgi.boot.utils.internal;
14  
15  import java.lang.reflect.Field;
16  import java.lang.reflect.Method;
17  import java.net.URL;
18  import java.net.URLConnection;
19  
20  import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
21  import org.osgi.framework.Bundle;
22  
23  /**
24   * Default implementation of the BundleClassLoaderHelper. Uses introspection to
25   * support equinox-3.5 and felix-2.0.0
26   */
27  public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
28  {
29  
30      private static boolean identifiedOsgiImpl = false;
31      private static boolean isEquinox = false;
32      private static boolean isFelix = false;
33  
34      private static void init(Bundle bundle)
35      {
36          identifiedOsgiImpl = true;
37          try
38          {
39              isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null;
40          }
41          catch (Throwable t)
42          {
43              isEquinox = false;
44          }
45          if (!isEquinox)
46          {
47              try
48              {
49                  isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null;
50              }
51              catch (Throwable t2)
52              {
53                  isFelix = false;
54              }
55          }
56          // System.err.println("isEquinox=" + isEquinox);
57          // System.err.println("isFelix=" + isFelix);
58      }
59  
60      /**
61       * Assuming the bundle is started.
62       * 
63       * @param bundle
64       * @return classloader object
65       */
66      public ClassLoader getBundleClassLoader(Bundle bundle)
67      {
68          String bundleActivator = (String)bundle.getHeaders().get("Bundle-Activator");
69          if (bundleActivator == null)
70          {
71              bundleActivator = (String)bundle.getHeaders().get("Jetty-ClassInBundle");
72          }
73          if (bundleActivator != null)
74          {
75              try
76              {
77                  return bundle.loadClass(bundleActivator).getClassLoader();
78              }
79              catch (ClassNotFoundException e)
80              {
81                  // should not happen as we are called if the bundle is started
82                  // anyways.
83                  e.printStackTrace();
84              }
85          }
86          // resort to introspection
87          if (!identifiedOsgiImpl)
88          {
89              init(bundle);
90          }
91          if (isEquinox)
92          {
93              return internalGetEquinoxBundleClassLoader(bundle);
94          }
95          else if (isFelix)
96          {
97              return internalGetFelixBundleClassLoader(bundle);
98          }
99          return null;
100     }
101 
102     private static Method Equinox_BundleHost_getBundleLoader_method;
103     private static Method Equinox_BundleLoader_createClassLoader_method;
104 
105     private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle)
106     {
107         // assume equinox:
108         try
109         {
110             if (Equinox_BundleHost_getBundleLoader_method == null)
111             {
112                 Equinox_BundleHost_getBundleLoader_method = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost")
113                         .getDeclaredMethod("getBundleLoader",new Class[] {});
114                 Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
115             }
116             Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle,new Object[] {});
117             if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
118             {
119                 Equinox_BundleLoader_createClassLoader_method = bundleLoader.getClass().getClassLoader().loadClass(
120                         "org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader",new Class[] {});
121                 Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
122             }
123             return (ClassLoader)Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader,new Object[] {});
124         }
125         catch (Throwable t)
126         {
127             t.printStackTrace();
128         }
129         return null;
130     }
131 
132     private static Field Felix_BundleImpl_m_modules_field;
133     private static Field Felix_ModuleImpl_m_classLoader_field;
134 
135     private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle)
136     {
137         // assume felix:
138         try
139         {
140             // now get the current module from the bundle.
141             // and return the private field m_classLoader of ModuleImpl
142             if (Felix_BundleImpl_m_modules_field == null)
143             {
144                 Felix_BundleImpl_m_modules_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl").getDeclaredField(
145                         "m_modules");
146                 Felix_BundleImpl_m_modules_field.setAccessible(true);
147             }
148             Object[] moduleArray = (Object[])Felix_BundleImpl_m_modules_field.get(bundle);
149             Object currentModuleImpl = moduleArray[moduleArray.length - 1];
150             if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null)
151             {
152                 Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField(
153                         "m_classLoader");
154                 Felix_ModuleImpl_m_classLoader_field.setAccessible(true);
155             }
156             // first make sure that the classloader is ready:
157             // the m_classLoader field must be initialized by the
158             // ModuleImpl.getClassLoader() private method.
159             ClassLoader cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
160             if (cl == null)
161             {
162                 // looks like it was not ready:
163                 // the m_classLoader field must be initialized by the
164                 // ModuleImpl.getClassLoader() private method.
165                 // this call will do that.
166                 bundle.loadClass("java.lang.Object");
167                 cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
168                 // System.err.println("Got the bundle class loader of felix_: "
169                 // + cl);
170                 return cl;
171             }
172             else
173             {
174                 // System.err.println("Got the bundle class loader of felix: " +
175                 // cl);
176                 return cl;
177             }
178         }
179         catch (Throwable t)
180         {
181             t.printStackTrace();
182         }
183         return null;
184     }
185 
186 }