Skip to content

Commit 80519a7

Browse files
Flossyclaude
andcommitted
docs: add comprehensive Builder documentation to MinioClassSource
Added detailed JavaDoc to MinioClassSource.Builder with: - Builder class-level documentation with usage examples - Method-level documentation for all builder methods - S3-compatible service examples (MinIO, AWS S3, Backblaze, Cloudflare R2) - Default values documentation - Advanced configuration examples Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent f818872 commit 80519a7

3 files changed

Lines changed: 195 additions & 1 deletion

File tree

.claude/scheduled_tasks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"cron": "*/10 * * * *",
66
"prompt": "Run the automated code review workflow: execute .claude/scripts/code_review.sh, create GitHub issues via .claude/scripts/create_review_issues.py, auto-commit any fixes, and push to main. Stop when no new issues are found for 2 consecutive cycles.",
77
"createdAt": 1780068397375,
8-
"lastFiredAt": 1780072447039,
8+
"lastFiredAt": 1780073047133,
99
"recurring": true,
1010
"createdBySessionId": "8cbb97ab-1c4f-49bf-a8f7-b64b9b26e19a",
1111
"createdByPid": 569417,

src/main/java/org/flossware/classloader/filesystem/HdfsClassSource.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,60 @@ public void close() throws IOException {
105105
}
106106
}
107107

108+
/**
109+
* Creates a new Builder for constructing HdfsClassSource instances.
110+
*
111+
* @return A new Builder with default configuration
112+
*/
108113
public static Builder builder() {
109114
return new Builder();
110115
}
111116

