blob: ecb3941f5d97a96442d5e57095c67b53f45c33d2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.framework;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import junit.framework.TestCase;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Capability;
import org.osgi.resource.Resource;
public class RequirementsCapabilitiesTest extends TestCase
{
private File tempDir;
private Framework felix;
private File cacheDir;
@Override
protected void setUp() throws Exception
{
super.setUp();
tempDir = File.createTempFile("felix-temp", ".dir");
assertTrue("precondition", tempDir.delete());
assertTrue("precondition", tempDir.mkdirs());
cacheDir = new File(tempDir, "felix-cache");
assertTrue("precondition", cacheDir.mkdir());
String cache = cacheDir.getPath();
Map<String,String> params = new HashMap<String, String>();
params.put("felix.cache.profiledir", cache);
params.put("felix.cache.dir", cache);
params.put(Constants.FRAMEWORK_STORAGE, cache);
felix = new Felix(params);
felix.init();
felix.start();
}
@Override
protected void tearDown() throws Exception
{
super.tearDown();
felix.stop(); // Note that this method is async
felix = null;
deleteDir(tempDir);
tempDir = null;
cacheDir = null;
}
public void testIdentityCapabilityBundleFragment() throws Exception
{
String bmf = "Bundle-SymbolicName: cap.bundle\n"
+ "Bundle-Version: 1.2.3.Blah\n"
+ "Bundle-ManifestVersion: 2\n"
+ "Import-Package: org.osgi.framework\n";
File bundleFile = createBundle(bmf);
String fmf = "Bundle-SymbolicName: cap.frag\n"
+ "Bundle-Version: 1.0.0\n"
+ "Fragment-Host: cap.bundle\n"
+ "Bundle-ManifestVersion: 2\n"
+ "Export-Package: org.foo.bar;version=\"2.0.0\"\n"
+ "Import-Package: org.osgi.util.tracker\n";
File fragFile = createBundle(fmf);
Bundle b = felix.getBundleContext().installBundle(bundleFile.toURI().toASCIIString());
Bundle f = felix.getBundleContext().installBundle(fragFile.toURI().toASCIIString());
// Check the bundle capabilities.
// First check the capabilities on the Bundle Revision, which is available on installed bundles
BundleRevision bbr = b.adapt(BundleRevision.class);
List<Capability> bwbCaps = bbr.getCapabilities("osgi.wiring.bundle");
assertEquals(1, bwbCaps.size());
Map<String, Object> expectedBWBAttrs = new HashMap<String, Object>();
expectedBWBAttrs.put("osgi.wiring.bundle", "cap.bundle");
expectedBWBAttrs.put("bundle-version", Version.parseVersion("1.2.3.Blah"));
Capability expectedBWBCap = new TestCapability("osgi.wiring.bundle",
expectedBWBAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedBWBCap, bwbCaps.get(0));
List<Capability> bwhCaps = bbr.getCapabilities("osgi.wiring.host");
assertEquals(1, bwhCaps.size());
Map<String, Object> expectedBWHAttrs = new HashMap<String, Object>();
expectedBWHAttrs.put("osgi.wiring.host", "cap.bundle");
expectedBWHAttrs.put("bundle-version", Version.parseVersion("1.2.3.Blah"));
Capability expectedBWHCap = new TestCapability("osgi.wiring.host",
expectedBWHAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedBWHCap, bwhCaps.get(0));
List<Capability> bwiCaps = bbr.getCapabilities("osgi.identity");
assertEquals(1, bwiCaps.size());
Map<String, Object> expectedBWIAttrs = new HashMap<String, Object>();
expectedBWIAttrs.put("osgi.identity", "cap.bundle");
expectedBWIAttrs.put("type", "osgi.bundle");
expectedBWIAttrs.put("version", Version.parseVersion("1.2.3.Blah"));
Capability expectedBWICap = new TestCapability("osgi.identity",
expectedBWIAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedBWICap, bwiCaps.get(0));
assertEquals("The Bundle should not directly expose osgi.wiring.package",
0, bbr.getCapabilities("osgi.wiring.package").size());
// Check the fragment's capabilities.
// First check the capabilities on the Bundle Revision, which is available on installed fragments
BundleRevision fbr = f.adapt(BundleRevision.class);
List<Capability> fwpCaps = fbr.getCapabilities("osgi.wiring.package");
assertEquals(1, fwpCaps.size());
Map<String, Object> expectedFWAttrs = new HashMap<String, Object>();
expectedFWAttrs.put("osgi.wiring.package", "org.foo.bar");
expectedFWAttrs.put("version", Version.parseVersion("2"));
expectedFWAttrs.put("bundle-symbolic-name", "cap.frag");
expectedFWAttrs.put("bundle-version", Version.parseVersion("1.0.0"));
Capability expectedFWCap = new TestCapability("osgi.wiring.package",
expectedFWAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedFWCap, fwpCaps.get(0));
List<Capability> fiCaps = fbr.getCapabilities("osgi.identity");
assertEquals(1, fiCaps.size());
Map<String, Object> expectedFIAttrs = new HashMap<String, Object>();
expectedFIAttrs.put("osgi.identity", "cap.frag");
expectedFIAttrs.put("type", "osgi.fragment");
expectedFIAttrs.put("version", Version.parseVersion("1.0.0"));
Capability expectedFICap = new TestCapability("osgi.identity",
expectedFIAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedFICap, fiCaps.get(0));
// Start the bundle. This will make the BundleWiring available on both the bundle and the fragment
b.start();
// Check the Bundle Wiring on the fragment. It should only contain the osgi.identity capability
// All the other capabilities should have migrated to the bundle's BundleWiring.
BundleWiring fbw = f.adapt(BundleWiring.class);
List<BundleCapability> fbwCaps = fbw.getCapabilities(null);
assertEquals("Fragment should only have 1 capability: it's osgi.identity", 1, fbwCaps.size());
assertCapsEquals(expectedFICap, fbwCaps.get(0));
// Check the Bundle Wiring on the bundle. It should contain all the capabilities originally on the
// bundle and also contain the osgi.wiring.package capability from the fragment.
BundleWiring bbw = b.adapt(BundleWiring.class);
List<BundleCapability> bwbCaps2 = bbw.getCapabilities("osgi.wiring.bundle");
assertEquals(1, bwbCaps2.size());
assertCapsEquals(expectedBWBCap, bwbCaps2.get(0));
List<BundleCapability> bwhCaps2 = bbw.getCapabilities("osgi.wiring.host");
assertEquals(1, bwhCaps2.size());
assertCapsEquals(expectedBWHCap, bwhCaps2.get(0));
List<BundleCapability> bwiCaps2 = bbw.getCapabilities("osgi.identity");
assertEquals(1, bwiCaps2.size());
assertCapsEquals(expectedBWICap, bwiCaps2.get(0));
List<BundleCapability> bwpCaps2 = bbw.getCapabilities("osgi.wiring.package");
assertEquals("Bundle should have inherited the osgi.wiring.package capability from the fragment",
1, bwpCaps2.size());
assertCapsEquals(expectedFWCap, bwpCaps2.get(0));
}
public void testIdentityCapabilityFrameworkExtension() throws Exception
{
String femf = "Bundle-SymbolicName: fram.ext\n"
+ "Bundle-Version: 1.2.3.test\n"
+ "Fragment-Host: system.bundle; extension:=framework\n"
+ "Bundle-ManifestVersion: 2\n"
+ "Export-Package: org.foo.bar;version=\"2.0.0\"\n";
File feFile = createBundle(femf);
Bundle fe = felix.getBundleContext().installBundle(feFile.toURI().toASCIIString());
BundleRevision fbr = fe.adapt(BundleRevision.class);
List<Capability> feCaps = fbr.getCapabilities("osgi.identity");
assertEquals(1, feCaps.size());
Map<String, Object> expectedFEAttrs = new HashMap<String, Object>();
expectedFEAttrs.put("osgi.identity", "fram.ext");
expectedFEAttrs.put("type", "osgi.fragment");
expectedFEAttrs.put("version", Version.parseVersion("1.2.3.test"));
Capability expectedFICap = new TestCapability("osgi.identity",
expectedFEAttrs, Collections.<String, String>emptyMap());
assertCapsEquals(expectedFICap, feCaps.get(0));
}
private File createBundle(String manifest) throws IOException
{
File f = File.createTempFile("felix-bundle", ".jar", tempDir);
Manifest mf = new Manifest(new ByteArrayInputStream(manifest.getBytes("utf-8")));
mf.getMainAttributes().putValue("Manifest-Version", "1.0");
JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
os.close();
return f;
}
private static void assertCapsEquals(Capability expected, Capability actual)
{
assertEquals(expected.getNamespace(), actual.getNamespace());
assertSubMap(expected.getAttributes(), actual.getAttributes());
assertSubMap(expected.getDirectives(), actual.getDirectives());
// We ignore the resource in the comparison
}
private static void assertSubMap(Map<?,?> subMap, Map<?,?> fullMap)
{
for (Map.Entry<?,?> entry : subMap.entrySet())
{
assertEquals(entry.getValue(), fullMap.get(entry.getKey()));
}
}
private static void deleteDir(File root) throws IOException
{
if (root.isDirectory())
{
for (File file : root.listFiles())
{
deleteDir(file);
}
}
assertTrue(root.delete());
}
static class TestCapability implements Capability
{
private final String namespace;
private final Map<String, Object> attributes;
private final Map<String, String> directives;
TestCapability(String ns, Map<String,Object> attrs, Map<String,String> dirs)
{
namespace = ns;
attributes = attrs;
directives = dirs;
}
public String getNamespace()
{
return namespace;
}
public Map<String, Object> getAttributes()
{
return attributes;
}
public Map<String, String> getDirectives()
{
return directives;
}
public Resource getResource()
{
return null;
}
}
}