Korelib design.
    This document describes the goals and design of Korelib. The document is
structured into several sections, each section providing describing various
aspects of Korelib. The order of sections is rather important, since one section
may use concepts defined/described in the previous section(s).

Goals
    The primary goal of Korelib is to provide an easy and consistent way of
creating modular (plugin-based) applications. A typical Korelib application
consists of a main app binary (executable) and a set of plugins (dynamic
libraries) which are loaded at run-time. Using Korelib gives your application
both a great deal of flexibility - you can develop a plugin or replace a plugin
with another one whithout needing to recompile your main application - and
scalability - by using load-as-needed of plugins your application can scale
up and down depending on the features you need at run-time.
    Also, as a side effect of the way Korelib is implemented (see
"Implementation Overview" section), Korelib can be used as lightweight component
model for your application. All you have to do is: inherit from various Korelib
classes (such as kore::Module or kore::ServiceProviders), fill in the necessary
stuff (such as kore::Module::Info and kore::ServiceProvider::services() ),
and register your components to the various Korelib managers.
    Last, but not the last, since Korelib is cross-platform - the current
version is working on Linux, FreeBSD, BeOS, AtheOS and Win32 - it hides the
platform-dependant details of loading dynamic libraries, providing a consistent
cross-platform API, and thus helping you in creating cross-platform applications.

Implementation Overview
    There are a lot of applications using the "plugin" (application module
loaded at run-time, most likely from a dynamic library) concept. Most of the
implementations, while being very simple and straightforward to use, have a few
limitations, such as:
- too application-specific; each application has it's own vision over what a
  plugin is. That means you have to learn a different API and programming model
  for each application you are writing plugin(s) for. More, you cannot write
  generic ("generic" as in "which can be used by more apps") plugins or use a
  plugin written for one app with another app. Most of the time you have to
  redesign/rewrite the plugin, or at least provide an "API bridge" between the
  2 plugin systems.
- no differentiation between the dynamic library (which is just a "plugin
  container", that is, just a file holding all the data and code for the
  plugin), and the actual plugin (which you use in your app). Since the two
  are different concepts (thus each of them having different attributes and
  actions that can be performed - different API's, in one word), you end up by
  either having both *full* API's put together in one API (which means bloat)
  or having the two API's trimmed down and put together (less bloat, but also
  less flexibility).
- the plugin model is too simple and inflexible, requring non-standard hacks
  (which may break in future versions of the app) and even changes to the
  plugin API (which may break the other exisiting plugins). Also, by not making
  a clear distinction between the dynamic library and the plugin, it may be not
  possible to bundle two or more related plugins into one single library.
- no introspective information; sometimes it's usefull to be able to find some
  "introspective" information about a given plugin, such as plugin name, plugin
  version, API version needed by the plugin (the application may want to refuse
  loading a plugin which requires an older API version, binary incompatible with
  the current API version), and so on.
- no central management of resources, such as: plugins, services and
  capabilities;
    Korelib solves the above limitations (as well as a few others) by adding
several levels of indirection to the way plugins are handled. At a first look,
loading and using plugins with Korelib may seem a little bit complex, but
things are really clear and easy once you understand the Korelib programming
model. Also, the initial code you need for creating a Korelib plugin can be more
complex than the code needed by other plugin-based apps; that's because Korelib
makes a clear distinction between the plugin container and the plugin itself,
and you have to write at least two classes: one for the container and one for
the plugin. However, you may use one of the samples that come with Korelib as
a template for your plugins, and only edit the relevant parts.

Concepts and Terminology
    Because of the apparent complexity of Korelib, there is an obvious need of
