/**
 * 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
 *
 * Initial developer: Philippe Coq
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.deployment.common.digester;

import java.io.IOException;
import java.io.Reader;

import org.ow2.jonas.deployment.api.DTDs;
import org.ow2.jonas.deployment.api.Schemas;
import org.ow2.jonas.deployment.common.DeploymentDescException;
import org.ow2.jonas.deployment.common.lib.JEntityResolver;
import org.ow2.jonas.deployment.common.rules.JRuleSetBase;
import org.ow2.jonas.deployment.common.xml.TopLevelElement;

import org.apache.commons.digester.Digester;


/**
 * This class defines a Digester for the xml parsing of
 * deployment descriptors standard and specific
 *
 * @author Philippe Coq
 */

public class JDigester extends Digester {

    /**
     * Construct an instance of a JDigester which is a Digester
     * that is configured for parsing the deployment descriptors standards
     * and specifics used in JOnAS application.
     * the Digester contains the rules for the xml parsing
     * By default the created digester is set with:
     *     useContextClassLoader = true
     * @param ruleSet an object that extends JRuleSetBase
     * @param parsingWithValidation flag for xmlvalidation
     * @param namespaceAware must be true when schema is used
     * @param dtds mapping between publicId and local Urls of DTDs
     * @param schemas local urls for the schemas
     * @throws DeploymentDescException if the deployment descriptors are corrupted.
     */

    public JDigester(JRuleSetBase ruleSet,
                     boolean parsingWithValidation,
                     boolean namespaceAware,
                     DTDs dtds,
                     Schemas schemas)
        throws DeploymentDescException {
        super();


        String packageName = ruleSet.getClass().getPackage().getName();
        String rootPackageName = packageName.substring(0, packageName.lastIndexOf('.'));


        // Set the validation process
        setNamespaceAware(namespaceAware);
        setValidating(parsingWithValidation);

        // Define an error handler
        setErrorHandler(new JErrorHandler());

        // Register all Sun dtds/Schemas
        JEntityResolver jEntityResolver = new JEntityResolverWithDigester(this);
        jEntityResolver.addDtds(dtds);
        jEntityResolver.addSchemas(schemas);
        setEntityResolver(jEntityResolver);


        // Set the schema that Digester must use
        if (parsingWithValidation) {
            try {
                setFeature("http://apache.org/xml/features/validation/schema",
                                             true);
            } catch (Exception ee) {
                throw new DeploymentDescException("Error setting feature", ee);
            }
        }

        org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(rootPackageName + ".digester");
        setLogger(log);

        // Set the encoding feature
        try {
            setFeature("http://apache.org/xml/features/allow-java-encodings",
                                         true);
        } catch (Exception ee) {
            throw new DeploymentDescException("Error setting feature", ee);
        }

        // Don't use ContextClassLoader
        setUseContextClassLoader(false);

        // Add rules
        addRuleSet(ruleSet);
    }


    /**
     * Parse the deployment descriptor
     * @param reader the Reader of the XML file.
     * @param fileName the name of the file.
     * @param element top level xml element
     *        which is a structure containing the result of the xml parsing.
     * @throws DeploymentDescException if the deployment descriptor
     * is corrupted.
     */
    public void parse(Reader reader,
                      String fileName,
                      TopLevelElement element)
        throws DeploymentDescException {
        try {
            clear();
            push(element);
            parse(reader);
        } catch (Exception ioe) {
            throw new DeploymentDescException("Error when parsing XML document " + fileName, ioe);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException ignored) {
                    getLogger().warn("Can't close '" + fileName + "'");
                }
            }
            push(null);
        }
    }

}
