ohair@286: /* aefimov@650: * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.xml.internal.bind.v2.runtime.unmarshaller; ohair@286: ohair@286: import javax.xml.bind.annotation.DomHandler; ohair@286: import javax.xml.transform.Result; ohair@286: import javax.xml.transform.sax.TransformerHandler; ohair@286: import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl; ohair@286: import org.xml.sax.SAXException; ohair@286: ohair@286: /** ohair@286: * Loads a DOM. ohair@286: * ohair@286: * @author Kohsuke Kawaguchi ohair@286: */ ohair@286: public class DomLoader extends Loader { ohair@286: ohair@286: private final DomHandler dom; ohair@286: ohair@286: /** ohair@286: * Used to capture the state. ohair@286: * ohair@286: * This instance is created for each unmarshalling episode. ohair@286: */ ohair@286: private final class State { alanb@368: ohair@286: /** This handler will receive SAX events. */ alanb@368: private TransformerHandler handler = null; ohair@286: ohair@286: /** {@link #handler} will produce this result. */ ohair@286: private final ResultT result; ohair@286: ohair@286: // nest level of elements. ohair@286: int depth = 1; ohair@286: ohair@286: public State( UnmarshallingContext context ) throws SAXException { alanb@368: handler = JAXBContextImpl.createTransformerHandler(context.getJAXBContext().disableSecurityProcessing); ohair@286: result = dom.createUnmarshaller(context); ohair@286: ohair@286: handler.setResult(result); ohair@286: ohair@286: // emulate the start of documents ohair@286: try { ohair@286: handler.setDocumentLocator(context.getLocator()); ohair@286: handler.startDocument(); ohair@286: declarePrefixes( context, context.getAllDeclaredPrefixes() ); ohair@286: } catch( SAXException e ) { ohair@286: context.handleError(e); ohair@286: throw e; ohair@286: } ohair@286: } ohair@286: ohair@286: public Object getElement() { ohair@286: return dom.getElement(result); ohair@286: } ohair@286: ohair@286: private void declarePrefixes( UnmarshallingContext context, String[] prefixes ) throws SAXException { ohair@286: for( int i=prefixes.length-1; i>=0; i-- ) { ohair@286: String nsUri = context.getNamespaceURI(prefixes[i]); ohair@286: if(nsUri==null) throw new IllegalStateException("prefix \'"+prefixes[i]+"\' isn't bound"); ohair@286: handler.startPrefixMapping(prefixes[i],nsUri ); ohair@286: } ohair@286: } ohair@286: ohair@286: private void undeclarePrefixes( String[] prefixes ) throws SAXException { ohair@286: for( int i=prefixes.length-1; i>=0; i-- ) ohair@286: handler.endPrefixMapping( prefixes[i] ); ohair@286: } ohair@286: } ohair@286: ohair@286: public DomLoader(DomHandler dom) { ohair@286: super(true); ohair@286: this.dom = dom; ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException { ohair@286: UnmarshallingContext context = state.getContext(); aefimov@650: if (state.getTarget() == null) aefimov@650: state.setTarget(new State(context)); ohair@286: aefimov@650: State s = (State) state.getTarget(); ohair@286: try { ohair@286: s.declarePrefixes(context, context.getNewlyDeclaredPrefixes()); ohair@286: s.handler.startElement(ea.uri, ea.local, ea.getQname(), ea.atts); ohair@286: } catch (SAXException e) { ohair@286: context.handleError(e); ohair@286: throw e; ohair@286: } ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException { aefimov@650: state.setLoader(this); aefimov@650: State s = (State) state.getPrev().getTarget(); ohair@286: s.depth++; aefimov@650: state.setTarget(s); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void text(UnmarshallingContext.State state, CharSequence text) throws SAXException { ohair@286: if(text.length()==0) ohair@286: return; // there's no point in creating an empty Text node in DOM. ohair@286: try { aefimov@650: State s = (State) state.getTarget(); ohair@286: s.handler.characters(text.toString().toCharArray(),0,text.length()); ohair@286: } catch( SAXException e ) { ohair@286: state.getContext().handleError(e); ohair@286: throw e; ohair@286: } ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void leaveElement(UnmarshallingContext.State state, TagName ea) throws SAXException { aefimov@650: State s = (State) state.getTarget(); ohair@286: UnmarshallingContext context = state.getContext(); ohair@286: ohair@286: try { ohair@286: s.handler.endElement(ea.uri, ea.local, ea.getQname()); ohair@286: s.undeclarePrefixes(context.getNewlyDeclaredPrefixes()); ohair@286: } catch( SAXException e ) { ohair@286: context.handleError(e); ohair@286: throw e; ohair@286: } ohair@286: ohair@286: if((--s.depth)==0) { ohair@286: // emulate the end of the document ohair@286: try { ohair@286: s.undeclarePrefixes(context.getAllDeclaredPrefixes()); ohair@286: s.handler.endDocument(); ohair@286: } catch( SAXException e ) { ohair@286: context.handleError(e); ohair@286: throw e; ohair@286: } ohair@286: ohair@286: // we are done aefimov@650: state.setTarget(s.getElement()); ohair@286: } ohair@286: } ohair@286: ohair@286: }