diff -r 000000000000 -r 373ffda63c9a src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BinderImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BinderImpl.java Wed Apr 27 01:27:09 2016 +0800 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.bind.v2.runtime; + +import javax.xml.bind.Binder; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.PropertyException; +import javax.xml.bind.ValidationEventHandler; +import javax.xml.validation.Schema; +import javax.xml.namespace.QName; + +import com.sun.xml.internal.bind.unmarshaller.InfosetScanner; +import com.sun.xml.internal.bind.v2.runtime.output.DOMOutput; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + * Implementation of {@link Binder}. + * + * TODO: investigate how much in-place unmarshalling is implemented + * - some preliminary work is there. Probably buggy. + * TODO: work on the marshaller side. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class BinderImpl extends Binder { + + /** + * The parent context object. + */ + private final JAXBContextImpl context; + + /** + * Lazily created unmarshaller to do XML->Java binding. + * @see #getUnmarshaller() + */ + private UnmarshallerImpl unmarshaller; + + /** + * Lazily create marshaller to do Java->XML binding. + * @see #getMarshaller() + */ + private MarshallerImpl marshaller; + + private final InfosetScanner scanner; + + /** + * A {@link Binder} always works with the same + * association map. + */ + private final AssociationMap assoc = new AssociationMap(); + + BinderImpl(JAXBContextImpl _context,InfosetScanner scanner) { + this.context = _context; + this.scanner = scanner; + } + + private UnmarshallerImpl getUnmarshaller() { + if(unmarshaller==null) + unmarshaller = new UnmarshallerImpl(context,assoc); + return unmarshaller; + } + + private MarshallerImpl getMarshaller() { + if(marshaller==null) + marshaller = new MarshallerImpl(context,assoc); + return marshaller; + } + + public void marshal(Object jaxbObject, XmlNode xmlNode) throws JAXBException { + if ((xmlNode == null) || (jaxbObject == null)) + throw new IllegalArgumentException(); + getMarshaller().marshal(jaxbObject,createOutput(xmlNode)); + } + + // TODO move this to a sub class once we support something other than W3C DOM + private DOMOutput createOutput(XmlNode xmlNode) { + return new DOMOutput((Node)xmlNode,assoc); + } + + + public Object updateJAXB(XmlNode xmlNode) throws JAXBException { + return associativeUnmarshal(xmlNode,true,null); + } + + public Object unmarshal( XmlNode xmlNode ) throws JAXBException { + return associativeUnmarshal(xmlNode,false,null); + } + + public JAXBElement unmarshal(XmlNode xmlNode, Class expectedType) throws JAXBException { + if(expectedType==null) throw new IllegalArgumentException(); + return (JAXBElement)associativeUnmarshal(xmlNode,true,expectedType); + } + + public void setSchema(Schema schema) { + getMarshaller().setSchema(schema); + getUnmarshaller().setSchema(schema); + } + + public Schema getSchema() { + return getUnmarshaller().getSchema(); + } + + private Object associativeUnmarshal(XmlNode xmlNode, boolean inplace, Class expectedType) throws JAXBException { + if (xmlNode == null) + throw new IllegalArgumentException(); + + JaxBeanInfo bi = null; + if(expectedType!=null) + bi = context.getBeanInfo(expectedType, true); + + InterningXmlVisitor handler = new InterningXmlVisitor( + getUnmarshaller().createUnmarshallerHandler(scanner,inplace,bi)); + scanner.setContentHandler(new SAXConnector(handler,scanner.getLocator())); + try { + scanner.scan(xmlNode); + } catch( SAXException e ) { + throw unmarshaller.createUnmarshalException(e); + } + + return handler.getContext().getResult(); + } + + public XmlNode getXMLNode(Object jaxbObject) { + if(jaxbObject==null) + throw new IllegalArgumentException(); + AssociationMap.Entry e = assoc.byPeer(jaxbObject); + if(e==null) return null; + return e.element(); + } + + public Object getJAXBNode(XmlNode xmlNode) { + if(xmlNode==null) + throw new IllegalArgumentException(); + AssociationMap.Entry e = assoc.byElement(xmlNode); + if(e==null) return null; + if(e.outer()!=null) return e.outer(); + return e.inner(); + } + + public XmlNode updateXML(Object jaxbObject) throws JAXBException { + return updateXML(jaxbObject,getXMLNode(jaxbObject)); + } + + public XmlNode updateXML(Object jaxbObject, XmlNode xmlNode) throws JAXBException { + if(jaxbObject==null || xmlNode==null) throw new IllegalArgumentException(); + + // TODO + // for now just marshal + // TODO: object model independenc + Element e = (Element)xmlNode; + Node ns = e.getNextSibling(); + Node p = e.getParentNode(); + p.removeChild(e); + + // if the type object is passed, the following step is necessary to make + // the marshalling successful. + JaxBeanInfo bi = context.getBeanInfo(jaxbObject, true); + if(!bi.isElement()) + jaxbObject = new JAXBElement(new QName(e.getNamespaceURI(),e.getLocalName()),bi.jaxbType,jaxbObject); + + + getMarshaller().marshal(jaxbObject,p); + Node newNode = p.getLastChild(); + p.removeChild(newNode); + p.insertBefore(newNode,ns); + + return (XmlNode)newNode; + } + + public void setEventHandler(ValidationEventHandler handler) throws JAXBException { + getUnmarshaller().setEventHandler(handler); + getMarshaller().setEventHandler(handler); + } + + public ValidationEventHandler getEventHandler() { + return getUnmarshaller().getEventHandler(); + } + + public Object getProperty(String name) throws PropertyException { + if (name == null) + throw new IllegalArgumentException(Messages.NULL_PROPERTY_NAME.format()); + + // exclude RI properties that don't make sense for Binder + if (excludeProperty(name)) { + throw new PropertyException(name); + } + + Object prop = null; + PropertyException pe = null; + + try { + prop = getMarshaller().getProperty(name); + return prop; + } catch (PropertyException p) { + pe = p; + } + + try { + prop = getUnmarshaller().getProperty(name); + return prop; + } catch (PropertyException p) { + pe = p; + } + + pe.setStackTrace(Thread.currentThread().getStackTrace()); + throw pe; + } + + public void setProperty(String name, Object value) throws PropertyException { + if (name == null) + throw new IllegalArgumentException(Messages.NULL_PROPERTY_NAME.format()); + + // exclude RI properties that don't make sense for Binder + if (excludeProperty(name)) { + throw new PropertyException(name, value); + } + + PropertyException pe = null; + + try { + getMarshaller().setProperty(name, value); + return; + } catch (PropertyException p) { + pe = p; + } + + try { + getUnmarshaller().setProperty(name, value); + return; + } catch (PropertyException p) { + pe = p; + } + + // replace the stacktrace - we don't want to see a trace + // originating from Un|Marshaller.setProperty + pe.setStackTrace(Thread.currentThread().getStackTrace()); + throw pe; + } + + private boolean excludeProperty(String name) { + return name.equals( + MarshallerImpl.ENCODING_HANDLER) || + name.equals(MarshallerImpl.XMLDECLARATION) || + name.equals(MarshallerImpl.XML_HEADERS); + } +}