1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xerces.internal.util;
  23 
  24 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
  25 import com.sun.org.apache.xerces.internal.jaxp.validation.WrappedSAXException;
  26 import com.sun.org.apache.xerces.internal.xni.QName;
  27 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  28 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  29 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  30 import com.sun.org.apache.xerces.internal.xni.XMLString;
  31 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  32 import org.xml.sax.Attributes;
  33 import org.xml.sax.ContentHandler;
  34 import org.xml.sax.Locator;
  35 import org.xml.sax.SAXException;
  36 
  37 /**
  38  * Receves SAX {@link ContentHandler} events
  39  * and produces the equivalent {@link XMLDocumentHandler} events.
  40  *
  41  * @author
  42  *     Kohsuke Kawaguchi
  43  */
  44 public class SAX2XNI implements ContentHandler, XMLDocumentSource {
  45     public SAX2XNI( XMLDocumentHandler core ) {
  46         this.fCore = core;
  47     }
  48 
  49     private XMLDocumentHandler fCore;
  50 
  51     private final NamespaceSupport nsContext = new NamespaceSupport();
  52     private final SymbolTable symbolTable = new SymbolTable();
  53 
  54 
  55     public void setDocumentHandler(XMLDocumentHandler handler) {
  56         fCore = handler;
  57     }
  58 
  59     public XMLDocumentHandler getDocumentHandler() {
  60         return fCore;
  61     }
  62 
  63 
  64     //
  65     //
  66     // ContentHandler implementation
  67     //
  68     //
  69     public void startDocument() throws SAXException {
  70         try {
  71             nsContext.reset();
  72 
  73             XMLLocator xmlLocator;
  74             if(locator==null)
  75                 // some SAX source doesn't provide a locator,
  76                 // in which case we assume no line information is available
  77                 // and use a dummy locator. With this, downstream components
  78                 // can always assume that they will get a non-null Locator.
  79                 xmlLocator=new SimpleLocator(null,null,-1,-1);
  80             else
  81                 xmlLocator=new LocatorWrapper(locator);
  82 
  83             fCore.startDocument(
  84                     xmlLocator,
  85                     null,
  86                     nsContext,
  87                     null);
  88         } catch( WrappedSAXException e ) {
  89             throw e.exception;
  90         }
  91     }
  92 
  93     public void endDocument() throws SAXException {
  94         try {
  95             fCore.endDocument(null);
  96         } catch( WrappedSAXException e ) {
  97             throw e.exception;
  98         }
  99     }
 100 
 101     public void startElement( String uri, String local, String qname, Attributes att ) throws SAXException {
 102         try {
 103             fCore.startElement(createQName(uri,local,qname),createAttributes(att),null);
 104         } catch( WrappedSAXException e ) {
 105             throw e.exception;
 106         }
 107     }
 108 
 109     public void endElement( String uri, String local, String qname ) throws SAXException {
 110         try {
 111             fCore.endElement(createQName(uri,local,qname),null);
 112         } catch( WrappedSAXException e ) {
 113             throw e.exception;
 114         }
 115     }
 116 
 117     public void characters( char[] buf, int offset, int len ) throws SAXException {
 118         try {
 119             fCore.characters(new XMLString(buf,offset,len),null);
 120         } catch( WrappedSAXException e ) {
 121             throw e.exception;
 122         }
 123     }
 124 
 125     public void ignorableWhitespace( char[] buf, int offset, int len ) throws SAXException {
 126         try {
 127             fCore.ignorableWhitespace(new XMLString(buf,offset,len),null);
 128         } catch( WrappedSAXException e ) {
 129             throw e.exception;
 130         }
 131     }
 132 
 133     public void startPrefixMapping( String prefix, String uri ) {
 134         nsContext.pushContext();
 135         nsContext.declarePrefix(prefix,uri);
 136     }
 137 
 138     public void endPrefixMapping( String prefix ) {
 139         nsContext.popContext();
 140     }
 141 
 142     public void processingInstruction( String target, String data ) throws SAXException {
 143         try {
 144             fCore.processingInstruction(
 145                     symbolize(target),createXMLString(data),null);
 146         } catch( WrappedSAXException e ) {
 147             throw e.exception;
 148         }
 149     }
 150 
 151     public void skippedEntity( String name ) {
 152     }
 153 
 154     private Locator locator;
 155     public void setDocumentLocator( Locator _loc ) {
 156         this.locator = _loc;
 157     }
 158 
 159     /** Creates a QName object. */
 160     private QName createQName(String uri, String local, String raw) {
 161 
 162         int idx = raw.indexOf(':');
 163 
 164         if( local.length()==0 ) {
 165             // if naemspace processing is turned off, local could be "".
 166             // in that case, treat everything to be in the no namespace.
 167             uri = "";
 168             if(idx<0)
 169                 local = raw;
 170             else
 171                 local = raw.substring(idx+1);
 172         }
 173 
 174         String prefix;
 175         if (idx < 0)
 176             prefix = null;
 177         else
 178             prefix = raw.substring(0, idx);
 179 
 180         if (uri != null && uri.length() == 0)
 181             uri = null; // XNI uses null whereas SAX uses the empty string
 182 
 183         return new QName(symbolize(prefix), symbolize(local), symbolize(raw), symbolize(uri));
 184     }
 185 
 186     /** Symbolizes the specified string. */
 187     private String symbolize(String s) {
 188         if (s == null)
 189             return null;
 190         else
 191             return symbolTable.addSymbol(s);
 192     }
 193 
 194     private XMLString createXMLString(String str) {
 195         // with my patch
 196         // return new XMLString(str);
 197 
 198         // for now
 199         return new XMLString(str.toCharArray(), 0, str.length());
 200     }
 201 
 202 
 203     /** only one instance of XMLAttributes is used. */
 204     private final XMLAttributes xa = new XMLAttributesImpl();
 205 
 206     /** Creates an XMLAttributes object. */
 207     private XMLAttributes createAttributes(Attributes att) {
 208         xa.removeAllAttributes();
 209         int len = att.getLength();
 210         for (int i = 0; i < len; i++)
 211             xa.addAttribute(
 212                     createQName(att.getURI(i), att.getLocalName(i), att.getQName(i)),
 213                     att.getType(i),
 214                     att.getValue(i));
 215         return xa;
 216     }
 217 }