0
# Utilities
1
2
Quarkus Core Deployment provides a comprehensive set of utility classes for common deployment-time operations including reflection, file system operations, service loading, artifact handling, container runtime detection, and various helper functions that support the build and deployment process.
3
4
## Core Imports
5
6
```java
7
// Reflection utilities
8
import io.quarkus.deployment.util.ReflectUtil;
9
import io.quarkus.deployment.util.ClassUtil;
10
import io.quarkus.deployment.util.DeploymentUtil;
11
12
// Service loading utilities
13
import io.quarkus.deployment.util.ServiceUtil;
14
15
// File system utilities
16
import io.quarkus.deployment.util.FileUtil;
17
import io.quarkus.deployment.util.IoUtil;
18
import io.quarkus.deployment.util.PathUtil;
19
20
// Artifact and dependency utilities
21
import io.quarkus.deployment.util.ArtifactInfoUtil;
22
import io.quarkus.deployment.util.ArtifactResultBuilder;
23
24
// Container runtime utilities
25
import io.quarkus.deployment.util.ContainerRuntimeUtil;
26
import io.quarkus.deployment.util.ProcessUtil;
27
28
// Hashing and validation utilities
29
import io.quarkus.deployment.util.HashUtil;
30
import io.quarkus.deployment.util.StringUtil;
31
32
// Bean and proxy utilities
33
import io.quarkus.deployment.bean.BeanArchiveIndex;
34
import io.quarkus.deployment.bean.JavaBeanUtil;
35
import io.quarkus.deployment.proxy.ProxyFactory;
36
37
// Type parsing and handling
38
import io.quarkus.deployment.types.ParsedType;
39
import io.quarkus.deployment.types.TypeParser;
40
41
// Code generation framework
42
import io.quarkus.deployment.CodeGenProvider;
43
import io.quarkus.deployment.CodeGenContext;
44
import io.quarkus.deployment.CodeGenerator;
45
import io.quarkus.bootstrap.prebuild.CodeGenException;
46
```
47
48
## Reflection Utilities
49
50
### ReflectUtil
51
52
Comprehensive reflection utilities for deployment-time introspection and manipulation.
53
54
```java { .api }
55
class ReflectUtil {
56
/**
57
* Gets a method by name and parameter types
58
*/
59
static Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes)
60
throws NoSuchMethodException;
61
62
/**
63
* Gets a field by name
64
*/
65
static Field getField(Class<?> clazz, String name)
66
throws NoSuchFieldException;
67
68
/**
69
* Creates a new instance using default constructor
70
*/
71
static <T> T newInstance(Class<T> clazz);
72
73
/**
74
* Creates a new instance using constructor with parameters
75
*/
76
static <T> T newInstance(Class<T> clazz, Class<?>[] paramTypes, Object... args);
77
78
/**
79
* Invokes a method on an instance
80
*/
81
static Object invoke(Method method, Object instance, Object... args);
82
83
/**
84
* Invokes a static method
85
*/
86
static Object invokeStatic(Method method, Object... args);
87
88
/**
89
* Gets or sets a field value
90
*/
91
static Object getFieldValue(Field field, Object instance);
92
static void setFieldValue(Field field, Object instance, Object value);
93
94
/**
95
* Finds all methods with given annotation
96
*/
97
static List<Method> getMethodsWithAnnotation(Class<?> clazz,
98
Class<? extends Annotation> annotation);
99
100
/**
101
* Finds all fields with given annotation
102
*/
103
static List<Field> getFieldsWithAnnotation(Class<?> clazz,
104
Class<? extends Annotation> annotation);
105
106
/**
107
* Gets raw class from parameterized type
108
*/
109
static Class<?> getRawType(Type type);
110
111
/**
112
* Checks if class is assignable from type
113
*/
114
static boolean isAssignableFrom(Class<?> clazz, Type type);
115
}
116
```
117
118
**Usage Examples:**
119
120
```java
121
@BuildStep
122
void processReflectiveAccess(CombinedIndexBuildItem index,
123
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
124
125
// Find all classes with @Entity annotation
126
Collection<AnnotationInstance> entities = index.getIndex()
127
.getAnnotations(DotName.createSimple("javax.persistence.Entity"));
128
129
for (AnnotationInstance entity : entities) {
130
String className = entity.target().asClass().name().toString();
131
132
try {
133
Class<?> entityClass = Class.forName(className);
134
135
// Register class for reflection
136
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(entityClass)
137
.constructors()
138
.methods()
139
.fields()
140
.build());
141
142
// Check for getter/setter methods
143
List<Method> getters = ReflectUtil.getMethodsWithAnnotation(
144
entityClass, Getter.class);
145
List<Method> setters = ReflectUtil.getMethodsWithAnnotation(
146
entityClass, Setter.class);
147
148
} catch (ClassNotFoundException e) {
149
// Handle missing class
150
}
151
}
152
}
153
154
@BuildStep
155
@Record(ExecutionTime.STATIC_INIT)
156
void setupReflection(MyRecorder recorder) {
157
// Use reflection to configure framework
158
recorder.configure(ReflectUtil.class);
159
}
160
```
161
162
## Service Loading Utilities
163
164
### ServiceUtil
165
166
Utilities for loading and managing service implementations via ServiceLoader.
167
168
```java { .api }
169
class ServiceUtil {
170
/**
171
* Loads all implementations of a service from classpath
172
*/
173
static <T> List<T> classPathServices(Class<T> serviceType, ClassLoader classLoader);
174
175
/**
176
* Loads first implementation of a service
177
*/
178
static <T> Optional<T> classPathService(Class<T> serviceType, ClassLoader classLoader);
179
180
/**
181
* Loads services with specific context class loader
182
*/
183
static <T> List<T> loadServices(Class<T> serviceType, ClassLoader classLoader);
184
185
/**
186
* Gets service implementation classes (not instances)
187
*/
188
static <T> List<Class<? extends T>> loadServiceClasses(Class<T> serviceType,
189
ClassLoader classLoader);
190
191
/**
192
* Checks if service implementation exists
193
*/
194
static boolean hasService(Class<?> serviceType, ClassLoader classLoader);
195
196
/**
197
* Creates service loader for given type
198
*/
199
static <T> ServiceLoader<T> load(Class<T> serviceType, ClassLoader classLoader);
200
}
201
```
202
203
**Usage Examples:**
204
205
```java
206
@BuildStep
207
void discoverCompilationProviders(BuildProducer<CompilationProviderBuildItem> providers) {
208
209
// Load all compilation providers from classpath
210
List<CompilationProvider> compilationProviders =
211
ServiceUtil.classPathServices(CompilationProvider.class,
212
Thread.currentThread().getContextClassLoader());
213
214
for (CompilationProvider provider : compilationProviders) {
215
providers.produce(new CompilationProviderBuildItem(provider.getClass()));
216
}
217
}
218
219
@BuildStep
220
void configureCodeGenerators(BuildProducer<CodeGenProviderBuildItem> codeGenProviders) {
221
222
// Check if specific code generator is available
223
if (ServiceUtil.hasService(GrpcCodeGenProvider.class,
224
Thread.currentThread().getContextClassLoader())) {
225
226
Optional<GrpcCodeGenProvider> provider = ServiceUtil.classPathService(
227
GrpcCodeGenProvider.class,
228
Thread.currentThread().getContextClassLoader());
229
230
if (provider.isPresent()) {
231
codeGenProviders.produce(new CodeGenProviderBuildItem(provider.get()));
232
}
233
}
234
}
235
```
236
237
## File System Utilities
238
239
### FileUtil
240
241
Comprehensive file system operations for deployment processing.
242
243
```java { .api }
244
class FileUtil {
245
/**
246
* Copies a file from source to target
247
*/
248
static void copyFile(Path source, Path target) throws IOException;
249
250
/**
251
* Copies directory recursively
252
*/
253
static void copyDirectory(Path source, Path target) throws IOException;
254
255
/**
256
* Moves file or directory
257
*/
258
static void moveFile(Path source, Path target) throws IOException;
259
260
/**
261
* Deletes file or directory recursively
262
*/
263
static void deleteDirectory(Path directory) throws IOException;
264
static boolean deleteIfExists(Path path) throws IOException;
265
266
/**
267
* Creates directories if they don't exist
268
*/
269
static Path ensureDirectoryExists(Path directory) throws IOException;
270
271
/**
272
* Checks if directory is empty
273
*/
274
static boolean isDirectoryEmpty(Path directory) throws IOException;
275
276
/**
277
* Gets relative path between two paths
278
*/
279
static String relativize(Path base, Path child);
280
281
/**
282
* Reads file content as string
283
*/
284
static String readFileToString(Path file, StandardCharsets charset) throws IOException;
285
286
/**
287
* Writes string content to file
288
*/
289
static void writeStringToFile(Path file, String content, StandardCharsets charset)
290
throws IOException;
291
292
/**
293
* Lists files in directory with filter
294
*/
295
static List<Path> listFiles(Path directory, String... extensions) throws IOException;
296
297
/**
298
* Finds files recursively with pattern
299
*/
300
static List<Path> findFiles(Path directory, String pattern) throws IOException;
301
}
302
```
303
304
### IoUtil
305
306
Lower-level I/O utilities and stream operations.
307
308
```java { .api }
309
class IoUtil {
310
/**
311
* Reads all bytes from input stream
312
*/
313
static byte[] readBytes(InputStream inputStream) throws IOException;
314
315
/**
316
* Copies input stream to output stream
317
*/
318
static long copy(InputStream input, OutputStream output) throws IOException;
319
320
/**
321
* Reads properties from input stream
322
*/
323
static Properties readProperties(InputStream inputStream) throws IOException;
324
325
/**
326
* Creates buffered reader for path
327
*/
328
static BufferedReader newBufferedReader(Path path, Charset charset) throws IOException;
329
330
/**
331
* Creates buffered writer for path
332
*/
333
static BufferedWriter newBufferedWriter(Path path, Charset charset) throws IOException;
334
335
/**
336
* Safely closes multiple closeables
337
*/
338
static void safeClose(Closeable... closeables);
339
}
340
```
341
342
**Usage Examples:**
343
344
```java
345
@BuildStep
346
void processConfigurationFiles(ApplicationArchivesBuildItem archives,
347
BuildProducer<ConfigurationBuildItem> config) throws IOException {
348
349
for (ApplicationArchive archive : archives.getAllApplicationArchives()) {
350
Path resourceDir = archive.apply(tree -> {
351
OpenPathTree.PathVisit visit = tree.visit("META-INF");
352
return visit != null ? visit.getPath() : null;
353
});
354
355
if (resourceDir != null) {
356
// Find all .properties files
357
List<Path> propFiles = FileUtil.findFiles(resourceDir, "*.properties");
358
359
for (Path propFile : propFiles) {
360
Properties props = new Properties();
361
try (InputStream is = Files.newInputStream(propFile)) {
362
props = IoUtil.readProperties(is);
363
}
364
365
// Process properties
366
processConfigProperties(props);
367
}
368
}
369
}
370
}
371
372
@BuildStep
373
void generateConfigurationFiles(ConfigurationBuildItem config,
374
BuildProducer<GeneratedResourceBuildItem> resources)
375
throws IOException {
376
377
Path tempDir = Files.createTempDirectory("quarkus-config");
378
try {
379
// Generate configuration file
380
Path configFile = tempDir.resolve("runtime-config.properties");
381
382
Properties runtimeProps = new Properties();
383
config.getPropertyNames().forEach(name -> {
384
runtimeProps.setProperty(name, config.getValue(name, String.class).orElse(""));
385
});
386
387
try (OutputStream os = Files.newOutputStream(configFile)) {
388
runtimeProps.store(os, "Generated runtime configuration");
389
}
390
391
// Read generated content
392
byte[] content = FileUtil.readFileToString(configFile, StandardCharsets.UTF_8)
393
.getBytes(StandardCharsets.UTF_8);
394
395
resources.produce(new GeneratedResourceBuildItem(
396
"META-INF/quarkus-runtime-config.properties", content));
397
398
} finally {
399
FileUtil.deleteDirectory(tempDir);
400
}
401
}
402
```
403
404
## Code Generation Framework
405
406
Quarkus provides a comprehensive code generation framework that allows extensions to generate source code during the build process. This system enables build-time code generation from various input formats including protobuf, OpenAPI, GraphQL schemas, and custom domain-specific languages.
407
408
### CodeGenProvider
409
410
Interface for implementing custom code generators that run during the generate-sources phase.
411
412
```java { .api }
413
interface CodeGenProvider {
414
/**
415
* Unique identifier for this code generator, corresponds to the directory
416
* name in generated-sources
417
*/
418
String providerId();
419
420
/**
421
* File extensions that this code generator can process
422
*/
423
String[] inputExtensions();
424
425
/**
426
* Name of the input directory relative to source roots
427
* For example: src/main/{inputDirectory} and src/test/{inputDirectory}
428
*/
429
String inputDirectory();
430
431
/**
432
* Optional absolute path override for input directory
433
* Called after init(), returning null uses default inputDirectory()
434
*/
435
default Path getInputDirectory() { return null; }
436
437
/**
438
* Initialize the provider with application model and build properties
439
*/
440
default void init(ApplicationModel model, Map<String, String> properties) {}
441
442
/**
443
* Trigger code generation process
444
* @param context Code generation context with paths and configuration
445
* @return true if any files were generated or modified
446
*/
447
boolean trigger(CodeGenContext context) throws CodeGenException;
448
449
/**
450
* Determine if code generator should run based on source directory and config
451
*/
452
default boolean shouldRun(Path sourceDir, Config config) {
453
return Files.isDirectory(sourceDir);
454
}
455
}
456
```
457
458
### CodeGenContext
459
460
Context object providing all necessary information for code generation.
461
462
```java { .api }
463
class CodeGenContext {
464
/**
465
* Application model with dependency information
466
*/
467
ApplicationModel applicationModel();
468
469
/**
470
* Target directory for generated output
471
* Typically: target/generated-sources/{providerId}
472
*/
473
Path outDir();
474
475
/**
476
* Working directory (typically project build directory)
477
*/
478
Path workDir();
479
480
/**
481
* Input directory containing source files to process
482
* Typically: src/main/{inputDirectory} or src/test/{inputDirectory}
483
*/
484
Path inputDir();
485
486
/**
487
* Whether spawned processes should redirect I/O streams
488
*/
489
boolean shouldRedirectIO();
490
491
/**
492
* Build-time configuration
493
*/
494
Config config();
495
496
/**
497
* Whether generation is for tests (true) or main sources (false)
498
*/
499
boolean test();
500
}
501
```
502
503
### CodeGenerator
504
505
Static utility class for initializing and executing code generators.
506
507
```java { .api }
508
class CodeGenerator {
509
/**
510
* Initialize and run all code generators for given parameters
511
*/
512
static void initAndRun(
513
QuarkusClassLoader classLoader,
514
PathCollection sourceParentDirs,
515
Path generatedSourcesDir,
516
Path buildDir,
517
Consumer<Path> sourceRegistrar,
518
ApplicationModel appModel,
519
Properties properties,
520
String launchMode,
521
boolean test
522
) throws CodeGenException;
523
524
/**
525
* Trigger a specific code generator
526
*/
527
static boolean trigger(
528
ClassLoader deploymentClassLoader,
529
CodeGenData data,
530
ApplicationModel appModel,
531
Config config,
532
boolean test
533
) throws CodeGenException;
534
535
/**
536
* Get build-time configuration for code generation
537
*/
538
static Config getConfig(
539
ApplicationModel appModel,
540
LaunchMode launchMode,
541
Properties buildSystemProps,
542
QuarkusClassLoader deploymentClassLoader
543
) throws CodeGenException;
544
}
545
```
546
547
**Usage Examples:**
548
549
```java
550
/**
551
* Example: Protocol Buffer code generator
552
*/
553
public class ProtobufCodeGenProvider implements CodeGenProvider {
554
555
@Override
556
public String providerId() {
557
return "protobuf";
558
}
559
560
@Override
561
public String[] inputExtensions() {
562
return new String[]{"proto"};
563
}
564
565
@Override
566
public String inputDirectory() {
567
return "proto";
568
}
569
570
@Override
571
public void init(ApplicationModel model, Map<String, String> properties) {
572
// Initialize protoc compiler path, output options, etc.
573
this.protocPath = properties.get("protoc.path");
574
this.javaOut = Boolean.parseBoolean(properties.get("protobuf.java.out"));
575
}
576
577
@Override
578
public boolean trigger(CodeGenContext context) throws CodeGenException {
579
Path inputDir = context.inputDir();
580
Path outputDir = context.outDir();
581
582
if (!Files.exists(inputDir)) {
583
return false;
584
}
585
586
boolean generated = false;
587
try (Stream<Path> protoFiles = Files.walk(inputDir)) {
588
List<Path> protoSources = protoFiles
589
.filter(p -> p.toString().endsWith(".proto"))
590
.collect(Collectors.toList());
591
592
if (!protoSources.isEmpty()) {
593
// Run protoc compiler
594
List<String> command = List.of(
595
protocPath,
596
"--java_out=" + outputDir,
597
"--proto_path=" + inputDir
598
);
599
command.addAll(protoSources.stream()
600
.map(Path::toString)
601
.collect(Collectors.toList()));
602
603
ProcessBuilder pb = new ProcessBuilder(command);
604
if (context.shouldRedirectIO()) {
605
pb.inheritIO();
606
}
607
608
Process process = pb.start();
609
int exitCode = process.waitFor();
610
611
if (exitCode != 0) {
612
throw new CodeGenException("protoc compilation failed with exit code: " + exitCode);
613
}
614
615
generated = true;
616
}
617
} catch (IOException | InterruptedException e) {
618
throw new CodeGenException("Protocol buffer code generation failed", e);
619
}
620
621
return generated;
622
}
623
624
@Override
625
public boolean shouldRun(Path sourceDir, Config config) {
626
return Files.isDirectory(sourceDir) &&
627
config.getOptionalValue("quarkus.protobuf.enabled", Boolean.class).orElse(true);
628
}
629
}
630
631
/**
632
* Build step that configures code generation
633
*/
634
@BuildStep
635
void configureCodeGeneration(BuildProducer<CodeGenProviderBuildItem> codeGenProviders) {
636
codeGenProviders.produce(new CodeGenProviderBuildItem(ProtobufCodeGenProvider.class.getName()));
637
}
638
639
/**
640
* Integration with development mode
641
*/
642
@BuildStep
643
void setupDevModeCodeGeneration(LaunchModeBuildItem launchMode,
644
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
645
if (launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT) {
646
// Watch .proto files for changes
647
watchedFiles.produce(HotDeploymentWatchedFileBuildItem.builder()
648
.setLocationGlob("src/main/proto/**/*.proto")
649
.setRestartNeeded(true)
650
.build());
651
}
652
}
653
```
654
655
## Artifact and Dependency Utilities
656
657
### ArtifactInfoUtil
658
659
Utilities for working with Maven artifacts and dependency information.
660
661
```java { .api }
662
class ArtifactInfoUtil {
663
/**
664
* Parses artifact coordinates from string
665
*/
666
static ArtifactKey parseArtifactKey(String coords);
667
668
/**
669
* Creates artifact key from components
670
*/
671
static ArtifactKey createArtifactKey(String groupId, String artifactId,
672
String classifier, String type);
673
674
/**
675
* Gets artifact version from dependency
676
*/
677
static String getArtifactVersion(ResolvedDependency dependency);
678
679
/**
680
* Checks if artifact matches pattern
681
*/
682
static boolean matches(ArtifactKey artifact, String pattern);
683
684
/**
685
* Gets all transitive dependencies
686
*/
687
static Set<ResolvedDependency> getTransitiveDependencies(
688
ResolvedDependency rootDependency,
689
boolean includeOptional
690
);
691
692
/**
693
* Filters dependencies by scope
694
*/
695
static List<ResolvedDependency> filterByScope(
696
List<ResolvedDependency> dependencies,
697
String... scopes
698
);
699
700
/**
701
* Creates dependency tree string representation
702
*/
703
static String createDependencyTree(ApplicationModel applicationModel);
704
}
705
```
706
707
**Usage Examples:**
708
709
```java
710
@BuildStep
711
void analyzeDependencies(ApplicationArchivesBuildItem archives,
712
BuildProducer<DependencyAnalysisBuildItem> analysis) {
713
714
List<ResolvedDependency> runtimeDeps = new ArrayList<>();
715
716
for (ApplicationArchive archive : archives.getApplicationArchives()) {
717
ResolvedDependency dependency = archive.getResolvedDependency();
718
719
if (dependency != null) {
720
// Filter runtime dependencies
721
if (ArtifactInfoUtil.filterByScope(List.of(dependency), "compile", "runtime")
722
.contains(dependency)) {
723
runtimeDeps.add(dependency);
724
}
725
726
// Check for specific artifacts
727
if (ArtifactInfoUtil.matches(dependency.getKey(), "org.hibernate.*")) {
728
// Handle Hibernate dependency
729
handleHibernateDependency(dependency);
730
}
731
}
732
}
733
734
analysis.produce(new DependencyAnalysisBuildItem(runtimeDeps));
735
}
736
```
737
738
## Container Runtime Utilities
739
740
### ContainerRuntimeUtil
741
742
Utilities for detecting and working with container runtimes like Docker and Podman.
743
744
```java { .api }
745
class ContainerRuntimeUtil {
746
/**
747
* Detects available container runtime
748
*/
749
static Optional<ContainerRuntime> detectContainerRuntime();
750
751
/**
752
* Checks if container runtime is available
753
*/
754
static boolean isContainerRuntimeAvailable();
755
756
/**
757
* Gets container runtime executable path
758
*/
759
static Optional<String> getContainerRuntimeExecutable();
760
761
/**
762
* Executes container command
763
*/
764
static ProcessResult executeContainerCommand(List<String> command,
765
Path workingDirectory)
766
throws IOException;
767
768
/**
769
* Builds container image
770
*/
771
static ProcessResult buildImage(Path dockerfile,
772
String imageName,
773
Path context) throws IOException;
774
775
/**
776
* Runs container
777
*/
778
static ProcessResult runContainer(String imageName,
779
Map<String, String> env,
780
List<String> ports,
781
List<String> volumes) throws IOException;
782
783
enum ContainerRuntime {
784
DOCKER("docker"),
785
PODMAN("podman");
786
787
String getExecutableName();
788
List<String> getDefaultOptions();
789
}
790
}
791
```
792
793
### ProcessUtil
794
795
Utilities for executing external processes.
796
797
```java { .api }
798
class ProcessUtil {
799
/**
800
* Executes process with arguments
801
*/
802
static ProcessResult execute(List<String> command,
803
Path workingDirectory,
804
Map<String, String> environment,
805
Duration timeout) throws IOException;
806
807
/**
808
* Executes process and returns result
809
*/
810
static ProcessResult executeAndWait(String... command) throws IOException;
811
812
/**
813
* Checks if executable is available in PATH
814
*/
815
static boolean isExecutableInPath(String executable);
816
817
/**
818
* Gets executable path
819
*/
820
static Optional<Path> findExecutable(String executable);
821
822
/**
823
* Process execution result
824
*/
825
static class ProcessResult {
826
int getExitCode();
827
String getStdout();
828
String getStderr();
829
boolean isSuccess();
830
Duration getDuration();
831
}
832
}
833
```
834
835
**Usage Examples:**
836
837
```java
838
@BuildStep(onlyIf = ContainerImageRequested.class)
839
void buildContainerImage(JarBuildItem jar,
840
ImageConfig imageConfig,
841
BuildProducer<ContainerImageBuildItem> containerImage)
842
throws IOException {
843
844
if (!ContainerRuntimeUtil.isContainerRuntimeAvailable()) {
845
throw new RuntimeException("No container runtime available for image building");
846
}
847
848
ContainerRuntime runtime = ContainerRuntimeUtil.detectContainerRuntime()
849
.orElseThrow(() -> new RuntimeException("Container runtime detection failed"));
850
851
// Generate Dockerfile
852
Path dockerfile = generateDockerfile(jar, imageConfig);
853
854
// Build image
855
String imageName = "quarkus-app:latest";
856
ProcessResult result = ContainerRuntimeUtil.buildImage(
857
dockerfile,
858
imageName,
859
jar.getPath().getParent()
860
);
861
862
if (!result.isSuccess()) {
863
throw new RuntimeException("Container image build failed: " + result.getStderr());
864
}
865
866
containerImage.produce(new ContainerImageBuildItem(imageName));
867
}
868
```
869
870
## Hash and Validation Utilities
871
872
### HashUtil
873
874
Utilities for generating hashes and checksums.
875
876
```java { .api }
877
class HashUtil {
878
/**
879
* Generates SHA-256 hash of file
880
*/
881
static String sha256(Path file) throws IOException;
882
883
/**
884
* Generates SHA-256 hash of bytes
885
*/
886
static String sha256(byte[] data);
887
888
/**
889
* Generates MD5 hash of file
890
*/
891
static String md5(Path file) throws IOException;
892
893
/**
894
* Generates hash using specified algorithm
895
*/
896
static String hash(Path file, String algorithm) throws IOException;
897
898
/**
899
* Verifies file against checksum
900
*/
901
static boolean verify(Path file, String expectedHash, String algorithm) throws IOException;
902
903
/**
904
* Generates hash of directory contents
905
*/
906
static String directoryHash(Path directory, String algorithm) throws IOException;
907
}
908
```
909
910
### StringUtil
911
912
String manipulation and validation utilities.
913
914
```java { .api }
915
class StringUtil {
916
/**
917
* Converts string to kebab-case
918
*/
919
static String toKebabCase(String input);
920
921
/**
922
* Converts string to camelCase
923
*/
924
static String toCamelCase(String input);
925
926
/**
927
* Converts string to PascalCase
928
*/
929
static String toPascalCase(String input);
930
931
/**
932
* Checks if string is null or empty
933
*/
934
static boolean isNullOrEmpty(String str);
935
936
/**
937
* Checks if string is null, empty, or whitespace
938
*/
939
static boolean isNullOrBlank(String str);
940
941
/**
942
* Joins strings with delimiter
943
*/
944
static String join(String delimiter, String... parts);
945
static String join(String delimiter, Collection<String> parts);
946
947
/**
948
* Splits string and trims whitespace
949
*/
950
static List<String> splitAndTrim(String input, String delimiter);
951
952
/**
953
* Replaces placeholders in template
954
*/
955
static String substitute(String template, Map<String, String> replacements);
956
}
957
```
958
959
**Usage Examples:**
960
961
```java
962
@BuildStep
963
void generateHashManifest(JarBuildItem jar,
964
BuildProducer<GeneratedResourceBuildItem> resources) throws IOException {
965
966
// Generate hash of JAR file
967
String jarHash = HashUtil.sha256(jar.getPath());
968
969
// Generate hash of dependencies
970
Map<String, String> dependencyHashes = new HashMap<>();
971
if (jar.getLibraryDir().isPresent()) {
972
List<Path> libFiles = FileUtil.listFiles(jar.getLibraryDir().get(), "jar");
973
for (Path libFile : libFiles) {
974
String hash = HashUtil.sha256(libFile);
975
dependencyHashes.put(libFile.getFileName().toString(), hash);
976
}
977
}
978
979
// Create manifest content
980
StringBuilder manifest = new StringBuilder();
981
manifest.append("application.jar=").append(jarHash).append("\n");
982
dependencyHashes.forEach((name, hash) ->
983
manifest.append("lib/").append(name).append("=").append(hash).append("\n"));
984
985
resources.produce(new GeneratedResourceBuildItem(
986
"META-INF/quarkus-hash-manifest.txt",
987
manifest.toString().getBytes(StandardCharsets.UTF_8)
988
));
989
}
990
991
@BuildStep
992
void processConfigurationKeys(ConfigurationBuildItem config,
993
BuildProducer<ConfigKeyBuildItem> configKeys) {
994
995
// Convert configuration keys to different naming conventions
996
for (String propertyName : config.getPropertyNames()) {
997
String kebabCase = StringUtil.toKebabCase(propertyName);
998
String camelCase = StringUtil.toCamelCase(propertyName);
999
1000
configKeys.produce(new ConfigKeyBuildItem(propertyName, kebabCase, camelCase));
1001
}
1002
}
1003
```
1004
1005
## Bean and Proxy Utilities
1006
1007
### JavaBeanUtil
1008
1009
Utilities for working with JavaBeans and property introspection.
1010
1011
```java { .api }
1012
class JavaBeanUtil {
1013
/**
1014
* Gets bean properties for class
1015
*/
1016
static List<PropertyDescriptor> getBeanProperties(Class<?> beanClass);
1017
1018
/**
1019
* Checks if method is a getter
1020
*/
1021
static boolean isGetter(Method method);
1022
1023
/**
1024
* Checks if method is a setter
1025
*/
1026
static boolean isSetter(Method method);
1027
1028
/**
1029
* Gets property name from getter/setter method
1030
*/
1031
static String getPropertyName(Method method);
1032
1033
/**
1034
* Gets property type
1035
*/
1036
static Class<?> getPropertyType(PropertyDescriptor property);
1037
1038
/**
1039
* Sets property value using setter
1040
*/
1041
static void setProperty(Object bean, String propertyName, Object value);
1042
1043
/**
1044
* Gets property value using getter
1045
*/
1046
static Object getProperty(Object bean, String propertyName);
1047
}
1048
```
1049
1050
### ProxyFactory
1051
1052
Factory for creating runtime proxies for interfaces.
1053
1054
```java { .api }
1055
class ProxyFactory {
1056
/**
1057
* Creates proxy for interface with invocation handler
1058
*/
1059
static <T> T createProxy(Class<T> interfaceType,
1060
InvocationHandler handler,
1061
ClassLoader classLoader);
1062
1063
/**
1064
* Creates proxy class for interface
1065
*/
1066
static Class<?> createProxyClass(Class<?>[] interfaces,
1067
ClassLoader classLoader);
1068
1069
/**
1070
* Checks if class is a proxy class
1071
*/
1072
static boolean isProxyClass(Class<?> clazz);
1073
}
1074
```
1075
1076
**Usage Examples:**
1077
1078
```java
1079
@BuildStep
1080
void processConfigurationBeans(CombinedIndexBuildItem index,
1081
BuildProducer<ConfigBeanBuildItem> configBeans) {
1082
1083
// Find classes annotated with @ConfigProperties
1084
Collection<AnnotationInstance> configProperties = index.getIndex()
1085
.getAnnotations(DotName.createSimple("io.quarkus.arc.config.ConfigProperties"));
1086
1087
for (AnnotationInstance annotation : configProperties) {
1088
String className = annotation.target().asClass().name().toString();
1089
1090
try {
1091
Class<?> configClass = Class.forName(className);
1092
1093
// Get bean properties
1094
List<PropertyDescriptor> properties = JavaBeanUtil.getBeanProperties(configClass);
1095
1096
for (PropertyDescriptor property : properties) {
1097
String configKey = StringUtil.toKebabCase(property.getName());
1098
configBeans.produce(new ConfigBeanBuildItem(
1099
configClass,
1100
property.getName(),
1101
configKey,
1102
property.getPropertyType()
1103
));
1104
}
1105
1106
} catch (ClassNotFoundException e) {
1107
// Handle missing class
1108
}
1109
}
1110
}
1111
```