/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2005 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or 1any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jonasadmin.test.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import org.objectweb.jonas.adm.AdmInterface;

/**
 * JOnAS property accessor
 * @author kemlerp
 */
public class JProperties {

    /**
     * Name of the JOnAS server used for tests
     */
    private static String jonasName = "jonas";

    /**
     * Initial context used for lookup
     */
    private static Context ictx = null;

    /**
     * JOnAS admin used for communicate via JMX to JOnAS
     */
    private static AdmInterface admI = null;

    /**
     * System properties
     */
    private static Properties systEnv = System.getProperties();

    /**
     * Separator of file
     */
    private static String fileSeparator = systEnv.getProperty("file.separator");

    /**
     * -Djonas.test property
     */
    private static final String JONAS_TEST = "jonas.test";

    /**
     * JONAS_TEST
     */
    private static String jonasTest = systEnv.getProperty(JONAS_TEST);

    /**
     * -Djonas.base property
     */
    private static final String JONAS_BASE = "jonas.base";

    /**
     * JONAS_BASE
     */
    private static String jonasBase = systEnv.getProperty(JONAS_BASE);

    /**
     * resource directory name
     */
    private static final String RESOURCE_DIR = "resources";

    /**
     * conf directory name
     */
    private static final String CONF_DIR = "conf";

    /**
     * Get initialContext
     * @return the initialContext
     * @throws NamingException if the initial context can't be retrieved
     */
    private Context getInitialContext() throws NamingException {
        return new InitialContext();
    }

    /**
     * Get list environnement
     * @return JOnAS protperties
     * @throws Exception if list environnement cannot be got
     */
    public Properties getPropertiesEnv() throws Exception {
        Properties prop = null;

        try {
            if (ictx == null) {
                ictx = getInitialContext();
            }
            if (admI == null) {
                admI = (AdmInterface) PortableRemoteObject.narrow(ictx.lookup(jonasName + "_Adm"), AdmInterface.class);
            }
            prop = admI.listEnv();
        } catch (Exception e) {
            throw new Exception("Cannot get list environnement : " + e.getMessage());
        }

        return prop;
    }

    /**
     * Get services in jonas properties
     * @return A table of string with services in jonas properties
     * @throws Exception if properties cannot be got
     */
    public String[] getServices() throws Exception {
        Properties propertiesEnv = getPropertiesEnv();
        String services = propertiesEnv.getProperty("jonas.services");
        return services.split(",");
    }

    /**
     * Search a service in services
     * @param service The string that is searched
     * @return true if there is the service in services else false
     * @throws Exception if services cannot be got
     */
    public boolean searchService(String service) throws Exception {
        String[] services = getServices();
        boolean found = false;
        int i = 0;

        while (!found && i < services.length) {
            if (services[i].equals(service)) {
                found = true;
            }
            i++;
        }

        return found;
    }

    /**
     * Db in service property
     * @return True if db is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isDb() throws Exception {
        boolean exist = false;
        try {
            if (searchService("db")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Dbm in service property
     * @return True if dbm is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isDbm() throws Exception {
        boolean exist = false;
        try {
            if (searchService("dbm")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Discovery in service property
     * @return True if discovery is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isDiscovery() throws Exception {
        boolean exist = false;
        try {
            if (searchService("discovery")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Ear in service property
     * @return True if ear is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isEar() throws Exception {
        boolean exist = false;
        try {
            if (searchService("ear")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Ejb in service property
     * @return True if ejb is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isEjb() throws Exception {
        boolean exist = false;
        try {
            if (searchService("ejb")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Jms in service property
     * @return True if jms is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isJms() throws Exception {
        boolean exist = false;
        try {
            if (searchService("jms")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Jmx in service property
     * @return True if Jmx is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isJmx() throws Exception {
        boolean exist = false;
        try {
            if (searchService("jmx")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Jtm in service property
     * @return True if jtm is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isJtm() throws Exception {
        boolean exist = false;
        try {
            if (searchService("jtm")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Mail in service property
     * @return True if db is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isMail() throws Exception {
        boolean exist = false;
        try {
            if (searchService("mail")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Registry in service property
     * @return True if registry is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isRegistry() throws Exception {
        boolean exist = false;
        try {
            if (searchService("registry")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Resource in service property
     * @return True if resource is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isResource() throws Exception {
        boolean exist = false;
        try {
            if (searchService("resource")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Security in service property
     * @return True if security is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isSecurity() throws Exception {
        boolean exist = false;
        try {
            if (searchService("security")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Web in service property
     * @return True if web is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isWeb() throws Exception {
        boolean exist = false;
        try {
            if (searchService("web")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * Ws in service property
     * @return True if ws is a value of service property
     * @throws Exception if service property cannot be got
     */
    public boolean isWs() throws Exception {
        boolean exist = false;
        try {
            if (searchService("ws")) {
                exist = true;
            }
        } catch (Exception e) {
            throw new Exception("Cannot get services : " + e.getMessage());
        }
        return exist;
    }