117+
/**
118+
* Builder for constructing HdfsClassSource instances with fluent API.
119+
*
120+
* <p>Configures Hadoop HDFS connection for class loading from distributed storage.</p>
121+
*
122+
* <p><b>Basic Example:</b></p>
123+
* <pre>{@code
124+
* HdfsClassSource source = HdfsClassSource.builder()
125+
* .nameNodeUri("hdfs://namenode.example.com:9000")
126+
* .basePath("/app/classes")
127+
* .build();
128+
* }</pre>
129+
*
130+
* <p><b>Advanced Example with Timeouts and Size Limits:</b></p>
131+
* <pre>{@code
132+
* HdfsClassSource source = HdfsClassSource.builder()
133+
* .nameNodeUri("hdfs://namenode:9000")
134+
* .basePath("/production/classes/v2")
135+
* .socketTimeout(60000) // 60 seconds
136+
* .connectTimeout(15000) // 15 seconds
137+
* .maxClassSize(20 * 1024 * 1024) // 20MB
138+
* .build();
139+
* }</pre>
140+
*
141+
* <p><b>Using Custom Hadoop Configuration:</b></p>
142+
* <pre>{@code
143+
* Configuration conf = new Configuration();
144+
* conf.set("dfs.replication", "2");
145+
* conf.set("dfs.nameservices", "mycluster");
146+
*
147+
* HdfsClassSource source = HdfsClassSource.builder()
148+
* .configuration(conf)
149+
* .basePath("/classes")
150+
* .build();
151+
* }</pre>
152+
*
153+
* <p><b>Defaults:</b></p>
154+
* <ul>
155+
* <li>basePath: "/" (root)</li>
156+
* <li>socketTimeout: 30000ms (30 seconds)</li>
157+
* <li>connectTimeout: 10000ms (10 seconds)</li>
158+
* <li>maxClassSize: 10MB</li>
159+
* <li>configuration: new Configuration() (from classpath)</li>
160+
* </ul>
161+
*/
112162
public static class Builder {
113163
private String nameNodeUri;
114164
private String basePath = "/";

src/main/java/org/flossware/classloader/objectstore/MinioClassSource.java

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,64 @@ private String buildObjectName(String className) {
141141
return prefix + (prefix.endsWith("/") ? "" : "/") + classPath;
142142
}
143143

144+
/**
145+
* Creates a new Builder for constructing MinioClassSource instances.
146+
*
147+
* @return A new Builder with default configuration
148+
*/
144149
public static Builder builder() {
145150
return new Builder();
146151
}
147152

153+
/**
154+
* Builder for constructing MinioClassSource instances with fluent API.
155+
*
156+
* <p>Configures MinIO object storage connection for class loading.</p>
157+
*
158+
* <p><b>Basic Example:</b></p>
159+
* <pre>{@code
160+
* MinioClassSource source = MinioClassSource.builder()
161+
* .endpoint("minio.example.com")
162+
* .accessKey("minioadmin")
163+
* .secretKey("minioadmin")
164+
* .bucket("classes")
165+
* .build();
166+
* }</pre>
167+
*
168+
* <p><b>Advanced Example with Prefix and Custom Port:</b></p>
169+
* <pre>{@code
170+
* MinioClassSource source = MinioClassSource.builder()
171+
* .endpoint("localhost")
172+
* .port(9000) // Custom port
173+
* .secure(false) // HTTP instead of HTTPS
174+
* .accessKey("mykey")
175+
* .secretKey("mysecret")
176+
* .bucket("app-classes")
177+
* .prefix("production/v2") // Object key prefix
178+
* .region("us-east-1")
179+
* .maxClassSize(20 * 1024 * 1024) // 20MB limit
180+
* .build();
181+
* }</pre>
182+
*
183+
* <p><b>S3-Compatible Services:</b></p>
184+
* <p>Works with any S3-compatible service:</p>
185+
* <ul>
186+
* <li>MinIO</li>
187+
* <li>Amazon S3</li>
188+
* <li>Backblaze B2</li>
189+
* <li>Cloudflare R2</li>
190+
* <li>DigitalOcean Spaces</li>
191+
* </ul>
192+
*
193+
* <p><b>Defaults:</b></p>
194+
* <ul>
195+
* <li>secure: true (HTTPS)</li>
196+
* <li>port: 443 (HTTPS) or 9000 (HTTP if secure=false)</li>
197+
* <li>maxClassSize: 10MB</li>
198+
* <li>prefix: "" (bucket root)</li>
199+
* <li>region: null (auto-detect)</li>
200+
* </ul>
201+
*/
148202
public static class Builder {
149203
private String endpoint;
150204
private String accessKey;
@@ -156,36 +210,97 @@ public static class Builder {
156210
private int port = 443; // Default HTTPS port
157211
private long maxClassSize = MAX_CLASS_SIZE;
158212

213+
/**
214+
* Sets the MinIO/S3 endpoint hostname.
215+
*
216+
* <p>Examples:</p>
217+
* <ul>
218+
* <li>MinIO: "minio.example.com" or "localhost"</li>
219+
* <li>Amazon S3: "s3.amazonaws.com"</li>
220+
* <li>Backblaze B2: "s3.us-west-002.backblazeb2.com"</li>
221+
* <li>Cloudflare R2: "ACCOUNT_ID.r2.cloudflarestorage.com"</li>
222+
* </ul>
223+
*
224+
* @param endpoint Hostname (without http:// or https://)
225+
* @return this builder
226+
* @throws NullPointerException if endpoint is null
227+
*/
159228
public Builder endpoint(String endpoint) {
160229
this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null");
161230
return this;
162231
}
163232

233+
/**
234+
* Sets the access key (username) for authentication.
235+
*
236+
* @param accessKey Access key ID
237+
* @return this builder
238+
* @throws NullPointerException if accessKey is null
239+
*/
164240
public Builder accessKey(String accessKey) {
165241
this.accessKey = Objects.requireNonNull(accessKey, "accessKey cannot be null");
166242
return this;
167243
}
168244

245+
/**
246+
* Sets the secret key (password) for authentication.
247+
*
248+
* @param secretKey Secret access key
249+
* @return this builder
250+
* @throws NullPointerException if secretKey is null
251+
*/
169252
public Builder secretKey(String secretKey) {
170253
this.secretKey = Objects.requireNonNull(secretKey, "secretKey cannot be null");
171254
return this;
172255
}
173256

257+
/**
258+
* Sets the bucket name containing class files.
259+
*
260+
* @param bucketName Bucket name (e.g., "classes", "app-binaries")
261+
* @return this builder
262+
* @throws NullPointerException if bucketName is null
263+
*/
174264
public Builder bucket(String bucketName) {
175265
this.bucketName = Objects.requireNonNull(bucketName, "bucketName cannot be null");
176266
return this;
177267
}
178268

269+
/**
270+
* Sets an optional object key prefix.
271+
*
272+
* <p>Useful for organizing classes in subdirectories within a bucket.</p>
273+
*
274+
* <p>Example: If prefix is "production/v2" and loading class "com.example.MyClass",
275+
* the object key will be "production/v2/com/example/MyClass.class"</p>
276+
*
277+
* @param prefix Object key prefix (null or "" for bucket root)
278+
* @return this builder
279+
*/
179280
public Builder prefix(String prefix) {
180281
this.prefix = prefix;
181282
return this;
182283
}
183284

285+
/**
286+
* Sets the region (optional, auto-detected if not specified).
287+
*
288+
* @param region AWS region code (e.g., "us-east-1", "eu-west-1")
289+
* @return this builder
290+
*/
184291
public Builder region(String region) {
185292
this.region = region;
186293
return this;
187294
}
188295

296+
/**
297+
* Sets whether to use HTTPS (true) or HTTP (false).
298+
*
299+
* <p>Automatically adjusts port: 443 for HTTPS, 9000 for HTTP (unless explicitly set).</p>
300+
*
301+
* @param secure true for HTTPS (default), false for HTTP
302+
* @return this builder
303+
*/
189304
public Builder secure(boolean secure) {
190305
this.secure = secure;
191306
// Adjust default port based on secure setting
@@ -195,6 +310,20 @@ public Builder secure(boolean secure) {
195310
return this;
196311
}
197312

313+
/**
314+
* Sets a custom port number.
315+
*
316+
* <p>Common ports:</p>
317+
* <ul>
318+
* <li>443: HTTPS (default)</li>
319+
* <li>9000: MinIO HTTP (default when secure=false)</li>
320+
* <li>9001: MinIO Console</li>
321+
* </ul>
322+
*
323+
* @param port Port number (1-65535)
324+
* @return this builder
325+
* @throws IllegalArgumentException if port is outside valid range
326+
*/
198327
public Builder port(int port) {
199328
if (port < 1 || port > 65535) {
200329
throw new IllegalArgumentException("Port must be 1-65535");
@@ -203,6 +332,15 @@ public Builder port(int port) {
203332
return this;
204333
}
205334

335+
/**
336+
* Sets the maximum allowed class file size.
337+
*
338+
* <p>Prevents OOM attacks by rejecting files larger than this limit.</p>
339+
*
340+
* @param maxBytes Maximum size in bytes (default: 10MB)
341+
* @return this builder
342+
* @throws IllegalArgumentException if maxBytes <= 0
343+
*/
206344
public Builder maxClassSize(long maxBytes) {
207345
if (maxBytes <= 0) {
208346
throw new IllegalArgumentException("maxClassSize must be positive");
@@ -211,6 +349,12 @@ public Builder maxClassSize(long maxBytes) {
211349
return this;
212350
}
213351

352+
/**
353+
* Builds the MinioClassSource with configured settings.
354+
*
355+
* @return A new MinioClassSource instance
356+
* @throws NullPointerException if endpoint, accessKey, secretKey, or bucketName not set
357+
*/
214358
public MinioClassSource build() {
215359
Objects.requireNonNull(endpoint, "endpoint must be set");
216360
Objects.requireNonNull(accessKey, "accessKey must be set");

0 commit comments

Comments
 (0)