/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: jonas-team@ow2.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 any 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.ow2.jonas.lib.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Properties;

import org.ow2.jonas.lib.bootstrap.JProp;

/**
 * This class implements utility methods for the manipulation of application modules.
 * @author Adriana Danes
 */
public class JModule {

    /**
     * file extension containing the different module types.
     */
    public static final String EJBJAR_EXTENSION = "jar";
    public static final String RAR_EXTENSION = "rar";
    public static final String WAR_EXTENSION = "war";
    public static final String EAR_EXTENSION = "ear";

    /**
     * Child directory of a expanded container.
     */
    public static final String EJBJAR_CHILD_DIR = "META-INF";
    public static final String RAR_CHILD_DIR = "META-INF";
    public static final String WAR_CHILD_DIR = "WEB-INF";
    public static final String EAR_CHILD_DIR = "META-INF";

    /**
     * xml file in a child directory of a expanded container.
     */
    public static final String EJBJAR_CONFIRM_FILE = "ejb-jar.xml";
    public static final String RAR_CONFIRM_FILE = "ra.xml";
    public static final String WAR_CONFIRM_FILE = "web.xml";
    public static final String EAR_CONFIRM_FILE = "application.xml";

    public static final String JONAS_BASE = JProp.getJonasBase();
    public static final String DEPLOY_DIR = JONAS_BASE + File.separator + "deploy";
    /**
     * properties file extension.
     */
    public static final String PROPS_EXTENSION = "properties";


    /**
     * name of the directory containig configuration.
     */
    public static final String CONF_DIR = "conf";

