JPF System Overview
The JPF framework is based around the concept of "plug-ins". A plug-in is a structured component that contributes code and resources to the system and describes them in a structured way. These plug-ins can further define extension points, well-defined method hooks that can be extended by other plug-ins. When one plug-in provides an implementation of an extension point defined by another plug-in, we say that it adds an extension to the system. This approach allows developers using JPF to build highly modular and easily extendible applications.
All required information about a plug-in is defined in the plug-in manifest. Depending on the PluginRegistry, this may be any structured data that exists at some URL. JPF provides a default XML-based manifest implementation. The format of this XML document is defined by the JPF plug-in DTD. It is very important to include as much information about a plug-in in its manifest as possible. This is because the JPF framework uses this information to check plug-in consistency, whether plug-in dependencies (relationships between plug-ins) are satisfied (including version compatibility check) and that all declared resources are available. JPF also checks that all provided extensions have been declared with the required parameters.
The high-level structure of framework can be represented by this diagram:
The diagram shows the three major parts of JPF:
- PluginRegistry - the storage repository for meta-information about all discovered plug-ins
- PathResolver - the component responsible for finding the physical lcation of all discovered resources
- PluginManager - the framework runtime that loads and activates the plug-ins
PluginRegistry is a set of interfaces that abstract meta-information about plug-ins and plug-in fragments. The framework provides default implementations of these interfaces based on XML plug-in manifests mentioned earlier (plug-in DTD). The general rule here is that a manifest should be registered with the PluginRegistry for every plug-in and plug-in fragment.
The framework also provides a default implementation of PathResolver, which simply maps manifest locations to the context ("home") folder of their corresponding plug-ins. A special implementation of PathResolver is also available that makes "shadow copies" of plug-in resources before resolving paths to them. This helps avoid locking of local resources and running native code from remote locations.
Bringing these interfaces together is PluginManager. You can access an instance of the "standard", or default, PluginManager by just one method call. This makes using JPF very simple in most situations.
If you are using the default XML based implementation of PluginRegistry provided by JPF, you'll need to learn the plug-in manifest syntax. It is simple and shouldn't be too difficult for any familiar with HTML or XML.
The plug-in manifest is an XML file which contains all the information needed by the JPF framework about each plug-in. The XML syntax should conform to the plug-in manifest DTD. Look at this file carefully, all elements are documented.
PluginRegistry manages all meta-information about discovered plug-ins. In general, you may provide your own registry implementation, but the standard one should be enough in most cases.
To make plug-in meta-data available for the application, you (as the application developer, but not plug-in developer) should register their manifests with PluginRegistry. The counterpart method - unregister() is used to "remove" plug-in meta-data from the registry. To make plug-ins available for activation, use publishPlugins() method (about PluginManager class see bellow). Note that all mentioned methods may be called not only during the application start up phase but in also at runtime. This allows application developers to implement "hot" plug-in deployment functionality.
PluginManager is the runtime system of the Framework. The main responsibility of the manager is to activate (load plug-in code and call the plug-in initializer class) plug-ins upon client code requests and manage inter plug-in dependencies. Usually, programmers shouldn't care about plug-in activation, this is done automatically when the plug-in code is first called. It is also possible to "deactivate" plug-ins during the life of the application. This feature may help to reduce application resources requirements. For complex usage scenarios it is possible to disable/enable plug-ins. A plug-in that is marked as disabled can't be activated with PluginManager (but it's meta-data remains available from the PluginRegistry).
The ObjectFactory class allows application developers to easily create base JPF objects: PluginRegistry, PluginManager and PathResolver. It uses a simple and efficient discovery algorithm to find the available implementations of the main framework classes. It is possible to provide your own "vision" of all aspects of the Framework: you may write your own registry and manager and that will be used by JPF.
A typical JPF-based application may consist of a small boot launcher, which initializes the registry, instanciates PluginManager and activates the main plug-in by calling some of it's methods (Or you can use the JPF Boot Library provided by JPF to greatly simplify this task). From this point on the flow of control remains within the registered plug-in code. This allows the development of applications of any kind, not only GUI applications, but also J2EE applications, command line utilities and more.