/*
 * 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.
 */

package org.netbeans.modules.web.monitor.server;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

import java.net.MalformedURLException;

import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.ResourceBundle;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;

import java.text.DateFormat;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;

import org.netbeans.modules.web.monitor.data.*;

public class MonitorFilter extends Logger implements Filter {

    // REPLAY strings - must be coordinated with client.Controller
    public final static String REPLAY = "netbeans.replay"; //NOI18N
    public final static String PORT = "netbeans.replay.port"; //NOI18N
    public final static String REPLAYSTATUS = "netbeans.replay.status"; //NOI18N
    public final static String REPLAYSESSION = "netbeans.replay.session"; //NOI18N

    // The request attribute name under which we store a reference to
    // ourself. 
    private String attribute = null;
    public final static String PREFIX = "netbeans.monitor"; //NOI18N
    private final static String attNameRequest =
	"netbeans.monitor.request"; //NOI18N
    private final static String attNameResponse =
	"netbeans.monitor.response"; //NOI18N
    private final static String attNameFilter =
	"netbeans.monitor.filter"; //NOI18N
    private final static String attNameMonData =
	"netbeans.monitor.monData"; //NOI18N
    //private final static String attNameExecTime =
    //"netbeans.monitor.execTime"; //NOI18N
    public static final String IDE = "netbeans.monitor.ide"; //NOI18N
    public static final String IDES = "netbeans.monitor.register"; //NOI18N

    // Are we supposed to run?
    private static boolean collectData = true;
    
    // The filter configuration object we are associated with.  If
    // this value is null, this filter instance is not currently
    // configured. 
    private FilterConfig filterConfig = null;

    private final static String className = 
	"org.netbeans.modules.web.monitor.server.Monitor"; //NOI18N
    
    private static ResourceBundle statusmsgs = 
	ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.MonitorBundle"); //NOI18N 

    private static NotifyUtil notifyUtil = null;

    /**
     * List of AppServer system web modules whose requests will be filtered out
     */
    private static final String APPSERVER_SYSTEM_WEB_MODULES[] = {
                "/com_sun_web_ui", //NOI18N
                "/asadmin", //NOI18N
                "/web1"}; //NOI18N

    /**
     * Netbeans internal request URI to find out the Tomcat running status.
     *
     * Issue #47048 - the HttpURLConnection is now used to determine whether Tomcat
     * is running. The request URI equals "/netbeans-tomcat-status-test" to make
     * it possible for the monitor to filter it out.
     */
    private static final String NETBEANS_INTERNAL_REQUEST_URI = 
                "/netbeans-tomcat-status-test"; //NOI18N

    // debugging 
    private final static boolean debug = false;

    public MonitorFilter() { 
    } 

