// This file is part of AceWiki. // Copyright 2008-2013, AceWiki developers. // // AceWiki 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. // // AceWiki 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 AceWiki. If // not, see http://www.gnu.org/licenses/. package ch.uzh.ifi.attempto.acewiki; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import nextapp.echo.app.ApplicationInstance; import nextapp.echo.webcontainer.WebContainerServlet; import ch.uzh.ifi.attempto.base.APE; import ch.uzh.ifi.attempto.base.LoggerContext; /** * This servlet class is used by the web server to start AceWiki. * In order to run the AceWiki servlet, a web application archive (WAR) file has to be created. * See the <a href="{@docRoot}/README.txt">README file</a> and the * <a href="{@docRoot}/web.xml">web.xml example file</a>. *<p> * An APE should be accessible for the server, either directly installed on local or using socket * or web service. See the documentation of {@link APE} for more information. *<p> * For larger ontologies it might be necessary to adjust the stack and heap size, for example by * the following Java VM arguments: * <code>-Xmx400m -Xss4m</code> * * @author Tobias Kuhn * @author Yu Changyuan */ public class AceWikiServlet extends WebContainerServlet { private static final long serialVersionUID = -7342857942059126499L; private final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass()); private LoggerContext loggerContext; private Backend backend; private Map<String, String> parameters; private String backendName; /** * Creates a new AceWiki servlet object. */ public AceWikiServlet() { } /** * Init the AceWiki servlet, get its Backend from ServletContext according * to its config in web.xml or create backend if no 'backend' parameter * exist. * * @param config servlet config. */ public void init(ServletConfig config) throws ServletException { parameters = getInitParameters(config); if (loggerContext == null) { loggerContext = new LoggerContext("syst", "syst", "0"); } loggerContext.propagateWithinThread(); org.slf4j.MDC.put("type", "appl"); backendName = config.getInitParameter("backend"); if (backendName != null) { log.info("use backend: {}", backendName); while (true) { backend = (Backend) config.getServletContext().getAttribute(backendName); if (backend != null) break; try { Thread.sleep(1000); } catch (InterruptedException e) { break; } } // merge backend parameters Map<String, String> p = parameters; parameters = new HashMap<String,String>(); parameters.putAll(backend.getParameters()); parameters.putAll(p); } else { log.info("create backend"); APE.setParameters(parameters); backend = new Backend(parameters); } super.init(config); } public ApplicationInstance newApplicationInstance() { loggerContext.propagateWithinThread(); org.slf4j.MDC.put("type", "appl"); log.info("new application instance: {}", parameters.get("ontology")); return new AceWikiApp(backend, parameters); } protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String params = ""; String p; boolean hasInternalParams = false; // URLs of the form "...?showpage=ArticleName" can be used to access an article directly. // For the internal processing "...?page=ArticleName" is used. p = request.getParameter("showpage"); if (p != null) params += "&page=" + p; if (request.getParameter("page") != null) hasInternalParams = true; // URLs of the form "...?showlang=Language" can be used to access a specific language // version of the wiki. For the internal processing "...?lang=Language" is used. p = request.getParameter("showlang"); if (p != null) params += "&lang=" + p; if (request.getParameter("lang") != null) hasInternalParams = true; if (!request.getSession().isNew() && params.length() > 0) { response.sendRedirect( response.encodeRedirectURL("?sid=ExternalEvent" + params) ); } if (params.length() == 0 && hasInternalParams && request.getParameter("sid") == null) { response.sendRedirect(response.encodeRedirectURL(".")); } org.slf4j.MDC.put("type", "fail"); try { super.process(request, response); } catch (RuntimeException | IOException | ServletException ex) { loggerContext.propagateWithinThread(); log.error("fatal error", ex); ex.printStackTrace(); throw ex; } } @SuppressWarnings("rawtypes") static Map<String, String> getInitParameters(ServletConfig config) { Map<String, String> initParameters = new HashMap<String, String>(); Enumeration paramEnum = config.getInitParameterNames(); while (paramEnum.hasMoreElements()) { String n = paramEnum.nextElement().toString(); initParameters.put(n, config.getInitParameter(n)); } Enumeration contextParamEnum = config.getServletContext().getInitParameterNames(); while (contextParamEnum.hasMoreElements()) { String n = contextParamEnum.nextElement().toString(); initParameters.put("context:" + n, config.getServletContext().getInitParameter(n)); } // Set default parameters: if (initParameters.get("context:apecommand") == null) { initParameters.put("context:apecommand", "ape.exe"); } if (initParameters.get("context:logdir") == null) { initParameters.put("context:logdir", "logs"); } if (initParameters.get("context:datadir") == null) { initParameters.put("context:datadir", "data"); } return initParameters; } }