/*
 * $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServletConfig.java,v 1.16 2005/06/23 09:01:49 unico Exp $
 * $Revision: 1.16 $
 * $Date: 2005/06/23 09:01:49 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.apache.slide.webdav;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

import org.apache.slide.util.XMLValue;
import org.jdom.Element;
import org.jdom.JDOMException;

/**
 * WebDAV Servlet Configuration. This class wraps around a ServletConfig object
 * and makes the parameters conveniently accessible to the WebdavServlet and 
 * the WebdavMethod implementations.
 * 
 * @see org.apache.slide.webdav.method.WebdavMethod#getConfig
 * 
 */
public class WebdavServletConfig
    implements ServletConfig {
    
    
    // -------------------------------------------------------------- Constants
    
    
    static final String DEFAULT_SERVLET_PARAMETER =
        "default-servlet";
    
    
    static final String DEPTH_LIMIT_PARAMETER =
        "depth-limit";
    
    
    static final String DEFAULT_MIME_TYPE_PARAMETER =
        "default-mime-type";
    
    
    static final String METHOD_FACTORY_PARAMETER =
        "method-factory";
    
    
    static final String SCOPE_PARAMETER =
        "scope";
    
    static final String LOCKDISCOVERY_INCL_PRINCIPAL =
        "lockdiscoveryIncludesPrincipalURL";

    static final String AUTHENTICATION_HEADER =
        "authentication-header";

    static final String AUTHENTICATION_HEADER_DEFAULT =
        "Basic realm=\"Slide DAV Server\"";

    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * The wrapped ServletConfig.
     */
    protected ServletConfig config;
    
    
    /**
     * Whether or not the servlet is mapped as default servlet of the web 
     * application. This has quite drastic consequences for the mapping of
     * request URIs (the path-info is then returned by getServletPath() instead
     * of getPathInfo()), but there is no safe way for the servlet to determine
     * whether it's mapped as default servlet. For this reason we need an extra
     * initialization parameter to tell us whether we're the default servlet
     * or not.
     *
     * Because the Slide WebdavServlet is usually deployed as default servlet, 
     * this setting defaults to <code>true</code>
     */
    protected boolean isDefaultServlet = true;
    
    
    /**
     * Default MIME type of resources.
     */
    protected String defaultMimeType = "text/plain";
    
    
    /**
     * Depth limit. To limit tree browsing when using depth = infinity.
     */
    protected int depthLimit = 3;
    
    
    /**
     * Scope parameter for servlet configuration.
     * @see #getScope()
     */
    protected String scope = "";
    
    
    /**
     * Class name of the WebdavMethodFactory.
     */
    protected String methodFactory;
    
    /**
     * Maps report-root-element-name -> implementing-class-name
     */
    protected Map externalReports = new HashMap();
    
    protected boolean lockdiscoveryIncludesPrincipalURL = false;
    
    protected String authenticationHeader = AUTHENTICATION_HEADER_DEFAULT;
    
    // ----------------------------------------------------------- Construction
    
    
    /**
     * Constructor.
     *
     * @param config the ServletConfig to wrap
     */
    public WebdavServletConfig(ServletConfig config) {
        
        this.config = config;
        
        ServletContext context = getServletContext();
        String value = null;
        
        // read 'scope' parameter
        value = getInitParameter(SCOPE_PARAMETER);
        if (value == null) {
            value = context.getInitParameter(SCOPE_PARAMETER);
        }
        if (value != null) {
            scope = value;
        }
        
        // read 'depth-limit' parameter
        value = getInitParameter(DEPTH_LIMIT_PARAMETER);
        if (value == null) {
            value = context.getInitParameter(DEPTH_LIMIT_PARAMETER);
        }
        if (value != null) {
            depthLimit = Integer.parseInt(value);
            // value of -1 signifies no depthlimit
            if (depthLimit == -1) {
                depthLimit = Integer.MAX_VALUE;
            }
        }
        
        // read 'default-mime-type' parameter
        value = getInitParameter(DEFAULT_MIME_TYPE_PARAMETER);
        if (value == null) {
            value = context.getInitParameter(DEFAULT_MIME_TYPE_PARAMETER);
        }
        if (value != null) {
            defaultMimeType = value;
        }
        
        // read 'default-servlet' parameter
        value = getInitParameter(DEFAULT_SERVLET_PARAMETER);
        if (value != null) {
            isDefaultServlet = Boolean.valueOf(value).booleanValue();
        }
        
        // read 'method-factory' parameter
        value = getInitParameter(METHOD_FACTORY_PARAMETER);
        if (value == null) {
            value = context.getInitParameter(METHOD_FACTORY_PARAMETER);
        }
        if (value != null) {
            methodFactory = value;
        }
        
        value = getInitParameter(LOCKDISCOVERY_INCL_PRINCIPAL);
        if (value == null) {
            value = context.getInitParameter(LOCKDISCOVERY_INCL_PRINCIPAL);
        }
        if (value != null) {
            lockdiscoveryIncludesPrincipalURL =!("false".equalsIgnoreCase(value));
        }
        
        value = getInitParameter(AUTHENTICATION_HEADER);
        if (value != null) {
            authenticationHeader = value;
        }
        
        // read external reports parameter
        try {
            XMLValue xv = new XMLValue(getInitParameter("external-reports"));
            Iterator i = xv.iterator();
            while (i.hasNext()) {
                Object r = i.next();
                if (r instanceof Element && "report".equals(((Element)r).getName())) {
                    
                    String name = ((Element)r).getAttributeValue("name");
                    String clsName = ((Element)r).getTextTrim();
                    externalReports.put(name, clsName);
                }
            }
        }
        catch (JDOMException e) {
            e.printStackTrace();
        }
    }
    
    
    // ------------------------------------------- ServletConfig Implementation
    
    
    /**
     * Returns a String containing the value of the named initialization 
     * parameter, or null if the parameter does not exist.
     *
     * @param name a String specifying the name of the initialization parameter
     * @return a String containing the value of the initialization parameter
     */
    public String getInitParameter(String name) {
        
        return config.getInitParameter(name);
    }
    
    
    /**
     * Returns the names of the servlet's initialization parameters as an 
     * Enumeration of String objects, or an empty Enumeration if the servlet 
     * has no initialization parameters.
     *
     * @return an Enumeration of String objects containing the names of the 
     *         servlet's initialization parameters
     */
    public Enumeration getInitParameterNames() {
        
        return config.getInitParameterNames();
    }
    
    
    /**
     * Returns a reference to the ServletContext in which the caller 
     * is executing.
     *
     * @return a ServletContext object, used by the caller to interact with 
     *         its servlet container
     */
    public ServletContext getServletContext() {
        
        return config.getServletContext();
    }
    
    
    /**
     * Returns the name of this servlet instance.
     * The name may be provided via server administration, assigned in the 
     * web application deployment descriptor, or for an unregistered (and thus 
     * unnamed) servlet instance it will be the servlet's class name.
     *
     * @return the name of the servlet instance
     */
    public String getServletName() {
        
        return config.getServletName();
    }
    
    // --------------------------------------------------------- Public Methods
    
    
    /**
     * Returns the default MIME type of resources, to be used for example when
     * clients do not specify the content-type of files uploaded with the 
     * PUT method.
     *
     * @return the default MIME type (for example &quot;text/plain&quot;)
     */
    public String getDefaultMimeType() {
        
        return defaultMimeType;
    }
    
    
    /**
     * Returns the depth limit. The depth limit should be used to limit the 
     * depth of (for instance) PROPFIND operations, in case the client has 
     * requested &quot;Depth: infinity&quot;
     *
     * @return the depth limit
     */
    public int getDepthLimit() {
        
        return depthLimit;
    }
    
    
    /**
     * Returns the name of the WebdavMethodFactory class configured by the 
     * user, or the default class name if the corresponding initialization 
     * parameter 'method-factory' was not provided.
     *
     * @return class name of the method factory
     */
    public String getMethodFactory() {
        
        return methodFactory;
    }
    
    
    /**
     * Returns the user defined scope in the namespace that shall be exposed
     * by the WebdavServlet. This should be treated as root directory of the
     * WebDAV namespace. By default this will be an empty string.
     *
     * @return the scope URI
     */
    public String getScope() {
        
        return scope;
    }
    
    
    /**
     * Returns whether the servlet is mapped as default servlet of the web 
     * application.
     * 
     * @returns true if the servlet is configured as default servlet of the
     *          context
     */
    public boolean isDefaultServlet() {
        
        return isDefaultServlet;
    }
    
    /**
     * Returns name of the implementing class of the specified report
     *
     * @param    name                the report root element name
     *
     * @return   a String
     *
     */
    public String getExternalReport(String name) {
        return (String)externalReports.get(name);
    }
    
    public boolean lockdiscoveryIncludesPrincipalURL() {
        return lockdiscoveryIncludesPrincipalURL;
    }
    
    /**
     * Returns the value of the authentication header when (re-)authentication is required by
     * throwing the {@link org.apache.slide.security.UnauthenticatedException}.
     * 
     */
    public String getAuthenticationHeader() {
        return authenticationHeader;
    }
}