    /**
     * Collects data of the HTTP Transaction
     *
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
	throws IOException, ServletException {

	// Time stamp for when Monitor filter is invoked
	//long entryTime = System.currentTimeMillis(); 

	if(debug) log("doFilter()");  //NOI18N

	// PENDING - checking with Tomcat developers to find out if
	// there is some other way to reliably determine that a
	// request is for the manager application.
	Object obj = getFilterConfig().getServletContext().getAttribute("org.apache.catalina.MBeanServer"); 
        
        boolean internalAppServerRequest = false;
        boolean internalIDERequest = false;
        if (request instanceof HttpServletRequest) {
            // PENDING - a saffer way how to filter out internal AppServer requests
            // should be used, system web modules URIs can be changed in the next 
            // AppServer release
            String requestURI = ((HttpServletRequest)request).getRequestURI();
            for (int i = 0; i < APPSERVER_SYSTEM_WEB_MODULES.length; i++) {
                if (requestURI.startsWith(APPSERVER_SYSTEM_WEB_MODULES[i])) {
                    internalAppServerRequest = true;
                    break;
                }
            }
            
            // Issue #47048 - the HttpURLConnection is now used to determine whether Tomcat
            // is running. The requestURI is "/netbeans-tomcat-status-test" to make 
            // it possible for the monitor to filter it out.
            if (requestURI.startsWith(NETBEANS_INTERNAL_REQUEST_URI)) {
                internalIDERequest = true;
            }
        }
        
	if(!collectData || !(request instanceof HttpServletRequest) ||
	   obj != null || internalAppServerRequest || internalIDERequest)  {

	    if(debug) log("not collecting data"); //NOI18N
	    // Do not be tempted to factor this into its own methods
	    // - gotta retrow those exceptions remember... 
	    try {
		chain.doFilter(request, response);
	    }
	    catch(Throwable t) {
		rethrow(t);
	    }
	    return;
	}
	
	HttpServletRequest req = (HttpServletRequest)request; 
	if(debug) log("Request for: " + req.getRequestURI()); //NOI18N

	// On servlet 2.4 containers, the filter processes dispatched
	// requests as well. We need to know whether this invocation
	// is the outermost invocation or not. The outermost
	// invocation sets up the MonitorData object and replaces the
	// request and response with a wrappers, and is responsible
	// for sending data back. Inner invocations create another
	// type of data object and link them to the one for the parent
	// invocation. 
	boolean outermost = true; 

	HttpServletRequestWrapper requestWrapper = null; 
	HttpServletResponseWrapper responseWrapper = null; 

	// We collect the same type of data for original and
	// dispatched requests. The latter is nested inside the
	// former. The schema2beans library does (did?) not allow an
	// XML element to have itself as a member, so we use an
	// interface DataRecord to represent either a MonitorData
	// record (outer) or DispatchData (inner).
	DataRecord dr = null; 

	if(request instanceof HttpServletRequestWrapper &&
	   response instanceof HttpServletResponseWrapper) { 
	    
	    Object o = req.getAttribute(attNameRequest); 
	    if(o instanceof MonitorRequestWrapper) { 
		
		if(debug) 
		    log("Request previously processed by the monitor"); //NOI18N
		outermost = false; 

		// The response has been wrapped by the Monitor and
		// possibly by another entity as well (meaning that it
		// was dispatched). We use the outermost wrappers.
		requestWrapper = (HttpServletRequestWrapper)req; 
		responseWrapper = (HttpServletResponseWrapper)response;
		
		// Create the data record for the dispatched request
		// and link it into the parent data record. 
		dr = setupDispatchDataRecord((MonitorRequestWrapper)o); 

		// This will also add the time since the monitor last
		// left off to the execution time the resourced that
		// caused the current dispatch.
		//dr = setupDispatchDataRecord((MonitorRequestWrapper)o, 
		// entryTime); 
		if(dr == null) { 
		    if(debug) 
			log("failed to link to parent data record"); //NOI18N
		    try { chain.doFilter(request, response); }
		    catch(Throwable t) { rethrow (t); }
		    return;
		} 
	    }
			    
	    // If we can't get the MonitorRequestWrapper from the
	    // attribute, the request was wrapped, but not by the
	    // Monitor. This means that we're processing an incoming
	    // request (as opposed to a dispatched request, which
	    // would have been wrapped by the monitor already) and
	    // that another Filter has been deployed before the
	    // MonitorFilter. We log a warning to the log file to
	    // inform the user of this. (Unless the other filter
	    // modifies the request, this is probably harmless, though
	    // the other filter might give the "wrong" info in case of
	    // a replay for example).

	    if(requestWrapper == null) log(ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Deploy_first")); //NOI18N
	} 

	if(requestWrapper == null) { 

	    if(debug) log("request just entered container"); //NOI18N
	    // The request was not wrapped, signalling that it is an
	    // original (non-dispatched) request. 
	
	    // The first step is to check whether it was a replay or
	    // not. If it is a replay, the query string will have a
	    // replay parameter. Note that we must *not* use
	    // getParameter() because this will cause the query string
	    // and data to be parsed once and for all, and it is
	    // possible that the application object expects to parse
	    // the inputstream directly. 
	    String query = req.getQueryString();

	    if(query != null && query.startsWith(REPLAY)) { 

		if(debug) log("received replay request"); //NOI18N

		try { 
		    requestWrapper = getReplayRequest(req); 
		} 
		catch(IOException ioex) { 
		    // We received a request for a replay, but failed
		    // to retrive replay data. We process this as a
		    // normal request, as the request will go to the
		    // same resource, though perhaps the behaviour
		    // should be modified to show an error msg
		    // instead).  
		    try { chain.doFilter(request, response);	}
		    catch(Throwable t) { rethrow (t); }
		    return;
		}
	    }
	    else {
		if(debug) log("wrapping the request"); //NOI18N
		requestWrapper = new MonitorRequestWrapper(req);  
	    }
		
	    // Set the wrapper as a request attribute. Because
	    // developers can use as many filters that they like,
	    // and because these filter must use a wrapped request
	    // (since Servlet 2.4), there's no guarantee that the
	    // request object this filter receives on dispatch is
	    // a MonitorRequestWrapper. Setting it as an attribute
	    // saves us from walking the wrapper chain to find the
	    // wrapper, and also to find out if it this was a
	    // dispatched request (see above). 
	    requestWrapper.setAttribute(attNameRequest, requestWrapper); 

	    // Create the data record, using the wrapped request. 
	    dr = setupDataRecord(requestWrapper); 

	    // Create the response wrapper
	    if(debug) log(" Replace Response"); //NOI18N
	    HttpServletResponse res = (HttpServletResponse)response;

	    // The responseWrapper has a handle on the response
	    // (obviously) and also on the request. The latter is
	    // used to determine whether the request is currently
	    // dispatched as an include, for the purposes of knowing
	    // whether cookies can be added or not. 
	    responseWrapper = 
		new MonitorResponseWrapper(res, requestWrapper); 
	    
	    // We need the response wrapper to collect data after the
	    // request has processed, this saves us from walking the
	    // wrapper chain. 
	    requestWrapper.setAttribute(attNameResponse, responseWrapper); 
	    
	    // This attribute allows a Servlet 2.3 container to locate
	    // the filter and invoke the methods deal with dispatched
	    // requests if they have the capability of listening to
	    // such events. 
	    requestWrapper.setAttribute(attNameFilter, this); 
	} 

	Throwable processingError = null;
	boolean cntnue = true; 

	// Collect data about the request before it is processed
	if(debug) log("doFilter(): Collect data before"); //NOI18N

	try { 
	    getDataBefore(dr, requestWrapper); 

	}
	catch(StackOverflowError soe) { 
	    // The developer has done something that causes an
	    // infinite loop. We will not go through with running the
	    // filter and catching more data. Technically we should
	    // delete the last DispatchData record from the monitor
	    // stack, but I will just push on an incomplete one. The
	    // user would have to open about a 100 nested records to
	    // see an error. 

	    if(debug) 
		log(" StackOverflow before processing the request"); //NOI18N
	    processingError = soe; 
	    cntnue = false; 
	}

	catch(Throwable t) { 
	    // There was a problem in the monitor code, ignore and continue
	    if(debug) log(getStackTrace(t)); 
	} 

	if(cntnue) { 

	    //if(debug) log("Setting time in request attribute"); 
	    //requestWrapper.setAttribute(attNameExecTime, 
	    //new Long(System.currentTimeMillis())); 
	    try { 
		chain.doFilter(requestWrapper, responseWrapper);
	    }

	    catch(StackOverflowError soe) { 
		// The developer has done something that causes an
		// infinite loop. We will not go through with running the
		// filter and catching more data. Technically we should
		// delete the last DispatchData record from the monitor
		// stack, but I will just push on an incomplete one. The
		// user would have to open about a 100 nested records to
		// see an error. 

		if(debug) 
		    log(" StackOverflow while processing the request"); //NOI18N
		processingError = soe; 
		cntnue = false; 
	    }

	    catch(Throwable t) {
		processingError = t;
	    }
	    /*
	      try { 
	      long exit = System.currentTimeMillis();
	      if(debug) log("Setting execution time on last known data record");
	      long entry = ((Long)requestWrapper.getAttribute(attNameExecTime)).
	      longValue(); 
	      dr.addExecTime(exit-entry); 
	      }
	      catch(NullPointerException npe) { 
	      // Couldn't get the attribute - perhaps the request got
	      // mangled by an intrusive user request wrapper
	      if(debug) npe.printStackTrace();
	      }
	      catch(ClassCastException cce) { 
	      // The attribute did not contain a long. Shouldn't
	      // happen. 
	      if(debug) cce.printStackTrace();
	      }
	      catch(Throwable t) { 
	      // The attribute did not contain a long. Shouldn't
	      // happen. 
	      if(debug) t.printStackTrace();
	      }
	    */
	}

	if(cntnue) { 

	    // Collect data after the request is processed. (This method
	    // gets the MonitorResponseWrapper from the request
	    // attribute. As for the request, we can get it from any
	    // request object, we need the wrapper only for the replay
	    // setup.) 
	    if(debug) log("doFilter(): Collect data after"); //NOI18N

	    try { 
		getDataAfter(dr, requestWrapper); 
	    }
	    catch(Throwable t) { 
		if(debug) log(getStackTrace(t)); 
	    } 
	} 

	// Finish the record
	if(outermost) { 
	    if(debug) log("Final, send data to server"); //NOI18N
	    disposeDataRecord(requestWrapper); 
	} 
	else { 
	    if(debug) log("Non-final, continue processing"); //NOI18N
	    disposeDispatchedDataRecord(requestWrapper); 
	    // Pop the RequestWrapper's parameter stack	
	    ((MonitorRequestWrapper)(requestWrapper.getAttribute(attNameRequest))).popExtraParameters(); 
	} 
       
	if(processingError != null) {
	    // user will get this from the log 
	    // log("A web application object caused an exception"); //NOI18N
	    // log(getStackTrace(processingError)); 
	    rethrow(processingError); 
	}
    
	// Set the time stamp
	// req.setAttribute(attNameExecTime, 
	//	new Long(System.currentTimeMillis())); 
    }

    private DataRecord setupDataRecord(ServletRequest req) { 

	if(debug) log("setupDataRecord()"); //NOI18N
	MonitorData md = new MonitorData(); 
	Stack dataStack = new Stack(); 
	dataStack.push(md);
	if(debug) log(" created MonData stack & set attribute");  //NOI18N
	req.setAttribute(attNameMonData, dataStack); 
	return md; 
    }

    /**
     * setupDispatchDataRecord creates a new DispatchDataRecord to
     * record data for the request we are about to process and links
     * it to the Dispatches category of the data record associated 
     * with the resource which dispatched the request. If that
     * resource has not dispatched before (true if forward, or if
     * first include), then we create a Dispatches object for this
     * data record.  
     * @param req The MonitorRequestWrapper associated with the
     * request.
     * @return a fresh DataRecord
     */
    private DataRecord setupDispatchDataRecord(MonitorRequestWrapper req) { 

	/* @param entryTime The value returned by
	 * System.currentTimeMillis() when the MonitorFilter kicked in for
	 * this request. Gotten by doFilter in a Servlet 2.4 environment,
	 * by handleDispatchedBefore pre Servlet 2.4. */
	// long entryTime) 

	req.pushExtraParameters(); 
	if(debug) log("Pushed the wrapper parameters"); //NOI18N

	Stack dataStack = null;
	try {
	    dataStack = (Stack)(req.getAttribute(attNameMonData)); 
	}
	catch(Throwable t){
	    // This should not fail 
	    if(debug) log("MonitorFilter - this request had no stack");//NOI18N
	    return null;
	}
	 
	if(dataStack.empty()) {
	    if(debug) log("process dispatched ERROR - stack is empty");//NOI18N
	    return null;
	}

	Object obj = dataStack.peek(); 
	Dispatches disp = null;

	if(!(obj instanceof DataRecord)) {
	    if(debug) log("ERROR - obj on stack is not DataRecord"); //NOI18N
	    return null; 
	} 

	DataRecord dr = (DataRecord)obj;

	// Add the execution time to the record
	/*
	  try { 
	  if(debug) log("Setting execution time on last known data record");
	  long lastExit = ((Long)req.getAttribute(attNameExecTime)).longValue(); 
	  dr.addExecTime(entryTime-lastExit); 
	  }
	  catch(NullPointerException npe) { 
	  // Couldn't get the attribute - perhaps the request got
	  // mangled by an intrusive user request wrapper
	  if(debug) npe.printStackTrace();
	  }
	  catch(ClassCastException cce) { 
	  // The attribute did not contain a long. Shouldn't
	  // happen. 
	  if(debug) cce.printStackTrace();
	  }
	  catch(Throwable t) { 
	  // Something went wrong with schema2beans
	  if(debug) t.printStackTrace();
	  }
	*/

	disp = dr.getDispatches();
	if(disp == null) { 
	    if(debug) log("Data record had no dispatches yet"); //NOI18N
	    disp = new Dispatches();
	    dr.setDispatches(disp);
	}

	DispatchData disData = new DispatchData();
	disp.addDispatchData(disData);
	if(debug) log("Added new data record to existing one"); //NOI18N

	dataStack.push(disData);
	if(debug) log("pushed the data record onto the stack"); //NOI18N
	return disData;
    } 

    private void disposeDataRecord(ServletRequest req) { 

	if(debug) log("disposeDataRecord()"); //NOI18N

	// Remove the attributes used by the monitor - we need to do
	// this in case there is an error...
	req.removeAttribute(attNameRequest); 
	req.removeAttribute(attNameResponse); 
	req.removeAttribute(attNameFilter); 

	MonitorData monData = null;

	Stack stack = (Stack)(req.getAttribute(attNameMonData)); 
	req.removeAttribute(attNameMonData); 

	if(stack != null && !stack.empty()) { 
	    if(debug) { 
		log("found mondata stack"); //NOI18N	
		log("stack size=" + stack.size()); //NOI18N	
	    } 
	    Object o = stack.pop(); 
	    if(o instanceof MonitorData) 
		monData = (MonitorData)o;
	    else if(debug) { 
		log(o.toString()); 
		log("ERROR - wrong type object on stack"); //NOI18N
	    } 
	}
	else if(debug) { 
	    log("ERROR - mondata stack empty"); //NOI18N
	} 

	if(monData == null) { 
	    return; 
	} 

	StringBuffer buf = 
	    new StringBuffer(monData.getAttributeValue("id")); //NOI18N
	buf.append(Constants.Punctuation.itemSep);
	buf.append(monData.getAttributeValue("method")); //NOI18N
	buf.append(Constants.Punctuation.itemSep);
	buf.append(monData.getAttributeValue("resource")); //NOI18N
	
	if(debug) { 
	    log(" Notify client"); //NOI18N	
	    log(" Query string is "  + //NOI18N
		buf.toString());
	    log("Notify util is " + notifyUtil.toString()); //NOI18N

	    String file = 
		monData.createTempFile("filter-send.xml"); // NOI18N
	    log("Wrote data to " + file); // NOI18N
	}

	notifyUtil.sendRecord(monData, buf.toString()); 
	if(debug) log("Notify util has terminated"); //NOI18N

    }

    private DataRecord disposeDispatchedDataRecord(ServletRequest req) { 

	Stack stack = (Stack)(req.getAttribute(attNameMonData)); 
	Object o = null; 
	if(stack != null && !stack.empty())
	    o = stack.pop(); 
	if(o instanceof DataRecord) return (DataRecord)o; 
	return null; 
    } 

    /**
     * This is a utility method for Servlet 2.3 containers. Configure
     * the container to access the servlet filter from the request
     * attribute and invoke this method in order to gather data about
     * dispatched requests. 
     */
    public void handleDispatchedBefore(ServletRequest req) { 

	// Time stamp for when Monitor filter is invoked
	// long entryTime = System.currentTimeMillis(); 

	if(debug) log ("handleDispatchBefore: start");//NOI18N

	Object w  = req.getAttribute(attNameRequest); 
	if(w == null || !(w instanceof MonitorRequestWrapper)) { 
	    return; 
	} 
	// get the dispatch data 
	DataRecord dr = setupDispatchDataRecord((MonitorRequestWrapper)w); 
	//entryTime); 

	if(dr == null) return; 

	// collect data 
	getDataBefore(dr, (HttpServletRequest)req); 

	/*
	  if(debug) log("Setting time attribute on request wrapper");
	  req.setAttribute(attNameExecTime, 
	  new Long(System.currentTimeMillis())); 
	*/
	return; 
    } 
				       

    /**
     * This is a utility method for Servlet 2.3 containers. Configure
     * the container to access the servlet filter from the request
     * attribute and invoke this method in order to gather data about
     * dispatched requests. 
     */
    public void handleDispatchedAfter(ServletRequest req) { 

	//long entry = System.currentTimeMillis(); 
	
	if(debug) log ("handleDispatchedAfter()");//NOI18N

	Object w  = req.getAttribute(attNameRequest); 
	if(w == null || !(w instanceof MonitorRequestWrapper)) { 
	    return; 
	} 

	DataRecord dr = disposeDispatchedDataRecord((MonitorRequestWrapper)w);
	if(dr == null) return; 

	/*
	  try { 
	  if(debug) log("Setting execution time on last known data record");
	  long exit = 
	  ((Long)req.getAttribute(attNameExecTime)).longValue(); 
	  dr.addExecTime(entry-exit); 
	  }
	  catch(NullPointerException npe) { 
	  // Couldn't get the attribute - perhaps the request got
	  // mangled by an intrusive user request wrapper
	  if(debug) npe.printStackTrace();
	  }
	  catch(ClassCastException cce) { 
	  // The attribute did not contain a long. Shouldn't
	  // happen. 
	  if(debug) cce.printStackTrace();
	  }
	  catch(Throwable t) { 
	  // The attribute did not contain a long. Shouldn't
	  // happen. 
	  if(debug) t.printStackTrace();
	  }
	*/

	// collect data 
	getDataAfter(dr, (HttpServletRequest)req); 
	if(debug) log ("collected data");//NOI18N

	// Pop the RequestWrapper's parameter stack	
	((MonitorRequestWrapper)w).popExtraParameters(); 

	/*
	  if(debug) log("Setting time attribute on request wrapper");
	  req.setAttribute(attNameExecTime, 
	  new Long(System.currentTimeMillis())); 
	*/
	return; 
    } 
    
    /**
     * Collects data from the HttpServletRequest before the servlet
     * processes it 
     */
    private void getDataBefore(DataRecord dataRecord, 
			       HttpServletRequest request) {

	if(dataRecord instanceof MonitorData) {
	    String timestamp = String.valueOf(System.currentTimeMillis()); 
	    String method = request.getMethod();
	    String uri = request.getRequestURI();

	    // PENDING - this is used for the label and should refer to
	    // the resource, not to the URI that was used to access it. 
	    String resource = new String(uri);

	    // PENDING - don't use the timestamp as the ID
	    String id = new String(timestamp);
	    
	    if(debug) { 
		log("            id: " + id); //NOI18N
		log("           uri: " + request.getRequestURI()); //NOI18N
	    }
	    dataRecord.setAttributeValue("id", id); //NOI18N
	    dataRecord.setAttributeValue("timestamp", timestamp); //NOI18N
	    dataRecord.setAttributeValue("resource", resource); //NOI18N
	    dataRecord.setAttributeValue("method", method); //NOI18N
	}
	else if(dataRecord instanceof DispatchData) {
	    String resource =
		(String)request.getAttribute("javax.servlet.include.request_uri"); //NOI18N
	    if(resource == null || resource.equals("")) //NOI18N
		resource = request.getRequestURI();
	    
	    dataRecord.setAttributeValue("resource", resource);//NOI18N
	}
	
	// PENDING: 
	// The following three only need to be recorded once per
	// request. Need to modify the client first however. 
	// ---------------------- FROM HERE -------------------
	if(debug) log(" Client Data"); //NOI18N
	ClientData cd = new ClientData();
	recordClientData(cd, request);
	dataRecord.setClientData(cd);
	
	if(debug) log(" Context data"); //NOI18N
	ContextData cond = new ContextData();
	recordContextData(cond, request);
	dataRecord.setContextData(cond);
	
	if(debug) log(" Servlet engine data"); //NOI18N
	EngineData ed = new EngineData();
	recordEngineData(ed, request);
	dataRecord.setEngineData(ed);
	// ---------------------- TO HERE ---------------------
	 
	if(debug) log(" Session Data"); //NOI18N
	SessionData sd = new SessionData();
	getSessionIn(sd, request);
	dataRecord.setSessionData(sd);
	
	if(debug) log(" Request Data"); //NOI18N
	RequestData rd = new RequestData(); 
	recordRequestData(rd, request);
	if(debug) log(" Set Request Data"); //NOI18N
	dataRecord.setRequestData(rd); 

	// We must do this after we have processed the headers
	if(debug) log(" Cookie Data"); //NOI18N
	CookiesData cookiesData = new CookiesData();
	recordCookiesIn(cookiesData, request); 
	dataRecord.setCookiesData(cookiesData); 

	if(debug) log("getDataBefore(): done"); //NOI18N
    }

    
    private void getDataAfter(DataRecord dataRecord, 
			      HttpServletRequest request) { 

	if(debug) log("getDataAfter(DataRecord, HttpServletRequest)"); //NOI18N
	
	MonitorResponseWrapper monResponse = 
	    (MonitorResponseWrapper)request.getAttribute(attNameResponse); 
	
	if(debug) log(" Get status");	//NOI18N
	int status = monResponse.getStatus();
        RequestData rd = dataRecord.getRequestData();
        // if the exit status is unknown, display appropriate msg instead
        if (status == 0) {
            if(debug) log(ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Unknown_exit_status"));
            rd.setAttributeValue("status", //NOI18N
                    ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Unknown_exit_status"));
        } else {
            String statusStr = "sc".concat(String.valueOf(status)); //NOI18N
            if(debug) log("Status string is " + statusStr); 
	
            if(debug) log(String.valueOf(statusmsgs.getString(statusStr))); 

            rd.setAttributeValue("status", //NOI18N
			     statusmsgs.getString(statusStr)); //NOI18N
        }

	if(debug) log(" request attributes out"); //NOI18N
	RequestAttributesOut reqattrout = new RequestAttributesOut();
	reqattrout.setParam(recordRequestAttributes(request));
	
	rd.setRequestAttributesOut(reqattrout);

	if(debug)  log(" add request parameter"); //NOI18N
	addRequestParameters(rd, request); 

	if(debug) log(" Cookies out"); //NOI18N
	recordCookiesOut(dataRecord.getCookiesData(), monResponse); 

	if(debug) log(" Session out"); //NOI18N
	addSessionOut(dataRecord.getSessionData(), request);
    }
    

    /**
     * Creates an instance of ClientData based on the request
     */
    private void recordClientData(ClientData cd, 
				  HttpServletRequest request) {

	String protocol = request.getProtocol();
	while(protocol.endsWith("\n")) //NOI18N
	    protocol = protocol.substring(0, protocol.length()-2);
	 
	cd.setAttributeValue("protocol", protocol); //NOI18N
	cd.setAttributeValue("remoteAddress", //NOI18N
			     request.getRemoteAddr()); 

	Enumeration hvals; 
	StringBuffer valueBuf; 
	int counter; 

	// Software used
	valueBuf = new StringBuffer(128);
	counter = 0;
	hvals = request.getHeaders(Constants.Http.userAgent);
	if(hvals != null) { 
	    while(hvals.hasMoreElements()) { 
		if(counter > 0) valueBuf.append(", "); // NOI18N
		valueBuf.append((String)hvals.nextElement());
		++counter;
	    }
	}
	cd.setAttributeValue("software", valueBuf.toString()); //NOI18N
	 
	//Languages
	valueBuf = new StringBuffer(128);
	counter = 0;
	hvals = request.getHeaders(Constants.Http.acceptLang);
	if(hvals != null) { 
	    while(hvals.hasMoreElements()) { 
		if(counter > 0) valueBuf.append(", "); // NOI18N
		valueBuf.append((String)hvals.nextElement());
		++counter;
	    }
	}
	cd.setAttributeValue("locale", valueBuf.toString()); //NOI18N      

	// File formats
	valueBuf = new StringBuffer(128);
	counter = 0;
	hvals = request.getHeaders(Constants.Http.accept);
	if(hvals != null) { 
	    while(hvals.hasMoreElements()) { 
		if(counter > 0) valueBuf.append(", "); // NOI18N
		valueBuf.append((String)hvals.nextElement());
		++counter;
	    }
	}
	cd.setAttributeValue("formatsAccepted", valueBuf.toString()); //NOI18N
			   
	// Encoding
	valueBuf = new StringBuffer(128);
	counter = 0;
	hvals = request.getHeaders(Constants.Http.acceptEncoding);
	if(hvals != null) { 
	    while(hvals.hasMoreElements()) { 
		if(counter > 0) valueBuf.append(", "); // NOI18N
		valueBuf.append((String)hvals.nextElement());
		++counter;
	    }
	}
	cd.setAttributeValue("encodingsAccepted", valueBuf.toString()); //NOI18N
	//Char sets
	valueBuf = new StringBuffer(128);
	counter = 0;
	hvals = request.getHeaders(Constants.Http.acceptCharset);
	if(hvals != null) { 
	    while(hvals.hasMoreElements()) { 
		if(counter > 0) valueBuf.append(", "); // NOI18N
		valueBuf.append((String)hvals.nextElement());
		++counter;
	    }
	}
	cd.setAttributeValue("charsetsAccepted", valueBuf.toString()); //NOI18N    
	
    }
    
    private void recordCookiesIn(CookiesData cd, 
				 HttpServletRequest request) {  

	Cookie cks[] = null; 

	try { 
	    cks = request.getCookies();
	}
	catch(Exception ex) { 
	    // Do nothing, there were no cookies
	}
	
	if(cks == null || cks.length == 0) { 
	    if(debug) log(" no incoming cookies"); //NOI18N
	    cd.setCookieIn(new CookieIn[0]);
	    return;
	}

	if(debug) log(" found incoming cookies"); //NOI18N
	CookieIn[] theCookies = new CookieIn[cks.length];
	for (int i = 0; i < theCookies.length; i++) {
	    theCookies[i] = new CookieIn(cks[i]);
	    if(debug) log("cookie: " + //NOI18N
			  theCookies[i].toString());
	}
	cd.setCookieIn(theCookies);
    }
    
    private void recordCookiesOut(CookiesData cd, 
				  MonitorResponseWrapper response) {  

	if(debug) log(" Cookies out"); //NOI18N

	Enumeration e = response.getCookies();
	int numCookies = 0;
	while(e.hasMoreElements()) {
	    e.nextElement();
	    ++numCookies;
	}
	
	if(numCookies == 0) {
	    if(debug) log(" no cookies"); //NOI18N
	    cd.setCookieOut(new CookieOut[0]);
	    return;
	}

	if(debug) log(" number of cookies is " + //NOI18N
		      String.valueOf(numCookies)); //NOI18N
	e = response.getCookies();
	CookieOut[] theCookies = null;
	try {
	    theCookies = new CookieOut[numCookies];
	    for (int i = 0; i < theCookies.length; i++) {
		theCookies[i] = new CookieOut((Cookie)e.nextElement()); 
		if(debug) log("cookie: " + //NOI18N
			      theCookies[i].toString());
	    }
	}
	catch(NullPointerException ne) {
	    theCookies = new CookieOut[0];
	}
	cd.setCookieOut(theCookies);
    }


    private void getSessionIn(SessionData sess, 
			      HttpServletRequest request) {  

	HttpSession sessIn = null; 
	try { 
	    sessIn = request.getSession(false); 
	}
	catch(Exception ne) {}

	if(sessIn == null) {
	    sess.setAttributeValue("before", "false"); //NOI18N
	    return;
	}

	sess.setAttributeValue("before", "true"); //NOI18N

	sess.setAttributeValue("id", sessIn.getId()); //NOI18N
	DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
						       DateFormat.SHORT);  
	Date date = new Date(sessIn.getCreationTime()); 
	sess.setAttributeValue("created", df.format(date)); //NOI18N

	SessionIn si = new SessionIn();
	int maxint = 0; 
	try { 
	    maxint = sessIn.getMaxInactiveInterval(); 
	    if(maxint != 0) 
		// Note that XMLBeans library treats NMTOKENS as Strings
		si.setAttributeValue("inactiveInterval", //NOI18N
				     String.valueOf(maxint) );
	} 
	catch(NumberFormatException ne) {} 
	     
	try {
	    date = new Date(sessIn.getLastAccessedTime()); 
	    si.setAttributeValue("lastAccessed", df.format(date)); //NOI18N
	}
	catch(Exception ex) {}

	si.setParam(getSessionAttributes(sessIn)); 
	sess.setSessionIn(si);
    }
    
    private void addSessionOut(SessionData sess, HttpServletRequest request) {  
	
	HttpSession sessOut = null; 
	try { 
	    sessOut = request.getSession(false); 
	}
	catch(Exception ne) {}

	if(sessOut == null) {
	    sess.setAttributeValue("after", "false"); //NOI18N
	    return;
	}

	DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
						       DateFormat.SHORT);  

	sess.setAttributeValue("after", "true"); //NOI18N
	Date date = null;
	
	if(sess.getAttributeValue("before").equals("false")) { //NOI18N
	    sess.setAttributeValue("id", sessOut.getId());  //NOI18N
	    date = new Date(sessOut.getCreationTime()); 
	    sess.setAttributeValue("created", df.format(date));  //NOI18N
	}
	
	SessionOut so = new SessionOut();
	int maxint = 0; 
	try { 
	    maxint = sessOut.getMaxInactiveInterval(); 
	    if(maxint != 0) 
		so.setAttributeValue("inactiveInterval", //NOI18N
				     String.valueOf(maxint)); 
	} 
	catch(NumberFormatException ne) {} 
	try {
	    date = new Date(sessOut.getLastAccessedTime()); 
	    so.setAttributeValue("lastAccessed", df.format(date)); //NOI18N
	}
	catch(Exception ex) {}

	Param[] params = getSessionAttributes(sessOut);
	so.setParam(params);
	sess.setSessionOut(so);
    }
    

    private Param[] getSessionAttributes(HttpSession session) {

	Enumeration names = null;
	try {
	    names = session.getAttributeNames(); 
	}
	catch(Exception e) {}
	
	if(names == null || !names.hasMoreElements()) 
	    return new Param[0];

	Vector v = new Vector();
	while (names.hasMoreElements()) {
	    String name = (String)names.nextElement();
	    Object value = session.getAttribute(name);
	    String valueRep = null;            
            try {
                if(value == null) {
                    valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_attributes"); //NOI18N
                } else {
                    valueRep = value.toString();                    
                    if (valueRep == null) {
                        valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_null"); //NOI18N
                    }
                }
            } catch (Throwable t) {
                // Ensure that the monitor can continue to run even if there is a
                // serious problem in the application code that it is monitoring
                valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_exception"); //NOI18N
            }            
	    Param p = new Param();
	    p.setAttributeValue("name", name); //NOI18N
	    p.setAttributeValue("value", valueRep); //NOI18N
	    v.add(p);
	}
	int size = v.size();
	Param[] params = new Param[size]; 
	for(int i=0; i<size; ++i) 
	    params[i] = (Param)v.elementAt(i);
	return params;
    }


    /**
     * Creates an instance of RequestData based on the request
     */
    private void recordRequestData(RequestData rd, 
				   HttpServletRequest request) {

	if(debug)  log(" recordRequestData()"); //NOI18N
	
	// The method variable is used again below
	String method = request.getMethod();
	
	rd.setAttributeValue("uri", request.getRequestURI()); //NOI18N
	rd.setAttributeValue("method", method); //NOI18N

	String protocol = request.getProtocol();
	while(protocol.endsWith("\n")) //NOI18N
	    protocol = protocol.substring(0, protocol.length()-2);
	rd.setAttributeValue("protocol", protocol); //NOI18N

	rd.setAttributeValue("ipaddress", request.getRemoteAddr());//NOI18N

	if(debug)  log("               doing query string"); //NOI18N

	String queryString = request.getQueryString();
	if(queryString == null || queryString.trim().equals("")) { //NOI18N
	    queryString = ""; //NOI18N
	}

	if(debug)  log("Query string is: " + queryString); // NOI18N

	// Parse it the way we do with the errors... 
	rd.setAttributeValue("queryString", queryString); //NOI18N

	//NOI18N
	rd.setAttributeValue("scheme", request.getScheme()); //NOI18N

	if(debug)  log("               doing headers"); //NOI18N
	Headers headers = new Headers();
	headers.setParam(recordHeaders(request));
	rd.setHeaders(headers);

	if(debug)  log("               doing request attributes...in"); //NOI18N
	RequestAttributesIn reqattrin = new RequestAttributesIn();
	reqattrin.setParam(recordRequestAttributes(request));
	rd.setRequestAttributesIn(reqattrin);
    }

    /**
     * Creates an instance of ContextData based on the request
     */
    private void recordContextData(ContextData cd, 
				   HttpServletRequest request) 
    {
	ServletContext context = filterConfig.getServletContext();
	
	if(debug) log(" Getting servlet context props"); //NOI18N
	cd.setAttributeValue("absPath", context.getRealPath("/")); //NOI18N
	cd.setAttributeValue("contextName", //NOI18N
			     context.getServletContextName()); //NOI18N

	if(debug)  log(" context attributes"); //NOI18N
	ContextAttributes ctxtattr = new ContextAttributes();
	ctxtattr.setParam(recordContextAttributes(context));
	cd.setContextAttributes(ctxtattr);

	if(debug) log(" Getting context init parameters"); //NOI18N
	Enumeration e = context.getInitParameterNames(); 
	Vector v = new Vector();

	while (e.hasMoreElements()) {
	    String name = (String)e.nextElement();
	    String value = context.getInitParameter(name);
	    Param p = new Param();
	    p.setAttributeValue("name", name); //NOI18N
	    p.setAttributeValue("value", value); //NOI18N
	    v.add(p);
	}

	int size = v.size();
	Param[] params = new Param[size];
	for(int i=0; i< size; ++i) 
	    params[i] = (Param)v.elementAt(i);
	cd.setParam(params);
    }
    


    /**
     * Creates an instance of EngineData based on the request
     */
    private void recordEngineData(EngineData ed, 
				  HttpServletRequest request) 
    {
	ServletContext context = filterConfig.getServletContext();
	ed.setAttributeValue("serverName", request.getServerName()); //NOI18N
	ed.setAttributeValue("serverPort", //NOI18N
			     String.valueOf(request.getServerPort()));
	ed.setAttributeValue("jre", //NOI18N
			     System.getProperty("java.version"));
	ed.setAttributeValue("platform", context.getServerInfo()); //NOI18N
    }
         
    /**
     * Creates an instance of Headers based on the request
     */
    private Param[] recordHeaders(HttpServletRequest request) {

	if(debug) log(" Doing headers");  //NOI18N
	
	Vector v = new Vector(); 
	Vector names = new Vector(); 
	 
	Enumeration e = request.getHeaderNames();
	 
	while (e.hasMoreElements()) {
	    String name = (String)e.nextElement();
	    if(debug) log(" Header name: " + name);  //NOI18N
	    if(names.contains(name)) continue;
	    if(debug) log(" Get enumeration of header values");  //NOI18N
	    Enumeration value = request.getHeaders(name);
	    int counter = 0; 
	    while(value.hasMoreElements()) { 
		if(debug) log(" Adding new parameter");  //NOI18N
		v.add(new Param(name, (String)value.nextElement())); 
		++counter;
	    } 
	    if(counter > 1) names.add(name); 
	}
	int size = v.size();
	Param[] params = new Param[size];
	for(int i=0; i< size; ++i) 
	    params[i] = (Param)v.elementAt(i);

	return params;
    }

    /**
     * Adds parameters to the RequestData
     */
    private void addRequestParameters(RequestData rd, 
				      HttpServletRequest request) {
	
	String method = rd.getAttributeValue("method"); //NOI18N

	// If it is a POST request we check if it was URL encoded 
	// Not sure this matters if we record the parameters after the 
	// request has been processed 

	boolean urlencoded = true;
	if(debug)  log("               doing parameters"); //NOI18N
	if(method.equals("POST")) { //NOI18N

	    Headers headers = rd.getHeaders();
	    String urlencodedS = "application/x-www-form-urlencoded"; //NOI18N
	    String typeS = "Content-type"; //NOI18N
 
	    if(headers.containsHeader(typeS) && 
	       !(headers.getHeader(typeS).equalsIgnoreCase(urlencodedS)))
		urlencoded = false; 
	}
	rd.setAttributeValue("urlencoded", //NOI18N
			     String.valueOf(urlencoded)); 


	if(method.equals("GET")) { //NOI18N
	
	    if(debug)  log("GET"); //NOI18N

	    try {
		Enumeration e = request.getParameterNames();
		while(e.hasMoreElements()) {
		    String name = (String)e.nextElement();	    
		    if(debug) log("Parameter name: " + //NOI18N
				  name); 
		    String[] vals = request.getParameterValues(name);
		    for(int i=0; i<vals.length; ++i) 
			rd.addParam(new Param(name, vals[i]));
		}
	    }
	    catch(Exception ex) {
		// The query string was not parameterized. This is
		// legal. If this happens we simply don't record
		// anything here, since the query string is recorded
		// separately. 
		if(debug) log("Non parameterized query string"); //NOI18N
	    }
	    
 
	    if(debug)  log("GET end"); //NOI18N
	}

	else if (method.equals("POST") && urlencoded) { //NOI18N
	    
 	    if(debug)  log("POST"); //NOI18N
	    Enumeration e = null;
	     
	    try {
		e = request.getParameterNames();
		while(e.hasMoreElements()) {
		    String name = (String)e.nextElement();	    
		    if(debug) log("Parameter name: " +  //NOI18N
				  name);
		    String[] vals = request.getParameterValues(name);
		    for(int i=0; i<vals.length; ++i) 
			rd.addParam(new Param(name, vals[i]));
		}
	    }
	    catch(Exception ex) {
		// PENDING: this could also be because the user choose 
		// to parse the parameters themselves. Need to fix
		// this message.
		rd.setAttributeValue("urlencoded", "bad"); //NOI18N
	    }

 	    if(debug)  log("POST"); //NOI18N
	}
    }

    /**
     * Creates a Param[] from a HttpServletRequest
     */
    private Param[] recordRequestAttributes(HttpServletRequest request) {

	if(debug) log("recordRequestAttributes(): start"); //NOI18N
	
	Vector v = new Vector();
	 
	Enumeration e = request.getAttributeNames();
	 
	while (e.hasMoreElements()) {
	    String name = (String)e.nextElement();
	    if(debug) log(" name: " + name); //NOI18N
	    Object value = request.getAttribute(name);
            String valueRep = null;
            try {
                valueRep = value.toString();
                if (valueRep == null) {
                    valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_null"); //NOI18N
                }
            } catch (Throwable t) {
                // Ensure that the monitor can continue to run even if there is a
                // serious problem in the application code that it is monitoring
                valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_exception"); //NOI18N
            }
	    Param p = new Param();
	    p.setAttributeValue("name", name);  //NOI18N
	    p.setAttributeValue("value", valueRep); //NOI18N
	    v.add(p);
	}
	if(debug) log("Got all request attributes"); //NOI18N

	int size = v.size();

	Param[] params = new Param[size];
	for(int i=0; i< size; ++i) 
	    params[i] = (Param)v.elementAt(i);

	if(debug) log("recordRequestAttributes(): end"); //NOI18N
	return params;
    }


    /**
     * Creates a Param[] of attributes from a Context
     */
    private Param[] recordContextAttributes(ServletContext context) {

	if(debug) log("recordContextAttributes"); //NOI18N
	
	Vector v = new Vector();
	 
	Enumeration e = context.getAttributeNames();
	 
	while (e.hasMoreElements()) {
	    String name = (String)e.nextElement();
	    if(debug) log(" name: " + name);  //NOI18N
	    Object value = context.getAttribute(name);
            String valueRep = null;
            try {
                if(value == null) {
                    valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_attributes"); //NOI18N
                } else if (value.getClass().isArray()) {
                    Object[] valueItems = (Object[])value;
                    StringBuffer sb = new StringBuffer(valueItems.length * 16);
                    if (valueItems.length > 0) sb.append(valueItems[0]);
                    for(int i=1; i < valueItems.length; i++) {
                        sb.append(", "); // NOI18N
                        sb.append(valueItems[i]);
                    }
                    valueRep = sb.toString();
                } else {
                    valueRep = value.toString();
                    if (valueRep == null) {
                        valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_null"); //NOI18N
                    }
                }
            } catch (Throwable t) {
                // Ensure that the monitor can continue to run even if there is a
                // serious problem in the application code that it is monitoring
                valueRep = ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Warning_toString_exception"); //NOI18N
            }
	    Param p = new Param();
	    p.setAttributeValue("name", name);  //NOI18N
	    p.setAttributeValue("value", valueRep);  //NOI18N
	    v.add(p);
	}
	int size = v.size();
	Param[] params = new Param[size];
	for(int i=0; i< size; ++i) 
	    params[i] = (Param)v.elementAt(i);

	return params;
    }


    // PENDING - add own exception 
    private MonitorRequestWrapper getReplayRequest(HttpServletRequest req)
	throws IOException {  

	// Fail if we don't identify the old request
	String status = req.getParameter(REPLAYSTATUS); 
	if (status == null) {
	    String msg = " replay request corrupted"; //NOI18N
	    if(debug) log(msg); 
	    throw new IOException(msg); 
	}


	String id = req.getParameter(REPLAY);
	String portS = req.getParameter(PORT);
	int port = 0; 
	try { 
	    port = Integer.parseInt(portS);
	}
	catch(NumberFormatException nfe) {
	    // We have no port to get the request from, so we return
	    String msg = " Request did not provide a port number"; //NOI18N
	    if(debug) log(msg); 
	    throw new IOException(msg); 
	} 
	
	String ipaddress = req.getRemoteAddr(); 
	RequestData rd = notifyUtil.getRecord(id, status, ipaddress, port);

	if(rd == null) { 
	    String msg = "Failed to get the request";  //NOI18N
	    if(debug) log(msg); 
	    throw new IOException(msg); 
	}

	if(debug) log("Got requestdata as we should");  //NOI18N

	boolean replaceSessionID = false;
	try {
	    String sessionID = req.getParameter(REPLAYSESSION);
	    if(sessionID != null) {
		if(debug) log("User asked for new session " + //NOI18N
			      sessionID);
		replaceSessionID = true;
	    }
	    else if(debug) log("User wants browser's session"); //NOI18N
	}
	catch(NullPointerException npe) {
	    log("NPE when getting " + REPLAYSESSION); //NOI18N
	}


	MonitorRequestWrapper requestWrapper = 
	    new  MonitorRequestWrapper(req);
	if(debug) log("Created wrapper");  //NOI18N
	requestWrapper.populate(rd, replaceSessionID); 
	if(debug) log("Populated wrapper");  //NOI18N
	//requestWrapper.setAttribute(attNameRequest, requestWrapper);
	return requestWrapper; 
    }
    
    
    /**
     * Return the filter configuration object for this filter.
     */
    public FilterConfig getFilterConfig() {
	return (this.filterConfig);
    }


    /**
     * Set the filter configuration object for this filter.
     *
     * @param filterConfig The filter configuration object
     */
    public void setFilterConfig(FilterConfig filterConfig) {

	this.filterConfig = filterConfig;
	if (filterConfig != null)
	    this.attribute = filterConfig.getInitParameter("attribute"); //NOI18N
	else
	    this.attribute = null;
    }

    /**
     * Destroy method for this filter 
     *
     */
    public void destroy() { 
    }


    /**
     * Init method for this filter 
     *
     */
    public void init(FilterConfig filterConfig) { 

	if(debug) System.out.println("init()");//NOI18N
	
	this.filterConfig = filterConfig;

	notifyUtil = new NotifyUtil();

	boolean noIDE = true;
	String ide = filterConfig.getInitParameter(IDE); 
	if(ide != null && !ide.equals("")) { //NOI18N

	    if(debug) log("trying to start the IDE with " + ide);//NOI18N
	    try { 
		notifyUtil.setIDE(ide); 
		collectData = true;
		if(debug) log("Starting server with ide " + ide); //NOI18N
	    } 
	    catch(MalformedURLException mux) { 
		log("IDE init parameter has an invalid value:"); //NOI18N
		log(ide);
		log("starting anyway"); //NOI18N
	    }
	}
	else { 
	    log("IDE init parameter has an invalid value:"); //NOI18N
	    log(ide);
	    log("starting anyway"); //NOI18N
	}

	String ides = filterConfig.getInitParameter(IDES); 
	if(ides != null && !ides.trim().equals("")) { //NOI18N

	    StringTokenizer st = new StringTokenizer(ides, ","); //NOI18N
	    String name; 
	    while(st.hasMoreTokens()) { 

		name = (String)(st.nextToken());
		try { 
		    notifyUtil.setIDE(name.trim()); 
		    collectData = true;
		    if(debug) log("Starting server with name " + name); //NOI18N
		} 
		catch(MalformedURLException mux) { 
		    log("additional IDE includes an invalid server declaration:"); //NOI18N
		    log(name);
		    log("starting anyway"); //NOI18N
		}
	    }
	}
	if(debug) 
	    log("We're collecting data " + //NOI18N
		String.valueOf(collectData)); 
    }
    
    /**
     * Return a String representation of this object.
     */
    public String toString() {

	if (filterConfig == null) return ("MonitorFilter()"); //NOI18N
	StringBuffer sb = new StringBuffer("MonitorFilter("); //NOI18N
	sb.append(filterConfig);
	sb.append(")"); //NOI18N
	return (sb.toString());

    }

    /**
     * Get the value of collectData.
     * @return Value of collectData.
     */
    public static boolean getCollectData() {
	return collectData;
    }
    
    /**
     * Set the value of collectData.
     * @param v  Value to assign to collectData.
     */
    public static void setCollectData(boolean  v) {
	collectData = v;
    }

    private void rethrow(Throwable t) throws IOException,
					     ServletException { 

	if(debug) log(" rethrow(" + t.getMessage() + ")"); //NOI18N
	if(t instanceof StackOverflowError) { 
	    String message =
		ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_overflow"); 
	    filterConfig.getServletContext().log(message); 
	    System.out.println(message); 
	    throw new ServletException(message, t);
	}
	if(t instanceof RuntimeException) throw (RuntimeException)t;
	if(t instanceof ServletException) throw (ServletException)t;
	if(t instanceof IOException) throw (IOException)t;
	else { 
	    String message =
		ResourceBundle.getBundle("org.netbeans.modules.web.monitor.server.Bundle").getString("MON_Rethrow"); 
	    throw new ServletException(message, t);
	}
    }

    public void log(String msg) {
	//filterConfig.getServletContext().log("MonitorFilter::" + msg); //NOI18N
	System.out.println("MonitorFilter::" + msg);//NOI18N
    }

    public void log(Throwable t) {
	log(getStackTrace(t)); 
    }
}


