System Bundle

The System Bundle is provided by the mBS framework and delivers to bundle developers important system functions available mainly through the framework.

Contents:


Bundle Information

Bundle JAR

The System Bundle has no JAR file because its functionaly is provided by the framework itself.

Import

The System Bundle imports no packages.

Export

Package Content
com.prosyst.mbs.framework.access The Framework Access service for access to special features delivered by the framework.
com.prosyst.mbs.framework.certmanager The Certificate Database service for checking the trust of certificates against Java 2 keystores.
com.prosyst.mbs.framework.event The Event Thread utility for asynchronous event delivering and listener management.
com.prosyst.mbs.framework.fm The Fault Manager service for managing faults.
com.prosyst.mbs.framework.logdispatcher The Log Dispatcher for added queued log messages.
com.prosyst.mbs.framework.packages The ProSyst extension of the OSGi Package Admin Service
com.prosyst.mbs.framework.permissionadmin The ProSyst extension of the OSGi Permission Admin Service
com.prosyst.mbs.framework.resman The Resource Manager service
com.prosyst.mbs.framework.resman.j9 The J9-specific extension of the Resource Manager service
com.prosyst.mbs.framework.sbctx The SBCtx utility for accessing the bundle context of the System Bundle.
com.prosyst.mbs.framework.tracer The Tracer service
com.prosyst.security.domain The expiration certificate reader utility for checking if a specific evaluation license has expired. The utility is intended for internal use only.
com.prosyst.util.breq The Bundle Requirement utility containing useful methods for resource management
com.prosyst.util.hash Hashtable utilities
com.prosyst.util.io The I/O utilities for enhanced object serialization and remote access
com.prosyst.util.jar The JAR utility for reading the content of a JAR file.
com.prosyst.util.pid The process utility providing access to OS native processes. For internal use only.
com.prosyst.util.pool The object pool for creating reusable objects
com.prosyst.util.propertiesfile The Resource Bundle utility
com.prosyst.util.security The security utility, which helps security management
com.prosyst.util.string The char buffer utility for optimized string buffering
com.prosyst.util.text The date format utility for formatting and parsing dates in compliance with the most widely used formats
com.prosyst.util.time The time utility for high-resolution time measurement
javax.microedition.io The J2ME Connection Framework API
org.mbs.services.transaction The Transaction Manager service
org.mbs.services.transaction.file The file transaction utility
org.osgi.framework The OSGi Framework API
org.osgi.service.condpermadmin The OSGi Conditional Permission Admin Service
org.osgi.service.packageadmin The OSGi Package Admin Service
org.osgi.service.permissionadmin The OSGi Permission Admin Service
org.osgi.service.startlevel The OSGi Start Level service
org.osgi.service.url The OSGi URL Handlers API
Packages Exported Only for the Connector Version of the Framework
org.mbs.services.io The ProSyst extension to the OSGi Connector service which allows you to receive events about connections
org.osgi.service.io The OSGi Connector Service API.
Packages Exported Only for the Standard Version of the Framework
com.prosyst.mbs.framework.flash The Flash Manager service for editing data files on RAM and storing them on flash. Exported only by the Standard Version of the framework.

Services

Start Level Service

The Start Level service can be used by admin bundles to get and/or change the active start level of the framework as well as modify the start levels of bundles. The Start Level service is defined by the OSGi Start Level Specification and other bundles can access it through the org.osgi.service.startlevel.StartLevel interface.

In brief, the framework starts only those bundles whose start levels are less or equal to the framework active start level. In this way, the framework enables the definition of specific startup sequences of bundles. This option brings many benefits, such as the introduction of bundle priorities, preliminary handling service dependencies, etc.

There are two types of bundle start levels - initial, assigned to the bundle when it is first installed, and active start level, assigned to the bundle after it is installed for the first time.

More information about the concept of start levels and about the usage of the Start Level service is available in OSGi Start Level Specification.

Package Admin Service

The Package Admin service allows bundles of admininistration type to trace what packages are exported/imported and by which bundles. Other bundles can access the Package Admin service through its registered interfaces: org.osgi.service.packageadmin.PackageAdmin, which is defined by OSGi Package Admin specification, and com.prosyst.mbs.framework.packages.PackageAdmin, which an extension by ProSYst which adds methods for remote transfer of information about available packages in the framework.