    public static ArrayList<String> getFilesInDir(final String dirName, final String extension) throws Exception {
        ArrayList<String> al = new ArrayList<String>();
        File file = new File(dirName);
        String[] files = file.list();
        int pos;
        String fileName;
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                file = new File(dirName, files[i]);
                if (file.isFile()) {
                    fileName = file.getName().toLowerCase();
                    pos = fileName.lastIndexOf(extension);
                    if (pos > -1) {
                        if (pos == (fileName.length() - extension.length())) {
                            al.add(file.getName());
                        }
                    }
                }
            }
        }
        Collections.sort(al);
        return al;
    }

    public static ArrayList<String> getDatasourcePropsInDir() throws Exception {
        // Get all files include in configuration directory
        ArrayList<String> al = getFilesInDir(JProp.getJonasBase() + File.separator + CONF_DIR, PROPS_EXTENSION);
        // Keep all datasources properties
        String sPath;
        Properties oProps = new Properties();
        boolean bDelete;
        int i = 0;
        while (i < al.size()) {
            sPath = JProp.getJonasBase() + File.separator + CONF_DIR  + File.separator
                + al.get(i).toString();
            bDelete = true;
            try {
                oProps.clear();
                oProps.load(new FileInputStream(sPath));
                // Detect datasource property
                if (oProps.getProperty("datasource.name") != null) {
                    // Remove Extension
                    int iPos = al.get(i).toString().toLowerCase().lastIndexOf(".properties");
                    al.set(i, al.get(i).toString().substring(0, iPos));
                    // Next
                    i++;
                    bDelete = false;
                }
            } catch (Exception e) {
                // none
            } finally {
                // Remove no-datasource
                if (bDelete) {
                    al.remove(i);
                }
            }
        }
        return al;
    }

    public static ArrayList<String> getMailFactoryPropsInDir(final String type) throws Exception {
        // Get all files include in configuration directory
        ArrayList<String> al = getFilesInDir(JProp.getJonasBase() + File.separator + CONF_DIR, PROPS_EXTENSION);
        // Keep all datasources properties
        String sPath;
        Properties oProps = new Properties();
        boolean bDelete;
        int i = 0;
        while (i < al.size()) {
            sPath = JProp.getJonasBase() + File.separator + CONF_DIR  + File.separator
                + al.get(i).toString();
            bDelete = true;
            try {
                oProps.clear();
                oProps.load(new FileInputStream(sPath));
                // Detect mail factory property
                if (oProps.getProperty("mail.factory.name") != null) {
                    boolean bToReturn;
                    if (type == null) {
                        // any type OK
                        bToReturn = true;
                    } else {
                        // Check type
                        if (oProps.getProperty("mail.factory.type").equals(type)) {
                            bToReturn = true;
                        } else {
                            bToReturn = false;
                        }
                    }
                    if (bToReturn) {
                        // Remove Extension
                        int iPos = al.get(i).toString().toLowerCase().lastIndexOf(".properties");
                        al.set(i, al.get(i).toString().substring(0, iPos));
                        // Next
                        i++;
                        bDelete = false;
                    }
                }
            } catch (Exception e) {
                // none
            } finally {
                // Remove no-mail factory
                if (bDelete) {
                    al.remove(i);
                }
            }
        }
        return al;
    }

    public static ArrayList<String> getMailFactoryPropsInDir() throws Exception {
        return getMailFactoryPropsInDir(null);
    }

    /**
     * Return the URL list of files (possibly directories) having a given extension located in a given directory.
     * @param dirName name of the directory to lookup
     * @param extension extension to check
     * @return list of URLs of the files/directories which were found
     * @throws MalformedURLException If the path cannot be parsed as a URL
     * @throws IOException If an I/O error occurs, which is possible because the
     *          construction of the canonical pathname may require
     *          file system queries
     */
    public static ArrayList<URL> getInstalledFileInDir(final String dirName, final String extension) throws MalformedURLException, IOException {
        ArrayList<URL> al = new ArrayList<URL>();
        // Search all files in directory
        File oFile = new File(dirName);
        String[] asFiles = oFile.list();
        if (asFiles != null) {
            // Loop for each found file
            for (int i = 0; i < asFiles.length; i++) {
                oFile = new File(dirName, asFiles[i]);
                // Detect extension
                String sFilename = oFile.getName().toLowerCase();
                int iPos = sFilename.lastIndexOf(extension);
                if (iPos > -1 && iPos == (sFilename.length() - extension.length())) {
                    URL url = oFile.getCanonicalFile().toURL();
                    al.add(url);
                }
            }
        }
        return al;
    }

    /**
     * Return the list of all installed containers in a directory.
     * The container may be : <br>
     * - a archive file container with a known extension : jar, war, ear, rar<br>
     * - a directory where the container is expanded<br>
     * To control if a directory contains a expanded container, it's necessary
     * to provide the child directory and the xml file that confirm the expanded container.<br>
     * Parameter example to retrieve :<br>
     * - web application : war, WEB-INF, web.xml
     * - application : ear, META-INF, application.xml
     * - ejb container : jar, META-INF, ejb-jar.xml
     * - resource : rar, META-INF, ra.xml
     *
     * @param p_DirName The name of the directory to find
     * @param p_Extension The extension of container (jar, war, ear, rar)
     * @param p_DirChildConfirm The child directory that confirm the container
     * @param p_FileConfirm The xml file inside the child directory that confirm the container
     * @return A list of absolute path container
     * @throws Exception
     */
    public static ArrayList<String> getInstalledContainersInDir(final String p_DirName,
                                                                final String p_Extension,
                                                                final String p_DirChildConfirm,
                                                                final String p_FileConfirm)
        throws Exception {

        // Return variable
        ArrayList<String> al = new ArrayList<String>();
        // Variables used in loop
        int iPos;
        String sFilename;
        File oDirChild;
        File oFileConfirm;
        // Search all files in directory
        File oFile = new File(p_DirName);
        String[] asFiles = oFile.list();

        if (asFiles != null) {
            // Loop for each found file
            for (int i = 0; i < asFiles.length; i++) {
                oFile = new File(p_DirName, asFiles[i]);
                // Detect file with extension
                if (oFile.isFile()) {
                    sFilename = oFile.getName().toLowerCase();
                    iPos = sFilename.lastIndexOf(p_Extension);
                    if (iPos > -1) {
                        if (iPos == (sFilename.length() - p_Extension.length())) {
                            al.add(oFile.getCanonicalFile().toURL().getPath());
                        }
                    }
                }
                // Detect directory of expanded container
                else if (oFile.isDirectory()) {
                    oDirChild = new File(oFile, p_DirChildConfirm);
                    if (oDirChild.exists() && oDirChild.isDirectory()) {
                        oFileConfirm = new File(oDirChild, p_FileConfirm);
                        if (oFileConfirm.exists()) {
                            al.add(oFile.getCanonicalFile().toURL().getPath());
                        }
                    }
                }
            }
        }
        return al;
    }

    /**
     * Return the list of all installed modules/apps in a directory.
     * The container may be : <br>
     * - a archive file container with a known extension : jar, war, ear, rar<br>
     * - a directory where the container is expanded<br>
     *
     * @param dirName The name of the directory to find
     * @param extension The extension of container (jar, war, ear, rar)
     * @return A list of absolute paths
     * @throws Exception
     */
    public static ArrayList<String> getInstalledContainersInDir(final String dirName, final String extension)
        throws Exception {

        // Return variable
        ArrayList<String> al = new ArrayList<String>();
        // Variables used in loop
        int iPos;
        String sFilename;
        // Search all files in directory
        File oFile = new File(dirName);
        String[] asFiles = oFile.list();

        if (asFiles != null) {
            // Loop for each found file
            for (int i = 0; i < asFiles.length; i++) {
                oFile = new File(dirName, asFiles[i]);
                // Detect file with extension
                if (oFile.isFile()) {
                    sFilename = oFile.getName().toLowerCase();
                    iPos = sFilename.lastIndexOf(extension);
                    if (iPos > -1) {
                        if (iPos == (sFilename.length() - extension.length())) {
                            al.add(oFile.getCanonicalFile().toURL().getPath());
                        }
                    }
                }
                // Detect directory of expanded container
                else if (oFile.isDirectory()) {
                    // yet not support
                }
            }
        }
        return al;
    }

}
