001    package com.thaiopensource.validate.xerces;
002    
003    import com.oxygenxml.validate.nvdl.NvdlProperty;
004    import com.thaiopensource.util.PropertyMap;
005    import com.thaiopensource.util.PropertyId;
006    import com.thaiopensource.validate.IncorrectSchemaException;
007    import com.thaiopensource.validate.Schema;
008    import com.thaiopensource.validate.SchemaReader;
009    import com.thaiopensource.validate.ValidateProperty;
010    import com.thaiopensource.validate.Option;
011    import com.thaiopensource.validate.xerces.SAXXMLErrorHandler;
012    import com.thaiopensource.validate.xerces.SchemaImpl;
013    import org.apache.xerces.parsers.CachingParserPool;
014    import org.apache.xerces.parsers.XMLGrammarPreparser;
015    import org.apache.xerces.util.SymbolTable;
016    import org.apache.xerces.util.SynchronizedSymbolTable;
017    import org.apache.xerces.util.XMLGrammarPoolImpl;
018    import org.apache.xerces.util.EntityResolverWrapper;
019    import org.apache.xerces.xni.XNIException;
020    import org.apache.xerces.xni.grammars.XMLGrammarDescription;
021    import org.apache.xerces.xni.grammars.XMLGrammarPool;
022    import org.apache.xerces.xni.parser.XMLInputSource;
023    import org.xml.sax.ErrorHandler;
024    import org.xml.sax.InputSource;
025    import org.xml.sax.SAXException;
026    import org.xml.sax.EntityResolver;
027    
028    import java.io.IOException;
029    import java.io.StringReader;
030    
031    class SchemaReaderImpl implements SchemaReader {
032      private static final PropertyId[] supportedPropertyIds = {
033        ValidateProperty.ERROR_HANDLER,
034        ValidateProperty.ENTITY_RESOLVER,
035      };
036      public Schema createSchema(InputSource in, PropertyMap properties)
037              throws IOException, SAXException, IncorrectSchemaException {
038        SymbolTable symbolTable = new SymbolTable();
039        XMLGrammarPreparser preparser = new XMLGrammarPreparser(symbolTable);
040        XMLGrammarPool grammarPool = new XMLGrammarPoolImpl();
041        preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null);
042        preparser.setGrammarPool(grammarPool);
043        ErrorHandler eh = ValidateProperty.ERROR_HANDLER.get(properties);
044        SAXXMLErrorHandler xeh = new SAXXMLErrorHandler(eh);
045        preparser.setErrorHandler(xeh);
046        EntityResolver er = ValidateProperty.ENTITY_RESOLVER.get(properties);
047        if (er != null)
048          preparser.setEntityResolver(new EntityResolverWrapper(er));
049        try {
050          preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, toXMLInputSource(in));
051          if (properties.contains(NvdlProperty.ATTRIBUTES_SCHEMA)) {
052            // Add a schema for virtual element.
053            String virtualElementSchema =
054                            "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://purl.oclc.org/dsdl/nvdl/ns/instance/1.0\">\n" + 
055                            "  <xs:element name=\"virtualElement\">\n" + 
056                            "    <xs:complexType>\n" + 
057                            "      <xs:anyAttribute processContents=\"strict\"/>\n" + 
058                            "    </xs:complexType>\n" + 
059                            "  </xs:element>\n" + 
060                            "</xs:schema>";
061            XMLInputSource xin = new XMLInputSource(
062                            "", 
063                            "", 
064                            "", 
065                            new StringReader(virtualElementSchema),
066                            "UTF-8");
067            preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, xin);
068          }
069        }
070        catch (XNIException e) {
071          throw ValidatorImpl.toSAXException(e);
072        }
073        if (xeh.getHadError())
074          throw new IncorrectSchemaException();
075        return new SchemaImpl(new SynchronizedSymbolTable(symbolTable),
076                              new CachingParserPool.SynchronizedGrammarPool(grammarPool),
077                              properties,
078                              supportedPropertyIds);
079      }
080    
081      public Option getOption(String uri) {
082        return null;
083      }
084    
085      private static XMLInputSource toXMLInputSource(InputSource in) {
086        XMLInputSource xin = new XMLInputSource(in.getPublicId(), in.getSystemId(), null);
087        xin.setByteStream(in.getByteStream());
088        xin.setCharacterStream(in.getCharacterStream());
089        xin.setEncoding(in.getEncoding());
090        return xin;
091      }
092    }