The service basic concepts and terms are specified by the OSGi Alliance in the Package Admin Service Specification.

In general, the Package Admin service allows to retrieve:

  import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;

public class PackageAdminTester implements BundleActivator {
ServiceReference pAdminRef = null;
PackageAdmin pAdmin = null;
String servName = "org.osgi.service.packageadmin.PackageAdmin";

public void start(BundleContext bc) {
// Calling the Package Admin service
pAdminRef = bc.getServiceReference(servName);
if(pAdminRef != null) {
pAdmin = (PackageAdmin) bc.getService(pAdminRef); }
// Getting all exported packages in the framework
ExportedPackage[] packages = pAdmin.getExportedPackages((Bundle)null);
for(int i=0; i< packages.length; i++) {
// Searching for the org.osgi.service.http package
if((packages[i].getName()).equals("org.osgi.service.http")) {
// Operations on a package match
listPackages(packages[i]);
}
}
}

public void stop(BundleContext bc) {
bc.ungetService(pAdminRef);
}

// This method prints in the system output the bundle that
// exports the passed package as well as the bundles that import it
public void listPackages(ExportedPackage ePackage) {
Bundle httpBundle = ePackage.getExportingBundle();
System.out.println("Bundle that exports the "
+ ePackage.getName() + " package:");
System.out.println("\t" + httpBundle.getHeaders().get("Bundle-Name"));
Bundle[] userBundles = ePackage.getImportingBundles();
for(int j=0; j<userBundles.length; j++) {
System.out.println("Bundle that imports the "
+ ePackage.getName() + " package: ");
System.out.println("\t" + userBundles[j].getHeaders().get("Bundle-Name"));
}
}
}
Listing 1.1: Using the OSGi Package Admin Service.

For more information about the OSGi Package Admin service, refer to the OSGi Package Admin Service Specification, and for the ProSyst extension - in the API documentation.

Certificate Manager

The Certificate Manager service provides means to verify a certificate chain against a certificate storage, as described in the "Certificate Manager" document. The service becomes available when the mbs.certificates system property is true.

The Certificate Manager service is represented by the com.prosyst.mbs.framework.certmanager.CertificateManager interface. The service offers methods for getting the distinguished names (DNs) of the owners whose certificates are saved in the database, for getting only the trusted certificate chains in a collection of certificate chains (e.g. the certificate chains used to sign a bundle JAR file), and for checking if a certificate is trusted and if a certificate is available in the database.

Tip: You can conveniently use the ProSyst JAR utility for getting the trusted certificates a bundle JAR is signed with according to the content of the certificate storage.

Permission Admin Service

The Permission Admin Service is specified by OSGi and is available when the framework is started with security. The service is published under the org.osgi.service.permissionadmin.PermissionAdmin and com.prosyst.mbs.framework.permissionadmin.PermissionAdmin interfaces. The org.osgi.service.permissionadmin.PermissionAdmin is termed by the OSGi Permission Admin service. The ProSyst extension to the OSGi Permission Admin contains methods for retrieving the trusted certificate chains and the certificates of a signed bundle JAR, as well as for matching the match the distinguished name of a certificate against a specified pattern.

The Permission Admin Service allows bundles of administration type to assign permissions to bundles. These permissions are based on the location of the bundles and may remain after framework restarts. The bundle location/permission collection pairs are kept in a permission table with locations being the keys. If there is no table entry for the location of a bundle, then a default set of permissions is used for check.

The assigned permissions are represented by the org.osgi.service.permissionadmin.PermissionInfo objects. Each PermissionInfo instance wraps the permission type (that is, a subclass of java.security.Permission), the permission name and the permission actions. Note that the permission type should have a constructor with two arguments - the permission name and actions.

To be able to set permissions dynamically at bundle installation, you may implement org.osgi.framework.SynchronousBundleListener to wait for bundle events associated with bundle installations. Then, you can check the permission of installed bundles and assign new ones before bundles are started. In this way, you do not have to preliminary know what bundles are to be installed.

The code example below assigns org.osgi.framework.PackagePermission with action "import" and org.osgi.framework.ServicePermission with action "get" to each bundle that is installed afterwards. The snippet implements SynchronousBundleListener and in this way, when it is notified about a bundle being installed, it dynamically attaches the permissions to the bundle location.

  import org.osgi.service.permissionadmin.PermissionAdmin;
