/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * 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.security.internal;

import java.util.Enumeration;
import java.util.Hashtable;

import org.ow2.jonas.jmx.JmxService;
import org.ow2.jonas.security.SecurityService;
import org.ow2.jonas.security.internal.realm.factory.JResourceDS;
import org.ow2.jonas.security.internal.realm.factory.JResourceLDAP;
import org.ow2.jonas.security.internal.realm.factory.JResourceMemory;
import org.ow2.jonas.security.realm.factory.JResource;



/**
 *
 *
 * @author Guillaume Sauthier
 */
public class JResources {

    /**
     * List of Resource.
     * TODO Change this to have a Map ?
     */
    private Hashtable<String, JResource> jResources = null;

    /**
     * SecurityService.
     */
    private SecurityService service = null;

    /**
     * Reference to the jmx service.
     */
    private JmxService jmxService = null;

    /**
     * name of the management domain.
     */
    private String domainName = null;

    /**
     * XML Header.
     */
    public static final String HEADER_XML =
        "<?xml version='1.0' encoding='utf-8'?>\n"
        + "<!DOCTYPE jonas-realm PUBLIC\n"
        + "          \"-//ObjectWeb//DTD JOnAS realm 1.0//EN\"\n"
        + "          \"http://www.objectweb.org/jonas/dtds/jonas-realm_1_0.dtd\">\n";

    /**
     * Create a JResoures list attached to a given SecurityService.
     * @param s the parent SecurityService
     */
    public JResources() {
        jResources = new Hashtable<String, JResource>();
    }

    /**
     * Add the Resource (memory, ldap, datasource,...).
     * @param jResource  an instance of JResource or subclasses (JResourceMemory, JResourceDS,...)
     * @throws Exception if the resource name already exists
     */
    public void addJResource(final JResource jResource) throws Exception {
        if (jResources.get(jResource.getName()) != null) {
            throw new Exception("The resource name " + jResource.getName() + " already exists !");
        }

        jResources.put(jResource.getName(), jResource);
        jResource.setJmxService(jmxService);
        jResource.setDomainName(domainName);
        jResource.setSecurityService(service);

        service.bindResource(jResource.getName(), jResource);
    }

    /**
     * Removes the named JResource from the JResource list.
     * @param resourceName JResource name to be removed
     * @return the removed JResource
     * @throws Exception when JResource is not found with given name.
     */
    public JResource remove(final String resourceName) throws Exception {
        JResource jResource = jResources.get(resourceName);
        if (jResource == null) {
            throw new Exception("The resource name " + resourceName + " doesn't exist !");
        }
       jResources.remove(resourceName);
       return jResource;
    }

    /**
     * @param name the name of the JResource to get.
     * @return Returns the named JResource
     */
    public JResource getJResource(final String name) {
        return jResources.get(name);
    }

    /**
     * @return Returns the JResources Enumeration
     */
    public Enumeration<JResource> getResources() {
        return jResources.elements();
    }

    /**
     * String representation of the JOnAS realm.
     * @return the xml representation of the JOnAS realm
     */
    public String toXML() {

        // Required values

        StringBuffer xml = new StringBuffer(HEADER_XML);
        xml.append("<!--\n");
        xml.append(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
        xml.append(" - Define a jonas-realm.xml file for JOnAS realms\n");
        xml.append(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
        xml.append(" -->\n");

        xml.append("<jonas-realm>\n");

        // Memory realms
        xml.append("  <!--\n");
        xml.append("       -=  MEMORY REALM =-\n");
        xml.append("       Define the users, groups and roles\n");
        xml.append("  -->\n");
        xml.append("  <jonas-memoryrealm>\n");
        for (Enumeration<JResource> e = jResources.elements(); e.hasMoreElements();) {
                JResource o = e.nextElement();
                if (o instanceof JResourceMemory) {
                    xml.append(o.toString());
                    xml.append("\n");
                }
        }
        xml.append("  </jonas-memoryrealm>\n");


        // Datasource realms
        xml.append("  <!--\n");
        xml.append("       -=  DATASOURCE REALM =-\n");
        xml.append("       Define the configuration to use datas from a datasource\n");
        xml.append("  -->\n");
        xml.append("  <jonas-dsrealm>\n");
        for (Enumeration<JResource> e = jResources.elements(); e.hasMoreElements();) {
                JResource o = e.nextElement();
                if (o instanceof JResourceDS) {
                    xml.append(o.toString());
                    xml.append("\n");
                }
        }
        xml.append("  </jonas-dsrealm>\n");

        // Ldap realms
        xml.append("  <!--\n");
        xml.append("       -=  LDAP REALM =-\n");
        xml.append("       Define the configuration to use datas from an ldap server\n");
        xml.append("  -->\n");
        xml.append("  <jonas-ldaprealm>\n");
        for (Enumeration<JResource> e = jResources.elements(); e.hasMoreElements();) {
                JResource o = e.nextElement();
                if (o instanceof JResourceLDAP) {
                    xml.append(o.toString());
                    xml.append("\n");
                }
        }
        xml.append("  </jonas-ldaprealm>\n");



        xml.append("</jonas-realm>\n");


        return xml.toString();
    }

    /**
     * Set the security service reference
     * @param sec security service reference
     */
    public void setSecurityService(final SecurityService service) {
        this.service = service;
    }

    /**
     * Set the domain name
     * @param domain the domain name
     */
    public void setDomainName(final String domain) {
        domainName = domain;
    }

    /**
     * Set the jmx service reference
     * @param jmxService the jmx service reference
     */
    public void setJmxService(final JmxService jmx) {
        jmxService = jmx;
    }

    /**
     * Allows to chek if the jmx service reference is set.
     * @return true if the jmx service reference set, false otherwise false.
     */
    public boolean hasJmxService() {
        if (jmxService != null) {
            return true;
        } else {
            return false;
        }
    }
}
