All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.grizzly.http.servlet.deployer.WebAppAdapter Maven / Gradle / Ivy

/**
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. *
 * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved. *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 *
 * Contributor(s):
 *
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 */
package com.sun.grizzly.http.servlet.deployer;

import com.sun.grizzly.http.servlet.ServletAdapter;
import com.sun.grizzly.http.webxml.schema.*;
import com.sun.grizzly.tcp.http11.GrizzlyRequest;
import com.sun.grizzly.tcp.http11.GrizzlyResponse;
import com.sun.grizzly.tcp.http11.GrizzlyAdapter;
import com.sun.grizzly.util.ClassLoaderUtil;

import javax.servlet.Servlet;
import javax.servlet.Filter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * {@link com.sun.grizzly.http.webxml.schema.WebApp} Adapter.
 *
 * @author Sebastien Dionne
 * @author Hubert Iwaniuk
 * @since Aug 25, 2009
 */
public class WebAppAdapter extends ServletAdapter {

    private static Logger logger = Logger.getLogger("WebAppAdapter");
    private static final String EMPTY_SERVLET_PATH = "";

    private static final String ROOT = "/";

    private Map> toRegister = new HashMap>();
    private WebApp webApp;
    private ClassLoader webAppCL;
    private String root;
    private String context;
    
    /**
     * Blank constructor
     */
    public WebAppAdapter(){
    	
    }

    /**
     * Default constructor, takes care of setting up adapter.
     *
     * @param root       Root folder, for serving static resources
     * @param context    Context to be deployed to.
     * @param webApp     Web application to be run by this adapter.
     * @param webAppCL   Web application class loader.
     * @param webdefault Default web application.
     */
    public WebAppAdapter(String root, String context, final WebApp webApp, ClassLoader webAppCL, WebApp webdefault) {
        this.root = root;
        this.context = context;
        if (webdefault != null) {
            this.webApp = webApp.mergeWith(webdefault);
        } else {
            this.webApp = webApp;
        }
        this.webAppCL = webAppCL;
        ClassLoader prevCL = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(webAppCL);
        try {
            initialize();
        } finally {
            Thread.currentThread().setContextClassLoader(prevCL);
        }
    }

    private void initialize() {

        boolean blankContextServletPathFound = false;
        boolean defaultContextServletPathFound = false;

        List aliasesUsed = new ArrayList();

        for (Map.Entry> adapterAliases :
                getServletAdaptersToAlises(webApp, context).entrySet()) {
            ServletAdapter sa = adapterAliases.getKey();
            sa.setClassLoader(webAppCL);

            // set context params
            setContextParams(webApp, sa);

            // set Filters for this context if there are some
            setFilters(webApp, sa);

            // set Listeners
            setListeners(webApp, sa);

            //set root Folder
            sa.addRootFolder(root);

            // create the alias array from the list of urlPattern
            String alias[] = getAlias(sa, adapterAliases.getValue());

            // need to be disabled for JSP
            sa.setHandleStaticResources(false);

            // enabled it if not / or /*
            for (String item : alias) {
                if (item.endsWith(ROOT) || item.endsWith("/*")) {
                    sa.setHandleStaticResources(true);
                }
            }

            if (logger.isLoggable(Level.FINEST)) {
                logServletAdapterConfigurationWithAliases(sa, alias);
            }

            // keep trace of mapping
            List stringList = Arrays.asList(alias);
            aliasesUsed.addAll(stringList);

            toRegister.put(sa, new HashSet(stringList));

            if (ROOT.equals(sa.getServletPath())) {
                defaultContextServletPathFound = true;
            }

            if (EMPTY_SERVLET_PATH.equals(sa.getServletPath())) {
                blankContextServletPathFound = true;
            }
        }

        // we need one servlet that will handle "/"
        if (!defaultContextServletPathFound) {
            logger.log(Level.FINEST, "Adding a ServletAdapter to handle / path");
            createAndInstallServletAdapter(root, context, ROOT);
        }

        // pour les jsp dans le root du context
        if (!blankContextServletPathFound && !aliasesUsed.contains(context + ROOT)) {
            logger.log(Level.FINEST, "Adding a ServletAdapter to handle root path");
            createAndInstallServletAdapter(root, context, EMPTY_SERVLET_PATH);
        }
    }

    private void createAndInstallServletAdapter(
            final String rootFolder, final String context, final String tmpPath) {
        ServletAdapter sa = new ServletAdapter();

        sa.setContextPath(context);
        sa.setServletPath(tmpPath);
        sa.setHandleStaticResources(true);
        sa.addRootFolder(rootFolder);

        logServletAdapterConfiguration(context, sa);

        toRegister.put(sa, Collections.singleton(context + ROOT));
    }