import org.osgi.service.permissionadmin.PermissionInfo;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.framework.BundleEvent;

public class PermissionTest implements BundleActivator,
SynchronousBundleListener {
ServiceReference sRef = null;
PermissionAdmin pAdmin = null;
String sName = "org.osgi.service.permissionadmin.PermissionAdmin";
String permType1 = "org.osgi.framework.PackagePermission";
String permType2 = "org.osgi.framework.ServicePermission";

public void start(BundleContext bc) {
sRef = bc.getServiceReference(sName);
if(sRef != null) {
pAdmin = (PermissionAdmin)bc.getService(sRef);
// Registering the SynchronousBundleListener
bc.addBundleListener(this);
} else {
System.out.println("The Permission Admin Service is not active.");
}
}

public void stop(BundleContext bc) {
bc.removeBundleListener(this);
bc.ungetService(sRef);
}

// Implemented from SynchronousBundleListener
public void bundleChanged(BundleEvent bEv) {
if(bEv.getType() == BundleEvent.INSTALLED) {
// Defining permissions
PermissionInfo[] perms = new PermissionInfo[2];
perms[0] = new PermissionInfo(permType1, "package_to_import", "import");
perms[1] = new PermissionInfo(permType2, "service_to_get", "get");
String location = bEv.getBundle().getLocation();
// Setting permissions to the locations of installed bundles
pAdmin.setPermissions(location, perms);
System.out.println("Assigning permissions to: " + location);
}
String[] locs = pAdmin.getLocations();
for(int i=0; i < locs.length; i++) {
System.out.println("Locations with assigned permissions: " + locs[i]);
}
}
}
Listing 1.2: Using the OSGi Permission Admin Service.

Note: The Permission Admin Service can be used only by bundles that own org.osgi.framework.AdminPermission.

A more detailed description of the OSGi Permission Admin service is available in the OSGi Permission Admin Service Specification and of the ProSyst extension - the API documentation.

Conditional Permission Admin

The Conditional Permission Admin service is defined by the OSGi Service Platform Core Specification release 4. The service extends the concepts of dynamic permission definition of the OSGi Permission Admin service by introducing conditional permissions. It is registered under the org.osgi.service.condpermadmin.ConditionalPermissionAdmin basic interface and under the com.prosyst.mbs.framework.condpermadmin.MbsConditionalPermissionAdmin ProSyst-defined on, and is available only if the framework is started with security.

A conditional permission is associated with a set of conditions and a set of permissions. The permissions of the conditional permission become granted when all associated conditions become satisfied.

Bundle developers can defined local permissions which define the maximum set of permissions that a bundle should have. This allows for better restriction of permissions as well as for auditing the functions that the bundle has. The local permissions of a bundle should be placed in a file, called permissions.perm and placed within the OSGI-INF directory of the bundle JAR file. Each permission definition should be in a new line following the encoded form supported by its class definition. If the local permission resource is not included in a bundle, the framework will set java.security.AllPermission as local permissions for the bundle.

Tip: You can turn off the processing of local permissions by using the mbs.disableLocalPermissions system property.

The Conditional Permission Admin Service Specification introduces two standard conditions - bundle location condition and bundle signer condition. The bundle location (org.osgi.service.condpermadmin.BundleLocationCondition) condition is an analog to the permission definitions used in the OSGi Permission Admin service. The bundle signer condition is related to the principal distinguished name of the certificate the bundle is signed with.

When adding a conditional permission to the Conditional Permission Admin service, you should supply info objects for required conditions and permissions. The encoded string of a condition info should have the format:

[condition_class_name "condition_arg" "condition_arg"]

and the one of a permisison info

(permission_class_name "permission_name" "permission_actions")

The concept of default permissions from the Permission Admin service is still preserved though slightly modified - as default permissions the Conditional Permission Admin treats those conditional permissions which do not have conditions.

In addition, you can explicitly force evaluation of the conditional permissions of a specific bundle by using the methods of the com.prosyst.mbs.framework.condpermadmin.MbsConditionalPermissionAdmin service interface.

Privileged Threads Manager

