alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

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 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
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.