001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.bind.v2.runtime.unmarshaller;
027:
028: import javax.xml.bind.annotation.DomHandler;
029: import javax.xml.transform.Result;
030: import javax.xml.transform.sax.TransformerHandler;
031:
032: import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
033:
034: import org.xml.sax.SAXException;
035:
036: /**
037: * Loads a DOM.
038: *
039: * @author Kohsuke Kawaguchi
040: */
041: public class DomLoader<ResultT extends Result> extends Loader {
042:
043: private final DomHandler<?, ResultT> dom;
044:
045: /**
046: * Used to capture the state.
047: *
048: * This instance is created for each unmarshalling episode.
049: */
050: private final class State {
051: /** This handler will receive SAX events. */
052: private final TransformerHandler handler = JAXBContextImpl
053: .createTransformerHandler();
054:
055: /** {@link #handler} will produce this result. */
056: private final ResultT result;
057:
058: // nest level of elements.
059: int depth = 1;
060:
061: public State(UnmarshallingContext context) throws SAXException {
062: result = dom.createUnmarshaller(context);
063:
064: handler.setResult(result);
065:
066: // emulate the start of documents
067: try {
068: handler.setDocumentLocator(context.getLocator());
069: handler.startDocument();
070: declarePrefixes(context, context
071: .getAllDeclaredPrefixes());
072: } catch (SAXException e) {
073: context.handleError(e);
074: throw e;
075: }
076: }
077:
078: public Object getElement() {
079: return dom.getElement(result);
080: }
081:
082: private void declarePrefixes(UnmarshallingContext context,
083: String[] prefixes) throws SAXException {
084: for (int i = prefixes.length - 1; i >= 0; i--) {
085: String nsUri = context.getNamespaceURI(prefixes[i]);
086: if (nsUri == null)
087: throw new IllegalStateException("prefix \'"
088: + prefixes[i] + "\' isn't bound");
089: handler.startPrefixMapping(prefixes[i], nsUri);
090: }
091: }
092:
093: private void undeclarePrefixes(String[] prefixes)
094: throws SAXException {
095: for (int i = prefixes.length - 1; i >= 0; i--)
096: handler.endPrefixMapping(prefixes[i]);
097: }
098: }
099:
100: public DomLoader(DomHandler<?, ResultT> dom) {
101: super (true);
102: this .dom = dom;
103: }
104:
105: public void startElement(UnmarshallingContext.State state,
106: TagName ea) throws SAXException {
107: UnmarshallingContext context = state.getContext();
108: if (state.target == null)
109: state.target = new State(context);
110:
111: State s = (State) state.target;
112: try {
113: s.declarePrefixes(context, context
114: .getNewlyDeclaredPrefixes());
115: s.handler.startElement(ea.uri, ea.local, ea.getQname(),
116: ea.atts);
117: } catch (SAXException e) {
118: context.handleError(e);
119: throw e;
120: }
121: }
122:
123: public void childElement(UnmarshallingContext.State state,
124: TagName ea) throws SAXException {
125: state.loader = this ;
126: State s = (State) state.prev.target;
127: s.depth++;
128: state.target = s;
129: }
130:
131: public void text(UnmarshallingContext.State state, CharSequence text)
132: throws SAXException {
133: if (text.length() == 0)
134: return; // there's no point in creating an empty Text node in DOM.
135: try {
136: State s = (State) state.target;
137: s.handler.characters(text.toString().toCharArray(), 0, text
138: .length());
139: } catch (SAXException e) {
140: state.getContext().handleError(e);
141: throw e;
142: }
143: }
144:
145: public void leaveElement(UnmarshallingContext.State state,
146: TagName ea) throws SAXException {
147: State s = (State) state.target;
148: UnmarshallingContext context = state.getContext();
149:
150: try {
151: s.handler.endElement(ea.uri, ea.local, ea.getQname());
152: s.undeclarePrefixes(context.getNewlyDeclaredPrefixes());
153: } catch (SAXException e) {
154: context.handleError(e);
155: throw e;
156: }
157:
158: if ((--s.depth) == 0) {
159: // emulate the end of the document
160: try {
161: s.undeclarePrefixes(context.getAllDeclaredPrefixes());
162: s.handler.endDocument();
163: } catch (SAXException e) {
164: context.handleError(e);
165: throw e;
166: }
167:
168: // we are done
169: state.target = s.getElement();
170: }
171: }
172:
173: }
|