/******************************************************************************* * Copyright 2015 xWic group (http://www.xwic.de) * * Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ /* * de.jwic.web.DispatcherServlet * $Id: DispatcherServlet.java,v 1.9 2012/09/02 13:21:09 lordsam Exp $ */ package de.jwic.web; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.PropertyConfigurator; import de.jwic.base.ConfigurationTool; import de.jwic.base.IApplicationSetup; import de.jwic.base.JWicRuntime; import de.jwic.base.XmlApplicationSetup; import de.jwic.upload.Upload; /** * Dispatches incoming request to an existing or new JWic session. * * <p>The DispatcherServlet can initialize a log4j system if required. To do so, * place a log4j.properties file somewhere (WEB-INF is a good place) and point * to it using the init-param "log4j-init-file" in the servlet definition.</p> * <p>Sample: * <pre> * <init-param> * <param-name>log4j-init-file</param-name> * <param-value>WEB-INF/log4j.properties</param-value> * </init-param> * </pre> * </p> * * @author Florian Lippisch * @version $Revision: 1.9 $ */ public class DispatcherServlet extends HttpServlet implements IApplicationSetupProvider { private static final long serialVersionUID = 2L; public final static String INIT_LOG4JINIT = "log4j-init-file"; public final static String INIT_SETROOTDIR = "setRootDir"; public final static String INIT_INTERCEPTORS = "servlet.interceptors"; public final static String INIT_ENGINE_LISTENERS = "engine.listeners"; public final static String INIT_AUTHENTICATOR = "authenticator"; public final static String INIT_LOGIN_URL = "login"; public final static String INIT_UPLOAD_LIMIT = "uploadlimit"; protected final Log log = LogFactory.getLog(getClass()); private JWicRuntime jRuntime = null; private ServletInterceptor[] interceptors = null; private WebEngine engine = null; private long uploadLimit = 4 * 1024 * 1024; /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // invoke all configured interceptors if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { try { if (interceptors[i] != null) { interceptors[i].preHandle(req, res); } } catch (Throwable thr) { log.error("Error executing interceptor.preHandle " + interceptors[i].getClass().getName(), thr); } } } // Store the context path initialy in the JWicRuntime to allow // other tools to build full path links. if (jRuntime.getContextPath() == null) { jRuntime.setContextPath(req.getContextPath()); } super.service(req, res); // invoke all configured interceptors if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { try { if (interceptors[i] != null) { interceptors[i].postHandle(req, res); } } catch (Throwable thr) { log.error("Error executing interceptor.postHandle " + interceptors[i].getClass().getName(), thr); } } } } /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { log.debug("incoming GET request: " + req.getRequestURI()); try { engine.handleRequest(req, res, null); } catch (Exception e) { log.error("Error in doGet()", e); engine.displayError(req, res, e, null); } } /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { Upload upload = null; if(req.getContentType().startsWith("multipart")) { // parse data using "multipart" mode upload = new Upload(req, ".", uploadLimit, 1 * 1024 * 1024); // get parameters from the stream and set them as AgoraRequest parameters. // fill webform Map<String, List<String>> fields = upload.getParams(); req = new UploadHttpServletRequest(req, fields); } engine.handleRequest(req, res, upload); } /* (non-Javadoc) * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig) */ public void init(ServletConfig cfg) throws ServletException { super.init(cfg); ServletContext srvCtx = getServletContext(); String webAppRoot = srvCtx.getRealPath("/"); /* Set the web application root directory as system.property named by "setRootDir" param */ String propertyName = getInitParameter(INIT_SETROOTDIR); if (propertyName != null) { System.setProperty(propertyName, webAppRoot); } /* Setup the log4j system if specified in the web.xml */ String file = getInitParameter(INIT_LOG4JINIT); if(file != null) { PropertyConfigurator.configure(webAppRoot + file); } /* Setup the runtime */ jRuntime = JWicRuntime.getJWicRuntime(); jRuntime.setRootPath(webAppRoot); String savePath = srvCtx.getRealPath("WEB-INF/jwic/sessions"); if (savePath == null) { savePath = srvCtx.getRealPath("/WEB-INF/jwic/sessions"); } if (savePath != null) { jRuntime.setSavePath(savePath); } else { log.warn("No savePath for serializing sessions could be evaluated. This may happen if this app is run out of a WAR file."); } ConfigurationTool.setRootPath(webAppRoot); // because some WebServers need a leading slash while others do // only work with a relative path, we try both ways. InputStream in = getServletContext().getResourceAsStream("WEB-INF/jwic-setup.xml"); if (in == null) { in = getServletContext().getResourceAsStream("/WEB-INF/jwic-setup.xml"); } if (in != null) { jRuntime.setupRuntime(in); } else { throw new ServletException("/WEB-INF/jwic-setup.xml not found."); } try { engine = new WebEngine(this, webAppRoot); } catch (Exception e1) { log.error("Can not instanciate WebEngine.", e1); throw new ServletException("Can not instanciate WebEngine: " + e1); } // init Authentication String authenticationClass = getInitParameter(INIT_AUTHENTICATOR); String loginPage = getInitParameter(INIT_LOGIN_URL); if (authenticationClass != null) { // use custom class try { IAuthenticator authenticator = (IAuthenticator)Class.forName(authenticationClass).newInstance(); engine.setAuthenticator(authenticator); engine.setLoginPage(loginPage); } catch (Exception e) { log.error("Error creating Authentication '" + authenticationClass + "'", e); } } else { log.warn("No authenticator configured."); } // set the upload limit try { String upLimit = getInitParameter(INIT_UPLOAD_LIMIT); if (upLimit != null) { uploadLimit = Long.parseLong(upLimit); } } catch (NumberFormatException nfe) { log.warn("Upload-Limit parameter can not be read: ", nfe); } // Initialize the interceptors String intClasses = getInitParameter(INIT_INTERCEPTORS); if (intClasses != null && intClasses.length() != 0) { StringTokenizer stk = new StringTokenizer(intClasses, ";"); interceptors = new ServletInterceptor[stk.countTokens()]; int i = 0; while (stk.hasMoreTokens()) { String classname = stk.nextToken(); try { interceptors[i++] = (ServletInterceptor)Class.forName(classname).newInstance(); } catch (Throwable t) { log.error("Error creating ServletInterceptor '" + classname + "'", t); } } } // Initialize the engine listeners String intListeners = getInitParameter(INIT_ENGINE_LISTENERS); if (intListeners != null && intListeners.length() != 0) { StringTokenizer stk = new StringTokenizer(intListeners, ";"); while (stk.hasMoreTokens()) { String classname = stk.nextToken(); try { IWebEngineListener listener = (IWebEngineListener)Class.forName(classname).newInstance(); engine.addWebEngineListener(listener); } catch (Throwable t) { log.error("Error creating IWebEngineListener '" + classname + "'", t); } } } } /** * Destroy the servlet and the JWicRuntime. */ public void destroy() { log.info("DispatcherServlet.destroy()"); JWicRuntime.getJWicRuntime().destroy(); } /* (non-Javadoc) * @see de.jwic.web.IApplicationSetupProvider#createApplicationSetup(javax.servlet.http.HttpServletRequest) */ public IApplicationSetup createApplicationSetup(HttpServletRequest request) throws IOException { String name = request.getServletPath(); InputStream in = null; if (name.endsWith(".xwic")) { in = getServletContext().getResourceAsStream(name + ".xml"); } if (in == null) { in = getServletContext().getResourceAsStream(name); // try old name, for compatibility } if (in == null) { // still not found? throw new FileNotFoundException(request.getServletPath()); } return new XmlApplicationSetup(in); } }