This document describes the basic modules of the mBS framework.
Contents:
The framework implementation of the mBS is composed of modules each providing separate functionality.
Figure 1: mBS framework architecture.
The Startup module executes the essential initialization and loading of the framework and its modules:
The Boot module is responsible for installing a predefined set of bundles at framework startup.
By default, the Boot module takes the initial bundle set from a boot INI file, which contains bundle intallation instructions (like install, start, stop) in XML format. The boot INI file may also contain the initial start level and required permissions of startup bundles.
The logic of the boot process can be customized by defining a boot extension - such an extension can perform its own installation process instead of the default one. A boot extension can also be used to preserve the default boot logic implying the use of a boot INI, but to load the boot INI from a remote URL since the framework initially locates the boot INI as a resource in the local file system.
Refer to the "Boot INI and Boot Extension" document to get more information on the boot INI features and format.
The Boot module might be disabled by setting the mbs.boot.disableProcessing system property to true.
The mBS framework supports bundle start levels, as defined in the OSGi Start Level Specification. Briefly, the framework starts those bundles which have a start level less or equal to the framework active level. Similarly, it stops installed bundles in level descending order.
The framework active start level is determined through the mbs.startlevel
system property
at startup. Runtime framework and bundle start levels can be changed with the
startlevel text command
or with the mConsole.
Bundle start levels at framework startup are specified in a boot INI, which
sets 5 as initial bundle start level. The framework considers the bundles from the boot INI as system bundles, and all bundles installed after installing those boot bundles - as application bundles. Such application bundles are associated with a special , more restrictive, start level, which is determined as the value of the mbs.applicationBundleStartLevel system property (default is (<highest_level_from_boot_ini>+1)).
Management bundles can use the OSGi Start Level service of the System Bundle to dynamically change the framework active level and the start levels of bundles.
The Bundle Manager manages the installation and the life cycle of bundles. It loads bundles from the ready storage if available or installs the bundles defined in the boot INI file. Next, loaded bundles are activated according to their start level.
The Bundle Loader module implements the
com.prosyst.mbs.framework.classloader.ClassProvider interface and the
framework uses it for loading the classes of bundles.
There are modifications of the bundle loader for security mode of the framework, and for working with bundles packed in JXE files and in Tao native format.
You can define a custom bundle loader by providing a class that implements the com.prosyst.mbs.framework.classloader.ClassProvider interface and extends the java.lang.ClassLoader class. The loader class must have a constructor with a single argument com.prosyst.mbs.impl.framework.BundleLoader. Your bundle loader implementation can call the generic BundleLoader to retrieve useful bundle management utilities.
Finally,
to make the framework
use your loader, set the mbs.loader.type system property to custom and use the mbs.loader.class one to specify the name of the class implementing ClassProvider.
Note: As the BundleLoader class interface is considered as internal and is not included in the API documentation, contact ProSyst for more information on their structure and usage.
The Package Manager module manages package dependencies between the bundles in the framework.
Tip: There are some useful issues about the Package Manager in the "Issues" document.
The Service Manager handles service-related operations in the framework, such as service registration and retrieval.
The Event Manager manages the listener registration and cares to send events synchronously or asynchronously (in a separate event delivering thread).
The Handlers Manager module implements the OSGi URL Handlers Service Specification. It is responsible for extending the Java runtime with new URL schemes and content-types, provided, respectively, by URL Stream Handler and Content Handler services in the framework.
Due to differences between the URLStreamHandler class in JDK 1.2.x,
JDK1.3.x and CDC/Foundation, to enable the correct work of the Handlers Manager:
The ProSyst Security Manager extends java.lang.SecurityManager
to make native libraries work on JDK1.1 compatible VMs. This manager is also
needed by the Security module.
The ProSyst Security Manager also has some additional functions not related directly to the Java security model:
If resource management is disabled, then threads are not created in bundle-specific thread groups.
The features of the ProSyst Security Manager are available in the following cases:
mbs.sm system property is set true.mbs.sm system property is not specified but resource management is turned on by setting the mbs.resman.enabled system property to true. The Security module is responsible for security-related operations. It works
with the security models of Java 2 and PersonalJava. The security module
is activated if the ProSyst Security Manager is on (if one of the system properties mbs.sm or mbs.resman.enabled has value true) and the mbs.security property has value different from none.
In addition, this module implements the following services of the System Bundle:
org.osgi.service.permissionadmin.PermissionAdmin) and ProSyst Permission Admin (com.prosyst.mbs.framework.permissionadmin.PermissionAdmin)org.osgi.service.condpermadmin.ConditionalPermissionAdmin) and ProSyst Conditional Permission Admin (com.prosyst.mbs.framework.condpermadmin.MbsConditionalPermissionAdmin) You can develop a custom Security module by implementing the com.prosyst.mbs.framework.security.Security interface, setting the mbs.security system property to custom and declaring the implementation class through the mbs.security.class system property.
The Certificate Manager module provides means for checking the trust of certificates against a certificate storage. The Certificate Manager is available only if the mbs.certificates system property is true.
For more information about the functionality that the Certificate Manager offers, refer to the "Certificate Manager" document.
The System Bundle registers as services modules that are part of the framework and can be used by management bundles for execution of administration operations. The bundleID of the System Bundle is always 0. Its lifecycle cannot be managed as conventional bundles, because its state is tightly bound to the state of the framework. For example, to stop the System Bundle means to shut down the framework and to update it - to restart the framework (possible through the mBedded System Agent).
It is possible via system properties to add to the System Bundle export-packages, activators and configurations, placed in the framework JAR or added to the classpath. This saves great part of the resources, consumed for activation of bundles, as no bundle objects and class loaders are created.
For more details about the features of the System Bundle, refer to the "System Bundle" document.
The Storage module is responsible for the operations with files - ZIPs, JARs,
native libraries, and for providing a java.io.File object when
a bundle calls getDataFile from BundleContext.
The Storage module has three implementations:
java.io packagejava.io package with Connector
support Operates on the standard I/O library from the java.io package.
This storage works with ZIP files through the java.util.zip API.
You can use the ProSyst ZIP implementation as well, which is pure Java.
This type of storage is activated through the mbs.storage.impl
system property with value com.prosyst.mbs.impl.framework.module.storage.file.StorageImpl.
With this type of storage you can benefit from the following features:
Uses the I/O facilities from the java.io package and supplies
a Connection Factory for the Connector Version
of the framework. This storage works with ZIP files through the API from the
java.util.zip package. You can use the ProSyst ZIP implementation
as well, which is pure Java.
This type of storage is activated through the mbs.storage.impl
system property with value com.prosyst.mbs.impl.framework.module.storage.file.StorageImpl.
Uses the MMFS module of the framework and provides a Connection Factory for
the Connector Version of the framework.
You activate the Storage on top of MMFS with Connector Support by setting
the mbs.storage.impl system property to com.prosyst.mbs.impl.
framework.module.storage.mm.StorageImpl.
The storage on top of MMFS uses the ProSyst support of ZIP files.
You can disable the support of native libraries by setting value false
to property mbs.storage.mm.nativelibs.
You can provide a custom storage by implementing the com.prosyst.mbs.framework.storage.Storage
interface and declaring it with the mbs.storage.impl system property.
Developers may contact ProSyst
in order to receive more details about storage implementation.
The MMFS is intended mainly for gateway platforms that are not capable of persistent
storage, do not have hierarchical file system, or provide incomplete support
of the java.io package. You should specify appropriate values to
the system properties mbs.storage.mm.cluster.count and mbs.storage.mm.cluster.size,
which determine the number and size of data clusters to segment an MMFS into.
All currently supported MMFS modifications can load data from a remote built
storage represented as a storage.mbs file. The remote URL, where the
corresponding storage.mbs is accessible, should be specified with the
mbs.storage.url system property.
There are two implementations of MMFS, which are described below.
All information is kept in a single java.io.RandomAccessFile object,
which is physically situated on an external data bearer - Hard Disk Drive, flash,
etc. You activate it by setting file to the mbs.storage.mm.type
system property.
The File MMFS uses a locally stored storage.mbs. The name/location of
this file can be altered with the mbs.storage.mm.file.name system
property.
Storage on RAM memory which is persistent only for the current framework session,
that is on framework restart data is lost. You activate this MMFS implementation
by setting value ram to the mbs.storage.mm.type system
property.
You can use ProSyst's MMFS, but change the way in which the external bearer
is accessed. In such case implement the com.prosyst.mbs.impl.services.mm.logic.MemoryModel
interface. Then set the mbs.storage.mm.type system property to
custom and declare the implementation class with the system property
mbs.storage.mm.impl. For more details, you can contact ProSyst.
The mBS framework offers a flash manager, which can be used for transferring bundle data files from a flash file system, which is persistent but with slow write access, to a temporary storage on a RAM file system, which is not persistent but is with much faster access. After the operations with files on the RAM are done, they can be flushed from the RAM to the flash storage overwriting the original files. In this way the benefits of both flash and RAM storage can be used.
The flash manager is available as a System
Bundle service in the Standard
Version of framework. It can be configured with the mbs.storage.ramroot,
mbs.storage.flashmgr.replace, mbs.storage.flashmgr.flatram
and mbs.storage.norename system
properties. Note that the flash manager service is registered only if the
mbs.storage.ramroot property is set.
The framework contains own class loader, called the Framework Loader, which should be used when working with extension bundles.
It is not needed to restart the framework when installing framework extension bundles - the classes from the extension are internally added to classpath of the framework. Yet, in the case of a boot classpath extension, the requirement to restart framework remains. In this case, when the Framework Loader is enabled, the framework will add the extension to the bootclasspath and will restart itself automatically by using the proper command line from the JVM-specific starting script.
To make the framework use the Framework Loader for loading framework core and extension classes, prior to starting the framework set the mbs.customFrameworkLoader system propery to true in the framework starting script (see "Starting the Framework"). The scripts in the Framework Professional Edition Package distribution activate the Framework Loader by default.
Additionally, to have support of extension bundles, the properties org.osgi.supports.framework.fragment, org.osgi.supports.framework.extension and org.osgi.supports.bootclasspath.extension should also be set to true in the starting script or in framework properties file (default.prs).
Tip: The framework writes the locations of bootclasspath extension bundles into a script file, called bootcp.set, in the working directory (i.e. in bin/vms/<vm_name>) and on startup includes the script file content in the bootclasspath.
Tip: Use the mbs.noFwRestart system property to prevent the framework from restart when installing or updating bootclasspath extension.
Note: If you have launched the framework by writing a custom command line, the automatic restart feature of the Framework Loader will not be available.
The Fault Manager module can be used to signal fault situations which depending on the Fault Manager implementation may be resolved through device reset, restart of the framework process, etc., so as to avoid further damage.
The Fault Manager is a customizable module - different implementations can exist, each reflecting a specific fault solution method.
By default, there is no active Fault Manager implementation in the framework. Such can be specified with the mbs.fm.class system property.
The default Fault Manager implementation that the framework contains is com.prosyst.mbs.impl.framework.module.fm.FaultManagerImpl. It records fault messages in a file.
The active Fault Manager implementation can be accessed as a System Bundle service. To reduce development efforts, bundles can conveniently use the log reference utility of the ProSyst Util Bundle to indicate fault situations.
Bundles as well as the framework itself can use the Tracer module to send log messages about their current status or about the operations being executed to a remote visual application, such as the mConsole, or to preserve the messages for future reviewing.The remote visual application can then filter the information according to user preferences.
The Tracer is able to send message in synchronous and asynchronous manner. It is available as a System Bundle service and can be used to provide tracing information about a module. Nevertheless, it is recommended that bundles use the Tracer module through the log reference utility of the ProSyst Util Bundle.
By default, the Tracer module is turned off. It can be activated by setting
the mbs.tracer.impl system property to default.
Messages are carried to their remote destination over a tracer transport - TCP, UDP, etc. Initially, TCP is supported.
It is possible to provide a custom Tracer transport - it must implement the
com.prosyst.mbs.framework.tracer.TraceRemoteLogger interface and
then set it with the mbs.tracer.transport system
property.
You can provide a custom Tracer. In such case it is necessary to implement
the org.osgi.framework.ServiceFactory interface by providing a
default constructor and instances of com.prosyst.mbs.framework.tracer.TraceService
in the getService method. Then, the ServiceFactory
implementation class should be specified with the mbs.tracer.impl
system property.
Bundles operating in the context of the mBS framework can define bundle requirements for system resources, permissions and runtime platforms. Refer to the "Bundle Requirements" document for more details.
The mBS framework provides means for enhanced management of system resources required and consumed by bundles. Refer to the "Resource Management" document for more details.
The Framework Access module provides access to some of the framework's powerful features, such as:
This module is available as a service of the System Bundle and is intended mainly for internal use.
The Framework Measurement module is capable of measuring consumption of specific memory type on Java level and on OS native level. See the "Framework Measurement" document for further details.
The Transaction Manager module provides transactional behavior to applications. It allows applications to manage transactions (begin, commit, rollback, etc.) as well as to add transactional logic to existing transactions. The Transaction Manager is available as a service under the org.mbs.services.transaction.TransactionManager interface in case the mbs.tm.class system property is set to a Transaction Manager implementation class name. The default implementation of the Transaction Manager is com.prosyst.mbs.impl.framework.module.transaction.TransactionManagerImpl.
You can implement your own Transaction Manager (org.mbs.services.transaction.TransactionManager) and specify its class name under the mbs.tm.class property prior to starting the framework.
When a bundle is updated or uninstalled, there are two ways to handle the bundles that depend on it ( bundles that import packages from this bundle):
refreshPackages on
the Package Admin service.The update mode can be changed at runtime from the framework console through the updatemode command. See "Framework Commands" for more details about the commands available in the framework console.
The framework allows you to control the way in which bundles export packages
and are resolved - after installing a bundle or before a bundle is started.
This is done through the system property mbs.bundles.resolve.
If this property is set to true (the default is false), after
installing a bundle the framework will try to resolve it (this includes
exporting its packages in the framework).
A resolve check can be made in three other cases:
start method is called.getState method for the bundle is called.The Storage on top of java.io is capable of using factory and dynamic storage.
A factory storage keeps an initial set of bundles with their archives, native libraries and data files, which cannot be changed by mBS's OSGi framework. In this way, the framework can easily restore its initial state in case of a fault.
Dynamic storage (default) is defined to include data for bundles installed or updated through the OSGi Framework API. As this storage is supposed to keep frequently changing data, it can be placed on a special R/W file system (e.g. RAM or flash).
mBS's OSGi framework treats bundles included in a factory storage as installed from file as their JARs remain at their original location, and only their manifests and related data files are copied to the framework storage. The factory storage keeps the original locations of its bundles in a file (f.st) so that they can be located at startup. Bundles can be placed in a common directory or in different ones depending on the system requirements.
In addition, if explicitly specified and if the installed bundle JAR file is originally located in a directory called bundles, the bundle's manifest and data files may be saved to the parent directory of the bundles one within a subdirectory, called data, and not be placed in the default framework storage location.
If a bundle changes its data files or is updated through the OSGi Framework API, the changes are written into dynamic storage and thereafter the data from dynamic storage is used. The bundle is not considered as installed from file anymore, but as regularly installed one.
Dynamic storage is with higher priority than factory storage – if there is data in both storages for a bundle, the framework will use the one from dynamic storage. If a bundle is uninstalled, its data will be deleted from dynamic storage.
Factory storage should be explicitly modeled by adding installed from files bundles to the framework, which as a result will produce the appropriate storage structure and content. Installing bundles from factory storage should be done in a special way not defined by the OSGi Framework Specification - at framework runtime through an option of the fw.install command and at framework startup through the boot INI file.
When started with Storage on top of java.io, the framework supports a mechanism for tamper protection of its storage. In order to avoid tampering with stored bundles and specially with extension bundles, when a bundle is installed in the framework and is stored outside a "trusted" directory, the framework calculates its CRC checksum and saves it persistently. When the framework is restarted, it recalculates the checksum and compares the new value with the stored one. Bundles whose old checksums do not match the new ones, are removed from the framework.
The trusted storage directory is determined as the value of the mbs.storage.trustedRoot system property.
If you are using the J9 VM and the Standard Version of the framework, you can convert the framework JAR to a JXE file and pack your bundles in JXE files, instead of in JARs. This increases the size of the framework and bundles, but makes them faster to load.
Tip: For more details about starting the framework via its JXE, refer to "Starting the Framework on J9".
To be able to use JXE bundles, before starting the framework set the system
property mbs.loader.type to jxe22
for J9 2.2 and J9 2.3.
The main goal of watchdog feature is to prevent from the following situation - if during initial framework startup/shutdown a bundle from the initially-loaded set hangs in the start or stop method of its activator, the whole framework will not start or stop correctly. The watchdog enables initial startup and shutdown of the framework in a separate thread with defined timeout (mbs.core.timeout) for starting and stopping of each bundle. The watchdog can be turned on (default) and off by using the mbs.watchdog system property.
It is possible to limit the number of installed bundles, registered services and listeners (defined in the OSGi Framework Specification). These limits take effect when the following methods are invoked:
BundleContext.installBundle – If the bundles limit is
reached (and the bundle is not already installed), a BundleException
is thrown. BundleContext.registerService – If the services limit
is reached, an IllegalStateException is thrown.BundleContext.addXxxListener – If the listeners limit
is reached, an IllegalStateException is thrown.The number of bundles, services and listeners are respectively defined with
the mbs.bundle.count, mbs.service.count and mbs.listener.count
system properties. By default, no limits are imposed.
Some platforms do not offer a console, or the console has a small buffer. On such platforms it is better to redirect the system output of the framework to a file or to a remote console.
The remote console is a simple application that
opens a TCP/IP socket on port 2000 and writes in the System.out all data received from the framework as well as forwards all data entered in the System.in back to the framework. Tune the input and output settings through the input and output
system properties.
The framework contains a dispatcher for log messages which prints in the system output logs by arranging them in a queue. This allows the framework and bundles to log information in the runtime console by means of non-blocking method calls. The use of the log dispatcher in the framework can be activated with the mbs.usedispatcher system property.