Initial support for Fragments
thomas.diesler Jan 13, 2010 1:48 PMOSGiBundleManager makes the distinction between bundles and fragments based on Fragment-Host in the manifest. The appropriate
state object is attached.
public AbstractBundleState addDeployment(DeploymentUnit unit) { ... OSGiMetaData osgiMetaData = unit.getAttachment(OSGiMetaData.class); ParameterizedAttribute fragmentHost = osgiMetaData.getFragmentHost(); if (fragmentHost != null) { // Create a new OSGiFragmentState OSGiFragmentState fragmentState = new OSGiFragmentState(unit); absBundle = fragmentState; addBundle(fragmentState); } else { // Create a new OSGiBundleState AbstractDeployedBundleState bundleState = new OSGiBundleState(unit); absBundle = bundleState; addBundle(bundleState); } // Attach the abstract bundle state unit.addAttachment(AbstractBundleState.class, absBundle);
There are two ClassLoadingMetaData deployers.
* OSGiBundleClassLoadingDeployer
* OSGiFragmentClassLoadingDeployer
The former does (currently) nothing special additional to consuming OSGiMetaData and constructing/configuring the OSGiClassLoadingMetaData. The latter addtionally configures FragmentHostMetaData
Fragment attachment is supposed to happen during bundle resolve phase.
OSGiFragmentAttachmentDeployer iterate over all installed fragments and attaches the OSGiFragmentState to the host's OSGiBundleState when appropriate. It then creates a DelegateLoader for the fragment and adds it to the host's OSGiClassLoaderPolicy.
All of this should really be handled at the underlying CL layer. There should be support for fragments in ClassLoadingMetaData, which should create the appropriate delegates in the underlying policy.
Resource and class loading from bundles is (due to the above limitations) handled in the OSGiClassLoaderPolicy and OSGiClassLoader respectively.
@Override public URL getResource(String path) { URL resourceURL = super.getResource(path); // Try to find the resource in the attached fragments if (resourceURL == null && fragmentLoaders != null) { for (DelegateLoader fragLoader : fragmentLoaders) { resourceURL = fragLoader.getResource(path); if (resourceURL != null) break; } } return resourceURL; }
@Override public Class<?> loadClass(String className) throws ClassNotFoundException { try { Class<?> clazz = super.loadClass(className); return clazz; } catch (ClassNotFoundException ex) { // Try to load the class in the attached fragments List<DelegateLoader> fragmentLoaders = osgiPolicy.getFragmentLoaders(); if (fragmentLoaders != null) { for (DelegateLoader fragLoader : fragmentLoaders) { Class<?> clazz = fragLoader.loadClass(className); if (clazz != null) return clazz; } } // Throw the ClassNotFoundException throw ex; } }
which is both incorrect and only works for the most basic scenarios. See JBCL-137 for progress on this.
Test coverage is here
$ mvn -Dtest=fragments/** test
Running org.jboss.test.osgi.fragments.FragmentTestCase
Tests run: 6, Failures: 0, Errors: 0, Skipped: 3, Time elapsed: 3.932 sec