//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.servlet;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/* ------------------------------------------------------------ */
/**  Dynamic Servlet Invoker.
 * This servlet invokes anonymous servlets that have not been defined
 * in the web.xml or by other means. The first element of the pathInfo
 * of a request passed to the envoker is treated as a servlet name for
 * an existing servlet, or as a class name of a new servlet.
 * This servlet is normally mapped to /servlet/*
 * This servlet support the following initParams:
 * <PRE>
 *  nonContextServlets       If false, the invoker can only load
 *                           servlets from the contexts classloader.
 *                           This is false by default and setting this
 *                           to true may have security implications.
 *
 *  verbose                  If true, log dynamic loads
 *
 *  *                        All other parameters are copied to the
 *                           each dynamic servlet as init parameters
 * </PRE>
 * @version $Id: Invoker.java 4780 2009-03-17 15:36:08Z jesse $
 *
 */
public class Invoker extends HttpServlet
{
    private static final Logger LOG = Log.getLogger(Invoker.class);


    private ContextHandler _contextHandler;
    private ServletHandler _servletHandler;
    private Map.Entry<String, ServletHolder> _invokerEntry;
    private Map<String, String> _parameters;
    private boolean _nonContextServlets;
    private boolean _verbose;

    /* ------------------------------------------------------------ */
    public void init()
    {
        ServletContext config=getServletContext();
        _contextHandler=((ContextHandler.Context)config).getContextHandler();

        Handler handler=_contextHandler.getHandler();
        while (handler!=null && !(handler instanceof ServletHandler) && (handler instanceof HandlerWrapper))
            handler=((HandlerWrapper)handler).getHandler();
        _servletHandler = (ServletHandler)handler;
        Enumeration<String> e = getInitParameterNames();
        while(e.hasMoreElements())
        {
            String param=e.nextElement();
            String value=getInitParameter(param);
            String lvalue=value.toLowerCase(Locale.ENGLISH);
            if ("nonContextServlets".equals(param))
            {
                _nonContextServlets=value.length()>0 && lvalue.startsWith("t");
            }
            if ("verbose".equals(param))
            {
                _verbose=value.length()>0 && lvalue.startsWith("t");
            }
            else
            {
                if (_parameters==null)
                    _parameters=new HashMap<String, String>();
                _parameters.put(param,value);
            }
        }
    }

