Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7077542

javax.xml.parsers.DocumentBuilder.parse(File) does not always close file.

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 6u26
    • xml

      FULL PRODUCT VERSION :
      java version "1.6.0_26"
      Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
      Java HotSpot(TM) Client VM (build 20.1-b02, mixed mode, sharing)

      also

      java version "1.7.0"
      Java(TM) SE Runtime Environment (build 1.7.0-b147)
      Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      When javax.xml.parsers.DocumentBuilder.parse(File) is called and a SAXException is thrown in the ErrorHandler, the file is not closed.

      This bug is present in java 1.6.0_26 and java 1.7.0. This bug is not present in java 1.5.0_22.

      REGRESSION. Last worked in version 5.0

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Use an instance of javax.xml.parsers.DocumentBuilder to parse a java.io.File that contains XML that is not well-formed.

      2. Check that the XML file is still open (e.g. by trying to delete it).


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The parse will cause a SAXException to be thrown. Using a finally block it should be possible to delete the XML input file.
      ACTUAL -
      The XML input file could not be deleted.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.Closeable;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.IOException;

      import javax.xml.parsers.DocumentBuilder;
      import javax.xml.parsers.DocumentBuilderFactory;
      import javax.xml.parsers.ParserConfigurationException;

      import org.xml.sax.ErrorHandler;
      import org.xml.sax.SAXException;
      import org.xml.sax.SAXParseException;

      public class Main {
         private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
         private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

         private static class SimpleErrorHandler implements ErrorHandler {
            private final boolean rethrow;

            public SimpleErrorHandler( boolean rethrow )
            {
               this.rethrow = rethrow;
            }

            public void error( SAXParseException ex ) throws SAXException
            {
               conditionallyThrow( ex );
            }

            public void fatalError( SAXParseException ex ) throws SAXException
            {
               conditionallyThrow( ex );
            }

            public void warning( SAXParseException ex ) throws SAXException
            {
               conditionallyThrow( ex );
            }

            private void conditionallyThrow( SAXException ex ) throws SAXException
            {
               if(this.rethrow) {
                  throw ex;
               }
            }
         }

         // The output should be:
         //
         // File "D:\work\Parse\temp.xml" deleted.
         // File "D:\work\Parse\temp.xml" deleted.
         //
         // but in java 1.6.0_26 and java 1.7.0 the output is:
         //
         // File "D:\work\Parse\temp.xml" deleted.
         // File "D:\work\Parse\temp.xml" not deleted.
         public static void main( String[] args ) throws Exception
         {
            Main main = new Main();
            main.test( false );
            main.test( true );
         }

         private void close( Closeable closeable )
         {
            if(closeable != null) {
               try {
                  closeable.close();
               } catch(IOException ex) {
                  ex.printStackTrace();
               }
            }
         }

         private File getFile() throws IOException
         {
            File fileIn = new File( "save.xml" );
            File fileOut = new File( "temp.xml" );
            FileInputStream in = null;
            FileOutputStream out = null;

            try {
               in = new FileInputStream( fileIn );
               out = new FileOutputStream( fileOut );

               byte[] buffer = new byte[ 4096 ];
               int read;

               while(( read = in.read( buffer ) ) != -1) {
                  out.write( buffer, 0, read );
               }
            } finally {
               close( out );
               close( in );
            }

            return fileOut;
         }

         private void test( boolean rethrow ) throws ParserConfigurationException, IOException
         {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setAttribute( JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA );
            factory.setNamespaceAware( true );
            factory.setValidating( true );
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setErrorHandler( new SimpleErrorHandler( rethrow ) );
            File file = getFile();

            try {
               builder.parse( file );
            } catch(SAXException ex) {
               // System.out.println( ex );
            } finally {
               System.out.println( "File \"" + file.getAbsolutePath() + "\"" +
                                   ( file.delete() ? " deleted." : " not deleted." ) );
            }
         }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use DocumentBuilder.parse(InputStream) and then close the input stream in a finally block.

            aefimov Aleksej Efimov
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: