0
# Context and Resource Handling
1
2
Context and resource handling provides servlet-like contexts for organizing handlers, virtual host support, resource serving, and static content management.
3
4
## ContextHandler
5
6
The `ContextHandler` provides a servlet-like context for organizing request handling with path mapping, virtual hosts, and resource management.
7
8
```java { .api }
9
public class ContextHandler extends Handler.Wrapper implements Attributes, AliasCheck {
10
// Constructors
11
public ContextHandler();
12
public ContextHandler(String contextPath);
13
public ContextHandler(Handler handler, String contextPath);
14
15
// Context path configuration
16
public String getContextPath();
17
public void setContextPath(String contextPath);
18
public String getPathInContext(String canonicallyEncodedPath);
19
20
// Resource management
21
public Resource getBaseResource();
22
public void setBaseResource(Resource resource);
23
public void setResourceBase(String resourceBase);
24
public String getResourceBase();
25
26
// Virtual host support
27
public List<String> getVirtualHosts();
28
public void setVirtualHosts(String... vhosts);
29
public void addVirtualHosts(String... virtualHosts);
30
31
// Class loading
32
public ClassLoader getClassLoader();
33
public void setClassLoader(ClassLoader classLoader);
34
35
// MIME types
36
public MimeTypes getMimeTypes();
37
public void setMimeTypes(MimeTypes mimeTypes);
38
39
// Temporary directory
40
public File getTempDirectory();
41
public void setTempDirectory(File temp);
42
43
// Context initialization
44
public Map<String, String> getInitParams();
45
public String getInitParameter(String name);
46
public void setInitParameter(String name, String value);
47
48
// Display name
49
public String getDisplayName();
50
public void setDisplayName(String servletContextName);
51
52
// Alias checking
53
public boolean checkAlias(String pathInContext, Resource resource);
54
public void addAliasCheck(AliasCheck check);
55
public List<AliasCheck> getAliasChecks();
56
57
// Context availability
58
public boolean isAvailable();
59
public void setAvailable(boolean available);
60
public String getUnavailableException();
61
}
62
```
63
64
## Basic Context Usage
65
66
```java
67
// Create server
68
Server server = new Server(8080);
69
70
// Create context handler for /api
71
ContextHandler apiContext = new ContextHandler("/api");
72
apiContext.setHandler(new ApiHandler());
73
74
// Create context handler for /web
75
ContextHandler webContext = new ContextHandler("/web");
76
webContext.setResourceBase("src/main/webapp");
77
webContext.setHandler(new DefaultServlet()); // For static files
78
79
// Create context collection to route requests
80
ContextHandlerCollection contexts = new ContextHandlerCollection();
81
contexts.setHandlers(new Handler[]{apiContext, webContext});
82
83
server.setHandler(contexts);
84
```
85
86
## Advanced Context Configuration
87
88
```java
89
public class AdvancedContextSetup {
90
91
public void setupContexts(Server server) {
92
// Main application context
93
ContextHandler mainContext = createMainContext();
94
95
// Admin interface context
96
ContextHandler adminContext = createAdminContext();
97
98
// Static resources context
99
ContextHandler staticContext = createStaticContext();
100
101
// Combine contexts
102
ContextHandlerCollection contexts = new ContextHandlerCollection();
103
contexts.setHandlers(new Handler[]{
104
mainContext, adminContext, staticContext
105
});
106
107
server.setHandler(contexts);
108
}
109
110
private ContextHandler createMainContext() {
111
ContextHandler context = new ContextHandler("/app");
112
113
// Set display name
114
context.setDisplayName("Main Application");
115
116
// Configure resources
117
context.setResourceBase("src/main/webapp");
118
119
// Set initialization parameters
120
context.setInitParameter("debug", "true");
121
context.setInitParameter("environment", "development");
122
123
// Configure virtual hosts
124
context.setVirtualHosts(new String[]{"example.com", "www.example.com"});
125
126
// Set custom class loader
127
URLClassLoader customClassLoader = createCustomClassLoader();
128
context.setClassLoader(customClassLoader);
129
130
// Configure MIME types
131
MimeTypes mimeTypes = new MimeTypes();
132
mimeTypes.addMimeMapping("json", "application/json");
133
context.setMimeTypes(mimeTypes);
134
135
// Set temporary directory
136
context.setTempDirectory(new File("/tmp/jetty-main"));
137
138
// Add alias checks for security
139
context.addAliasCheck(new SymlinkAllowedResourceAliasChecker(context));
140
context.addAliasCheck(new AllowedResourceAliasChecker(context));
141
142
// Set handler
143
context.setHandler(new MainApplicationHandler());
144
145
return context;
146
}
147
148
private ContextHandler createAdminContext() {
149
ContextHandler context = new ContextHandler("/admin");
150
context.setDisplayName("Admin Interface");
151
152
// Restrict to localhost
153
context.setVirtualHosts(new String[]{"127.0.0.1", "localhost"});
154
155
// Admin-specific configuration
156
context.setInitParameter("adminMode", "true");
157
context.setHandler(new AdminHandler());
158
159
return context;
160
}
161
162
private ContextHandler createStaticContext() {
163
ContextHandler context = new ContextHandler("/static");
164
context.setDisplayName("Static Resources");
165
context.setResourceBase("static-content/");
166
167
// Use resource handler for static files
168
ResourceHandler resourceHandler = new ResourceHandler();
169
resourceHandler.setDirectoriesListed(false);
170
resourceHandler.setWelcomeFiles(new String[]{"index.html"});
171
172
context.setHandler(resourceHandler);
173
174
return context;
175
}
176
177
private URLClassLoader createCustomClassLoader() {
178
// Create custom class loader for context
179
return new URLClassLoader(new URL[]{}, getClass().getClassLoader());
180
}
181
}
182
```
183
184
## ContextHandlerCollection
185
186
Collection of context handlers with automatic routing based on context paths.
187
188
```java { .api }
189
public class ContextHandlerCollection extends Handler.Sequence {
190
// Context management
191
public ContextHandler[] getContextHandlers();
192
public void setContextHandlers(ContextHandler[] contextHandlers);
193
public void addContextHandler(ContextHandler contextHandler);
194
public boolean removeContextHandler(ContextHandler contextHandler);
195
196
// Context lookup
197
public ContextHandler getContextHandler(String contextPath);
198
public Map<String, ContextHandler> getContextHandlerMap();
199
200
// Request handling
201
public boolean handle(Request request, Response response, Callback callback) throws Exception;
202
}
203
```
204
205
## ResourceHandler
206
207
Specialized handler for serving static resources with caching, directory listing, and welcome files.
208
209
```java { .api }
210
public class ResourceHandler extends Handler.Wrapper {
211
// Resource configuration
212
public Resource getBaseResource();
213
public void setBaseResource(Resource baseResource);
214
public void setResourceBase(String resourceBase);
215
public String getResourceBase();
216
217
// Welcome files
218
public List<String> getWelcomeFiles();
219
public void setWelcomeFiles(String... welcomeFiles);
220
public void addWelcomeFiles(String... welcomeFiles);
221
222
// Directory listing
223
public boolean isDirectoriesListed();
224
public void setDirectoriesListed(boolean directoriesListed);
225
226
// Resource serving options
227
public boolean isAcceptRanges();
228
public void setAcceptRanges(boolean acceptRanges);
229
public boolean isEtags();
230
public void setEtags(boolean etags);
231
public int getCacheControl();
232
public void setCacheControl(int cacheControl);
233
234
// Resource service
235
public ResourceService getResourceService();
236
public void setResourceService(ResourceService resourceService);
237
238
// Path mapping
239
public String[] getPathInfoOnly();
240
public void setPathInfoOnly(String... pathInfoOnly);
241
}
242
```
243
244
## Resource Serving Examples
245
246
```java
247
public class StaticResourceServer {
248
249
public void setupStaticResources(Server server) {
250
// Create resource handler
251
ResourceHandler resourceHandler = new ResourceHandler();
252
253
// Configure base resource directory
254
resourceHandler.setResourceBase("src/main/webapp");
255
256
// Configure welcome files
257
resourceHandler.setWelcomeFiles(new String[]{
258
"index.html", "index.htm", "default.html"
259
});
260
261
// Enable directory listings for development
262
resourceHandler.setDirectoriesListed(true);
263
264
// Enable range requests for partial content
265
resourceHandler.setAcceptRanges(true);
266
267
// Enable ETags for caching
268
resourceHandler.setEtags(true);
269
270
// Set cache control (1 hour)
271
resourceHandler.setCacheControl(3600);
272
273
// Create context for static resources
274
ContextHandler staticContext = new ContextHandler("/static");
275
staticContext.setHandler(resourceHandler);
276
277
server.setHandler(staticContext);
278
}
279
}
280
```
281
282
### Advanced Resource Configuration
283
284
```java
285
public class AdvancedResourceHandler extends ResourceHandler {
286
287
@Override
288
protected void doStart() throws Exception {
289
super.doStart();
290
291
// Custom resource service configuration
292
ResourceService service = getResourceService();
293
294
// Configure caching
295
service.setAcceptRanges(true);
296
service.setDirAllowed(false); // Disable directory access
297
service.setRedirectWelcome(true); // Redirect to welcome files
298
service.setGzipEquivalentFileExtensions(Arrays.asList(".gz"));
299
300
// Custom welcome file resolution
301
service.setWelcomeFactory(this::findWelcomeFile);
302
}
303
304
private String findWelcomeFile(String pathInContext) {
305
// Custom logic to find welcome files
306
Resource resource = getBaseResource().resolve(pathInContext);
307
if (resource.isDirectory()) {
308
// Try different welcome files based on context
309
if (pathInContext.startsWith("/api")) {
310
return "api-index.html";
311
} else if (pathInContext.startsWith("/docs")) {
312
return "documentation.html";
313
}
314
}
315
return null; // Use default welcome files
316
}
317
318
@Override
319
public boolean handle(Request request, Response response, Callback callback)
320
throws Exception {
321
322
// Add custom headers for all resources
323
String path = request.getHttpURI().getPath();
324
325
if (path.endsWith(".css")) {
326
response.getHeaders().add("Content-Type", "text/css; charset=utf-8");
327
} else if (path.endsWith(".js")) {
328
response.getHeaders().add("Content-Type", "application/javascript; charset=utf-8");
329
}
330
331
// Add CORS headers for API resources
332
if (path.startsWith("/api")) {
333
response.getHeaders().add("Access-Control-Allow-Origin", "*");
334
}
335
336
return super.handle(request, response, callback);
337
}
338
}
339
```
340
341
## Resource Interface
342
343
The `Resource` interface provides abstraction for accessing files, directories, and other resources.
344
345
```java { .api }
346
public interface Resource {
347
// Resource identification
348
String getName();
349
URI getURI();
350
Path getPath();
351
352
// Resource state
353
boolean exists();
354
boolean isDirectory();
355
boolean isReadable();
356
long length();
357
long lastModified();
358
359
// Content access
360
InputStream newInputStream() throws IOException;
361
ReadableByteChannel newReadableByteChannel() throws IOException;
362
363
// Directory operations
364
List<Resource> list();
365
Resource resolve(String subPath);
366
367
// Resource creation
368
static Resource newResource(String resource);
369
static Resource newResource(URI uri);
370
static Resource newResource(Path path);
371
}
372
```
373
374
## Context Request and Response
375
376
### ContextRequest
377
378
Context-specific request wrapper providing additional context information.
379
380
```java { .api }
381
public class ContextRequest extends Request.Wrapper implements Invocable {
382
// Context information
383
public ContextHandler getContextHandler();
384
public Context getContext();
385
public String getContextPath();
386
public String getPathInContext();
387
388
// Session management
389
public HttpSession getSession();
390
public HttpSession getSession(boolean create);
391
392
// Attributes with context scope
393
public Object getAttribute(String name);
394
public void setAttribute(String name, Object value);
395
public void removeAttribute(String name);
396
public Set<String> getAttributeNameSet();
397
398
// Request dispatcher
399
public RequestDispatcher getRequestDispatcher(String path);
400
}
401
```
402
403
### ContextResponse
404
405
Context-specific response wrapper.
406
407
```java { .api }
408
public class ContextResponse extends Response.Wrapper {
409
// Response encoding
410
public void setCharacterEncoding(String encoding);
411
public String getCharacterEncoding();
412
public void setContentType(String contentType);
413
public String getContentType();
414
415
// Output handling
416
public PrintWriter getWriter() throws IOException;
417
public ServletOutputStream getOutputStream() throws IOException;
418
}
419
```
420
421
## Virtual Host Configuration
422
423
```java
424
public class VirtualHostExample {
425
426
public void setupVirtualHosts(Server server) {
427
// Context for main site
428
ContextHandler mainSite = new ContextHandler("/");
429
mainSite.setVirtualHosts(new String[]{"example.com", "www.example.com"});
430
mainSite.setHandler(new MainSiteHandler());
431
432
// Context for API subdomain
433
ContextHandler apiSite = new ContextHandler("/");
434
apiSite.setVirtualHosts(new String[]{"api.example.com"});
435
apiSite.setHandler(new ApiHandler());
436
437
// Context for admin subdomain with IP restriction
438
ContextHandler adminSite = new ContextHandler("/");
439
adminSite.setVirtualHosts(new String[]{"admin.example.com", "127.0.0.1:8080"});
440
adminSite.setHandler(new AdminHandler());
441
442
// Context for mobile site
443
ContextHandler mobileSite = new ContextHandler("/");
444
mobileSite.setVirtualHosts(new String[]{"m.example.com", "mobile.example.com"});
445
mobileSite.setHandler(new MobileSiteHandler());
446
447
// Combine all contexts
448
ContextHandlerCollection contexts = new ContextHandlerCollection();
449
contexts.setHandlers(new Handler[]{
450
mainSite, apiSite, adminSite, mobileSite
451
});
452
453
server.setHandler(contexts);
454
}
455
}
456
```
457
458
## Alias Checking and Security
459
460
### AliasCheck Interface
461
462
```java { .api }
463
public interface AliasCheck {
464
boolean checkAlias(String pathInContext, Resource resource);
465
}
466
```
467
468
### Built-in Alias Checkers
469
470
```java { .api }
471
public class AllowedResourceAliasChecker extends AbstractLifeCycle implements AliasCheck {
472
public AllowedResourceAliasChecker(ContextHandler contextHandler);
473
public boolean checkAlias(String pathInContext, Resource resource);
474
protected boolean check(String pathInContext, Resource resource);
475
}
476
477
public class SymlinkAllowedResourceAliasChecker extends AllowedResourceAliasChecker {
478
public SymlinkAllowedResourceAliasChecker(ContextHandler contextHandler);
479
}
480
```
481
482
### Custom Alias Checker
483
484
```java
485
public class SecurityAliasChecker implements AliasCheck {
486
private final Set<String> allowedExtensions;
487
private final Set<String> blockedPaths;
488
489
public SecurityAliasChecker() {
490
this.allowedExtensions = Set.of(".html", ".css", ".js", ".png", ".jpg", ".gif");
491
this.blockedPaths = Set.of("/WEB-INF", "/META-INF", "/.git", "/.svn");
492
}
493
494
@Override
495
public boolean checkAlias(String pathInContext, Resource resource) {
496
// Block access to sensitive directories
497
for (String blockedPath : blockedPaths) {
498
if (pathInContext.startsWith(blockedPath)) {
499
return false;
500
}
501
}
502
503
// Only allow specific file extensions
504
String fileName = resource.getName();
505
if (fileName != null) {
506
for (String ext : allowedExtensions) {
507
if (fileName.endsWith(ext)) {
508
return true;
509
}
510
}
511
}
512
513
return false; // Deny by default
514
}
515
}
516
517
// Usage
518
ContextHandler context = new ContextHandler("/files");
519
context.addAliasCheck(new SecurityAliasChecker());
520
```
521
522
## Context Initialization
523
524
```java
525
public class ContextInitializationExample extends ContextHandler {
526
527
@Override
528
protected void doStart() throws Exception {
529
// Pre-initialization
530
setupLogging();
531
loadConfiguration();
532
533
super.doStart();
534
535
// Post-initialization
536
initializeServices();
537
registerMBeans();
538
}
539
540
@Override
541
protected void doStop() throws Exception {
542
// Pre-shutdown
543
unregisterMBeans();
544
shutdownServices();
545
546
super.doStop();
547
548
// Post-shutdown
549
cleanupResources();
550
}
551
552
private void setupLogging() {
553
// Configure logging for this context
554
setAttribute("logLevel", "DEBUG");
555
}
556
557
private void loadConfiguration() {
558
// Load context-specific configuration
559
Properties config = new Properties();
560
try (InputStream is = getClass().getResourceAsStream("/context.properties")) {
561
if (is != null) {
562
config.load(is);
563
for (String key : config.stringPropertyNames()) {
564
setInitParameter(key, config.getProperty(key));
565
}
566
}
567
} catch (IOException e) {
568
throw new RuntimeException("Failed to load configuration", e);
569
}
570
}
571
572
private void initializeServices() {
573
// Initialize context-specific services
574
Object service = new MyContextService();
575
setAttribute("contextService", service);
576
}
577
578
private void registerMBeans() {
579
// Register JMX MBeans for monitoring
580
}
581
582
private void unregisterMBeans() {
583
// Unregister JMX MBeans
584
}
585
586
private void shutdownServices() {
587
// Shutdown services gracefully
588
Object service = getAttribute("contextService");
589
if (service instanceof MyContextService) {
590
((MyContextService) service).shutdown();
591
}
592
}
593
594
private void cleanupResources() {
595
// Final cleanup
596
}
597
}
598
```