001 /* 002 * Copyright 2008-2009 the original author or authors. 003 * The contents of this file are subject to the Mozilla Public License 004 * Version 1.1 (the "License"); you may not use this file except in 005 * compliance with the License. You may obtain a copy of the License at 006 * http://www.mozilla.org/MPL/ 007 * 008 * Software distributed under the License is distributed on an "AS IS" 009 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 010 * License for the specific language governing rights and limitations 011 * under the License. 012 */ 013 014 package com.mtgi.analytics.servlet; 015 016 import java.util.Enumeration; 017 import java.util.regex.Pattern; 018 019 import javax.servlet.ServletRequest; 020 import javax.servlet.http.HttpServletRequest; 021 022 import org.springframework.util.StringUtils; 023 024 import com.mtgi.analytics.BehaviorEvent; 025 import com.mtgi.analytics.BehaviorTrackingManager; 026 import com.mtgi.analytics.EventDataElement; 027 028 /** 029 * <p>Facilitates behavior tracking for servlet requests via calls to 030 * {@link #start(ServletRequest)} and {@link #stop(BehaviorEvent)}. The relative 031 * verbosity of event logging is configured in the {@link #ServletRequestBehaviorTrackingAdapter(String, BehaviorTrackingManager, String[]) constructor}.</p> 032 * 033 * <p>This class abstracts the details of tracking servlet requests, so that 034 * it can be reused by delegation in both listeners and filters.</p> 035 */ 036 public class ServletRequestBehaviorTrackingAdapter { 037 038 private String eventType; 039 private BehaviorTrackingManager manager; 040 private String[] parameters; 041 private Pattern[] uriPatterns; 042 043 public ServletRequestBehaviorTrackingAdapter(String eventType, BehaviorTrackingManager manager, String[] parameters, Pattern[] uriPatterns) { 044 this.eventType = StringUtils.hasText(eventType) ? eventType: "http-request"; 045 this.manager = manager; 046 this.parameters = parameters; 047 this.uriPatterns = uriPatterns; 048 } 049 050 public BehaviorEvent start(ServletRequest request) { 051 052 HttpServletRequest req = (HttpServletRequest)request; 053 if (!match(req)) 054 return null; 055 056 //use the request path as an event name, excluding proto, host, and query string. 057 String eventName = req.getRequestURI(); 058 BehaviorEvent event = manager.createEvent(eventType, eventName); 059 060 //log relevant request data and parameters to the event. 061 EventDataElement data = event.addData(); 062 data.add("uri", eventName); 063 data.add("protocol", req.getProtocol()); 064 data.add("method", req.getMethod()); 065 data.add("remote-address", req.getRemoteAddr()); 066 data.add("remote-host", req.getRemoteHost()); 067 068 EventDataElement parameters = data.addElement("parameters"); 069 if (this.parameters != null) { 070 //include only configured parameters 071 for (String name : this.parameters) { 072 String[] values = request.getParameterValues(name); 073 if (values != null) 074 addParameter(parameters, name, values); 075 } 076 } else { 077 //include all parameters 078 for (Enumeration<?> params = request.getParameterNames(); params.hasMoreElements(); ) { 079 String name = (String)params.nextElement(); 080 String[] values = request.getParameterValues(name); 081 addParameter(parameters, name, values); 082 } 083 } 084 085 manager.start(event); 086 return event; 087 } 088 089 public void stop(BehaviorEvent event) { 090 if (event != null) //event may be null if match() returned false at the start of the request. 091 manager.stop(event); 092 } 093 094 protected boolean match(HttpServletRequest request) { 095 if (uriPatterns == null) 096 return true; 097 for (Pattern p : uriPatterns) 098 if (p.matcher(request.getRequestURI()).matches()) 099 return true; 100 return false; 101 } 102 103 private static final void addParameter(EventDataElement parameters, String name, String[] values) { 104 EventDataElement param = parameters.addElement("param"); 105 param.add("name", name); 106 for (String v : values) 107 param.addElement("value").setText(v); 108 } 109 110 }