/** * Copyright 2005-2010 hdiv.org * * 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. */ package org.hdiv.filter; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.application.IApplication; import org.hdiv.config.HDIVConfig; import org.hdiv.config.multipart.IMultipartConfig; import org.hdiv.session.ISession; import org.hdiv.util.HDIVUtil; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.multipart.MaxUploadSizeExceededException; /** * An unique filter exists within HDIV. This filter has two responsabilities: * initialize and validate. In fact, the actual validation is not implemented in * this class, it is delegated to ValidatorHelper. * * @author Roberto Velasco * @author Gorka Vicente * @see org.hdiv.filter.ValidatorHelperThreadLocal */ public class ValidatorFilter extends OncePerRequestFilter { /** * Commons Logging instance. */ private static Log log = LogFactory.getLog(ValidatorFilter.class); /** * HDIV configuration object */ private HDIVConfig hdivConfig; /** * IValidationHelper object */ private IValidationHelper validationHelper; /** * The multipart config */ private IMultipartConfig multipartConfig; /** * Creates a new ValidatorFilter object. */ public ValidatorFilter() { } /** * Called by the web container to indicate to a filter that it is being * placed into service. * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ protected void initFilterBean() throws ServletException { ServletContext servletContext = getServletContext(); WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); this.hdivConfig = (HDIVConfig) context.getBean("config"); this.validationHelper = (IValidationHelper) context.getBean("validatorHelper"); if(context.containsBean("multipartConfig")){ //For applications without Multipart requests this.multipartConfig = (IMultipartConfig) context.getBean("multipartConfig"); } IApplication application = (IApplication) context.getBean("application"); ISession session = (ISession) context.getBean("sessionHDIV"); ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBeanClassLoader(context.getClassLoader()); String messageSourcePath = (String)context.getBean("messageSourcePath"); messageSource.setBasename(messageSourcePath); HDIVUtil.setApplication(application, servletContext); HDIVUtil.setMessageSource(messageSource, servletContext); HDIVUtil.setISession(session, servletContext); HDIVUtil.setHDIVConfig(this.hdivConfig, servletContext); } /** * Called by the container each time a request/response pair is passed * through the chain due to a client request for a resource at the end of * the chain. * * @param servletRequest request * @param servletResponse response * @param filterChain filter chain * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { this.initHDIV(request); ResponseWrapper responseWrapper = new ResponseWrapper(response); RequestWrapper requestWrapper = getRequestWrapper(request); try { boolean disableHDIV = hdivConfig.isDisableHDIV(); boolean legal = false; boolean isSizeLimitExceeded = false; if (this.isMultipartContent(request.getContentType())) { requestWrapper.setMultipart(true); try { if(this.multipartConfig == null){ throw new RuntimeException("No 'multipartConfig' configured. It is required to multipart requests."); } this.multipartConfig.handleMultipartRequest(requestWrapper, super.getServletContext()); } catch (DiskFileUpload.SizeLimitExceededException e) { request.setAttribute(IMultipartConfig.FILEUPLOAD_EXCEPTION, e); isSizeLimitExceeded = true; legal = true; } catch (MaxUploadSizeExceededException e) { isSizeLimitExceeded = true; legal = true; request.setAttribute(IMultipartConfig.FILEUPLOAD_EXCEPTION, e); } catch (FileUploadException e) { isSizeLimitExceeded = true; legal = true; if (e.getCause() == null) e = new FileUploadException(e.getMessage()); request.setAttribute(IMultipartConfig.FILEUPLOAD_EXCEPTION, e); } } if (!isSizeLimitExceeded) { if (disableHDIV) legal = true; else legal = this.validationHelper.validate(requestWrapper); } if (legal) { processRequest(requestWrapper, responseWrapper, filterChain); } else { response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + hdivConfig.getErrorPage())); } } catch (IOException e){ //Internal framework exception, rethrow exception throw e; } catch (ServletException e){ //Internal framework exception, rethrow exception throw e; } catch (Exception e) { if(log.isErrorEnabled()){ log.error("Exception in request validation:"); log.error("Message: "+e.getMessage()); StringBuffer buffer = new StringBuffer(); StackTraceElement[] trace = e.getStackTrace(); for (int i=0; i < trace.length; i++){ buffer.append("\tat " + trace[i] + System.getProperty("line.separator")); } log.error("StackTrace: "+buffer.toString()); log.error("Cause: "+e.getCause()); log.error("Exception: "+e.toString()); } response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + hdivConfig.getErrorPage())); } finally { HDIVUtil.resetLocalData(); } } /** * Initialize HDIV HTTP session * * @param request HTTP request */ public void initHDIV(HttpServletRequest request) { HDIVUtil.setHttpServletRequest(request); } /** * Utility method that determines whether the request contains multipart * content. * * @param contentType content type * @return <code>true</code> if the request is multipart. * <code>false</code> otherwise. */ public boolean isMultipartContent(String contentType) { return ((contentType != null) && (contentType.indexOf("multipart/form-data") != -1)); } /** * Processes requests for both HTTP <code>GET</code> and <code>POST</code> * methods. * * @param requestWrapper request wrapper * @param responseWrapper response wrapper * @param filterChain filter chain * @throws Exception if there is an error in request process. */ protected void processRequest(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, FilterChain filterChain) throws IOException, ServletException { this.validationHelper.startPage(requestWrapper); filterChain.doFilter(requestWrapper, responseWrapper); this.validationHelper.endPage(requestWrapper); } /** * Crea el wrapper del request * * @param request HTTP request * @return the request wrapper */ protected RequestWrapper getRequestWrapper(HttpServletRequest request){ RequestWrapper requestWrapper = new RequestWrapper(request); requestWrapper.setConfidentiality(this.hdivConfig.getConfidentiality()); requestWrapper.setCookiesConfidentiality(this.hdivConfig.isCookiesConfidentialityActivated()); return requestWrapper; } }