Home | History | Annotate | Download | only in servlet
      1 /**
      2  * Copyright (C) 2008 Google Inc.
      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 com.google.inject.servlet;
     17 
     18 import java.util.regex.Matcher;
     19 import java.util.regex.Pattern;
     20 
     21 /**
     22  * An enumeration of the available URI-pattern matching styles
     23  *
     24  * @since 3.0
     25  */
     26 public enum UriPatternType {
     27   SERVLET, REGEX;
     28 
     29   static UriPatternMatcher get(UriPatternType type, String pattern) {
     30     switch (type) {
     31       case SERVLET:
     32         return new ServletStyleUriPatternMatcher(pattern);
     33       case REGEX:
     34         return new RegexUriPatternMatcher(pattern);
     35       default:
     36         return null;
     37     }
     38   }
     39 
     40   private static String getUri(String uri) {
     41     // Strip out the query, if it existed in the URI.  See issue 379.
     42     int queryIdx = uri.indexOf('?');
     43     if (queryIdx != -1) {
     44       uri = uri.substring(0, queryIdx);
     45     }
     46     return uri;
     47   }
     48 
     49   /**
     50    * Matches URIs using the pattern grammar of the Servlet API and web.xml.
     51    *
     52    * @author dhanji (at) gmail.com (Dhanji R. Prasanna)
     53    */
     54   private static class ServletStyleUriPatternMatcher implements UriPatternMatcher {
     55     private final String pattern;
     56     private final Kind patternKind;
     57 
     58     private static enum Kind { PREFIX, SUFFIX, LITERAL, }
     59 
     60     public ServletStyleUriPatternMatcher(String pattern) {
     61       if (pattern.startsWith("*")) {
     62         this.pattern = pattern.substring(1);
     63         this.patternKind = Kind.PREFIX;
     64       } else if (pattern.endsWith("*")) {
     65         this.pattern = pattern.substring(0, pattern.length() - 1);
     66         this.patternKind = Kind.SUFFIX;
     67       } else {
     68         this.pattern = pattern;
     69         this.patternKind = Kind.LITERAL;
     70       }
     71     }
     72 
     73     public boolean matches(String uri) {
     74       if (null == uri) {
     75         return false;
     76       }
     77 
     78       uri = getUri(uri);
     79       if (patternKind == Kind.PREFIX) {
     80         return uri.endsWith(pattern);
     81       } else if (patternKind == Kind.SUFFIX) {
     82         return uri.startsWith(pattern);
     83       }
     84 
     85       //else treat as a literal
     86       return pattern.equals(uri);
     87     }
     88 
     89     public String extractPath(String path) {
     90       if (patternKind == Kind.PREFIX) {
     91         return null;
     92       } else if (patternKind == Kind.SUFFIX) {
     93         String extract = pattern;
     94 
     95         //trim the trailing '/'
     96         if (extract.endsWith("/")) {
     97           extract = extract.substring(0, extract.length() - 1);
     98         }
     99 
    100         return extract;
    101       }
    102 
    103       //else treat as literal
    104       return path;
    105     }
    106 
    107     public UriPatternType getPatternType() {
    108       return UriPatternType.SERVLET;
    109     }
    110   }
    111 
    112   /**
    113    * Matches URIs using a regular expression.
    114    *
    115    * @author dhanji (at) gmail.com (Dhanji R. Prasanna)
    116    */
    117   private static class RegexUriPatternMatcher implements UriPatternMatcher {
    118     private final Pattern pattern;
    119 
    120     public RegexUriPatternMatcher(String pattern) {
    121       this.pattern = Pattern.compile(pattern);
    122     }
    123 
    124     public boolean matches(String uri) {
    125       return null != uri && this.pattern.matcher(getUri(uri)).matches();
    126     }
    127 
    128     public String extractPath(String path) {
    129       Matcher matcher = pattern.matcher(path);
    130       if (matcher.matches() && matcher.groupCount() >= 1) {
    131 
    132         // Try to capture the everything before the regex begins to match
    133         // the path. This is a rough approximation to try and get parity
    134         // with the servlet style mapping where the path is a capture of
    135         // the URI before the wildcard.
    136         int end = matcher.start(1);
    137         if (end < path.length()) {
    138           return path.substring(0, end);
    139         }
    140       }
    141       return null;
    142     }
    143 
    144     public UriPatternType getPatternType() {
    145       return UriPatternType.REGEX;
    146     }
    147   }
    148 }
    149