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.