| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| /** |
| * @author Ana von Klopp |
| * @author Simran Gleason |
| */ |
| |
| package org.netbeans.modules.web.monitor.server; |
| |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Stack; |
| import java.util.Vector; |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletRequestWrapper; |
| import javax.servlet.http.HttpUtils; |
| import org.netbeans.modules.web.monitor.data.RequestData; |
| import org.netbeans.modules.web.monitor.data.Param; |
| |
| /** |
| * The MonitorRequestWrapper class is used by the MonitorFilter to |
| * wrap the request. It's main function is to ensure that the |
| * application receives the data from a replay request. |
| */ |
| public class MonitorRequestWrapper extends HttpServletRequestWrapper { |
| |
| private boolean replay = false; |
| |
| // These fields hold local variables during replays. |
| private String localMethod = null; |
| private String localProtocol = null; |
| private String localScheme = null; |
| private String localRemoteAddr = null; |
| private String localQueryString = null; |
| private Param[] localHeaders = null; |
| private Vector localCookies = null; |
| private Map oldParams = null; |
| private Map localParams = null; |
| private Stack extraParamStack = null; |
| |
| // These fields are used to manage session replacement during |
| // replay, if the server supports it |
| public final static String JSESSIONID = "JSESSIONID"; // NOI18N |
| public final static String REPLACED = |
| "netbeans.replay.session-replaced"; //NOI18N |
| |
| private static final boolean debug = false; |
| |
| MonitorRequestWrapper(HttpServletRequest req) { |
| super(req); |
| } |
| |
| /** |
| * The filter will only wrap the request if it was a |
| * HttpServletRequest. This is a convenience method for |
| * accessing the request variable as such, for those methods that |
| * aren't available on the regular servlet request. |
| */ |
| private HttpServletRequest getHRequest() { |
| return (HttpServletRequest)getRequest(); |
| } |
| |
| // GETTERS FROM THE HttpServletRequest |
| // |
| // The getters implement the decorator pattern, except for replays |
| // where we use local data. |
| |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public String getMethod() { |
| if (replay) { |
| return localMethod; |
| } |
| return getHRequest().getMethod(); |
| } |
| |
| // ********************** PARAMETERS ************************* |
| // All the getParameter methods must refer to getParameterMap for |
| // locally set parameters. See pushExtraParameters and |
| // popExtraParameters for additional detail on local parameters. |
| // |
| |
| /** getParameterMap returns<br> |
| * a) the parameter map from the request, if this is not a replay<br> |
| * b) the local parameter map, if no extra parameters have been |
| * set ("extra parameters" are parameters which are set through |
| * the <jsp:param> tag inside <jsp:forward/include>. <br> |
| * c) the local parameter map augmented with parameters so set. <br> |
| * |
| * @see pushExtraParameters |
| * @see popExtraParameters |
| */ |
| public java.util.Map getParameterMap() { |
| |
| if(debug) log("getParameterMap()"); //NOI18N |
| |
| if (!replay) return getRequest().getParameterMap(); |
| |
| // Could cache the results of processing the parameters, but |
| // it is relatively unusual that this gets expensive. It will |
| // only get repeated on a replay where the request processing |
| // involves a dispatch made from a JSP using the param tag AND |
| // the file that got dispatched to accesses the parameter more |
| // than once. |
| if(extraParamStack == null || extraParamStack.empty()) |
| return (java.util.Map)localParams; |
| |
| Map map = (Map)extraParamStack.peek(); |
| |
| if(map.size() == 0) return (java.util.Map)localParams; |
| |
| Hashtable ht = new Hashtable(); |
| |
| Iterator keys = localParams.keySet().iterator(); |
| while(keys.hasNext()) { |
| Object o = keys.next(); |
| if(map.containsKey(o)) { |
| String[] vals0 = (String[])localParams.get(o); |
| String[] vals1 = (String[])map.get(o); |
| String[] vals2 = new String[vals0.length + vals1.length]; |
| System.arraycopy(vals0, 0, vals2, 0, vals0.length); |
| System.arraycopy(vals1, 0, vals2, vals0.length, vals1.length); |
| ht.put(o, vals2); |
| } |
| else |
| ht.put(o, localParams.get(o)); |
| } |
| |
| keys = map.keySet().iterator(); |
| while(keys.hasNext()) { |
| Object o = keys.next(); |
| if(localParams.containsKey(o)) continue; |
| ht.put(o, map.get(o)); |
| } |
| return (Map)ht; |
| } |
| |
| |
| /** |
| * If this is not a replay, getParameter(key) returns the value of |
| * invoking the method on the original request. If it is a replay, |
| * it returns the first string of the String array for the key, if |
| * such an array exists. Otherwise it returns null. |
| */ |
| public String getParameter(String key) { |
| |
| if(debug) log("getParameters()"); //NOI18N |
| |
| if (!replay) return getRequest().getParameter(key); |
| |
| String [] values = (String[])getParameterMap().get(key); |
| if (values != null && values.length > 0) { |
| return values[0]; |
| } |
| return null; |
| } |
| |
| /** |
| * If this is not a replay, getParameterNames returns the value of |
| * invoking the method on the original request. If it is a replay, |
| * it returns an Enumeration derived from the keyset of the |
| * parameter map. |
| */ |
| public Enumeration getParameterNames() { |
| if(debug) log("getParameterNames"); //NOI18N |
| if (!replay) |
| return getRequest().getParameterNames(); |
| if(debug) { |
| Enumeration e = new Vector(getParameterMap().keySet()).elements(); |
| while(e.hasMoreElements()) |
| log("\t" + String.valueOf(e.nextElement())); //NOI18N |
| } |
| return new Vector(getParameterMap().keySet()).elements(); |
| } |
| |
| /** |
| * If this is not a replay, getParameterValues returns the value of |
| * invoking the method on the original request. If it is a replay, |
| * it returns a String array matching the key in the local parameter |
| * map. |
| */ |
| public String [] getParameterValues(String name) { |
| if(debug) log("getParameterValues"); //NOI18N |
| if (!replay) |
| return getRequest().getParameterValues(name); |
| return (String[])getParameterMap().get(name); |
| } |
| |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public String getQueryString() { |
| if (!replay) |
| return getHRequest().getQueryString(); |
| return localQueryString; |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public String getProtocol() { |
| if (!replay) |
| return getRequest().getProtocol(); |
| return localProtocol; |
| } |
| |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public String getScheme() { |
| if (replay) return localScheme; |
| return getRequest().getScheme(); |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| * |
| * According to the Servlet specification, this method must return |
| * null if there is no header of the specified name. |
| */ |
| public String getHeader(String key) { |
| |
| if (replay) { |
| int len = localHeaders.length; |
| for(int i=0; i<len; ++i) { |
| if(localHeaders[i].getName().equalsIgnoreCase(key)) |
| return localHeaders[i].getValue(); |
| } |
| if(debug) log("didn't find header"); //NOI18N |
| return null; |
| } |
| |
| if(debug) { |
| log("Headers not set locally"); //NOI18N |
| log(key + " " + getHRequest().getHeader(key)); //NOI18N |
| } |
| return getHRequest().getHeader(key); |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public Enumeration getHeaderNames() { |
| |
| if (replay) { |
| Vector v = new Vector(); |
| |
| int len = localHeaders.length; |
| for(int i=0; i<len; ++i) |
| v.add(localHeaders[i].getName()); |
| |
| return v.elements(); //NOI18N |
| } |
| return getHRequest().getHeaderNames(); |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public Enumeration getHeaders(String name) { |
| |
| if (replay) { |
| |
| Vector v = new Vector(); |
| |
| int len = localHeaders.length; |
| for(int i=0; i<len; ++i) { |
| if(localHeaders[i].getName().equalsIgnoreCase(name)) |
| v.add(localHeaders[i].getValue()); |
| } |
| return v.elements(); //NOI18N |
| } |
| return getHRequest().getHeaders(name); |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public int getIntHeader(String name) { |
| int headerValue = -1; |
| String value = getHeader(name); |
| if (value != null) |
| headerValue = Integer.parseInt(value); |
| |
| return headerValue; |
| } |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public long getDateHeader (String name) { |
| |
| long dateValue = -1; |
| String value = getHeader(name); |
| |
| if (value != null) { |
| int el = value.indexOf (';'); |
| if (el != -1) |
| value = value.substring (0, el); |
| |
| try { |
| dateValue = Date.parse (value); |
| } catch (Exception e) { |
| } |
| if (dateValue == -1) { |
| // let it throw |
| throw new IllegalArgumentException (); |
| } |
| } |
| return dateValue; |
| } |
| |
| |
| /** |
| * During a replay, returns the local value. If not a replay, |
| * simply returns the value of invoking the method on the wrapped |
| * request. |
| */ |
| public Cookie[] getCookies() { |
| if(!replay) |
| return getHRequest().getCookies(); |
| |
| if(localCookies == null) |
| return new Cookie[0]; |
| |
| int numCookies = localCookies.size(); |
| Cookie[] cookieArray = new Cookie[numCookies]; |
| Enumeration e = localCookies.elements(); |
| int index = 0; |
| while(e.hasMoreElements()) { |
| cookieArray[index] = (Cookie)e.nextElement(); |
| ++index; |
| } |
| return cookieArray; |
| } |
| |
| /** |
| * This always returns the attributes that are set on the wrapped |
| * request, regardless of whether this is a replay or |
| * not. (Attributes are set by the web components, not as a result |
| * of parsing the request). This method strips off any attributes |
| * names which are used by the HTTP Monitor itself (these start |
| * with "netbeans.monitor." so it's unlikely that they'll be used |
| * in a regular app. |
| */ |
| public Enumeration getAttributeNames() { |
| |
| if(debug) log("getAttributeNames()"); //NOI18N |
| |
| Enumeration e = getRequest().getAttributeNames(); |
| |
| // If we're debugging, check the monitor attributes while |
| // we're at it... |
| if(debug) return e; |
| |
| Vector v = new Vector(); |
| while (e.hasMoreElements()) { |
| String name = (String)e.nextElement(); |
| // We don't record the request or the servlet attributes |
| // because we made those oursevles. |
| if(name.startsWith(MonitorFilter.PREFIX)) { |
| if(debug) log("discarded " + name); //NOI18N |
| continue; |
| } |
| if(debug) log("keeping " + name); //NOI18N |
| v.add(name); |
| } |
| return v.elements(); |
| } |
| |
| // Pending - not held as local data though it should be |
| public String getRemoteAddr() { |
| return getRequest().getRemoteAddr(); |
| /* |
| if (!replay) |
| //return null; // not yet: getRequest().getRemoteAddr(); |
| return getRequest().getRemoteAddr(); |
| return localRemoteAddr; |
| */ |
| } |
| |
| //*********************** END GETTERS ********************** |
| |
| |
| /** |
| * Populates the request wrapper with local data during a replay. |
| * |
| * @param rd The RequestData object that we use to repopulate this |
| * request |
| * @param replaceSessionID true if the user requested for the |
| * session ID to be replaced |
| * @param canplaceSessionID true if the server can replace the |
| * session ID |
| **/ |
| public void populate(RequestData rd, |
| boolean replaceSessionID) { |
| |
| // Replay is true, values are local |
| replay = true; |
| |
| // Set the request method |
| localMethod = rd.getAttributeValue("method"); // NOI18N |
| |
| // Set the protocol |
| localProtocol = rd.getAttributeValue("protocol"); // NOI18N |
| |
| // Set the scheme |
| localScheme = rd.getAttributeValue("scheme"); // NOI18N |
| |
| // PENDING: Set the remote address |
| // localRemoteAddr = |
| // rd.getClientData().getAttributeValue("remoteAddress"); // NOI18N |
| |
| // Set the query string |
| localQueryString = rd.getAttributeValue("queryString"); // NOI18N |
| |
| oldParams = getRequest().getParameterMap(); |
| |
| // Do the parameters |
| if(localMethod.equals("GET")) { //NOI18N |
| |
| try { |
| localParams = HttpUtils.parseQueryString(localQueryString); |
| } |
| catch(Exception ex) { |
| // This utility doesn't like query strings that aren't |
| // in parameter format |
| localParams = new Hashtable(); |
| } |
| } |
| |
| else if(localMethod.equals("POST")) { // NOI18N |
| |
| try { |
| localParams = HttpUtils.parseQueryString(localQueryString); |
| } |
| catch(Exception ex) { |
| // This utility doesn't like query strings that aren't |
| // in parameter format |
| localParams = new Hashtable(); |
| } |
| |
| // PENDING - this assumes the stuff comes in as parameters, |
| // but it could come in as non-parameterized data and |
| // ideally we should deal with this case also (and |
| // multiforms). Right now we just make sure we don't break |
| // everything if there is a non-parametrized request. |
| |
| Param[] params = rd.getParam(); |
| int numParams = params.length; |
| |
| for(int i=0; i<numParams; ++i) { |
| String name = params[i].getAttributeValue("name"); // NOI18N |
| String[] values = null; |
| if(localParams.containsKey(name)) { |
| values = (String[])localParams.get(name); |
| String[] newvals = new String[values.length+1]; |
| int j; |
| for(j=0; j<values.length; ++j) |
| newvals[j] = values[j]; |
| newvals[j] = params[i].getAttributeValue("value"); // NOI18N |
| localParams.put(name, newvals); |
| } |
| else { |
| values = new String[1]; |
| values[0] = params[i].getAttributeValue("value"); // NOI18N |
| localParams.put(name, values); |
| } |
| } |
| } |
| else if(localMethod.equals("PUT")) { // NOI18N |
| |
| localParams = new Hashtable(); |
| |
| // PENDING |
| // This method would normally come with a file passed in |
| // through the inputstream. I am ignoring that. |
| } |
| |
| else { |
| // The user shouldn't be able to set any parameters for |
| // other HTTP methods. |
| localParams = new Hashtable(); |
| } |
| |
| // Set the headers and cookies |
| if(debug) { |
| log("CookieString from real req: " + //NOI18N |
| String.valueOf(getHRequest().getHeader("cookie"))); //NOI18N |
| log("CookieString from rd: " + //NOI18N |
| String.valueOf(rd.getCookieString())); |
| |
| } |
| |
| // Used to create the cookie header |
| StringBuffer cookieBuf = new StringBuffer(); |
| |
| // Set the headers in the wrapper to what they were set to in |
| // the data record. It will have to be modified in case either |
| // a) The user wanted to use the browser's cookie |
| // b) The server can't replace the session cookie |
| int numHeaders = rd.getHeaders().sizeParam(); |
| localHeaders = new Param[numHeaders]; |
| for(int i=0; i<numHeaders; ++i) |
| localHeaders[i] = rd.getHeaders().getParam(i); |
| |
| if(debug) { |
| log("How many parameters do we have?"); //NOI18N |
| log("param length is " + String.valueOf(localHeaders.length)); //NOI18N |
| for(int i=0; i<localHeaders.length; ++i) |
| log(localHeaders[i].getName() + " " + //NOI18N |
| localHeaders[i].getValue()); |
| } |
| |
| // We're going to parse the cookies again so we'll start with |
| // an empty vector |
| localCookies = new Vector(); |
| |
| // Holds the session id from the data record |
| String idFromRequest = null; |
| |
| // Cookies from the data record |
| Param[] myCookies = rd.getCookiesAsParams(); |
| |
| // Start by adding the recorded cookies, if there were any |
| if(myCookies != null && myCookies.length > 0) { |
| |
| if(debug) log("Now adding cookies"); //NOI18N |
| |
| String ckname = null, ckvalue=null; |
| for(int i=0; i<myCookies.length; ++i) { |
| |
| ckname = myCookies[i].getAttributeValue("name"); //NOI18N |
| ckvalue = myCookies[i].getAttributeValue("value"); //NOI18N |
| |
| // We don't add the session cookie yet, but we keep |
| // the session id from the record in case |
| if(ckname.equalsIgnoreCase(JSESSIONID)) { |
| idFromRequest = ckvalue; |
| continue; |
| } |
| localCookies.add(new Cookie(ckname, ckvalue)); |
| if(debug) log("Added " + ckname + "=" + ckvalue); //NOI18N |
| |
| if(cookieBuf.length() > 0) cookieBuf.append("; "); //NOI18N |
| cookieBuf.append(ckname); |
| cookieBuf.append("="); //NOI18N |
| cookieBuf.append(ckvalue); |
| } |
| } |
| |
| // Find out if the session id was replaced by checking whether |
| // the replaced attribute was set (by the MonitorValve, on |
| // Tomcat). |
| |
| boolean sessionReplaced = false; |
| try { |
| String value = (String)getHRequest().getAttribute(REPLACED); |
| if(value.equals("true")) sessionReplaced = true; //NOI18N |
| if(debug) log("replaced the session"); //NOI18N |
| } |
| catch(Exception ex) { |
| if(debug) log("didn't replace the session"); //NOI18N |
| } |
| |
| if(sessionReplaced) { |
| |
| // If the session ID was replaced, this could mean either |
| // that we request a different session or that the |
| // reference to the session was removed. In the former |
| // case, we add the session cookie to the vector and to |
| // the cookie string, using the ID from the data record. |
| |
| if(idFromRequest != null) { |
| |
| localCookies.add(new Cookie(JSESSIONID, idFromRequest)); |
| if(cookieBuf.length() > 0) cookieBuf.append("; "); //NOI18N |
| cookieBuf.append(JSESSIONID); |
| cookieBuf.append("="); //NOI18N |
| cookieBuf.append(idFromRequest); |
| } |
| // In the latter case we do nothing. |
| } |
| else { |
| |
| // The session ID was not replaced, and to adjust for this |
| // we add the session cookie from the incoming request, if |
| // there is one. |
| |
| // PENDING! |
| // If the user wanted to replace the ID and it failed, |
| // this should be flagged here. |
| |
| if(debug) log("Old request is " + getHRequest().toString()); //NOI18N |
| |
| Cookie[] ck = getHRequest().getCookies(); |
| |
| if(debug) log("Got the incoming cookies"); //NOI18N |
| |
| if(ck != null && ck.length > 0) { |
| for(int i=0; i<ck.length; ++i) { |
| if(ck[i].getName().equals(JSESSIONID)) { |
| localCookies.add(ck[i]); |
| if(cookieBuf.length() > 0) cookieBuf.append("; "); //NOI18N |
| cookieBuf.append(JSESSIONID); |
| cookieBuf.append("="); //NOI18N |
| cookieBuf.append(ck[i].getValue()); |
| } |
| } |
| } |
| // the entity that sent the request did not send any |
| // cookies, do nothing |
| } |
| String cookieStr = cookieBuf.toString(); |
| if(cookieStr.equals("")) { //NOI18N |
| if(debug) log("No cookies, deleting cookie header"); //NOI18N |
| removeHeader("cookie"); //NOI18N |
| } |
| else { |
| if(debug) log("Setting cookie header to " + //NOI18N |
| cookieBuf.toString()); |
| setHeader("cookie", cookieBuf.toString()); //NOI18N |
| } |
| } |
| |
| |
| // UTILITY METHODS |
| // These methods set local data. They are used by |
| // populate to set data during replays. |
| |
| |
| /** |
| * This method MUST be invoked by the monitor filter whenever it |
| * receives a request to process a dispatched request, BEFORE it |
| * collects any data. |
| * We need to do this because the specs allow web components to |
| * add extra parameters on dispatch, e.g. |
| * <jsp:forward page="page.jsp"> |
| * <jsp:param name="name" value="value"/> |
| * </jsp:forward> |
| * and these are only available to the dispatched-to resources |
| * (at least some servers remove them after the request dispatcher |
| * has terminated). So we must have a mechanism which guarantees |
| * that the resources in the web app (and the monitor itself) only |
| * sees the parameters when they would have been visible without |
| * the monitor in place. |
| * To deal with such parameters on a replay (where the request's |
| * "real" parameters have been replaced with the ones from the |
| * original request) I have to add them to the ones that the |
| * wrapper already knows about. |
| */ |
| void pushExtraParameters() { |
| |
| if(!replay) return; |
| |
| if(debug) log("pushExtraParameters"); //NOI18N |
| |
| // If this is a replay and the request was dispatched using |
| // the following type of syntax |
| // <jsp:forward page="page.jsp"> |
| // <jsp:param name="name" value="value"/> |
| // </jsp:forward> |
| // then the server will add a parameter to the request in the |
| // background (there are no API methods to do this). So we |
| // have to check if the parameters that the original request |
| // is aware of have grown. If so, we create an additional map |
| // with the extra parameters. |
| |
| Map extraParams = new Hashtable(); |
| |
| Map currentMap = getRequest().getParameterMap(); |
| Iterator keys = currentMap.keySet().iterator(); |
| |
| while(keys.hasNext()) { |
| Object o = keys.next(); |
| if(debug) { |
| //log("Key: " + (String)o); //NOI18N |
| String[] value = (String[])currentMap.get(o); |
| StringBuffer buf = new StringBuffer(); |
| for(int k=0; k<value.length; ++k) { |
| buf.append(value[k]); |
| buf.append(" "); //NOI18N |
| } |
| log("Value: " + buf.toString()); //NOI18N |
| } |
| |
| if(!oldParams.containsKey(o)) { |
| extraParams.put(o, currentMap.get(o)); |
| continue; |
| } |
| |
| if(oldParams.get(o).equals(currentMap.get(o))) { |
| continue; |
| } |
| else { |
| extraParams.put(o, currentMap.get(o)); |
| } |
| } |
| if(extraParamStack == null) |
| extraParamStack = new Stack(); |
| |
| extraParamStack.push(extraParams); |
| if(debug) |
| log("Param stack size: " + String.valueOf(extraParamStack.size())); //NOI18N |
| } |
| |
| /** |
| * This method MUST be invoked by the monitor filter whenever it |
| * has finished processing a dispatched request, AFTER it has |
| * collected the data. |
| * |
| * @see pushExtraParameters |
| */ |
| void popExtraParameters() { |
| |
| if(!replay) return; |
| |
| if(debug) log("popExtraParameters"); //NOI18N |
| if(extraParamStack == null || extraParamStack.empty()) { |
| log("ERROR - MonitorRequestWrapper empty param stack!"); //NOI18N |
| return; |
| } |
| extraParamStack.pop(); |
| } |
| |
| |
| /** |
| * The setHeader method allows the request wrapper to modify |
| * the value of a header. This method is only used during replay, |
| * by the populate method. |
| */ |
| private void setHeader(String headerName, String headerValue) { |
| |
| if(!replay) { |
| log("setHeader() must only be used from replay"); //NOI18N |
| return; |
| } |
| |
| boolean addedHeader = false; |
| |
| if(debug) log("Headers were set locally"); //NOI18N |
| for(int i=0; i<localHeaders.length; ++i) { |
| if(localHeaders[i].getName().equalsIgnoreCase(headerName)) { |
| localHeaders[i].setValue(headerValue); |
| addedHeader = true; |
| if(debug) log("Replaced existing header"); //NOI18N |
| break; |
| } |
| } |
| if(addedHeader) return; |
| Param[] p = new Param[localHeaders.length + 1]; |
| int numHeaders = 0; |
| while(numHeaders < localHeaders.length) { |
| p[numHeaders] = localHeaders[numHeaders]; |
| ++numHeaders; |
| } |
| p[numHeaders] = new Param(headerName, headerValue); |
| localHeaders = p; |
| if(debug) log("Added new header"); //NOI18N |
| return; |
| } |
| |
| /** |
| * The removeHeader method allows the request wrapper to delete |
| * a header. This may be necessary during a replay, to remove the |
| * session cookie if the browser didn't send one. Note that using |
| * this method will result in the headers being local to the |
| * RequestWrapper, since we can't manipulate the headers on the |
| * actual request. |
| */ |
| private void removeHeader(String headerName) { |
| |
| if(!replay) { |
| log("removeHeader() must only be used from replay"); //NOI18N |
| return; |
| } |
| |
| if(debug) log("removeHeader()"); //NOI18N |
| |
| Vector v = new Vector(); |
| |
| for(int i=0; i<localHeaders.length; ++i) { |
| if(localHeaders[i].getName().equalsIgnoreCase(headerName)) |
| continue; |
| v.add(localHeaders[i]); |
| } |
| |
| int size = v.size(); |
| localHeaders = new Param[size]; |
| for(int i=0; i< size; ++i) |
| localHeaders[i] = (Param)v.elementAt(i); |
| return; |
| } |
| |
| |
| |
| /** |
| * toString prints out the main values of the request. |
| */ |
| public String toString() { |
| StringBuffer buf = new StringBuffer(); |
| buf.append("uri: "); // NOI18N |
| buf.append(getRequestURI()); |
| buf.append("\n"); // NOI18N |
| buf.append("method: "); // NOI18N |
| buf.append(getMethod()); |
| buf.append("\n"); // NOI18N |
| buf.append("QueryString: "); // NOI18N |
| buf.append(getQueryString()); |
| buf.append("\n"); // NOI18N |
| buf.append("Parameters:\n"); // NOI18N |
| Enumeration e = getParameterNames(); |
| while(e.hasMoreElements()) { |
| String name = (String)e.nextElement(); |
| String value = getParameter(name); |
| buf.append("\tName: "); // NOI18N |
| buf.append(name); |
| buf.append("\tValue: "); // NOI18N |
| buf.append(value); |
| buf.append("\n"); // NOI18N |
| } |
| |
| buf.append("Headers:\n"); // NOI18N |
| e = getHeaderNames(); |
| while(e.hasMoreElements()) { |
| String name = (String)e.nextElement(); |
| String value = getHeader(name); |
| buf.append("\tName: "); // NOI18N |
| buf.append(name); |
| buf.append("\tValue: "); // NOI18N |
| buf.append(value); |
| buf.append("\n"); // NOI18N |
| } |
| return buf.toString(); |
| } |
| |
| /* |
| * log, used for debugging. |
| */ |
| private void log(String s) { |
| System.out.println("MonitorRequestWrapper::" + s); // NOI18N |
| } |
| |
| } // MonitorRequestWrapper |