or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

class-info.mdindex.mdquerying.mdresources.mdscanning.mdtype-signatures.md

resources.mddocs/

0

# Resources and Classpath

1

2

ClassGraph provides comprehensive support for discovering, accessing, and managing resources and classpath elements. This includes files in JARs, directories, modules, and various classpath configurations.

3

4

## Resource Discovery and Access

5

6

```java { .api }

7

import io.github.classgraph.Resource;

8

import io.github.classgraph.ResourceList;

9

import java.io.InputStream;

10

import java.nio.ByteBuffer;

11

import java.nio.charset.StandardCharsets;

12

import java.util.Map;

13

import java.util.regex.Pattern;

14

import java.util.Properties;

15

```

16

17

### Basic Resource Operations

18

19

```java { .api }

20

try (ScanResult scanResult = new ClassGraph().acceptPaths("META-INF", "config").scan()) {

21

// Get all resources found during scan

22

ResourceList allResources = scanResult.getAllResources();

23

24

// Get resources as a map (path -> ResourceList)

25

Map<String, ResourceList> resourceMap = scanResult.getAllResourcesAsMap();

26

27

// Find resources by exact path

28

ResourceList springFactories = scanResult.getResourcesWithPath("META-INF/spring.factories");

29

30

// Find resources ignoring accept/reject filters

31

ResourceList allSpringFactories = scanResult.getResourcesWithPathIgnoringAccept("META-INF/spring.factories");

32

}

33

```

34

35

### Resource Filtering and Pattern Matching

36

37

```java { .api }

38

// Find by filename (leaf name)

39

ResourceList applicationProperties = scanResult.getResourcesWithLeafName("application.properties");

40

ResourceList configFiles = scanResult.getResourcesWithLeafName("config.xml");

41

42

// Find by file extension

43

ResourceList jsonFiles = scanResult.getResourcesWithExtension("json");

44

ResourceList sqlFiles = scanResult.getResourcesWithExtension("sql");

45

ResourceList propertiesFiles = scanResult.getResourcesWithExtension("properties");

46

47

// Find by regex pattern

48

Pattern logbackPattern = Pattern.compile(".*logback.*\\.xml");

49

ResourceList logbackConfigs = scanResult.getResourcesMatchingPattern(logbackPattern);

50

51

// Find by wildcard pattern

52

ResourceList allJsonInConfig = scanResult.getResourcesMatchingWildcard("**/config/**/*.json");

53

ResourceList migrationFiles = scanResult.getResourcesMatchingWildcard("db/migration/**/*.sql");

54

```

55

56

## Resource Content Access

57

58

### Reading Resource Content

59

60

```java { .api }

61

Resource resource = scanResult.getResourcesWithPath("config/database.properties").get(0);

62

63

// Basic resource information

64

String path = resource.getPath(); // "config/database.properties"

65

String relativePath = resource.getPathRelativeToClasspathElement(); // Relative to JAR/directory root

66

long lastModified = resource.getLastModified(); // Timestamp

67

long length = resource.getLength(); // Size in bytes

68

69

// Content access methods

70

try (InputStream inputStream = resource.open()) {

71

// Read as stream

72

Properties props = new Properties();

73

props.load(inputStream);

74

}

75

76

// Read all content at once

77

byte[] content = resource.load();

78

String textContent = resource.getContentAsString(); // UTF-8 decoded

79

80

// Read as ByteBuffer (memory-efficient for large files)

81

ByteBuffer buffer = resource.read();

82

// Remember to call resource.close() when done with ByteBuffer

83

```

84

85

### Bulk Resource Processing

86

87

```java { .api }

88

// Process multiple resources with forEach methods

89

scanResult.getResourcesWithExtension("json")

90

.forEachByteArray((resource, content) -> {

91

String json = new String(content, StandardCharsets.UTF_8);

92

System.out.println("Processing " + resource.getPath() + ": " + json.length() + " bytes");

93

94

// Parse and process JSON

95

try {

96

JsonNode jsonNode = objectMapper.readTree(json);

97

processConfiguration(resource.getPath(), jsonNode);

98

} catch (Exception e) {

99

System.err.println("Failed to parse JSON in " + resource.getPath() + ": " + e.getMessage());

100

}

101

});

102

103

// Process with input streams

104

scanResult.getResourcesWithExtension("properties")

105

.forEach(resource -> {

106

try (InputStream input = resource.open()) {

107

Properties props = new Properties();

108

props.load(input);

109

110

System.out.println("Loaded " + props.size() + " properties from " + resource.getPath());

111

processProperties(resource.getPath(), props);

112

} catch (IOException e) {

113

System.err.println("Failed to load properties from " + resource.getPath());

114

}

115

});

116

```

