001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.bind.v2.runtime.unmarshaller;
038:
039: import javax.xml.bind.JAXBException;
040: import javax.xml.bind.UnmarshallerHandler;
041:
042: import com.sun.xml.bind.WhiteSpaceProcessor;
043:
044: import org.xml.sax.Attributes;
045: import org.xml.sax.Locator;
046: import org.xml.sax.SAXException;
047:
048: /**
049: * Receives SAX events and convert them to our internal events.
050: *
051: * @author Kohsuke Kawaguchi
052: */
053: public final class SAXConnector implements UnmarshallerHandler {
054:
055: private LocatorEx loc;
056:
057: /**
058: * SAX may fire consective characters event, but we don't allow it.
059: * so use this buffer to perform buffering.
060: */
061: private final StringBuilder buffer = new StringBuilder();
062:
063: private final XmlVisitor next;
064: private final UnmarshallingContext context;
065: private final XmlVisitor.TextPredictor predictor;
066:
067: private static final class TagNameImpl extends TagName {
068: String qname;
069:
070: public String getQname() {
071: return qname;
072: }
073: }
074:
075: private final TagNameImpl tagName = new TagNameImpl();
076:
077: /**
078: *
079: * @param externalLocator
080: * If the caller is producing SAX events from sources other than Unicode and angle brackets,
081: * the caller can override the default SAX {@link Locator} object by this object
082: * to provide better location information.
083: */
084: public SAXConnector(XmlVisitor next, LocatorEx externalLocator) {
085: this .next = next;
086: this .context = next.getContext();
087: this .predictor = next.getPredictor();
088: this .loc = externalLocator;
089: }
090:
091: public Object getResult() throws JAXBException,
092: IllegalStateException {
093: return context.getResult();
094: }
095:
096: public UnmarshallingContext getContext() {
097: return context;
098: }
099:
100: public void setDocumentLocator(final Locator locator) {
101: if (loc != null)
102: return; // we already have an external locator. ignore.
103:
104: this .loc = new LocatorExWrapper(locator);
105: }
106:
107: public void startDocument() throws SAXException {
108: next.startDocument(loc, null);
109: }
110:
111: public void endDocument() throws SAXException {
112: next.endDocument();
113: }
114:
115: public void startPrefixMapping(String prefix, String uri)
116: throws SAXException {
117: next.startPrefixMapping(prefix, uri);
118: }
119:
120: public void endPrefixMapping(String prefix) throws SAXException {
121: next.endPrefixMapping(prefix);
122: }
123:
124: public void startElement(String uri, String local, String qname,
125: Attributes atts) throws SAXException {
126: // work gracefully with misconfigured parsers that don't support namespaces
127: if (uri == null || uri.length() == 0)
128: uri = "";
129: if (local == null || local.length() == 0)
130: local = qname;
131: if (qname == null || qname.length() == 0)
132: qname = local;
133:
134: processText(true);
135:
136: tagName.uri = uri;
137: tagName.local = local;
138: tagName.qname = qname;
139: tagName.atts = atts;
140: next.startElement(tagName);
141: }
142:
143: public void endElement(String uri, String localName, String qName)
144: throws SAXException {
145: processText(false);
146: tagName.uri = uri;
147: tagName.local = localName;
148: tagName.qname = qName;
149: next.endElement(tagName);
150: }
151:
152: public final void characters(char[] buf, int start, int len) {
153: if (predictor.expectText())
154: buffer.append(buf, start, len);
155: }
156:
157: public final void ignorableWhitespace(char[] buf, int start, int len) {
158: characters(buf, start, len);
159: }
160:
161: public void processingInstruction(String target, String data) {
162: // nop
163: }
164:
165: public void skippedEntity(String name) {
166: // nop
167: }
168:
169: private void processText(boolean ignorable) throws SAXException {
170: if (predictor.expectText()
171: && (!ignorable || !WhiteSpaceProcessor
172: .isWhiteSpace(buffer)))
173: next.text(buffer);
174: buffer.setLength(0);
175: }
176:
177: }
|