View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.http.pathmap;
20  
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  
24  public class RegexPathSpec extends PathSpec
25  {
26      protected Pattern pattern;
27  
28      protected RegexPathSpec()
29      {
30          super();
31      }
32  
33      public RegexPathSpec(String regex)
34      {
35          super.pathSpec = regex;
36          boolean inGrouping = false;
37          this.pathDepth = 0;
38          this.specLength = pathSpec.length();
39          // build up a simple signature we can use to identify the grouping
40          StringBuilder signature = new StringBuilder();
41          for (char c : pathSpec.toCharArray())
42          {
43              switch (c)
44              {
45                  case '[':
46                      inGrouping = true;
47                      break;
48                  case ']':
49                      inGrouping = false;
50                      signature.append('g'); // glob
51                      break;
52                  case '*':
53                      signature.append('g'); // glob
54                      break;
55                  case '/':
56                      if (!inGrouping)
57                      {
58                          this.pathDepth++;
59                      }
60                      break;
61                  default:
62                      if (!inGrouping)
63                      {
64                          if (Character.isLetterOrDigit(c))
65                          {
66                              signature.append('l'); // literal (exact)
67                          }
68                      }
69                      break;
70              }
71          }
72          this.pattern = Pattern.compile(pathSpec);
73  
74          // Figure out the grouping based on the signature
75          String sig = signature.toString();
76  
77          if (Pattern.matches("^l*$",sig))
78          {
79              this.group = PathSpecGroup.EXACT;
80          }
81          else if (Pattern.matches("^l*g+",sig))
82          {
83              this.group = PathSpecGroup.PREFIX_GLOB;
84          }
85          else if (Pattern.matches("^g+l+$",sig))
86          {
87              this.group = PathSpecGroup.SUFFIX_GLOB;
88          }
89          else
90          {
91              this.group = PathSpecGroup.MIDDLE_GLOB;
92          }
93      }
94  
95      public Matcher getMatcher(String path)
96      {
97          return this.pattern.matcher(path);
98      }
99  
100     @Override
101     public String getPathInfo(String path)
102     {
103         // Path Info only valid for PREFIX_GLOB types
104         if (group == PathSpecGroup.PREFIX_GLOB)
105         {
106             Matcher matcher = getMatcher(path);
107             if (matcher.matches())
108             {
109                 if (matcher.groupCount() >= 1)
110                 {
111                     String pathInfo = matcher.group(1);
112                     if ("".equals(pathInfo))
113                     {
114                         return "/";
115                     }
116                     else
117                     {
118                         return pathInfo;
119                     }
120                 }
121             }
122         }
123         return null;
124     }
125 
126     @Override
127     public String getPathMatch(String path)
128     {
129         Matcher matcher = getMatcher(path);
130         if (matcher.matches())
131         {
132             if (matcher.groupCount() >= 1)
133             {
134                 int idx = matcher.start(1);
135                 if (idx > 0)
136                 {
137                     if (path.charAt(idx - 1) == '/')
138                     {
139                         idx--;
140                     }
141                     return path.substring(0,idx);
142                 }
143             }
144             return path;
145         }
146         return null;
147     }
148 
149     public Pattern getPattern()
150     {
151         return this.pattern;
152     }
153 
154     @Override
155     public String getRelativePath(String base, String path)
156     {
157         // TODO Auto-generated method stub
158         return null;
159     }
160 
161     @Override
162     public boolean matches(final String path)
163     {
164         int idx = path.indexOf('?');
165         if (idx >= 0)
166         {
167             // match only non-query part
168             return getMatcher(path.substring(0,idx)).matches();
169         }
170         else
171         {
172             // match entire path
173             return getMatcher(path).matches();
174         }
175     }
176 }