org.wings.session.SmartURLsFilter Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS 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.
*
* Please see COPYING for the complete licence.
*/
package org.wings.session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author hengels
*/
public class SmartURLsFilter
implements Filter {
private final transient static Logger log = LoggerFactory.getLogger(SmartURLsFilter.class);
private String parameterSeparator = ";";
private String nameValueSeparator = ",";
private Pattern encodePattern;
private Pattern decodePattern;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
if (filterConfig.getInitParameter("wings.servlet.smarturls.parameterSeparator") != null)
parameterSeparator = filterConfig.getInitParameter("wings.servlet.smarturls.parameterSeparator");
if (filterConfig.getInitParameter("wings.servlet.smarturls.nameValueSeparator") != null)
nameValueSeparator = filterConfig.getInitParameter("wings.servlet.smarturls.nameValueSeparator");
log.info("wings.servlet.smarturls.parameterSeparator " + parameterSeparator);
log.info("wings.servlet.smarturls.nameValueSeparator " + nameValueSeparator);
encodePattern = Pattern.compile('(' + "\\?|&" + ")([a-zA-Z0-9%+.-[*]_]*)" +
'(' + '=' + ")([a-zA-Z0-9%+.-[*]_=/:]*)");
decodePattern = Pattern.compile('(' + parameterSeparator + ")([a-zA-Z0-9%+.-[*]_]*)" +
'(' + nameValueSeparator + ")([a-zA-Z0-9%+.-[*]_=/:]*)");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
ServletRequest request = servletRequest;
ServletResponse response = servletResponse;
if (servletRequest instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(httpServletRequest);
if (requestWrapper.getPathInfo() == null || requestWrapper.getPathInfo().indexOf('.') == -1) {
response = new MyHttpServletResponseWrapper(servletResponse);
if ("get".equalsIgnoreCase(httpServletRequest.getMethod()))
request = requestWrapper;
log.debug("wrap " + requestWrapper.getPathInfo());
} else
log.debug("don't wrap " + requestWrapper.getPathInfo());
}
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
public static final String replace(String s,
String toFind, String replace) {
int indexOf = s.indexOf(toFind);
if (indexOf == -1) return s;
int lastindex = 0;
StringBuilder erg = new StringBuilder();
while (indexOf != -1) {
erg.append(s.substring(lastindex, indexOf)).append(replace);
lastindex = indexOf + toFind.length();
indexOf = s.indexOf(toFind, lastindex);
}
erg.append(s.substring(lastindex));
return erg.toString();
}
private class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
private Map parameterMap;
private String pathInfo;
private String queryString;
public MyHttpServletRequestWrapper(HttpServletRequest httpServletRequest) {
super(httpServletRequest);
pathInfo = httpServletRequest.getPathInfo();
queryString = httpServletRequest.getQueryString();
parameterMap = httpServletRequest.getParameterMap();
log.debug("pathInfo = " + pathInfo);
log.debug("queryString = " + queryString);
log.debug("parameterMap = " + parameterMap);
if (pathInfo == null)
return;
int pos = pathInfo.indexOf(parameterSeparator);
if (pos != -1) {
queryString = pathInfo.substring(pos);
pathInfo = pathInfo.substring(0, pos);
parameterMap = new HashMap();
StringBuffer buffer = new StringBuffer(queryString.length());
Matcher matcher = decodePattern.matcher(queryString);
while (matcher.find()) {
String param = matcher.group();
pos = param.indexOf(nameValueSeparator);
parameterMap.put(param.substring(1, pos), param.substring(pos + 1));
matcher.appendReplacement(buffer, "&$2=$4");
}
queryString = buffer.substring(1);
log.debug("modified pathInfo = " + pathInfo);
log.debug("modified queryString = " + queryString);
log.debug("modified parameterMap = " + parameterMap);
}
}
@Override
public String getRequestURI() {
return super.getRequestURI();
}
@Override
public Map getParameterMap() {
return parameterMap;
}
@Override
public String getPathInfo() {
return pathInfo;
}
@Override
public String getQueryString() {
return queryString;
}
@Override
public String getParameter(String string) {
Object value = parameterMap.get(string);
if (value instanceof String)
return (String) value;
else
return ((String[]) value)[0];
}
@Override
public Enumeration getParameterNames() {
return Collections.enumeration(parameterMap.keySet());
}
@Override
public String[] getParameterValues(String string) {
Object value = parameterMap.get(string);
if (value instanceof String)
return new String[]{(String) value};
else
return (String[]) value;
}
}
private static class MyHttpServletResponseWrapper extends HttpServletResponseWrapper {
public MyHttpServletResponseWrapper(ServletResponse servletResponse) {
super((HttpServletResponse) servletResponse);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
final ServletOutputStream superOut = super.getOutputStream();
return new MyServletOutputStream(superOut);
}
private static class MyServletOutputStream extends ServletOutputStream {
private final ServletOutputStream superOut;
ByteArrayOutputStream bytes;
public MyServletOutputStream(ServletOutputStream superOut) {
this.superOut = superOut;
bytes = new ByteArrayOutputStream(1000);
}
@Override
public void write(int b) throws IOException {
bytes.write(b);
}
@Override
public void close() throws IOException {
encode(bytes, superOut);
superOut.close();
}
}
}
private static void encode(ByteArrayOutputStream bytes, ServletOutputStream out) throws IOException {
SmartURLsFilter smartURLsFilter = new SmartURLsFilter();
String replacement =
smartURLsFilter.parameterSeparator + "$2" +
smartURLsFilter.nameValueSeparator + "$4";
smartURLsFilter.encodePattern = Pattern.compile('(' + "\\?|&" + ")([a-zA-Z0-9%+.-[*]_]*)" +
'(' + '=' + ")([a-zA-Z0-9%+.-[*]_=/]*)");
CharBuffer chars = CharBuffer.wrap(bytes.toString());
String regex = "(href|src|action) *= *\"([^\"]*)\"";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(chars);
int pos = 0;
while (matcher.find()) {
out.print(chars.subSequence(pos, matcher.start()).toString());
pos = matcher.end();
Matcher matcher2 = smartURLsFilter.encodePattern.matcher(matcher.group(2));
String group2 = matcher2.replaceAll(replacement);
out.print(matcher.group(1) + "=\"" + group2 + '"');
}
out.print(chars.subSequence(pos, bytes.size()).toString());
}
}