Through the Privileged Threads Manager service, registered when the framework is started with security, you can mark the current thread as privileged so that no permission checks on it are made until you take off the security privilege.

The interface of the Privileged Threads Manager service is com.prosyst.mbs.framework.permissionadmin.PriviligedThreadsManager. The method to make the current thread privileged is markCurrent. To make the thread not privileged again, use the unmark method.

Tracer Service

Through the Tracer Service bundles can send log messages to a remote client so that their operation can be traced. A tracing message can identify the module and submodule that caused its generation.

The Tracer Service implements the com.prosyst.mbs.framework.tracer.TraceService interface and is available only if the mbs.tracer.impl system property is set.

Note: It is recommended that bundles use the functionality of the Tracer Service indirectly through the log reference utility of the ProSyst Util Bundle.

Resource Manager

Based on bundle's resource requirements and framework default values for those resources, a resource manager monitors each bundle's allocations, and when they reach undesired limits it may either refuse to give any more resources or to stop the bundle. Each bundle is assigned a resource context, which is used to track the resource requests of the bundle.

Tip: To get more information about the resource manager, refer to the "Resource Management" document.

To be able to benefit from the resource manager features, you should first turn it on with the mbs.resman.enabled system property.

The resource managers provided in mBS framework register as a service under the com.prosyst.mbs.framework.resman.ResourceManager interface. The service interface provides methods for monitoring resource requirements and resource allocations, and for switching between resource contexts of objects and bundles.

The ResourceManager methods related to current resource allocations and requirements (specified in a requirement XML) of a bundle are respectively getResourceAllocations and getResourceRequirements. With the getSystemDefaults method you can view the general resource restrictions for bundles in the framework.

The switchToXXX methods enable a bundle to switch between resource contexts. Call the getCurrentContextName method to get the currently active resource context.

Note: The resource managers for J9, activated with the mbs.resman.class system property, also implement the com.prosyst.mbs.framework.resman.j9.MemoryCommands service interface, which is used for the memory text command of the info group (see "ProSyst Util Bundle -> System Service" for more details about this command usage).

IO Connector and Connection Factory Services

The OSGi IO Connector service of the System Bundle is registered when the Connector Version of the framework is used. Its interface is org.osgi.service.io.ConnectorService and its principles of work are the same as the ones of the OSGi IO Connector service in the Connector Bundle.

When using the Connector Version of framework, the System Bundle registers a Connection Factory service (org.osgi.service.io.ConnectionFactory) for the file scheme. The operation of the Connection Factory differs according to the type of used storage. Refer to the Connector Version description for more details about the service usage and concepts.

Flash Manager

The Flash Manager service is available only if the Standard Version of the framework is used and the mbs.storage.ramroot system property is set. The main purpose of the Flash Manager is to enable bundles to move their data files from a flash persistent storage to a non-persistent RAM storage, which is with faster writer access, and after modifying the files - flush them back to the flash storage.

The interface of the Flash Manager service is com.prosyst.mbs.framework.flash.FlashManager.

To be notified that the flush operation on a data file has been successful, implement the com.prosyst.mbs.framework.framework.flash.FlashListener interface and provide it as a parameter to the flushFile method.

Listing 1.3 contains an example, which writes a data file - test.txt, into the RAM storage. Then writes some data in the file, flushes it. When the file is flushed successfully, the example prints the resulting data file to the system output.

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mbs.framework.flash.FlashManager;
import com.prosyst.mbs.framework.flash.FileListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
public class MyFlusher implements BundleActivator, FileListener {
         
