/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.web.tomcat6;

import org.apache.catalina.startup.ContextConfig;
import org.apache.tomcat.util.digester.Digester;
import org.ow2.jonas.security.SecurityService;

import java.lang.reflect.Field;

/**
 * Own JOnAS context config object in order to change some default values.
 * @author Florent BENOIT
 */
public class JOnASContextConfig extends ContextConfig {

    /**
     * {@link SecurityService} instance to pass to the {@link org.ow2.jonas.web.tomcat6.security.Realm}s.
     */
    private SecurityService service = null;

    /**
     * Path to the default Context for Tomcat6 (can use /).
     */
    public static final String DEFAULT_CONTEXT_XML = "conf/tomcat6-context.xml";

    /**
     * Path to the default Web.xml object for Tomcat6 (can use /).
     */
    public static final String DEFAULT_WEB_XML = "conf/tomcat6-web.xml";

    /**
     * @return the location of the default deployment descriptor
     */
    @Override
    public String getDefaultWebXml() {
        if (this.defaultWebXml == null) {
            defaultWebXml = DEFAULT_WEB_XML;
        }

        return (this.defaultWebXml);

    }

    /**
     * @return the location of the default context file
     */
    @Override
    public String getDefaultContextXml() {
        if (defaultContextXml == null) {
            defaultContextXml = DEFAULT_CONTEXT_XML;
        }

        return (this.defaultContextXml);

    }

    /**
     * Extend META-INF/Context.xml Digester with JOnAS {@link SecurityService} setup.
     * @return an extended Digester.
     */
    @Override
    protected Digester createContextDigester() {
        // Get base Digester
        Digester digester =  super.createContextDigester();
        // If a JOnAS Realm is found, inject the SecurityService
        digester.addRule("Context/Realm", new SetSecurityServiceRule(service));
        return digester;
    }

    /**
     * @param service {@link SecurityService} instance to assign.
     */
    public void setSecurityService(final SecurityService service) {
        this.service = service;
    }

    /**
     * Always nullify the 'contextDigeste'r static reference.
     * @see org.apache.catalina.startup.ContextConfig#init()
     */
    @Override
    protected synchronized void init() {
        // nullify the digester Object
        // was holding a reference on a discarded security service.
        contextDigester = null;
        super.init();
    }


    /**
     * Process the application configuration file, if it exists.
     */
    protected void applicationWebConfig() {
        super.applicationWebConfig();


            // Keep value of the ignoreAnnotations flag
            boolean ignore = context.getIgnoreAnnotations();
            if (ignore) {
                org.apache.AnnotationProcessor annotationProcessor = ((org.apache.catalina.core.StandardContext) context).getAnnotationProcessor();
                Class clazz= annotationProcessor.getClass();
                Field f = null;
                try {
                    f = clazz.getDeclaredField("disabledAnnotation");
                    f.setAccessible(true);
                    f.set(annotationProcessor, Boolean.TRUE);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Unable to find the field", e);
                } catch (NoSuchFieldException e) {
                    throw new IllegalStateException("Unable to find the field", e);
                }

                // Enable annotation processing
                context.setIgnoreAnnotations(false);

            }
    }

    /**
     * @param tomcat6ContextConfPath The path to the tomcat 6 configuration file to set
     */
    public void setDefaultContextXml(final String tomcat6ContextConfPath) {
        this.defaultContextXml = tomcat6ContextConfPath;
    }

    /**
     * @param tomcat6WebConfPath Path to the tomcat 6 web configuration file to set
     */
    public void setDefaultWebXml(final String tomcat6WebConfPath) {
        this.defaultWebXml = tomcat6WebConfPath;
    }
}