defining the concepts Korelib is based on, as well as defining a consistent
terminology to be used with Korelib. Sometimes the terms used to describe a
concept have different meaning with Korelib than with other plugin-based systems.
That's mostly because Korelib is more fine-grained (thus giving more flexibility)
than the other plugin systems, and it is using two or more concepts for in places
where the other systems are using only one single concept. Ie. kore::Plugin is
actually only the plugin container (dynamic library), while the kore::Module
(and it's subclass kore::ServiceProvider) is the "actual plugin".
    There are three main orthogonal concepts in Korelib: Module, Service and
Plugin.
    1. The Module (sometimes called "component") is Korelib's basic structural
    and functional unit. Basically everything in Korelib (except for some helper
    classes) is a module. Also, if you plan to use Korelib in your application,
    you will most likely make your classes inherit (directly or indirectly) the
    kore::Module class. What differentiates a module from a regular C++ class is
    that each module has a Info property associated to it. The module Info is
    used for holding a few module meta-properties (information), such as: module
    name, type and description, module and Korelib API version, and so on. Your
    application may query your module for these meta-properties and make some
    decisions depending on that (ie. it may refuse to use a module who's version
    is different from the version your app is expecting).
    Korelib also provides a centralised way of managing modules via it's
    kore::ModuleManager (please note that the ModuleManager is a Module itself,
    actually a special type of Module - ServiceProvider). Your application has to
    register all it's Modules to the ModuleManager right after the Modules are
    created and unregister them from the ModuleManager before destroing them.
    The ModuleManager can be queried at any time for the list of the Modules
    that are registered to it.
    2. Since one size doesn't fit all, it's not possible to provide one generic
    API for all Korelib's modules. That is, different modules may have different
    capabilities (ie. perform different tasks), and therefore we need a way to
    tell what capabilities a particular module has. More, the application should
    be able to both query a module for it's capabilities at run-time and find
    out which module(s) have a certain capability. Korelib handles the task by
    splitting each module capability into two parts: a dynamic (run-time) part
    and a static (compile-time) part. The dynamic part of a module capability is
    called Service and it provides all the necessary information (such as
    service name and description) for querying a module for its capabilities at
    run-time. The static part of a module capability is a class interface (API)
    that the module has to implement. The class interface is usually an abstract
    C++ class (having all it's methods pure virtual); the module has to inherit
    from it and implement all of its methods.
    "Module X has the Y capability" means both "Module X provides the Y service"
    and "Module X implements the Y interface/API". A Korelib ServiceProvider is
    a Module (that is, kore::ServiceProvider inherits from kore::Module) which
    provides at least one Service. The main difference between a ServiceProvider
    and a "regular" Module is that the ServiceProvider can be queried for the
    Services it provides. Same as for modules, Korelib has a ServiceManager to
    handle the Services and ServiceProviders in a centralised manner. Each newly
    created ServiceProvider has to be registered to the ServiceManager (actually
    the services it provides is what get's registered) right after it was
    created, and unregistered from the ServiceManager before getting destroyed.
    The ServiceManager can be queried at any time for: what services are
    registered, what providers are registered, which services are provided by
    a given ServiceProvider, which ServiceProvider(s) are providing a given
    service, and so on. Please note that a ServiceProvider may provide more than
    one Service, and a service may be provided by more than one ServiceProvider.
    3. The Korelib Plugin is a cross-platform representation of a dynamic linked
    library (dll). The Plugin has a dual role:
    1) Provide a cross-platform abstraction for dll's and hide platform-dependant
    implementation details;
    2) Provide hooks (API) for various dynamic loading related tasks. Ie. the
    Plugin::pluginLoaded() and Plugin::unloadingPlugin() hooks are triggered
    after loading (pluginLoaded()) the dll and before unloading
    (unloadinPlugin()) the dll. The user may override these methods in order to
    perform some initialization/cleanup.
    Please note that a kore::Plugin is a kore::Module, but not a
    kore::ServiceProvider, which means a Plugin itself cannot provide any Services.
    The right way to make a dll provide one or more Korelib services is to bundle
    up one or more ServiceProviders into a dll and make the Plugin take care of
    registering/unregistering those ServiceProviders to the ServiceManager.
    Plugins can be loaded/unloaded via the kore::PluginLoader and they have to
    be registered/unregitered to the kore::PluginManager.

Structure Overview
    Korelib consists of several classes that are implementing the concepts
described in the "Concepts and Terminology" section. In order to avoid possible
nameclashes with other class libraries, all the Korelib classes are using the
namespace "kore". There are two kinds of classes: modules (those inheriting from
kore::Module) and helper classes.
    The helper classes are used by the modules in order to provide various
module meta-information. Instaces of helper classes are non-mutable (read-only).
Here is the list of helper classes for the current version of Korelib:
    kore::Version
    kore::Module::Info
    kore::ServiceProvider::Service

    kore::Version is used for holding common version information, such as
major/minor/revision number and version string (in "<major>.<minor>.<revision>"
format). Also, it defines a set of operators for testing source/binary
compatibility of two versions, and for version matching/comparison.
kore::Version instances are returned by the kore::Module::Info::version() and
kore::Module::Info::APIVersion() methods.
    kore::Module::Info holds kore::Module meta-information, such as module
name, type, description and version, as well as Korelib API version needed by
the module. kore::Module::Info instances are returned by kore::Module::info()
method.
    kore::ServiceProvider::Service is Korelib's implementation of the Service
concept. Each kore::ServiceProvider::Service has a service name, provider and
service description. kore::ServiceProvider::Service instances are returned by
the kore::ServiceProvider::services(), kore::ServiceProvider::service(...),
kore::ServiceManager::registeredService() and kore::ServiceManager::registeredServices()
methods.

    The kore::Module is the base class for all the module classes. Here is the
class hierarchy for the current version of Korelib:
    kore::Module
        kore::Plugin
        kore::ServiceProvider
            kore::Kernel
            kore::ModuleManager
            kore::PluginLoader
            kore::PluginManager
            kore::ServiceManager

    kore::Module is Korelib's implementation for the Module concept. Each
kore::Module instance has a kore::Module::Info associated to it. Also, the
kore::Module class provides four hooks/callbacks that are triggered
before/after the module get's registered/unregistered to a ModuleManager.
The classes inheriting from kore::Module may override these methods in order
to perform some useful tasks.
kore::Module instances are returned by the kore::Module::Info::module() and
kore::ModuleManager::registeredModules() methods.
    kore::Plugin is Korelib's implementation of the Plugin (dynamic library)
concept. the kore::Plugin class provides four hooks/callbacks triggered when
the Plugin get's loaded/unloaded/activated/deactivated.
kore::Plugin instance are returned by the kore::PluginLoader::openPlugin()
and kore::PluginLoader::runPlugin() methods.
    kore::ServiceProvider is a kore::Module which provides at least one
kore::ServiceProvider::Service. The kore::ServiceProvider API extends the
kore::Module API by addind three methods for quering the provider for the
kore::Services it provides: kore::ServiceProvider::services() and
kore::ServiceProvider::service(...). Also, the kore::ServiceProvider has
eight hooks/callbacks triggered before/after registering/unregistering the
provider/services to a kore::ServiceManager.
kore::ServiceProvider instance are returned by the
kore::ServiceProvider::Service::provider(), kore::ServiceManager::registeredProvider(...)
and kore::ServiceManager::registeredProviders() methods.
    kore::Kernel is the provider of the "Kore/Kernel/Kernel" service. This class
is a singleton and it can be used as a starting point for accessing all the
other modules in an application. The kore::Kernel::instance() static method
returns the single kore::Kernel instance (it also creates the instace first
time when it's invoked). The kore::Kernel::serviceManager() method returns the
kore::ServiceManager associated to this Kernel.
The kore::Kernel instance is returned by kore::Kernel::instance() and
dynamic_cast<kore::Kernel*>(kore::ServiceManager::registeredProvider("Kore/Kernel/Kernel"))
calls.
    kore::ModuleManager is the provider for the "Kore/Kernel/Module Manager" service.
The kore::ModuleManager class has four methods for registering/unregistering
one or more kore::Modules, and one method for getting the list of registered
kore::Modules. It also takes care of triggering the right registering/unregistering
callbacks in kore::Module.
kore::ModuleManager instances are returned by the
dynamic_cast<kore::ModuleManager*>(kore::ServiceManager::registeredProvider("Kore/Kernel/Module Manager"))
call.
    kore::PluginLoader is the provider for the "Kore/Kernel/Plugin Loader" service.
The kore::PluginLoader is a cross-platform loader for dynamic linked libraries.
It hides the platform-specific implementation details and provides a consistent
API for loading/initialising/unloading kore::Plugins, error handling and
conversion between plugin name and dll name. It also takes care of triggering
the right callbacks in kore::Plugin.
kore::PluginLoader instances are returned by the
dynamic_cast<kore::PluginLoader*>(kore::ServiceManager::registeredProvider("Kore/Kernel/Plugin Loader"))
call.
    kore::PluginManager is not implemented yet.
    kore::ServiceManager is the provider for the "Kore/Kernel/Service Manager" service.
The kore::ServiceManager class has eight methods for registering/unregistering
one or more providers/services to it, six methods for quering for registered
services and five methods for quering for registered providers. It also takes
care of triggering the right registering/unregistering callbacks in
kore::ServiceProvider.
kore::ServiceManager instances are returned by the
kore::Kernel::serviceManager() and
dynamic_cast<kore::ServiceManager*>(kore::ServiceManager::registeredProvider("Kore/Kernel/Service Manager"))
calls.

Implementation Detail

Programming Model
    This section describes how to use Korelib to create your own Plugins, as
well as how to load a Plugin and use the services it provides:
1. Decide what services you want to provide. Create a kore::ServiceProvider::Service
instance for each service and fill in the necessary information (service name
and a short description of the service).
2. Write the interface classes for each service. Each interface class should be
a C++ abstract class defined in it's own header file. Decide what API (methods)
will each interface provide and make all the methods pure virtual.
3. Write the providers for the services you want to provide. Please note that
one provider can provide more than one service and one service can be provided
by more than one provider. It's up to you to decide how many providers you
will have and which/how many services will each one provide. The only restrictions
when writing a provider are: the provider has to inherit (directly or indirectly)
from kore::ServiceProvider and the provider has to implement (ie. inherit from)
all the interfaces of the services it provides. Fill in the necessary information
(such as kore::Module::Info and services) for each provider. Hint: for the module
Info you may either override the kore::Module::info() method and return you own
Info instance or use the kore::Module::setInfo(...) protected method to set your
provider's Info (in which case you don't have to override the info() method).
Same, for the list of services you may either override the
kore::ServiceProvider::services() method and return the list of services you
provide, or use the kore::ServiceProvider::addService() to add services to your
provider (in which case you don't need to override the services() method).
You may also want to check Korelib's providers (such as Kernel, ServiceManager,
and so on) for examples of how to write a provider.
Also, don't forget to set the provider field of each kore::Service so that it
points to the right provider. Obviously, if you have two providers which are
providing the same service, you'll need two kore::Service instance, one for
each provider. The two instance will have the same service name and different
provider and service description.
4. If you want your providers in a separate dll loaded at run-time, you'll have
to write a kore::Plugin class and fill in the kore::Module::Info for it.
Your plugin will have to:
- "export" itself, so that the kore::PluginLoader can get a reference to it.
  This is done by using:
  extern "C" {
    PLUGIN_MAIN_HDR(libHandle,libName,libPath,libFlags);
  }
  in its header file, and:
  PLUGIN_MAIN_BODY(<MyPluginClassName>,libHandle,libName,libPath,libFlags);
  in its cpp file. The <MyPluginClassName> needs to be replaced with the actual
  name of your plugin class.
  Also, your plugin constructor needs to have the following signature:
  MyPlugin::MyPlugin(HMODULE libhandle, const char* libname, const char* libpath, int flags):Plugin(libhandle,libname,libpath,flags);
- take care of registering/unregistering your providers to the
  kore::ServiceManager each time the plugin get's activated/deactivated.
  Each time your plugin get's activated, the kore::Plugin::initPlugin() callback
  will get triggered, so this is the right place to put your registration code.
  A typical initPlugin() should look like this:
  void MyPlugin::initPlugin()
  {
    // get a reference to the kore::ServiceManager
    ServiceManager* sm = Kernel::instance()->serviceManager();
    // get a reference to the kore::ModuleManager
    ModuleManager* mm = dynamic_cast<ModuleManager*>(sm->registeredProvider("Kore/Kernel/Module Manager"));
    // create your providers
    prv1 = new MyFirstProvider();
    prv2 = new MySecondProvider();
    // register them to the kore::ServiceManager
    sm->registerProvider(prv1);
    sm->registerProvider(prv2);
    // since each kore::ServiceProvider is also a kore::Module, try to
    // register your providers to the kore::ModuleManager
    if( mm )
    {
        mm->registerModule(prv1);
        mm->registerModule(prv2);
    }
  }
  Each time your module get's deactivated the kore::Plugin::finalizePlugin()
  callback get's triggered, so this is the right place to put your unregistration
  code. A typical finalizePlugin() should look like this:
  void MyPlugin::finalizePlugin()
  {
    // get a reference to the kore::ServiceManager
    ServiceManager* sm = Kernel::instance()->serviceManager();
    // get a reference to the kore::ModuleManager
    ModuleManager* mm = dynamic_cast<ModuleManager*>(sm->registeredProvider("Kore/Kernel/Module Manager"));
    // unregister them from the kore::ServiceManager
    sm->unregisterProvider(prv1);
    sm->unregisterProvider(prv2);
    // since each kore::ServiceProvider is also a kore::Module, try to
    // unregister your providers from the kore::ModuleManager
    if( mm )
    {
        mm->unregisterModule(prv1);
        mm->unregisterModule(prv2);
    }
    // destroy your providers
    delete prv1;
    prv1 = 0;
    delete prv2;
    prv2 = 0;
  }
  Important: the current Korelib implementation does NOT guarantee that
  kore::Plugin::finalizePlugin() get's triggered before
  kore::Plugin::unloadingPlugin(), so it is possible that the Plugin will
  get unloaded before being finalize, and that may be a cause for various
  run-time errors (ie. if you use one of the providers after the plugin was
  unloaded, your application will crash). In order to fix that, you need to
  override kore::Plugin::unloadingPlugin() and add a call to finalizePlugin()
  in there.
5.In order to use the newly created Plugin in your application you need to
  load and initialize the plugin (using kore::PluginLoader::runPlugin(...) ),
  query the kore::ServiceManager for the various services provided by the
  providers bundled in your plugin, cast the kore::ServiceProvider(s) returned
  by the previous query to the interface associated to the queried service, and
  use the inteface's API to get access to the various methods.
  Here is a short sample:
  // called when the application is created/initialised
  void appInit()
  {
    // get a reference to the kore::ServiceManager
    ServiceManager* sm = Kernel::instance()->serviceManager();
    // get a reference to the kore::ModuleManager
    ModuleManager* mm = dynamic_cast<ModuleManager*>(sm->registeredProvider("Kore/Kernel/Module Manager"));
    // get a reference to the kore::PluginLoader
    PluginLoader* loader = dynamic_cast<PluginLoader*> (sm->registeredProvider("Kore/Kernel/Plugin Loader"));
    if( loader )
    {
        // try to load and initialise your plugin. We assume the plugin is contained
        // in a dll named "libmy_plugin.so" (or "my_plugin.dll" on Win32).
        Plugin* myplugin = loader->runPlugin("my_plugin");
        // check if the plugin dll was found
        if( myplugin )
        {
            // since each kore::Plugin is also a kore::Module,
            // try to register our plugin to the kore::ModuleManager
            if( mm )
                mm->registerModule(myplugin);
            // note: future Korelib versions may require that you register
            // your plugin to the kore::PluginManager, as well.
        }
        else
            // the plugin dll was not found. Display a diagnostic message
            printMessage( loader->lastError() );
    }
  }
  // a function that performs some useful task
  void doSomeWork()
  {
    // get a reference to the kore::ServiceManager
    ServiceManager* sm = Kernel::instance()->serviceManager();
    // query the kore::ServiceManager for one of the service provided by your plugin
    // we assume that the service name is "My Plugin/My Services/First Service"
    ServiceProvider* prv = sm->registeredProvider("My Plugin/My Services/First Service");
    // cast the above kore::ServiceProvider to MyFirstInterface
    // we assume that every provider of the "My Plugin/My Services/First Service"
    // is implementing MyFirstInterface
    MyFirstInterface* sp1 = reinterpret_cast<MyFirstInterface*>(prv);
    // do some work
    ...
    // use the provider. We assume that MyFirstInterface has method named met1()
    sp1->met1();
    // do some more work
    ...
  }
  // called when the application prepares to exit
  void appCleanup()
  {
    // get a reference to the kore::ServiceManager
    ServiceManager* sm = Kernel::instance()->serviceManager();
    // get a reference to the kore::ModuleManager
    ModuleManager* mm = dynamic_cast<ModuleManager*>(sm->registeredProvider("Kore/Kernel/Module Manager"));
    // get a reference to the kore::PluginLoader
    PluginLoader* loader = dynamic_cast<PluginLoader*> (sm->registeredProvider("Kore/Kernel/Plugin Loader"));
    // get a reference to the your previously loaded plugin. This can be done by
    // either using a global variable pointing to your plugin, or by querying
    // the kore::ModuleManager:
    Plugin* myplugin = 0;
    if( mm )
    {
        Module** modules = mm->registeredModules();
        // modules is a null-terminated array of modules registered to the manager
        for(int i=0; modules[i]; i++)
            // search the list of registered modules by module name
            if( !strcmp( modules[i]->info()->name(), "my_plugin" )
            {
                // found the plugin. cast the kore::Module to kore::Plugin and
                // exit the loop.
                myplugin = dynamic_cast<Plugin*>(modules[i]);
                break;
            }
        // if the plugin was found
        if( myplugin )
            // unregister it from the kore::ModuleManager
            mm->unregisterModule( myplugin );
    }
    // if the plugin was found
    if( myplugin )
    {
        // unload it
        if( loader )
            loader->closePlugin();
    }
    // perform the final cleanup by deleting the kore::Kernel
    delete Kernel::instance();
  }
  // sample main() function
  void main(void)
  {
    appInit();
    doSomeWork();
    appCleanup();
  }

Thanks and Credits to:
- an Infinite Number of Monkeys for typing in Korelib
- my employer - theKompany.com (http://www.thekompany.com) - for providing the
  necessary resources (such as salaries, and an Inifinite Number of Typewriters)
  for the Infinite Number of Monkeys
- SteQven M. Christey <steqve@shore.net> for designing the wonderful IMPS
  (Infinite Monkey Protocol Suite) as described in RFC 2795
  (http://www.faqs.org/rfcs/rfc2795.html)

Version and Copyright
    Version 0.1
    Copyright(C) 2000 Catalin Climov <xxl@thekompany.com>
