[FELIX-4370] Support for RepositoryContent interface
Added test and also some other refactoring/improvements.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1563948 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 8b171d5..5d3e7bb 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
@@ -14,9 +14,9 @@
package org.apache.felix.bundlerepository.impl;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
-import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Resource;
@@ -24,6 +24,7 @@
{
private final org.apache.felix.bundlerepository.Capability capability;
private final Resource resource;
+ private volatile Map<String, Object> convertedAttributes;
public FelixCapabilityAdapter(org.apache.felix.bundlerepository.Capability capability, Resource resource)
{
@@ -35,22 +36,18 @@
public Map<String, Object> getAttributes()
{
- 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));
+ if (convertedAttributes == null)
+ {
+ Map<String, Object> orgMap = capability.getPropertiesAsMap();
+ HashMap<String, Object> converted = new HashMap<String, Object>(orgMap.size());
- /*
- 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()));
- else if (BundleNamespace.BUNDLE_NAMESPACE.equals(namespace))
- result.put(BundleNamespace.BUNDLE_NAMESPACE, result.get(org.apache.felix.bundlerepository.Resource.SYMBOLIC_NAME));
- else
- result.put(namespace, result.get(capability.getName()));
- */
- return result;
+ for (Map.Entry<String, Object> entry : orgMap.entrySet())
+ {
+ converted.put(NamespaceTranslator.getOSGiNamespace(entry.getKey()), entry.getValue());
+ }
+ convertedAttributes = converted; // Cache the result
+ }
+ return convertedAttributes;
}
public Map<String, String> getDirectives()
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 5dbb07a..21f7671 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
@@ -17,13 +17,9 @@
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
-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;
import org.osgi.resource.Requirement;
@@ -44,13 +40,19 @@
{
if (namespace == null || namespace.equals(IdentityNamespace.IDENTITY_NAMESPACE))
{
- Capability c = newOsgiIdentityCapability(this, resource.getSymbolicName(), resource.getVersion());
- return Collections.singletonList(c);
+ // TODO cater for null request
+ Object type = resource.getProperties().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE);
+ OSGiCapabilityImpl c = OSGiRepositoryImpl.newOSGiIdentityCapability(resource.getSymbolicName(),
+ type != null ? type.toString() : IdentityNamespace.TYPE_BUNDLE, resource.getVersion());
+ c.setResource(this);
+ return Collections.<Capability>singletonList(c);
}
if (namespace.equals(ContentNamespace.CONTENT_NAMESPACE))
{
- Capability c = newOsgiContentCapability(this, resource.getURI(), resource.getSize());
- return Collections.singletonList(c);
+ // TODO cater for null request
+ OSGiCapabilityImpl c = OSGiRepositoryImpl.newOSGiContentCapability(resource.getURI(), resource.getSize());
+ c.setResource(this);
+ return Collections.<Capability>singletonList(c);
}
namespace = NamespaceTranslator.getFelixNamespace(namespace);
@@ -66,40 +68,13 @@
return result;
}
- private static Capability newOsgiIdentityCapability(Resource res, String symbolicName, Version version)
- {
- Map<String, Object> idAttrs = new HashMap<String, Object>();
- idAttrs.put(IdentityNamespace.IDENTITY_NAMESPACE, symbolicName);
- idAttrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, IdentityNamespace.TYPE_BUNDLE);
- idAttrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
-
- return new OSGiCapabilityImpl(IdentityNamespace.IDENTITY_NAMESPACE, idAttrs, Collections.<String, String> emptyMap(), res);
- }
-
- private static Capability newOsgiContentCapability(Resource res, final String uri, long size)
- {
- // TODO duplicated in OSGiRepositoryImpl
- 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);
- return new OSGiCapabilityImpl(ContentNamespace.CONTENT_NAMESPACE, contentAttrs, Collections.<String, String> emptyMap());
- }
-
public InputStream getContent()
{
try
{
return new URL(resource.getURI()).openStream();
- } catch (Exception e)
+ }
+ catch (Exception e)
{
throw new RuntimeException(e);
}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImpl.java
index ca7500a..04473e4 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImpl.java
@@ -37,6 +37,7 @@
import org.apache.felix.bundlerepository.impl.LazyHashMap.LazyValue;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Namespace;
@@ -107,37 +108,16 @@
private void addResourceForIdentity(final org.apache.felix.bundlerepository.Resource res, Filter filter, List<Capability> caps)
throws Exception
{
- Map<String, Object> idAttrs = new HashMap<String, Object>();
- idAttrs.put(IdentityNamespace.IDENTITY_NAMESPACE, res.getSymbolicName());
Object type = res.getProperties().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE);
- idAttrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
- type != null ? type.toString() : IdentityNamespace.TYPE_BUNDLE);
- idAttrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, res.getVersion());
-
+ OSGiCapabilityImpl idCap = newOSGiIdentityCapability(res.getSymbolicName(),
+ type != null ? type.toString() : IdentityNamespace.TYPE_BUNDLE, res.getVersion());
if (filter != null)
{
- if (!filter.matches(idAttrs))
+ if (!filter.matches(idCap.getAttributes()))
return;
}
- OSGiCapabilityImpl idCap = new OSGiCapabilityImpl(IdentityNamespace.IDENTITY_NAMESPACE, idAttrs,
- Collections.<String, String>emptyMap());
-
- LazyValue<String, Object> lazyValue = new LazyHashMap.LazyValue<String, Object>(ContentNamespace.CONTENT_NAMESPACE,
- new Callable<Object>()
- {
- public Object call() throws Exception
- {
- // This is expensive to compute, so only do it if we need it...
- return getSHA256(res.getURI());
- }
- });
- 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, res.getSize());
- contentAttrs.put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, res.getURI());
- OSGiCapabilityImpl contentCap = new OSGiCapabilityImpl(ContentNamespace.CONTENT_NAMESPACE, contentAttrs,
- Collections.<String, String>emptyMap());
+ OSGiCapabilityImpl contentCap = newOSGiContentCapability(res.getURI(), res.getSize());
List<OSGiCapabilityImpl> capabilities = Arrays.<OSGiCapabilityImpl>asList(idCap, contentCap);
Resource resource =
@@ -151,6 +131,33 @@
caps.add(idCap);
}
+ static OSGiCapabilityImpl newOSGiIdentityCapability(String symbolicName, String type, Version version)
+ {
+ Map<String, Object> idAttrs = new HashMap<String, Object>();
+ idAttrs.put(IdentityNamespace.IDENTITY_NAMESPACE, symbolicName);
+ idAttrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, type);
+ idAttrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+
+ return new OSGiCapabilityImpl(IdentityNamespace.IDENTITY_NAMESPACE, idAttrs, Collections.<String, String> emptyMap());
+ }
+
+ static OSGiCapabilityImpl newOSGiContentCapability(final String uri, long size)
+ {
+ 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"); // TODO support other types
+ contentAttrs.put(ContentNamespace.CAPABILITY_SIZE_ATTRIBUTE, size);
+ contentAttrs.put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, uri);
+ return new OSGiCapabilityImpl(ContentNamespace.CONTENT_NAMESPACE, contentAttrs, Collections.<String, String> emptyMap());
+ }
+
static String getSHA256(String uri) throws IOException, NoSuchAlgorithmException // TODO find a good place for this
{
InputStream is = new URL(uri).openStream();
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImplTest.java
index 1c25735..87f0888 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRepositoryImplTest.java
@@ -40,9 +40,38 @@
import org.osgi.resource.Resource;
import org.osgi.service.repository.ContentNamespace;
import org.osgi.service.repository.Repository;
+import org.osgi.service.repository.RepositoryContent;
public class OSGiRepositoryImplTest extends TestCase
{
+ public void testRepositoryContent() throws Exception {
+ RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
+ URL url = getClass().getResource("/another_repository.xml");
+ repoAdmin.addRepository(url);
+
+ Repository repo = new OSGiRepositoryImpl(repoAdmin);
+ Requirement req = new OSGiRequirementImpl("osgi.wiring.package",
+ "(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.0.1)(!(version>=2)))");
+
+ 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("osgi.wiring.package", cap.getNamespace());
+ assertEquals("org.apache.commons.logging", cap.getAttributes().get("osgi.wiring.package"));
+ assertEquals(Version.parseVersion("1.0.4"), cap.getAttributes().get("version"));
+
+ Resource resource = cap.getResource();
+ RepositoryContent rc = (RepositoryContent) resource; // Repository Resources must implement this interface
+ byte[] actualBytes = Streams.suck(rc.getContent());
+
+ URL actualURL = getClass().getResource("/repo_files/test_file_1.jar");
+ byte[] expectedBytes = Streams.suck(actualURL.openStream());
+
+ assertTrue(Arrays.equals(expectedBytes, actualBytes));
+ }
+
public void testIdentityAndContentCapabilities() throws Exception
{
RepositoryAdminImpl repoAdmin = createRepositoryAdmin();