View Javadoc

1   /*
2    ~ Copyright 2006-2007 Nicolas De Loof.
3    ~
4    ~ Licensed under the Apache License, Version 2.0 (the "License");
5    ~ you may not use this file except in compliance with the License.
6    ~ You may obtain a copy of the License at
7    ~
8    ~      http://www.apache.org/licenses/LICENSE-2.0
9    ~
10   ~ Unless required by applicable law or agreed to in writing, software
11   ~ distributed under the License is distributed on an "AS IS" BASIS,
12   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   ~ See the License for the specific language governing permissions and
14   ~ limitations under the License.
15   */
16  package org.jmonit.web;
17  
18  import java.io.IOException;
19  import java.util.HashMap;
20  import java.util.Map;
21  import java.util.StringTokenizer;
22  
23  import javax.servlet.Filter;
24  import javax.servlet.FilterChain;
25  import javax.servlet.FilterConfig;
26  import javax.servlet.ServletException;
27  import javax.servlet.ServletRequest;
28  import javax.servlet.ServletResponse;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.jmonit.Monitor;
33  import org.jmonit.Monitoring;
34  import org.jmonit.Repository;
35  import org.jmonit.Stopwatch;
36  import org.jmonit.events.HttpRequestServed;
37  
38  /**
39   * A servlet Filter to be configured in your WEB-INF/web.xml to intercept all
40   * incoming request.
41   * 
42   * <pre>
43   *         &lt;filter&gt;
44   *         &lt;filter-name&gt;jMonit&lt;/filter-name&gt;
45   *         &lt;filter-class&gt;org.jmonit.web.JMonitFilter&lt;/filter-class&gt;
46   *         &lt;/filter&gt;
47   *         &lt;filter-mapping&gt;
48   *         &lt;filter-name&gt;jMonit&lt;/filter-name&gt;
49   *         &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
50   *         &lt;/filter-mapping&gt;
51   * </pre>
52   * 
53   * <p>
54   * A monitor will be created for each application URI. By default, the requested
55   * resource extension is used to group monitors in sub-categories.
56   * 
57   * @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
58   */
59  public class JMonitFilter
60      implements Filter
61  {
62      /**
63       *
64       */
65      private static final String MONITOR_HTTP = "monitor-HTTP";
66  
67      /** Configuration param for domain mappings */
68      private static final String MAPPINGS = "mappings";
69  
70      /** Configuration param default tag (when no mapping matches) */
71      private static final String DEFAULT_TAG = "default-tag";
72  
73      /** Configuration param tag for web resources */
74      private static final String WEB_RESOURCES_TAG = "web-ressources-tag";
75  
76      /** tag mappings for web resources */
77      private Map<String, String> tags = new HashMap<String, String>();
78  
79      /** Repository of monitors */
80      private Repository repository;
81  
82      /** Default cqtegory for request without matching mapping */
83      private String defaultTag = "other";
84  
85      /** Tag for web resources */
86      private String tag = "web";
87  
88      /** enable HTTP monitoring */
89      private boolean monitorHttp;
90  
91      /**
92       * {@inheritDoc}
93       * 
94       * @see javax.servlet.Filter#destroy()
95       */
96      public void destroy()
97      {
98      }
99  
100     /**
101      * Http specific doFilter implementation
102      * 
103      * @param request Http request
104      * @param response Http response
105      * @param chain request chain
106      * @throws IOException IO exception occurs
107      * @throws ServletException servlet Exception occurs
108      */
109     public void doFilter( HttpServletRequest request, HttpServletResponse response,
110                           FilterChain chain )
111         throws IOException, ServletException
112     {
113         String uri = getRequestedUri( request );
114 
115         String name = buildMonitorNameFromUri( uri );
116         Monitor monitor = repository.getMonitor( name ).tag( tag );
117         monitor.tag( getTagForUri( uri ) );
118 
119         Stopwatch execution = Stopwatch.start( monitor );
120         try
121         {
122             if ( monitorHttp )
123             {
124                 response = new MonitoredHttpServletResponse( response );
125             }
126             chain.doFilter( request, response );
127         }
128         finally
129         {
130             execution.stop();
131             if ( monitorHttp )
132             {
133                 int sc = ( (MonitoredHttpServletResponse) response ).getStatus();
134                 monitor.fireMonitoringEvent( new HttpRequestServed( request, execution
135                     .getElapsedTime(), sc, monitor ) );
136             }
137         }
138     }
139 
140     protected String getRequestedUri( HttpServletRequest request )
141     {
142         String uri = request.getRequestURI();
143         String context = request.getContextPath();
144         uri = uri.substring( context.length() );
145         return uri;
146     }
147 
148     /**
149      * Delegates to Http based doFilter. {@inheritDoc}
150      * 
151      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
152      * javax.servlet.ServletResponse, javax.servlet.FilterChain)
153      */
154     public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
155         throws IOException, ServletException
156     {
157         if ( request instanceof HttpServletRequest )
158         {
159             HttpServletRequest httpRequest = (HttpServletRequest) request;
160             HttpServletResponse httpResponse = (HttpServletResponse) response;
161             doFilter( httpRequest, httpResponse, chain );
162         }
163         else
164         {
165             // Not an HTTP request...
166             chain.doFilter( request, response );
167         }
168 
169     }
170 
171     /**
172      * {@inheritDoc}
173      * 
174      * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
175      */
176     public void init( FilterConfig filterConfig )
177         throws ServletException
178     {
179         this.monitorHttp = "true".equals( filterConfig.getInitParameter( MONITOR_HTTP ) );
180         initRepository( filterConfig );
181         initDefaultTags( filterConfig );
182         initMapping( filterConfig );
183     }
184 
185     /**
186      * @param tags The tags to set
187      */
188     public void setTags( Map<String, String> tags )
189     {
190         this.tags = tags;
191     }
192 
193     /**
194      * @param repository the repository to set
195      */
196     public void setRepository( Repository repository )
197     {
198         this.repository = repository;
199     }
200 
201     /**
202      * Build the monitor name from request URI.
203      * <p>
204      * Override this method in a custom filter to define application specific
205      * monitors based on URIs.
206      * 
207      * @param uri requested URI
208      * @return monitor name
209      */
210     protected String buildMonitorNameFromUri( String uri )
211     {
212         return uri;
213     }
214 
215     /**
216      * Build the monitor name from request URI.
217      * <p>
218      * Override this method in a custom filter to define application specific
219      * monitors based on URIs.
220      * 
221      * @param uri requested URI
222      * @return domain Domain for requested URI
223      */
224     protected String getTagForUri( String uri )
225     {
226         String uriTags = defaultTag;
227         int i = uri.lastIndexOf( "." );
228         if ( i > 0 )
229         {
230             String extension = uri.substring( i );
231             if ( tags.containsKey( extension ) )
232             {
233                 uriTags = tags.get( extension );
234             }
235         }
236         return uriTags;
237     }
238 
239     /**
240      * @param filterConfig configuration
241      */
242     protected void initDefaultTags( FilterConfig filterConfig )
243     {
244         String tag = filterConfig.getInitParameter( DEFAULT_TAG );
245         if ( tag != null )
246         {
247             this.defaultTag = tag;
248         }
249 
250         tag = filterConfig.getInitParameter( WEB_RESOURCES_TAG );
251         if ( tag != null )
252         {
253             this.tag = tag;
254         }
255     }
256 
257     /**
258      * @param filterConfig configuration
259      */
260     protected void initMapping( FilterConfig filterConfig )
261     {
262         String maps = filterConfig.getInitParameter( MAPPINGS );
263         if ( maps == null )
264         {
265             // Default mappings
266             tags.put( ".do", "struts" );
267             tags.put( ".action", "struts2" );
268             tags.put( ".jsf", "jsf" );
269             tags.put( ".js", "static" );
270             tags.put( ".html", "static" );
271             tags.put( ".css", "static" );
272             tags.put( ".gif", "static" );
273             tags.put( ".png", "static" );
274             tags.put( ".jpg", "static" );
275         }
276         else
277         {
278             StringTokenizer tokenizer = new StringTokenizer( maps );
279             while ( tokenizer.hasMoreTokens() )
280             {
281                 String token = tokenizer.nextToken();
282                 int i = token.indexOf( '=' );
283                 if ( i < 0 )
284                 {
285                     continue;
286                 }
287                 String category = token.substring( 0, i ).trim();
288                 tags.put( token.substring( i + 1 ).trim(), category );
289             }
290         }
291     }
292 
293     /**
294      * @param filterConfig configuration
295      */
296     protected void initRepository( FilterConfig filterConfig )
297     {
298         if ( repository == null )
299         {
300             repository = Monitoring.getRepository();
301         }
302     }
303 
304 }