  private ServiceReference refFlashManager; 
  private FlashManager flashManager; 
  final static String SERVICE_FLASHMANAGER = FlashManager.class.getName();
  private BundleContext bc;
  private File flashDataFile;
  private File ramDataFile;
  public void start(BundleContext bc) throws Exception {
    this.bc = bc;
    try { 
      refFlashManager = bc.getServiceReference(SERVICE_FLASHMANAGER);
      if (refFlashManager != null) { 
        flashManager = (FlashManager)bc.getService(refFlashManager); 
        flashDataFile = bc.getDataFile("test.txt"); 
        ramDataFile = flashManager.getFile(flashDataFile);
        if(ramDataFile != null) {
          changeFile();
          flashManager.flushFile(ramDataFile, this); 
        }
      }
    } catch (Exception exc) {
      dump("[MyFlusher]Error in start method: " + exc.getMessage(), exc);
    } 
  }
  public void stop(BundleContext bc) throws Exception {
    if (refFlashManager != null) {
      bc.ungetService(refFlashManager);
    } 
  }
  public static void dump(String str, Throwable t) {
    if (t != null) {
      t.printStackTrace();
    }
  }
  public void flushed(File file) { 
    System.out.println("[MyFlusher]File " + file.getPath() + " flushed.");
    readDataFile();
  }
  private void changeFile(){
    try {
      FileOutputStream ramOut = new FileOutputStream(ramDataFile);
      ramOut.write((new String("[MyFlusher]Data changed on RAM")).getBytes());
      ramOut.close(); 
    } catch (Exception exc) {
      dump("[MyFlusher]Error in modifying file on RAM: " + exc.getMessage(), exc);
    }
  }
         
  private void readDataFile() {
    try { 
      FileInputStream flashIn = new FileInputStream(flashDataFile);
      byte[] buff = new byte[flashIn.available()];
      while(flashIn.read(buff) > 0){
        System.out.println("[MyFlusher]Data flushed : " + new String(buff));
      }
    } catch (Exception exc) {
      dump("[MyFlusher]Error in flushing file: " + exc.getMessage(), exc);
    }
  }
}
Listing 1.3: Using the Flash Manager service.

Fault Manager

The Fault Manager service allows bundles to indicate faults, which are then collected and management by a Fault Manager implementation. The Fault Manager service is available under the com.prosyst.mbs.framework.fm.FaultManager interface.

The service is registered only in case a Fault Manager implementation class is specified with the mbs.fm.class system property. As a value to the mbs.fm.class property you can set the class of the default Fault Manager - com.prosyst.mbs.impl.framework.module.fm.FaultManagerImpl. This Fault Manager saves fault records in a file indicated with the mbs.faultmanager.file system property. This file can contain up to mbs.faultmanager.records and can keep the time each fault occurred if mbs.faultmanager.nodate is false (default).

Bundles can conveniently signal faults to the Fault Manager through the log reference utility of the ProSyst Util Bundle.

Framework Access

The Framework Access service provides access to some special functionality offered by the mBS framework. The Framework Access service is published under the com.prosyst.mbs.framework.access.FrameworkAccess interface name.

The Framework Access service allows you to:

Transaction Manager

The Transaction Manager service allows applications to execute operations in transactions. The service is registered under the org.mbs.services.transaction.TransactionManager interface and is available only if the mbs.tm.class system property is set to a Transaction Manager implementation class name. To have the default Transaction Manager service implementation in the framework, set the mbs.tm.class system property to com.prosyst.mbs.impl.framework.module.transaction.TransactionManagerImpl.

OSGi URL Handlers API

The OSGi URL Handlers Service Specification defines an API for introducing new URL schemes and content-types to the Java runtime of the framework.

In general, developers that want to extend the collection of schemes currently supported in the Java runtime environment, should implement org.osgi.service.url.URLHandlerService interface and register a service under this interface. The service must be registered with the org.osgi.service.url.URLConstants.URL_HANDLER_PROTOCOL property of indicating the new scheme(s).

To introduce support for a custom content-type, the java.net.ContentHandler class must be extended with the getContent method overridden. Next, the custom content handler must be registered as a java.net.ContentHandler service with the URLConstants.URL_CONTENT_MIMETYPE property indicating the new content-type(s).

More information about the OSGi URL Handlers API usage is available in the OSGi Service Platform Specification Release 4.

Utilities

This chapter describes the interfaces and classes that developers can use to ease the development and enhance the performance of their bundles.

Bundle Requirement

The com.prosyst.util.breq.BundleRequirementsUtils class contains a collection of static methods that allows you to retrieve the requirements of a bundle defined in its requirement XML. BundleRequirementsUtils allows you to:

Char Buffer

The com.prosyst.util.string.CharBuffer class is a char buffer utility that can be used instead of StringBuffer. It directly uses char arrays with the exact length and no redundant elements, and avoids the creation of buffer String objects and char arrays with empty elements. In this way, to some extent resource consumption on the framework device is reduced.

Date Format

