001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013: package org.wings.session;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017: import org.wings.util.SStringBuilder;
018:
019: import javax.servlet.*;
020: import javax.servlet.http.HttpServletRequest;
021: import javax.servlet.http.HttpServletRequestWrapper;
022: import javax.servlet.http.HttpServletResponse;
023: import javax.servlet.http.HttpServletResponseWrapper;
024: import java.io.ByteArrayOutputStream;
025: import java.io.IOException;
026: import java.nio.CharBuffer;
027: import java.util.Collections;
028: import java.util.Enumeration;
029: import java.util.HashMap;
030: import java.util.Map;
031: import java.util.regex.Matcher;
032: import java.util.regex.Pattern;
033:
034: /**
035: * @author hengels
036: */
037: public class SmartURLsFilter implements Filter {
038: private final transient static Log log = LogFactory
039: .getLog(SmartURLsFilter.class);
040: private String parameterSeparator = ";";
041: private String nameValueSeparator = ",";
042: private Pattern encodePattern;
043: private Pattern decodePattern;
044:
045: public void init(FilterConfig filterConfig) throws ServletException {
046: if (filterConfig
047: .getInitParameter("wings.servlet.smarturls.parameterSeparator") != null)
048: parameterSeparator = filterConfig
049: .getInitParameter("wings.servlet.smarturls.parameterSeparator");
050:
051: if (filterConfig
052: .getInitParameter("wings.servlet.smarturls.nameValueSeparator") != null)
053: nameValueSeparator = filterConfig
054: .getInitParameter("wings.servlet.smarturls.nameValueSeparator");
055:
056: log.info("wings.servlet.smarturls.parameterSeparator "
057: + parameterSeparator);
058: log.info("wings.servlet.smarturls.nameValueSeparator "
059: + nameValueSeparator);
060:
061: encodePattern = Pattern.compile("(" + "\\?|&"
062: + ")([a-zA-Z0-9%+.-[*]_]*)" + "(" + "="
063: + ")([a-zA-Z0-9%+.-[*]_=/:]*)");
064: decodePattern = Pattern.compile("(" + parameterSeparator
065: + ")([a-zA-Z0-9%+.-[*]_]*)" + "(" + nameValueSeparator
066: + ")([a-zA-Z0-9%+.-[*]_=/:]*)");
067: }
068:
069: public void doFilter(ServletRequest servletRequest,
070: ServletResponse servletResponse, FilterChain filterChain)
071: throws IOException, ServletException {
072: ServletRequest request = servletRequest;
073: ServletResponse response = servletResponse;
074:
075: if (servletRequest instanceof HttpServletRequest) {
076: HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
077:
078: MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(
079: httpServletRequest);
080: if (requestWrapper.getPathInfo() == null
081: || requestWrapper.getPathInfo().indexOf('.') == -1) {
082: response = new MyHttpServletResponseWrapper(
083: servletResponse);
084:
085: if ("get".equalsIgnoreCase(httpServletRequest
086: .getMethod()))
087: request = requestWrapper;
088:
089: log.debug("wrap " + requestWrapper.getPathInfo());
090: } else
091: log.debug("don't wrap " + requestWrapper.getPathInfo());
092: }
093: filterChain.doFilter(request, response);
094: }
095:
096: public void destroy() {
097: }
098:
099: public static final String replace(String s, String toFind,
100: String replace) {
101: SStringBuilder erg = new SStringBuilder();
102:
103: int lastindex = 0;
104: int indexOf = s.indexOf(toFind);
105: if (indexOf == -1)
106: return s;
107: while (indexOf != -1) {
108: erg.append(s.substring(lastindex, indexOf)).append(replace);
109: lastindex = indexOf + toFind.length();
110: indexOf = s.indexOf(toFind, lastindex);
111: }
112:
113: erg.append(s.substring(lastindex));
114:
115: return erg.toString();
116: }
117:
118: private class MyHttpServletRequestWrapper extends
119: HttpServletRequestWrapper {
120: private Map parameterMap;
121: private String pathInfo;
122: private String queryString;
123:
124: public MyHttpServletRequestWrapper(
125: HttpServletRequest httpServletRequest) {
126: super (httpServletRequest);
127:
128: pathInfo = httpServletRequest.getPathInfo();
129: queryString = httpServletRequest.getQueryString();
130: parameterMap = httpServletRequest.getParameterMap();
131: log.debug("pathInfo = " + pathInfo);
132: log.debug("queryString = " + queryString);
133: log.debug("parameterMap = " + parameterMap);
134:
135: if (pathInfo == null)
136: return;
137:
138: int pos = pathInfo.indexOf(parameterSeparator);
139: if (pos != -1) {
140: queryString = pathInfo.substring(pos);
141: pathInfo = pathInfo.substring(0, pos);
142:
143: parameterMap = new HashMap();
144: StringBuffer buffer = new StringBuffer(queryString
145: .length());
146: Matcher matcher = decodePattern.matcher(queryString);
147: while (matcher.find()) {
148: String param = matcher.group();
149: pos = param.indexOf(nameValueSeparator);
150: parameterMap.put(param.substring(1, pos), param
151: .substring(pos + 1));
152: matcher.appendReplacement(buffer, "&$2=$4");
153: }
154: queryString = buffer.substring(1);
155: log.debug("modified pathInfo = " + pathInfo);
156: log.debug("modified queryString = " + queryString);
157: log.debug("modified parameterMap = " + parameterMap);
158: }
159: }
160:
161: public String getRequestURI() {
162: return super .getRequestURI();
163: }
164:
165: public Map getParameterMap() {
166: return parameterMap;
167: }
168:
169: public String getPathInfo() {
170: return pathInfo;
171: }
172:
173: public String getQueryString() {
174: return queryString;
175: }
176:
177: public String getParameter(String string) {
178: Object value = getParameterMap().get(string);
179: if (value instanceof String)
180: return (String) value;
181: else
182: return ((String[]) value)[0];
183: }
184:
185: public Enumeration getParameterNames() {
186: return Collections.enumeration(getParameterMap().keySet());
187: }
188:
189: public String[] getParameterValues(String string) {
190: Object value = getParameterMap().get(string);
191: if (value instanceof String)
192: return new String[] { (String) value };
193: else
194: return (String[]) value;
195: }
196: }
197:
198: private static class MyHttpServletResponseWrapper extends
199: HttpServletResponseWrapper {
200: public MyHttpServletResponseWrapper(
201: ServletResponse servletResponse) {
202: super ((HttpServletResponse) servletResponse);
203: }
204:
205: public ServletOutputStream getOutputStream() throws IOException {
206: final ServletOutputStream super Out = super
207: .getOutputStream();
208: return new ServletOutputStream() {
209: ByteArrayOutputStream bytes = new ByteArrayOutputStream(
210: 1000);
211:
212: public void write(int b) throws IOException {
213: bytes.write(b);
214: }
215:
216: public void close() throws IOException {
217: encode(bytes, super Out);
218: super Out.close();
219: }
220: };
221: }
222: }
223:
224: private static void encode(ByteArrayOutputStream bytes,
225: ServletOutputStream out) throws IOException {
226: String regex = "(href|src|action) *= *\"([^\"]*)\"";
227:
228: SmartURLsFilter smartURLsFilter = new SmartURLsFilter();
229: String replacement = smartURLsFilter.parameterSeparator + "$2"
230: + smartURLsFilter.nameValueSeparator + "$4";
231:
232: smartURLsFilter.encodePattern = Pattern.compile("(" + "\\?|&"
233: + ")([a-zA-Z0-9%+.-[*]_]*)" + "(" + "="
234: + ")([a-zA-Z0-9%+.-[*]_=/]*)");
235:
236: CharBuffer chars = CharBuffer.wrap(bytes.toString());
237: Pattern pattern = Pattern.compile(regex);
238: Matcher matcher = pattern.matcher(chars);
239: int pos = 0;
240: while (matcher.find()) {
241: out.print(chars.subSequence(pos, matcher.start())
242: .toString());
243: pos = matcher.end();
244: Matcher matcher2 = smartURLsFilter.encodePattern
245: .matcher(matcher.group(2));
246: String group2 = matcher2.replaceAll(replacement);
247:
248: out.print(matcher.group(1) + "=\"" + group2 + "\"");
249: }
250: out.print(chars.subSequence(pos, bytes.size()).toString());
251: }
252: }
|