    /* ------------------------------------------------------------ */
    protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        // Get the requested path and info
        boolean included=false;
        String servlet_path=(String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
        if (servlet_path==null)
            servlet_path=request.getServletPath();
        else
            included=true;
        String path_info = (String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
        if (path_info==null)
            path_info=request.getPathInfo();

        // Get the servlet class
        String servlet = path_info;
        if (servlet==null || servlet.length()<=1 )
        {
            response.sendError(404);
            return;
        }


        int i0=servlet.charAt(0)=='/'?1:0;
        int i1=servlet.indexOf('/',i0);
        servlet=i1<0?servlet.substring(i0):servlet.substring(i0,i1);

        // look for a named holder
        ServletHolder[] holders = _servletHandler.getServlets();
        ServletHolder holder = getHolder (holders, servlet);

        if (holder!=null)
        {
            // Found a named servlet (from a user's web.xml file) so
            // now we add a mapping for it
            if (LOG.isDebugEnabled())
                LOG.debug("Adding servlet mapping for named servlet:"+servlet+":"+URIUtil.addPaths(servlet_path,servlet)+"/*");
            ServletMapping mapping = new ServletMapping();
            mapping.setServletName(servlet);
            mapping.setPathSpec(URIUtil.addPaths(servlet_path,servlet)+"/*");
            _servletHandler.setServletMappings(ArrayUtil.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
        }
        else
        {
            // look for a class mapping
            if (servlet.endsWith(".class"))
                servlet=servlet.substring(0,servlet.length()-6);
            if (servlet==null || servlet.length()==0)
            {
                response.sendError(404);
                return;
            }

            synchronized(_servletHandler)
            {
                // find the entry for the invoker (me)
                 _invokerEntry=_servletHandler.getHolderEntry(servlet_path);

                // Check for existing mapping (avoid threaded race).
                String path=URIUtil.addPaths(servlet_path,servlet);
                Map.Entry<String, ServletHolder> entry = _servletHandler.getHolderEntry(path);

                if (entry!=null && !entry.equals(_invokerEntry))
                {
                    // Use the holder
                    holder=(ServletHolder)entry.getValue();
                }
                else
                {
                    // Make a holder
                    if (LOG.isDebugEnabled())
                        LOG.debug("Making new servlet="+servlet+" with path="+path+"/*");
                    holder=_servletHandler.addServletWithMapping(servlet, path+"/*");

                    if (_parameters!=null)
                        holder.setInitParameters(_parameters);

                    try {holder.start();}
                    catch (Exception e)
                    {
                        LOG.debug(e);
                        throw new UnavailableException(e.toString());
                    }

                    // Check it is from an allowable classloader
                    if (!_nonContextServlets)
                    {
                        Object s=holder.getServlet();

                        if (_contextHandler.getClassLoader()!=
                            s.getClass().getClassLoader())
                        {
                            try
                            {
                                holder.stop();
                            }
                            catch (Exception e)
                            {
                                LOG.ignore(e);
                            }

                            LOG.warn("Dynamic servlet "+s+
                                         " not loaded from context "+
                                         request.getContextPath());
                            throw new UnavailableException("Not in context");
                        }
                    }

                    if (_verbose && LOG.isDebugEnabled())
                        LOG.debug("Dynamic load '"+servlet+"' at "+path);
                }
            }
        }

        if (holder!=null)
        {
            final Request baseRequest=Request.getBaseRequest(request);
            holder.handle(baseRequest,
                    new InvokedRequest(request,included,servlet,servlet_path,path_info),
                          response);
        }
        else
        {
            LOG.info("Can't find holder for servlet: "+servlet);
            response.sendError(404);
        }


    }

    /* ------------------------------------------------------------ */
    class InvokedRequest extends HttpServletRequestWrapper
    {
        String _servletPath;
        String _pathInfo;
        boolean _included;

        /* ------------------------------------------------------------ */
        InvokedRequest(HttpServletRequest request,
                boolean included,
                String name,
                String servletPath,
                String pathInfo)
        {
            super(request);
            _included=included;
            _servletPath=URIUtil.addPaths(servletPath,name);
            _pathInfo=pathInfo.substring(name.length()+1);
            if (_pathInfo.length()==0)
                _pathInfo=null;
        }

        /* ------------------------------------------------------------ */
        public String getServletPath()
        {
            if (_included)
                return super.getServletPath();
            return _servletPath;
        }

        /* ------------------------------------------------------------ */
        public String getPathInfo()
        {
            if (_included)
                return super.getPathInfo();
            return _pathInfo;
        }

        /* ------------------------------------------------------------ */
        public Object getAttribute(String name)
        {
            if (_included)
            {
                if (name.equals(Dispatcher.INCLUDE_REQUEST_URI))
                    return URIUtil.addPaths(URIUtil.addPaths(getContextPath(),_servletPath),_pathInfo);
                if (name.equals(Dispatcher.INCLUDE_PATH_INFO))
                    return _pathInfo;
                if (name.equals(Dispatcher.INCLUDE_SERVLET_PATH))
                    return _servletPath;
            }
            return super.getAttribute(name);
        }
    }


    private ServletHolder getHolder(ServletHolder[] holders, String servlet)
    {
        if (holders == null)
            return null;

        ServletHolder holder = null;
        for (int i=0; holder==null && i<holders.length; i++)
        {
            if (holders[i].getName().equals(servlet))
            {
                holder = holders[i];
            }
        }
        return holder;
    }
}
