-
1. Re: Priming the repository
thomas.diesler May 22, 2012 9:16 AM (in response to thomas.diesler)The RepositoryStorage should be obtained from the Repository like this
RepositoryStorage storage = ((XPersistentRepository)getRepository()).getRepositoryStorage();
in jbosgi-repository-1.3.0.Beta3 RepositoryStorage is no longer directly available as a service.
This code
RepositoryReader reader = RepositoryXMLReader.create(contentURL.openStream()); XResource resource = reader.nextResource(); while (resource != null) { rs.addResource(resource); resource = reader.nextResource(); }
is fine, except that the name 'contentURL' usualy means the URL to the resource content which is available as an attribute on the content capability.
Part of the resource metadata (in XML) is that URL - it must point to real bytes - otherwise the RepositoryStorage cannot copy them.
Another approach would be to use this API
/** * Add a resource from the given input stream * * @param mime An IANA defined MIME type for the format * @param input The bytes for the resource * @return The resource being added, which may be a modified copy of the give resource * @throws RepositoryStorageException If there is a problem storing the resource */ XResource addResource(String mime, InputStream input) throws RepositoryStorageException;
-
2. Re: Priming the repository
bosschaert May 22, 2012 10:44 AM (in response to thomas.diesler)Thanks Thomas.
I would like to use the Repository XML as defined by the OSGi R5 spec, so in that case I should probably used the RepositoryXMLReader.
The issue I'm encountering is the following with the code snippet as above:
{code}
java.lang.ClassCastException: org.jboss.osgi.resolver.spi.AbstractResource cannot be cast to org.osgi.service.repository.RepositoryContent
at org.jboss.osgi.repository.core.FileBasedRepositoryStorage.addResourceInternal(FileBasedRepositoryStorage.java:123)
at org.jboss.osgi.repository.core.FileBasedRepositoryStorage.addResource(FileBasedRepositoryStorage.java:106)
at org.jboss.test.osgi.repository.tck.Activator.primeRepository(Activator.java:96)
{code}
The FileRepository casts the XResource to a RespositoryContent, however resources created by the RepositoryXMLReader don't seem to implement this interface.
-
3. Re: Priming the repository
thomas.diesler May 22, 2012 11:15 AM (in response to bosschaert)Ok, that is a bug - fixing ...
-
4. Re: Priming the repository
thomas.diesler May 22, 2012 12:02 PM (in response to thomas.diesler)Fixed in jbosgi-repository-1.3.0.Beta4
@Test public void testAddResource() throws Exception { // Assert empty repository Assert.assertNull(storage.getRepositoryReader().nextResource()); // Write the bundle to the location referenced by repository-testA.xml getBundleA().as(ZipExporter.class).exportTo(new File("./target/bundleA.jar"), true); RepositoryReader reader = getRepositoryReader("xml/repository-testA.xml"); XResource resource = storage.addResource(reader.nextResource()); verifyResource(resource); }
-
5. Re: Priming the repository
bosschaert May 23, 2012 7:31 AM (in response to thomas.diesler)The exception is gone and I can now see the following message appearing, which looks good:
{code} INFO: JBOSGI020400: Resource added: URLResource[org.osgi.test.cases.repository.tb1:1.0.0.test]{code}
However, I don't seem to be able to retrieve the resource using an arbitrary requirement yet.
For example, my resource is defined in XML as follows (the value specified with URL is where the resource can actually be found):
{code:xml}<repository name='OSGi Repository' increment='1' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
<resource>
<capability namespace='osgi.identity'>
<attribute name='osgi.identity' value='org.osgi.test.cases.repository.tb1' />
<attribute name='version' type='Version' value='1.0.0.test' />
<attribute name='type' value='osgi.bundle' />
</capability>
<capability namespace='osgi.content'>
<attribute name='osgi.content' value='a20e2054404fff56d0de8be82cfdace9aec45027b8a1acb4b65b62e034801714' />
<attribute name='url' value='bundleresource://5.fwk637148086/tb1.jar' />
<attribute name='size' type='Long' value='3796' />
<attribute name='mime' value='application/vnd.osgi.bundle' />
</capability>
<capability namespace='osgi.wiring.bundle'>
<attribute name='osgi.wiring.bundle' value='org.osgi.test.cases.repository.tb1' />
<attribute name='bundle-version' type='Version' value='1.0.0.test' />
</capability>
<capability namespace='osgi.wiring.package'>
<attribute name='osgi.wiring.package' value='org.osgi.test.cases.repository.tb1.pkg1' />
<attribute name='version' type='Version' value='0.9' />
<attribute name='bundle-version' type='Version' value='1.0.0.test' />
<attribute name='bundle-symbolic-name' value='org.osgi.test.cases.repository.tb1' />
</capability>
</resource>
</repository>{code}
Then, I use the following to try to retrieve the resource:
{code}RequirementImpl requirement = new RequirementImpl("osgi.wiring.bundle",
"(&(osgi.wiring.bundle=org.osgi.test.cases.repository.tb1)(bundle-version=1.0.0.test))");
Map<Requirement, Collection<Capability>> r = repository.findProviders(Collections.singleton(requirement));{code}
but the result is always empty. Is this functionality missing at this point in time?
-
6. Re: Priming the repository
thomas.diesler May 23, 2012 11:28 AM (in response to bosschaert)Fixed in Allow nsvalue in filter if not found as attribute on the requirement
public void testRequireBundleWithFilter() throws Exception { XRequirementBuilder builder = XRequirementBuilder.create(BundleNamespace.BUNDLE_NAMESPACE); builder.getDirectives().put(BundleNamespace.REQUIREMENT_FILTER_DIRECTIVE, "(osgi.wiring.bundle=org.acme.pool)"); XRequirement req = builder.getRequirement(); Collection<Capability> providers = storage.findProviders(req); Assert.assertNotNull(providers); Assert.assertEquals(1, providers.size()); XCapability cap = (XCapability) providers.iterator().next(); Assert.assertNotNull(cap); }
This however relies on a hack that tries to extract the namespace value from the filter if it is not given as attribute value
static CacheKey create(Requirement req) { String namespace = req.getNamespace(); String value = (String) req.getAttributes().get(namespace); if (value == null) { Filter filter = getRequiredFilter(req); String filterstr = filter.toString(); int index = filterstr.indexOf("(" + namespace + "="); if (index >= 0) { value = filterstr.substring(index + namespace.length() + 2); index = value.indexOf(")"); value = value.substring(0, index); } } return new CacheKey(namespace, value); }
-
7. Re: Priming the repository
bosschaert May 23, 2012 2:41 PM (in response to thomas.diesler)Thomas Diesler wrote:
This however relies on a hack that tries to extract the namespace value from the filter if it is not given as attribute value
Not sure why this is needed. Shouldn't the filter be simply applied to the attributes of the capability, e.g. using Filter.matches()? (Given that Capability.getNamespace() equals Requirement.getNamespace())
Basically you should just be able to take the value of the 'filter' directive of the requirement and match that to the map of attributes of the capability. I don't think any special tricks are needed (i.e. the capability attribute that has the same name as the capability namespace doesn't need any special code), or am I missing something?
-
8. Re: Priming the repository
thomas.diesler May 23, 2012 3:06 PM (in response to bosschaert)We internally cache by key [namespace:value]. Otherwise we would have very large collections of capabilities to iterate over.
-
9. Re: Priming the repository
thomas.diesler May 23, 2012 3:12 PM (in response to bosschaert)FYI, when adding a resource to the store the sha256 and the size are recalculated and the content url is rewritten. You can find the content & resulting xml in osgi-store/[repository-bundle]/repository