Resource Management

Introduction

The kernel of the jptools library is the resource management (ResourceManager). The idea is to provide a simple interface to load and store files (objects) from respective to a resource. All actions of the resource management are transparent. An application which use this management has not care about from which path, database or what ever a resource will be loaded or stored to.


Design

The file manager (FileManager)

The FileManager interface defines the general access methods to a file:



The concrete implementation class is the class FileCacheManager. It implements the FileManager and additionaly a simple cache which can be enabled or disabled. The subclasses PropertiesManager and the XMLManager implements the file handling to special files like properties or xml files. The FileCacheManager can also be used to read or store a file. It reads the whole file and give it back in a String representation.

The BootManager is a special FileManager. It is used to load a configuration like the jptools.properties. The BootManager run through the following steps if it tries to load a resource:

  1. It test first if an alias exist (see more in the chapter The resource mapping).

  2. After resolving the alias, it tries to load the searched file with the FileResourceHandler (see more in the chapter The resource handler).

  3. If it can not found by the FileResourceHandler it tries to load the resource with the ClasspathResourceHandler but only if the flag resource.bootmanager.enableClasspathLoader in the configutation is set to true (see more in the chapter The resource handler).


The default settings are:

##############################################################################  
# resource configuration
##############################################################################
resource.propertiesDescritption            =
resource.enableSystemKeyValueFileLoader    = true
resource.bootmanager.enableClasspathLoader = true
resource.classPathLoaderPrefix             = $

# resource handlers
resource.handlerMapper1.jptools.resource.ClasspathResourceHandler = ^\\$.*
resource.handlerMapper2.jptools.resource.GZIPResourceHandler = .*\\.gz
resource.handlerMapper3.jptools.resource.FileResourceHandler = .*


The resource manager (ResourceManager)

All implementation of the FileManager are working with simple streams like InputStream and OutputStream. The ResourceManager builds the kernel of the resource management. It gets a caller for a given resource name a stream back. This can be either an InputStream or neither an OutpuStream.


The ResourceManager has a ResourceHandlerMap attribute which defines which resource with which resource handler (ResourceHandler) works. The ResourceManager also contains a ResourceConfig and a Map. In the next chapters the resource handler and the resource mapping are more explained. The configuration (ResourceConfig) defines the settings for the map and the resource handler.


The resource handler (ResourceHandler)

A ResourceHandler implements the concrete access to a resource. The following handlers are currently realized:

  • FileResourceHandler: This class implements the access of a file. The file can be accessed with absolult or realtiv path.

  • ClasspathResourceHandler: This handler implements the access of files which are placed in the classpath. Only read operations are supported.

  • TODO: JDBCResourceHandler: This class implements the access to a database over JDBC.

In the ResourceConfig which is hold by the ResourceManager is defined which resource will be loaded with which resource handler. There are two different ways to define or manipulate this definition:

  1. Rules are defined in the jptools.properties file. The entries starts with resource.handlerMapper and follows by a number. This number defines the sort order of the resource handler rule. After the sort order number the resource handler name follows. The value of the properties defines the rule to which resource the resource handler will be used. The rule is a regular expression:

    resource.handlerMapper1.jptools.resource.ClasspathResourceHandler = ^\\$.*
    resource.handlerMapper2.jptools.resource.FileResourceHandler = .*
    

    This example defines that each resource which starts with a $ character will loaded with the class jptools.resource.ClasspathResourceHandler. All other files are loaded with the class jptools.resource.FileResourceHandler.

    Each time when a resource should accessed by the ResourceManager the resource handler rules run through in the sort order which are defined by the described initialisation.

  2. The second way to modify the resource handler rules is to use the ResourceManager methods like getResourceHandlerMapper and setResourceHandlerMapper:
    public class Demo
    {
        public static void main (String[] args) throws Exception
        {
            ResourceHandlerMapper mapper = ResourceManager.getResourceHandlerMapper();
    
            try
            {
                mappper.clear();
                mapper.add( "^\\$.*",                  
                            "jptools.resource.ClasspathResourceHandler" );
                mapper.add( ".*",                  
                            "jptools.resource.DefaultResourceHandler" );
            }
            catch( RESyntaxException e )
            {
                log.error( "Wrong initialisation", e );
            }    
    
            ResourceManager.setResourceHandlerMapper( mapper );
        }
    }
    


The resource mapping (alias for a resource name)

The resource mapping maps as example a single resource name to another one. In other words it supports to set an alias for a resource. Recursive mappings (aliases) are supported!

Example:

  1. If the resource TestResourceName as example should be loaded than the resource management searches a mapping for it. In this case no mapping is found. After searching and resolving the mapping the resource manager searches a ResourceHandler to load the resource. If no handler is found than the FileResourceHandler will be used.

  2. If the following mapping is defined:

    • TestResourceName1 = TestResourceName2
    • TestResourceName2 = TestResourceName

    If the resource TestResourceName should be loaded than the resource management finds firstly a mapping to TestResourceName2. Afterwards the framework finds also a mapping of the resource TestResourceName2 to TestResourceName1. In this example will the resource TestResourceName1 loaded if the resource TestResourceName should be accessed.


There are different ways to set a resource mapping:

  1. The general way to set an alias is to use the jptools.properties file and add some entries in there like:
    resource.alias1.testfiles.conf = conf/testfiles.conf
    resource.alias2.conf/demo.xml = testcase/demo.xml
    
  2. Additional the method getResourceMapper() of the class ResourceManager could be used to receive the current mapping (HashMap). Add a new mapping by using the put method. The method setResourceMapper sets a mapping:
    public class Demo
    {
        public static void main (String[] args) throws Exception
        {
            Map fileMapper = ResourceManager.getResourceMapper();
            fileMapper.put( "logconfig.properties", "/conf/log.config" );
            fileMapper.put( "mail.conf", "conf/mail.conf" );
            fileMapper.put( "conf/mail.conf", "/conf/mail.conf" );
            ResourceManager.setResourceMapper( fileMapper );
        }
    }
    
  3. The way over system properties is also supported. But only if in the configuration the property resource.enableSystemKeyValueFileLoader is set to true. The system property key defines the resource name to map to another name and the value is the alias of the resource: java -Djptools.properties=config/jptools.properties ...


Examples

Reading an ASCII file

public class Demo
{
    public static void main (String[] args) throws Exception
    {
        FileCacheManager fileManager = new FileCacheManager();
        Object obj=fileManager.getFile( args[0] );    
    }
}

Reading a property file

public class Demo
{
    public static void main (String[] args) throws Exception
    {
        PropertiesManager propertiesManager = new PropertiesManager();

        /* the cast is necessary!!! */
        Properties prop = (Properties)propertiesManager.getFile( args[0] );
    }
}

Reading a xml file

public class Demo
{
    public static void main (String[] args) throws Exception
    {
        XMLManager xmlManager = new XMLManager();

        /* the cast is necessary!!! */
        org.w3c.dom.Document doc = 
              (org.w3c.dom.Document)xmlManager.getFile( args[0] );    
    }
}

Get a resource mapping of a file

public class Demo
{
    public static void main (String[] args) throws Exception
    {
        String fileName = ResourceManager.getInstance().getMappedResourceName( args[0] );
        
        File theFile = new File( fileName );
    }
}