KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > dispatch > FilterMapping


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.dispatch;
31
32 import com.caucho.config.ConfigException;
33 import com.caucho.server.util.CauchoSystem;
34 import com.caucho.util.CharBuffer;
35 import com.caucho.util.L10N;
36
37 import javax.annotation.PostConstruct;
38 import javax.servlet.ServletException JavaDoc;
39 import java.util.ArrayList JavaDoc;
40 import java.util.HashSet JavaDoc;
41 import java.util.regex.Pattern JavaDoc;
42
43 /**
44  * Configuration for a filter.
45  */

46 public class FilterMapping extends FilterConfigImpl {
47   static L10N L = new L10N(FilterMapping.class);
48
49   private String JavaDoc _urlPattern;
50   private final ArrayList JavaDoc<String JavaDoc> _servletNames = new ArrayList JavaDoc<String JavaDoc>();
51   
52   // The match expressions
53
private final ArrayList JavaDoc<Match> _matchList = new ArrayList JavaDoc<Match>();
54
55   private HashSet JavaDoc<String JavaDoc> _dispatcher;
56   
57   /**
58    * Creates a new filter mapping object.
59    */

60   public FilterMapping()
61   {
62   }
63
64   /**
65    * Sets the url pattern
66    */

67   public URLPattern createUrlPattern()
68     throws ServletException JavaDoc
69   {
70     return new URLPattern();
71   }
72
73   /**
74    * Gets the url pattern
75    */

76   public String JavaDoc getURLPattern()
77   {
78     return _urlPattern;
79   }
80
81   /**
82    * Sets the url regexp
83    */

84   public void setURLRegexp(String JavaDoc pattern)
85     throws ServletException JavaDoc
86   {
87     Pattern JavaDoc regexp;
88     
89     if (CauchoSystem.isCaseInsensitive())
90       regexp = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
91     else
92       regexp = Pattern.compile(pattern, 0);
93
94     _matchList.add(Match.createInclude(regexp));
95   }
96
97   /**
98    * Sets the servlet name
99    */

100   public void addServletName(String JavaDoc servletName)
101   {
102     _servletNames.add(servletName);
103   }
104
105   /**
106    * Adds a dispatcher.
107    */

108   public void addDispatcher(String JavaDoc dispatcher)
109     throws ConfigException
110   {
111     if (_dispatcher == null)
112       _dispatcher = new HashSet JavaDoc<String JavaDoc>();
113
114     if (dispatcher == null
115         || (! dispatcher.equals("REQUEST")
116             && ! dispatcher.equals("FORWARD")
117             && ! dispatcher.equals("INCLUDE")
118             && ! dispatcher.equals("ERROR"))) {
119       throw new ConfigException(L.l("`{0}' is an unknown value for <dispatcher> `REQUEST', `FORWARD', `INCLUDE', and `ERROR' are the valid values.",
120                                     dispatcher));
121     }
122
123     _dispatcher.add(dispatcher);
124   }
125
126   /**
127    * True if the dispatcher is for REQUEST.
128    */

129   public boolean isRequest()
130   {
131     return _dispatcher == null || _dispatcher.contains("REQUEST");
132   }
133
134   /**
135    * True if the dispatcher is for INCLUDE.
136    */

137   public boolean isInclude()
138   {
139     return _dispatcher != null && _dispatcher.contains("INCLUDE");
140   }
141
142   /**
143    * True if the dispatcher is for FORWARD.
144    */

145   public boolean isForward()
146   {
147     return _dispatcher != null && _dispatcher.contains("FORWARD");
148   }
149
150   /**
151    * True if the dispatcher is for ERROR.
152    */

153   public boolean isError()
154   {
155     return _dispatcher != null && _dispatcher.contains("ERROR");
156   }
157
158   /**
159    * Returns true if the filter map matches the invocation URL.
160    *
161    * @param invocation the request's invocation
162    * @param servletName the servlet name to match
163    */

164   boolean isMatch(String JavaDoc servletName)
165   {
166     for (int i = 0; i < _servletNames.size(); i++) {
167       String JavaDoc matchName = _servletNames.get(i);
168
169       if (servletName.equals(matchName) || "*".equals(matchName))
170     return true;
171     }
172
173     return false;
174   }
175
176   /**
177    * Returns true if the filter map matches the invocation URL.
178    *
179    * @param invocation the request's invocation
180    */

181   boolean isMatch(ServletInvocation invocation)
182   {
183     return isMatch(invocation.getServletPath(), invocation.getPathInfo());
184   }
185
186   /**
187    * Returns true if the filter map matches the servlet path and path info.
188    * */

189   public boolean isMatch(String JavaDoc servletPath, String JavaDoc pathInfo)
190   {
191     String JavaDoc uri;
192
193     if (pathInfo == null)
194       uri = servletPath;
195     else if (servletPath == null)
196       uri = pathInfo;
197     else
198       uri = servletPath + pathInfo;
199
200     int size = _matchList.size();
201     
202     for (int i = 0; i < size; i++) {
203       Match match = _matchList.get(i);
204
205       int value = match.match(uri);
206
207       switch (value) {
208       case Match.INCLUDE:
209     return true;
210       case Match.EXCLUDE:
211     return false;
212       }
213     }
214
215     return false;
216   }
217
218   /**
219    * Converts a url-pattern to a regular expression
220    *
221    * @param pattern the url-pattern to convert
222    * @param flags the regexp flags, e.g. "i" for case insensitive
223    *
224    * @return the equivalent regular expression
225    */

226   private Pattern JavaDoc urlPatternToRegexp(String JavaDoc pattern, int flags)
227     throws ServletException JavaDoc
228   {
229     if (pattern.length() == 0 ||
230         pattern.length() == 1 && pattern.charAt(0) == '/') {
231       try {
232         return Pattern.compile("^/$", flags);
233       } catch (Exception JavaDoc e) {
234         throw new ServletException JavaDoc(e);
235       }
236     }
237
238     int length = pattern.length();
239     boolean isExact = true;
240       
241     if (pattern.charAt(0) != '/' && pattern.charAt(0) != '*') {
242       pattern = "/" + pattern;
243       length++;
244     }
245
246     int prefixLength = -1;
247     boolean isShort = false;
248     CharBuffer cb = new CharBuffer();
249     cb.append("^");
250     for (int i = 0; i < length; i++) {
251       char ch = pattern.charAt(i);
252       
253       if (ch == '*' && i + 1 == length && i > 0) {
254         isExact = false;
255
256         if (pattern.charAt(i - 1) == '/') {
257           cb.setLength(cb.length() - 1);
258
259           if (prefixLength < 0)
260             prefixLength = i - 1;
261           
262         }
263         else if (prefixLength < 0)
264           prefixLength = i;
265         
266         if (prefixLength == 0)
267           prefixLength = 1;
268       }
269       else if (ch == '*') {
270         isExact = false;
271         cb.append(".*");
272         if (prefixLength < 0)
273           prefixLength = i;
274         
275         if (i == 0)
276           isShort = true;
277       }
278       else if (ch == '.' || ch == '[' || ch == '^' || ch == '$' ||
279                ch == '{' || ch == '}' || ch == '|' ||
280                ch == '(' || ch == ')' || ch == '?') {
281         cb.append('\\');
282         cb.append(ch);
283       }
284       else
285         cb.append(ch);
286     }
287
288     if (isExact)
289       cb.append('$');
290     else
291       cb.append("(?=/)|" + cb.toString() + "$");
292
293     try {
294       return Pattern.compile(cb.close(), flags);
295     } catch (Exception JavaDoc e) {
296       throw new ServletException JavaDoc(e);
297     }
298   }
299
300   /**
301    * Returns a printable representation of the filter config object.
302    */

303   public String JavaDoc toString()
304   {
305     return "FilterMapping[pattern=" + _urlPattern + ",name=" + getFilterName() + "]";
306   }
307
308   public class URLPattern {
309     boolean _hasInclude = false;
310
311     /**
312      * Sets the singleton url-pattern.
313      */

314     public void addText(String JavaDoc pattern)
315       throws ServletException JavaDoc
316     {
317       pattern = pattern.trim();
318       
319       _urlPattern = pattern;
320
321       Pattern JavaDoc regexp;
322       
323       if (CauchoSystem.isCaseInsensitive())
324     regexp = urlPatternToRegexp(pattern, Pattern.CASE_INSENSITIVE);
325       else
326     regexp = urlPatternToRegexp(pattern, 0);
327
328       _hasInclude = true;
329       
330       _matchList.add(Match.createInclude(regexp));
331     }
332
333     /**
334      * Adds an include pattern.
335      */

336     public void addIncludePattern(String JavaDoc pattern)
337       throws ServletException JavaDoc
338     {
339       pattern = pattern.trim();
340
341       Pattern JavaDoc regexp;
342       
343       if (CauchoSystem.isCaseInsensitive())
344     regexp = urlPatternToRegexp(pattern, Pattern.CASE_INSENSITIVE);
345       else
346     regexp = urlPatternToRegexp(pattern, 0);
347
348       _hasInclude = true;
349       
350       _matchList.add(Match.createInclude(regexp));
351     }
352
353     /**
354      * Adds an exclude pattern.
355      */

356     public void addExcludePattern(String JavaDoc pattern)
357       throws ServletException JavaDoc
358     {
359       pattern = pattern.trim();
360       
361       Pattern JavaDoc regexp;
362       
363       if (CauchoSystem.isCaseInsensitive())
364     regexp = urlPatternToRegexp(pattern, Pattern.CASE_INSENSITIVE);
365       else
366     regexp = urlPatternToRegexp(pattern, 0);
367
368       _matchList.add(Match.createExclude(regexp));
369     }
370
371     /**
372      * Adds an include regexp.
373      */

374     public void addIncludeRegexp(String JavaDoc pattern)
375     {
376       pattern = pattern.trim();
377
378       Pattern JavaDoc regexp;
379       
380       if (CauchoSystem.isCaseInsensitive())
381     regexp = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
382       else
383     regexp = Pattern.compile(pattern, 0);
384
385       _hasInclude = true;
386       
387       _matchList.add(Match.createInclude(regexp));
388     }
389
390     /**
391      * Adds an exclude regexp.
392      */

393     public void addExcludeRegexp(String JavaDoc pattern)
394     {
395       pattern = pattern.trim();
396
397       Pattern JavaDoc regexp;
398       
399       if (CauchoSystem.isCaseInsensitive())
400     regexp = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
401       else
402     regexp = Pattern.compile(pattern, 0);
403
404       _matchList.add(Match.createExclude(regexp));
405     }
406
407     /**
408      * Initialize, adding the all-match for exclude patterns.
409      */

410     @PostConstruct
411     public void init()
412       throws Exception JavaDoc
413     {
414       if (_matchList.size() > 0 && ! _hasInclude) {
415     Pattern JavaDoc regexp = Pattern.compile("");
416     _matchList.add(Match.createInclude(regexp));
417       }
418     }
419   }
420     
421   static class Match {
422     static final int INCLUDE = 1;
423     static final int EXCLUDE = -1;
424     static final int NO_MATCH = 0;
425     
426     private final Pattern JavaDoc _regexp;
427     private final int _value;
428
429     private Match(Pattern JavaDoc regexp, int value)
430     {
431       _regexp = regexp;
432       _value = value;
433     }
434
435     /**
436      * Creates an include pattern.
437      */

438     static Match createInclude(Pattern JavaDoc regexp)
439     {
440       return new Match(regexp, INCLUDE);
441     }
442
443     /**
444      * Creates an exclude pattern.
445      */

446     static Match createExclude(Pattern JavaDoc regexp)
447     {
448       return new Match(regexp, EXCLUDE);
449     }
450
451     /**
452      * Returns the match value.
453      */

454     int match(String JavaDoc uri)
455     {
456       if (_regexp.matcher(uri).find())
457     return _value;
458       else
459     return NO_MATCH;
460     }
461   }
462 }
463
Popular Tags