1. Bundles
获取Bundle信息接口:BundleContext,方法:
getBundles();获取当前容器中所有的Bundle
getBundle(long bundleId);获取指定Id的Bundle
getBundle();获取的当前Bundle
例如:
BundleContext bundleContext = (...)
Bundle[] bundles = bundleContext.getBundles();
long bundleIdentifier = 12;
Bundle bundle = bundleContext.getBundle(
bundleIdentifier
);
Bundle currentBundle = bundleContext.getBundle();
Accessing general and configuration information about a bundle:
Bundle bundle = (...)
Long bundleId = bundle.getBundleId();
String location = bundle.getLocation();
String symbolicName = bundle.getSymbolicName();
Dictionary<String,String> headers = bundleContext.getBundle().getHeaders();
String bundleName = headers.get(Constants.BUNDLE_NAME);
String bundleVersion = headers.get(Constants.BUNDLE_VERSION);
getResource()和findEntries()方法:
Bundle bundle = (...);
URL specificConfigurationFile = bundle.getResource("META-INF/spring/osgi-context.xml");
Enumeration configurationFiles = bundle.findEntries("META-INF/spring", "*.xml", false);
2. Lifecycle Management
States in a bundle’s lifecycle:
Installed: Bundle is installed within the OSGi container.
Uninstalled: Bundle is uninstalled from the OSGi container.
Resolved: Bundle is installed and all dependencies are resolved.
Starting: Bundle is starting, moving from the resolved to the active state.
Active: Bundle is available to do work within the OSGi container.
Stopping: Bundle is stopping, moving from the active to the resolved state.
例如:
BundleContext bundleContext = (...);
String absoluteBundlePath = (...);
Bundle bundle = bundleContext.installBundle(absoluteBundlePath);
int state = bundle.getState();
bundle.start();
int state = bundle.getState();
3. Properties
Access global properties which are defined by the OSGi Container via the BundleContext’s
getProperty method。
Several property keys are standardized in the OSGi specification and are present in the Constants
interface—these constants can be used as parameters of the getProperty method:
■ Constants.FRAMEWORK_VERSION and Constants.FRAMEWORK_VENDOR—The version
and name of the OSGi container used
■ Constants.FRAMEWORK_LANGUAGE—The language used by the container to implement
components
■ Constants.FRAMEWORK_OS_NAME and Constants.FRAMEWORK_OS_VERSION—The name and
version of the operating system that’s running the container
■ Constants.FRAMEWORK_PROCESSOR—The name of the processor corresponding to the host
computer
例如:
String containerName = bundleContext.getProperty(Constants.FRAMEWORK_VENDOR);
其中:如果在OSGi容器中搜索不到指定的属性,将搜索JVM的系统属性。
4. Event Support
OSGi’s event support at the bundle level allows code to be notified of every update to the state
of a component during its lifetime. It provides two ways to handle these events:
■ An asynchronous method using the BundleListener interface
■ A synchronous method using the SynchronousBundleLister interface
其中:The SynchronousBundleListener interface extends BundleListener without adding anything
more.
Handling a bundle event in an asynchronous listener:
public class SimpleBundleListener implements BundleListener {
public void bundleChanged(BundleEvent event) {
int type = event.getType();
String symbolicName = event.getBundle().getSymbolicName();
if (type==BundleEvent.STARTED) {
System.out.println("Bundle "+symbolicName+" started...");
} else if (type==BundleEvent.STOPPED)
System.out.println("Bundle "+symbolicName+" stopped...");
}
}
}
注册该监听器:使用BundleContext的addBundleListener方法。
5. Persistent Storage Area
Interacting with the persistent storage area of a component:
BundleContext bundleContext = (...)
File directory = bundleContext.getDataFile("/data");
if (!directory.exists()) {
directory.mkdir();
}
File file = bundleContext.getDataFile("/data/test.txt");
FileWriter writer = null;
try {
writer = new FileWriter(file, true);
writer.write("my content");
} catch(IOException ex) {
(...)
} finally {
closeWriter(writer);
}
6. BundleActivator
Registering and unregistering services with a BundleActivator:
public class SimpleActivator implements BundleActivator {
(...)
public void start(BundleContext context) {
registerServices(context);
}
public void stop(BundleContext context) {
unregisterServices(context);
}
}
其中该Activator 需要在MAINFEST.MF文件中通过Bundle-Activator Header定义。
7. Service support in OSGi
The OSGi services feature is based on the service registry, which provides nameand property
-based lookup, registration, and management of all service instances registered in the container.
It also can be used to notify components when changes occur, to prevent errors from occurring.
7.1 Providing Service
使用BundleContext的registerService()方法,该方法返回ServiceRegistration,该方法有 一下参数:
(1) clazz or clazzes: 一个或几个名字用来注册和 识别服务。 在OSGi中,这些名称对应的是 服务类的名称,
或者,如果是基于接口的编程,则是 实现的接口的名称 。 类型检查时将使用这些名字 。 具有相同名称的多哥服
务可共存于OSGi服务注册表 。
(2) service:The implementation of the service itself, or an instance of the ServiceFactory interface.
(3) properties: A set of properties to associate with the service. These properties must be of
type String. The value can be null if there are no properties. And the OSGi container automatically
inserts two additional properties that are related to the service identifier (service.id) and the
classes used for the registration (objectClass).
Simple implementation of the HelloWorldService interface:
public class SimpleServiceActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
String serviceName = "com.manning.sdmia.osgi.services.providing.service.SimpleService";
SimpleServiceImpl service = new SimpleServiceImpl();
Properties properties = new Properties();
properties.setProperty("creationDate",(new Date()).toString());
this.serviceRegistration= bundleContext.registerService(serviceName, service,
serviceProperties);
}
public void stop(BundleContext bundleContext) throws Exception {
if (this.serviceRegistration!=null) {
this.serviceRegistration.unregister();
}
}
}
Simple implementation of the ServiceFactory interface:
public class SimpleServiceFactory implements ServiceFactory {
public Object getService(
Bundle bundle, ServiceRegistration registration) {
String bundleSymbolicName = bundle.getSymbolicName();
if (bundleSymbolicName.startsWith("com.manning")) {
return new SimpleForManningServiceImpl();
} else {
return new SimpleServiceImpl();
}
}
public void ungetService(Bundle bundle,
ServiceRegistration registration, Object service) {
}
}
Note that implementations of this interface are used by the container and therefore must be
thread-safe. The instance returned by the getService method is cached by the framework until
the bundle releases the service.
7.2 Using Service
(1) Basic Approach
1. Get a ServiceReference instance for the service, based on the service name from the BundleContext instance.
2. Get the service instance itself, based on the BundleContext instance and the previously obtained ServiceReference instance.
Consuming an OSGi service:
String serviceName = SimpleService.class.getName();
ServiceReference serviceReference = null;
try {
serviceReference = bundleContext.getServiceReference(serviceName);
if (serviceReference!=null) {
SimpleService service= (SimpleService)bundleContext.getService(serviceReference);
service.test();
}
} catch(Exception ex) {
(...)
} finally {
if (serviceReference!=null) {
bundleContext.ungetService(serviceReference);
}
}
其中:ServiceReference instances can also be obtained by using bundle instances, which provide
the following methods:
■ getRegisteredServices—Returns the list of services registered by the bundle
■ getServicesInUse—Returns the list of the bundle services used by other bundles
(2) Service Tracker
需现在MANIFEST.MF中Import-Package:org.osgi.util.tracker,Using the ServiceTracker:
String serviceName = SimpleService.class.getName();
ServiceTracker serviceTracker = null;
try {
serviceTracker = new ServiceTracker(
bundleContext, serviceName, null);
serviceTracker.open();
SimpleService service = (SimpleService) serviceTracker.getService();
service.test();
} catch(Exception ex) {
(...)
} finally {
if (serviceTracker!=null) {
serviceTracker.close();
}
}
7.3 Service Event Support
使用ServiceLinstner接口,A ServiceListener implementation handling service events:
public class SimpleServiceListener implements ServiceListener {
private String getServiceName(ServiceEvent event) {
String[] objectClass = (String[])event.getServiceReference().getProperty("objectClass");
return objectClass[0];
}
public void serviceChanged(ServiceEvent event) {
int type = event.getType();
String serviceName = getServiceName(event);
String symbolicName = event.getServiceReference().getBundle().getSymbolicName();
if (type==ServiceEvent.REGISTERED) {
System.out.println("Service " + serviceName + " registred by the bundle "
+ symbolicName + "...");
} else if (type==ServiceEvent.UNREGISTERING) {
System.out.println("Service " + serviceName + " being unregistered by the bundle "
+ symbolicName + "...");
} else if (type==ServiceEvent.MODIFIED) {
System.out.println("Service " + serviceName + " modified by the bundle "
+ symbolicName + "...");
}
}
}
注册该监听器:
BundleContext context = (...)
SimpleServiceListener listener = new SimpleServiceListener();
Context.adServiceListener(listener);