117

118

## Resource Location and Context

119

120

### Location Information

121

122

```java { .api }

123

Resource resource = scanResult.getResourcesWithPath("META-INF/MANIFEST.MF").get(0);

124

125

// Resource URIs and URLs

126

URI resourceURI = resource.getURI(); // Full resource URI

127

URL resourceURL = resource.getURL(); // Full resource URL

128

129

// Containing classpath element information

130

URI classpathElementURI = resource.getClasspathElementURI(); // JAR or directory URI

131

URL classpathElementURL = resource.getClasspathElementURL(); // JAR or directory URL

132

File classpathElementFile = resource.getClasspathElementFile(); // JAR or directory as File

133

134

// Module information (if resource is in a module)

135

ModuleRef moduleRef = resource.getModuleRef(); // null if not in module

136

```

137

138

### Classpath Element Context

139

140

```java { .api }

141

// Determine resource context

142

if (resource.getModuleRef() != null) {

143

// Resource is in a JPMS module

144

ModuleRef module = resource.getModuleRef();

145

System.out.println("Resource in module: " + module.getName());

146

System.out.println("Module location: " + module.getLocationStr());

147

} else {

148

// Resource is in traditional classpath

149

File classpathElement = resource.getClasspathElementFile();

150

if (classpathElement.isFile()) {

151

System.out.println("Resource in JAR: " + classpathElement.getName());

152

} else {

153

System.out.println("Resource in directory: " + classpathElement.getPath());

154

}

155

}

156

```

157

158

## Classpath Management

159

160

### Classpath Information Access

161

162

```java { .api }

163

// Get classpath information from ClassGraph (before scanning)

164

ClassGraph classGraph = new ClassGraph();

165

166

List<File> classpathFiles = classGraph.getClasspathFiles();

167

String classpathString = classGraph.getClasspath();

168

List<URI> classpathURIs = classGraph.getClasspathURIs();

169

List<URL> classpathURLs = classGraph.getClasspathURLs();

170

171

// Get classpath information from ScanResult (after scanning)

172

try (ScanResult scanResult = new ClassGraph().scan()) {

173

List<File> scannedFiles = scanResult.getClasspathFiles();

174

String scannedClasspath = scanResult.getClasspath();

175

List<URI> scannedURIs = scanResult.getClasspathURIs();

176

List<URL> scannedURLs = scanResult.getClasspathURLs();

177

}

178

```

179

180

### Classpath Element Types

181

182

```java { .api }

183

// Analyze different types of classpath elements

184

List<File> classpathElements = classGraph.getClasspathFiles();

185

186

for (File element : classpathElements) {

187

if (element.isFile()) {

188

if (element.getName().endsWith(".jar") || element.getName().endsWith(".zip")) {

189

System.out.println("JAR/ZIP file: " + element.getPath());

190

} else {

191

System.out.println("Other file: " + element.getPath());

192

}

193

} else if (element.isDirectory()) {

194

System.out.println("Directory: " + element.getPath());

195

}

196

}

197

```

198

199

## Module System Support

200

201

### Module Information

202

203

```java { .api }

204

// Get module information from ClassGraph

205

List<ModuleRef> modules = classGraph.getModules();

206

ModulePathInfo modulePathInfo = classGraph.getModulePathInfo();

207

208

// Module path configuration

209

if (modulePathInfo != null) {

210

Set<String> modulePath = modulePathInfo.modulePath;

211

Set<String> addModules = modulePathInfo.addModules;

212

Set<String> patchModules = modulePathInfo.patchModules;

213

Set<String> addExports = modulePathInfo.addExports;

214

Set<String> addOpens = modulePathInfo.addOpens;

215

Set<String> addReads = modulePathInfo.addReads;

216

}

217

```

218

219

### Module Content Access

220

221

