0
# ZooKeeper Path Utilities
1
2
Comprehensive path manipulation utilities for ZooKeeper node operations, including path validation, tree operations, and node management. These utilities provide safe and efficient methods for working with ZooKeeper's hierarchical namespace.
3
4
## Capabilities
5
6
### ZKPaths Class
7
8
Central utility class providing comprehensive ZooKeeper path manipulation and tree operation methods.
9
10
```java { .api }
11
/**
12
* Utility class for ZooKeeper path operations and tree management
13
*/
14
public class ZKPaths {
15
/** ZooKeeper path separator constant */
16
public static final String PATH_SEPARATOR = "/";
17
18
/**
19
* Safely construct a path by joining parent and child components
20
* @param parent Parent path (can be null or empty for root)
21
* @param child Child node name
22
* @return Properly formatted ZooKeeper path
23
*/
24
public static String makePath(String parent, String child);
25
26
/**
27
* Safely construct a path by joining parent with multiple child components
28
* @param parent Parent path (can be null or empty for root)
29
* @param firstChild First child node name
30
* @param restChildren Additional child node names
31
* @return Properly formatted ZooKeeper path
32
*/
33
public static String makePath(String parent, String firstChild, String... restChildren);
34
35
/**
36
* Extract the node name from a full path
37
* @param path Full ZooKeeper path
38
* @return Node name (last component of path)
39
*/
40
public static String getNodeFromPath(String path);
41
42
/**
43
* Split a path into parent path and node name
44
* @param path Full ZooKeeper path
45
* @return PathAndNode object containing parent and node
46
*/
47
public static PathAndNode getPathAndNode(String path);
48
49
/**
50
* Split a path into individual components
51
* @param path ZooKeeper path to split
52
* @return List of path components (excluding empty root)
53
*/
54
public static List<String> split(String path);
55
56
/**
57
* Create all parent directories for a path (like mkdir -p)
58
* @param zookeeper ZooKeeper client instance
59
* @param path Path to create (parents will be created as needed)
60
* @throws KeeperException if ZooKeeper operation fails
61
* @throws InterruptedException if operation is interrupted
62
*/
63
public static void mkdirs(ZooKeeper zookeeper, String path) throws KeeperException, InterruptedException;
64
65
/**
66
* Create directories with control over creating the last node
67
* @param zookeeper ZooKeeper client instance
68
* @param path Path to create
69
* @param makeLastNode Whether to create the final path component
70
* @throws KeeperException if ZooKeeper operation fails
71
* @throws InterruptedException if operation is interrupted
72
*/
73
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode) throws KeeperException, InterruptedException;
74
75
/**
76
* Create directories with custom ACL provider
77
* @param zookeeper ZooKeeper client instance
78
* @param path Path to create
79
* @param makeLastNode Whether to create the final path component
80
* @param aclProvider ACL provider for created nodes
81
* @throws KeeperException if ZooKeeper operation fails
82
* @throws InterruptedException if operation is interrupted
83
*/
84
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider) throws KeeperException, InterruptedException;
85
86
/**
87
* Create directories with container support control
88
* @param zookeeper ZooKeeper client instance
89
* @param path Path to create
90
* @param makeLastNode Whether to create the final path component
91
* @param aclProvider ACL provider for created nodes
92
* @param asContainers Whether to create container nodes (if supported)
93
* @throws KeeperException if ZooKeeper operation fails
94
* @throws InterruptedException if operation is interrupted
95
*/
96
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider, boolean asContainers) throws KeeperException, InterruptedException;
97
98
/**
99
* Delete all children of a node, optionally deleting the node itself
100
* @param zookeeper ZooKeeper client instance
101
* @param path Path whose children should be deleted
102
* @param deleteSelf Whether to delete the path itself after children
103
* @throws KeeperException if ZooKeeper operation fails
104
* @throws InterruptedException if operation is interrupted
105
*/
106
public static void deleteChildren(ZooKeeper zookeeper, String path, boolean deleteSelf) throws KeeperException, InterruptedException;
107
108
/**
109
* Get sorted list of child nodes
110
* @param zookeeper ZooKeeper client instance
111
* @param path Parent path
112
* @return Sorted list of child node names
113
* @throws KeeperException if ZooKeeper operation fails
114
* @throws InterruptedException if operation is interrupted
115
*/
116
public static List<String> getSortedChildren(ZooKeeper zookeeper, String path) throws KeeperException, InterruptedException;
117
118
/**
119
* Get the appropriate CreateMode for container nodes (ZK 3.5+)
120
* @return CreateMode.CONTAINER if supported, otherwise CreateMode.PERSISTENT
121
*/
122
public static CreateMode getContainerCreateMode();
123
124
/**
125
* Check if ZooKeeper version supports container nodes
126
* @return true if container nodes are supported
127
*/
128
public static boolean hasContainerSupport();
129
130
/**
131
* Fix path for namespace by prepending namespace if needed
132
* @param namespace Namespace to apply (can be null)
133
* @param path Path to fix
134
* @return Path with namespace applied
135
*/
136
public static String fixForNamespace(String namespace, String path);
137
138
/**
139
* Fix path for namespace with sequential node support
140
* @param namespace Namespace to apply (can be null)
141
* @param path Path to fix
142
* @param isSequential Whether path will be used for sequential nodes
143
* @return Path with namespace applied
144
*/
145
public static String fixForNamespace(String namespace, String path, boolean isSequential);
146
147
/**
148
* Extract sequential suffix from a sequential node path
149
* @param path Path with potential sequential suffix
150
* @return Sequential suffix string, or null if not sequential
151
*/
152
public static String extractSequentialSuffix(String path);
153
}
154
```
155
156
**Usage Examples:**
157
158
```java
159
import org.apache.curator.utils.ZKPaths;
160
import org.apache.zookeeper.ZooKeeper;
161
162
// Path construction
163
String fullPath = ZKPaths.makePath("/app", "config"); // "/app/config"
164
String rootPath = ZKPaths.makePath(null, "root"); // "/root"
165
String nestedPath = ZKPaths.makePath("/a/b", "c"); // "/a/b/c"
166
167
// Path parsing
168
String nodeName = ZKPaths.getNodeFromPath("/app/config/database"); // "database"
169
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode("/app/config");
170
// pathAndNode.getPath() returns "/app", pathAndNode.getNode() returns "config"
171
172
List<String> components = ZKPaths.split("/app/config/database");
173
// Returns ["app", "config", "database"]
174
175
// Tree operations with ZooKeeper client
176
ZooKeeper zk = client.getZooKeeper();
177
178
// Create directory structure
179
ZKPaths.mkdirs(zk, "/app/config/database"); // Creates /app, /app/config, /app/config/database
180
181
// Clean up children
182
ZKPaths.deleteChildren(zk, "/app/config", false); // Delete children but keep /app/config
183
ZKPaths.deleteChildren(zk, "/temp", true); // Delete /temp and all children
184
185
// Get sorted children
186
List<String> children = ZKPaths.getSortedChildren(zk, "/app");
187
// Returns alphabetically sorted list of child node names
188
```
189
190
### PathAndNode Container Class
191
192
Container class for holding a path split into parent directory and node name components.
193
194
```java { .api }
195
/**
196
* Container for path and node name pairs
197
*/
198
public static class ZKPaths.PathAndNode {
199
/**
200
* Get the parent path component
201
* @return Parent path (null for root-level nodes)
202
*/
203
public String getPath();
204
205
/**
206
* Get the node name component
207
* @return Node name (last component of original path)
208
*/
209
public String getNode();
210
}
211
```
212
213
**Usage Examples:**
214
215
```java
216
// Split path into components
217
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode("/app/config/database");
218
219
String parentPath = pathAndNode.getPath(); // "/app/config"
220
String nodeName = pathAndNode.getNode(); // "database"
221
222
// Handle root-level paths
223
ZKPaths.PathAndNode rootNode = ZKPaths.getPathAndNode("/app");
224
String rootParent = rootNode.getPath(); // null (no parent)
225
String rootName = rootNode.getNode(); // "app"
226
```
227
228
### PathUtils Class
229
230
Path validation utilities ensuring ZooKeeper path compliance and safety.
231
232
```java { .api }
233
/**
234
* Utility class for ZooKeeper path validation
235
*/
236
public class PathUtils {
237
/**
238
* Validate a ZooKeeper path and return normalized version
239
* @param path Path to validate
240
* @return Validated and normalized path
241
* @throws IllegalArgumentException if path is invalid
242
*/
243
public static String validatePath(String path) throws IllegalArgumentException;
244
245
/**
246
* Validate a ZooKeeper path with sequential node support
247
* @param path Path to validate
248
* @param isSequential Whether path will be used for sequential nodes
249
* @throws IllegalArgumentException if path is invalid
250
*/
251
public static void validatePath(String path, boolean isSequential) throws IllegalArgumentException;
252
}
253
```
254
255
**Usage Examples:**
256
257
```java
258
import org.apache.curator.utils.PathUtils;
259
260
try {
261
// Validate and normalize paths
262
String validPath = PathUtils.validatePath("/app/config"); // OK
263
String normalizedPath = PathUtils.validatePath("//app///config"); // Returns "/app/config"
264
265
// Validate for sequential nodes
266
PathUtils.validatePath("/app/counters/counter-", true); // OK for sequential
267
268
// These would throw IllegalArgumentException:
269
// PathUtils.validatePath(""); // Empty path
270
// PathUtils.validatePath("no-slash"); // Must start with /
271
// PathUtils.validatePath("/app/"); // Cannot end with / (except root)
272
273
} catch (IllegalArgumentException e) {
274
System.err.println("Invalid path: " + e.getMessage());
275
}
276
```
277
278
### EnsurePath Class (Deprecated)
279
280
Legacy utility for ensuring path existence - superseded by `ZKPaths.mkdirs()`.
281
282
```java { .api }
283
/**
284
* @deprecated Use ZKPaths.mkdirs() instead
285
* Utility to ensure ZooKeeper path existence
286
*/
287
@Deprecated
288
public class EnsurePath {
289
/**
290
* Create EnsurePath instance for a specific path
291
* @param path Path to ensure exists
292
*/
293
public EnsurePath(String path);
294
295
/**
296
* Ensure the path exists, creating parent directories as needed
297
* @param client CuratorZookeeperClient instance
298
* @throws Exception if path creation fails
299
*/
300
public void ensure(CuratorZookeeperClient client) throws Exception;
301
302
/**
303
* Create EnsurePath instance excluding the last path component
304
* @return EnsurePath for parent directory only
305
*/
306
public EnsurePath excludingLast();
307
}
308
```
309
310
## Path Utility Patterns
311
312
### Safe Path Construction
313
314
```java
315
// Always use ZKPaths.makePath() for path construction
316
String configPath = ZKPaths.makePath("/app", "config");
317
String dbConfigPath = ZKPaths.makePath(configPath, "database");
318
String tablePath = ZKPaths.makePath(dbConfigPath, "users");
319
320
// Avoid manual string concatenation:
321
// String badPath = "/app" + "/" + "config"; // DON'T DO THIS
322
```
323
324
### Directory Tree Creation
325
326
```java
327
// Create entire directory tree in one call
328
ZKPaths.mkdirs(zookeeper, "/app/config/database/connection");
329
330
// This creates all intermediate paths:
331
// /app
332
// /app/config
333
// /app/config/database
334
// /app/config/database/connection
335
```
336
337
### Safe Tree Cleanup
338
339
```java
340
// Clean up temporary directories
341
String tempPath = "/temp/processing/" + UUID.randomUUID();
342
343
try {
344
// Create and use temp directory
345
ZKPaths.mkdirs(zookeeper, tempPath);
346
// ... do work ...
347
} finally {
348
// Clean up: delete temp directory and all contents
349
ZKPaths.deleteChildren(zookeeper, tempPath, true);
350
}
351
```
352
353
### Container Node Support
354
355
```java
356
// Use container nodes when available for automatic cleanup
357
CreateMode containerMode = ZKPaths.getContainerCreateMode();
358
359
if (ZKPaths.hasContainerSupport()) {
360
// ZooKeeper 3.5+ with container support
361
zookeeper.create("/app/locks", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, containerMode);
362
} else {
363
// Fallback for older ZooKeeper versions
364
zookeeper.create("/app/locks", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
365
}
366
```
367
368
## Utility Classes
369
370
### CloseableUtils Class
371
372
Utility for safely closing resources, providing functionality removed from Guava v16.0.
373
374
```java { .api }
375
/**
376
* Utility class for safely closing resources without throwing exceptions
377
*/
378
public class CloseableUtils {
379
/**
380
* Close a resource quietly, swallowing any IOException
381
* @param closeable Resource to close (can be null)
382
*/
383
public static void closeQuietly(Closeable closeable);
384
}
385
```
386
387
### ThreadUtils Class
388
389
Thread management and factory utilities for creating properly configured threads.
390
391
```java { .api }
392
/**
393
* Utility class for thread management and factory creation
394
*/
395
public class ThreadUtils {
396
/**
397
* Check if exception represents an interruption and restore thread state
398
* @param e Exception to check
399
* @return true if exception was InterruptedException
400
*/
401
public static boolean checkInterrupted(Throwable e);
402
403
/**
404
* Create single thread executor with named threads
405
* @param processName Name prefix for threads
406
* @return ExecutorService with single thread
407
*/
408
public static ExecutorService newSingleThreadExecutor(String processName);
409
410
/**
411
* Create fixed thread pool with named threads
412
* @param qty Number of threads in pool
413
* @param processName Name prefix for threads
414
* @return ExecutorService with fixed thread pool
415
*/
416
public static ExecutorService newFixedThreadPool(int qty, String processName);
417
418
/**
419
* Create single thread scheduled executor with named threads
420
* @param processName Name prefix for threads
421
* @return ScheduledExecutorService with single thread
422
*/
423
public static ScheduledExecutorService newSingleThreadScheduledExecutor(String processName);
424
425
/**
426
* Create scheduled thread pool with named threads
427
* @param qty Number of threads in pool
428
* @param processName Name prefix for threads
429
* @return ScheduledExecutorService with thread pool
430
*/
431
public static ScheduledExecutorService newFixedThreadScheduledPool(int qty, String processName);
432
433
/**
434
* Create thread factory with Curator naming conventions
435
* @param processName Process name for thread naming
436
* @return ThreadFactory for creating named daemon threads
437
*/
438
public static ThreadFactory newThreadFactory(String processName);
439
440
/**
441
* Create generic thread factory
442
* @param processName Process name for thread naming
443
* @return ThreadFactory for creating named daemon threads
444
*/
445
public static ThreadFactory newGenericThreadFactory(String processName);
446
447
/**
448
* Generate process name from class
449
* @param clazz Class to generate name from
450
* @return Simple class name for process naming
451
*/
452
public static String getProcessName(Class<?> clazz);
453
}
454
```
455
456
### ExceptionAccumulator Class
457
458
Utility for collecting and managing multiple exceptions during batch operations.
459
460
```java { .api }
461
/**
462
* Utility for accumulating exceptions from multiple operations
463
*/
464
public class ExceptionAccumulator {
465
/**
466
* Create new exception accumulator
467
*/
468
public ExceptionAccumulator();
469
470
/**
471
* Add exception to accumulator
472
* @param e Exception to add (null exceptions are ignored)
473
*/
474
public void add(Throwable e);
475
476
/**
477
* Get accumulated exception, if any
478
* @return Exception combining all accumulated exceptions, or null if none
479
*/
480
public Exception getCombinedException();
481
}
482
```
483
484
### CloseableExecutorService Class
485
486
Managed executor service that implements Closeable for proper resource management.
487
488
```java { .api }
489
/**
490
* ExecutorService wrapper that implements Closeable for automatic resource management
491
*/
492
public class CloseableExecutorService implements Closeable {
493
/**
494
* Create closeable executor service
495
* @param executorService Underlying executor service to wrap
496
*/
497
public CloseableExecutorService(ExecutorService executorService);
498
499
/**
500
* Get the underlying executor service
501
* @return Wrapped ExecutorService instance
502
*/
503
public ExecutorService getExecutorService();
504
505
/**
506
* Close executor service, shutting down gracefully
507
*/
508
@Override
509
public void close();
510
}
511
```
512
513
### CloseableScheduledExecutorService Class
514
515
Managed scheduled executor service extending CloseableExecutorService.
516
517
```java { .api }
518
/**
519
* ScheduledExecutorService wrapper that implements Closeable for automatic resource management
520
*/
521
public class CloseableScheduledExecutorService extends CloseableExecutorService {
522
/**
523
* Create closeable scheduled executor service
524
* @param scheduledExecutorService Underlying scheduled executor to wrap
525
*/
526
public CloseableScheduledExecutorService(ScheduledExecutorService scheduledExecutorService);
527
528
/**
529
* Get the underlying scheduled executor service
530
* @return Wrapped ScheduledExecutorService instance
531
*/
532
public ScheduledExecutorService getScheduledExecutorService();
533
}
534
```
535
536
### Path Parsing and Analysis
537
538
```java
539
String fullPath = "/app/config/database/connection";
540
541
// Extract components
542
String nodeName = ZKPaths.getNodeFromPath(fullPath); // "connection"
543
List<String> components = ZKPaths.split(fullPath); // ["app", "config", "database", "connection"]
544
545
// Split into parent and child
546
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode(fullPath);
547
String parentPath = pathAndNode.getPath(); // "/app/config/database"
548
String childName = pathAndNode.getNode(); // "connection"
549
550
// Validate before use
551
try {
552
PathUtils.validatePath(fullPath);
553
// Path is valid, safe to use
554
} catch (IllegalArgumentException e) {
555
// Handle invalid path
556
}
557
```