The com.prosyst.util.text.DateFormat class supports date formats that are most commonly used in most of the Internet communication protocols. In particular, DateFormat supports the date formats specified by RFC 1036, RFC 1123, and by the ANSI standard C asctime() function.

Event Thread

You can extend the com.prosyst.mbs.framework.event.EventThread to provide events to interested listeners asynchronously, that is in a separate event delivering thread. If there is a hanging listener (a listener, which processes events sent by an event dispatcher too long or "hangs" on doing this), a new event delivering thread can be created for the other listeners. The old thread can be stopped and the hanging listener - removed.

The com.prosyst.mbs.framework.event.Queue can be extended to represent the event queue of an EventThread-based event dispatcher.

In addition, the package contains a special listener interface - SystemListener, which a bundle registering framework or/and bundle listener can additionally implement, so that in case the listener is considered as hanging the framework asks the listener to confirm the unregistration of the listener. Otherwise, the framework will directly unregister the listener.

The SystemListener interface must be implemented by the same class implementing org.osgi.framework.FrameworkListener or org.osgi.framework.BundleListener. When the timeout for a listener to return from its frameworkEvent or bundleChanged method expires (it its determined by the value of the mbs.core.timeout system property), the framework will call the timeoutOccured() SystemListener's method. If the timeoutOccured method returns true, the framework will remove the listener from its event subscribers list.

Hashtable

The System Bundle contains helpful classes for associating long and integer values to objects in hashtables. In addition, there is a class that assists writing and reading properties in and from a text file. The com.prosyst.util.hash package keeps all these utilities.

Generally, hashtable facilities are two types - with synchronized methods and with not synchronized methods.

Class Synchronization Key Format Value Format
HashIntObjNS No int java.lang.Object
HashIntObjS Yes int java.lang.Object
HashObjIntNS No java.lang.Object int
HashObjIntS Yes java.lang.Object int
HashLongObjNS No long java.lang.Object
HashLongObjS Yes long java.lang.Object
HashObjLongNS No java.lang.Object long
HashObjLongS Yes java.lang.Object long

The XProperties class extends java.util.Properties and can help developers in reading/writing properties from/in a text file, which is represented by an input/output stream. You can create and access only files in the directory allocated for your bundle in the framework storage. To reach this directory, you invoke the getDataFile method of the current BundleContext.

I/O

The I/O utilities define structures for enhanced object serialization.

Externalizable

The com.prosyst.util.io.Externalizable interface defines a lightened structure for object serialization. A bundle developer may implement Externalizable for more precise activities for a class storing and restoring from a stream.

Externalizable Dictionary

The ExternalizableDictionary utility combines: a hashtable of string keys and various properties; and a serializable object. It can be used for serialization of dictionaries.

Remote

The com.prosyst.util.io.Remote interface can be used by implementations of protocols for remote access, such as PMP, to find out what types of objects (usually services) should be provided to interested parties. The remoteInterfaces method contains the classes and interfaces that remote applications can invoke objects of. In addition, roles (users and groups) for remote access to modules in the framework can be introduced.

JAR Utility

As the OSGi Service Platform Service Compendium defines a limited functionality for managing the content of JAR files, in particular of bundle JAR files, the framework export an utility providing the most important needed functionality for viewing and modifying the content of a JAR file.

The JAR utility components are available in the com.prosyst.util.jar package.

Basically, the JAR utility API follows the logic for JAR file I/O operations defined in J2SE by referring to the appropriate methods of the java.util.jar.JarInputStream class. In addition, by using the Certificate Manager service the JAR utility is capable of providing only the trusted certificates a JAR file is signed with.

The JAR utility has two usage aspects - for standard reading and writing of archived content, and for forwarding manifest information to an output stream. The second case is designed for internal use by the framework. The next paragraphs describe the first usage aspect.

Following are some guidelines about the usage of the JAR utility:

