431892 DefaultFileLocatorHelper.getBundleInstallLocation fails for equinox 3.10
This commit is contained in:
parent
64e11bc8e8
commit
90f387bc34
|
@ -37,37 +37,81 @@ import org.osgi.framework.Bundle;
|
|||
public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(BundleClassLoaderHelper.class);
|
||||
private static enum OSGiContainerType {EquinoxOld, EquinoxLuna, FelixOld, Felix403};
|
||||
private static OSGiContainerType osgiContainer;
|
||||
private static Class Equinox_BundleHost_Class;
|
||||
private static Class Equinox_EquinoxBundle_Class;
|
||||
private static Class Felix_BundleImpl_Class;
|
||||
private static Class Felix_BundleWiring_Class;
|
||||
//old equinox
|
||||
private static Method Equinox_BundleHost_getBundleLoader_method;
|
||||
private static Method Equinox_BundleLoader_createClassLoader_method;
|
||||
//new equinox
|
||||
private static Method Equinox_EquinoxBundle_getModuleClassLoader_Method;
|
||||
|
||||
private static boolean identifiedOsgiImpl = false;
|
||||
//new felix
|
||||
private static Method Felix_BundleImpl_Adapt_Method;
|
||||
//old felix
|
||||
private static Field Felix_BundleImpl_m_Modules_Field;
|
||||
private static Field Felix_ModuleImpl_m_ClassLoader_Field;
|
||||
private static Method Felix_BundleWiring_getClassLoader_Method;
|
||||
|
||||
private static boolean isEquinox = false;
|
||||
|
||||
private static boolean isFelix = false;
|
||||
|
||||
private static void init(Bundle bundle)
|
||||
private static void checkContainerType (Bundle bundle)
|
||||
{
|
||||
identifiedOsgiImpl = true;
|
||||
if (osgiContainer != null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null;
|
||||
Equinox_BundleHost_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost");
|
||||
osgiContainer = OSGiContainerType.EquinoxOld;
|
||||
return;
|
||||
}
|
||||
catch (Throwable t)
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
isEquinox = false;
|
||||
LOG.ignore(e);
|
||||
}
|
||||
if (!isEquinox)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null;
|
||||
Equinox_EquinoxBundle_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.framework.EquinoxBundle");
|
||||
osgiContainer = OSGiContainerType.EquinoxLuna;
|
||||
return;
|
||||
}
|
||||
catch (Throwable t2)
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
isFelix = false;
|
||||
LOG.ignore(e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//old felix or new felix?
|
||||
Felix_BundleImpl_Class = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
|
||||
try
|
||||
{
|
||||
Felix_BundleImpl_Adapt_Method = Felix_BundleImpl_Class.getDeclaredMethod("adapt", new Class[] {Class.class});
|
||||
osgiContainer = OSGiContainerType.Felix403;
|
||||
return;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
osgiContainer = OSGiContainerType.FelixOld;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
LOG.warn("Unknown OSGi container type");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assuming the bundle is started.
|
||||
*
|
||||
|
@ -93,37 +137,62 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
// resort to introspection
|
||||
if (!identifiedOsgiImpl)
|
||||
{
|
||||
init(bundle);
|
||||
}
|
||||
if (isEquinox)
|
||||
{
|
||||
return internalGetEquinoxBundleClassLoader(bundle);
|
||||
}
|
||||
else if (isFelix)
|
||||
{
|
||||
return internalGetFelixBundleClassLoader(bundle);
|
||||
return getBundleClassLoaderForContainer(bundle);
|
||||
}
|
||||
|
||||
LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
|
||||
/**
|
||||
* @param bundle
|
||||
* @return
|
||||
*/
|
||||
private ClassLoader getBundleClassLoaderForContainer (Bundle bundle)
|
||||
{
|
||||
checkContainerType (bundle);
|
||||
if (osgiContainer == null)
|
||||
{
|
||||
LOG.warn("No classloader for unknown OSGi container type");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method Equinox_BundleHost_getBundleLoader_method;
|
||||
switch (osgiContainer)
|
||||
{
|
||||
case EquinoxOld:
|
||||
case EquinoxLuna:
|
||||
{
|
||||
return internalGetEquinoxBundleClassLoader(bundle);
|
||||
}
|
||||
|
||||
private static Method Equinox_BundleLoader_createClassLoader_method;
|
||||
case FelixOld:
|
||||
case Felix403:
|
||||
{
|
||||
return internalGetFelixBundleClassLoader(bundle);
|
||||
}
|
||||
default:
|
||||
{
|
||||
LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param bundle
|
||||
* @return
|
||||
*/
|
||||
private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle)
|
||||
{
|
||||
// assume equinox:
|
||||
if (osgiContainer == OSGiContainerType.EquinoxOld)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Equinox_BundleHost_getBundleLoader_method == null)
|
||||
{
|
||||
Equinox_BundleHost_getBundleLoader_method =
|
||||
bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost").getDeclaredMethod("getBundleLoader", new Class[] {});
|
||||
Equinox_BundleHost_Class.getDeclaredMethod("getBundleLoader", new Class[] {});
|
||||
Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
|
||||
}
|
||||
Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle, new Object[] {});
|
||||
|
@ -135,38 +204,68 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
}
|
||||
return (ClassLoader) Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader, new Object[] {});
|
||||
}
|
||||
catch (ClassNotFoundException t)
|
||||
{
|
||||
LOG.warn(t);
|
||||
return null;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.warn(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (osgiContainer == OSGiContainerType.EquinoxLuna)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Equinox_EquinoxBundle_getModuleClassLoader_Method == null)
|
||||
Equinox_EquinoxBundle_getModuleClassLoader_Method = Equinox_EquinoxBundle_Class.getDeclaredMethod("getModuleClassLoader", new Class[] {Boolean.TYPE});
|
||||
|
||||
Equinox_EquinoxBundle_getModuleClassLoader_Method.setAccessible(true);
|
||||
return (ClassLoader)Equinox_EquinoxBundle_getModuleClassLoader_Method.invoke(bundle, new Object[] {Boolean.FALSE});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.warn("No classloader for equinox platform for bundle "+bundle.getSymbolicName());
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Field Felix_BundleImpl_m_modules_field;
|
||||
|
||||
private static Field Felix_ModuleImpl_m_classLoader_field;
|
||||
|
||||
private static Method Felix_adapt_method;
|
||||
|
||||
private static Method Felix_bundle_wiring_getClassLoader_method;
|
||||
|
||||
private static Class Felix_bundleWiringClazz;
|
||||
|
||||
private static Boolean isFelix403 = null;
|
||||
|
||||
/**
|
||||
* @param bundle
|
||||
* @return
|
||||
*/
|
||||
private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle)
|
||||
{
|
||||
//firstly, try to find classes matching a newer version of felix
|
||||
initFelix403(bundle);
|
||||
|
||||
if (isFelix403.booleanValue())
|
||||
if (osgiContainer == OSGiContainerType.Felix403)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object wiring = Felix_adapt_method.invoke(bundle, new Object[] {Felix_bundleWiringClazz});
|
||||
ClassLoader cl = (ClassLoader)Felix_bundle_wiring_getClassLoader_method.invoke(wiring);
|
||||
return cl;
|
||||
if (Felix_BundleWiring_Class == null)
|
||||
Felix_BundleWiring_Class = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
|
||||
|
||||
|
||||
Felix_BundleImpl_Adapt_Method.setAccessible(true);
|
||||
|
||||
if (Felix_BundleWiring_getClassLoader_Method == null)
|
||||
{
|
||||
Felix_BundleWiring_getClassLoader_Method = Felix_BundleWiring_Class.getDeclaredMethod("getClassLoader");
|
||||
Felix_BundleWiring_getClassLoader_Method.setAccessible(true);
|
||||
}
|
||||
|
||||
|
||||
Object wiring = Felix_BundleImpl_Adapt_Method.invoke(bundle, new Object[] {Felix_BundleWiring_Class});
|
||||
return (ClassLoader)Felix_BundleWiring_getClassLoader_Method.invoke(wiring);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -176,37 +275,29 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
}
|
||||
|
||||
|
||||
// Fallback to trying earlier versions of felix.
|
||||
if (Felix_BundleImpl_m_modules_field == null)
|
||||
if (osgiContainer == OSGiContainerType.FelixOld)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
|
||||
Felix_BundleImpl_m_modules_field = bundleImplClazz.getDeclaredField("m_modules");
|
||||
Felix_BundleImpl_m_modules_field.setAccessible(true);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
if (Felix_BundleImpl_m_Modules_Field == null)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (NoSuchFieldException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
Felix_BundleImpl_m_Modules_Field = Felix_BundleImpl_Class.getDeclaredField("m_modules");
|
||||
Felix_BundleImpl_m_Modules_Field.setAccessible(true);
|
||||
}
|
||||
|
||||
// Figure out which version of the modules is exported
|
||||
Object currentModuleImpl;
|
||||
|
||||
try
|
||||
{
|
||||
Object[] moduleArray = (Object[]) Felix_BundleImpl_m_modules_field.get(bundle);
|
||||
Object[] moduleArray = (Object[]) Felix_BundleImpl_m_Modules_Field.get(bundle);
|
||||
currentModuleImpl = moduleArray[moduleArray.length - 1];
|
||||
}
|
||||
catch (Throwable t2)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_modules_field.get(bundle);
|
||||
List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_Modules_Field.get(bundle);
|
||||
currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -216,31 +307,27 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
}
|
||||
}
|
||||
|
||||
if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null)
|
||||
if (Felix_ModuleImpl_m_ClassLoader_Field == null && currentModuleImpl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
|
||||
Felix_ModuleImpl_m_classLoader_field.setAccessible(true);
|
||||
Felix_ModuleImpl_m_ClassLoader_Field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
|
||||
Felix_ModuleImpl_m_ClassLoader_Field.setAccessible(true);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
catch (NoSuchFieldException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// first make sure that the classloader is ready:
|
||||
// the m_classLoader field must be initialized by the
|
||||
// ModuleImpl.getClassLoader() private method.
|
||||
ClassLoader cl = null;
|
||||
try
|
||||
{
|
||||
cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
|
||||
cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
|
||||
if (cl != null)
|
||||
return cl;
|
||||
}
|
||||
|
@ -257,7 +344,7 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
try
|
||||
{
|
||||
bundle.loadClass("java.lang.Object");
|
||||
cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
|
||||
cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
|
||||
return cl;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -266,33 +353,14 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
|
|||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void initFelix403 (Bundle bundle)
|
||||
{
|
||||
//see if the version of Felix is a new one
|
||||
if (isFelix403 == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
|
||||
Felix_bundleWiringClazz = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
|
||||
Felix_adapt_method = bundleImplClazz.getDeclaredMethod("adapt", new Class[] {Class.class});
|
||||
Felix_adapt_method.setAccessible(true);
|
||||
Felix_bundle_wiring_getClassLoader_method = Felix_bundleWiringClazz.getDeclaredMethod("getClassLoader");
|
||||
Felix_bundle_wiring_getClassLoader_method.setAccessible(true);
|
||||
isFelix403 = Boolean.TRUE;
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
LOG.warn("Felix 4.x classes not found in environment");
|
||||
isFelix403 = Boolean.FALSE;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
LOG.warn("Felix 4.x classes not found in environment");
|
||||
isFelix403 = Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
LOG.warn("No classloader for felix platform for bundle "+bundle.getSymbolicName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,24 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
|
||||
private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile
|
||||
|
||||
private static final String[] FILE_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry","org.eclipse.osgi.storage.bundlefile.FileBundleEntry"};
|
||||
private static final String[] ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry","org.eclipse.osgi.storage.bundlefile.ZipBundleEntry"};
|
||||
private static final String[] DIR_ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry","org.eclipse.osgi.storage.bundlefile.DirZipBundleEntry"};
|
||||
private static final String[] BUNDLE_URL_CONNECTION_CLASSES = {"org.eclipse.osgi.framework.internal.core.BundleURLConnection", "org.eclipse.osgi.storage.url.BundleURLConnection"};
|
||||
|
||||
|
||||
public static boolean match (String name, String... names)
|
||||
{
|
||||
if (name == null || names == null)
|
||||
return false;
|
||||
boolean matched = false;
|
||||
for (int i=0; i< names.length && !matched; i++)
|
||||
if (name.equals(names[i]))
|
||||
matched = true;
|
||||
return matched;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Works with equinox, felix, nuxeo and probably more. Not exactly in the
|
||||
* spirit of OSGi but quite necessary to support self-contained webapps and
|
||||
|
@ -107,7 +125,8 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
BUNDLE_ENTRY_FIELD.setAccessible(true);
|
||||
}
|
||||
Object bundleEntry = BUNDLE_ENTRY_FIELD.get(con);
|
||||
if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry"))
|
||||
|
||||
if (match(bundleEntry.getClass().getName(), FILE_BUNDLE_ENTRY_CLASSES))
|
||||
{
|
||||
if (FILE_FIELD == null)
|
||||
{
|
||||
|
@ -117,7 +136,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
File f = (File) FILE_FIELD.get(bundleEntry);
|
||||
return f.getParentFile().getParentFile();
|
||||
}
|
||||
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry"))
|
||||
else if (match(bundleEntry.getClass().getName(), ZIP_BUNDLE_ENTRY_CLASSES))
|
||||
{
|
||||
url = bundle.getEntry("/");
|
||||
|
||||
|
@ -144,7 +163,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
|
||||
return new File(zipFile.getName());
|
||||
}
|
||||
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry"))
|
||||
else if (match (bundleEntry.getClass().getName(), DIR_ZIP_BUNDLE_ENTRY_CLASSES))
|
||||
{
|
||||
// that will not happen as we did ask for the manifest not a
|
||||
// directory.
|
||||
|
@ -309,7 +328,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL == null && match(conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
|
||||
{
|
||||
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
|
||||
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
|
||||
|
@ -340,7 +359,9 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL == null
|
||||
&&
|
||||
match (conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
|
||||
{
|
||||
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
|
||||
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
|
||||
|
|
Loading…
Reference in New Issue