Aperture in OSGi
Using Aperture in OSGI requires a certain environment to be set. You need to include RDF2Go, a triple store implementation with it's driver and
dependencies, the SLF4J Logging API and some logging implementation. It is all summarized on a diagram below.
The aperture bundles are generated automatically by the build.xml ant script.
Just invoke it and in the directory build/dist/bundles - you will get three
jar files whose names begin with: org.semanticdesktop.aperture,
org.semanticdesktop.aperture.impl and org.semanticdesktop.aperture.example.
org.semanticdesktop.aperture
This is the bundle that contains all the core interfaces, services, vocabularies and utility classes. It doesn't contain any implementations.
If you'd like to extend aperture, write your own crawler, accessor or extractor - this is the bundle you will have to depend on. Also every
client application will only need this single dependency. Simple and convenient.
Activating this bundle in an osgi environment makes following services available:
- org.semanticdesktop.aperture.accessor.DataAccessorRegistry
- org.semanticdesktop.aperture.crawler.CrawlerRegistry
- org.semanticdesktop.aperture.datasource.DataSourceRegistry
- org.semanticdesktop.aperture.extractor.ExtractorRegistry
- org.semanticdesktop.aperture.opener.DataOpenerRegistry
- org.semanticdesktop.aperture.hypertext.linkextractor.ExtractorRegistry
- org.semanticdesktop.aperture.mime.identifier.MimeTypeIdentifierRegistry
- org.semanticdesktop.aperture.security.trustdecider.TrustDeciderRegistry
- org.semanticdesktop.aperture.security.trustmanager.TrustManagerRegistry
These registries will listen for appropriate factories appearing in the environment and will automatically include them.
org.semanticdesktop.aperture.impl
This bundle contains all implementations. Every implementation depends on core. The activator of this bundle registers services under
appropriate names, so that registries can detect them. Every factory is treated as a separate service. It is registered under the name
of the generic interface it implements (e.g. a FileSystemCrawlerFactory is registered under the name of a CrawlerFactory). This enables
automatic detection.
org.semanticdesktop.aperture
This bundle contains a quick example how Aperture can be used in OSGI environment. It can be used as a test to determine if you set
up your environment correctly. When you start this bundle, it will begin crawling your home directory and extracting all
information it can. It won't dig into subdirectories so it shouldn't last too long. After the crawler has finished, you should see
the RDF information printed on your screen.
Build infrastructure
This part of this document is a bit technical. You may skip it if you only want to use Aperture. Nevertheless, It may be of some interest
to all that need to include aperture in their own projects and would like to influence the packaging.
The OSGi packaging had to be as unobtrusive as possible. It has been decided that the structure of the source tree must not
be altered, and that the former packaging method (as a plain jar) must remain available.
build.xml script
Classes that should fall within a bundle are chosen one-by-one. A sophisticated system of selectors has been introduced in the ant build
script. Those selectors have been extracted into the selectors.xml file. Aperture has been conceptually divided into ca. 40 'elementary'
bundles. In this division the vocabulary and
utility classes are in separate bundles. Every Registry service and every implementation has it's own bundle. Every 'elementary'
bundle has:
- It's own selector in the build script. This selector covers:
- Source files
- Class files
- Activator source
- Activator files
- Non-java resources (like xml, dtd or icons)
- Library jars (that are to be included in the bundle
-
It's own activator class.
In order for this to work - every selector is applied to five directories:
- src/java
- src/activators
- build/classes
- build/classes-activators
- lib
Additional measures have been taken to prevent non-java resources from being copied twice (from the source and from the classes
directory.
Activators
The activators have been kept separate from the 'normal' source code. They are stored in the src/activators subdirectory. Every
'elementary' bundle has it's own Activator. There are basically two kinds of activators: registry activators and implementation activators.
The registry activators are responsible for running the the registries. They are also equipped with osgi ServiceTrackers that listen for
implementations appearing and disappearing. There were two reasons why this approach has been chosen.
- It is much cleaner and simpler. Only the registry Activators need to be aware of other services appearing and disappearing. It is enough
for them to use a 15-line service tracker. The implementations can be completely unaware of the registries. The client application
can even bypass the registries altogether and search for implementations by itself (by looking for services under the name of the
factory interface - see aperture-impl)
- It makes it possible to have multiple registries in a system.
The coarsegrained bundles are built out of 'elementary' bundles. Every coarsegrained bundle (that is core and impl) has an activator that
simply calls the activators of all 'elementary' bundles.
middle-grained bundles
Some attempt has been made to implement a more detailed packaging scheme. It would consist of six bundles:
- vocabulary (Vocabulary classes)
- util (Utility classes)
- Core services:
- Registries and interfaces for:
- DataAccessors
- Crawlers
- Extractors
- DataSources
- DataOpeners
-
Core rdf interfaces and classes (RDFContainer, RDF2GoRDFContainer etc.)
- Supporting services:
- Registries and interfaces for:
- LinkExtractors
- MimeTypeIdentifiers
- TrustManagers
- TrustDeciders
-
Core rdf interfaces and classes (RDFContainer, RDF2GoRDFContainer etc.)
-
Core implementations - implementations of the all mentioned interfaces.
-
Supporting implementations.
Following things have been prepared for this:
- There are 'middlegrained' selectors that combine appropriate elementary selectors
- There are targets that create jar files with bundles
- Those jar files contain manifests that have also been prepared
Unfortunately the 'middle-grained' approach has been abandoned. It prooved too time-consuming to maintain the manifest files for six bundles.
It could potentially be done by adopting one of following approaches:
- Use eclipse plugin development environment. Create separate projects for every bundle, import the source from external directory
(that is from the main aperture directory), use the include/exclude feature to have every bundle include the appropriate set of
files and libraries. This approach has the disadvantage, that the build process would not be automated.
- Find some tool that would generate manifest files automatically it should provide following functionality
- Generate the Bundle-Classpath list - a list of all jar files that are included in the bundle
- Create a set of imports
- Exclude imports from bundles that are on the Required-bundle list
- Exclude imports from jars, that are included in the Bundle-Classpath
- Exclude other imports - defined by some rules
- Create a set of exports - all packages in the bundle
- Exclude exports defined by a set of rules
A tool called mangen has been evaluated but with no success.