    private static void logServletAdapterConfiguration(final String ctx, final ServletAdapter sa) {
        if (logger.isLoggable(Level.FINEST)) {
            debugServletAdapterConfiguration(sa, ctx + ROOT);
        }
    }

    public void service(final GrizzlyRequest request, final GrizzlyResponse response) {
        ClassLoader prevCL = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(webAppCL);
        try {
            // TODO here we should take care of welcome-file
        } finally {
            Thread.currentThread().setContextClassLoader(prevCL);
        }
    }

    /**
     * @param webApp  Contains the info about the web.xml
     * @param context context of the application
     * @return a list of ServletAdapter with the UrlPattern for each Servlet.
     */
    public Map> getServletAdaptersToAlises(WebApp webApp, String context) {

        Map> servletAdapterMap;

        if (webApp == null || webApp.getServletMapping() == null || webApp.getServletMapping().isEmpty()) {
            ServletAdapter sa = new ServletAdapter();

            sa.setContextPath(context);
            sa.setServletPath(EMPTY_SERVLET_PATH);

            servletAdapterMap = new HashMap>(1);
            servletAdapterMap.put(sa, Arrays.asList(ROOT));
        } else {
            // if we have servletMapping

            final List mappings = webApp.getServletMapping();
            servletAdapterMap = new HashMap>(mappings.size());
            for (ServletMapping servletMapping : mappings) {

                List urlPatternList = servletMapping.getUrlPattern();

                //TODO support multiple urlPattern ???  for that the SA need to have multiple servletpath ?
                // ex  : urlPattern = /xxx/1.y
                //       urlPattern = /xxx/yyy/1.z
                //       the servlet path will not be the same.. do we create 2 SA ?

                // WE WILL GET ONLY THE FIRST urlPattern
                String urlPattern;
                //if empty, assume "/" as context
                if (urlPatternList == null || urlPatternList.isEmpty()) {
                    urlPattern = ROOT;
                } else {
                    urlPattern = urlPatternList.get(0);
                }

                // get the context path. The urlPattern could be "", "/",
                // "/bla/xyz/..."
                // just to be sure we don't obtain two slash "//"

                if (!urlPattern.startsWith(ROOT)) {
                    urlPattern = String.format("%s%s", ROOT, urlPattern);
                }
                String servletUrlPattern = urlPattern;

                if (servletUrlPattern.indexOf("//") > -1) {
                    servletUrlPattern = servletUrlPattern.replaceAll("//", ROOT);
                }

                ServletAdapter sa = createServletAdapter(context, servletUrlPattern);

                // Set the Servlet
                setServlet(webApp, sa, servletMapping);

                servletAdapterMap.put(sa, Arrays.asList(urlPattern));
            }
        }

        return servletAdapterMap;
    }

    protected static void setServlet(WebApp webApp, ServletAdapter sa, ServletMapping servletMapping) {
        //we need to get the servlet according to the servletMapping
        for (com.sun.grizzly.http.webxml.schema.Servlet servletItem : webApp.getServlet()) {

            if (servletItem.getServletName().equalsIgnoreCase(servletMapping.getServletName())) {
                sa.setServletInstance((Servlet) ClassLoaderUtil.load(servletItem.getServletClass()));

                List initParamsList = servletItem.getInitParam();

                if (initParamsList != null && !initParamsList.isEmpty()) {
                    for (InitParam element : initParamsList) {
                        sa.addInitParameter(element.getParamName(), element.getParamValue());
                    }
                }
                
                // load-on-startup
                
                int loadOnStartup = -1;
                
                try {
                	loadOnStartup = Integer.parseInt(servletItem.loadOnStartup);
                } catch (Exception e){
                	
                }
                
                if(loadOnStartup!=-1){
                	sa.setProperty(ServletAdapter.LOAD_ON_STARTUP, Boolean.TRUE);
                }
                
                break;
            }
        }
    }

    /**
     * @param path Path to convert.
     * @return Converted path.
     */
    public static String getServletPath(String path) {

        String result;
        if (path == null) {
            result = ROOT;
        } else {

            // need to replace "\" and "\\" by "/"
            result = path.replaceAll("\\\\", ROOT);

            // the path need to start by "/"
            if (!result.startsWith(ROOT)) {
                result = ROOT + result;
            }

            // we could have multiples options
            // /servlet
            // /servlet/
            // /servlet/subpath
            // /servlet/subpath/
            // /servlet/* or /servlet/*.x
            // all theses must return /servlet

            // remove the trailing "/"
            if (result.endsWith(ROOT) && result.length() > 1) {
                result = result.substring(0, result.length() - 1);
            } else if (!result.endsWith(ROOT)) {

                // find the last "/"
                int index = result.lastIndexOf(ROOT);

                // find if we have a wildcard "*" or a extension "."
                if (result.lastIndexOf('*') > index || result.lastIndexOf('.') > index) {

                    // do we have something like : /a.cdcdcd or /* or /*.abc
                    if (index == 0) {
                        result = ROOT;
                    } else if (index > 0) {
                        //remove the urlpattern
                        if (index < result.length()) {
                            result = result.substring(0, index);
                        }
                    }
                }
            }
        }
        return result;
    }

