0
# Class Visibility Controls
1
2
Jetty WebApp provides fine-grained control over class visibility and loading delegation through pattern-based class matchers. This system allows precise control over which classes are loaded by the system classloader, server classloader, or webapp classloader.
3
4
## Capabilities
5
6
### ClassMatcher
7
8
Pattern-based matcher for controlling class visibility and loading delegation.
9
10
```java { .api }
11
/**
12
* Pattern matcher for classes based on package, location, and module patterns.
13
* Supports inclusion and exclusion patterns with precedence rules.
14
*/
15
public class ClassMatcher extends AbstractSet<String> {
16
17
/**
18
* Create empty class matcher
19
*/
20
public ClassMatcher();
21
22
/**
23
* Copy constructor
24
*/
25
public ClassMatcher(ClassMatcher patterns);
26
27
/**
28
* Create with initial patterns
29
*/
30
public ClassMatcher(String... patterns);
31
32
/**
33
* Create with single pattern
34
*/
35
public ClassMatcher(String pattern);
36
}
37
```
38
39
### Pattern Management
40
41
Methods for adding and managing class patterns.
42
43
```java { .api }
44
/**
45
* Include class patterns (positive match)
46
*/
47
public boolean include(String name);
48
public boolean include(String... name);
49
50
/**
51
* Exclude class patterns (negative match)
52
*/
53
public boolean exclude(String name);
54
public boolean exclude(String... name);
55
56
/**
57
* Add patterns (defaults to inclusion)
58
*/
59
public boolean add(String pattern);
60
public boolean add(String... pattern);
61
62
/**
63
* Get all patterns
64
*/
65
public String[] getPatterns();
66
67
/**
68
* Get inclusion patterns only
69
*/
70
public String[] getInclusions();
71
72
/**
73
* Get exclusion patterns only
74
*/
75
public String[] getExclusions();
76
```
77
78
**Usage Examples:**
79
80
```java
81
ClassMatcher matcher = new ClassMatcher();
82
83
// Include patterns
84
matcher.include("com.mycompany.");
85
matcher.include("org.apache.commons.");
86
87
// Exclude patterns
88
matcher.exclude("com.mycompany.internal.");
89
matcher.exclude("org.apache.commons.logging.");
90
91
// Add multiple patterns
92
matcher.add("javax.servlet.", "jakarta.servlet.");
93
```
94
95
### Pattern Matching
96
97
Methods for testing class names against patterns.
98
99
```java { .api }
100
/**
101
* Test if class name matches patterns
102
*/
103
public boolean match(String name);
104
105
/**
106
* Test if class matches patterns
107
*/
108
public boolean match(Class<?> clazz);
109
110
/**
111
* Test if class name and URL match patterns
112
*/
113
public boolean match(String name, URL url);
114
```
115
116
**Usage Examples:**
117
118
```java
119
// Test class names
120
if (matcher.match("com.mycompany.MyClass")) {
121
// Class matches inclusion patterns
122
}
123
124
// Test class objects
125
if (matcher.match(String.class)) {
126
// java.lang.String matches patterns
127
}
128
129
// Test with URL context
130
URL jarUrl = new URL("file:/path/to/lib.jar");
131
if (matcher.match("com.example.Service", jarUrl)) {
132
// Class from specific JAR matches
133
}
134
```
135
136
### Pattern Entry Details
137
138
Information about individual pattern entries and specialized implementations.
139
140
```java { .api }
141
/**
142
* Represents a single pattern entry with inclusion/exclusion flag
143
*/
144
public static class Entry {
145
146
/**
147
* Get the pattern string
148
*/
149
public String getPattern();
150
151
/**
152
* Get the pattern name (same as pattern)
153
*/
154
public String getName();
155
156
/**
157
* Check if this is an inclusive pattern
158
*/
159
public boolean isInclusive();
160
161
/**
162
* Test if this entry matches a class name
163
*/
164
public boolean match(String name);
165
166
/**
167
* Test if this entry matches a class and URL
168
*/
169
public boolean match(String name, URL url);
170
}
171
172
/**
173
* Entry for package-based patterns
174
*/
175
public static class PackageEntry extends Entry {
176
public PackageEntry(String pattern, boolean inclusive);
177
}
178
179
/**
180
* Entry for exact class name patterns
181
*/
182
public static class ClassEntry extends Entry {
183
public ClassEntry(String pattern, boolean inclusive);
184
}
185
186
/**
187
* Entry for location-based patterns (JAR files, directories)
188
*/
189
public static class LocationEntry extends Entry {
190
public LocationEntry(String pattern, boolean inclusive);
191
}
192
193
/**
194
* Entry for module-based patterns (Java 9+ modules)
195
*/
196
public static class ModuleEntry extends Entry {
197
public ModuleEntry(String pattern, boolean inclusive);
198
}
199
```
200
201
## Pattern Syntax
202
203
### Basic Patterns
204
205
```java
206
// Package prefix matching
207
"com.mycompany." // Matches com.mycompany.* packages
208
"org.eclipse.jetty." // Matches org.eclipse.jetty.* packages
209
210
// Exact class matching
211
"com.mycompany.MyClass" // Matches exact class only
212
213
// Wildcard matching
214
"com.mycompany.*" // Same as "com.mycompany."
215
"*.internal.*" // Matches any package containing "internal"
216
```
217
218
### Advanced Patterns
219
220
```java
221
// Exclusion patterns (prefix with '-')
222
"-com.mycompany.internal." // Exclude internal packages
223
"-org.eclipse.jetty.util.log." // Exclude logging utilities
224
225
// Location-based patterns
226
"file:/path/to/specific.jar" // Match classes from specific JAR
227
"file:/lib/" // Match classes from lib directory
228
229
// Module-based patterns (Java 9+)
230
"java.base/" // Match classes from java.base module
231
"java.logging/" // Match classes from java.logging module
232
```
233
234
### Pattern Precedence
235
236
```java
237
ClassMatcher matcher = new ClassMatcher();
238
239
// More specific patterns take precedence
240
matcher.include("com.mycompany."); // Include mycompany packages
241
matcher.exclude("com.mycompany.internal."); // But exclude internal
242
matcher.include("com.mycompany.internal.api."); // Except API classes
243
244
// Test precedence
245
matcher.match("com.mycompany.Service"); // true (included)
246
matcher.match("com.mycompany.internal.Util"); // false (excluded)
247
matcher.match("com.mycompany.internal.api.Service"); // true (re-included)
248
```
249
250
## Integration with WebApp Components
251
252
### WebAppContext Integration
253
254
WebAppContext uses ClassMatcher for system and server class controls.
255
256
```java { .api }
257
// WebAppContext methods using ClassMatcher
258
public ClassMatcher getSystemClassMatcher();
259
public void setSystemClassMatcher(ClassMatcher systemClasses);
260
public void addSystemClassMatcher(ClassMatcher systemClasses);
261
262
public ClassMatcher getServerClassMatcher();
263
public void setServerClassMatcher(ClassMatcher serverClasses);
264
public void addServerClassMatcher(ClassMatcher serverClasses);
265
```
266
267
**Usage Examples:**
268
269
```java
270
WebAppContext webapp = new WebAppContext();
271
272
// Set system classes (loaded by system classloader)
273
ClassMatcher systemClasses = new ClassMatcher();
274
systemClasses.include("java.", "javax.", "jakarta.");
275
systemClasses.include("org.xml.", "org.w3c.");
276
webapp.setSystemClassMatcher(systemClasses);
277
278
// Set server classes (hidden from webapp)
279
ClassMatcher serverClasses = new ClassMatcher();
280
serverClasses.include("org.eclipse.jetty.");
281
serverClasses.exclude("org.eclipse.jetty.servlet.listener.");
282
webapp.setServerClassMatcher(serverClasses);
283
```
284
285
### Configuration Integration
286
287
Configurations can contribute class visibility patterns.
288
289
```java { .api }
290
// Configuration interface methods
291
default ClassMatcher getSystemClasses() { return null; }
292
default ClassMatcher getServerClasses() { return null; }
293
294
// AbstractConfiguration protected methods
295
protected void protect(String... classes); // Add to system classes
296
protected void hide(String... classes); // Add to server classes
297
protected void expose(String... classes); // Remove from server classes
298
protected void protectAndExpose(String... classes); // Add to system, remove from server
299
```
300
301
**Usage Examples:**
302
303
```java
304
public class MyConfiguration extends AbstractConfiguration {
305
public MyConfiguration() {
306
// Protect shared libraries
307
protect("com.mycompany.shared.");
308
309
// Hide internal server classes
310
hide("com.mycompany.server.internal.");
311
312
// Expose specific server utilities to webapps
313
expose("com.mycompany.server.util.StringUtils");
314
}
315
}
316
```
317
318
## Default Class Patterns
319
320
### Default System Classes
321
322
Classes loaded by the system classloader (not isolated per webapp).
323
324
```java
325
// Java platform classes
326
"java."
327
"javax."
328
"jakarta."
329
"sun."
330
"com.sun."
331
332
// XML processing
333
"org.xml."
334
"org.w3c."
335
336
// Other system classes
337
"org.slf4j." // Logging facade
338
"org.apache.commons.logging." // Commons logging
339
```
340
341
### Default Server Classes
342
343
Classes hidden from webapps (loaded by server classloader).
344
345
```java
346
// Jetty server classes
347
"org.eclipse.jetty."
348
"-org.eclipse.jetty.servlet.listener." // Except servlet listeners
349
"-org.eclipse.jetty.util.log." // Except webapp logging
350
351
// Server implementation classes
352
"org.mortbay."
353
"org.apache.jasper." // JSP compiler (when present)
354
```
355
356
## Usage Patterns
357
358
### Custom Class Isolation
359
360
```java
361
// Create webapp with custom class isolation
362
WebAppContext webapp = new WebAppContext();
363
364
// System classes: shared across all webapps
365
ClassMatcher systemClasses = new ClassMatcher();
366
systemClasses.include("java.", "javax.", "jakarta.");
367
systemClasses.include("com.mycompany.shared.");
368
webapp.setSystemClassMatcher(systemClasses);
369
370
// Server classes: hidden from webapps
371
ClassMatcher serverClasses = new ClassMatcher();
372
serverClasses.include("org.eclipse.jetty.");
373
serverClasses.include("com.mycompany.server.");
374
serverClasses.exclude("com.mycompany.server.api."); // Expose API
375
webapp.setServerClassMatcher(serverClasses);
376
```
377
378
### Development vs Production Patterns
379
380
```java
381
// Development: expose more server classes for debugging
382
if (isDevelopmentMode()) {
383
ClassMatcher serverClasses = webapp.getServerClassMatcher();
384
serverClasses.exclude("org.eclipse.jetty.util.log.");
385
serverClasses.exclude("org.eclipse.jetty.server.handler.DebugHandler");
386
}
387
388
// Production: strict isolation
389
if (isProductionMode()) {
390
ClassMatcher serverClasses = new ClassMatcher();
391
serverClasses.include("org.eclipse.jetty.");
392
serverClasses.include("com.mycompany.server.");
393
// No exclusions - strict hiding
394
webapp.setServerClassMatcher(serverClasses);
395
}
396
```
397
398
### Multi-Tenant Applications
399
400
```java
401
// Isolate tenant-specific classes
402
public class TenantConfiguration extends AbstractConfiguration {
403
private final String tenantId;
404
405
public TenantConfiguration(String tenantId) {
406
this.tenantId = tenantId;
407
408
// Each tenant gets their own version of these classes
409
hide("com.myapp.tenant." + tenantId + ".");
410
411
// But shared utilities are system classes
412
protect("com.myapp.shared.");
413
}
414
}
415
416
// Apply to webapp
417
webapp.addConfiguration(new TenantConfiguration("tenant1"));
418
```
419
420
### Library Version Isolation
421
422
```java
423
// Isolate specific library versions per webapp
424
ClassMatcher serverClasses = webapp.getServerClassMatcher();
425
426
// Hide server's Jackson version, let webapp use its own
427
serverClasses.include("com.fasterxml.jackson.");
428
429
// Hide server's Spring version
430
serverClasses.include("org.springframework.");
431
432
// But expose specific server utilities
433
serverClasses.exclude("com.mycompany.server.jackson.CustomModule");
434
```
435
436
### Dynamic Class Pattern Updates
437
438
```java
439
// Update patterns at runtime (before webapp start)
440
ClassMatcher matcher = webapp.getSystemClassMatcher();
441
442
// Add patterns dynamically
443
Properties config = loadConfiguration();
444
for (String pattern : config.getProperty("system.classes", "").split(",")) {
445
if (!pattern.trim().isEmpty()) {
446
matcher.include(pattern.trim());
447
}
448
}
449
450
// Remove patterns
451
for (String pattern : config.getProperty("exclude.system.classes", "").split(",")) {
452
if (!pattern.trim().isEmpty()) {
453
matcher.exclude(pattern.trim());
454
}
455
}
456
```