    /**
     * JMS service location
     * @return True if it is collocated, else False
     * @throws Exception if property cannot be got
     */
    public boolean isJMSCollocated() throws Exception {
        Properties propertiesEnv = getPropertiesEnv();
        boolean collocated = Boolean.valueOf(propertiesEnv.getProperty("jonas.service.jms.collocated")).booleanValue();
        return collocated;
    }

    /**
     * Catalina in jonas properties
     * @return True if Catalina is the web service, else false
     * @throws Exception if property cannot be got
     */
    public boolean isCatalina() throws Exception {
        Properties propertiesEnv = getPropertiesEnv();
        String webClass = propertiesEnv.getProperty("jonas.service.web.class");
        return webClass.endsWith("CatalinaJWebContainerServiceWrapper");
    }

    /**
     * Jtm location
     * @return True if jtm is remote, False if it is collocated
     * @throws Exception if property cannot be got
     */
    public boolean isJtmRemote() throws Exception {
        Properties propertiesEnv = getPropertiesEnv();
        boolean remote = Boolean.valueOf(propertiesEnv.getProperty("jonas.service.jtm.remote")).booleanValue();
        return remote;
    }

    /**
     * Get properties from a file in resources directory.
     * @param fileName name of the property file with ".properties".
     * @return Properties.
     * @throws Exception if the file is not found.
     */
    public Properties getProperties(String fileName) throws Exception {
        // Get ClassLoader
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        URL url = cl.getResource(fileName);
        InputStream is = cl.getResourceAsStream(fileName);
        Properties configFile  = new Properties();
        configFile.load(is);
        return configFile;
    }

    /**
     * Get properties from a file in $JONAS_TEST/jonasadmin directory.
     * @param fileName name of the property file without ".properties".
     * @return Properties.
     * @throws FileNotFoundException if the file is not found.
     */
    private Properties getCarolProperties() throws FileNotFoundException {
        // ${jonas.base}/conf/carol.properties
        if (jonasBase.equalsIgnoreCase("${myenv.JONAS_BASE}")) {
            throw new FileNotFoundException("You must add JONAS_BASE in your environnement variables. ");
        } else {
            String propFileName = jonasBase + fileSeparator + CONF_DIR + fileSeparator + "carol" + ".properties";

            File f = null;
            Properties configFile  = new Properties();
            try {
                f = new File(propFileName);
                FileInputStream is = new FileInputStream(f);
                configFile.load(is);
            } catch (FileNotFoundException e) {
                throw new FileNotFoundException("Cannot find properties for " + propFileName);
            } catch (IOException e) {
                System.err.println(e);
            }
            return configFile;
        }
    }

    /**
     * Get registry protocol
     * @return protocol name (jrmp, jeremie, iiop, cmi)
     */
    public String getRegistryProtocol() {
        String protocol = null;
        try {
            protocol = getCarolProperties().getProperty("carol.protocols");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return protocol;
    }

    /**
     * Get registry url
     * @return url of the registry
     */
    public String getRegistryUrl() {
        String protocol = null;
        String url = null;
        try {
            protocol = getCarolProperties().getProperty("carol.protocols");

            try {
                url = getCarolProperties().getProperty("carol." + protocol + ".url");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return url;
    }

    /**
     * Get Jvm Version
     * @return the java version
     */
    public String getJvmVersion() {
        return systEnv.getProperty("java.version");
    }

    /**
     * Get Jvm vendor
     * @return value of the property java.vm.specification.vendor
     */
    public String getJvmVendor() {
        return systEnv.getProperty("java.vm.specification.vendor");
    }
}