To add a new custom configuration type, implement the Configurable interface and register its instance as a service in the OSGi framework.
Implement Configurable
There are two approaches in implementing the Configurable interface to add a new configuration type:
General Principles in Implementing Configurable
In a Configurable implementation, you have to integrate a persistent storage to save the root ConfigNode and its components. The setConfig method of the Configurable implementation should write to the storage and return the status of the operation. The getConfig methods should retrieve the requested data from there.
Usually, a configurable is mapped to entities of a certain type in the OSGi platform. In case there are changes in some of the entities, the associated configurable must be modified accordingly. You can clone the target config node and performs some modification and validation checks upon the contained entries. Then, apply the changes by calling the setConfig method of your Configurable implementation.
Extending BaseConfigurable
The BaseConfigurable class uses the database support of the DB Manager and provides persistence across restarts. It saves every configuration in a separate custom database named after the configuration type.
The BaseConfigurable class provides methods for notification on a configuration change as well as for performing input validation.
ConfigTree gives opportunity to BaseConfigurable inheritors to refine loaded Configuration before return it to the user. The inheritor can remove some of the unnecessary configurations during the load process.
Configuration Update Notification
Implement the configurationUpdated method so as to reflect the behavior of your application when its configuration is changed. Use the int flag argument to get the type of the configuration modification (add, update or remove a configuration node, update a configuration property of an existing configuration node).
Data Validation
The validate method of the MemoryConfigurable class can be used for performing validation to each configuration node that is appended to the existing configuration.
Register the Configurable as a Service
Next, to add support for your configuration type to the Config Tree, register the Configurable implementation instance as a service in the OSGi framework with a registration property Configurable.CONFIGURABLE_TYPE equal to the type of the configuration.
Example Configurable
This listing contains a simple Configurable, based on BaseConfigurable, for the "CustomConfigType" configuration type. When a configuration node is updated in the Config Tree, the configurable simply prints information about the location of the update.
An example of Configurable implementation:
import com.prosyst.mbs.services.configtree.BaseConfigurable;
import com.prosyst.mbs.services.configtree.ConfigNode;
import com.prosyst.mbs.services.configtree.ConfigUtils;
import com.prosyst.mbs.services.configtree.Status;
public class ExampleApplication extends BaseConfigurable {
public static final String MY_CONFIG_TYPE = "CustomConfigType";
public MyConfigurable(String type) {
super(type); }
public Status setConfig(ConfigNode rootNode) {
return super.setConfig(rootNode); }
public void configurationUpdated(String[] changedTree, int flag) {
System.out.println("ExampleApplication [" + getType() + "] updated("
+ ConfigUtils.treeToPath(changedTree) + "). Is config null: "
+ (getConfig() == null ? "YES" : "NO")); } }
This listing below contains the bundle activator for the example Configurable.
A bundle activator registering a Configurable service:
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import com.prosyst.mbs.services.configtree.Configurable;
public class Activator implements BundleActivator {
private BundleContext bc;
private ServiceRegistration reg;
private ExampleApplication app;
public void start(BundleContext _bc) throws Exception {
this.bc = _bc;
// Create an ExampleApplication configurable object and
// register it as a Configurable service
app = new ExampleApplication(ExampleApplication.MY_CONFIG_TYPE);
Hashtable props = new Hashtable();
props.put(Configurable.CONFIGURABLE_TYPE, ExampleApplication.MY_CONFIG_TYPE);
reg = bc.registerService(Configurable.class.getName(), app, props);
}
public void stop(BundleContext bc) throws Exception {
if (reg != null) {
reg.unregister();
reg = null;
app = null;
}
}
}