Listing 2 illustrates the usage of the JAR utility - the example prints the trusted certificates a bundle with symbolic name "test.log.generator" is signed with.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.Vector;
import java.util.zip.ZipEntry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.ServiceReference;
import com.prosyst.util.jar.*;
import com.prosyst.mbs.framework.certmanager.CertificateManager;
public class JarUtilTest implements BundleActivator, BundleListener {
  private static final String LOG_GENERATOR_SNAME = "test.log.generator";
  private ServiceReference certDbRef;
  private CertificateManager certDb;
  // Method inherited from BundleListener
  public void bundleChanged(BundleEvent bEvent) {
    Bundle eventSource = bEvent.getBundle();
    // Checking the symbolic name of the installed bundle
if ((bEvent.getType() == BundleEvent.INSTALLED) && (eventSource.getSymbolicName().equals(LOG_GENERATOR_SNAME))) { String sourceLocation = eventSource.getLocation(); // Printing the certificate chains the bundle is signed with
printCertificate(sourceLocation); }
}
  // Prints the trusted certificate chains of the bundle with the specified location
private void printCertificate(String sourceLocation) { FileInputStream fIn; try { fIn = new FileInputStream(sourceLocation); JarInputStream jarIn = new JarInputStream(fIn, new Manifest(15), certDb); Manifest mf = jarIn.getManifest(); ZipEntry entry = jarIn.getNextEntry(); while(entry != null) { byte[] buff = new byte[1024]; try { int index = jarIn.read(buff, 0, buff.length); while(index != -1) { index = jarIn.read(buff, 0, buff.length); } } catch (Exception e) { e.printStackTrace(); } JarEntry jarEntry = mf.getJarEntry(entry); String[][] certs = jarEntry.getCerts(); for (int i = 0; (certs != null) && (i < certs.length); i++ ) { for (int j = 0; j < certs[i].length; j++ ) { System.out.println("[JarUtilTest] " + j + " " + certs[i][j]); } } entry = jarIn.getNextEntry(); }
} catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
} // Checks if the test.log.generator bundle is already installed
private boolean checkIfInstalled(BundleContext bc) { Bundle[] bundles = bc.getBundles(); for (int i = 0; i < bundles.length; i++ ) { if (bundles[i].getSymbolicName().equals(LOG_GENERATOR_SNAME)) { printCertificate(bundles[i].getLocation()); return true; } } return false; }
  // Methods inherited from BundleActivator
public void start(BundleContext bc) throws Exception { certDbRef = bc.getServiceReference(CertificateManager.class.getName()); if (certDbRef != null) { certDb = (CertificateManager) bc.getService(certDbRef); if (!checkIfInstalled(bc)) bc.addBundleListener(this); }
}
  public void stop(BundleContext bc) throws Exception {
    if (certDbRef != null) {
      bc.ungetService(certDbRef);
      certDbRef = null;
      certDb = null;
    }
}
}
Listing 2: Using the ProSyst JAR utility.

Log Dispatcher

The com.prosyst.mbs.framework.logdispatcher.LogDispatcher utility allows logging information in the runtime text console in a non-blocking way.

Direct usage of the log dispatcher is not recommended. Instead, bundle can use the Tracer-enabled methods of the log reference utility - the log utility calls internally the log dispatcher if the latter is enabled.

Object Pool

The object pool utility creates pools of reusable objects of certain type. It helps you get free instances of a class and easily release them if you need them no more. The components of the object pool utility are in the com.prosyst.util.pool package. A pool is represented by an ObjectPool instance.

You should specify the object type to the pool when instantiating ObjectPool. There are two ways to define the type of objects to keep in the pool:

The object pool maintains objects as a two-dimensional array, which is characterized by size and by factor. The size stands for the first dimension of this object array (Object [][]), that is the number of contained one-dimensional arrays. The factor stands for the second dimension of the object array (Object [][]), that is the number of elements contained in a single one-dimensional array. You can also specify the minimum number of objects in the pool which is set to 1 if such is not explicitly defined.

You get an object by calling the getObject method. If there is a free object in the pool, the method returns it to the requester. Otherwise, it returns a new instance. To release an object, invoke the releaseObject method.

If the objects created in the pool become too many, you can shrink their number to the defined minimum by calling the shrink method.

Resource Bundle

The com.prosyst.util.propertiesfile.ResourceBundle class allows using locale-specific resources in a way similar to the java.util.ResourceBundle. The Resource Bundle utility uses less resources and is intended for use on small devices. In addition, is can be used for loading images for an application in the framework.

Resource bundles are grouped in families that share a common base name, for example "MyResources". Each family can contain as many as needed local-specific members but it must have a default resource bundle that will be used in case a specific locale is not supported.