    protected ServletAdapter createServletAdapter(
            final String context, final String servletUrlPattern) {
        ServletAdapter sa = new ServletAdapter();
        sa.setContextPath(context);

        // be sure not the get the extension mapping
        // like /blabla/*.jsp
        sa.setServletPath(getServletPath(servletUrlPattern));
        return sa;
    }

    protected static void setFilters(WebApp webApp, ServletAdapter sa) {

        if (webApp == null || sa == null) {
            return;
        }

        // Add the Filters
        List filterList = webApp.getFilter();

        List filterMappingList = webApp.getFilterMapping();

        if (filterList != null && !filterList.isEmpty()) {
            for (com.sun.grizzly.http.webxml.schema.Filter filterItem : filterList) {

                // we had the filter if the url-pattern is for this context
                // we need to get the right filter-mapping form the name
                for (FilterMapping filterMapping : filterMappingList) {

                    //we need to find in the filterMapping is for this filter
                    if (filterItem.getFilterName().equalsIgnoreCase(filterMapping.getFilterName())) {
                        Filter filter = (Filter) ClassLoaderUtil.load(filterItem.getFilterClass());

                        // initParams
                        List initParamList = filterItem.getInitParam();

                        Map initParamsMap = new HashMap();
                        if (initParamList != null) {
                            for (InitParam param : initParamList) {
                                initParamsMap.put(param.getParamName(), param.getParamValue());
                            }
                        }

                        sa.addFilter(filter, filterItem.getFilterName(), initParamsMap);

                    }
                }

            }
        }


    }

    protected static void setListeners(WebApp webApp, ServletAdapter sa) {
        if (webApp == null || sa == null) {
            return;
        }

        // Add the Listener
        List listeners = webApp.getListener();

        if (listeners != null) {
            for (Listener element : listeners) {
                sa.addServletListener(element.getListenerClass());
            }
        }
    }

    protected static void setContextParams(WebApp webApp, ServletAdapter sa) {
        if(webApp == null || sa == null) {
            return;
        }

        // Add the context param
        List contextParmas = webApp.getContextParam();

        if(contextParmas != null) {
            for(ContextParam element : contextParmas) {
                sa.addContextParameter(element.getParamName(), element.getParamValue());
            }
        }
    }

    /**
     * @param sa      ServletAdapter
     * @param aliases contains the list of UrlPattern for this ServletAdapter
     * @return the alias list for this ServletAdapter
     */
    public static String[] getAlias(ServletAdapter sa, Collection aliases) {

        List aliasList;
        if (sa == null || aliases == null) {
            // Default context
            aliasList = Arrays.asList(ROOT);
        } else {

            aliasList = new ArrayList(aliases.size());
            for (String urlPattern : aliases) {

                String mapping = EMPTY_SERVLET_PATH;

                if (!sa.getServletPath().equals(urlPattern) && urlPattern.indexOf(sa.getServletPath()) > -1) {
                    mapping = urlPattern.substring(urlPattern.indexOf(sa.getServletPath()) + sa.getServletPath().length());
                }

                // the alias is the context + servletPath + mapping
                String aliasTmp = String.format("%s%s%s", sa.getContextPath(), sa.getServletPath(), mapping);

                if (aliasTmp.indexOf("//") > -1) {
                    aliasTmp = aliasTmp.replaceAll("//", ROOT);
                }
                aliasList.add(aliasTmp);
            }
        }
        return aliasList.toArray(new String[aliasList.size()]);
    }

    static void logServletAdapterConfigurationWithAliases(
            final ServletAdapter sa, final String[] aliases) {
        StringBuilder sb = new StringBuilder(64);
        sb.append('[');
        for (String item : aliases) {
            sb.append(item).append(',');
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(']');
        debugServletAdapterConfiguration(sa, sb.toString());
    }

    static void debugServletAdapterConfiguration(
            final ServletAdapter sa, final String alias) {
        logger.log(Level.FINEST, "sa context=" + sa.getContextPath());
        logger.log(Level.FINEST, "sa servletPath=" + sa.getServletPath());
        logger.log(Level.FINEST, "sa alias=" + alias);
        logger.log(Level.FINEST, "sa rootFolders=" + sa.getRootFolders());
    }

    public Map> getToRegister() {
        return toRegister;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy