package com.fpcms.common.web.filter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.apache.shiro.util.AntPathMatcher; import org.springframework.util.StringUtils; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.filter.OncePerRequestFilter; import com.fpcms.common.util.CmsSiteUtil; import com.fpcms.common.util.StrSubstitutorUtil; import com.fpcms.service.CmsSiteService; public class StrSubstitutorFilter extends OncePerRequestFilter implements Filter { private AntPathMatcher antPathMatcher = new AntPathMatcher(); private Set<String> includeSet = new HashSet<String>(); @Override protected void initFilterBean() throws ServletException { String includes = getFilterConfig().getInitParameter("includes"); if (StringUtils.hasText(includes)) { for (String str : StringUtils.tokenizeToStringArray(includes, ", \t\n")) { includeSet.add(str); } logger.info("StrSubstitutorFilter includeSet:" + includeSet); } } private Map<String, String> getSiteProperties(HttpServletRequest request) { WebApplicationContext wac = WebApplicationContextUtils .getRequiredWebApplicationContext(getServletContext()); CmsSiteService cmsSiteService = wac .getBean(CmsSiteService.class); String site = CmsSiteUtil.getSite(request,cmsSiteService); if(StringUtils.hasText(site)) { return cmsSiteService.getSiteProperties(site); } return new HashMap<String,String>(0); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (isInclude(request) && isNotExclude(request)) { FreemarkerServletResponseWrapper respWrapper = new FreemarkerServletResponseWrapper( response,getSiteProperties(request)); filterChain.doFilter(request, respWrapper); respWrapper.flushBuffer(); } else { filterChain.doFilter(request, response); } } private boolean isNotExclude(HttpServletRequest request) { return true; } private boolean isInclude(HttpServletRequest request) { String path = request.getServletPath(); String requestURI = request.getRequestURI(); String contextPath = request.getContextPath(); String requestPath = requestURI.substring(contextPath.length()); return isInclude(path) || isInclude(requestPath) ; } private boolean isInclude(String path) { if(includeSet.contains(path)) { return true; } for(String pattern : includeSet) { if( antPathMatcher.match(pattern, path)) { return true; } } return false; } class FreemarkerServletResponseWrapper extends HttpServletResponseWrapper { private ServletOutputStream outputStream; private ByteArrayOutputStream cacheOutput = new ByteArrayOutputStream( 1024 * 24); private Map<String,String> variables = new HashMap(); FreemarkerServletResponseWrapper(HttpServletResponse resp,Map variables) throws IOException { super(resp); this.variables = variables; } public void flushBuffer() throws IOException { if (writer != null) { writer.flush(); } outputStream = getResponse().getOutputStream(); String charset = getCharacterEncoding(); String replaced = StrSubstitutorUtil.strSubstitutor(cacheOutput.toString(charset), getVariables()); outputStream.write((replaced).getBytes()); outputStream.flush(); } private Map getVariables() { final Map map = new HashMap(); map.putAll(System.getProperties()); map.put("env", System.getenv()); map.putAll(variables); return map; } public ServletOutputStream getOutputStream() throws IOException { if (cacheOutput == null) { cacheOutput = new ByteArrayOutputStream(1024 * 24); } return new ServletOutputStreamProxy(cacheOutput); } private PrintWriter writer = null; public PrintWriter getWriter() throws IOException { if (writer == null) { writer = new PrintWriter(new OutputStreamWriter( getOutputStream(), getCharacterEncoding())) { public void write(char[] cb, int off, int len) { super.write(cb, off, len); super.flush(); } }; } return writer; } } static class ServletOutputStreamProxy extends ServletOutputStream { private OutputStream proxy; public ServletOutputStreamProxy(OutputStream proxy) { super(); this.proxy = proxy; } /* The first three methods must be overwritten */ @Override public void write(int b) throws IOException { proxy.write(b); } @Override public void flush() throws IOException { proxy.flush(); } @Override public void close() throws IOException { proxy.close(); } /* * These two are not absolutely needed. They are here simply because * they were overriden by GZIPOutputStream. */ @Override public void write(byte[] b) throws IOException { proxy.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { proxy.write(b, off, len); } @Override public boolean isReady() { // TODO Auto-generated method stub return false; } @Override public void setWriteListener(WriteListener writeListener) { } } }