This section describe a proposal, how can you use Crispy in a OSGi envionment (how knopflerfish, oscar or equinox).
Crispy offer two classes. The first class ist the service provider net.sf.crispy.extension.osgi.CrispyActivator. The second class is a example for a client, the service consumer net.sf.crispy.extension.osgi.CrispyClientActivator.
By the osgi specification describe the META-INF/Manifest.mf the service properties. For example:
Manifest-Version: 1.0 Bundle-Description: Crispy - OSGi extension Bundle-Name: CrispyActivator Bundle-Classpath: ., commons-logging.jar, crispy-with-tests-0.6.2.jar, commons-proxy-0.1-SNAPSHOT.jar Bundle-Activator: net.sf.crispy.extension.osgi.CrispyActivator Import-Package: org.osgi.framework, net.sf.crispy, net.sf.crispy.impl, test.crispy.example.service Bundle-Vendor: Crispy Bundle-SymbolicName: CrispyActivator Export-Package: test.crispy.example.service, net.sf.crispy.impl, net.sf.crispy Bundle-Version: 1.0.0
This implementation from the org.osgi.framework.BundleActivator interface, the CrispyActivator, will internal create a instance of the ServiceManager. The ServiceManager can be describe with a property file. The location from this file can be in the META-INF directory or in the same package how the CrispyActivator class, with the name service.properties. For example:
crispy.prop.dynamic.proxy.class=jdk_proxy crispy.prop.server.url=rmi://localhost:1099 crispy.prop.executor.class=net.sf.crispy.impl.RmiExecutor test.crispy.example.service.Echo=test.crispy.example.service.EchoImpl test.crispy.example.service.Calculator=test.crispy.example.service.CalculatorImpl crispy.osgi.services=test.crispy.example.service.Echo,test.crispy.example.service.Calculator
The source from the CrispyActivator:
public class CrispyActivator implements BundleActivator {
private static BundleContext bundleContext = null;
public void start(BundleContext pvContext) throws Exception {
bundleContext = pvContext;
URL lvUrl = pvContext.getBundle().getResource("META-INF/service.properties");
PropertiesLoader lvPropertiesLoader = null;
// first try to load the properties
if (lvUrl != null) {
lvPropertiesLoader = new UrlPropertiesLoader(lvUrl);
}
// second try to load the properties
if (lvPropertiesLoader == null) {
lvPropertiesLoader = new ClassPropertiesLoader(CrispyActivator.class, "service.properties");
}
Properties lvProperties = lvPropertiesLoader.load();
ServiceManager lvServiceManager = new ServiceManager(lvProperties);
createServices(lvProperties, lvServiceManager);
bundleContext.registerService(IServiceManager.class.getName(), lvServiceManager, new Properties());
}
public void stop(BundleContext pvContext) throws Exception {
bundleContext = null;
}
private void createServices(Properties pvProperties, IServiceManager pvServiceManager) throws Exception {
String lvServiceClassStrings = (String) pvProperties.get("crispy.osgi.services");
if (lvServiceClassStrings != null) {
String lvClassStr[] = lvServiceClassStrings.split(",");
for (int i = 0; i < lvClassStr.length; i++) {
Class lvServiceClass = Class.forName(lvClassStr[i]);
Object lvServiceProxy = pvServiceManager.createService(lvServiceClass);
bundleContext.registerService(lvClassStr[i], lvServiceProxy, new Properties());
}
}
}
By Client is the description in the META-INF/Manifest.mf too. For example:
Manifest-Version: 1.0 Bundle-Name: CrispyClient Bundle-ClassPath: ., crispy-with-tests-0.6.2.jar, commons-logging.jar, commons-proxy-0.1-SNAPSHOT.jar Bundle-Activator: net.sf.crispy.extension.osgi.CrispyClientActivator Import-Package: org.osgi.framework, test.crispy.example.service Bundle-SymbolicName: CrispyClient Bundle-Version: 1.0.0
A possible implementation from the service consumer:
public class CrispyClientActivator implements BundleActivator {
public void start(BundleContext pvContext) throws Exception {
// first a echo example
String filter = "(objectclass=" + Echo.class.getName() + ")";
ServiceReference[] srl = pvContext.getServiceReferences(null, filter);
Echo lvEcho = (Echo) pvContext.getService(srl[0]);
System.out.println("Echo: " + lvEcho.echo("Hello Crispy ..."));
// second a calculator example
filter = "(objectclass=" + Calculator.class.getName() + ")";
srl = pvContext.getServiceReferences(null, filter);
Calculator lvCalculator = (Calculator) pvContext.getService(srl[0]);
System.out.println("Add 5.3 + 6.3 = " + lvCalculator.add(5.3, 6.4));
}
public void stop(BundleContext pvContext) throws Exception { }
}
Importend:
The Bundle-ClassPath must contain all libraries. In this example can you see the required libraries. The Import-Package part describe the packages from the required services.