/**
 * 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.lib;

import java.io.Reader;
import java.net.URL;

import org.apache.commons.digester.Digester;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.jmx.JmxService;
import org.ow2.jonas.lib.util.Log;
import org.ow2.jonas.security.internal.JResources;
import org.ow2.jonas.security.internal.SecurityServiceException;
import org.ow2.jonas.security.rules.JDSRuleSet;
import org.ow2.jonas.security.rules.JLDAPRuleSet;
import org.ow2.jonas.security.rules.JMemoryRuleSet;


/**
 * Parse config file
 * @author Guillaume Sauthier
 */
public class JResourceManager {

    /**
     * Logger which is used.
     */
    private static Logger logger = Log.getLogger(Log.JONAS_SECURITY_PREFIX);

    /**
     * DTD of the realm configuration file.
     */
    protected static final String CONFIG_FILE_DTD = "jonas-realm_1_0.dtd";

    /**
     * Resource for the DTD.
     */
    protected static final String DTD_RESOURCE = "org/ow2/jonas/security/realm/dtd/jonas-realm_1_0.dtd";

    /**
     * Unique JresourceManager instance.
     */
    private static JResourceManager instance = null;

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

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

    /**
     * Private Constructor for Singleton.
     */
    private JResourceManager() {

    }

    /**
     * @return returns the unique JResourceManager instance
     */
    public static JResourceManager getInstance() {
        if (instance == null) {
            instance = new JResourceManager();
        }
        return instance;
    }

    /**
     * Create and configure the Digester that will be used for the xml
     * parsing of the JOnAS realm file.
     * @return Digester the digester containing the rules for the xml parsing
     * of the JOnAS realm file (jonas-realm.xml)
     */
    protected Digester createRealmDigester() {

        boolean validating = true;
        URL dtdUrl = getClass().getResource("/" + DTD_RESOURCE);

        if (dtdUrl == null) {
            // Can't locate URL for DTD, no validation
            logger.log(BasicLevel.INFO, "Unable to find the '" + DTD_RESOURCE + "' resource. no validation will be done.");
            validating = false;
        }

        // Initialize the digester
        Digester digester = null;
        try {
            digester = new Digester();
        } catch (Throwable e) {
            System.out.println("new Digester: " + e);
            throw new RuntimeException("Cannot create Digester" + e);
        }

        if (validating) {
            digester.register("-//ObjectWeb//DTD JOnAS realm 1.0//EN", dtdUrl.toExternalForm());
        }

        digester.setValidating(validating);
        digester.setErrorHandler(new JErrorHandler());
        digester.addRuleSet(new JMemoryRuleSet("jonas-realm/jonas-memoryrealm/"));
        digester.addRuleSet(new JDSRuleSet("jonas-realm/jonas-dsrealm/"));
        digester.addRuleSet(new JLDAPRuleSet("jonas-realm/jonas-ldaprealm/"));

        return (digester);
    }

    /**
     * Add JResource(s) created from parsing of the reader contents inside the JResources given instance.
     *
     * @param res JResources element where JResource will be addded.
     * @param reader XML Content Reader
     * @param xml filename / xml : used in Error messages
     *
     * @throws SecurityServiceException When parsing fails
     */
    public void addResources(final JResources res, final Reader reader, final String xml) throws SecurityServiceException {
        if (!res.hasJmxService()) {
            res.setJmxService(jmxService);
            res.setDomainName(domainName);
        }
        try {
            // Create the digester for the parsing of the jonas-realm.xml file.
            Digester realmDigester = createRealmDigester();
            realmDigester.setClassLoader(getClass().getClassLoader());
            realmDigester.push(res);
            realmDigester.parse(reader);
            reader.close();
        } catch (org.xml.sax.SAXException saxe) {
            throw new SecurityServiceException("Error when parsing the XML of the file " + xml, saxe);
        } catch (Exception e) {
            throw new SecurityServiceException("Error when reading config file from the xml file " + xml, e);
        }

    }

    /**
     * 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;
    }

    public boolean hasJmxService() {
        if (jmxService != null) {
            return true;
        } else {
            return false;
        }
    }

}
