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

com.manydesigns.portofino.dispatcher.Dispatcher Maven / Gradle / Ivy

/*
 * Copyright (C) 2005-2017 ManyDesigns srl.  All rights reserved.
 * http://www.manydesigns.com/
 *
 * This 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 3 of
 * the License, or (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package com.manydesigns.portofino.dispatcher;

import com.manydesigns.elements.ElementsThreadLocals;
import com.manydesigns.elements.servlet.ServletUtils;
import com.manydesigns.portofino.di.Injections;
import com.manydesigns.portofino.pages.Page;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Factory object that can produce {@link Dispatch} instances given the requested path.
 *
 * @author Paolo Predonzani     - [email protected]
 * @author Angelo Lupo          - [email protected]
 * @author Giampiero Granatella - [email protected]
 * @author Alessio Stalla       - [email protected]
 */
public class Dispatcher {
    public static final String copyright =
            "Copyright (C) 2005-2017 ManyDesigns srl";

    public static final Logger logger =
            LoggerFactory.getLogger(Dispatcher.class);

    protected final Configuration configuration;
    protected final File pagesDirectory;
    protected final Map cache = new ConcurrentHashMap();

    public Dispatcher(Configuration configuration, File pagesDirectory) {
        this.configuration = configuration;
        this.pagesDirectory = pagesDirectory;
    }

    /**
     * Returns a dispatch for the provided path.
     * @param path the path to resolve, not including the context path.
     * @return the dispatch. If no dispatch can be constructed, this method returns null.
     */
    public Dispatch getDispatch(String path) {
        if(!isPotentialPagePath(path)) {
            logger.debug("Path is certainly not a page ({}), not dispatching to save time.", path);
            return null;
        }

        path = normalizePath(path);

        if(path.isEmpty() || path.equals("/")) {
            return null;
        }

        Dispatch dispatch = cache.get(path);
        if(dispatch != null) {
            return dispatch;
        }

        int index;
        String subPath = path;
        while((index = subPath.lastIndexOf('/')) != -1) {
            subPath = path.substring(0, index);
            dispatch = cache.get(subPath);
            if(dispatch != null) {
                break;
            }
        }

        Iterator fragmentsIterator;
        DispatchElement currentElement;
        PageInstance currentPageInstance;
        List pagePath = new ArrayList();
        if(dispatch == null) {
            String[] fragments = StringUtils.split(path, '/');
            List fragmentsAsList = Arrays.asList(fragments);
            fragmentsIterator = fragmentsAsList.iterator();
            try {
                currentElement = new Root();
                currentPageInstance = currentElement.getPageInstance();
                pagePath.add(currentPageInstance);
            } catch (Exception e) {
                logger.error("Cannot load root page", e);
                return null;
            }
        } else {
            pagePath = new ArrayList(Arrays.asList(dispatch.getPageInstancePath()));
            String[] fragments = StringUtils.split(path.substring(subPath.length()), '/');

            List fragmentsAsList = Arrays.asList(fragments);
            fragmentsIterator = fragmentsAsList.listIterator();
            currentElement = dispatch.getLastPageInstance().getActionBean();
        }

        while(fragmentsIterator.hasNext()) {
            try {
                currentElement = currentElement.consumePathFragment(fragmentsIterator.next());
                if(currentElement == null) {
                    logger.debug("Couldn't create dispatch");
                    return null;
                }
                currentPageInstance = currentElement.getPageInstance();
                if(!pagePath.contains(currentPageInstance)) {
                    pagePath.add(currentPageInstance);
                }
            } catch (Exception e) {
                logger.error("Couldn't create dispatch", e);
                return null;
            }
        }
        dispatch = new Dispatch(pagePath.toArray(new PageInstance[pagePath.size()]));
        cache.put(path, dispatch);
        return dispatch;
    }

    protected boolean isPotentialPagePath(String path) {
        return !(
                ((path.startsWith("/webjars/") || path.startsWith("/theme/") || path.startsWith("/m/")) &&
                 (path.endsWith(".js") || path.endsWith(".css") || path.endsWith(".html"))) ||
                path.endsWith(".jsp"));
    }

    protected static String normalizePath(String originalPath) {
        String path = ServletUtils.removePathParameters(originalPath);
        path = ServletUtils.removeRedundantTrailingSlashes(path);
        return path;
    }

    public class Root implements DispatchElement {

        private PageInstance pageInstance;

        public Root() {
            Page rootPage = DispatcherLogic.getPage(pagesDirectory);
            pageInstance = new PageInstance(null, pagesDirectory, rootPage, null);
        }

        @Override
        public DispatchElement consumePathFragment(String pathFragment) {
            PageAction subpage = DispatcherLogic.getSubpage(configuration, pageInstance, pathFragment);
            HttpServletRequest request = ElementsThreadLocals.getHttpServletRequest();
            Injections.inject(subpage, request.getServletContext(), request);
            return subpage;
        }

        public PageInstance getPageInstance() {
            return pageInstance;
        }

        public void setPageInstance(PageInstance pageInstance) {
            this.pageInstance = pageInstance;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy