| /* |
| * 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)); |
| } |
| } |
| |
| |