From b8ce4f20faa94ac53f1f5bf28ea9186fb65b869e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 7 Sep 2026 12:19:10 +0100 Subject: [PATCH] Release the classpath ResourceLoader when scomp fails SchemaCompiler.compile builds a PathResourceLoader over the -cp entries, which opens a ZipFile per jar, and closes it on the last line of the method. Nothing guards the path in between: if loadTypeSystem, system.save(filer), generateTypes or the extension hooks throw, every classpath jar stays open for the life of the JVM. Put the body in a try/finally. The change is almost entirely re-indentation - "git diff -w" shows the try, the finally and a comment. Co-Authored-By: Claude Opus 5 (1M context) --- .../xmlbeans/impl/tool/SchemaCompiler.java | 158 +++++++++--------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java b/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java index c5340bb6f..25b948864 100644 --- a/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java +++ b/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java @@ -669,103 +669,107 @@ public static boolean compile(Parameters params) { boolean result = true; - File schemasDir = IOUtil.createDir(classesDir, SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/src"); - - // build the in-memory type system - XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener); - SchemaTypeSystem system = loadTypeSystem(name, xsdFiles, wsdlFiles, urlFiles, configFiles, - javaFiles, cpResourceLoader, download, noUpa, noPvr, noAnn, noVDoc, noExt, sourceCodeEncoding, mdefNamespaces, - baseDir, sourcesToCopyMap, errorListener, schemasDir, cmdLineEntRes, classpath); - if (errorListener.hasError()) { - result = false; - } - long finish = System.currentTimeMillis(); - if (!quiet) { - System.out.println("Time to build schema type system: " + ((double) (finish - start) / 1000.0) + " seconds"); - } - - // now code generate and compile the JAR - if (result && system != null) // todo: don't check "result" here if we want to compile anyway, ignoring invalid schemas - { - start = System.currentTimeMillis(); - - // filer implementation writes binary .xsd and generated source to disk - Repackager repackager = (repackage == null ? null : new Repackager(repackage)); - FilerImpl filer = new FilerImpl(classesDir, srcDir, repackager, verbose, incrSrcGen); - - // currently just for schemaCodePrinter - XmlOptions options = new XmlOptions(); - if (codePrinter != null) { - options.setSchemaCodePrinter(codePrinter); + // the loader holds an open ZipFile per classpath jar - it has to be released + // even when code generation or compilation throws + try { + File schemasDir = IOUtil.createDir(classesDir, SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/src"); + + // build the in-memory type system + XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener); + SchemaTypeSystem system = loadTypeSystem(name, xsdFiles, wsdlFiles, urlFiles, configFiles, + javaFiles, cpResourceLoader, download, noUpa, noPvr, noAnn, noVDoc, noExt, sourceCodeEncoding, mdefNamespaces, + baseDir, sourcesToCopyMap, errorListener, schemasDir, cmdLineEntRes, classpath); + if (errorListener.hasError()) { + result = false; + } + long finish = System.currentTimeMillis(); + if (!quiet) { + System.out.println("Time to build schema type system: " + ((double) (finish - start) / 1000.0) + " seconds"); } - options.setCompilePartialMethod(partialMethods); - options.setCompileNoAnnotations(noAnn); - options.setCompileAnnotationAsJavadoc(copyAnn); - options.setCharacterEncoding(sourceCodeEncoding); - - // save .xsb files - system.save(filer); - // gen source files - result = SchemaTypeSystemCompiler.generateTypes(system, filer, options); + // now code generate and compile the JAR + if (result && system != null) // todo: don't check "result" here if we want to compile anyway, ignoring invalid schemas + { + start = System.currentTimeMillis(); - if (incrSrcGen) { - // We have to delete extra source files that may be out of date - SchemaCodeGenerator.deleteObsoleteFiles(srcDir, srcDir, - new HashSet<>(filer.getSourceFiles())); - } + // filer implementation writes binary .xsd and generated source to disk + Repackager repackager = (repackage == null ? null : new Repackager(repackage)); + FilerImpl filer = new FilerImpl(classesDir, srcDir, repackager, verbose, incrSrcGen); - if (result) { - finish = System.currentTimeMillis(); - if (!quiet) { - System.out.println("Time to generate code: " + ((double) (finish - start) / 1000.0) + " seconds"); + // currently just for schemaCodePrinter + XmlOptions options = new XmlOptions(); + if (codePrinter != null) { + options.setSchemaCodePrinter(codePrinter); } - } + options.setCompilePartialMethod(partialMethods); + options.setCompileNoAnnotations(noAnn); + options.setCompileAnnotationAsJavadoc(copyAnn); + options.setCharacterEncoding(sourceCodeEncoding); - // compile source - if (result && !nojavac) { - start = System.currentTimeMillis(); + // save .xsb files + system.save(filer); - List sourcefiles = filer.getSourceFiles(); + // gen source files + result = SchemaTypeSystemCompiler.generateTypes(system, filer, options); - if (javaFiles != null) { - sourcefiles.addAll(java.util.Arrays.asList(javaFiles)); - } - if (!CodeGenUtil.externalCompile(sourcefiles, classesDir, classpath, debug, compiler, null, - memoryInitialSize, memoryMaximumSize, quiet, verbose, sourceCodeEncoding)) { - result = false; + if (incrSrcGen) { + // We have to delete extra source files that may be out of date + SchemaCodeGenerator.deleteObsoleteFiles(srcDir, srcDir, + new HashSet<>(filer.getSourceFiles())); } - finish = System.currentTimeMillis(); - if (result && !params.isQuiet()) { - System.out.println("Time to compile code: " + ((double) (finish - start) / 1000.0) + " seconds"); + if (result) { + finish = System.currentTimeMillis(); + if (!quiet) { + System.out.println("Time to generate code: " + ((double) (finish - start) / 1000.0) + " seconds"); + } } - // jar classes and .xsb - if (result && outputJar != null) { - try { - new JarHelper().jarDir(classesDir, outputJar); - } catch (IOException e) { - System.err.println("IO Error " + e); + // compile source + if (result && !nojavac) { + start = System.currentTimeMillis(); + + List sourcefiles = filer.getSourceFiles(); + + if (javaFiles != null) { + sourcefiles.addAll(java.util.Arrays.asList(javaFiles)); + } + if (!CodeGenUtil.externalCompile(sourcefiles, classesDir, classpath, debug, compiler, null, + memoryInitialSize, memoryMaximumSize, quiet, verbose, sourceCodeEncoding)) { result = false; } + finish = System.currentTimeMillis(); if (result && !params.isQuiet()) { - System.out.println("Compiled types to: " + outputJar); + System.out.println("Time to compile code: " + ((double) (finish - start) / 1000.0) + " seconds"); + } + + // jar classes and .xsb + if (result && outputJar != null) { + try { + new JarHelper().jarDir(classesDir, outputJar); + } catch (IOException e) { + System.err.println("IO Error " + e); + result = false; + } + + if (result && !params.isQuiet()) { + System.out.println("Compiled types to: " + outputJar); + } } } } - } - if (!result && !quiet) { - System.out.println("BUILD FAILED"); - } else { - // call schema compiler extension if registered - runExtensions(extensions, system, classesDir); - } - - if (cpResourceLoader != null) { - cpResourceLoader.close(); + if (!result && !quiet) { + System.out.println("BUILD FAILED"); + } else { + // call schema compiler extension if registered + runExtensions(extensions, system, classesDir); + } + } finally { + if (cpResourceLoader != null) { + cpResourceLoader.close(); + } } return result; }