/////////////////////////////////////////////////////////////////////////
//
// © Institute for Software Science, University of Vienna, 2004
//
// Copyright in this software belongs to Institute for Software Science, 
// University of Vienna, Nordbergstrasse 15/C/3, 1090 Vienna, Austria
//
// 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 :		Aleksandar Dimitrov
//	Created Date :		2004/02/24
//	Created for Project:	GEMSS
//
////////////////////////////////////////////////////////////////////////
//
// Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//	Last commit info:	$Author: dimitrov $
//					$Date: 2004/06/01 12:51:03 $
//					$Revision: 1.6 $
//
/////////////////////////////////////////////////////////////////////////

package at.ac.univie.iss.registry;

import java.io.IOException;
import java.io.File;
import java.rmi.RemoteException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogManager;
import java.util.Vector;
import java.util.Enumeration;


/**
 * This class implements the Registry interface
 * in order to make possible the services
 * to register or unregister themselves 
 * on a registry and the clients to look 
 * for suitable services.
 */
public class RegistryImpl implements Registry {

    private DataStoreHandler dataStoreHandler;
    private static Logger logger = null;

    /**
     * Creates a new <code>DataStoreHandler</code> object, 
     * which is used to operate with registry store. 
     *
     * @throws  RemoteException if an error occured
     *			during the creation of database file.
     */
    public RegistryImpl() throws RemoteException {

        logger = Logger.getLogger("logging.registry");               
                
        init(logger);
        
        String issDBFile = System.getProperty("iss.registry.dbFile");
        
        if ((issDBFile == null) || (!(new File(issDBFile)).canWrite())) {
        	
            // Creates a database file with name registry.dbFile. 
            // This file is located in JAVA temporary directory.
            // This directory is overwritten by starting of Tomcat and
            // in such way the database file will be in tomcat temp directory.
            issDBFile = System.getProperty("java.io.tmpdir")
                    + File.separatorChar + "registry.dbFile";
        }
        
        dataStoreHandler = new DataStoreHandler(issDBFile);
    }

    /**
     * Queries the registry to retrieve one or more service 
     * descriptions that meet certain criteria(attribute).
     *
     * @throws  RemoteException if an error occured
     *			during the publishing of the service description
     *
     * @param	attribute array of service descriptions
     *          in a form of one or more Name/Value pairs
     *
     * @see		at.ac.univie.iss.registry.Attribute	 
     */
    public Vector query(Attribute[] attribute) throws RemoteException {
	    
        logger.log(Level.INFO, "find specified services\n");	
        return dataStoreHandler.inquiry(attribute);
    }

    /**
     * Publishes the service description to a registry.
     *
     * @throws  RemoteException if an error occured
     *			during the registration of the service description
     *
     * @param	service object that is used for 
     *          description of existing service
     *
     * @see		at.ac.univie.iss.registry.ServiceDescription	
     */
    public void publishService(ServiceDescription service) throws RemoteException {
	
        logger.log(Level.INFO, "publish a service\n");	
        dataStoreHandler.register(service);
    }

    /**
     * Removes the service description from a registry.
     *
     * @throws  RemoteException if an error occured
     *          during the removing of the service description
     *
     * @param   serviceURI URI of the service that will be 
     *          remove(unregister) from registry
     */
    public void removeService(String serviceURI) throws RemoteException {
    
        logger.log(Level.INFO, "remove a service\n");	
        dataStoreHandler.unregister(serviceURI);
    }    
    
    private void init(Logger fhLogger) throws RemoteException {

		String loggingNS = fhLogger.getName();
		
		LogManager logManager = LogManager.getLogManager();
		
		String logDir = new String(".." + File.separatorChar + "logs");

		String logFilePattern = logDir + File.separatorChar + loggingNS + ".log";
		int logFileLimit = 0;
		int logFileCount = 1;    	

		removeAllLogHandlers(fhLogger);		
		
		try {
			if (logManager.getProperty(loggingNS + ".pattern") != null) {
				logFilePattern = logManager.getProperty(loggingNS + ".pattern");
			}
			if (logManager.getProperty(loggingNS + ".limit") != null) {
				logFileLimit = Integer.parseInt(logManager.getProperty(loggingNS + ".limit"));
			}
			if (logManager.getProperty(loggingNS + ".count") != null) {
				logFileCount = Integer.parseInt(logManager.getProperty(loggingNS + ".count"));
			}
		}
		catch (Exception exception) {
			fhLogger.log(Level.CONFIG, "Not all specific settings for FileHandler of logger: " + loggingNS + " found! Using the following (defaults?):");
			fhLogger.log(Level.CONFIG, "Logging file pattern: " + logFilePattern);
			fhLogger.log(Level.CONFIG, "Logging file limit: " + logFileLimit);
			fhLogger.log(Level.CONFIG, "Logging file count: " + logFileCount);
		}

		try {		    
		    if (logManager.getProperty(loggingNS + ".pattern") != null) {
							    
			    fhLogger.log(Level.FINEST, "The following file handler (" + logFilePattern + "/" + logFileLimit + "/" +
											logFileCount + "/true) will be added!\n" );

			    FileHandler fileHandler = new FileHandler(logFilePattern, logFileLimit, logFileCount, true);
			    
			    if (fileHandler.getFormatter() instanceof java.util.logging.XMLFormatter) {
                    fileHandler.setFormatter(new java.util.logging.SimpleFormatter()); 
			    }
			    
			    fhLogger.addHandler(fileHandler);
			}    
		}
		catch (IOException ioException) {
			fhLogger.log(Level.CONFIG, "FileHandler of logger: " + loggingNS + " throws an I/O exception!", ioException);
		}		 
		
    }
    
    private void removeAllLogHandlers(Logger tempLogger) throws RemoteException {

        java.util.logging.Handler[] handlers = tempLogger.getHandlers();

        if ((handlers != null) && (handlers.length > 0)) {
        
            for (int count = 0; count < handlers.length; count++) {
                handlers[count].close();
                tempLogger.removeHandler(handlers[count]);
            }
        }
    }        
}
