View Javadoc

1   package fr.in2p3.jsaga.helpers;
2   
3   import fr.in2p3.jsaga.Base;
4   import org.w3c.dom.Document;
5   import org.w3c.dom.Element;
6   import org.xml.sax.SAXException;
7   import org.xml.sax.SAXParseException;
8   
9   import javax.xml.parsers.*;
10  import javax.xml.transform.*;
11  import javax.xml.transform.dom.DOMSource;
12  import javax.xml.transform.stream.StreamResult;
13  import java.io.*;
14  
15  /* ***************************************************
16  * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
17  * ***             http://cc.in2p3.fr/             ***
18  * ***************************************************
19  * File:   XMLFileParser
20  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
21  * Date:   16 avr. 2007
22  * ***************************************************
23  * Description:                                      */
24  /**
25   *
26   */
27  public class XMLFileParser {
28      /**
29       * Note: DocumentBuilderFactory is thread-safe, while DocumentBuilder is not.
30       */
31      private DocumentBuilderFactory m_parser;
32  
33      public XMLFileParser(String[] schemaResourcePaths) throws IOException {
34          System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
35                  "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
36          System.setProperty("javax.xml.parsers.SAXParserFactory",
37                  "org.apache.xerces.jaxp.SAXParserFactoryImpl");
38          System.setProperty("org.apache.xerces.xni.parser.XMLParserConfiguration",
39                  "org.apache.xerces.parsers.XIncludeParserConfiguration");
40          m_parser = DocumentBuilderFactory.newInstance();
41          m_parser.setNamespaceAware(true);
42          if (schemaResourcePaths!=null && schemaResourcePaths.length>0) {
43              extractSchemaFiles(schemaResourcePaths);
44              m_parser.setValidating(true);
45              m_parser.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
46                      "http://www.w3.org/2001/XMLSchema");
47              m_parser.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource",
48                      new File(Base.JSAGA_VAR, schemaResourcePaths[0]).getAbsolutePath());
49          } else {
50              m_parser.setValidating(false);
51          }
52      }
53  
54      public XMLFileParser() throws IOException {
55          this(null);
56      }
57  
58      /**
59       * Note: included files are relative to the parent directory of this file.
60       */
61      public byte[] xinclude(InputStream xmlStream) throws ParserConfigurationException, IOException, SAXException, TransformerException {
62          ByteArrayOutputStream dump = new ByteArrayOutputStream();
63          dump(m_parser.newDocumentBuilder().parse(xmlStream), dump);
64          return dump.toByteArray();
65      }
66  
67      /**
68       * Note: included files are relative to the working directory of the application.
69       */
70      public Document parse(InputStream xmlStream, File dumpMergedFile) throws ParserConfigurationException, IOException, SAXException, TransformerException {
71          Document doc;
72          if (m_parser.isValidating()) {
73              DocumentBuilder builder = m_parser.newDocumentBuilder();
74              XMLFileParserExceptionHandler handler = new XMLFileParserExceptionHandler();
75              builder.setErrorHandler(handler);
76              doc = builder.parse(xmlStream);
77              if(handler.getSAXParseException() != null) {
78                  SAXParseException e = handler.getSAXParseException();
79                  String filename;
80                  if (e.getSystemId() != null) {
81                      filename = new File(e.getSystemId()).getName();
82                  } else {
83                      filename = dumpMergedFile.getName();
84                      if (dumpMergedFile.getParentFile().mkdirs()) {
85                          dump(doc, new FileOutputStream(dumpMergedFile));
86                      }
87                  }
88                  throw new SAXException("["+filename+": "+e.getLineNumber()+"] "+e.getMessage());
89              }
90          } else {
91              DocumentBuilder builder = m_parser.newDocumentBuilder();
92              doc = builder.parse(xmlStream);
93          }
94          return doc;
95      }
96  
97      public static void dump(Document doc, OutputStream out) throws TransformerException {
98          dump(doc.getDocumentElement(), out);
99      }
100     public static void dump(Element doc, OutputStream out) throws TransformerException {
101         Transformer transformer = TransformerFactory.newInstance().newTransformer();
102         transformer.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, "xml");
103         transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
104         transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
105         transformer.setOutputProperty("{http://xml.apache.org/xalan/}indent-amount", "4");
106         transformer.transform(new DOMSource(doc), new StreamResult(out));
107     }
108 
109     private void extractSchemaFiles(String[] schemaResourcePaths) throws IOException {
110         for (int i=0; schemaResourcePaths!=null && i<schemaResourcePaths.length; i++) {
111             String resourcePath = schemaResourcePaths[i];
112             File schemaFile = new File(Base.JSAGA_VAR, resourcePath);
113             if (!schemaFile.exists()) {
114                 InputStream in = getClass().getClassLoader().getResourceAsStream(resourcePath);
115                 if (in == null) {
116                     throw new IOException("Schema resource not found: "+resourcePath);
117                 }
118                 schemaFile.getParentFile().mkdirs();
119                 copyBytes(in, new FileOutputStream(schemaFile));
120             }
121         }
122     }
123 
124     private void copyBytes(InputStream in, OutputStream out) throws IOException {
125         byte[] buffer = new byte[1024];
126         int len;
127         while((len=in.read(buffer))>0) {
128             out.write(buffer, 0, len);
129         }
130         out.close();
131         in.close();
132     }
133 }