```java { .api }

222

// Access module information from scan results

223

try (ScanResult scanResult = new ClassGraph().enableSystemJarsAndModules().scan()) {

224

ModuleInfoList modules = scanResult.getModuleInfo();

225

226

for (ModuleInfo module : modules) {

227

System.out.println("Module: " + module.getName());

228

System.out.println("Location: " + module.getLocation());

229

230

// Module contents

231

ClassInfoList classesInModule = module.getClassInfo();

232

PackageInfoList packagesInModule = module.getPackageInfo();

233

234

System.out.println(" Classes: " + classesInModule.size());

235

System.out.println(" Packages: " + packagesInModule.size());

236

237

// Module annotations

238

AnnotationInfoList moduleAnnotations = module.getAnnotationInfo();

239

if (!moduleAnnotations.isEmpty()) {

240

System.out.println(" Annotations: " + moduleAnnotations.size());

241

}

242

}

243

}

244

```

245

246

### ModuleRef Details

247

248

```java { .api }

249

ModuleRef moduleRef = resource.getModuleRef();

250

251

if (moduleRef != null) {

252

// Basic module information

253

String name = moduleRef.getName(); // Module name

254

URI location = moduleRef.getLocation(); // Module location

255

String locationStr = moduleRef.getLocationStr(); // Location as string

256

File locationFile = moduleRef.getLocationFile(); // Location as File

257

258

// Module version

259

String version = moduleRef.getRawVersion(); // Version string if available

260

261

// Module contents

262

List<String> packages = moduleRef.getPackages(); // Packages in module

263

264

// Module system objects (via reflection)

265

Object moduleReference = moduleRef.getReference(); // ModuleReference

266

Object moduleLayer = moduleRef.getLayer(); // ModuleLayer

267

Object moduleDescriptor = moduleRef.getDescriptor(); // ModuleDescriptor

268

269

System.out.println("Module: " + name + " v" + version);

270

System.out.println("Location: " + locationStr);

271

System.out.println("Packages: " + packages.size());

272

}

273

```

274

275

## Advanced Resource Operations

276

277

### Custom Resource Processing

278

279

```java { .api }

280

// Custom resource filtering with functional interface

281

ResourceList filteredResources = scanResult.getAllResources()

282

.filter(resource -> {

283

String path = resource.getPath();

284

return path.startsWith("META-INF/") &&

285

path.endsWith(".xml") &&

286

!path.contains("test");

287

});

288

289

// Process configuration files by type

290

Map<String, List<Resource>> configByType = scanResult.getResourcesMatchingWildcard("**/config/**")

291

.stream()

292

.collect(groupingBy(resource -> {

293

String path = resource.getPath();

294

int lastDot = path.lastIndexOf('.');

295

return lastDot > 0 ? path.substring(lastDot + 1).toLowerCase() : "unknown";

296

}));

297

298

System.out.println("Configuration files by type:");

299

configByType.forEach((type, resources) -> {

300

System.out.println(" " + type + ": " + resources.size() + " files");

301

});

302

```

303

304

### Resource Content Analysis

305

306

```java { .api }

307

// Analyze SQL migration files

308

ResourceList sqlFiles = scanResult.getResourcesMatchingWildcard("db/migration/**/*.sql");

309

310

for (Resource sqlFile : sqlFiles) {

311

String content = sqlFile.getContentAsString();

312

313

// Extract version from filename (e.g., V001__create_users.sql)

314

String filename = sqlFile.getPath();

315

Pattern versionPattern = Pattern.compile("V(\\d+)__(.+)\\.sql");

316

Matcher matcher = versionPattern.matcher(filename);

317

318

if (matcher.find()) {

319

String version = matcher.group(1);

320

String description = matcher.group(2).replace("_", " ");

321

322

System.out.println("Migration " + version + ": " + description);

323

System.out.println(" File: " + filename);

324

System.out.println(" Size: " + content.length() + " characters");

325

326

// Analyze SQL content

327

boolean hasCreate = content.toUpperCase().contains("CREATE TABLE");

328

boolean hasInsert = content.toUpperCase().contains("INSERT INTO");

329

boolean hasUpdate = content.toUpperCase().contains("UPDATE ");

330

331

System.out.println(" Operations: " +

332

(hasCreate ? "CREATE " : "") +

333

(hasInsert ? "INSERT " : "") +

334

(hasUpdate ? "UPDATE " : ""));

335

}

336

}

337

```

338

339

### Resource Dependency Analysis

340

341

