001    package com.thaiopensource.validate.auto;
002    
003    import org.xml.sax.XMLReader;
004    import org.xml.sax.SAXException;
005    import org.xml.sax.Locator;
006    import org.xml.sax.Attributes;
007    import org.xml.sax.ContentHandler;
008    import org.xml.sax.SAXParseException;
009    import org.xml.sax.helpers.DefaultHandler;
010    
011    import java.io.IOException;
012    import java.util.Vector;
013    
014    import com.thaiopensource.validate.Schema;
015    import com.thaiopensource.validate.IncorrectSchemaException;
016    import com.thaiopensource.util.Localizer;
017    import com.thaiopensource.util.PropertyMap;
018    
019    public class AutoSchemaReceiver implements SchemaReceiver {
020      private final PropertyMap properties;
021      private final Rewindable rewindable;
022    
023      private class Handler extends DefaultHandler implements SchemaFuture {
024        private final XMLReader xr;
025        private SchemaFuture sf = null;
026        private Locator locator = null;
027        private final Vector prefixMappings = new Vector();
028    
029        private Handler(XMLReader xr) {
030          this.xr = xr;
031        }
032    
033        public void setDocumentLocator(Locator locator) {
034          this.locator = locator;
035        }
036    
037        public void startPrefixMapping(String prefix, String uri) {
038          prefixMappings.addElement(prefix);
039          prefixMappings.addElement(uri);
040        }
041    
042        public void startElement(String uri, String localName,
043                                 String qName, Attributes attributes)
044                throws SAXException {
045          SchemaReceiverFactory srf = SchemaReceiverFactory.PROPERTY.get(properties);
046          SchemaReceiver sr = srf.createSchemaReceiver(uri, properties);
047          if (sr == null) {
048            Localizer localizer = new Localizer(AutoSchemaReceiver.class);
049            String detail = ("".equals(uri)
050                             ? localizer.message("no_namespace")
051                             : localizer.message("unknown_namespace", uri));
052            throw new SAXParseException(detail, locator);
053          }
054          sf = sr.installHandlers(xr);
055          rewindable.willNotRewind();
056          ContentHandler contentHandler = xr.getContentHandler();
057          if (contentHandler == null)
058            return;
059          if (locator != null) {
060            contentHandler.setDocumentLocator(locator);
061            contentHandler = xr.getContentHandler();
062          }
063          contentHandler.startDocument();
064          contentHandler = xr.getContentHandler();
065          for (int i = 0, len = prefixMappings.size(); i < len; i += 2) {
066            contentHandler.startPrefixMapping((String)prefixMappings.elementAt(i),
067                                              (String)prefixMappings.elementAt(i + 1));
068            contentHandler = xr.getContentHandler();
069          }
070          contentHandler.startElement(uri, localName, qName, attributes);
071        }
072    
073        public Schema getSchema() throws IncorrectSchemaException, SAXException, IOException {
074          if (sf == null)
075            throw new IncorrectSchemaException();
076          return sf.getSchema();
077        }
078    
079        public RuntimeException unwrapException(RuntimeException e) throws SAXException, IOException, IncorrectSchemaException {
080          if (sf == null)
081            return e;
082          return sf.unwrapException(e);
083        }
084      }
085    
086      public AutoSchemaReceiver(PropertyMap properties, Rewindable rewindable) {
087        this.properties = properties;
088        this.rewindable = rewindable;
089      }
090    
091      public SchemaFuture installHandlers(XMLReader xr) {
092        Handler h = new Handler(xr);
093        xr.setContentHandler(h);
094        return h;
095      }
096    }