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