View Javadoc

1   
2   /*
3    * Copyright (C) 2005 by Arno Schumacher
4    *
5    * This file is part of net.sourceforge.servletspy
6    *
7    * net.sourceforge.servletspy is free software; you can redistribute
8    * it and/or modify it under the terms of the GNU General Public 
9    * License as published by the Free Software Foundation; either 
10   * version 2, or (at your option) any later version.
11   *
12   * net.sourceforge.servletspy is distributed in the hope that it will
13   * be useful, but WITHOUT ANY WARRANTY; without even the implied 
14   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
15   * See the GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA 
20   */
21  
22  package net.sourceforge.servletspy.handler.servlet;
23  
24  import java.lang.reflect.Array;
25  import java.lang.reflect.InvocationHandler;
26  import java.lang.reflect.Method;
27  import java.lang.reflect.Proxy;
28  import java.util.Arrays;
29  import java.util.Enumeration;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  
34  import javax.servlet.ServletRequest;
35  import javax.servlet.http.HttpServletRequest;
36  
37  import net.sourceforge.servletspy.IContext;
38  import net.sourceforge.servletspy.IContextHandler;
39  import net.sourceforge.servletspy.config.Param;
40  
41  /***
42   * @author arno schumacher
43   */
44  public final class RequestHandler implements IContextHandler {
45  
46      /*** The prefix for all extra contexts to generate. */
47      private static final String BASE_KEY_NAME = "~";
48  
49      /*** The name of the sub context for the request attributes. */
50      private static final String ATTRIBUTES_KEY_NAME = BASE_KEY_NAME
51              + "attributes";
52  
53      /*** The name of the sub context for the request headers. */
54      private static final String HEADERS_KEY_NAME = BASE_KEY_NAME + "headers";
55  
56      /*** The name of the sub context for the request parameters. */
57      private static final String PARAMETERS_KEY_NAME = BASE_KEY_NAME
58              + "parameters";
59  
60      /***
61       * A list methods which should be excluded while generating a node
62       * representation for the request object. Retrieval of <code>Reader</code>
63       * and <code>InputStream</code> could cause some troble, see servlet
64       * specification. For <code>ParameterMap</code> and <code>Session</code>
65       * an alternate representation is generated.
66       */
67      private static List excludefilterList = Arrays.asList(new String[] {
68              "getSession", "getInputStream", "getReader", "getParameterMap" });
69  
70      /***
71       * Returns the proxy interface for the provided class.
72       *
73       * @param o
74       *            The servlet request object.
75       * @return The proxy interface.
76       */
77      private static Class[] getProxyInterfaces(final Object o) {
78          return (o instanceof HttpServletRequest) ? new Class[] {
79                  HttpServletRequest.class, ServletRequest.class}
80                  : new Class[] {ServletRequest.class};
81      }
82  
83      /***
84       * Generates a string represenation of the provided array.
85       *
86       * @param array
87       *            The array.
88       * @return A string representation of the provided array.
89       */
90      private static String arrayAsString(final Object array) {
91          if (array == null) {
92              return "null";
93          } else {
94              if (array.getClass().isArray()) {
95                  int iLength = Array.getLength(array);
96  
97                  if (iLength == 0) {
98                      return "[]";
99                  } else {
100                     StringBuffer sb = new StringBuffer();
101                     for (int i = 0; i < iLength; i++) {
102                         sb.append("[");
103                         Object o = Array.get(array, i);
104                         String str;
105                         try {
106                             if (o == null) {
107                                 str = "null";
108                             } else if (o.getClass().isArray()) {
109                                 str = arrayAsString(o);
110                             } else {
111                                 str = o.toString();
112                             }
113                         } catch (Throwable t) {
114                             str = "?";
115                         }
116                         sb.append(str);
117                         sb.append("]");
118                     }
119                     return sb.toString();
120                 }
121             } else {
122                 throw new IllegalArgumentException("Not an array: " + array);
123             }
124         }
125     }
126 
127     /***
128      * Returns a map holding all attributes of the provided request object.
129      *
130      * @param request
131      *            The request
132      * @return The attribute map generated using the provided request object.
133      */
134     private static Map generateAttributeMap(final ServletRequest request) {
135         final Map map = new HashMap();
136         final Enumeration enumeration = request.getAttributeNames();
137         while (enumeration.hasMoreElements()) {
138             final String key = String.valueOf(enumeration.nextElement());
139             final Object value = request.getAttribute(key);
140             map.put(key, value);
141         }
142         return map;
143     }
144 
145     /***
146      * Returns a map holding all headers of the provided request object.
147      *
148      * @param request
149      *            The request
150      * @return The header map generated using the provided request object.
151      */
152     private static Map generateHeadersMap(final HttpServletRequest request) {
153         final Map mapParamters = new HashMap();
154         final Enumeration enumeration = request.getHeaderNames();
155         while (enumeration.hasMoreElements()) {
156             final String key = String.valueOf(enumeration.nextElement());
157             final Object value = request.getHeader(key);
158             mapParamters.put(key, value);
159         }
160         return mapParamters;
161     }
162 
163     /***
164      * Returns a map holding all request parameters of the provided request
165      * object.
166      *
167      * @param request
168      *            The request
169      * @return The request parameter map generated using the provided request
170      *         object.
171      */
172     private static Map generateParameterMap(final ServletRequest request) {
173         final Map mapParamters = new HashMap();
174         final Enumeration enumerationParameters = request.getParameterNames();
175         while (enumerationParameters.hasMoreElements()) {
176             final String key = String.valueOf(enumerationParameters
177                     .nextElement());
178             final Object value = request.getParameterValues(key);
179             mapParamters.put(key, arrayAsString(value));
180         }
181         return mapParamters;
182     }
183 
184     /*
185      * (non-Javadoc)
186      * @see net.sourceforge.servletspy.ILifecycle#destroy()
187      */
188     public void destroy() {
189     }
190 
191     /*
192      * (non-Javadoc)
193      * @see net.sourceforge.servletspy.IContextHandler#handle(net.sourceforge.servletspy.IContext)
194      */
195     public void handle(final IContext context) throws Exception {
196         if (context.getSubject() instanceof ServletRequest) {
197             final ServletRequest request = (ServletRequest) context
198                     .getSubject();
199             final ServletRequest requestWrapper = (ServletRequest) Proxy
200                     .newProxyInstance(context.getClass().getClassLoader(),
201                             getProxyInterfaces(request),
202                             new InvocationHandler() {
203                                 public Object invoke(
204                                         final Object proxy,
205                                         final Method method, 
206                                         final Object[] args)
207                                         throws Throwable {
208                                     return excludefilterList.contains(method
209                                             .getName()) ? null : method.invoke(
210                                             request, args);
211                                 }
212                             });
213 
214             context.setSubject(requestWrapper);
215             context.proceed();
216             context.add(ATTRIBUTES_KEY_NAME, generateAttributeMap(request));
217             context.add(PARAMETERS_KEY_NAME, generateParameterMap(request));
218             if (context.getSubject() instanceof HttpServletRequest) {
219                 context.add(HEADERS_KEY_NAME,
220                         generateHeadersMap((HttpServletRequest) request));
221             }
222         } else {
223             context.proceed();
224         }
225     }
226 
227     /*
228      * (non-Javadoc)
229      * @see net.sourceforge.servletspy.ILifecycle#init(net.sourceforge.servletspy.config.Param[])
230      */
231     public void init(final Param[] params) {
232     }
233 }