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  import java.util.List;
20  
21  import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
22  import org.osgi.framework.Bundle;
23  
24  /**
25   * Default implementation of the BundleClassLoaderHelper. Uses introspection to
26   * support equinox-3.5 and felix-2.0.0
27   */
28  public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
29  {
30  
31      private static boolean identifiedOsgiImpl = false;
32      private static boolean isEquinox = false;
33      private static boolean isFelix = false;
34  
35      private static void init(Bundle bundle)
36      {
37          identifiedOsgiImpl = true;
38          try
39          {
40              isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null;
41          }
42          catch (Throwable t)
43          {
44              isEquinox = false;
45          }
46          if (!isEquinox)
47          {
48              try
49              {
50                  isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null;
51              }
52              catch (Throwable t2)
53              {
54                  isFelix = false;
55              }
56          }
57          // System.err.println("isEquinox=" + isEquinox);
58          // System.err.println("isFelix=" + isFelix);
59      }
60  
61      /**
62       * Assuming the bundle is started.
63       * 
64       * @param bundle
65       * @return classloader object
66       */
67      public ClassLoader getBundleClassLoader(Bundle bundle)
68      {
69          String bundleActivator = (String)bundle.getHeaders().get("Bundle-Activator");
70          if (bundleActivator == null)
71          {
72              bundleActivator = (String)bundle.getHeaders().get("Jetty-ClassInBundle");
73          }
74          if (bundleActivator != null)
75          {
76              try
77              {
78                  return bundle.loadClass(bundleActivator).getClassLoader();
79              }
80              catch (ClassNotFoundException e)
81              {
82                  // should not happen as we are called if the bundle is started
83                  // anyways.
84                  e.printStackTrace();
85              }
86          }
87          // resort to introspection
88          if (!identifiedOsgiImpl)
89          {
90              init(bundle);
91          }
92          if (isEquinox)
93          {
94              return internalGetEquinoxBundleClassLoader(bundle);
95          }
96          else if (isFelix)
97          {
98              return internalGetFelixBundleClassLoader(bundle);
99          }
100         return null;
101     }
102 
103     private static Method Equinox_BundleHost_getBundleLoader_method;
104     private static Method Equinox_BundleLoader_createClassLoader_method;
105 
106     private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle)
107     {
108         // assume equinox:
109         try
110         {
111             if (Equinox_BundleHost_getBundleLoader_method == null)
112             {
113                 Equinox_BundleHost_getBundleLoader_method = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost")
114                         .getDeclaredMethod("getBundleLoader",new Class[] {});
115                 Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
116             }
117             Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle,new Object[] {});
118             if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
119             {
120                 Equinox_BundleLoader_createClassLoader_method = bundleLoader.getClass().getClassLoader().loadClass(
121                         "org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader",new Class[] {});
122                 Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
123             }
124             return (ClassLoader)Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader,new Object[] {});
125         }
126         catch (Throwable t)
127         {
128             t.printStackTrace();
129         }
130         return null;
131     }
132 
133     private static Field Felix_BundleImpl_m_modules_field;
134     private static Field Felix_ModuleImpl_m_classLoader_field;
135 
136     private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle)
137     {
138         // assume felix:
139         try
140         {
141             // now get the current module from the bundle.
142             // and return the private field m_classLoader of ModuleImpl
143             if (Felix_BundleImpl_m_modules_field == null)
144             {
145                 Felix_BundleImpl_m_modules_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl").getDeclaredField(
146                         "m_modules");
147                 Felix_BundleImpl_m_modules_field.setAccessible(true);
148             }
149 
150             // Figure out which version of the modules is exported
151             Object currentModuleImpl;
152             try
153             {
154                 Object[] moduleArray = (Object[])Felix_BundleImpl_m_modules_field.get(bundle);
155                 currentModuleImpl = moduleArray[moduleArray.length - 1];
156             }
157             catch (Throwable t2)
158             {
159                 @SuppressWarnings("unchecked")
160                 List<Object> moduleArray = (List<Object>)Felix_BundleImpl_m_modules_field.get(bundle);
161                 currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
162             }
163             
164             if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null)
165             {
166                 Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField(
167                         "m_classLoader");
168                 Felix_ModuleImpl_m_classLoader_field.setAccessible(true);
169             }
170             // first make sure that the classloader is ready:
171             // the m_classLoader field must be initialized by the
172             // ModuleImpl.getClassLoader() private method.
173             ClassLoader cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
174             if (cl == null)
175             {
176                 // looks like it was not ready:
177                 // the m_classLoader field must be initialized by the
178                 // ModuleImpl.getClassLoader() private method.
179                 // this call will do that.
180                 bundle.loadClass("java.lang.Object");
181                 cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
182                 // System.err.println("Got the bundle class loader of felix_: "
183                 // + cl);
184                 return cl;
185             }
186             else
187             {
188                 // System.err.println("Got the bundle class loader of felix: " +
189                 // cl);
190                 return cl;
191             }
192         }
193         catch (Throwable t)
194         {
195             t.printStackTrace();
196         }
197         return null;
198     }
199 
200 }