0
# Path Mapping
1
2
Flexible path specification matching for routing and dispatch with support for servlet-style, regex, and URI template patterns, plus efficient mapping collections.
3
4
## Capabilities
5
6
### PathSpec Interface
7
8
Core path specification interface for matching and path extraction.
9
10
```java { .api }
11
/**
12
* Path specification interface for matching and path extraction
13
*/
14
interface PathSpec extends Comparable<PathSpec> {
15
/** Get original path specification string */
16
String getDeclaration();
17
18
/** Get path prefix (for prefix matches) */
19
String getPrefix();
20
21
/** Get path suffix (for suffix matches) */
22
String getSuffix();
23
24
/** Get path specification group for ordering */
25
PathSpecGroup getGroup();
26
27
/** Get specification length for priority */
28
int getSpecLength();
29
30
/** Get path depth for priority */
31
int getPathDepth();
32
33
/** Check if path matches this specification */
34
boolean matches(String path);
35
36
/** Get matched path information */
37
MatchedPath matched(String path);
38
39
/** Extract path info from matched path */
40
String getPathInfo(String path);
41
42
/** Extract matched portion from path */
43
String getPathMatch(String path);
44
}
45
```
46
47
### MatchedPath Interface
48
49
Result of path matching with match and info extraction.
50
51
```java { .api }
52
/**
53
* Result of path matching with details
54
*/
55
interface MatchedPath {
56
/** Get matched portion of path */
57
String getPathMatch();
58
59
/** Get remaining path info */
60
String getPathInfo();
61
62
/** Get path specification that matched */
63
PathSpec getPathSpec();
64
}
65
```
66
67
### PathSpec Implementations
68
69
Various path specification implementations for different matching patterns.
70
71
```java { .api }
72
/**
73
* Base class for path specifications
74
*/
75
abstract class AbstractPathSpec implements PathSpec {
76
/** Create with path specification string */
77
AbstractPathSpec(String pathSpec);
78
79
/** Get path specification string */
80
String getDeclaration();
81
82
/** Compare specifications for ordering */
83
int compareTo(PathSpec other);
84
}
85
86
/**
87
* Servlet-style path specifications
88
* Supports: /exact, /prefix/*, *.extension, /
89
*/
90
class ServletPathSpec extends AbstractPathSpec {
91
/** Create servlet path specification */
92
ServletPathSpec(String servletPathSpec);
93
94
/** Check if exact match specification */
95
boolean isExact();
96
97
/** Check if prefix match specification */
98
boolean isPrefix();
99
100
/** Check if suffix match specification */
101
boolean isSuffix();
102
103
/** Check if default/root specification */
104
boolean isDefault();
105
106
/** Get variable portion length */
107
int getVariableLength();
108
}
109
110
/**
111
* Regular expression path specifications
112
*/
113
class RegexPathSpec extends AbstractPathSpec {
114
/** Create regex path specification */
115
RegexPathSpec(String regex);
116
117
/** Get compiled pattern */
118
Pattern getPattern();
119
120
/** Get regex group count */
121
int getGroupCount();
122
}
123
124
/**
125
* URI template path specifications
126
* Supports: /users/{id}, /api/{version}/users/{userId}
127
*/
128
class UriTemplatePathSpec extends AbstractPathSpec {
129
/** Create URI template path specification */
130
UriTemplatePathSpec(String template);
131
132
/** Get template variable names */
133
List<String> getVariableNames();
134
135
/** Get number of template variables */
136
int getVariableCount();
137
138
/** Extract path parameters from matched path */
139
Map<String, String> getPathParams(String path);
140
141
/** Check if template has variables */
142
boolean hasVariables();
143
}
144
```
145
146
### PathSpecGroup Enumeration
147
148
Groups path specifications by matching priority and type.
149
150
```java { .api }
151
/**
152
* Groups path specs by matching priority
153
*/
154
enum PathSpecGroup {
155
/** Exact path matches (highest priority) */
156
EXACT,
157
158
/** Prefix with glob patterns (/path/*) */
159
PREFIX_GLOB,
160
161
/** Suffix with glob patterns (*.ext) */
162
SUFFIX_GLOB,
163
164
/** Regular expression patterns */
165
REGEX,
166
167
/** Default/fallback matches (lowest priority) */
168
DEFAULT;
169
170
/** Get group priority (lower number = higher priority) */
171
int getPriority();
172
}
173
```
174
175
### Path Mapping Collections
176
177
Collections for managing and matching multiple path specifications.
178
179
```java { .api }
180
/**
181
* Collection of path mappings with efficient matching
182
*/
183
class PathMappings<E> extends AbstractMap<PathSpec, E>
184
implements Iterable<MappedResource<E>> {
185
186
/** Create empty path mappings */
187
PathMappings();
188
189
/** Get best matching resource for path */
190
MappedResource<E> getMatched(String path);
191
192
/** Get all matching resources for path (ordered by priority) */
193
List<MappedResource<E>> getMatches(String path);
194
195
/** Add path specification mapping */
196
boolean put(PathSpec pathSpec, E resource);
197
198
/** Add path specification mapping with string */
199
E put(String pathSpec, E resource);
200
201
/** Remove path specification mapping */
202
boolean remove(PathSpec pathSpec);
203
204
/** Remove all mappings */
205
void clear();
206
207
/** Get number of mappings */
208
int size();
209
210
/** Check if mappings are empty */
211
boolean isEmpty();
212
213
/** Get all path specifications */
214
Set<PathSpec> keySet();
215
216
/** Get all mapped resources */
217
Collection<E> values();
218
219
/** Get all mappings as entries */
220
Set<Entry<PathSpec, E>> entrySet();
221
222
/** Iterator over mapped resources */
223
Iterator<MappedResource<E>> iterator();
224
}
225
226
/**
227
* Set of path specifications with efficient matching
228
*/
229
class PathSpecSet extends AbstractSet<String> implements Predicate<String> {
230
/** Create empty path spec set */
231
PathSpecSet();
232
233
/** Test if path matches any specification */
234
boolean test(String path);
235
236
/** Add path specification string */
237
boolean add(String pathSpec);
238
239
/** Remove path specification string */
240
boolean remove(String pathSpec);
241
242
/** Check if contains specification */
243
boolean contains(Object pathSpec);
244
245
/** Get number of specifications */
246
int size();
247
248
/** Check if set is empty */
249
boolean isEmpty();
250
251
/** Clear all specifications */
252
void clear();
253
254
/** Iterator over specification strings */
255
Iterator<String> iterator();
256
}
257
```
258
259
### Supporting Classes
260
261
Classes for representing mapping results and matched resources.
262
263
```java { .api }
264
/**
265
* Path mapping result with resource and match information
266
*/
267
class MappedResource<E> implements Comparable<MappedResource<E>>,
268
Map.Entry<PathSpec, E> {
269
270
/** Create mapped resource */
271
MappedResource(E resource, PathSpec pathSpec, MatchedPath matchedPath);
272
273
/** Get mapped resource */
274
E getResource();
275
276
/** Get path specification */
277
PathSpec getPathSpec();
278
279
/** Get matched path information */
280
MatchedPath getMatchedPath();
281
282
/** Get matched portion of path */
283
String getPathMatch();
284
285
/** Get remaining path info */
286
String getPathInfo();
287
288
/** Get resource (Map.Entry interface) */
289
E getValue();
290
291
/** Get path spec (Map.Entry interface) */
292
PathSpec getKey();
293
294
/** Compare resources by path spec priority */
295
int compareTo(MappedResource<E> other);
296
}
297
298
/**
299
* Resource matched to a specific path
300
*/
301
class MatchedResource<E> {
302
/** Create from mapping entry and matched path */
303
static <E> MatchedResource<E> of(Map.Entry<PathSpec, E> mapping,
304
MatchedPath matchedPath);
305
306
/** Get matched resource */
307
E getResource();
308
309
/** Get path specification */
310
PathSpec getPathSpec();
311
312
/** Get matched path information */
313
MatchedPath getMatchedPath();
314
}
315
```
316
317
**Usage Examples:**
318
319
```java
320
import org.eclipse.jetty.http.pathmap.*;
321
import java.util.Map;
322
323
// Create servlet-style path specifications
324
PathSpec exactSpec = new ServletPathSpec("/api/users");
325
PathSpec prefixSpec = new ServletPathSpec("/api/*");
326
PathSpec suffixSpec = new ServletPathSpec("*.json");
327
PathSpec defaultSpec = new ServletPathSpec("/");
328
329
// Test path matching
330
boolean matches = exactSpec.matches("/api/users"); // true
331
boolean prefixMatch = prefixSpec.matches("/api/users/123"); // true
332
boolean suffixMatch = suffixSpec.matches("/data.json"); // true
333
334
// Extract path information
335
String pathInfo = prefixSpec.getPathInfo("/api/users/123"); // "/users/123"
336
String pathMatch = prefixSpec.getPathMatch("/api/users/123"); // "/api"
337
338
// Regular expression path specs
339
PathSpec regexSpec = new RegexPathSpec("^/users/([0-9]+)$");
340
boolean regexMatch = regexSpec.matches("/users/123"); // true
341
342
MatchedPath matched = regexSpec.matched("/users/123");
343
String matchedPortion = matched.getPathMatch(); // "/users/123"
344
345
// URI template path specs with parameter extraction
346
UriTemplatePathSpec templateSpec = new UriTemplatePathSpec("/users/{userId}/posts/{postId}");
347
boolean templateMatch = templateSpec.matches("/users/123/posts/456"); // true
348
349
Map<String, String> params = templateSpec.getPathParams("/users/123/posts/456");
350
String userId = params.get("userId"); // "123"
351
String postId = params.get("postId"); // "456"
352
353
List<String> variableNames = templateSpec.getVariableNames(); // ["userId", "postId"]
354
355
// Path mappings for routing
356
PathMappings<String> routes = new PathMappings<>();
357
358
// Add route mappings
359
routes.put("/api/users", "UserController");
360
routes.put("/api/users/*", "UserController");
361
routes.put("/api/posts/*", "PostController");
362
routes.put("*.json", "JsonRenderer");
363
routes.put("/", "DefaultController");
364
365
// Find best match for a path
366
MappedResource<String> match = routes.getMatched("/api/users/123");
367
if (match != null) {
368
String controller = match.getResource(); // "UserController"
369
String pathInfo = match.getPathInfo(); // "/123"
370
PathSpec spec = match.getPathSpec(); // ServletPathSpec("/api/users/*")
371
}
372
373
// Get all matches (ordered by priority)
374
List<MappedResource<String>> allMatches = routes.getMatches("/api/users/123.json");
375
// Will include both "/api/users/*" and "*.json" matches
376
377
// Path specification set for filtering
378
PathSpecSet allowedPaths = new PathSpecSet();
379
allowedPaths.add("/api/*");
380
allowedPaths.add("/public/*");
381
allowedPaths.add("*.css");
382
allowedPaths.add("*.js");
383
384
// Test if path is allowed
385
boolean allowed = allowedPaths.test("/api/users"); // true
386
boolean blocked = allowedPaths.test("/admin/config"); // false
387
388
// Use as Predicate in streams
389
List<String> paths = Arrays.asList("/api/users", "/admin/config", "/public/style.css");
390
List<String> allowedOnly = paths.stream()
391
.filter(allowedPaths)
392
.collect(Collectors.toList()); // ["/api/users", "/public/style.css"]
393
394
// Path spec comparison and ordering
395
List<PathSpec> specs = Arrays.asList(
396
new ServletPathSpec("*.json"), // Lower priority (suffix)
397
new ServletPathSpec("/api/users"), // Higher priority (exact)
398
new ServletPathSpec("/api/*"), // Medium priority (prefix)
399
new ServletPathSpec("/") // Lowest priority (default)
400
);
401
402
Collections.sort(specs); // Sorts by priority: exact, prefix, suffix, default
403
404
// Working with path spec groups
405
PathSpecGroup group = exactSpec.getGroup(); // PathSpecGroup.EXACT
406
int priority = group.getPriority(); // Lower numbers = higher priority
407
408
// Advanced routing with custom resources
409
class RouteHandler {
410
private final String method;
411
private final String handler;
412
413
RouteHandler(String method, String handler) {
414
this.method = method;
415
this.handler = handler;
416
}
417
418
// getters...
419
}
420
421
PathMappings<RouteHandler> apiRoutes = new PathMappings<>();
422
apiRoutes.put("/api/users", new RouteHandler("GET", "listUsers"));
423
apiRoutes.put("/api/users/*", new RouteHandler("GET", "getUser"));
424
425
// URI template with multiple variables
426
UriTemplatePathSpec complexTemplate = new UriTemplatePathSpec(
427
"/api/{version}/users/{userId}/posts/{postId}/comments/{commentId}"
428
);
429
430
Map<String, String> complexParams = complexTemplate.getPathParams(
431
"/api/v1/users/123/posts/456/comments/789"
432
);
433
// Results: {version=v1, userId=123, postId=456, commentId=789}
434
435
// Path spec properties
436
ServletPathSpec prefixPathSpec = new ServletPathSpec("/api/*");
437
boolean isPrefix = prefixPathSpec.isPrefix(); // true
438
boolean isExact = prefixPathSpec.isExact(); // false
439
int specLength = prefixPathSpec.getSpecLength(); // 5 (length of "/api/")
440
int pathDepth = prefixPathSpec.getPathDepth(); // 1 (one path segment)
441
```