001    package com.oxygenxml.validate.isoschematron;
002    
003    import com.thaiopensource.util.PropertyMap;
004    import com.thaiopensource.validate.ValidateProperty;
005    import com.thaiopensource.validate.Validator;
006    import com.thaiopensource.xml.sax.DelegatingContentHandler;
007    import org.xml.sax.ContentHandler;
008    import org.xml.sax.DTDHandler;
009    import org.xml.sax.ErrorHandler;
010    import org.xml.sax.InputSource;
011    import org.xml.sax.Locator;
012    import org.xml.sax.SAXException;
013    
014    import javax.xml.transform.Templates;
015    import javax.xml.transform.Transformer;
016    import javax.xml.transform.TransformerConfigurationException;
017    import javax.xml.transform.TransformerException;
018    import javax.xml.transform.sax.SAXResult;
019    import javax.xml.transform.sax.SAXSource;
020    
021    class ValidatorImpl extends DelegatingContentHandler implements Validator {
022      private final Transformer transformer;
023      private Locator locator;
024      private TransformerException transformerException;
025    
026      private final Object contentHandlerMonitor = new Object();
027      private final Object parseMonitor = new Object();
028      private final Object transformMonitor = new Object();
029      private Thread transformThread;
030      private final ContentHandler outputHandler;
031    
032      class BlockingReader extends XMLReaderImpl {
033        public void parse(InputSource in) throws SAXException {
034          synchronized (parseMonitor) {
035            synchronized (contentHandlerMonitor) {
036              contentHandlerMonitor.notify();
037            }
038            try {
039              parseMonitor.wait();
040            }
041            catch (InterruptedException e) {
042              throw new SAXException(e);
043            }
044          }
045        }
046    
047        public void setContentHandler(ContentHandler handler) {
048          setDelegate(handler);
049        }
050    
051        public ContentHandler getContentHandler() {
052          return getDelegate();
053        }
054    
055      }
056    
057      ValidatorImpl(Templates templates, PropertyMap properties) {
058        ErrorHandler eh = ValidateProperty.ERROR_HANDLER.get(properties);
059        outputHandler = new OutputHandler(eh);
060        try {
061          transformer = templates.newTransformer();
062          // XXX set up transformer with a resolver that uses the resolver
063          // XXX and XMLReaderCreator from properties
064          // XXX set up transformer with an ErrorListener that just throws
065        }
066        catch (TransformerConfigurationException e) {
067          throw new RuntimeException("could not create transformer");
068        }
069      }
070    
071      public ContentHandler getContentHandler() {
072        return this;
073      }
074    
075      public DTDHandler getDTDHandler() {
076        return null;
077      }
078    
079      public void reset() {
080        if (transformThread != null) {
081          synchronized (transformMonitor) {
082            transformThread.interrupt();
083            try {
084              transformMonitor.wait();
085            }
086            catch (InterruptedException e) { }
087            transformThread = null;
088          }
089        }
090        transformerException = null;
091        locator = null;
092      }
093    
094      public void setDocumentLocator(Locator locator) {
095        this.locator = locator;
096      }
097    
098      public void startDocument()
099              throws SAXException {
100        final SAXSource source = new SAXSource(new BlockingReader(),
101                                               new InputSource(""));
102        transformThread = new Thread(new Runnable() {
103          public void run() {
104            try {
105              transformer.transform(source, new SAXResult(outputHandler));
106            }
107            catch (TransformerException e) {
108              transformerException = e;
109            }
110            finally {
111              synchronized (transformMonitor) {
112                transformMonitor.notify();
113              }
114            }
115          }
116        }, "Transform");
117        synchronized (contentHandlerMonitor) {
118          transformThread.start();
119          try {
120            contentHandlerMonitor.wait();
121          }
122          catch (InterruptedException e) {
123            throw new SAXException(e);
124          }
125        }
126        if (locator != null)
127          super.setDocumentLocator(locator);
128        super.startDocument();
129      }
130    
131      public void endDocument()
132              throws SAXException {
133        super.endDocument();
134        synchronized (transformMonitor) {
135          synchronized (parseMonitor) {
136            parseMonitor.notify();
137          }
138          try {
139            transformMonitor.wait();
140          }
141          catch (InterruptedException e) {
142            throw new SAXException(e);
143          }
144          finally {
145            transformThread = null;
146          }
147        }
148        if (transformerException != null)
149          throw toSAXException(transformerException);
150      }
151    
152      static SAXException toSAXException(TransformerException transformerException) {
153        // Unwrap where possible
154        Throwable wrapped = transformerException.getException();
155        if (wrapped instanceof SAXException)
156          return (SAXException)wrapped;
157        if (wrapped instanceof RuntimeException)
158          throw (RuntimeException)wrapped;
159        if (wrapped instanceof Exception)
160          return new SAXException((Exception)wrapped);
161        return new SAXException(transformerException);
162      }
163    }