308 lines
12 KiB
Java
308 lines
12 KiB
Java
/*
|
|
* Copyright (C) 2016 LibreCCM Foundation.
|
|
*
|
|
* This library 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 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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 library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
package com.arsdigita.cms;
|
|
|
|
import com.arsdigita.bebop.Page;
|
|
import com.arsdigita.cms.dispatcher.CMSPage;
|
|
import com.arsdigita.cms.ui.CMSApplicationPage;
|
|
import com.arsdigita.cms.ui.contentcenter.MainPage;
|
|
|
|
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
import com.arsdigita.dispatcher.RequestContext;
|
|
import com.arsdigita.kernel.security.Util;
|
|
import com.arsdigita.templating.PresentationManager;
|
|
import com.arsdigita.templating.Templating;
|
|
import com.arsdigita.ui.login.LoginHelper;
|
|
import com.arsdigita.web.ApplicationFileResolver;
|
|
import com.arsdigita.web.BaseApplicationServlet;
|
|
import com.arsdigita.web.LoginSignal;
|
|
import com.arsdigita.web.WebConfig;
|
|
import com.arsdigita.xml.Document;
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
import org.apache.shiro.authz.AuthorizationException;
|
|
import org.libreccm.cdi.utils.CdiUtil;
|
|
import org.libreccm.security.PermissionChecker;
|
|
import org.libreccm.security.Shiro;
|
|
import org.libreccm.web.CcmApplication;
|
|
import org.librecms.contentsection.ContentSection;
|
|
import org.librecms.contentsection.ContentSectionRepository;
|
|
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
|
|
import java.io.IOException;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import javax.servlet.RequestDispatcher;
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.annotation.WebServlet;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
/**
|
|
* CMS ContentCenter (content-center) application servlet serves all request
|
|
* made within the Content Center application.
|
|
*
|
|
* @author Peter Boy <pboy@barkhof.uni-bremen.de>
|
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
*/
|
|
@WebServlet(urlPatterns = "/content-center/*")
|
|
public class ContentCenterServlet extends BaseApplicationServlet {
|
|
|
|
private static final long serialVersionUID = 16543266935651171L;
|
|
|
|
/**
|
|
* URL (pathinfo) -> Page object mapping. Based on it (and the http request
|
|
* url) the doService method to selects a page to display
|
|
*/
|
|
private final Map<String, Page> pages = new HashMap<>();
|
|
|
|
/**
|
|
* Path to directory containg ccm-cms template files
|
|
*/
|
|
private String m_templatePath;
|
|
/**
|
|
* Resolvers to find templates (JSP) and other stuff stored in file system.
|
|
*/
|
|
private ApplicationFileResolver m_resolver;
|
|
|
|
private static final Logger LOGGER = LogManager.getLogger(
|
|
ContentCenterServlet.class);
|
|
|
|
/**
|
|
* Use parent's class initialisation extension point to perform additional
|
|
* initialisation tasks.
|
|
*/
|
|
@Override
|
|
protected void doInit() {
|
|
LOGGER.info("starting doInit method");
|
|
|
|
// NEW STUFF here used to process the pages in this servlet
|
|
// Addresses previously noted in WEB-INF/resources/content-center-map.xml
|
|
// Obviously not required.
|
|
|
|
|
|
addPage("/", new MainPage()); // index page at address ~/cc
|
|
addPage("/index", new MainPage());
|
|
|
|
|
|
// addPage("/item-search", new CMSItemSearchPage());
|
|
// Old style
|
|
//addPage("/item-search", new ItemSearchPage());
|
|
//addPage("/searchredirect", new CMSSearchResultRedirector());
|
|
|
|
// STUFF to use for JSP extension, i.e. jsp's to try for URLs which are not
|
|
// handled by the this servlet directly.
|
|
/**
|
|
* Set Template base path for JSP's
|
|
*/
|
|
// ToDo: Make it configurable by an appropriate config registry entry!
|
|
// m_templatePath = CMS.getConfig().getTemplateRoot();
|
|
m_templatePath = "/templates/ccm-cms/content-center";
|
|
/**
|
|
* Set TemplateResolver class
|
|
*/
|
|
m_resolver = WebConfig.getConfig().getResolver();
|
|
}
|
|
|
|
@Override
|
|
protected void doService(final HttpServletRequest sreq,
|
|
final HttpServletResponse sresp,
|
|
final CcmApplication app) throws ServletException,
|
|
IOException {
|
|
LOGGER.info("starting doService method");
|
|
|
|
// ContentCenter workspace = (ContentCenter) app;
|
|
|
|
/* Check user and privilegies */
|
|
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
if (!shiro.getSubject().isAuthenticated()) {
|
|
throw new LoginSignal(sreq); // send to login page
|
|
}
|
|
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
PermissionChecker.class);
|
|
final ContentSectionRepository sectionRepo = cdiUtil.findBean(
|
|
ContentSectionRepository.class);
|
|
final List<ContentSection> sections = sectionRepo.findAll();
|
|
boolean hasAccess = false;
|
|
for (final ContentSection section : sections) {
|
|
if (permissionChecker.isPermitted(ItemPrivileges.EDIT,
|
|
section.getRootDocumentsFolder())) {
|
|
hasAccess = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!hasAccess) { // user has no access privilege
|
|
throw new AuthorizationException(
|
|
"User is not entitled to access any content section");
|
|
// throw new LoginSignal(sreq); // send to login page
|
|
}
|
|
|
|
// New way to fetch the page
|
|
String pathInfo = sreq.getPathInfo();
|
|
if (pathInfo.length() > 1 && pathInfo.endsWith("/")) {
|
|
/* NOTE: ServletAPI specifies, pathInfo may be empty or will
|
|
* start with a '/' character. It currently carries a
|
|
* trailing '/' if a "virtual" page, i.e. not a real jsp, but
|
|
* result of a servlet mapping. But Application requires url
|
|
* NOT to end with a trailing '/' for legacy free applications. */
|
|
pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
|
|
}
|
|
|
|
// An empty remaining URL or a URL which doesn't end in trailing slash:
|
|
// probably want to redirect.
|
|
// Probably DEPRECATED with new access method or only relevant for jsp
|
|
// extension
|
|
// if (m_trailingSlashList.contains(url) && !originalUrl.endsWith("/")) {
|
|
// DispatcherHelper.sendRedirect(sresp, originalUrl + "/");
|
|
// return;
|
|
// }
|
|
final Page page = pages.get(pathInfo);
|
|
if (page != null) {
|
|
|
|
// Check user access.
|
|
checkUserAccess(sreq, sresp);
|
|
|
|
if (page instanceof CMSPage) {
|
|
// backwards compatibility fix until migration completed
|
|
final CMSPage cmsPage = (CMSPage) page;
|
|
final RequestContext ctx = DispatcherHelper.getRequestContext();
|
|
cmsPage.init();
|
|
cmsPage.dispatch(sreq, sresp, ctx);
|
|
} else {
|
|
final CMSApplicationPage cmsAppPage = (CMSApplicationPage) page;
|
|
cmsAppPage.init(sreq, sresp, app);
|
|
// Serve the page.
|
|
final Document doc = cmsAppPage.buildDocument(sreq, sresp);
|
|
|
|
PresentationManager pm = Templating.getPresentationManager();
|
|
pm.servePage(doc, sreq, sresp);
|
|
}
|
|
|
|
} else {
|
|
// Fall back on the JSP application dispatcher.
|
|
// NOTE: The JSP must ensure the proper authentication and
|
|
// authorisation if required!
|
|
LOGGER.info("NO page registered to serve the requst url.");
|
|
|
|
RequestDispatcher rd = m_resolver.resolve(m_templatePath,
|
|
sreq, sresp, app);
|
|
if (rd != null) {
|
|
LOGGER.debug("Got dispatcher " + rd);
|
|
|
|
final HttpServletRequest origreq = DispatcherHelper
|
|
.restoreOriginalRequest(sreq);
|
|
rd.forward(origreq, sresp);
|
|
} else {
|
|
|
|
sresp.sendError(404, sreq.getRequestURI()
|
|
+ " not found on this server.");
|
|
}
|
|
|
|
}
|
|
|
|
LOGGER.info("doService method completed");
|
|
|
|
} // END doService()
|
|
|
|
/**
|
|
* Internal service mechod, adds one pair of Url - Page to the internal hash
|
|
* map, used as a cache.
|
|
*
|
|
* @param pathInfo url stub for a page to display
|
|
* @param page Page object to display
|
|
*/
|
|
private void addPage(final String pathInfo, final Page page) {
|
|
|
|
// Current Implementation requires pathInfo to start with a leading '/'
|
|
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
|
|
// with a '/' character."
|
|
pages.put(pathInfo, page);
|
|
|
|
}
|
|
|
|
// /**
|
|
// * Service Method returns the URL stub for the class name, can return null
|
|
// * if not mapped
|
|
// */
|
|
// // Currently still in use by c.ad.cms.ui.ItemSearchWidget
|
|
// public static String getURLStubForClass(String classname) {
|
|
// LOGGER.debug("Getting URL Stub for : " + classname);
|
|
// Iterator itr = s_pageURLs.keySet().iterator();
|
|
// while (itr.hasNext()) {
|
|
// String classname2 = (String) itr.next();
|
|
// s_log.debug("key: " + classname + " value: "
|
|
// + (String) s_pageURLs.get(classname2));
|
|
// }
|
|
// String url = (String) s_pageURLs.get(classname);
|
|
// return url;
|
|
// }
|
|
/**
|
|
* Verify that the user is logged in and is able to view the page.
|
|
* Subclasses can override this method if they need to, but should always be
|
|
* sure to call super.checkUserAccess(...)
|
|
*
|
|
* @param request The HTTP request
|
|
* @param response The HTTP response
|
|
* @param actx The request context
|
|
*
|
|
*/
|
|
protected void checkUserAccess(final HttpServletRequest request,
|
|
final HttpServletResponse response //,
|
|
/// final RequestContext actx
|
|
)
|
|
throws ServletException {
|
|
|
|
if (!CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject()
|
|
.isAuthenticated()) {
|
|
throw new LoginSignal(request);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirects the client to the login page, setting the return url to the
|
|
* current request URI.
|
|
*
|
|
* @exception ServletException If there is an exception thrown while trying
|
|
* to redirect, wrap that exception in a
|
|
* ServletException
|
|
*
|
|
*/
|
|
protected void redirectToLoginPage(HttpServletRequest req,
|
|
HttpServletResponse resp)
|
|
throws ServletException {
|
|
String url = Util.getSecurityHelper()
|
|
.getLoginURL(req)
|
|
+ "?" + LoginHelper.RETURN_URL_PARAM_NAME
|
|
+ "=" + DispatcherHelper.encodeReturnURL(req);
|
|
try {
|
|
LoginHelper.sendRedirect(req, resp, url);
|
|
} catch (IOException e) {
|
|
LOGGER.error("IO Exception", e);
|
|
throw new ServletException(e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
|
|
}
|