@@ -426,10 +426,56 @@ public BytecodeVerifier getBytecodeVerifier() {
426426 return bytecodeVerifier ;
427427 }
428428
429+ /**
430+ * Creates a new Builder for constructing ApplicationClassLoader instances.
431+ *
432+ * @return A new Builder with default configuration
433+ */
429434 public static Builder builder () {
430435 return new Builder ();
431436 }
432437
438+ /**
439+ * Builder for constructing ApplicationClassLoader instances with fluent API.
440+ *
441+ * <p>Supports configuration of:</p>
442+ * <ul>
443+ * <li>Multiple class sources (local, HTTP, cloud storage, databases, Maven, etc.)</li>
444+ * <li>Class caching (in-memory or filesystem-based)</li>
445+ * <li>Delegation strategy (parent-first, parent-last, custom)</li>
446+ * <li>Lifecycle listeners (logging, resource tracking, metrics)</li>
447+ * <li>Bytecode verification (checksum validation)</li>
448+ * </ul>
449+ *
450+ * <p><b>Basic Example:</b></p>
451+ * <pre>{@code
452+ * ApplicationClassLoader loader = ApplicationClassLoader.builder()
453+ * .addLocalSource("/path/to/classes")
454+ * .addRemoteSource("https://example.com/classes")
455+ * .addMavenCentral("com.example:my-lib:1.0")
456+ * .parentLast() // Load from sources before parent
457+ * .build();
458+ * }</pre>
459+ *
460+ * <p><b>Advanced Example with Caching and Listeners:</b></p>
461+ * <pre>{@code
462+ * ApplicationClassLoader loader = ApplicationClassLoader.builder()
463+ * .addRemoteJar("https://cdn.example.com/lib.jar")
464+ * .cache(new FileSystemCache(Paths.get("/tmp/class-cache")))
465+ * .addLoggingListener(true) // Verbose logging
466+ * .trackResources() // Track loaded resources
467+ * .bytecodeVerifier(new ChecksumValidator(checksumMap))
468+ * .build();
469+ * }</pre>
470+ *
471+ * <p><b>Defaults:</b></p>
472+ * <ul>
473+ * <li>parent: Thread.currentThread().getContextClassLoader()</li>
474+ * <li>delegation: ParentFirstDelegation (standard Java behavior)</li>
475+ * <li>cache: In-memory cache (if useCache=true)</li>
476+ * <li>bytecodeVerifier: null (no verification)</li>
477+ * </ul>
478+ */
433479 public static class Builder {
434480 private static final int MAX_CLASS_SOURCES = 100 ;
435481
@@ -441,11 +487,29 @@ public static class Builder {
441487 private final List <ClassLoaderLifecycleListener > listeners = new ArrayList <>();
442488 private BytecodeVerifier bytecodeVerifier ;
443489
490+ /**
491+ * Sets the parent ClassLoader for delegation.
492+ *
493+ * <p>If not set, defaults to {@code Thread.currentThread().getContextClassLoader()}.</p>
494+ *
495+ * @param parent The parent ClassLoader (null to use bootstrap classloader as parent)
496+ * @return this builder
497+ */
444498 public Builder parent (ClassLoader parent ) {
445499 this .parent = parent ;
446500 return this ;
447501 }
448502
503+ /**
504+ * Adds a custom ClassSource to the loading chain.
505+ *
506+ * <p>Sources are tried in the order they're added. Maximum 100 sources.</p>
507+ *
508+ * @param source The ClassSource to add
509+ * @return this builder
510+ * @throws NullPointerException if source is null
511+ * @throws IllegalStateException if MAX_CLASS_SOURCES (100) is exceeded
512+ */
449513 public Builder addClassSource (ClassSource source ) {
450514 Objects .requireNonNull (source , "source cannot be null" );
451515 if (classSources .size () >= MAX_CLASS_SOURCES ) {
@@ -456,18 +520,49 @@ public Builder addClassSource(ClassSource source) {
456520 return this ;
457521 }
458522
523+ /**
524+ * Adds a local filesystem directory as a class source.
525+ *
526+ * <p>Classes are loaded from {@code path + "/" + className.replace('.', '/') + ".class"}</p>
527+ *
528+ * @param path Base directory path (e.g., "/opt/app/classes" or "target/classes")
529+ * @return this builder
530+ */
459531 public Builder addLocalSource (String path ) {
460532 return addClassSource (new LocalClassSource (path ));
461533 }
462534
535+ /**
536+ * Adds an HTTP/HTTPS URL as a class source (no authentication).
537+ *
538+ * <p>Classes are loaded from {@code baseUrl + "/" + className.replace('.', '/') + ".class"}</p>
539+ *
540+ * @param baseUrl Base URL (e.g., "https://cdn.example.com/classes")
541+ * @return this builder
542+ */
463543 public Builder addRemoteSource (String baseUrl ) {
464544 return addClassSource (new RemoteClassSource (baseUrl ));
465545 }
466546
547+ /**
548+ * Adds an HTTP/HTTPS URL as a class source with authentication.
549+ *
550+ * @param baseUrl Base URL
551+ * @param authConfig Authentication configuration (basic auth, bearer token, API key, etc.)
552+ * @return this builder
553+ */
467554 public Builder addRemoteSource (String baseUrl , AuthConfig authConfig ) {
468555 return addClassSource (new RemoteClassSource (baseUrl , authConfig ));
469556 }
470557
558+ /**
559+ * Adds a remote JAR file as a class source (no authentication).
560+ *
561+ * <p>Downloads and caches the entire JAR, then loads classes from it.</p>
562+ *
563+ * @param jarUrl URL to JAR file (e.g., "https://cdn.example.com/lib-1.0.jar")
564+ * @return this builder
565+ */
471566 public Builder addRemoteJar (String jarUrl ) {
472567 return addClassSource (new JarRemoteClassSource (jarUrl ));
473568 }
@@ -488,6 +583,22 @@ public Builder addNexusMavenSource(MavenNexusClassSource source) {
488583 return addClassSource (source );
489584 }
490585
586+ /**
587+ * Adds Maven Central as a class source for specified artifacts.
588+ *
589+ * <p>Coordinates format: {@code "groupId:artifactId:version"}</p>
590+ *
591+ * <p>Example:</p>
592+ * <pre>{@code
593+ * builder.addMavenCentral(
594+ * "com.google.guava:guava:32.1.0-jre",
595+ * "org.apache.commons:commons-lang3:3.12.0"
596+ * )
597+ * }</pre>
598+ *
599+ * @param artifactCoordinates Maven coordinates (groupId:artifactId:version)
600+ * @return this builder
601+ */
491602 public Builder addMavenCentral (String ... artifactCoordinates ) {
492603 MavenRepositoryClassSource .Builder builder = MavenRepositoryClassSource .builder ()
493604 .mavenCentral ();
@@ -530,15 +641,53 @@ public Builder useCache(boolean useCache) {
530641 return this ;
531642 }
532643
644+ /**
645+ * Sets a custom delegation strategy.
646+ *
647+ * <p>Determines whether to check parent ClassLoader before or after custom sources.</p>
648+ *
649+ * @param strategy The delegation strategy
650+ * @return this builder
651+ * @throws NullPointerException if strategy is null
652+ */
533653 public Builder delegationStrategy (DelegationStrategy strategy ) {
534654 this .delegationStrategy = Objects .requireNonNull (strategy , "delegationStrategy cannot be null" );
535655 return this ;
536656 }
537657
658+ /**
659+ * Uses parent-first delegation (standard Java ClassLoader behavior).
660+ *
661+ * <p>Checks parent ClassLoader first, then custom sources. This is the default.</p>
662+ *
663+ * @return this builder
664+ */
538665 public Builder parentFirst () {
539666 return delegationStrategy (new ParentFirstDelegation ());
540667 }
541668
669+ /**
670+ * Uses parent-last delegation (checks custom sources before parent).
671+ *
672+ * <p>Allows overriding classes from parent ClassLoader, except for specified prefixes
673+ * which are always loaded from parent (e.g., JDK classes).</p>
674+ *
675+ * <p>Default always-parent prefixes include:</p>
676+ * <ul>
677+ * <li>java. (Java platform classes)</li>
678+ * <li>javax. (Java extensions)</li>
679+ * <li>sun. (Sun/Oracle internal classes)</li>
680+ * <li>jdk. (JDK internal classes)</li>
681+ * </ul>
682+ *
683+ * <p>Example:</p>
684+ * <pre>{@code
685+ * builder.parentLast("com.example.core.") // Always load com.example.core.* from parent
686+ * }</pre>
687+ *
688+ * @param alwaysParentPrefixes Additional prefixes to always load from parent
689+ * @return this builder
690+ */
542691 public Builder parentLast (String ... alwaysParentPrefixes ) {
543692 return delegationStrategy (new org .flossware .classloader .delegation .ParentLastDelegation (alwaysParentPrefixes ));
544693 }
@@ -564,11 +713,33 @@ public Builder trackResources() {
564713 return addListener (new org .flossware .classloader .lifecycle .ResourceTrackingListener ());
565714 }
566715
716+ /**
717+ * Sets a bytecode verifier for security validation.
718+ *
719+ * <p>Verifies loaded bytecode before defining classes (e.g., checksum validation).</p>
720+ *
721+ * <p>Example:</p>
722+ * <pre>{@code
723+ * Map<String, String> checksums = new HashMap<>();
724+ * checksums.put("com.example.MyClass", "sha256:abc123...");
725+ *
726+ * builder.bytecodeVerifier(new ChecksumValidator(checksums));
727+ * }</pre>
728+ *
729+ * @param verifier The bytecode verifier (null to disable verification)
730+ * @return this builder
731+ */
567732 public Builder bytecodeVerifier (BytecodeVerifier verifier ) {
568733 this .bytecodeVerifier = verifier ;
569734 return this ;
570735 }
571736
737+ /**
738+ * Builds the ApplicationClassLoader with configured settings.
739+ *
740+ * @return A new ApplicationClassLoader instance
741+ * @throws IllegalStateException if no class sources are configured
742+ */
572743 public ApplicationClassLoader build () {
573744 if (classSources .isEmpty ()) {
574745 throw new IllegalStateException ("At least one class source must be configured" );
0 commit comments