1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http.pathmap;
20
21 import org.eclipse.jetty.util.URIUtil;
22
23 public class ServletPathSpec extends PathSpec
24 {
25 public ServletPathSpec(String servletPathSpec)
26 {
27 super();
28 assertValidServletPathSpec(servletPathSpec);
29
30
31 if ((servletPathSpec == null) || (servletPathSpec.length() == 0))
32 {
33 super.pathSpec = "";
34 super.pathDepth = -1;
35 this.specLength = 1;
36 this.group = PathSpecGroup.ROOT;
37 return;
38 }
39
40
41 if("/".equals(servletPathSpec))
42 {
43 super.pathSpec = "/";
44 super.pathDepth = -1;
45 this.specLength = 1;
46 this.group = PathSpecGroup.DEFAULT;
47 return;
48 }
49
50 this.specLength = servletPathSpec.length();
51 super.pathDepth = 0;
52 char lastChar = servletPathSpec.charAt(specLength - 1);
53
54 if ((servletPathSpec.charAt(0) == '/') && (specLength > 1) && (lastChar == '*'))
55 {
56 this.group = PathSpecGroup.PREFIX_GLOB;
57 }
58
59 else if (servletPathSpec.charAt(0) == '*')
60 {
61 this.group = PathSpecGroup.SUFFIX_GLOB;
62 }
63 else
64 {
65 this.group = PathSpecGroup.EXACT;
66 }
67
68 for (int i = 0; i < specLength; i++)
69 {
70 int cp = servletPathSpec.codePointAt(i);
71 if (cp < 128)
72 {
73 char c = (char)cp;
74 switch (c)
75 {
76 case '/':
77 super.pathDepth++;
78 break;
79 }
80 }
81 }
82
83 super.pathSpec = servletPathSpec;
84 }
85
86 private void assertValidServletPathSpec(String servletPathSpec)
87 {
88 if ((servletPathSpec == null) || servletPathSpec.equals(""))
89 {
90 return;
91 }
92
93 int len = servletPathSpec.length();
94
95 if (servletPathSpec.charAt(0) == '/')
96 {
97
98 if (len == 1)
99 {
100 return;
101 }
102 int idx = servletPathSpec.indexOf('*');
103 if (idx < 0)
104 {
105 return;
106 }
107
108 if (idx != (len - 1))
109 {
110 throw new IllegalArgumentException("Servlet Spec 12.2 violation: glob '*' can only exist at end of prefix based matches: bad spec \""+ servletPathSpec +"\"");
111 }
112 }
113 else if (servletPathSpec.startsWith("*."))
114 {
115
116 int idx = servletPathSpec.indexOf('/');
117
118 if (idx >= 0)
119 {
120 throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have path separators: bad spec \""+ servletPathSpec +"\"");
121 }
122
123 idx = servletPathSpec.indexOf('*',2);
124
125 if (idx >= 1)
126 {
127 throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have multiple glob '*': bad spec \""+ servletPathSpec +"\"");
128 }
129 }
130 else
131 {
132 throw new IllegalArgumentException("Servlet Spec 12.2 violation: path spec must start with \"/\" or \"*.\": bad spec \""+ servletPathSpec +"\"");
133 }
134 }
135
136 @Override
137 public String getPathInfo(String path)
138 {
139
140 if (group == PathSpecGroup.PREFIX_GLOB)
141 {
142 if (path.length() == (specLength - 2))
143 {
144 return null;
145 }
146 return path.substring(specLength - 2);
147 }
148
149 return null;
150 }
151
152 @Override
153 public String getPathMatch(String path)
154 {
155 switch (group)
156 {
157 case EXACT:
158 if (pathSpec.equals(path))
159 {
160 return path;
161 }
162 else
163 {
164 return null;
165 }
166 case PREFIX_GLOB:
167 if (isWildcardMatch(path))
168 {
169 return path.substring(0,specLength - 2);
170 }
171 else
172 {
173 return null;
174 }
175 case SUFFIX_GLOB:
176 if (path.regionMatches(path.length() - (specLength - 1),pathSpec,1,specLength - 1))
177 {
178 return path;
179 }
180 else
181 {
182 return null;
183 }
184 case DEFAULT:
185 return path;
186 default:
187 return null;
188 }
189 }
190
191 @Override
192 public String getRelativePath(String base, String path)
193 {
194 String info = getPathInfo(path);
195 if (info == null)
196 {
197 info = path;
198 }
199
200 if (info.startsWith("./"))
201 {
202 info = info.substring(2);
203 }
204 if (base.endsWith(URIUtil.SLASH))
205 {
206 if (info.startsWith(URIUtil.SLASH))
207 {
208 path = base + info.substring(1);
209 }
210 else
211 {
212 path = base + info;
213 }
214 }
215 else if (info.startsWith(URIUtil.SLASH))
216 {
217 path = base + info;
218 }
219 else
220 {
221 path = base + URIUtil.SLASH + info;
222 }
223 return path;
224 }
225
226 private boolean isWildcardMatch(String path)
227 {
228
229 int cpl = specLength - 2;
230 if ((group == PathSpecGroup.PREFIX_GLOB) && (path.regionMatches(0,pathSpec,0,cpl)))
231 {
232 if ((path.length() == cpl) || ('/' == path.charAt(cpl)))
233 {
234 return true;
235 }
236 }
237 return false;
238 }
239
240 @Override
241 public boolean matches(String path)
242 {
243 switch (group)
244 {
245 case EXACT:
246 return pathSpec.equals(path);
247 case PREFIX_GLOB:
248 return isWildcardMatch(path);
249 case SUFFIX_GLOB:
250 return path.regionMatches((path.length() - specLength) + 1,pathSpec,1,specLength - 1);
251 case ROOT:
252
253 return ("/".equals(path));
254 case DEFAULT:
255
256 return true;
257 default:
258 return false;
259 }
260 }
261 }