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
22package com.sun.org.apache.xerces.internal.util;
23
24import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
25import com.sun.org.apache.xerces.internal.jaxp.validation.WrappedSAXException;
26import com.sun.org.apache.xerces.internal.xni.QName;
27import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
28import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
29import com.sun.org.apache.xerces.internal.xni.XMLLocator;
30import com.sun.org.apache.xerces.internal.xni.XMLString;
31import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
32import org.xml.sax.Attributes;
33import org.xml.sax.ContentHandler;
34import org.xml.sax.Locator;
35import 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 (kohsuke.kawaguchi@sun.com)
43 */
44public 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}
218