2011-11-17 4 views
5

Estoy tratando de validar un archivo XML contra un esquema en Java y el problema es que si la validación del archivo falla, entonces el archivo queda bloqueado hasta que la aplicación finaliza. Si el archivo de entrada era válido, entonces el archivo no se bloquea y todo está bien.El Validador de Java bloquea el archivo en caso de falla. ¿Qué estoy haciendo mal?

Estoy usando el método javax.xml.validation.Validator y validate(). Esto parece bastante simple y está bien cuando se aprueba la validación. Solo puedo suponer que me falta algo en mi manejo de errores, pero la API para Validator no parece proporcionar nada que sea útil. ¿Alguien puede arrojar luz sobre lo que estoy haciendo mal aquí?

He simplificado todo esto en una clase independiente a continuación. Si ejecuta esto, entonces en el punto en que se inicia el Escáner, verifique el archivo de entrada y puede ver que ahora está bloqueado. Puedo proporcionar un archivo de entrada y estructura si lo requiere.

Gracias,

Phil

 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.net.URI; 
import java.util.Scanner; 

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; 

public class ValidationTest { 

    public static void validate(URI xmlLocation, URI schemaLocation) throws Exception { 

     SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); 

     Source schemaSource = new StreamSource(schemaLocation.toString()); 
     Schema schema = schemaFactory.newSchema(schemaSource); 

     Validator schemaValidator = schema.newValidator(); 

     StreamSource source = new StreamSource(xmlLocation.getPath()); 
     schemaValidator.validate(source); 
    } 


    public static void main(String[] args) throws Exception { 
     File srcFile = new File("c:/aaa/MySrc-Broken.xml"); 
     File schema = new File("c:/aaa/MyStructureDefinition.xsd"); 

     try { 
      ValidationTest.validate(srcFile.toURI(), schema.toURI()); 
     } catch(Exception e) { 
      System.err.println(e); 
     } 

     // Use a Scanner to pause the thread, so that I can 
     // go and check the file's permissions. 
     Scanner scan = new Scanner(System.in); 
     scan.nextLine(); 
    } 
} 

 

Actualización:

Tengo un poco de un truco que proporciona una solución de (mala). Agrego un errorHandler personalizado a schemaValidator. Este errorHandler simplemente almacena cualquier error en una variable miembro. Esto significa que el validador siempre tendrá éxito y, por lo tanto, liberará todos los bloqueos en el archivo de entrada. Sin embargo, luego tengo que verificar el controlador de errores para ver si hubo algún error y luego arrojar un error si hubiera. Esto no es genial pero me ayuda a resolver este problema.

Respuesta

1

detecta la excepción planteada en su llamada a validate(), cierre el objeto StreamSource vinculado a su archivo para liberar los recursos del archivo y luego agregue la excepción a su método de llamada.

editar: puede que tenga que recuperar el InputStream explícitamente para cerrar el manejador del archivo subyacente; parece que StreamSource no define una forma explícita de cerrar la secuencia subyacente. Comprueba si obtienes un objeto InputStream devuelto por source.getInputStream(); si es así, al cerrarlo se deberían liberar los identificadores subyacentes de tu archivo.

+1

Parece una solución para un error, ¿sí? –

+0

O eso o está siendo causado por el OP que usa las clases incorrectamente. No he utilizado StreamSources personalmente, así que no tengo más consejos que ofrecer, pero un archivo bloqueado equivale a un identificador de archivo inédito, y el único candidato que veo más arriba es el objeto StreamSource. – mcfinnigan

+1

Parece un error ... "si la validación del archivo falla, entonces el archivo se bloquea hasta que la aplicación finaliza. Si el archivo de entrada era válido, entonces el archivo no se bloquea y todo está bien". En mi humilde opinión, el archivo debe estar siempre bloqueado o liberado independientemente del resultado.Corrija mi noción si me equivoco – Pitelk

3

Tenga en cuenta que las instancias de StreamSource no están permitidas. (http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/Validator.html)

URL xmlFileURL = xmlFileToCheck.toURI().toURL(); 
InputStream inputStream = xmlFileURL.openStream(); 
InputSource is = new InputSource(inputStream); 
SAXSource saxSource = new SAXSource(is); 

xmlValidator.validate(saxSource); 

inputStream.close(); // this is probably important... 
+0

No existe tal restricción en el último JDK, aún este error está presente. Debe instanciar un FileInputStream y cerrarlo en el manejador de excepciones. :( –

+0

Esto ayudó. Gracias – puspen

0

El validador no tiene manera de cerrar una Source. Esto podría ser la única razón you are not supposed to use a StreamSource with the validate() method. (Pero puede haber otros, lo que podría querer reconsiderar su enfoque.)

La aplicación tendrá que hacerse cargo de cerrar las corrientes. Para asegurarse de que esto ocurra, puede usar un bloque finally.

public static void validate(URI xmlLocation, URI schemaLocation) 
    throws Exception 
{ 
    SchemaFactory schemaFactory = 
    SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); 
    InputStream sIn = schemaLocation.toURL().openStream(); 
    try { 
    Source schemaSource = new StreamSource(sIn, schemaLocation.toString()); 
    Schema schema = schemaFactory.newSchema(schemaSource); 
    Validator schemaValidator = schema.newValidator(); 
    InputStream xIn = xmlLocation.toURL().openStream(); 
    try { 
     StreamSource source = new StreamSource(xIn, xmlLocation.toString()); 
     schemaValidator.validate(source); 
    } finally { 
     xIn.close(); 
    } 
    } finally { 
    sIn.close(); 
    } 
} 
Cuestiones relacionadas