Project

Profile

Help

Handle leak while transforming an XML file ?

Added by NoData Found over 8 years ago

Hello,

I am working on Windows 7 x64 with Saxon-HE 9.7.0-1

I have a list of XML file that I wish to process using some stylesheet and to that end, I use JAXB and the following Java code:


    final TransformerFactory tf = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", this.getClass().getClassLoader());
    tf.setFeature(FeatureKeys.LINE_NUMBERING, true);

    final InputStream stream = this.getClass().getResourceAsStream("/stylesheets/mediainfo.xsl");
    final URL uri = this.getClass().getResource("/stylesheets");

    final Source stylesheet = new StreamSource(stream, uri.toString());

    final Transformer transformer = tf.newTransformer(stylesheet);
    transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, indent ? "yes" : "no");
    for (final Path path : files) {
      final StreamSource source = new StreamSource(path.toFile());
      final Path tmp = Files.createTempFile(path.getParent(), path.getFileName().toString(), "~");
      final Result target = new StreamResult(tmp.toFile());

      transformer.transform(source, target);

      Files.move(tmp, path, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
    }

The move operation fails with the following message "Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus." (it is French for "File is being used by another person or program").

Upon investigating, I think the error is in method net.sf.saxon.jaxp.TransformerImpl.transform(Source, Result)


                    FileOutputStream stream;
                    try {
                        stream = new FileOutputStream(file);
                        closeResultAfterUse = true;
                    } catch (FileNotFoundException e) {
                        throw new XPathException("Failed to create output file", e);
                    }
                    destination = xsltExecutable.getProcessor().newSerializer(stream);

As far as I understood the code, the class Serializer closes its output stream only when it was initialized with a File instance, which is not the case here. So, the method transform invoke destination.close() ... which does nothing in that case.

If I switch to Input/OutputStream in the main loop, the error goes away:


    for (final Path path : files) {
      final Path tmp = Files.createTempFile(path.getParent(), path.getFileName().toString(), "~");
      try (final InputStream  is = Files.newInputStream(path);
           final OutputStream os = Files.newOutputStream(tmp)) {
        transformer.transform(new StreamSource(is), new StreamResult(os));
      }
      Files.move(tmp, path, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
    }

Should I create a bug report instead?

Regards,


Replies (3)

Please register to reply

RE: Handle leak while transforming an XML file ? - Added by Michael Kay over 8 years ago

It looks as if we failed to apply the fix for bug #2250 on the 9.7 development branch. Sorry about that: I will reopen bug #2250.

RE: Handle leak while transforming an XML file ? - Added by NoData Found over 8 years ago

No problem. Dealing with a try-with-resources is a fine work-around for me.

RE: Handle leak while transforming an XML file ? - Added by O'Neil Delpratt almost 8 years ago

We have applied a fix to this in the Serializer class to close the file upon completion. Regression testing done, but not really been tested on all platforms

    (1-3/3)

    Please register to reply