use of org.apache.felix.framework.cache.Content in project felix by apache.
the class ExtensionManager method resolveExtensionBundles.
public List<Bundle> resolveExtensionBundles(Felix felix) {
if (m_unresolvedExtensions.isEmpty()) {
return Collections.emptyList();
}
// Collect the highest version of unresolved that are not already resolved by bsn
List<BundleRevisionImpl> extensions = new ArrayList<BundleRevisionImpl>();
// Collect the unresolved that where filtered out as alternatives in case the highest version doesn't resolve
List<BundleRevisionImpl> alt = new ArrayList<BundleRevisionImpl>();
outer: for (BundleRevisionImpl revision : m_unresolvedExtensions) {
// Already resolved by bsn?
for (BundleRevisionImpl existing : m_resolvedExtensions) {
if (existing.getSymbolicName().equals(revision.getSymbolicName())) {
// Then ignore it
continue outer;
}
}
// Otherwise, does a higher version exist by bsn?
for (BundleRevisionImpl other : m_unresolvedExtensions) {
if ((revision != other) && (revision.getSymbolicName().equals(other.getSymbolicName())) && revision.getVersion().compareTo(other.getVersion()) < 0) {
// Add this one to alternatives and filter it
alt.add(revision);
continue outer;
}
}
// no higher version and not resolved yet by bsn - try to resolve it
extensions.add(revision);
}
// This will return all resolvable revisions with the wires they need
Map<BundleRevisionImpl, List<BundleWire>> wirings = findResolvableExtensions(extensions, alt);
List<Bundle> result = new ArrayList<Bundle>();
for (Map.Entry<BundleRevisionImpl, List<BundleWire>> entry : wirings.entrySet()) {
BundleRevisionImpl revision = entry.getKey();
// move this revision from unresolved to resolved
m_unresolvedExtensions.remove(revision);
m_resolvedExtensions.add(revision);
BundleWire wire = new BundleWireImpl(revision, revision.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE).get(0), m_systemBundleRevision, getCapabilities(BundleRevision.HOST_NAMESPACE).get(0));
try {
revision.resolve(new BundleWiringImpl(m_logger, m_configMap, null, revision, null, Collections.singletonList(wire), Collections.EMPTY_MAP, Collections.EMPTY_MAP));
} catch (Exception ex) {
m_logger.log(revision.getBundle(), Logger.LOG_ERROR, "Error resolving extension bundle : " + revision.getBundle(), ex);
}
felix.getDependencies().addDependent(wire);
appendCapabilities(entry.getKey().getDeclaredExtensionCapabilities(null));
for (BundleWire w : entry.getValue()) {
if (!w.getRequirement().getNamespace().equals(BundleRevision.HOST_NAMESPACE) && !w.getRequirement().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) {
((BundleWiringImpl) w.getRequirer().getWiring()).addDynamicWire(w);
felix.getDependencies().addDependent(w);
}
}
final File f;
Content revisionContent = revision.getContent();
if (revisionContent instanceof JarContent) {
f = ((JarContent) revisionContent).getFile();
} else {
f = ((DirectoryContent) revisionContent).getFile();
}
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
m_extenderFramework.add(f);
return null;
}
});
} catch (Exception ex) {
m_logger.log(revision.getBundle(), Logger.LOG_ERROR, "Error adding extension bundle to framework classloader: " + revision.getBundle(), ex);
}
felix.setBundleStateAndNotify(revision.getBundle(), Bundle.RESOLVED);
result.add(revision.getBundle());
}
// at this point, all revisions left in unresolved are not resolvable
m_failedExtensions.addAll(m_unresolvedExtensions);
m_unresolvedExtensions.clear();
if (!wirings.isEmpty()) {
felix.getResolver().addRevision(getRevision());
}
return result;
}
use of org.apache.felix.framework.cache.Content in project felix by apache.
the class ExtensionManager method addExtensionBundle.
/**
* Add an extension bundle. The bundle will be added to the parent classloader
* and it's exported packages will be added to the module definition
* exports of this instance. Subsequently, they are available form the
* instance in it's role as content loader.
*
* @param felix the framework instance the given extension bundle comes from.
* @param bundle the extension bundle to add.
* @throws BundleException if extension bundles are not supported or this is
* not a framework extension.
* @throws SecurityException if the caller does not have the needed
* AdminPermission.EXTENSIONLIFECYCLE and security is enabled.
* @throws Exception in case something goes wrong.
*/
synchronized void addExtensionBundle(Felix felix, BundleImpl bundle) throws Exception {
Object sm = System.getSecurityManager();
if (sm != null) {
((SecurityManager) sm).checkPermission(new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
if (!((BundleProtectionDomain) bundle.getProtectionDomain()).impliesDirect(new AllPermission())) {
throw new SecurityException("Extension Bundles must have AllPermission");
}
}
String directive = ManifestParser.parseExtensionBundleHeader((String) ((BundleRevisionImpl) bundle.adapt(BundleRevision.class)).getHeaders().get(Constants.FRAGMENT_HOST));
final ClassPathExtenderFactory.ClassPathExtender extender;
if (!Constants.EXTENSION_FRAMEWORK.equals(directive)) {
throw new BundleException("Unsupported Extension Bundle type: " + directive, new UnsupportedOperationException("Unsupported Extension Bundle type!"));
} else if (m_extenderFramework == null) {
// We don't support extensions
m_logger.log(bundle, Logger.LOG_WARNING, "Unable to add extension bundle - Maybe ClassLoader is not supported (on java9, try --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED)?");
throw new UnsupportedOperationException("Unable to add extension bundle.");
}
Content content = bundle.adapt(BundleRevisionImpl.class).getContent();
final File file;
if (content instanceof JarContent) {
file = ((JarContent) content).getFile();
} else if (content instanceof DirectoryContent) {
file = ((DirectoryContent) content).getFile();
} else {
file = null;
}
if (file == null) {
// We don't support revision type for extension
m_logger.log(bundle, Logger.LOG_WARNING, "Unable to add extension bundle - wrong revision type?");
throw new UnsupportedOperationException("Unable to add extension bundle.");
}
BundleRevisionImpl bri = bundle.adapt(BundleRevisionImpl.class);
bri.resolve(null);
// we have to try again for all previously failed extensions because maybe they can now resolve.
m_unresolvedExtensions.addAll(m_failedExtensions);
m_failedExtensions.clear();
m_unresolvedExtensions.add(bri);
}
use of org.apache.felix.framework.cache.Content in project felix by apache.
the class BundleRevisionImpl method getResourcesLocal.
Enumeration getResourcesLocal(String name) {
List l = new ArrayList();
// Special case "/" so that it returns a root URLs for
// each bundle class path entry...this isn't very
// clean or meaningful, but the Spring guys want it.
final List<Content> contentPath = getContentPath();
if (contentPath == null)
return Collections.enumeration(Collections.emptyList());
if (name.equals("/")) {
for (int i = 0; i < contentPath.size(); i++) {
l.add(createURL(i + 1, name));
}
} else {
// Remove leading slash, if present.
if (name.startsWith("/")) {
name = name.substring(1);
}
// Check the module class path.
for (int i = 0; i < contentPath.size(); i++) {
if (contentPath.get(i).hasEntry(name)) {
// Use the class path index + 1 for creating the path so
// that we can differentiate between module content URLs
// (where the path will start with 0) and module class
// path URLs.
l.add(createURL(i + 1, name));
}
}
}
return Collections.enumeration(l);
}
use of org.apache.felix.framework.cache.Content in project felix by apache.
the class BundleWiringImplTest method testFindClassBadWeave.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testFindClassBadWeave() throws Exception {
Felix mockFramework = mock(Felix.class);
Content mockContent = mock(Content.class);
ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);
Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
hooks.add(mockServiceReferenceWeavingHook);
DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();
Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
listeners.add(mockServiceReferenceWovenClassListener);
Class testClass = TestClass.class;
String testClassName = testClass.getName();
String testClassAsPath = testClassName.replace('.', '/') + ".class";
byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
List<Content> contentPath = new ArrayList<Content>();
contentPath.add(mockContent);
initializeSimpleBundleWiring();
when(mockBundle.getFramework()).thenReturn(mockFramework);
when(mockFramework.getBootPackages()).thenReturn(new String[0]);
when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(testClassBytes);
HookRegistry hReg = mock(HookRegistry.class);
when(hReg.getHooks(WeavingHook.class)).thenReturn(hooks);
when(mockFramework.getHookRegistry()).thenReturn(hReg);
when(mockFramework.getService(mockFramework, mockServiceReferenceWeavingHook, false)).thenReturn(new BadDummyWovenHook());
when(hReg.getHooks(WovenClassListener.class)).thenReturn(listeners);
when(mockFramework.getService(mockFramework, mockServiceReferenceWovenClassListener, false)).thenReturn(dummyWovenClassListener);
BundleClassLoader bundleClassLoader = createBundleClassLoader(BundleClassLoader.class, bundleWiring);
assertNotNull(bundleClassLoader);
try {
bundleClassLoader.findClass(TestClass.class.getName());
fail("Class should throw exception");
} catch (Error e) {
// This is expected
}
assertEquals("There should be 1 state changes fired by the weaving", 1, dummyWovenClassListener.stateList.size());
assertEquals("The only state change should be a failed transform on the class", (Object) WovenClass.TRANSFORMING_FAILED, dummyWovenClassListener.stateList.get(0));
}
use of org.apache.felix.framework.cache.Content in project felix by apache.
the class BundleWiringImplTest method testFindClassWeaveDefineError.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testFindClassWeaveDefineError() throws Exception {
Felix mockFramework = mock(Felix.class);
Content mockContent = mock(Content.class);
ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);
Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
hooks.add(mockServiceReferenceWeavingHook);
DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();
Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
listeners.add(mockServiceReferenceWovenClassListener);
Class testClass = TestClass.class;
String testClassName = testClass.getName();
String testClassAsPath = testClassName.replace('.', '/') + ".class";
byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
List<Content> contentPath = new ArrayList<Content>();
contentPath.add(mockContent);
initializeSimpleBundleWiring();
when(mockBundle.getFramework()).thenReturn(mockFramework);
when(mockFramework.getBootPackages()).thenReturn(new String[0]);
when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(testClassBytes);
HookRegistry hReg = mock(HookRegistry.class);
when(hReg.getHooks(WeavingHook.class)).thenReturn(hooks);
when(mockFramework.getHookRegistry()).thenReturn(hReg);
when(mockFramework.getService(mockFramework, mockServiceReferenceWeavingHook, false)).thenReturn(new BadDefineWovenHook());
when(hReg.getHooks(WovenClassListener.class)).thenReturn(listeners);
when(mockFramework.getService(mockFramework, mockServiceReferenceWovenClassListener, false)).thenReturn(dummyWovenClassListener);
BundleClassLoader bundleClassLoader = createBundleClassLoader(BundleClassLoader.class, bundleWiring);
assertNotNull(bundleClassLoader);
try {
bundleClassLoader.findClass(TestClass.class.getName());
fail("Class should throw exception");
} catch (Throwable e) {
}
assertEquals("There should be 2 state changes fired by the weaving", 2, dummyWovenClassListener.stateList.size());
assertEquals("The first state change should transform the class", (Object) WovenClass.TRANSFORMED, dummyWovenClassListener.stateList.get(0));
assertEquals("The second state change failed the define on the class", (Object) WovenClass.DEFINE_FAILED, dummyWovenClassListener.stateList.get(1));
}
Aggregations