```java { .api }

342

// Find Spring configuration files and their dependencies

343

ResourceList springConfigs = scanResult.getResourcesMatchingWildcard("**/spring/**/*.xml");

344

345

for (Resource config : springConfigs) {

346

String content = config.getContentAsString();

347

348

// Parse for import statements

349

Pattern importPattern = Pattern.compile("<import\\s+resource=[\"']([^\"']+)[\"']");

350

Matcher importMatcher = importPattern.matcher(content);

351

352

List<String> imports = new ArrayList<>();

353

while (importMatcher.find()) {

354

imports.add(importMatcher.group(1));

355

}

356

357

// Parse for bean definitions

358

Pattern beanPattern = Pattern.compile("<bean\\s+[^>]*class=[\"']([^\"']+)[\"']");

359

Matcher beanMatcher = beanPattern.matcher(content);

360

361

Set<String> referencedClasses = new HashSet<>();

362

while (beanMatcher.find()) {

363

referencedClasses.add(beanMatcher.group(1));

364

}

365

366

System.out.println("Spring config: " + config.getPath());

367

System.out.println(" Imports: " + imports.size());

368

System.out.println(" Bean classes: " + referencedClasses.size());

369

370

// Check if referenced classes exist in scan results

371

for (String className : referencedClasses) {

372

ClassInfo classInfo = scanResult.getClassInfo(className);

373

if (classInfo == null) {

374

System.out.println(" WARNING: Missing class " + className);

375

}

376

}

377

}

378

```

379

380

## Resource Lists and Collection Operations

381

382

### ResourceList Operations

383

384

```java { .api }

385

ResourceList resources = scanResult.getResourcesWithExtension("properties");

386

387

// Get paths and URLs

388

List<String> paths = resources.getPaths();

389

List<String> relativePaths = resources.getPathsRelativeToClasspathElement();

390

List<URL> urls = resources.getURLs();

391

List<URI> uris = resources.getURIs();

392

393

// Access specific resources

394

ResourceList configResources = resources.get("application.properties"); // Resources with specific path

395

Resource firstConfig = configResources.isEmpty() ? null : configResources.get(0);

396

397

// Filtering

398

ResourceList prodConfigs = resources.filter(resource ->

399

resource.getPath().contains("prod") || resource.getPath().contains("production"));

400

401

// Combine with other ResourceLists

402

ResourceList allConfigs = resources.union(

403

scanResult.getResourcesWithExtension("yml"),

404

scanResult.getResourcesWithExtension("yaml")

405

);

406

```

407

408

## Error Handling and Resource Management

409

410

### Safe Resource Access

411

412

```java { .api }

413

// Safe resource processing with proper cleanup

414

ResourceList jsonConfigs = scanResult.getResourcesWithExtension("json");

415

416

for (Resource resource : jsonConfigs) {

417

try {

418

// Option 1: Use try-with-resources for streams

419

try (InputStream input = resource.open()) {

420

JsonNode config = objectMapper.readTree(input);

421

processConfiguration(resource.getPath(), config);

422

}

423

424

// Option 2: Use convenience method for small files

425

String content = resource.getContentAsString();

426

JsonNode config = objectMapper.readTree(content);

427

processConfiguration(resource.getPath(), config);

428

429

// Option 3: Use ByteBuffer for large files (remember to close resource)

430

ByteBuffer buffer = resource.read();

431

try {

432

// Process buffer...

433

} finally {

434

resource.close(); // Important: close resource when using ByteBuffer

435

}

436

437

} catch (IOException e) {

438

System.err.println("Failed to process " + resource.getPath() + ": " + e.getMessage());

439

// Continue processing other resources

440

}

441

}

442

```

443

444

### Resource Change Detection

445

446

```java { .api }

447

try (ScanResult scanResult = new ClassGraph().scan()) {

448

// Check if any resources have changed since scan

449

boolean modified = scanResult.classpathContentsModifiedSinceScan();

450

451

if (modified) {

452

System.out.println("Classpath contents have been modified since scan");

453

454

// Get timestamp of most recent modification

455

long lastModified = scanResult.classpathContentsLastModifiedTime();

456

System.out.println("Last modified: " + new Date(lastModified));

457

458

// Consider rescanning for updated results

459

}

460

}

461

```

462

463

ClassGraph's resource system provides comprehensive access to all classpath and module path resources with efficient processing capabilities and proper resource management, making it ideal for configuration discovery, asset processing, and build-time analysis tasks.