FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600]
A DESCRIPTION OF THE PROBLEM :
Using javax.xml.validation.Validator to validate an invalid XML against a schema does not close the file handle. Because of this, on Windows it is not possible to delete the file afterwards.
ADDITIONAL REGRESSION INFORMATION:
There are some comments in com.sun.org.apache.xerces.internal.impl.XMLEntityManager.closeReaders that indicates that might have worked in Java 5.
/** this call actually does nothing, readers are closed in the endEntity method
* through the current entity.
* The change seems to have happened during the jdk6 development with the
* addition of StAX
**/
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run source code attached to this bug
2. This results in an exception such as "The process cannot access the file because it is being used by another process."
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Using Validator should close the file handle in all cases.
ACTUAL -
The file handle is not closed, therefore it is not possible to delete the file.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.nio.file.FileSystemException: testfile.txt: The process cannot access the file because it is being used by another process.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1126)
at Main.main(Main.java:55)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.xml.sax.SAXException;
public class Main {
private static final String XSD_PATH = "testschema.xsd";
private static final String XSD = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ " attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\">"
+ "<xs:element name=\"myelement\">" + "</xs:element>" + "</xs:schema>";
private static final String TESTED_FILE_PATH = "testfile.txt";
private static final String TESTED_FILE_CONTENT = "foo";
public static void main(String[] args) {
// Generate test files
File xsdFile = new File(XSD_PATH);
File testedFile = new File(TESTED_FILE_PATH);
try (FileWriter w = new FileWriter(xsdFile); FileWriter w2 = new FileWriter(testedFile)) {
w.append(XSD);
xsdFile.deleteOnExit();
w2.append(TESTED_FILE_CONTENT);
} catch (IOException e2) {
e2.printStackTrace();
}
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source xmlSource = new StreamSource(testedFile);
try {
URL url = xsdFile.toURI().toURL();
Schema schema = schemaFactory.newSchema(url);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
} catch (SAXException | IOException e) {
System.out.println("not valid");
}
try {
// Fails because file handle not closed
Files.delete(Paths.get(TESTED_FILE_PATH));
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
In some situations, it is possible to work around this kind of problem by not deleting files.