[FELIX-4368] More work to support OSGi Repository 1.0
The SHA-256 for the content capability is now lazily computated.
Additional unit tests.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1563864 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java
index 4845264..8b171d5 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java
@@ -17,7 +17,6 @@
import java.util.Map;
import org.osgi.framework.namespace.BundleNamespace;
-import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Resource;
@@ -38,6 +37,11 @@
{
Map<String, Object> result = capability.getPropertiesAsMap();
String namespace = getNamespace();
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(namespace))
+ result.put(BundleNamespace.BUNDLE_NAMESPACE, result.get(org.apache.felix.bundlerepository.Resource.SYMBOLIC_NAME));
+
+ /*
+ This was here, but I don't think it applies in this use-case.
if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
result.put(ServiceNamespace.CAPABILITY_OBJECTCLASS_ATTRIBUTE,
result.get(ServiceNamespace.CAPABILITY_OBJECTCLASS_ATTRIBUTE.toLowerCase()));
@@ -45,6 +49,7 @@
result.put(BundleNamespace.BUNDLE_NAMESPACE, result.get(org.apache.felix.bundlerepository.Resource.SYMBOLIC_NAME));
else
result.put(namespace, result.get(capability.getName()));
+ */
return result;
}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixResourceAdapter.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixResourceAdapter.java
index f12b2b1..5dbb07a 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixResourceAdapter.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixResourceAdapter.java
@@ -20,7 +20,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Callable;
+import org.apache.felix.bundlerepository.impl.LazyHashMap.LazyValue;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Capability;
@@ -74,20 +76,18 @@
return new OSGiCapabilityImpl(IdentityNamespace.IDENTITY_NAMESPACE, idAttrs, Collections.<String, String> emptyMap(), res);
}
- private static Capability newOsgiContentCapability(Resource res, String uri, long size)
+ private static Capability newOsgiContentCapability(Resource res, final String uri, long size)
{
// TODO duplicated in OSGiRepositoryImpl
- Map<String, Object> contentAttrs = new HashMap<String, Object>();
- try
- {
- // TODO can we do this lazily?
- contentAttrs.put(ContentNamespace.CONTENT_NAMESPACE, OSGiRepositoryImpl.getSHA256(uri));
- } catch (Exception e)
- {
- // TODO handle properly. When if the sha computation can be done
- // lazily this exception will go away...
- throw new RuntimeException(e);
- }
+ LazyValue<String, Object> lazyValue =
+ new LazyValue<String, Object>(ContentNamespace.CONTENT_NAMESPACE, new Callable<Object>() {
+ public Object call() throws Exception
+ {
+ // This is expensive to do, so only compute it when actually obtained...
+ return OSGiRepositoryImpl.getSHA256(uri);
+ }
+ });
+ Map<String, Object> contentAttrs = new LazyHashMap<String, Object>(Collections.singleton(lazyValue));
contentAttrs.put(ContentNamespace.CAPABILITY_MIME_ATTRIBUTE, "application/vnd.osgi.bundle");
contentAttrs.put(ContentNamespace.CAPABILITY_SIZE_ATTRIBUTE, size);
contentAttrs.put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, uri);
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryXMLTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryXMLTest.java
index c299c2a..669d294 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryXMLTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryXMLTest.java
@@ -19,10 +19,13 @@
package org.apache.felix.bundlerepository.impl;
import java.net.URL;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
+import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import junit.framework.TestCase;
@@ -34,11 +37,13 @@
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.ContentNamespace;
import org.osgi.service.repository.Repository;
public class OSGiRepositoryXMLTest extends TestCase
{
- public void testParseStandardRepositoryXML() throws Exception
+ public void testIdentityCapability() throws Exception
{
RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
URL url = getClass().getResource("/spec_repository.xml");
@@ -58,6 +63,55 @@
assertEquals("osgi.subsystem.feature", cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
}
+ public void testContentCapability() throws Exception
+ {
+ RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
+ URL url = getClass().getResource("/spec_repository.xml");
+ repoAdmin.addRepository(url);
+
+ Repository repo = new OSGiRepositoryImpl(repoAdmin);
+ Requirement req = new OSGiRequirementImpl("foo", "(bar=toast)");
+
+ Map<Requirement, Collection<Capability>> result = repo.findProviders(Collections.singleton(req));
+ assertEquals(1, result.size());
+ Collection<Capability> caps = result.values().iterator().next();
+ assertEquals(1, caps.size());
+ Capability cap = caps.iterator().next();
+
+ assertEquals("foo", cap.getNamespace());
+ assertEquals(0, cap.getDirectives().size());
+ assertEquals(1, cap.getAttributes().size());
+ Entry<String, Object> fooCap = cap.getAttributes().entrySet().iterator().next();
+ assertEquals("bar", fooCap.getKey());
+ assertEquals("toast", fooCap.getValue());
+
+ Resource res = cap.getResource();
+ List<Capability> idCaps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ assertEquals(1, idCaps.size());
+ Capability idCap = idCaps.iterator().next();
+
+ assertEquals("org.apache.felix.bundlerepository.test_file_3", idCap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertEquals(Version.parseVersion("1.2.3.something"), idCap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ assertEquals("osgi.bundle", idCap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+
+ List<Capability> contentCaps = res.getCapabilities(ContentNamespace.CONTENT_NAMESPACE);
+ assertEquals(1, contentCaps.size());
+ Capability contentCap = contentCaps.iterator().next();
+
+ assertEquals("b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78",
+ contentCap.getAttributes().get(ContentNamespace.CONTENT_NAMESPACE));
+ assertEquals(new Long(3), contentCap.getAttributes().get(ContentNamespace.CAPABILITY_SIZE_ATTRIBUTE));
+ assertEquals("application/vnd.osgi.bundle", contentCap.getAttributes().get(ContentNamespace.CAPABILITY_MIME_ATTRIBUTE));
+
+ URL fileURL = getClass().getResource("/repo_files/test_file_3.jar");
+ byte[] expectedBytes = Streams.suck(fileURL.openStream());
+
+ String resourceURL = (String) contentCap.getAttributes().get(ContentNamespace.CAPABILITY_URL_ATTRIBUTE);
+ byte[] actualBytes = Streams.suck(new URL(resourceURL).openStream());
+ assertEquals(3L, actualBytes.length);
+ assertTrue(Arrays.equals(expectedBytes, actualBytes));
+ }
+
private RepositoryAdminImpl createRepositoryAdmin() throws Exception
{
Bundle sysBundle = Mockito.mock(Bundle.class);
@@ -69,4 +123,6 @@
return new RepositoryAdminImpl(bc, new Logger(bc));
}
+
+
}
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/Streams.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/Streams.java
new file mode 100644
index 0000000..77881e5
--- /dev/null
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/Streams.java
@@ -0,0 +1,57 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class Streams {
+ private Streams() {}
+
+ public static void pump(InputStream is, OutputStream os) throws IOException {
+ byte[] bytes = new byte[8192];
+
+ int length = 0;
+ int offset = 0;
+
+ while ((length = is.read(bytes, offset, bytes.length - offset)) != -1) {
+ offset += length;
+
+ if (offset == bytes.length) {
+ os.write(bytes, 0, bytes.length);
+ offset = 0;
+ }
+ }
+ if (offset != 0) {
+ os.write(bytes, 0, offset);
+ }
+ }
+
+ public static byte [] suck(InputStream is) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ pump(is, baos);
+ return baos.toByteArray();
+ } finally {
+ is.close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/bundlerepository/src/test/resources/repo_files/test_file_3.jar b/bundlerepository/src/test/resources/repo_files/test_file_3.jar
new file mode 100644
index 0000000..48b83b8
--- /dev/null
+++ b/bundlerepository/src/test/resources/repo_files/test_file_3.jar
@@ -0,0 +1 @@
+ABC
\ No newline at end of file
diff --git a/bundlerepository/src/test/resources/spec_repository.xml b/bundlerepository/src/test/resources/spec_repository.xml
index ffd6c2e..ff95b9e 100644
--- a/bundlerepository/src/test/resources/spec_repository.xml
+++ b/bundlerepository/src/test/resources/spec_repository.xml
@@ -20,6 +20,22 @@
<repository increment='1389802088217' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
<resource>
<capability namespace='osgi.identity'>
+ <attribute name='osgi.identity' value='org.apache.felix.bundlerepository.test_file_3'/>
+ <attribute name='type' value='osgi.bundle'/>
+ <attribute name='version' type='Version' value='1.2.3.something'/>
+ </capability>
+ <capability namespace='osgi.content'>
+ <attribute name='osgi.content' value='a1c64578808c38a63cd6563e9936f025638aeaf9de70f36765367db81c0afc38'/>
+ <attribute name='url' value='repo_files/test_file_3.jar'/>
+ <attribute name='size' type='Long' value='3'/>
+ <attribute name='mime' value='application/vnd.osgi.bundle'/>
+ </capability>
+ <capability namespace='foo'>
+ <attribute name='bar' value='toast'/>
+ </capability>
+ </resource>
+ <resource>
+ <capability namespace='osgi.identity'>
<attribute name='osgi.identity' value='org.apache.sshd.core'/>
<attribute name='type' value='osgi.bundle'/>
<attribute name='version' type='Version' value='0.9.0'/>