Resource bundles that belong to one family should contain the same items, translated for the locales represented by them. Resources for each resource bundle are stored in a separate .properties files as key/value pairs and are placed in the bundle JAR file. The name of each file must have the following structure:

<base_name>_<language>_<country>.properties

Following is an example of a resource bundle .properties file for the Dutch locale that is named MyResources_nl.properties and resides in the MY-INF directory of the bundle:

name=naam
street=straat
country=staat
image=http://www.flags.com/countryflags/dutch.gif
Listing 2.1: Sample .properties file for a resource bundle.

If you need a locale-specific resource bundle, you can obtain a ResourceBundle instance by calling the getBundle(String name, String locale, Bundle loader) method.

To retrieve an object from a resource bundle, you should use the getObject(String key) method passing the key of the locale-specific object as an argument.

To get information about all locales that a resource bundle provides, call the getLocales(String name,
Bundle loader)
which returns a String [] of the available locales.

The methods of the ResourceBundle class take the following parameters:

The following source example illustrates getting the desired ResourceBundle instance and using it to obtain the value of a property.

package myresourcebundle.test;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.prosyst.util.propertiesfile.ResourceBundle;

public class MyTestResources implements BundleActivator {
  
  ResourceBundle resourcebundle = null;
  Bundle bundle = null;
  
  public void start(BundleContext bc) throws Exception {
  
    // Getting the resource bundle for the Dutch locale
    bundle = bc.getBundle();
    resourcebundle = ResourceBundle.getBundle("MY-INF/MyResources", "nl", bundle);
   
    // Obtaining all available locales for the resource bundle 
    String[] locales = ResourceBundle.getLocales("MY-INF/MyResources", bundle);
    System.out.println("The locales for the resource bundle are: ");
      for (int i = 0; i < locales.length; i++) {
        System.out.println(locales[i]);
      }
	  
    // Getting the locale that is used when loading the resource bundle
    String locale = resourcebundle.getLocale();
  }

  public void stop(BundleContext bc) throws Exception {
  
  }
}
Listing 2.2: Using the Resource Bundle utility.

SBCtx

The SBCtx utility, com.prosyst.mbs.framework.sbctx.SBCtx, provides access directly to the org.osgi.framework.BundleContext of the System Bundle. This utility is useful to extension bundles - as such bundles do not have activator and are not able to register services, receive events, etc., they can use the SBCtx utility to perform such operations through the BundleContext of the System Bundle.

Security

The security utilities of the framework are located in the com.prosyst.util.security package.

The SecurityUtil class allows you to execute common operations related to management of bundles, services, files, system properties, etc., in a java.security.AccessController's doPrivileged block without the need of creating such a block by yourself. In addition, you can define and execute custom tasks accepting a certain number of arguments - implement a com.prosyst.util.security.PrivilegedRunner.PrivilegedDispatcher instance and call the proper doPrivileged method passing the PrivilegedRunner.PrivilegedDispatcher instance, the task type and task's argument.

The AccessController class was planned to act like java.security.AccessController for Java virtual machines not implementing this class (e.g. VMs compliant with JDK 1.1.x). In this release of the Framework Professional Edition Package, this utility does not provide any functionality - it is left in the framework only for backward compatibility. Instead, bundles can use the conventional java.security.AccessController and its helper classes as they are included in the serverjvm11.jar and serverjvm11conn.jar JAR files, intended for use on JDK 1.1.x compliant JVMs.

Time

The com.prosyst.util.time.Time utility can be used instead of System.currentTimeMillis for measurement of time intervals through a native timer, based on the OS high-resolution clock. The usage of the time utility can prevent from possible problems emerging when device's time settings are changed - in such case using System.currentTimeMillis, which returns absolute time, may result in later/earlier time notification, invalid time periods measured, etc.

mBS offers implementations of the native timer for the following operating systems:

To make the Time class use the OS-appropriate native timer in its getTickCount method, prior to framework startup:

If mbs.native.time is false (default) or the corresponding shared library cannot be located, the standard approach with calling System.currentTimeMillis will be used.

Note: If needed you can implement a custom OS-specific com.prosyst.util.time.Time class. Then, to make the framework set your timer class in the generic Time class, in the default.prs file before starting the framework set the mbs.native.time.class system property to the class name of your Time implementation.

References


System Bundles