/*
 ************************************************************************
 *
 * Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
 *
 * Copyright in this software belongs to C&C Research Laboratories,
 * Rathausallee 10, 53757 Sankt Augustin, Germany.
 *
 * This software may not be used, sold, licensed, transferred, copied
 * or reproduced in whole or in part in any manner or form or in or
 * on any media by any person other than in accordance with the terms
 * of the Licence Agreement supplied with the software, or otherwise
 * without the prior written consent of the copyright owners.
 *
 * This software is distributed WITHOUT ANY WARRANTY, without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE, except where stated in the Licence Agreement supplied with
 * the software.
 *
 *  Created By :           G.A. Kohring
 *  Created for Project :  GEMSS (IST-2001-37153)
 *
 ************************************************************************
 *
 */

package de.nece.ccrle.gemss;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.IllegalArgumentException;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Properties;
import java.util.logging.Logger;

import de.nece.ccrle.util.VariableProperties;
import eu.gemss.components.Configuration;

/**
 * A class to hold configuration data for the GEMSS environment.
 *
 * @author G.A. Kohring
 */
public class ConfigurationImpl implements Configuration {

    private static Logger logger =
                       Logger.getLogger( ConfigurationImpl.class.getName() );

    private Properties properties = null;
    private String gemssHome = null;

    /**
     * The default constructor locates and parses the system configuration
     * file.
     *
     * @throws IOException if the configuration file cannot be found.
     */
    public ConfigurationImpl() throws IOException {

        // Find GEMSS's home 

        gemssHome = (String) AccessController.doPrivileged(
            new PrivilegedAction() {
                public Object run() {
                    return System.getProperty( "gemss.home" );
                }
            }
        );


        // If system's home is not set, then abort.
        if ( gemssHome == null ){
            throw new IOException( "gemss.home == null!" );
        }

        properties = new VariableProperties ();

        properties.setProperty( "gemss.home", gemssHome );


        // Locate the configuration files
        String gemssConfigDir = gemssHome + File.separator + "config";

        properties.setProperty( "gemss.config.home", gemssConfigDir );

        final String gemssConfig = gemssConfigDir + File.separator 
                             + "gemss.config";

        // Read in any configuration information

        FileInputStream configFile = null;

        try{
            configFile = (FileInputStream) AccessController.doPrivileged(
                new PrivilegedExceptionAction() {
                    public Object run() throws FileNotFoundException {
                        return new FileInputStream( gemssConfig );
                    }
                }
            );
        } catch ( PrivilegedActionException pae ){
            throw (FileNotFoundException) pae.getException();
        }

        properties.load( configFile );
        configFile.close();

        // Check that the desired configuration values have been set

        String keyStore = null;
        if ( (keyStore = properties.getProperty( "gemss.keystore" )) == null ){
            throw new IOException( "gemss.keystore == null!" );
        } else {
            String keyStorePath = configurePath( keyStore, gemssHome );
            properties.setProperty( "gemss.keystore", keyStorePath );
        }

        String sessions = null;
        if ( (sessions = properties.getProperty( "gemss.sessions" )) == null ){
            throw new IOException( "gemss.sessions == null!" );
        } else {
            String userHome = (String) AccessController.doPrivileged(
                new PrivilegedAction() {
                    public Object run() {
                        return System.getProperty( "user.home" );
                    }
                }
            );
            String sessionsPath = configurePath( sessions, userHome );
            properties.setProperty( "gemss.sessions", sessionsPath );
        }

        String componentPath = gemssHome + File.separator + "components/";
        properties.setProperty( "gemss.components", componentPath );

    }

    public String getHome(){
        if ( properties == null ) return null;
        return properties.getProperty( "gemss.home" );
    }

    public String getKeyStoreFilename(){
        return properties.getProperty( "gemss.keystore" );
    }

    public String getKeyStoreType(){
        return properties.getProperty( "gemss.keystoreType" );
    }


    public String getComponentStore(){
        return properties.getProperty( "gemss.components" );
    }

    public String getSessionStore(){
        return properties.getProperty( "gemss.sessions" );
    }

    public String getConfigDir(){
        return properties.getProperty( "gemss.config.home" );
    }

    public String[] getDaemons(){
        // Get a list of the components to be initialized

        String daemons = properties.getProperty( "gemss.daemons" );

        // If the daemons property is not present, set daemons to the empty
        // string

        if ( daemons == null ){
            daemons = "";
        }

        String[] initThese = daemons.split( "\\s" );

        // Find any extraneous elements left over from the split

        int i;
        int count = 0;
        for ( i = 0; i < initThese.length; i++){
            if ( initThese[i].equals( "" ) ){
                initThese[i] = null;
            } else {
                count++;
            }
        }

        // Create and return a new list without any extraneous elements

        String[] components = new String[count];
        int c = 0;
        for ( i = 0; i < initThese.length; i++){
            if ( initThese[i] != null ){
                components[c] = initThese[i].trim();
                c++;
            }
        }

        return components;
    }

    public long getRepositoryUpdateInterval(){
        String updateInterval = properties.getProperty( 
                                    "gemss.repository.UpdateInterval" );

        long ui = -1;

        if ( updateInterval != null ) {
            try{
                ui = Long.parseLong( updateInterval );
            } catch ( NumberFormatException nfe ){
                logger.info( nfe.getMessage() );
                // ignore the error and leave ui unchanged
            }
        }

        return ui;
    }

    // Configure the path relative to the base.
    private String configurePath( String relPath, String base ){

        if ( relPath ==  null ){
            throw new IllegalArgumentException( "relPath == null!" );
        }

        if ( relPath.startsWith( File.separator ) ){
            return relPath;
        } else if ( relPath.startsWith( "." ) ){
            return relPath;
        } else if ( relPath.charAt( 1 ) == ':' ){
            return relPath;
        } else {
            if ( ( base != null ) && ( !base.equals( "" ) ) ) {
                String path = base + File.separator + relPath;
                return path;
            } else {
                return relPath;
            }
        }

    }


}
