From d704efe6b26d276ce7d8e4c9d025603e5ffac349 Mon Sep 17 00:00:00 2001 From: Emmanuel GALLOIS Date: Fri, 29 May 2026 17:31:57 +0200 Subject: [PATCH] chore(QTDI-2901): S2095 Resource leaks --- .../runtime/manager/ComponentManager.java | 26 +++++++++------ .../xbean/converter/SchemaConverter.java | 6 ++-- .../testing/spark/internal/BaseSpark.java | 8 +++-- .../service/VirtualDependenciesService.java | 8 ++--- .../component/tools/AsciidoctorExecutor.java | 5 ++- .../documentation/WriteIfDifferentStream.java | 6 +++- .../component/maven/WebsiteBuilderMojo.java | 32 ++++++++++++------- 7 files changed, 60 insertions(+), 31 deletions(-) diff --git a/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/ComponentManager.java b/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/ComponentManager.java index 70a32144b8ab0..863e2d5427e39 100644 --- a/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/ComponentManager.java +++ b/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/ComponentManager.java @@ -1035,6 +1035,8 @@ public String addPlugin(final String pluginRootFile) { return pluginId; } + // Container lifecycle is owned by ContainerManager (registered on create, closed via removePlugin) + @SuppressWarnings({ "resource", "java:S2095" }) final String id = this.container .builder(pluginRootFile) .withCustomizer(createContainerCustomizer(pluginRootFile)) @@ -1053,6 +1055,8 @@ private String findPluginId(final String pluginRootFile) { } public String addWithLocationPlugin(final String location, final String pluginRootFile) { + // Container lifecycle is owned by ContainerManager (registered on create, closed via removePlugin) + @SuppressWarnings({ "resource", "java:S2095" }) final String id = this.container .builder(pluginRootFile) .withCustomizer(createContainerCustomizer(location)) @@ -1064,6 +1068,8 @@ public String addWithLocationPlugin(final String location, final String pluginRo } protected String addPlugin(final String forcedId, final String pluginRootFile) { + // Container lifecycle is owned by ContainerManager (registered on create, closed via removePlugin) + @SuppressWarnings({ "resource", "java:S2095" }) final String id = this.container .builder(forcedId, pluginRootFile) .withCustomizer(createContainerCustomizer(forcedId)) @@ -1831,21 +1837,23 @@ private Archive toArchive(final String module, final String moduleId, final Conf final URL nestedJar = loader.getParent().getResource(ConfigurableClassLoader.NESTED_MAVEN_REPOSITORY + module); if (nestedJar != null) { - InputStream nestedStream = null; - final JarInputStream jarStream; + final InputStream nestedStream; try { nestedStream = nestedJar.openStream(); - jarStream = new JarInputStream(nestedStream); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + try { + final JarInputStream jarStream = new JarInputStream(nestedStream); log.debug("Found a nested resource for " + module); return new NestedJarArchive(nestedJar, jarStream, loader); } catch (final IOException e) { - if (nestedStream != null) { - try { // normally not needed - nestedStream.close(); - } catch (final IOException e1) { - // no-op - } + try { // normally not needed + nestedStream.close(); + } catch (final IOException e1) { + // no-op } + throw new IllegalStateException(e); } } throw new IllegalArgumentException( diff --git a/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/xbean/converter/SchemaConverter.java b/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/xbean/converter/SchemaConverter.java index 8f51b1dc4fd2a..3ff87f411e904 100644 --- a/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/xbean/converter/SchemaConverter.java +++ b/component-runtime-manager/src/main/java/org/talend/sdk/component/runtime/manager/xbean/converter/SchemaConverter.java @@ -32,6 +32,7 @@ import javax.json.JsonNumber; import javax.json.JsonObject; import javax.json.JsonObjectBuilder; +import javax.json.JsonReader; import javax.json.JsonString; import javax.json.JsonValue; import javax.json.spi.JsonProvider; @@ -75,8 +76,9 @@ public SchemaConverter() { @Override public Object toObjectImpl(final String s) { if (!s.isEmpty()) { - final JsonObject json = JsonProvider.provider().createReader(new StringReader(s)).readObject(); - return toSchema(json); + try (final JsonReader reader = JsonProvider.provider().createReader(new StringReader(s))) { + return toSchema(reader.readObject()); + } } return null; } diff --git a/component-runtime-testing/component-runtime-testing-spark/src/main/java/org/talend/sdk/component/runtime/testing/spark/internal/BaseSpark.java b/component-runtime-testing/component-runtime-testing-spark/src/main/java/org/talend/sdk/component/runtime/testing/spark/internal/BaseSpark.java index e0e95ee569275..20cd567754f17 100644 --- a/component-runtime-testing/component-runtime-testing-spark/src/main/java/org/talend/sdk/component/runtime/testing/spark/internal/BaseSpark.java +++ b/component-runtime-testing/component-runtime-testing-spark/src/main/java/org/talend/sdk/component/runtime/testing/spark/internal/BaseSpark.java @@ -305,8 +305,9 @@ private File buildSparkHome(final Version version) { fail(e.getMessage()); } - try (final JarOutputStream file = new JarOutputStream(new FileOutputStream(new File(sparkHome, - version.libFolder() + "/spark-assembly-" + sparkVersion + "-hadoop2.6.0.jar")))) { + try (final FileOutputStream fos = new FileOutputStream(new File(sparkHome, + version.libFolder() + "/spark-assembly-" + sparkVersion + "-hadoop2.6.0.jar")); + final JarOutputStream file = new JarOutputStream(fos)) { file.putNextEntry(new ZipEntry("META-INF/marker")); file.write("just to let spark find the jar".getBytes(StandardCharsets.UTF_8)); } catch (final IOException e) { @@ -452,6 +453,9 @@ public void submit(final Class main, final String... args) { args == null ? Stream.empty() : Stream.of(args)) .toArray(String[]::new); LOGGER.info("Submitting: " + asList(submitArgs)); + // Monitor is a long-running Thread; closed in the success branch below + // and via the cleanup task / shutdown hook fallback (see config.cleanupTasks). + @SuppressWarnings({ "resource", "java:S2095" }) final SparkProcessMonitor monitor = new SparkProcessMonitor(config.get(), "spark-submit-" + main.getSimpleName() + "-monitor", () -> true, submitArgs); final Thread hook = new Thread(monitor::close); diff --git a/component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/service/VirtualDependenciesService.java b/component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/service/VirtualDependenciesService.java index 10b6c8beeeac0..0e5df4380f1a5 100644 --- a/component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/service/VirtualDependenciesService.java +++ b/component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/service/VirtualDependenciesService.java @@ -227,7 +227,8 @@ private byte[] generateConfigurationJar(final String family, final Properties us mainAttributes.putValue("Created-By", "Talend Component Kit Server"); mainAttributes.putValue("Talend-Time", Long.toString(System.currentTimeMillis())); mainAttributes.putValue("Talend-Family-Name", family); - try (final JarOutputStream jar = new JarOutputStream(new BufferedOutputStream(outputStream), manifest)) { + try (final BufferedOutputStream buffered = new BufferedOutputStream(outputStream); + final JarOutputStream jar = new JarOutputStream(buffered, manifest)) { jar.putNextEntry(new JarEntry("TALEND-INF/local-configuration.properties")); userConfiguration.store(jar, "Configuration of the family " + family); jar.closeEntry(); @@ -300,9 +301,8 @@ private Map findJars(final Path familyFolder, final String famil if (!Files.isDirectory(familyFolder)) { return emptyMap(); } - try { - return Files - .list(familyFolder) + try (final Stream files = Files.list(familyFolder)) { + return files .filter(file -> file.getFileName().toString().endsWith(".jar")) .collect(toMap(it -> { try { diff --git a/component-tools/src/main/java/org/talend/sdk/component/tools/AsciidoctorExecutor.java b/component-tools/src/main/java/org/talend/sdk/component/tools/AsciidoctorExecutor.java index 67872d0d7eab1..f57b625b3902f 100644 --- a/component-tools/src/main/java/org/talend/sdk/component/tools/AsciidoctorExecutor.java +++ b/component-tools/src/main/java/org/talend/sdk/component/tools/AsciidoctorExecutor.java @@ -86,7 +86,10 @@ public void doMain(final String[] args) throws IOException { final Path adoc = PathFactory.get(args[0]).toAbsolutePath(); final File output = adoc.getParent().resolve(args.length > 1 ? args[1] : args[0].replace(".adoc", ".pdf")).toFile(); - final List lines = Files.lines(adoc).collect(toList()); + final List lines; + try (final Stream stream = Files.lines(adoc)) { + lines = stream.collect(toList()); + } final String version = lines .stream() .filter(it -> it.startsWith("v")) diff --git a/documentation/src/main/java/org/talend/runtime/documentation/WriteIfDifferentStream.java b/documentation/src/main/java/org/talend/runtime/documentation/WriteIfDifferentStream.java index 62344e073db21..b2201d10eb3e6 100644 --- a/documentation/src/main/java/org/talend/runtime/documentation/WriteIfDifferentStream.java +++ b/documentation/src/main/java/org/talend/runtime/documentation/WriteIfDifferentStream.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; @@ -53,7 +54,10 @@ public void close() throws IOException { } private boolean isDifferent(final byte[] bytes) throws IOException { - final String source = Files.lines(destination.toPath()).collect(joining("\n")).trim(); + final String source; + try (final Stream lines = Files.lines(destination.toPath())) { + source = lines.collect(joining("\n")).trim(); + } final String target = new String(bytes, StandardCharsets.UTF_8).trim(); return !source.equals(target); } diff --git a/talend-component-maven-plugin/src/main/java/org/talend/sdk/component/maven/WebsiteBuilderMojo.java b/talend-component-maven-plugin/src/main/java/org/talend/sdk/component/maven/WebsiteBuilderMojo.java index d4ca80617014b..12292c029e5c6 100644 --- a/talend-component-maven-plugin/src/main/java/org/talend/sdk/component/maven/WebsiteBuilderMojo.java +++ b/talend-component-maven-plugin/src/main/java/org/talend/sdk/component/maven/WebsiteBuilderMojo.java @@ -258,7 +258,11 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { - if (Files.list(dir).count() == 0) { + final boolean empty; + try (final Stream entries = Files.list(dir)) { + empty = entries.findAny().isEmpty(); + } + if (empty) { Files.delete(dir); } return super.postVisitDirectory(dir, exc); @@ -364,17 +368,21 @@ private void generateFolder(final Object context, final Path dir, final Path tem } try { - Files.list(templatesDir).filter(it -> it.endsWith(".mustache")).forEach(template -> { - final String name = template.getFileName().toString(); - try (final Reader tpl = Files.newBufferedReader(template); - final Writer writer = Files - .newBufferedWriter( - dir.resolve(name.substring(0, name.length() - "mustache".length()) + "html"))) { - mustacheFactory.compile(tpl, dir.getFileName().toString() + '_' + name).execute(writer, context); - } catch (final IOException e) { - throw new IllegalStateException(e); - } - }); + try (final Stream templates = Files.list(templatesDir)) { + templates.filter(it -> it.endsWith(".mustache")).forEach(template -> { + final String name = template.getFileName().toString(); + try (final Reader tpl = Files.newBufferedReader(template); + final Writer writer = Files + .newBufferedWriter( + dir.resolve(name.substring(0, name.length() - "mustache".length()) + + "html"))) { + mustacheFactory.compile(tpl, dir.getFileName().toString() + '_' + name) + .execute(writer, context); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + }); + } } catch (final IOException e) { throw new IllegalStateException(e); }