feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.bind.annotation.W3CDomHandler;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DomLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} for handling <tt>xs:anyType</tt>.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class AnyTypeBeanInfo extends JaxBeanInfo<Object> implements AttributeAccessor {
|
||||
|
||||
private boolean nilIncluded = false;
|
||||
|
||||
public AnyTypeBeanInfo(JAXBContextImpl grammar,RuntimeTypeInfo anyTypeInfo) {
|
||||
super(grammar, anyTypeInfo, Object.class, new QName(WellKnownNamespace.XML_SCHEMA,"anyType"), false, true, false);
|
||||
}
|
||||
|
||||
public String getElementNamespaceURI(Object element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getElementLocalName(Object element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object createInstance(UnmarshallingContext context) {
|
||||
throw new UnsupportedOperationException();
|
||||
// return JAXBContextImpl.createDom().createElementNS("","noname");
|
||||
}
|
||||
|
||||
public boolean reset(Object element, UnmarshallingContext context) {
|
||||
return false;
|
||||
// NodeList nl = element.getChildNodes();
|
||||
// while(nl.getLength()>0)
|
||||
// element.removeChild(nl.item(0));
|
||||
// NamedNodeMap al = element.getAttributes();
|
||||
// while(al.getLength()>0)
|
||||
// element.removeAttributeNode((Attr)al.item(0));
|
||||
// return true;
|
||||
}
|
||||
|
||||
public String getId(Object element, XMLSerializer target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void serializeBody(Object element, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
NodeList childNodes = ((Element)element).getChildNodes();
|
||||
int len = childNodes.getLength();
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Node child = childNodes.item(i);
|
||||
switch(child.getNodeType()) {
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
case Node.TEXT_NODE:
|
||||
target.text(child.getNodeValue(),null);
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
target.writeDom((Element)child,domHandler,null,null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeAttributes(Object element, XMLSerializer target) throws SAXException {
|
||||
NamedNodeMap al = ((Element)element).getAttributes();
|
||||
int len = al.getLength();
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Attr a = (Attr)al.item(i);
|
||||
// work defensively
|
||||
String uri = a.getNamespaceURI();
|
||||
if(uri==null) uri="";
|
||||
String local = a.getLocalName();
|
||||
String name = a.getName();
|
||||
if(local==null) local = name;
|
||||
if (uri.equals(WellKnownNamespace.XML_SCHEMA_INSTANCE) && ("nil".equals(local))) {
|
||||
isNilIncluded = true;
|
||||
}
|
||||
if(name.startsWith("xmlns")) continue;// DOM reports ns decls as attributes
|
||||
|
||||
target.attribute(uri,local,a.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeRoot(Object element, XMLSerializer target) throws SAXException {
|
||||
target.reportError(
|
||||
new ValidationEventImpl(
|
||||
ValidationEvent.ERROR,
|
||||
Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(element.getClass().getName()),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
|
||||
public void serializeURIs(Object element, XMLSerializer target) {
|
||||
NamedNodeMap al = ((Element)element).getAttributes();
|
||||
int len = al.getLength();
|
||||
NamespaceContext2 context = target.getNamespaceContext();
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Attr a = (Attr)al.item(i);
|
||||
if ("xmlns".equals(a.getPrefix())) {
|
||||
context.force(a.getValue(), a.getLocalName());
|
||||
continue;
|
||||
}
|
||||
if ("xmlns".equals(a.getName())) {
|
||||
if (element instanceof org.w3c.dom.Element) {
|
||||
context.declareNamespace(a.getValue(), null, false);
|
||||
continue;
|
||||
} else {
|
||||
context.force(a.getValue(), "");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
String nsUri = a.getNamespaceURI();
|
||||
if(nsUri!=null && nsUri.length()>0)
|
||||
context.declareNamespace( nsUri, a.getPrefix(), true );
|
||||
}
|
||||
}
|
||||
|
||||
public Transducer<Object> getTransducer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
if(typeSubstitutionCapable)
|
||||
return substLoader;
|
||||
else
|
||||
return domLoader;
|
||||
}
|
||||
|
||||
private static final W3CDomHandler domHandler = new W3CDomHandler();
|
||||
private static final DomLoader domLoader = new DomLoader(domHandler);
|
||||
private final XsiTypeLoader substLoader = new XsiTypeLoader(this);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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 java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeArrayInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} implementation that binds T[] to a complex type
|
||||
* with an element for each item.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ArrayBeanInfoImpl extends JaxBeanInfo {
|
||||
|
||||
private final Class itemType;
|
||||
private final JaxBeanInfo itemBeanInfo;
|
||||
private Loader loader;
|
||||
|
||||
public ArrayBeanInfoImpl(JAXBContextImpl owner, RuntimeArrayInfo rai) {
|
||||
super(owner,rai,rai.getType(), rai.getTypeName(), false, true, false);
|
||||
this.itemType = jaxbType.getComponentType();
|
||||
this.itemBeanInfo = owner.getOrCreate(rai.getItemType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void link(JAXBContextImpl grammar) {
|
||||
getLoader(grammar,false);
|
||||
super.link(grammar);
|
||||
}
|
||||
|
||||
private final class ArrayLoader extends Loader implements Receiver {
|
||||
public ArrayLoader(JAXBContextImpl owner) {
|
||||
super(false);
|
||||
itemLoader = itemBeanInfo.getLoader(owner,true);
|
||||
}
|
||||
|
||||
private final Loader itemLoader;
|
||||
|
||||
@Override
|
||||
public void startElement(UnmarshallingContext.State state, TagName ea) {
|
||||
state.setTarget(new ArrayList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveElement(UnmarshallingContext.State state, TagName ea) {
|
||||
state.setTarget(toArray((List)state.getTarget()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
if(ea.matches("","item")) {
|
||||
state.setLoader(itemLoader);
|
||||
state.setReceiver(this);
|
||||
} else {
|
||||
super.childElement(state,ea);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QName> getExpectedChildElements() {
|
||||
return Collections.singleton(new QName("","item"));
|
||||
}
|
||||
|
||||
public void receive(UnmarshallingContext.State state, Object o) {
|
||||
((List)state.getTarget()).add(o);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object toArray( List list ) {
|
||||
int len = list.size();
|
||||
Object array = Array.newInstance(itemType,len);
|
||||
for( int i=0; i<len; i++ )
|
||||
Array.set(array,i,list.get(i));
|
||||
return array;
|
||||
}
|
||||
|
||||
public void serializeBody(Object array, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
int len = Array.getLength(array);
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Object item = Array.get(array,i);
|
||||
// TODO: check the namespace URI.
|
||||
target.startElement("","item",null,null);
|
||||
if(item==null) {
|
||||
target.writeXsiNilTrue();
|
||||
} else {
|
||||
target.childAsXsiType(item,"arrayItem",itemBeanInfo, false);
|
||||
}
|
||||
target.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
public final String getElementNamespaceURI(Object array) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final String getElementLocalName(Object array) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final Object createInstance(UnmarshallingContext context) {
|
||||
// we first create a List and then later convert it to an array
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
public final boolean reset(Object array, UnmarshallingContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final String getId(Object array, XMLSerializer target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void serializeAttributes(Object array, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public final void serializeRoot(Object array, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
target.reportError(
|
||||
new ValidationEventImpl(
|
||||
ValidationEvent.ERROR,
|
||||
Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(array.getClass().getName()),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
|
||||
public final void serializeURIs(Object array, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public final Transducer getTransducer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
if(loader==null)
|
||||
loader = new ArrayLoader(context);
|
||||
|
||||
// type substitution not possible
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Bi-directional map between elements, inner peers,
|
||||
* and outer peers.
|
||||
*
|
||||
* <p>
|
||||
* TODO: this should be rewritten for efficiency.
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class AssociationMap<XmlNode> {
|
||||
final static class Entry<XmlNode> {
|
||||
/** XML element. */
|
||||
private XmlNode element;
|
||||
/** inner peer, or null. */
|
||||
private Object inner;
|
||||
/** outer peer, or null. */
|
||||
private Object outer;
|
||||
|
||||
public XmlNode element() {
|
||||
return element;
|
||||
}
|
||||
public Object inner() {
|
||||
return inner;
|
||||
}
|
||||
public Object outer() {
|
||||
return outer;
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<XmlNode,Entry<XmlNode>> byElement = new IdentityHashMap<XmlNode,Entry<XmlNode>>();
|
||||
private final Map<Object,Entry<XmlNode>> byPeer = new IdentityHashMap<Object,Entry<XmlNode>>();
|
||||
private final Set<XmlNode> usedNodes = new HashSet<XmlNode>();
|
||||
|
||||
/** Records the new element<->inner peer association. */
|
||||
public void addInner( XmlNode element, Object inner ) {
|
||||
Entry<XmlNode> e = byElement.get(element);
|
||||
if(e!=null) {
|
||||
if(e.inner!=null)
|
||||
byPeer.remove(e.inner);
|
||||
e.inner = inner;
|
||||
} else {
|
||||
e = new Entry<XmlNode>();
|
||||
e.element = element;
|
||||
e.inner = inner;
|
||||
}
|
||||
|
||||
byElement.put(element,e);
|
||||
|
||||
Entry<XmlNode> old = byPeer.put(inner,e);
|
||||
if(old!=null) {
|
||||
if(old.outer!=null)
|
||||
byPeer.remove(old.outer);
|
||||
if(old.element!=null)
|
||||
byElement.remove(old.element);
|
||||
}
|
||||
}
|
||||
|
||||
/** Records the new element<->outer peer association. */
|
||||
public void addOuter( XmlNode element, Object outer ) {
|
||||
Entry<XmlNode> e = byElement.get(element);
|
||||
if(e!=null) {
|
||||
if(e.outer!=null)
|
||||
byPeer.remove(e.outer);
|
||||
e.outer = outer;
|
||||
} else {
|
||||
e = new Entry<XmlNode>();
|
||||
e.element = element;
|
||||
e.outer = outer;
|
||||
}
|
||||
|
||||
byElement.put(element,e);
|
||||
|
||||
Entry<XmlNode> old = byPeer.put(outer,e);
|
||||
if(old!=null) {
|
||||
old.outer=null;
|
||||
|
||||
if(old.inner==null)
|
||||
// remove this entry
|
||||
byElement.remove(old.element);
|
||||
}
|
||||
}
|
||||
|
||||
public void addUsed( XmlNode n ) {
|
||||
usedNodes.add(n);
|
||||
}
|
||||
|
||||
public Entry<XmlNode> byElement( Object e ) {
|
||||
return byElement.get(e);
|
||||
}
|
||||
|
||||
public Entry<XmlNode> byPeer( Object o ) {
|
||||
return byPeer.get(o);
|
||||
}
|
||||
|
||||
public Object getInnerPeer( XmlNode element ) {
|
||||
Entry e = byElement(element);
|
||||
if(e==null) return null;
|
||||
else return e.inner;
|
||||
}
|
||||
|
||||
public Object getOuterPeer( XmlNode element ) {
|
||||
Entry e = byElement(element);
|
||||
if(e==null) return null;
|
||||
else return e.outer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author snajper
|
||||
*/
|
||||
public interface AttributeAccessor<BeanT> {
|
||||
|
||||
public boolean isNilIncluded();
|
||||
}
|
||||
277
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/BinderImpl.java
Normal file
277
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/BinderImpl.java
Normal file
@@ -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<XmlNode> extends Binder<XmlNode> {
|
||||
|
||||
/**
|
||||
* 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<XmlNode> scanner;
|
||||
|
||||
/**
|
||||
* A {@link Binder} always works with the same
|
||||
* association map.
|
||||
*/
|
||||
private final AssociationMap<XmlNode> assoc = new AssociationMap<XmlNode>();
|
||||
|
||||
BinderImpl(JAXBContextImpl _context,InfosetScanner<XmlNode> 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 <T> JAXBElement<T> unmarshal(XmlNode xmlNode, Class<T> 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<XmlNode> 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.MarshalException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.UnmarshalException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.api.Bridge;
|
||||
import com.sun.xml.internal.bind.api.TypeReference;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Bridge} decorator for {@link XmlAdapter}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class BridgeAdapter<OnWire,InMemory> extends InternalBridge<InMemory> {
|
||||
private final InternalBridge<OnWire> core;
|
||||
private final Class<? extends XmlAdapter<OnWire,InMemory>> adapter;
|
||||
|
||||
public BridgeAdapter(InternalBridge<OnWire> core, Class<? extends XmlAdapter<OnWire,InMemory>> adapter) {
|
||||
super(core.getContext());
|
||||
this.core = core;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public void marshal(Marshaller m, InMemory inMemory, XMLStreamWriter output) throws JAXBException {
|
||||
core.marshal(m,adaptM(m,inMemory),output);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller m, InMemory inMemory, OutputStream output, NamespaceContext nsc) throws JAXBException {
|
||||
core.marshal(m,adaptM(m,inMemory),output,nsc);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller m, InMemory inMemory, Node output) throws JAXBException {
|
||||
core.marshal(m,adaptM(m,inMemory),output);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller context, InMemory inMemory, ContentHandler contentHandler) throws JAXBException {
|
||||
core.marshal(context,adaptM(context,inMemory),contentHandler);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller context, InMemory inMemory, Result result) throws JAXBException {
|
||||
core.marshal(context,adaptM(context,inMemory),result);
|
||||
}
|
||||
|
||||
private OnWire adaptM(Marshaller m,InMemory v) throws JAXBException {
|
||||
XMLSerializer serializer = ((MarshallerImpl)m).serializer;
|
||||
serializer.pushCoordinator();
|
||||
try {
|
||||
return _adaptM(serializer, v);
|
||||
} finally {
|
||||
serializer.popCoordinator();
|
||||
}
|
||||
}
|
||||
|
||||
private OnWire _adaptM(XMLSerializer serializer, InMemory v) throws MarshalException {
|
||||
XmlAdapter<OnWire,InMemory> a = serializer.getAdapter(adapter);
|
||||
try {
|
||||
return a.marshal(v);
|
||||
} catch (Exception e) {
|
||||
serializer.handleError(e,v,null);
|
||||
throw new MarshalException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public @NotNull InMemory unmarshal(Unmarshaller u, XMLStreamReader in) throws JAXBException {
|
||||
return adaptU(u, core.unmarshal(u,in));
|
||||
}
|
||||
|
||||
public @NotNull InMemory unmarshal(Unmarshaller u, Source in) throws JAXBException {
|
||||
return adaptU(u, core.unmarshal(u,in));
|
||||
}
|
||||
|
||||
public @NotNull InMemory unmarshal(Unmarshaller u, InputStream in) throws JAXBException {
|
||||
return adaptU(u, core.unmarshal(u,in));
|
||||
}
|
||||
|
||||
public @NotNull InMemory unmarshal(Unmarshaller u, Node n) throws JAXBException {
|
||||
return adaptU(u, core.unmarshal(u,n));
|
||||
}
|
||||
|
||||
public TypeReference getTypeReference() {
|
||||
return core.getTypeReference();
|
||||
}
|
||||
|
||||
private @NotNull InMemory adaptU(Unmarshaller _u, OnWire v) throws JAXBException {
|
||||
UnmarshallerImpl u = (UnmarshallerImpl) _u;
|
||||
XmlAdapter<OnWire,InMemory> a = u.coordinator.getAdapter(adapter);
|
||||
u.coordinator.pushCoordinator();
|
||||
try {
|
||||
return a.unmarshal(v);
|
||||
} catch (Exception e) {
|
||||
throw new UnmarshalException(e);
|
||||
} finally {
|
||||
u.coordinator.popCoordinator();
|
||||
}
|
||||
}
|
||||
|
||||
void marshal(InMemory o, XMLSerializer out) throws IOException, SAXException, XMLStreamException {
|
||||
try {
|
||||
core.marshal(_adaptM( XMLSerializer.getInstance(), o ), out );
|
||||
} catch (MarshalException e) {
|
||||
// recover from error by not marshalling this element.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.JAXBException;
|
||||
import javax.xml.bind.ValidationEventHandler;
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.bind.attachment.AttachmentUnmarshaller;
|
||||
|
||||
import com.sun.xml.internal.bind.api.BridgeContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
|
||||
|
||||
/**
|
||||
* {@link BridgeContext} implementation.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class BridgeContextImpl extends BridgeContext {
|
||||
|
||||
public final UnmarshallerImpl unmarshaller;
|
||||
public final MarshallerImpl marshaller;
|
||||
|
||||
BridgeContextImpl(JAXBContextImpl context) {
|
||||
unmarshaller = context.createUnmarshaller();
|
||||
marshaller = context.createMarshaller();
|
||||
}
|
||||
|
||||
public void setErrorHandler(ValidationEventHandler handler) {
|
||||
try {
|
||||
unmarshaller.setEventHandler(handler);
|
||||
marshaller.setEventHandler(handler);
|
||||
} catch (JAXBException e) {
|
||||
// impossible
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttachmentMarshaller(AttachmentMarshaller m) {
|
||||
marshaller.setAttachmentMarshaller(m);
|
||||
}
|
||||
|
||||
public void setAttachmentUnmarshaller(AttachmentUnmarshaller u) {
|
||||
unmarshaller.setAttachmentUnmarshaller(u);
|
||||
}
|
||||
|
||||
public AttachmentMarshaller getAttachmentMarshaller() {
|
||||
return marshaller.getAttachmentMarshaller();
|
||||
}
|
||||
|
||||
public AttachmentUnmarshaller getAttachmentUnmarshaller() {
|
||||
return unmarshaller.getAttachmentUnmarshaller();
|
||||
}
|
||||
}
|
||||
141
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/BridgeImpl.java
Normal file
141
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/BridgeImpl.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.api.Bridge;
|
||||
import com.sun.xml.internal.bind.api.TypeReference;
|
||||
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.SAXOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.XMLStreamWriterOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Bridge} implementaiton.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class BridgeImpl<T> extends InternalBridge<T> {
|
||||
|
||||
/**
|
||||
* Tag name associated with this {@link Bridge}.
|
||||
* Used for marshalling.
|
||||
*/
|
||||
private final Name tagName;
|
||||
private final JaxBeanInfo<T> bi;
|
||||
private final TypeReference typeRef;
|
||||
|
||||
public BridgeImpl(JAXBContextImpl context, Name tagName, JaxBeanInfo<T> bi,TypeReference typeRef) {
|
||||
super(context);
|
||||
this.tagName = tagName;
|
||||
this.bi = bi;
|
||||
this.typeRef = typeRef;
|
||||
}
|
||||
|
||||
public void marshal(Marshaller _m, T t, XMLStreamWriter output) throws JAXBException {
|
||||
MarshallerImpl m = (MarshallerImpl)_m;
|
||||
m.write(tagName,bi,t,XMLStreamWriterOutput.create(output,context, m.getEscapeHandler()),new StAXPostInitAction(output,m.serializer));
|
||||
}
|
||||
|
||||
public void marshal(Marshaller _m, T t, OutputStream output, NamespaceContext nsContext) throws JAXBException {
|
||||
MarshallerImpl m = (MarshallerImpl)_m;
|
||||
|
||||
Runnable pia = null;
|
||||
if(nsContext!=null)
|
||||
pia = new StAXPostInitAction(nsContext,m.serializer);
|
||||
|
||||
m.write(tagName,bi,t,m.createWriter(output),pia);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller _m, T t, Node output) throws JAXBException {
|
||||
MarshallerImpl m = (MarshallerImpl)_m;
|
||||
m.write(tagName,bi,t,new SAXOutput(new SAX2DOMEx(output)),new DomPostInitAction(output,m.serializer));
|
||||
}
|
||||
|
||||
public void marshal(Marshaller _m, T t, ContentHandler contentHandler) throws JAXBException {
|
||||
MarshallerImpl m = (MarshallerImpl)_m;
|
||||
m.write(tagName,bi,t,new SAXOutput(contentHandler),null);
|
||||
}
|
||||
|
||||
public void marshal(Marshaller _m, T t, Result result) throws JAXBException {
|
||||
MarshallerImpl m = (MarshallerImpl)_m;
|
||||
m.write(tagName,bi,t, m.createXmlOutput(result),m.createPostInitAction(result));
|
||||
}
|
||||
|
||||
public @NotNull T unmarshal(Unmarshaller _u, XMLStreamReader in) throws JAXBException {
|
||||
UnmarshallerImpl u = (UnmarshallerImpl)_u;
|
||||
return ((JAXBElement<T>)u.unmarshal0(in,bi)).getValue();
|
||||
}
|
||||
|
||||
public @NotNull T unmarshal(Unmarshaller _u, Source in) throws JAXBException {
|
||||
UnmarshallerImpl u = (UnmarshallerImpl)_u;
|
||||
return ((JAXBElement<T>)u.unmarshal0(in,bi)).getValue();
|
||||
}
|
||||
|
||||
public @NotNull T unmarshal(Unmarshaller _u, InputStream in) throws JAXBException {
|
||||
UnmarshallerImpl u = (UnmarshallerImpl)_u;
|
||||
return ((JAXBElement<T>)u.unmarshal0(in,bi)).getValue();
|
||||
}
|
||||
|
||||
public @NotNull T unmarshal(Unmarshaller _u, Node n) throws JAXBException {
|
||||
UnmarshallerImpl u = (UnmarshallerImpl)_u;
|
||||
return ((JAXBElement<T>)u.unmarshal0(n,bi)).getValue();
|
||||
}
|
||||
|
||||
public TypeReference getTypeReference() {
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
public void marshal(T value, XMLSerializer out) throws IOException, SAXException, XMLStreamException {
|
||||
out.startElement(tagName,null);
|
||||
if(value==null) {
|
||||
out.writeXsiNilTrue();
|
||||
} else {
|
||||
out.childAsXsiType(value,null,bi,false);
|
||||
}
|
||||
out.endElement();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, 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 java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.FinalArrayList;
|
||||
import com.sun.xml.internal.bind.Util;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.Property;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} implementation for j2s bean.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class ClassBeanInfoImpl<BeanT> extends JaxBeanInfo<BeanT> implements AttributeAccessor<BeanT> {
|
||||
|
||||
/**
|
||||
* Properties of this bean class but not its ancestor classes.
|
||||
*/
|
||||
public final Property<BeanT>[] properties;
|
||||
|
||||
/**
|
||||
* Non-null if this bean has an ID property.
|
||||
*/
|
||||
private Property<? super BeanT> idProperty;
|
||||
|
||||
/**
|
||||
* Immutable configured loader for this class.
|
||||
*
|
||||
* <p>
|
||||
* Set from the link method, but considered final.
|
||||
*/
|
||||
private Loader loader;
|
||||
private Loader loaderWithTypeSubst;
|
||||
|
||||
/**
|
||||
* Set only until the link phase to avoid leaking memory.
|
||||
*/
|
||||
private RuntimeClassInfo ci;
|
||||
|
||||
private final Accessor<? super BeanT,Map<QName,String>> inheritedAttWildcard;
|
||||
private final Transducer<BeanT> xducer;
|
||||
|
||||
/**
|
||||
* {@link ClassBeanInfoImpl} that represents the super class of {@link #jaxbType}.
|
||||
*/
|
||||
public final ClassBeanInfoImpl<? super BeanT> superClazz;
|
||||
|
||||
private final Accessor<? super BeanT,Locator> xmlLocatorField;
|
||||
|
||||
private final Name tagName;
|
||||
|
||||
private boolean retainPropertyInfo = false;
|
||||
|
||||
/**
|
||||
* The {@link AttributeProperty}s for this type and all its ancestors.
|
||||
* If {@link JAXBContextImpl#c14nSupport} is true, this is sorted alphabetically.
|
||||
*/
|
||||
private /*final*/ AttributeProperty<BeanT>[] attributeProperties;
|
||||
|
||||
/**
|
||||
* {@link Property}s that need to receive {@link Property#serializeURIs(Object, XMLSerializer)} callback.
|
||||
*/
|
||||
private /*final*/ Property<BeanT>[] uriProperties;
|
||||
|
||||
private final Method factoryMethod;
|
||||
|
||||
/*package*/ ClassBeanInfoImpl(JAXBContextImpl owner, RuntimeClassInfo ci) {
|
||||
super(owner,ci,ci.getClazz(),ci.getTypeName(),ci.isElement(),false,true);
|
||||
|
||||
this.ci = ci;
|
||||
this.inheritedAttWildcard = ci.getAttributeWildcard();
|
||||
this.xducer = ci.getTransducer();
|
||||
this.factoryMethod = ci.getFactoryMethod();
|
||||
this.retainPropertyInfo = owner.retainPropertyInfo;
|
||||
|
||||
// make the factory accessible
|
||||
if(factoryMethod!=null) {
|
||||
int classMod = factoryMethod.getDeclaringClass().getModifiers();
|
||||
|
||||
if(!Modifier.isPublic(classMod) || !Modifier.isPublic(factoryMethod.getModifiers())) {
|
||||
// attempt to make it work even if the constructor is not accessible
|
||||
try {
|
||||
factoryMethod.setAccessible(true);
|
||||
} catch(SecurityException e) {
|
||||
// but if we don't have a permission to do so, work gracefully.
|
||||
logger.log(Level.FINE,"Unable to make the method of "+factoryMethod+" accessible",e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(ci.getBaseClass()==null)
|
||||
this.superClazz = null;
|
||||
else
|
||||
this.superClazz = owner.getOrCreate(ci.getBaseClass());
|
||||
|
||||
if(superClazz!=null && superClazz.xmlLocatorField!=null)
|
||||
xmlLocatorField = superClazz.xmlLocatorField;
|
||||
else
|
||||
xmlLocatorField = ci.getLocatorField();
|
||||
|
||||
// create property objects
|
||||
Collection<? extends RuntimePropertyInfo> ps = ci.getProperties();
|
||||
this.properties = new Property[ps.size()];
|
||||
int idx=0;
|
||||
boolean elementOnly = true;
|
||||
for( RuntimePropertyInfo info : ps ) {
|
||||
Property p = PropertyFactory.create(owner,info);
|
||||
if(info.id()==ID.ID)
|
||||
idProperty = p;
|
||||
properties[idx++] = p;
|
||||
elementOnly &= info.elementOnlyContent();
|
||||
checkOverrideProperties(p);
|
||||
}
|
||||
// super class' idProperty might not be computed at this point,
|
||||
// so check that later
|
||||
|
||||
hasElementOnlyContentModel( elementOnly );
|
||||
// again update this value later when we know that of the super class
|
||||
|
||||
if(ci.isElement())
|
||||
tagName = owner.nameBuilder.createElementName(ci.getElementName());
|
||||
else
|
||||
tagName = null;
|
||||
|
||||
setLifecycleFlags();
|
||||
}
|
||||
|
||||
private void checkOverrideProperties(Property p) {
|
||||
ClassBeanInfoImpl bi = this;
|
||||
while ((bi = bi.superClazz) != null) {
|
||||
Property[] props = bi.properties;
|
||||
if (props == null) break;
|
||||
for (Property superProperty : props) {
|
||||
if (superProperty != null) {
|
||||
String spName = superProperty.getFieldName();
|
||||
if ((spName != null) && (spName.equals(p.getFieldName()))) {
|
||||
superProperty.setHiddenByOverride(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void link(JAXBContextImpl grammar) {
|
||||
if(uriProperties!=null)
|
||||
return; // avoid linking twice
|
||||
|
||||
super.link(grammar);
|
||||
|
||||
if(superClazz!=null)
|
||||
superClazz.link(grammar);
|
||||
|
||||
getLoader(grammar,true); // make sure to build the loader if we haven't done so.
|
||||
|
||||
// propagate values from super class
|
||||
if(superClazz!=null) {
|
||||
if(idProperty==null)
|
||||
idProperty = superClazz.idProperty;
|
||||
|
||||
if(!superClazz.hasElementOnlyContentModel())
|
||||
hasElementOnlyContentModel(false);
|
||||
}
|
||||
|
||||
// create a list of attribute/URI handlers
|
||||
List<AttributeProperty> attProps = new FinalArrayList<AttributeProperty>();
|
||||
List<Property> uriProps = new FinalArrayList<Property>();
|
||||
for (ClassBeanInfoImpl bi = this; bi != null; bi = bi.superClazz) {
|
||||
for (int i = 0; i < bi.properties.length; i++) {
|
||||
Property p = bi.properties[i];
|
||||
if(p instanceof AttributeProperty)
|
||||
attProps.add((AttributeProperty) p);
|
||||
if(p.hasSerializeURIAction())
|
||||
uriProps.add(p);
|
||||
}
|
||||
}
|
||||
if(grammar.c14nSupport)
|
||||
Collections.sort(attProps);
|
||||
|
||||
if(attProps.isEmpty())
|
||||
attributeProperties = EMPTY_PROPERTIES;
|
||||
else
|
||||
attributeProperties = attProps.toArray(new AttributeProperty[attProps.size()]);
|
||||
|
||||
if(uriProps.isEmpty())
|
||||
uriProperties = EMPTY_PROPERTIES;
|
||||
else
|
||||
uriProperties = uriProps.toArray(new Property[uriProps.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapUp() {
|
||||
for (Property p : properties)
|
||||
p.wrapUp();
|
||||
ci = null;
|
||||
super.wrapUp();
|
||||
}
|
||||
|
||||
public String getElementNamespaceURI(BeanT bean) {
|
||||
return tagName.nsUri;
|
||||
}
|
||||
|
||||
public String getElementLocalName(BeanT bean) {
|
||||
return tagName.localName;
|
||||
}
|
||||
|
||||
public BeanT createInstance(UnmarshallingContext context) throws IllegalAccessException, InvocationTargetException, InstantiationException, SAXException {
|
||||
|
||||
BeanT bean = null;
|
||||
if (factoryMethod == null){
|
||||
bean = ClassFactory.create0(jaxbType);
|
||||
}else {
|
||||
Object o = ClassFactory.create(factoryMethod);
|
||||
if( jaxbType.isInstance(o) ){
|
||||
bean = (BeanT)o;
|
||||
} else {
|
||||
throw new InstantiationException("The factory method didn't return a correct object");
|
||||
}
|
||||
}
|
||||
|
||||
if(xmlLocatorField!=null)
|
||||
// need to copy because Locator is mutable
|
||||
try {
|
||||
xmlLocatorField.set(bean,new LocatorImpl(context.getLocator()));
|
||||
} catch (AccessorException e) {
|
||||
context.handleError(e);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
public boolean reset(BeanT bean, UnmarshallingContext context) throws SAXException {
|
||||
try {
|
||||
if(superClazz!=null)
|
||||
superClazz.reset(bean,context);
|
||||
for( Property<BeanT> p : properties )
|
||||
p.reset(bean);
|
||||
return true;
|
||||
} catch (AccessorException e) {
|
||||
context.handleError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getId(BeanT bean, XMLSerializer target) throws SAXException {
|
||||
if(idProperty!=null) {
|
||||
try {
|
||||
return idProperty.getIdValue(bean);
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null,e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void serializeRoot(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
if(tagName==null) {
|
||||
Class beanClass = bean.getClass();
|
||||
String message;
|
||||
if (beanClass.isAnnotationPresent(XmlRootElement.class)) {
|
||||
message = Messages.UNABLE_TO_MARSHAL_UNBOUND_CLASS.format(beanClass.getName());
|
||||
} else {
|
||||
message = Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(beanClass.getName());
|
||||
}
|
||||
target.reportError(new ValidationEventImpl(ValidationEvent.ERROR,message,null, null));
|
||||
} else {
|
||||
target.startElement(tagName,bean);
|
||||
target.childAsSoleContent(bean,null);
|
||||
target.endElement();
|
||||
if (retainPropertyInfo) {
|
||||
target.currentProperty.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeBody(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
if (superClazz != null) {
|
||||
superClazz.serializeBody(bean, target);
|
||||
}
|
||||
try {
|
||||
for (Property<BeanT> p : properties) {
|
||||
if (retainPropertyInfo) {
|
||||
target.currentProperty.set(p);
|
||||
}
|
||||
boolean isThereAnOverridingProperty = p.isHiddenByOverride();
|
||||
if (!isThereAnOverridingProperty || bean.getClass().equals(jaxbType)) {
|
||||
p.serializeBody(bean, target, null);
|
||||
} else if (isThereAnOverridingProperty) {
|
||||
// need to double check the override - it should be safe to do after the model has been created because it's targeted to override properties only
|
||||
Class beanClass = bean.getClass();
|
||||
if (Utils.REFLECTION_NAVIGATOR.getDeclaredField(beanClass, p.getFieldName()) == null) {
|
||||
p.serializeBody(bean, target, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeAttributes(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
for( AttributeProperty<BeanT> p : attributeProperties )
|
||||
try {
|
||||
if (retainPropertyInfo) {
|
||||
final Property parentProperty = target.getCurrentProperty();
|
||||
target.currentProperty.set(p);
|
||||
p.serializeAttributes(bean,target);
|
||||
target.currentProperty.set(parentProperty);
|
||||
} else {
|
||||
p.serializeAttributes(bean,target);
|
||||
}
|
||||
if (p.attName.equals(WellKnownNamespace.XML_SCHEMA_INSTANCE, "nil")) {
|
||||
isNilIncluded = true;
|
||||
}
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null,e);
|
||||
}
|
||||
|
||||
try {
|
||||
if(inheritedAttWildcard!=null) {
|
||||
Map<QName,String> map = inheritedAttWildcard.get(bean);
|
||||
target.attWildcardAsAttributes(map,null);
|
||||
}
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null,e);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeURIs(BeanT bean, XMLSerializer target) throws SAXException {
|
||||
try {
|
||||
if (retainPropertyInfo) {
|
||||
final Property parentProperty = target.getCurrentProperty();
|
||||
for( Property<BeanT> p : uriProperties ) {
|
||||
target.currentProperty.set(p);
|
||||
p.serializeURIs(bean,target);
|
||||
}
|
||||
target.currentProperty.set(parentProperty);
|
||||
} else {
|
||||
for( Property<BeanT> p : uriProperties ) {
|
||||
p.serializeURIs(bean,target);
|
||||
}
|
||||
}
|
||||
if(inheritedAttWildcard!=null) {
|
||||
Map<QName,String> map = inheritedAttWildcard.get(bean);
|
||||
target.attWildcardAsURIs(map,null);
|
||||
}
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null,e);
|
||||
}
|
||||
}
|
||||
|
||||
public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
if(loader==null) {
|
||||
// these variables have to be set before they are initialized,
|
||||
// because the initialization may build other loaders and they may refer to this.
|
||||
StructureLoader sl = new StructureLoader(this);
|
||||
loader = sl;
|
||||
if(ci.hasSubClasses())
|
||||
loaderWithTypeSubst = new XsiTypeLoader(this);
|
||||
else
|
||||
// optimization. we know there can be no @xsi:type
|
||||
loaderWithTypeSubst = loader;
|
||||
|
||||
|
||||
sl.init(context,this,ci.getAttributeWildcard());
|
||||
}
|
||||
if(typeSubstitutionCapable)
|
||||
return loaderWithTypeSubst;
|
||||
else
|
||||
return loader;
|
||||
}
|
||||
|
||||
public Transducer<BeanT> getTransducer() {
|
||||
return xducer;
|
||||
}
|
||||
|
||||
private static final AttributeProperty[] EMPTY_PROPERTIES = new AttributeProperty[0];
|
||||
|
||||
private static final Logger logger = Util.getClassLogger();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.CompositeStructure;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class CompositeStructureBeanInfo extends JaxBeanInfo<CompositeStructure> {
|
||||
public CompositeStructureBeanInfo(JAXBContextImpl context) {
|
||||
super(context,null, CompositeStructure.class,false,true,false);
|
||||
}
|
||||
|
||||
public String getElementNamespaceURI(CompositeStructure o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getElementLocalName(CompositeStructure o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public CompositeStructure createInstance(UnmarshallingContext context) throws IllegalAccessException, InvocationTargetException, InstantiationException, SAXException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean reset(CompositeStructure o, UnmarshallingContext context) throws SAXException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getId(CompositeStructure o, XMLSerializer target) throws SAXException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
// no unmarshaller support for this.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void serializeRoot(CompositeStructure o, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
target.reportError(
|
||||
new ValidationEventImpl(
|
||||
ValidationEvent.ERROR,
|
||||
Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(o.getClass().getName()),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
|
||||
public void serializeURIs(CompositeStructure o, XMLSerializer target) throws SAXException {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void serializeAttributes(CompositeStructure o, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void serializeBody(CompositeStructure o, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
int len = o.bridges.length;
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Object value = o.values[i];
|
||||
InternalBridge bi = (InternalBridge)o.bridges[i];
|
||||
bi.marshal( value, target );
|
||||
}
|
||||
}
|
||||
|
||||
public Transducer<CompositeStructure> getTransducer() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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 com.sun.istack.internal.FinalArrayList;
|
||||
import com.sun.istack.internal.SAXException2;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Receives SAX2 events and send the equivalent events to
|
||||
* {@link XMLSerializer}
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
final class ContentHandlerAdaptor extends DefaultHandler {
|
||||
|
||||
/** Stores newly declared prefix-URI mapping. */
|
||||
private final FinalArrayList<String> prefixMap = new FinalArrayList<String>();
|
||||
|
||||
/** Events will be sent to this object. */
|
||||
private final XMLSerializer serializer;
|
||||
|
||||
private final StringBuffer text = new StringBuffer();
|
||||
|
||||
|
||||
ContentHandlerAdaptor( XMLSerializer _serializer ) {
|
||||
this.serializer = _serializer;
|
||||
}
|
||||
|
||||
public void startDocument() {
|
||||
prefixMap.clear();
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) {
|
||||
prefixMap.add(prefix);
|
||||
prefixMap.add(uri);
|
||||
}
|
||||
|
||||
private boolean containsPrefixMapping(String prefix, String uri) {
|
||||
for( int i=0; i<prefixMap.size(); i+=2 ) {
|
||||
if(prefixMap.get(i).equals(prefix)
|
||||
&& prefixMap.get(i+1).equals(uri))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
try {
|
||||
flushText();
|
||||
|
||||
int len = atts.getLength();
|
||||
|
||||
String p = getPrefix(qName);
|
||||
|
||||
// is this prefix going to be declared on this element?
|
||||
if(containsPrefixMapping(p,namespaceURI))
|
||||
serializer.startElementForce(namespaceURI,localName,p,null);
|
||||
else
|
||||
serializer.startElement(namespaceURI,localName, p,null);
|
||||
|
||||
// declare namespace events
|
||||
for (int i = 0; i < prefixMap.size(); i += 2) {
|
||||
// forcibly set this binding, instead of using declareNsUri.
|
||||
// this guarantees that namespaces used in DOM will show up
|
||||
// as-is in the marshalled output (instead of reassigned to something else,
|
||||
// which may happen if you'd use declareNsUri.)
|
||||
serializer.getNamespaceContext().force(
|
||||
prefixMap.get(i + 1), prefixMap.get(i));
|
||||
}
|
||||
// make sure namespaces needed by attributes are bound
|
||||
for( int i=0; i<len; i++ ) {
|
||||
String qname = atts.getQName(i);
|
||||
if(qname.startsWith("xmlns") || atts.getURI(i).length() == 0)
|
||||
continue;
|
||||
String prefix = getPrefix(qname);
|
||||
|
||||
serializer.getNamespaceContext().declareNamespace(
|
||||
atts.getURI(i), prefix, true );
|
||||
}
|
||||
|
||||
serializer.endNamespaceDecls(null);
|
||||
// fire attribute events
|
||||
for( int i=0; i<len; i++ ) {
|
||||
// be defensive.
|
||||
if(atts.getQName(i).startsWith("xmlns"))
|
||||
continue;
|
||||
serializer.attribute( atts.getURI(i), atts.getLocalName(i), atts.getValue(i));
|
||||
}
|
||||
prefixMap.clear();
|
||||
serializer.endAttributes();
|
||||
} catch (IOException e) {
|
||||
throw new SAXException2(e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new SAXException2(e);
|
||||
}
|
||||
}
|
||||
|
||||
// make sure namespaces needed by attributes are bound
|
||||
private String getPrefix(String qname) {
|
||||
int idx = qname.indexOf(':');
|
||||
String prefix = (idx == -1) ? "" : qname.substring(0, idx);
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
|
||||
try {
|
||||
flushText();
|
||||
serializer.endElement();
|
||||
} catch (IOException e) {
|
||||
throw new SAXException2(e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new SAXException2(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void flushText() throws SAXException, IOException, XMLStreamException {
|
||||
if( text.length()!=0 ) {
|
||||
serializer.text(text.toString(),null);
|
||||
text.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) {
|
||||
text.append(ch,start,length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.ValidationEventHandler;
|
||||
import javax.xml.bind.ValidationEventLocator;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Object that coordinates the marshalling/unmarshalling.
|
||||
*
|
||||
* <p>
|
||||
* This class takes care of the logic that allows code to obtain
|
||||
* {@link UnmarshallingContext} and {@link XMLSerializer} instances
|
||||
* during the unmarshalling/marshalling.
|
||||
*
|
||||
* <p>
|
||||
* This is done by using a {@link ThreadLocal}. Therefore one unmarshalling/marshalling
|
||||
* episode has to be done from the beginning till end by the same thread.
|
||||
* (Note that the same {@link Coordinator} can be then used by a different thread
|
||||
* for an entirely different episode.)
|
||||
*
|
||||
* This class also maintains the user-configured instances of {@link XmlAdapter}s.
|
||||
*
|
||||
* <p>
|
||||
* This class implements {@link ErrorHandler} and propages erros to this object
|
||||
* as the {@link ValidationEventHandler}, which will be implemented in a derived class.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class Coordinator implements ErrorHandler, ValidationEventHandler {
|
||||
|
||||
private final HashMap<Class<? extends XmlAdapter>,XmlAdapter> adapters =
|
||||
new HashMap<Class<? extends XmlAdapter>,XmlAdapter>();
|
||||
|
||||
|
||||
public final XmlAdapter putAdapter(Class<? extends XmlAdapter> c, XmlAdapter a) {
|
||||
if(a==null)
|
||||
return adapters.remove(c);
|
||||
else
|
||||
return adapters.put(c,a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of the adapter.
|
||||
*
|
||||
* @return
|
||||
* always non-null.
|
||||
*/
|
||||
public final <T extends XmlAdapter> T getAdapter(Class<T> key) {
|
||||
T v = key.cast(adapters.get(key));
|
||||
if(v==null) {
|
||||
v = ClassFactory.create(key);
|
||||
putAdapter(key,v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public <T extends XmlAdapter> boolean containsAdapter(Class<T> type) {
|
||||
return adapters.containsKey(type);
|
||||
}
|
||||
|
||||
// this much is necessary to avoid calling get and set twice when we push.
|
||||
private static final ThreadLocal<Coordinator> activeTable = new ThreadLocal<Coordinator>();
|
||||
|
||||
/**
|
||||
* The {@link Coordinator} in charge before this {@link Coordinator}.
|
||||
*/
|
||||
private Coordinator old;
|
||||
|
||||
/**
|
||||
* Called whenever an execution flow enters the realm of this {@link Coordinator}.
|
||||
*/
|
||||
protected final void pushCoordinator() {
|
||||
old = activeTable.get();
|
||||
activeTable.set(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever an execution flow exits the realm of this {@link Coordinator}.
|
||||
*/
|
||||
protected final void popCoordinator() {
|
||||
if (old != null)
|
||||
activeTable.set(old);
|
||||
else
|
||||
activeTable.remove();
|
||||
old = null; // avoid memory leak
|
||||
}
|
||||
|
||||
public static Coordinator _getInstance() {
|
||||
return activeTable.get();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// ErrorHandler implementation
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Gets the current location. Used for reporting the error source location.
|
||||
*/
|
||||
protected abstract ValidationEventLocator getLocation();
|
||||
|
||||
public final void error(SAXParseException exception) throws SAXException {
|
||||
propagateEvent( ValidationEvent.ERROR, exception );
|
||||
}
|
||||
|
||||
public final void warning(SAXParseException exception) throws SAXException {
|
||||
propagateEvent( ValidationEvent.WARNING, exception );
|
||||
}
|
||||
|
||||
public final void fatalError(SAXParseException exception) throws SAXException {
|
||||
propagateEvent( ValidationEvent.FATAL_ERROR, exception );
|
||||
}
|
||||
|
||||
private void propagateEvent( int severity, SAXParseException saxException )
|
||||
throws SAXException {
|
||||
|
||||
ValidationEventImpl ve =
|
||||
new ValidationEventImpl( severity, saxException.getMessage(), getLocation() );
|
||||
|
||||
Exception e = saxException.getException();
|
||||
if( e != null ) {
|
||||
ve.setLinkedException( e );
|
||||
} else {
|
||||
ve.setLinkedException( saxException );
|
||||
}
|
||||
|
||||
// call the client's event handler. If it returns false, then bail-out
|
||||
// and terminate the unmarshal operation.
|
||||
boolean result = handleEvent( ve );
|
||||
if( ! result ) {
|
||||
// bail-out of the parse with a SAX exception, but convert it into
|
||||
// an UnmarshalException back in in the AbstractUnmarshaller
|
||||
throw saxException;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Post-init action for {@link MarshallerImpl} that incorporate the in-scope namespace bindings
|
||||
* from a DOM node.
|
||||
*
|
||||
* TODO: do we really need this? think about a better way to put this logic back into marshaller.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DomPostInitAction implements Runnable {
|
||||
|
||||
private final Node node;
|
||||
private final XMLSerializer serializer;
|
||||
|
||||
DomPostInitAction(Node node, XMLSerializer serializer) {
|
||||
this.node = node;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
// declare the currently in-scope namespace bindings
|
||||
public void run() {
|
||||
Set<String> declaredPrefixes = new HashSet<String>();
|
||||
for( Node n=node; n!=null && n.getNodeType()==Node.ELEMENT_NODE; n=n.getParentNode() ) {
|
||||
NamedNodeMap atts = n.getAttributes();
|
||||
if(atts==null) continue; // broken DOM. but be graceful.
|
||||
for( int i=0; i<atts.getLength(); i++ ) {
|
||||
Attr a = (Attr)atts.item(i);
|
||||
String nsUri = a.getNamespaceURI();
|
||||
if(nsUri==null || !nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI))
|
||||
continue; // not a namespace declaration
|
||||
String prefix = a.getLocalName();
|
||||
if(prefix==null)
|
||||
continue; // broken DOM. skip to be safe
|
||||
if(prefix.equals("xmlns")) {
|
||||
prefix = "";
|
||||
}
|
||||
String value = a.getValue();
|
||||
if(value==null)
|
||||
continue; // broken DOM. skip to be safe
|
||||
if(declaredPrefixes.add(prefix)) {
|
||||
serializer.addInscopeBinding(value,prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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 java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.Property;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory;
|
||||
import com.sun.xml.internal.bind.v2.runtime.property.UnmarshallerChain;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Discarder;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Intercepter;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} implementation for {@link RuntimeElementInfo}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ElementBeanInfoImpl extends JaxBeanInfo<JAXBElement> {
|
||||
|
||||
private Loader loader;
|
||||
|
||||
private final Property property;
|
||||
|
||||
// used to create new instances of JAXBElement.
|
||||
private final QName tagName;
|
||||
public final Class expectedType;
|
||||
private final Class scope;
|
||||
|
||||
/**
|
||||
* If non-null, use this to create an instance.
|
||||
* It takes one value.
|
||||
*/
|
||||
private final Constructor<? extends JAXBElement> constructor;
|
||||
|
||||
ElementBeanInfoImpl(JAXBContextImpl grammar, RuntimeElementInfo rei) {
|
||||
super(grammar,rei,(Class<JAXBElement>)rei.getType(),true,false,true);
|
||||
|
||||
this.property = PropertyFactory.create(grammar,rei.getProperty());
|
||||
|
||||
tagName = rei.getElementName();
|
||||
expectedType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(rei.getContentInMemoryType());
|
||||
scope = rei.getScope()==null ? JAXBElement.GlobalScope.class : rei.getScope().getClazz();
|
||||
|
||||
Class type = (Class) Utils.REFLECTION_NAVIGATOR.erasure(rei.getType());
|
||||
if(type==JAXBElement.class)
|
||||
constructor = null;
|
||||
else {
|
||||
try {
|
||||
constructor = type.getConstructor(expectedType);
|
||||
} catch (NoSuchMethodException e) {
|
||||
NoSuchMethodError x = new NoSuchMethodError("Failed to find the constructor for " + type + " with " + expectedType);
|
||||
x.initCause(e);
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor for the sole instanceof {@link JaxBeanInfo} for
|
||||
* handling user-created {@link JAXBElement}.
|
||||
*
|
||||
* Such {@link JaxBeanInfo} is used only for marshalling.
|
||||
*
|
||||
* This is a hack.
|
||||
*/
|
||||
protected ElementBeanInfoImpl(final JAXBContextImpl grammar) {
|
||||
super(grammar,null,JAXBElement.class,true,false,true);
|
||||
tagName = null;
|
||||
expectedType = null;
|
||||
scope = null;
|
||||
constructor = null;
|
||||
|
||||
this.property = new Property<JAXBElement>() {
|
||||
public void reset(JAXBElement o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void serializeBody(JAXBElement e, XMLSerializer target, Object outerPeer) throws SAXException, IOException, XMLStreamException {
|
||||
Class scope = e.getScope();
|
||||
if(e.isGlobalScope()) scope = null;
|
||||
QName n = e.getName();
|
||||
ElementBeanInfoImpl bi = grammar.getElement(scope,n);
|
||||
if(bi==null) {
|
||||
// infer what to do from the type
|
||||
JaxBeanInfo tbi;
|
||||
try {
|
||||
tbi = grammar.getBeanInfo(e.getDeclaredType(),true);
|
||||
} catch (JAXBException x) {
|
||||
// if e.getDeclaredType() isn't known to this JAXBContext
|
||||
target.reportError(null,x);
|
||||
return;
|
||||
}
|
||||
Object value = e.getValue();
|
||||
target.startElement(n.getNamespaceURI(),n.getLocalPart(),n.getPrefix(),null);
|
||||
if(value==null) {
|
||||
target.writeXsiNilTrue();
|
||||
} else {
|
||||
target.childAsXsiType(value,"value",tbi, false);
|
||||
}
|
||||
target.endElement();
|
||||
} else {
|
||||
try {
|
||||
bi.property.serializeBody(e,target,e);
|
||||
} catch (AccessorException x) {
|
||||
target.reportError(null,x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeURIs(JAXBElement o, XMLSerializer target) {
|
||||
}
|
||||
|
||||
public boolean hasSerializeURIAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getIdValue(JAXBElement o) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.ELEMENT;
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
}
|
||||
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void wrapUp() {
|
||||
}
|
||||
|
||||
public RuntimePropertyInfo getInfo() {
|
||||
return property.getInfo();
|
||||
}
|
||||
|
||||
public boolean isHiddenByOverride() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setHiddenByOverride(boolean hidden) {
|
||||
throw new UnsupportedOperationException("Not supported on jaxbelements.");
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the previous {@link UnmarshallingContext.State}'s target to store
|
||||
* {@link JAXBElement} object to be unmarshalled. This allows the property {@link Loader}
|
||||
* to correctly find the parent object.
|
||||
* This is a hack.
|
||||
*/
|
||||
private final class IntercepterLoader extends Loader implements Intercepter {
|
||||
private final Loader core;
|
||||
|
||||
public IntercepterLoader(Loader core) {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
state.setLoader(core);
|
||||
state.setIntercepter(this);
|
||||
|
||||
// TODO: make sure there aren't too many duplicate of this code
|
||||
// create the object to unmarshal
|
||||
Object child;
|
||||
UnmarshallingContext context = state.getContext();
|
||||
|
||||
// let's see if we can reuse the existing peer object
|
||||
child = context.getOuterPeer();
|
||||
|
||||
if(child!=null && jaxbType!=child.getClass())
|
||||
child = null; // unexpected type.
|
||||
|
||||
if(child!=null)
|
||||
reset((JAXBElement)child,context);
|
||||
|
||||
if(child==null)
|
||||
child = context.createInstance(ElementBeanInfoImpl.this);
|
||||
|
||||
fireBeforeUnmarshal(ElementBeanInfoImpl.this, child, state);
|
||||
|
||||
context.recordOuterPeer(child);
|
||||
UnmarshallingContext.State p = state.getPrev();
|
||||
p.setBackup(p.getTarget());
|
||||
p.setTarget(child);
|
||||
|
||||
core.startElement(state,ea);
|
||||
}
|
||||
|
||||
public Object intercept(UnmarshallingContext.State state, Object o) throws SAXException {
|
||||
JAXBElement e = (JAXBElement)state.getTarget();
|
||||
state.setTarget(state.getBackup());
|
||||
state.setBackup(null);
|
||||
|
||||
if (state.isNil()) {
|
||||
e.setNil(true);
|
||||
state.setNil(false);
|
||||
}
|
||||
|
||||
if(o!=null)
|
||||
// if the value is a leaf type, it's often already set to the element
|
||||
// through Accessor.
|
||||
e.setValue(o);
|
||||
|
||||
fireAfterUnmarshal(ElementBeanInfoImpl.this, e, state);
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
public String getElementNamespaceURI(JAXBElement e) {
|
||||
return e.getName().getNamespaceURI();
|
||||
}
|
||||
|
||||
public String getElementLocalName(JAXBElement e) {
|
||||
return e.getName().getLocalPart();
|
||||
}
|
||||
|
||||
public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
if(loader==null) {
|
||||
// this has to be done lazily to avoid cyclic reference issue
|
||||
UnmarshallerChain c = new UnmarshallerChain(context);
|
||||
QNameMap<ChildLoader> result = new QNameMap<ChildLoader>();
|
||||
property.buildChildElementUnmarshallers(c,result);
|
||||
if(result.size()==1)
|
||||
// for ElementBeanInfoImpl created from RuntimeElementInfo
|
||||
this.loader = new IntercepterLoader(result.getOne().getValue().loader);
|
||||
else
|
||||
// for special ElementBeanInfoImpl only used for marshalling
|
||||
this.loader = Discarder.INSTANCE;
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
|
||||
public final JAXBElement createInstance(UnmarshallingContext context) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
return createInstanceFromValue(null);
|
||||
}
|
||||
|
||||
public final JAXBElement createInstanceFromValue(Object o) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
if(constructor==null)
|
||||
return new JAXBElement(tagName,expectedType,scope,o);
|
||||
else
|
||||
return constructor.newInstance(o);
|
||||
}
|
||||
|
||||
public boolean reset(JAXBElement e, UnmarshallingContext context) {
|
||||
e.setValue(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getId(JAXBElement e, XMLSerializer target) {
|
||||
// TODO: is this OK? Should we be returning the ID value of the type property?
|
||||
/*
|
||||
There's one case where we JAXBElement needs to be designated as ID,
|
||||
and that is when there's a global element whose type is ID.
|
||||
*/
|
||||
Object o = e.getValue();
|
||||
if(o instanceof String)
|
||||
return (String)o;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void serializeBody(JAXBElement element, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
try {
|
||||
property.serializeBody(element,target,null);
|
||||
} catch (AccessorException x) {
|
||||
target.reportError(null,x);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeRoot(JAXBElement e, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
serializeBody(e,target);
|
||||
}
|
||||
|
||||
public void serializeAttributes(JAXBElement e, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void serializeURIs(JAXBElement e, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public final Transducer<JAXBElement> getTransducer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapUp() {
|
||||
super.wrapUp();
|
||||
property.wrapUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void link(JAXBContextImpl grammar) {
|
||||
super.link(grammar);
|
||||
getLoader(grammar,true); // make sure to build them, if we hadn't done so
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Transducer} that delegates to another {@link Transducer}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class FilterTransducer<T> implements Transducer<T> {
|
||||
protected final Transducer<T> core;
|
||||
|
||||
protected FilterTransducer(Transducer<T> core) {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public final boolean isDefault() {
|
||||
// this must be used as a decorating transducer,
|
||||
// so it may never be default.
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean useNamespace() {
|
||||
return core.useNamespace();
|
||||
}
|
||||
|
||||
public void declareNamespace(T o, XMLSerializer w) throws AccessorException {
|
||||
core.declareNamespace(o, w);
|
||||
}
|
||||
|
||||
public @NotNull CharSequence print(@NotNull T o) throws AccessorException {
|
||||
return core.print(o);
|
||||
}
|
||||
|
||||
public T parse(CharSequence lexical) throws AccessorException, SAXException {
|
||||
return core.parse(lexical);
|
||||
}
|
||||
|
||||
public void writeText(XMLSerializer w, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
core.writeText(w, o, fieldName);
|
||||
}
|
||||
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
core.writeLeafElement(w,tagName,o,fieldName);
|
||||
}
|
||||
|
||||
public QName getTypeName(T instance) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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 java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
|
||||
|
||||
/**
|
||||
* Signals an incorrect use of JAXB annotations.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
* @since JAXB 2.0 EA1
|
||||
*/
|
||||
public class IllegalAnnotationException extends JAXBException {
|
||||
|
||||
/**
|
||||
* Read-only list of {@link Location}s.
|
||||
*/
|
||||
private final List<List<Location>> pos;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public IllegalAnnotationException(String message, Locatable src) {
|
||||
super(message);
|
||||
pos = build(src);
|
||||
}
|
||||
|
||||
public IllegalAnnotationException(String message, Annotation src) {
|
||||
this(message,cast(src));
|
||||
}
|
||||
|
||||
public IllegalAnnotationException(String message, Locatable src1, Locatable src2) {
|
||||
super(message);
|
||||
pos = build(src1,src2);
|
||||
}
|
||||
|
||||
public IllegalAnnotationException(String message, Annotation src1, Annotation src2) {
|
||||
this(message,cast(src1),cast(src2));
|
||||
}
|
||||
|
||||
public IllegalAnnotationException(String message, Annotation src1, Locatable src2) {
|
||||
this(message,cast(src1),src2);
|
||||
}
|
||||
|
||||
public IllegalAnnotationException(String message, Throwable cause, Locatable src) {
|
||||
super(message, cause);
|
||||
pos = build(src);
|
||||
}
|
||||
|
||||
private static Locatable cast(Annotation a) {
|
||||
if(a instanceof Locatable)
|
||||
return (Locatable)a;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<List<Location>> build(Locatable... srcs) {
|
||||
List<List<Location>> r = new ArrayList<List<Location>>();
|
||||
for( Locatable l : srcs ) {
|
||||
if(l!=null) {
|
||||
List<Location> ll = convert(l);
|
||||
if(ll!=null && !ll.isEmpty())
|
||||
r.add(ll);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of {@link Location}s out of a {@link Locatable}.
|
||||
*/
|
||||
private List<Location> convert(Locatable src) {
|
||||
if(src==null) return null;
|
||||
|
||||
List<Location> r = new ArrayList<Location>();
|
||||
for( ; src!=null; src=src.getUpstream())
|
||||
r.add(src.getLocation());
|
||||
return Collections.unmodifiableList(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a read-only list of {@link Location} that indicates
|
||||
* where in the source code the problem has happened.
|
||||
*
|
||||
* <p>
|
||||
* Normally, an annotation error happens on one particular
|
||||
* annotation, in which case this method returns a list that
|
||||
* contains another list, which in turn contains the location
|
||||
* information that leads to the error location
|
||||
* (IOW, <tt>[ [pos1,pos2,...,posN] ]</tt>)
|
||||
*
|
||||
* <p>
|
||||
* Sometimes, an error could occur because of two or more conflicting
|
||||
* annotations, in which case this method returns a list
|
||||
* that contains many lists, where each list contains
|
||||
* the location information that leads to each of the conflicting
|
||||
* annotations
|
||||
* (IOW, <tt>[ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]</tt>)
|
||||
*
|
||||
* <p>
|
||||
* Yet some other time, the runtime can fail to provide any
|
||||
* error location, in which case this method returns an empty list.
|
||||
* (IOW, <tt>[]</tt>). We do try hard to make sure this won't happen,
|
||||
* so please <a href="http://jaxb.dev.java.net/">let us know</a>
|
||||
* if you see this behavior.
|
||||
*
|
||||
*
|
||||
* <h3>List of {@link Location}</h3>
|
||||
* <p>
|
||||
* Each error location is identified not just by one {@link Location}
|
||||
* object, but by a sequence of {@link Location}s that shows why
|
||||
* the runtime is led to the place of the error.
|
||||
* This list is sorted such that the most specific {@link Location} comes
|
||||
* to the first in the list, sort of like a stack trace.
|
||||
*
|
||||
* <p>
|
||||
* For example, suppose you specify class <tt>Foo</tt> to {@link JAXBContext},
|
||||
* <tt>Foo</tt> derives from <tt>Bar</tt>, <tt>Bar</tt> has a field <tt>pea</tt>
|
||||
* that points to <tt>Zot</tt>, <tt>Zot</tt> contains a <tt>gum</tt>
|
||||
* property, and this property has an errornous annotation.
|
||||
* Then when this exception is thrown, the list of {@link Location}s
|
||||
* will look something like
|
||||
* <tt>[ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ]</tt>
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* can be empty when no source position is available,
|
||||
* but never null. The returned list will never contain
|
||||
* null nor length-0 {@link List}.
|
||||
*/
|
||||
public List<List<Location>> getSourcePos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception name, message, and related information
|
||||
* together in one string.
|
||||
*
|
||||
* <p>
|
||||
* Overriding this method (instead of {@link #printStackTrace} allows
|
||||
* this crucial detail to show up even when this exception is nested
|
||||
* inside other exceptions.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(getMessage());
|
||||
|
||||
for( List<Location> locs : pos ) {
|
||||
sb.append("\n\tthis problem is related to the following location:");
|
||||
for( Location loc : locs )
|
||||
sb.append("\n\t\tat ").append(loc.toString());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.core.ErrorHandler;
|
||||
|
||||
/**
|
||||
* A list of {@link IllegalAnnotationException} wrapped in one exception.
|
||||
*
|
||||
* <p>
|
||||
* This exception is used to report all the errors to the client application
|
||||
* through {@link JAXBContext#newInstance}.
|
||||
*
|
||||
* @since JAXB 2.0 EA1
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class IllegalAnnotationsException extends JAXBException {
|
||||
private final List<IllegalAnnotationException> errors;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public IllegalAnnotationsException(List<IllegalAnnotationException> errors) {
|
||||
super(errors.size()+" counts of IllegalAnnotationExceptions");
|
||||
assert !errors.isEmpty() : "there must be at least one error";
|
||||
this.errors = Collections.unmodifiableList(new ArrayList<IllegalAnnotationException>(errors));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(super.toString());
|
||||
sb.append('\n');
|
||||
|
||||
for( IllegalAnnotationException error : errors )
|
||||
sb.append(error.toString()).append('\n');
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a read-only list of {@link IllegalAnnotationException}s
|
||||
* wrapped in this exception.
|
||||
*
|
||||
* @return
|
||||
* a non-null list.
|
||||
*/
|
||||
public List<IllegalAnnotationException> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static class Builder implements ErrorHandler {
|
||||
private final List<IllegalAnnotationException> list = new ArrayList<IllegalAnnotationException>();
|
||||
public void error(IllegalAnnotationException e) {
|
||||
list.add(e);
|
||||
}
|
||||
/**
|
||||
* If an error was reported, throw the exception.
|
||||
* Otherwise exit normally.
|
||||
*/
|
||||
public void check() throws IllegalAnnotationsException {
|
||||
if(list.isEmpty())
|
||||
return;
|
||||
throw new IllegalAnnotationsException(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Transducer that signals the runtime that this binary data shall be always inlined.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class InlineBinaryTransducer<V> extends FilterTransducer<V> {
|
||||
public InlineBinaryTransducer(Transducer<V> core) {
|
||||
super(core);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CharSequence print(@NotNull V o) throws AccessorException {
|
||||
XMLSerializer w = XMLSerializer.getInstance();
|
||||
boolean old = w.setInlineBinaryFlag(true);
|
||||
try {
|
||||
return core.print(o);
|
||||
} finally {
|
||||
w.setInlineBinaryFlag(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeText(XMLSerializer w, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
boolean old = w.setInlineBinaryFlag(true);
|
||||
try {
|
||||
core.writeText(w,o,fieldName);
|
||||
} finally {
|
||||
w.setInlineBinaryFlag(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
boolean old = w.setInlineBinaryFlag(true);
|
||||
try {
|
||||
core.writeLeafElement(w, tagName, o, fieldName);
|
||||
} finally {
|
||||
w.setInlineBinaryFlag(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.Bridge;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Additional methods on {@link Bridge} that are only available for the JAXB runtime.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class InternalBridge<T> extends Bridge<T> {
|
||||
protected InternalBridge(JAXBContextImpl context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public JAXBContextImpl getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link CompositeStructureBeanInfo} to marshal this bridge as a sub-tree.
|
||||
*/
|
||||
abstract void marshal( T o, XMLSerializer out ) throws IOException, SAXException, XMLStreamException;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.Util;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Encapsulates various JAXB operations on objects bound by JAXB.
|
||||
* Immutable and thread-safe.
|
||||
*
|
||||
* <p>
|
||||
* Each JAXB-bound class has a corresponding {@link JaxBeanInfo} object,
|
||||
* which performs all the JAXB related operations on behalf of
|
||||
* the JAXB-bound object.
|
||||
*
|
||||
* <p>
|
||||
* Given a class, the corresponding {@link JaxBeanInfo} can be located
|
||||
* via {@link JAXBContextImpl#getBeanInfo(Class,boolean)}.
|
||||
*
|
||||
* <p>
|
||||
* Typically, {@link JaxBeanInfo} implementations should be generated
|
||||
* by XJC/JXC. Those impl classes will register themselves to their
|
||||
* master <tt>ObjectFactory</tt> class.
|
||||
*
|
||||
* <p>
|
||||
* The type parameter BeanT is the Java class of the bean that this represents.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public abstract class JaxBeanInfo<BeanT> {
|
||||
|
||||
protected boolean isNilIncluded = false;
|
||||
|
||||
/**
|
||||
* For {@link JaxBeanInfo} that has multiple type names.
|
||||
*/
|
||||
protected JaxBeanInfo(JAXBContextImpl grammar, RuntimeTypeInfo rti, Class<BeanT> jaxbType, QName[] typeNames, boolean isElement,boolean isImmutable, boolean hasLifecycleEvents) {
|
||||
this(grammar,rti,jaxbType,(Object)typeNames,isElement,isImmutable,hasLifecycleEvents);
|
||||
}
|
||||
|
||||
/**
|
||||
* For {@link JaxBeanInfo} that has one type name.
|
||||
*/
|
||||
protected JaxBeanInfo(JAXBContextImpl grammar, RuntimeTypeInfo rti, Class<BeanT> jaxbType, QName typeName, boolean isElement,boolean isImmutable, boolean hasLifecycleEvents) {
|
||||
this(grammar,rti,jaxbType,(Object)typeName,isElement,isImmutable,hasLifecycleEvents);
|
||||
}
|
||||
|
||||
/**
|
||||
* For {@link JaxBeanInfo} that has no type names.
|
||||
*/
|
||||
protected JaxBeanInfo(JAXBContextImpl grammar, RuntimeTypeInfo rti, Class<BeanT> jaxbType, boolean isElement,boolean isImmutable, boolean hasLifecycleEvents) {
|
||||
this(grammar,rti,jaxbType,(Object)null,isElement,isImmutable,hasLifecycleEvents);
|
||||
}
|
||||
|
||||
private JaxBeanInfo(JAXBContextImpl grammar, RuntimeTypeInfo rti, Class<BeanT> jaxbType, Object typeName, boolean isElement,boolean isImmutable, boolean hasLifecycleEvents) {
|
||||
grammar.beanInfos.put(rti,this);
|
||||
|
||||
this.jaxbType = jaxbType;
|
||||
this.typeName = typeName;
|
||||
this.flag = (short)((isElement?FLAG_IS_ELEMENT:0)
|
||||
|(isImmutable?FLAG_IS_IMMUTABLE:0)
|
||||
|(hasLifecycleEvents?FLAG_HAS_LIFECYCLE_EVENTS:0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Various boolean flags combined into one field to improve memory footprint.
|
||||
*/
|
||||
protected short flag;
|
||||
|
||||
private static final short FLAG_IS_ELEMENT = 1;
|
||||
private static final short FLAG_IS_IMMUTABLE = 2;
|
||||
private static final short FLAG_HAS_ELEMENT_ONLY_CONTENTMODEL = 4;
|
||||
private static final short FLAG_HAS_BEFORE_UNMARSHAL_METHOD = 8;
|
||||
private static final short FLAG_HAS_AFTER_UNMARSHAL_METHOD = 16;
|
||||
private static final short FLAG_HAS_BEFORE_MARSHAL_METHOD = 32;
|
||||
private static final short FLAG_HAS_AFTER_MARSHAL_METHOD = 64;
|
||||
private static final short FLAG_HAS_LIFECYCLE_EVENTS = 128;
|
||||
|
||||
/** cache of lifecycle methods */
|
||||
private LifecycleMethods lcm = null;
|
||||
|
||||
/**
|
||||
* True if {@link #jaxbType} has the lifecycle method.
|
||||
*/
|
||||
public final boolean hasBeforeUnmarshalMethod() {
|
||||
return (flag&FLAG_HAS_BEFORE_UNMARSHAL_METHOD) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if {@link #jaxbType} has the lifecycle method.
|
||||
*/
|
||||
public final boolean hasAfterUnmarshalMethod() {
|
||||
return (flag&FLAG_HAS_AFTER_UNMARSHAL_METHOD) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if {@link #jaxbType} has the lifecycle method.
|
||||
*/
|
||||
public final boolean hasBeforeMarshalMethod() {
|
||||
return (flag&FLAG_HAS_BEFORE_MARSHAL_METHOD) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if {@link #jaxbType} has the lifecycle method.
|
||||
*/
|
||||
public final boolean hasAfterMarshalMethod() {
|
||||
return (flag&FLAG_HAS_AFTER_MARSHAL_METHOD) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JAXB bound class type that this {@link JaxBeanInfo}
|
||||
* handles.
|
||||
*
|
||||
* <p>
|
||||
* IOW, when a bean info object is requested for T,
|
||||
* sometimes the bean info for one of its base classes might be
|
||||
* returned.
|
||||
*/
|
||||
public final Class<BeanT> jaxbType;
|
||||
|
||||
/**
|
||||
* Returns true if the bean is mapped to/from an XML element.
|
||||
*
|
||||
* <p>
|
||||
* When this method returns true, {@link #getElementNamespaceURI(Object)}
|
||||
* and {@link #getElementLocalName(Object)} returns the element name of
|
||||
* the bean.
|
||||
*/
|
||||
public final boolean isElement() {
|
||||
return (flag&FLAG_IS_ELEMENT)!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the bean is immutable.
|
||||
*
|
||||
* <p>
|
||||
* If this is true, Binder won't try to ueuse this object, and the unmarshaller
|
||||
* won't create a new instance of it before it starts.
|
||||
*/
|
||||
public final boolean isImmutable() {
|
||||
return (flag&FLAG_IS_IMMUTABLE)!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this bean has an element-only content model.
|
||||
* <p>
|
||||
* If this flag is true, the unmarshaller can work
|
||||
* faster by ignoring whitespaces more efficiently.
|
||||
*/
|
||||
public final boolean hasElementOnlyContentModel() {
|
||||
return (flag&FLAG_HAS_ELEMENT_ONLY_CONTENTMODEL)!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this bean has an element-only content model.
|
||||
* <p>
|
||||
* Should be considered immutable, though I can't mark it final
|
||||
* because it cannot be computed in this constructor.
|
||||
*/
|
||||
protected final void hasElementOnlyContentModel(boolean value) {
|
||||
if(value)
|
||||
flag |= FLAG_HAS_ELEMENT_ONLY_CONTENTMODEL;
|
||||
else
|
||||
flag &= ~FLAG_HAS_ELEMENT_ONLY_CONTENTMODEL;
|
||||
}
|
||||
|
||||
public boolean isNilIncluded() {
|
||||
return isNilIncluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to determine which of the sub-classes should be
|
||||
* interrogated for the existence of lifecycle methods.
|
||||
*
|
||||
* @return true if the un|marshaller should look for lifecycle methods
|
||||
* on this beanInfo, false otherwise.
|
||||
*/
|
||||
public boolean lookForLifecycleMethods() {
|
||||
return (flag&FLAG_HAS_LIFECYCLE_EVENTS)!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the namespace URI portion of the element name,
|
||||
* if the bean that this class represents is mapped from/to
|
||||
* an XML element.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if {@link #isElement} is false.
|
||||
*/
|
||||
public abstract String getElementNamespaceURI(BeanT o);
|
||||
|
||||
/**
|
||||
* Returns the local name portion of the element name,
|
||||
* if the bean that this class represents is mapped from/to
|
||||
* an XML element.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if {@link #isElement} is false.
|
||||
*/
|
||||
public abstract String getElementLocalName(BeanT o);
|
||||
|
||||
/**
|
||||
* Type names associated with this {@link JaxBeanInfo}.
|
||||
*
|
||||
* @see #getTypeNames()
|
||||
*/
|
||||
private final Object typeName; // either null, QName, or QName[]. save memory since most of them have just one.
|
||||
|
||||
/**
|
||||
* Returns XML Schema type names if the bean is mapped from
|
||||
* a complex/simple type of XML Schema.
|
||||
*
|
||||
* <p>
|
||||
* This is an ugly necessity to correctly handle
|
||||
* the type substitution semantics of XML Schema.
|
||||
*
|
||||
* <p>
|
||||
* A single Java class maybe mapped to more than one
|
||||
* XML types. All the types listed here are recognized
|
||||
* when we are unmarshalling XML.
|
||||
*
|
||||
* <p>
|
||||
* null if the class is not bound to a named schema type.
|
||||
*
|
||||
* <p>
|
||||
*/
|
||||
public Collection<QName> getTypeNames() {
|
||||
if(typeName==null) return Collections.emptyList();
|
||||
if(typeName instanceof QName) return Collections.singletonList((QName)typeName);
|
||||
return Arrays.asList((QName[])typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML type name to be used to marshal the specified instance.
|
||||
*
|
||||
* <P>
|
||||
* Most of the times the type can be determined regardless of the actual
|
||||
* instance, but there's a few exceptions (most notably {@link XMLGregorianCalendar}),
|
||||
* so as a general rule we need an instance to determine it.
|
||||
*/
|
||||
public QName getTypeName(@NotNull BeanT instance) {
|
||||
if(typeName==null) return null;
|
||||
if(typeName instanceof QName) return (QName)typeName;
|
||||
return ((QName[])typeName)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the bean.
|
||||
*
|
||||
* <p>
|
||||
* This operation is only supported when {@link #isImmutable} is false.
|
||||
*
|
||||
* @param context
|
||||
* Sometimes the created bean remembers the corresponding source location,
|
||||
*/
|
||||
public abstract BeanT createInstance(UnmarshallingContext context) throws IllegalAccessException, InvocationTargetException, InstantiationException, SAXException;
|
||||
|
||||
/**
|
||||
* Resets the object to the initial state, as if the object
|
||||
* is created fresh.
|
||||
*
|
||||
* <p>
|
||||
* This is used to reuse an existing object for unmarshalling.
|
||||
*
|
||||
* @param context
|
||||
* used for reporting any errors.
|
||||
*
|
||||
* @return
|
||||
* true if the object was successfuly resetted.
|
||||
* False if the object is not resettable, in which case the object will be
|
||||
* discarded and new one will be created.
|
||||
* <p>
|
||||
* If the object is resettable but failed by an error, it should be reported to the context,
|
||||
* then return false. If the object is not resettable to begin with, do not report an error.
|
||||
*
|
||||
* @throws SAXException
|
||||
* as a result of reporting an error, the context may throw a {@link SAXException}.
|
||||
*/
|
||||
public abstract boolean reset( BeanT o, UnmarshallingContext context ) throws SAXException;
|
||||
|
||||
/**
|
||||
* Gets the ID value of the given bean, if it has an ID value.
|
||||
* Otherwise return null.
|
||||
*/
|
||||
public abstract String getId(BeanT o, XMLSerializer target) throws SAXException;
|
||||
|
||||
/**
|
||||
* Serializes child elements and texts into the specified target.
|
||||
*/
|
||||
public abstract void serializeBody( BeanT o, XMLSerializer target ) throws SAXException, IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Serializes attributes into the specified target.
|
||||
*/
|
||||
public abstract void serializeAttributes( BeanT o, XMLSerializer target ) throws SAXException, IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Serializes the bean as the root element.
|
||||
*
|
||||
* <p>
|
||||
* In the java-to-schema binding, an object might marshal in two different
|
||||
* ways depending on whether it is used as the root of the graph or not.
|
||||
* In the former case, an object could marshal as an element, whereas
|
||||
* in the latter case, it marshals as a type.
|
||||
*
|
||||
* <p>
|
||||
* This method is used to marshal the root of the object graph to allow
|
||||
* this semantics to be implemented.
|
||||
*
|
||||
* <p>
|
||||
* It is doubtful to me if it's a good idea for an object to marshal
|
||||
* in two ways depending on the context.
|
||||
*
|
||||
* <p>
|
||||
* For schema-to-java, this is equivalent to {@link #serializeBody(Object, XMLSerializer)}.
|
||||
*/
|
||||
public abstract void serializeRoot( BeanT o, XMLSerializer target ) throws SAXException, IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Declares all the namespace URIs this object is using at
|
||||
* its top-level scope into the specified target.
|
||||
*/
|
||||
public abstract void serializeURIs( BeanT o, XMLSerializer target ) throws SAXException;
|
||||
|
||||
/**
|
||||
* Gets the {@link Loader} that will unmarshall the given object.
|
||||
*
|
||||
* @param context
|
||||
* The {@link JAXBContextImpl} object that governs this object.
|
||||
* This object is taken as a parameter so that {@link JaxBeanInfo} doesn't have
|
||||
* to store them on its own.
|
||||
*
|
||||
* When this method is invoked from within the unmarshaller, tihs parameter can be
|
||||
* null (because the loader is constructed already.)
|
||||
*
|
||||
* @param typeSubstitutionCapable
|
||||
* If true, the returned {@link Loader} is capable of recognizing @xsi:type (if necessary)
|
||||
* and unmarshals a subtype. This allowes an optimization where this bean info
|
||||
* is guaranteed not to have a type substitution.
|
||||
* If false, the returned {@link Loader} doesn't look for @xsi:type.
|
||||
* @return
|
||||
* must return non-null valid object
|
||||
*/
|
||||
public abstract Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable);
|
||||
|
||||
/**
|
||||
* If the bean's representation in XML is just a text,
|
||||
* this method return a {@link Transducer} that lets you convert
|
||||
* values between the text and the bean.
|
||||
*/
|
||||
public abstract Transducer<BeanT> getTransducer();
|
||||
|
||||
|
||||
/**
|
||||
* Called after all the {@link JaxBeanInfo}s are created.
|
||||
* @param grammar
|
||||
*/
|
||||
protected void link(JAXBContextImpl grammar) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at the end of the {@link JAXBContext} initialization phase
|
||||
* to clean up any unnecessary references.
|
||||
*/
|
||||
public void wrapUp() {}
|
||||
|
||||
|
||||
private static final Class[] unmarshalEventParams = { Unmarshaller.class, Object.class };
|
||||
private static Class[] marshalEventParams = { Marshaller.class };
|
||||
|
||||
/**
|
||||
* use reflection to determine which of the 4 object lifecycle methods exist on
|
||||
* the JAXB bound type.
|
||||
*/
|
||||
protected final void setLifecycleFlags() {
|
||||
try {
|
||||
Class<BeanT> jt = jaxbType;
|
||||
|
||||
if (lcm == null) {
|
||||
lcm = new LifecycleMethods();
|
||||
}
|
||||
|
||||
while (jt != null) {
|
||||
for (Method m : jt.getDeclaredMethods()) {
|
||||
String name = m.getName();
|
||||
|
||||
if (lcm.beforeUnmarshal == null) {
|
||||
if (name.equals("beforeUnmarshal")) {
|
||||
if (match(m, unmarshalEventParams)) {
|
||||
cacheLifecycleMethod(m, FLAG_HAS_BEFORE_UNMARSHAL_METHOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lcm.afterUnmarshal == null) {
|
||||
if (name.equals("afterUnmarshal")) {
|
||||
if (match(m, unmarshalEventParams)) {
|
||||
cacheLifecycleMethod(m, FLAG_HAS_AFTER_UNMARSHAL_METHOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lcm.beforeMarshal == null) {
|
||||
if (name.equals("beforeMarshal")) {
|
||||
if (match(m, marshalEventParams)) {
|
||||
cacheLifecycleMethod(m, FLAG_HAS_BEFORE_MARSHAL_METHOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lcm.afterMarshal == null) {
|
||||
if (name.equals("afterMarshal")) {
|
||||
if (match(m, marshalEventParams)) {
|
||||
cacheLifecycleMethod(m, FLAG_HAS_AFTER_MARSHAL_METHOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jt = (Class<BeanT>) jt.getSuperclass();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// this happens when we don't have enough permission.
|
||||
logger.log(Level.WARNING, Messages.UNABLE_TO_DISCOVER_EVENTHANDLER.format(
|
||||
jaxbType.getName(), e));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean match(Method m, Class[] params) {
|
||||
return Arrays.equals(m.getParameterTypes(),params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache a reference to the specified lifecycle method for the jaxbType
|
||||
* associated with this beanInfo.
|
||||
*
|
||||
* @param m Method reference
|
||||
* @param lifecycleFlag byte representing which of the 4 lifecycle methods
|
||||
* is being cached
|
||||
*/
|
||||
private void cacheLifecycleMethod(Method m, short lifecycleFlag) {
|
||||
//LifecycleMethods lcm = getLifecycleMethods();
|
||||
if(lcm==null) {
|
||||
lcm = new LifecycleMethods();
|
||||
//lcmCache.put(jaxbType, lcm);
|
||||
}
|
||||
|
||||
m.setAccessible(true);
|
||||
|
||||
flag |= lifecycleFlag;
|
||||
|
||||
switch (lifecycleFlag) {
|
||||
case FLAG_HAS_BEFORE_UNMARSHAL_METHOD:
|
||||
lcm.beforeUnmarshal = m;
|
||||
break;
|
||||
case FLAG_HAS_AFTER_UNMARSHAL_METHOD:
|
||||
lcm.afterUnmarshal = m;
|
||||
break;
|
||||
case FLAG_HAS_BEFORE_MARSHAL_METHOD:
|
||||
lcm.beforeMarshal = m;
|
||||
break;
|
||||
case FLAG_HAS_AFTER_MARSHAL_METHOD:
|
||||
lcm.afterMarshal = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the LifecycleMethods cache for this ClassBeanInfo's corresponding
|
||||
* jaxbType if it exists, else return null.
|
||||
*
|
||||
*/
|
||||
public final LifecycleMethods getLifecycleMethods() {
|
||||
return lcm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the beforeUnmarshal method if applicable.
|
||||
*/
|
||||
public final void invokeBeforeUnmarshalMethod(UnmarshallerImpl unm, Object child, Object parent) throws SAXException {
|
||||
Method m = getLifecycleMethods().beforeUnmarshal;
|
||||
invokeUnmarshallCallback(m, child, unm, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the afterUnmarshal method if applicable.
|
||||
*/
|
||||
public final void invokeAfterUnmarshalMethod(UnmarshallerImpl unm, Object child, Object parent) throws SAXException {
|
||||
Method m = getLifecycleMethods().afterUnmarshal;
|
||||
invokeUnmarshallCallback(m, child, unm, parent);
|
||||
}
|
||||
|
||||
private void invokeUnmarshallCallback(Method m, Object child, UnmarshallerImpl unm, Object parent) throws SAXException {
|
||||
try {
|
||||
m.invoke(child,unm,parent);
|
||||
} catch (IllegalAccessException e) {
|
||||
UnmarshallingContext.getInstance().handleError(e, false);
|
||||
} catch (InvocationTargetException e) {
|
||||
UnmarshallingContext.getInstance().handleError(e, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger logger = Util.getClassLogger();
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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 java.io.IOException;
|
||||
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeLeafInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TextLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} implementation for immutable leaf classes.
|
||||
*
|
||||
* <p>
|
||||
* Leaf classes are always bound to a text and they are often immutable.
|
||||
* The JAXB spec allows this binding for a few special Java classes plus
|
||||
* type-safe enums.
|
||||
*
|
||||
* <p>
|
||||
* This implementation obtains necessary information from {@link RuntimeLeafInfo}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class LeafBeanInfoImpl<BeanT> extends JaxBeanInfo<BeanT> {
|
||||
|
||||
private final Loader loader;
|
||||
private final Loader loaderWithSubst;
|
||||
|
||||
private final Transducer<BeanT> xducer;
|
||||
|
||||
/**
|
||||
* Non-null only if the leaf is also an element.
|
||||
*/
|
||||
private final Name tagName;
|
||||
|
||||
public LeafBeanInfoImpl(JAXBContextImpl grammar, RuntimeLeafInfo li) {
|
||||
super(grammar,li,li.getClazz(),li.getTypeNames(),li.isElement(),true,false);
|
||||
|
||||
xducer = li.getTransducer();
|
||||
loader = new TextLoader(xducer);
|
||||
loaderWithSubst = new XsiTypeLoader(this);
|
||||
|
||||
if(isElement())
|
||||
tagName = grammar.nameBuilder.createElementName(li.getElementName());
|
||||
else
|
||||
tagName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getTypeName(BeanT instance) {
|
||||
QName tn = xducer.getTypeName(instance);
|
||||
if(tn!=null) return tn;
|
||||
// rely on default
|
||||
return super.getTypeName(instance);
|
||||
}
|
||||
|
||||
public final String getElementNamespaceURI(BeanT t) {
|
||||
return tagName.nsUri;
|
||||
}
|
||||
|
||||
public final String getElementLocalName(BeanT t) {
|
||||
return tagName.localName;
|
||||
}
|
||||
|
||||
public BeanT createInstance(UnmarshallingContext context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final boolean reset(BeanT bean, UnmarshallingContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final String getId(BeanT bean, XMLSerializer target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void serializeBody(BeanT bean, XMLSerializer w) throws SAXException, IOException, XMLStreamException {
|
||||
// most of the times leaves are printed as leaf element/attribute property,
|
||||
// so this code is only used for example when you have multiple XmlElement on a property
|
||||
// and some of them are leaves. Hence this doesn't need to be super-fast.
|
||||
try {
|
||||
xducer.writeText(w,bean,null);
|
||||
} catch (AccessorException e) {
|
||||
w.reportError(null,e);
|
||||
}
|
||||
}
|
||||
|
||||
public final void serializeAttributes(BeanT bean, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public final void serializeRoot(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
if(tagName==null) {
|
||||
target.reportError(
|
||||
new ValidationEventImpl(
|
||||
ValidationEvent.ERROR,
|
||||
Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(bean.getClass().getName()),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
else {
|
||||
target.startElement(tagName,bean);
|
||||
target.childAsSoleContent(bean,null);
|
||||
target.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
public final void serializeURIs(BeanT bean, XMLSerializer target) throws SAXException {
|
||||
// TODO: maybe we should create another LeafBeanInfoImpl class for
|
||||
// context-dependent xducers?
|
||||
if(xducer.useNamespace()) {
|
||||
try {
|
||||
xducer.declareNamespace(bean,target);
|
||||
} catch (AccessorException e) {
|
||||
target.reportError(null,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
if(typeSubstitutionCapable)
|
||||
return loaderWithSubst;
|
||||
else
|
||||
return loader;
|
||||
}
|
||||
|
||||
public Transducer<BeanT> getTransducer() {
|
||||
return xducer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 java.lang.reflect.Method;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
/**
|
||||
* This class is a simple container for caching lifecycle methods that are
|
||||
* discovered during construction of (@link JAXBContext}.
|
||||
*
|
||||
* @see JaxBeanInfo#lcm
|
||||
* @see Loader#fireBeforeUnmarshal(JaxBeanInfo, Object, UnmarshallingContext.State)
|
||||
* @see Loader#fireAfterUnmarshal(JaxBeanInfo, Object, UnmarshallingContext.State)
|
||||
* @see XMLSerializer#fireMarshalEvent(Object, Method)
|
||||
*/
|
||||
final class LifecycleMethods {
|
||||
Method beforeUnmarshal;
|
||||
Method afterUnmarshal;
|
||||
Method beforeMarshal;
|
||||
Method afterMarshal;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Location information for {@link IllegalAnnotationException}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @since JAXB 2.0 EA1
|
||||
*/
|
||||
// internally, Location is created from Locatable.
|
||||
public interface Location {
|
||||
/**
|
||||
* Returns a human-readable string that represents this position.
|
||||
*
|
||||
* @return
|
||||
* never null.
|
||||
*/
|
||||
String toString();
|
||||
}
|
||||
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, 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 java.io.BufferedWriter;
|
||||
import java.io.Closeable;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.MarshalException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.PropertyException;
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.ValidationEventHandler;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.bind.helpers.AbstractMarshallerImpl;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.ValidatorHandler;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
|
||||
import com.sun.xml.internal.bind.api.JAXBRIContext;
|
||||
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
|
||||
import com.sun.xml.internal.bind.marshaller.DataWriter;
|
||||
import com.sun.xml.internal.bind.marshaller.DumbEscapeHandler;
|
||||
import com.sun.xml.internal.bind.marshaller.MinimumEscapeHandler;
|
||||
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
|
||||
import com.sun.xml.internal.bind.marshaller.NioEscapeHandler;
|
||||
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
|
||||
import com.sun.xml.internal.bind.marshaller.XMLWriter;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.C14nXmlOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.Encoded;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.ForkXmlOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.IndentingUTF8XmlOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.NamespaceContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.SAXOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.UTF8XmlOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.XMLEventWriterOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.XMLStreamWriterOutput;
|
||||
import com.sun.xml.internal.bind.v2.runtime.output.XmlOutput;
|
||||
import com.sun.xml.internal.bind.v2.util.FatalAdapter;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Implementation of {@link Marshaller} interface for the JAXB RI.
|
||||
*
|
||||
* <p>
|
||||
* Eventually all the {@link #marshal} methods call into
|
||||
* the {@link #write} method.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Vivek Pandey
|
||||
*/
|
||||
public /*to make unit tests happy*/ final class MarshallerImpl extends AbstractMarshallerImpl implements ValidationEventHandler
|
||||
{
|
||||
/** Indentation string. Default is four whitespaces. */
|
||||
private String indent = " ";
|
||||
|
||||
/** Used to assign prefixes to namespace URIs. */
|
||||
private NamespacePrefixMapper prefixMapper = null;
|
||||
|
||||
/** Object that handles character escaping. */
|
||||
private CharacterEscapeHandler escapeHandler = null;
|
||||
|
||||
/** XML BLOB written after the XML declaration. */
|
||||
private String header=null;
|
||||
|
||||
/** reference to the context that created this object */
|
||||
final JAXBContextImpl context;
|
||||
|
||||
protected final XMLSerializer serializer;
|
||||
|
||||
/**
|
||||
* Non-null if we do the marshal-time validation.
|
||||
*/
|
||||
private Schema schema;
|
||||
|
||||
/** Marshaller.Listener */
|
||||
private Listener externalListener = null;
|
||||
|
||||
/** Configured for c14n? */
|
||||
private boolean c14nSupport;
|
||||
|
||||
// while createing XmlOutput those values may be set.
|
||||
// if these are non-null they need to be cleaned up
|
||||
private Flushable toBeFlushed;
|
||||
private Closeable toBeClosed;
|
||||
|
||||
/**
|
||||
* @param assoc
|
||||
* non-null if the marshaller is working inside {@link BinderImpl}.
|
||||
*/
|
||||
public MarshallerImpl( JAXBContextImpl c, AssociationMap assoc ) {
|
||||
context = c;
|
||||
serializer = new XMLSerializer(this);
|
||||
c14nSupport = context.c14nSupport;
|
||||
|
||||
try {
|
||||
setEventHandler(this);
|
||||
} catch (JAXBException e) {
|
||||
throw new AssertionError(e); // impossible
|
||||
}
|
||||
}
|
||||
|
||||
public JAXBContextImpl getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals to {@link OutputStream} with the given in-scope namespaces
|
||||
* taken into account.
|
||||
*
|
||||
* @since 2.1.5
|
||||
*/
|
||||
public void marshal(Object obj, OutputStream out, NamespaceContext inscopeNamespace) throws JAXBException {
|
||||
write(obj, createWriter(out), new StAXPostInitAction(inscopeNamespace,serializer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException {
|
||||
write(obj, XMLStreamWriterOutput.create(writer,context, escapeHandler), new StAXPostInitAction(writer,serializer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object obj, XMLEventWriter writer) throws JAXBException {
|
||||
write(obj, new XMLEventWriterOutput(writer), new StAXPostInitAction(writer,serializer));
|
||||
}
|
||||
|
||||
public void marshal(Object obj, XmlOutput output) throws JAXBException {
|
||||
write(obj, output, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link XmlOutput} from the given {@link Result} object.
|
||||
*/
|
||||
final XmlOutput createXmlOutput(Result result) throws JAXBException {
|
||||
if (result instanceof SAXResult)
|
||||
return new SAXOutput(((SAXResult) result).getHandler());
|
||||
|
||||
if (result instanceof DOMResult) {
|
||||
final Node node = ((DOMResult) result).getNode();
|
||||
|
||||
if (node == null) {
|
||||
Document doc = JAXBContextImpl.createDom(getContext().disableSecurityProcessing);
|
||||
((DOMResult) result).setNode(doc);
|
||||
return new SAXOutput(new SAX2DOMEx(doc));
|
||||
} else {
|
||||
return new SAXOutput(new SAX2DOMEx(node));
|
||||
}
|
||||
}
|
||||
if (result instanceof StreamResult) {
|
||||
StreamResult sr = (StreamResult) result;
|
||||
|
||||
if (sr.getWriter() != null)
|
||||
return createWriter(sr.getWriter());
|
||||
else if (sr.getOutputStream() != null)
|
||||
return createWriter(sr.getOutputStream());
|
||||
else if (sr.getSystemId() != null) {
|
||||
String fileURL = sr.getSystemId();
|
||||
|
||||
try {
|
||||
fileURL = new URI(fileURL).getPath();
|
||||
} catch (URISyntaxException use) {
|
||||
// otherwise assume that it's a file name
|
||||
}
|
||||
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(fileURL);
|
||||
assert toBeClosed==null;
|
||||
toBeClosed = fos;
|
||||
return createWriter(fos);
|
||||
} catch (IOException e) {
|
||||
throw new MarshalException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsupported parameter type
|
||||
throw new MarshalException(Messages.UNSUPPORTED_RESULT.format());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an appropriate post-init action object.
|
||||
*/
|
||||
final Runnable createPostInitAction(Result result) {
|
||||
if (result instanceof DOMResult) {
|
||||
Node node = ((DOMResult) result).getNode();
|
||||
return new DomPostInitAction(node,serializer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void marshal(Object target,Result result) throws JAXBException {
|
||||
write(target, createXmlOutput(result), createPostInitAction(result));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by {@link BridgeImpl} to write an arbitrary object as a fragment.
|
||||
*/
|
||||
protected final <T> void write(Name rootTagName, JaxBeanInfo<T> bi, T obj, XmlOutput out,Runnable postInitAction) throws JAXBException {
|
||||
try {
|
||||
try {
|
||||
prewrite(out, true, postInitAction);
|
||||
serializer.startElement(rootTagName,null);
|
||||
if(bi.jaxbType==Void.class || bi.jaxbType==void.class) {
|
||||
// special case for void
|
||||
serializer.endNamespaceDecls(null);
|
||||
serializer.endAttributes();
|
||||
} else { // normal cases
|
||||
if(obj==null)
|
||||
serializer.writeXsiNilTrue();
|
||||
else
|
||||
serializer.childAsXsiType(obj,"root",bi, false);
|
||||
}
|
||||
serializer.endElement();
|
||||
postwrite();
|
||||
} catch( SAXException e ) {
|
||||
throw new MarshalException(e);
|
||||
} catch (IOException e) {
|
||||
throw new MarshalException(e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new MarshalException(e);
|
||||
} finally {
|
||||
serializer.close();
|
||||
}
|
||||
} finally {
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All the marshal method invocation eventually comes down to this call.
|
||||
*/
|
||||
private void write(Object obj, XmlOutput out, Runnable postInitAction) throws JAXBException {
|
||||
try {
|
||||
if( obj == null )
|
||||
throw new IllegalArgumentException(Messages.NOT_MARSHALLABLE.format());
|
||||
|
||||
if( schema!=null ) {
|
||||
// send the output to the validator as well
|
||||
ValidatorHandler validator = schema.newValidatorHandler();
|
||||
validator.setErrorHandler(new FatalAdapter(serializer));
|
||||
// work around a bug in JAXP validator in Tiger
|
||||
XMLFilterImpl f = new XMLFilterImpl() {
|
||||
@Override
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
super.startPrefixMapping(prefix.intern(), uri.intern());
|
||||
}
|
||||
};
|
||||
f.setContentHandler(validator);
|
||||
out = new ForkXmlOutput( new SAXOutput(f) {
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws SAXException, IOException, XMLStreamException {
|
||||
super.startDocument(serializer, false, nsUriIndex2prefixIndex, nsContext);
|
||||
}
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws SAXException, IOException, XMLStreamException {
|
||||
super.endDocument(false);
|
||||
}
|
||||
}, out );
|
||||
}
|
||||
|
||||
try {
|
||||
prewrite(out,isFragment(),postInitAction);
|
||||
serializer.childAsRoot(obj);
|
||||
postwrite();
|
||||
} catch( SAXException e ) {
|
||||
throw new MarshalException(e);
|
||||
} catch (IOException e) {
|
||||
throw new MarshalException(e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new MarshalException(e);
|
||||
} finally {
|
||||
serializer.close();
|
||||
}
|
||||
} finally {
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanUp() {
|
||||
if(toBeFlushed!=null)
|
||||
try {
|
||||
toBeFlushed.flush();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
if(toBeClosed!=null)
|
||||
try {
|
||||
toBeClosed.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
toBeFlushed = null;
|
||||
toBeClosed = null;
|
||||
}
|
||||
|
||||
// common parts between two write methods.
|
||||
|
||||
private void prewrite(XmlOutput out, boolean fragment, Runnable postInitAction) throws IOException, SAXException, XMLStreamException {
|
||||
serializer.startDocument(out,fragment,getSchemaLocation(),getNoNSSchemaLocation());
|
||||
if(postInitAction!=null) postInitAction.run();
|
||||
if(prefixMapper!=null) {
|
||||
// be defensive as we work with the user's code
|
||||
String[] decls = prefixMapper.getContextualNamespaceDecls();
|
||||
if(decls!=null) { // defensive check
|
||||
for( int i=0; i<decls.length; i+=2 ) {
|
||||
String prefix = decls[i];
|
||||
String nsUri = decls[i+1];
|
||||
if(nsUri!=null && prefix!=null) // defensive check
|
||||
serializer.addInscopeBinding(nsUri,prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
serializer.setPrefixMapper(prefixMapper);
|
||||
}
|
||||
|
||||
private void postwrite() throws IOException, SAXException, XMLStreamException {
|
||||
serializer.endDocument();
|
||||
serializer.reconcileID(); // extra check
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns escape handler provided with JAXB context parameters.
|
||||
*
|
||||
* @return escape handler
|
||||
*/
|
||||
CharacterEscapeHandler getEscapeHandler() {
|
||||
return escapeHandler;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// create XMLWriter by specifing various type of output.
|
||||
//
|
||||
//
|
||||
|
||||
protected CharacterEscapeHandler createEscapeHandler( String encoding ) {
|
||||
if( escapeHandler!=null )
|
||||
// user-specified one takes precedence.
|
||||
return escapeHandler;
|
||||
|
||||
if( encoding.startsWith("UTF") )
|
||||
// no need for character reference. Use the handler
|
||||
// optimized for that pattern.
|
||||
return MinimumEscapeHandler.theInstance;
|
||||
|
||||
// otherwise try to find one from the encoding
|
||||
try {
|
||||
// try new JDK1.4 NIO
|
||||
return new NioEscapeHandler( getJavaEncoding(encoding) );
|
||||
} catch( Throwable e ) {
|
||||
// if that fails, fall back to the dumb mode
|
||||
return DumbEscapeHandler.theInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public XmlOutput createWriter( Writer w, String encoding ) {
|
||||
// XMLWriter doesn't do buffering, so do it here if it looks like a good idea
|
||||
if(!(w instanceof BufferedWriter))
|
||||
w = new BufferedWriter(w);
|
||||
|
||||
assert toBeFlushed==null;
|
||||
toBeFlushed = w;
|
||||
|
||||
CharacterEscapeHandler ceh = createEscapeHandler(encoding);
|
||||
XMLWriter xw;
|
||||
|
||||
if(isFormattedOutput()) {
|
||||
DataWriter d = new DataWriter(w,encoding,ceh);
|
||||
d.setIndentStep(indent);
|
||||
xw=d;
|
||||
} else
|
||||
xw = new XMLWriter(w,encoding,ceh);
|
||||
|
||||
xw.setXmlDecl(!isFragment());
|
||||
xw.setHeader(header);
|
||||
return new SAXOutput(xw); // TODO: don't we need a better writer?
|
||||
}
|
||||
|
||||
public XmlOutput createWriter(Writer w) {
|
||||
return createWriter(w, getEncoding());
|
||||
}
|
||||
|
||||
public XmlOutput createWriter( OutputStream os ) throws JAXBException {
|
||||
return createWriter(os, getEncoding());
|
||||
}
|
||||
|
||||
public XmlOutput createWriter( OutputStream os, String encoding ) throws JAXBException {
|
||||
// UTF8XmlOutput does buffering on its own, and
|
||||
// otherwise createWriter(Writer) inserts a buffering,
|
||||
// so no point in doing a buffering here.
|
||||
|
||||
if(encoding.equals("UTF-8")) {
|
||||
Encoded[] table = context.getUTF8NameTable();
|
||||
final UTF8XmlOutput out;
|
||||
if(isFormattedOutput())
|
||||
out = new IndentingUTF8XmlOutput(os, indent, table, escapeHandler);
|
||||
else {
|
||||
if(c14nSupport)
|
||||
out = new C14nXmlOutput(os, table, context.c14nSupport, escapeHandler);
|
||||
else
|
||||
out = new UTF8XmlOutput(os, table, escapeHandler);
|
||||
}
|
||||
if(header!=null)
|
||||
out.setHeader(header);
|
||||
return out;
|
||||
}
|
||||
|
||||
try {
|
||||
return createWriter(
|
||||
new OutputStreamWriter(os,getJavaEncoding(encoding)),
|
||||
encoding );
|
||||
} catch( UnsupportedEncodingException e ) {
|
||||
throw new MarshalException(
|
||||
Messages.UNSUPPORTED_ENCODING.format(encoding),
|
||||
e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) throws PropertyException {
|
||||
if( INDENT_STRING.equals(name) )
|
||||
return indent;
|
||||
if( ENCODING_HANDLER.equals(name) || ENCODING_HANDLER2.equals(name) )
|
||||
return escapeHandler;
|
||||
if( PREFIX_MAPPER.equals(name) )
|
||||
return prefixMapper;
|
||||
if( XMLDECLARATION.equals(name) )
|
||||
return !isFragment();
|
||||
if( XML_HEADERS.equals(name) )
|
||||
return header;
|
||||
if( C14N.equals(name) )
|
||||
return c14nSupport;
|
||||
if ( OBJECT_IDENTITY_CYCLE_DETECTION.equals(name))
|
||||
return serializer.getObjectIdentityCycleDetection();
|
||||
|
||||
return super.getProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String name, Object value) throws PropertyException {
|
||||
if( INDENT_STRING.equals(name) ) {
|
||||
checkString(name, value);
|
||||
indent = (String)value;
|
||||
return;
|
||||
}
|
||||
if( ENCODING_HANDLER.equals(name) || ENCODING_HANDLER2.equals(name)) {
|
||||
if(!(value instanceof CharacterEscapeHandler))
|
||||
throw new PropertyException(
|
||||
Messages.MUST_BE_X.format(
|
||||
name,
|
||||
CharacterEscapeHandler.class.getName(),
|
||||
value.getClass().getName() ) );
|
||||
escapeHandler = (CharacterEscapeHandler)value;
|
||||
return;
|
||||
}
|
||||
if( PREFIX_MAPPER.equals(name) ) {
|
||||
if(!(value instanceof NamespacePrefixMapper))
|
||||
throw new PropertyException(
|
||||
Messages.MUST_BE_X.format(
|
||||
name,
|
||||
NamespacePrefixMapper.class.getName(),
|
||||
value.getClass().getName() ) );
|
||||
prefixMapper = (NamespacePrefixMapper)value;
|
||||
return;
|
||||
}
|
||||
if( XMLDECLARATION.equals(name) ) {
|
||||
checkBoolean(name, value);
|
||||
// com.sun.xml.internal.bind.xmlDeclaration is an alias for JAXB_FRAGMENT
|
||||
// setting it to false is treated the same as setting fragment to true.
|
||||
super.setProperty(JAXB_FRAGMENT, !(Boolean)value);
|
||||
return;
|
||||
}
|
||||
if( XML_HEADERS.equals(name) ) {
|
||||
checkString(name, value);
|
||||
header = (String)value;
|
||||
return;
|
||||
}
|
||||
if( C14N.equals(name) ) {
|
||||
checkBoolean(name,value);
|
||||
c14nSupport = (Boolean)value;
|
||||
return;
|
||||
}
|
||||
if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(name)) {
|
||||
checkBoolean(name,value);
|
||||
serializer.setObjectIdentityCycleDetection((Boolean)value);
|
||||
return;
|
||||
}
|
||||
|
||||
super.setProperty(name, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* assert that the given object is a Boolean
|
||||
*/
|
||||
private void checkBoolean( String name, Object value ) throws PropertyException {
|
||||
if(!(value instanceof Boolean))
|
||||
throw new PropertyException(
|
||||
Messages.MUST_BE_X.format(
|
||||
name,
|
||||
Boolean.class.getName(),
|
||||
value.getClass().getName() ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* assert that the given object is a String
|
||||
*/
|
||||
private void checkString( String name, Object value ) throws PropertyException {
|
||||
if(!(value instanceof String))
|
||||
throw new PropertyException(
|
||||
Messages.MUST_BE_X.format(
|
||||
name,
|
||||
String.class.getName(),
|
||||
value.getClass().getName() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
|
||||
if(type==null)
|
||||
throw new IllegalArgumentException();
|
||||
serializer.putAdapter(type,adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends XmlAdapter> A getAdapter(Class<A> type) {
|
||||
if(type==null)
|
||||
throw new IllegalArgumentException();
|
||||
if(serializer.containsAdapter(type))
|
||||
// so as not to create a new instance when this method is called
|
||||
return serializer.getAdapter(type);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttachmentMarshaller(AttachmentMarshaller am) {
|
||||
serializer.attachmentMarshaller = am;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachmentMarshaller getAttachmentMarshaller() {
|
||||
return serializer.attachmentMarshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Schema getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSchema(Schema s) {
|
||||
this.schema = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default error handling behavior fot {@link Marshaller}.
|
||||
*/
|
||||
public boolean handleEvent(ValidationEvent event) {
|
||||
// draconian by default
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener getListener() {
|
||||
return externalListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(Listener listener) {
|
||||
externalListener = listener;
|
||||
}
|
||||
|
||||
// features supported
|
||||
protected static final String INDENT_STRING = "com.sun.xml.internal.bind.indentString";
|
||||
protected static final String PREFIX_MAPPER = "com.sun.xml.internal.bind.namespacePrefixMapper";
|
||||
protected static final String ENCODING_HANDLER = "com.sun.xml.internal.bind.characterEscapeHandler";
|
||||
protected static final String ENCODING_HANDLER2 = "com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler";
|
||||
protected static final String XMLDECLARATION = "com.sun.xml.internal.bind.xmlDeclaration";
|
||||
protected static final String XML_HEADERS = "com.sun.xml.internal.bind.xmlHeaders";
|
||||
protected static final String C14N = JAXBRIContext.CANONICALIZATION_SUPPORT;
|
||||
protected static final String OBJECT_IDENTITY_CYCLE_DETECTION = "com.sun.xml.internal.bind.objectIdentitityCycleDetection";
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Message resources
|
||||
*/
|
||||
enum Messages {
|
||||
ILLEGAL_PARAMETER, // 2 args
|
||||
UNABLE_TO_FIND_CONVERSION_METHOD, // 3 args
|
||||
MISSING_ID, // 1 arg
|
||||
NOT_IMPLEMENTED_IN_2_0,
|
||||
UNRECOGNIZED_ELEMENT_NAME,
|
||||
TYPE_MISMATCH, // 3 args
|
||||
MISSING_OBJECT, // 1 arg
|
||||
NOT_IDENTIFIABLE, // 0 args
|
||||
DANGLING_IDREF, // 1 arg
|
||||
NULL_OUTPUT_RESOLVER, // 0 args
|
||||
UNABLE_TO_MARSHAL_NON_ELEMENT, // 1 arg
|
||||
UNABLE_TO_MARSHAL_UNBOUND_CLASS, // 1 arg
|
||||
UNSUPPORTED_PROPERTY, // 1 arg
|
||||
NULL_PROPERTY_NAME, // 0 args
|
||||
MUST_BE_X, // 3 args
|
||||
NOT_MARSHALLABLE, // 0 args
|
||||
UNSUPPORTED_RESULT, // 0 args
|
||||
UNSUPPORTED_ENCODING, // 1 arg
|
||||
SUBSTITUTED_BY_ANONYMOUS_TYPE, // 3 arg
|
||||
CYCLE_IN_MARSHALLER, // 1 arg
|
||||
UNABLE_TO_DISCOVER_EVENTHANDLER, // 1 arg
|
||||
ELEMENT_NEEDED_BUT_FOUND_DOCUMENT, // 1 arg
|
||||
UNKNOWN_CLASS, // 1 arg
|
||||
FAILED_TO_GENERATE_SCHEMA, // 0 args
|
||||
ERROR_PROCESSING_SCHEMA, // 0 args
|
||||
ILLEGAL_CONTENT, // 2 args
|
||||
;
|
||||
|
||||
private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName());
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return format();
|
||||
}
|
||||
|
||||
public String format( Object... args ) {
|
||||
return MessageFormat.format( rb.getString(name()), args );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.activation.MimeType;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Transducer} decorator that wraps another {@link Transducer}
|
||||
* and sets the expected MIME type to the context.
|
||||
*
|
||||
* <p>
|
||||
* Combined with {@link Transducer} implementations (such as one for {@link Image}),
|
||||
* this is used to control the marshalling of the BLOB types.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class MimeTypedTransducer<V> extends FilterTransducer<V> {
|
||||
private final MimeType expectedMimeType;
|
||||
|
||||
public MimeTypedTransducer(Transducer<V> core,MimeType expectedMimeType) {
|
||||
super(core);
|
||||
this.expectedMimeType = expectedMimeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence print(V o) throws AccessorException {
|
||||
XMLSerializer w = XMLSerializer.getInstance();
|
||||
MimeType old = w.setExpectedMimeType(expectedMimeType);
|
||||
try {
|
||||
return core.print(o);
|
||||
} finally {
|
||||
w.setExpectedMimeType(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeText(XMLSerializer w, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
MimeType old = w.setExpectedMimeType(expectedMimeType);
|
||||
try {
|
||||
core.writeText(w, o, fieldName);
|
||||
} finally {
|
||||
w.setExpectedMimeType(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
MimeType old = w.setExpectedMimeType(expectedMimeType);
|
||||
try {
|
||||
core.writeLeafElement(w, tagName, o, fieldName);
|
||||
} finally {
|
||||
w.setExpectedMimeType(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
98
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Name.java
Normal file
98
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Name.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.namespace.QName;
|
||||
|
||||
/**
|
||||
* The internal representation of an XML name.
|
||||
*
|
||||
* <p>
|
||||
* This class keeps indicies for URI and local name for enabling faster processing.
|
||||
*
|
||||
* <p>
|
||||
* {@link Name}s are ordered lexicographically (nsUri first, local name next.)
|
||||
* This is the same order required by canonical XML.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Name implements Comparable<Name> {
|
||||
/**
|
||||
* Namespace URI. interned.
|
||||
*/
|
||||
public final String nsUri;
|
||||
|
||||
/**
|
||||
* Local name. interned.
|
||||
*/
|
||||
public final String localName;
|
||||
|
||||
/**
|
||||
* Index -1 is reserved for representing the empty namespace URI of attributes.
|
||||
*/
|
||||
public final short nsUriIndex;
|
||||
public final short localNameIndex;
|
||||
|
||||
/**
|
||||
* Index of the Name for an EII or AII
|
||||
*/
|
||||
public final short qNameIndex;
|
||||
|
||||
/**
|
||||
* Specifies if the Name is associated with an EII or AII
|
||||
*/
|
||||
public final boolean isAttribute;
|
||||
|
||||
Name(int qNameIndex, int nsUriIndex, String nsUri, int localIndex, String localName, boolean isAttribute) {
|
||||
this.qNameIndex = (short)qNameIndex;
|
||||
this.nsUri = nsUri;
|
||||
this.localName = localName;
|
||||
this.nsUriIndex = (short)nsUriIndex;
|
||||
this.localNameIndex = (short)localIndex;
|
||||
this.isAttribute = isAttribute;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return '{'+nsUri+'}'+localName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link QName} from this.
|
||||
*/
|
||||
public QName toQName() {
|
||||
return new QName(nsUri,localName);
|
||||
}
|
||||
|
||||
public boolean equals( String nsUri, String localName ) {
|
||||
return localName.equals(this.localName) && nsUri.equals(this.nsUri);
|
||||
}
|
||||
|
||||
public int compareTo(Name that) {
|
||||
int r = this.nsUri.compareTo(that.nsUri);
|
||||
if(r!=0) return r;
|
||||
return this.localName.compareTo(that.localName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
/**
|
||||
* Creates {@link Name}s and assign index numbers to them.
|
||||
*
|
||||
* <p>
|
||||
* During this process, this class also finds out which namespace URIs
|
||||
* are statically known to be un-bindable as the default namespace.
|
||||
* Those are the namespace URIs that are used by attribute names.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@SuppressWarnings({"StringEquality"})
|
||||
public final class NameBuilder {
|
||||
private Map<String,Integer> uriIndexMap = new HashMap<String, Integer>();
|
||||
private Set<String> nonDefaultableNsUris = new HashSet<String>();
|
||||
private Map<String,Integer> localNameIndexMap = new HashMap<String, Integer>();
|
||||
private QNameMap<Integer> elementQNameIndexMap = new QNameMap<Integer>();
|
||||
private QNameMap<Integer> attributeQNameIndexMap = new QNameMap<Integer>();
|
||||
|
||||
public Name createElementName(QName name) {
|
||||
return createElementName(name.getNamespaceURI(),name.getLocalPart());
|
||||
}
|
||||
|
||||
public Name createElementName(String nsUri, String localName) {
|
||||
return createName(nsUri, localName, false, elementQNameIndexMap);
|
||||
}
|
||||
|
||||
public Name createAttributeName(QName name) {
|
||||
return createAttributeName(name.getNamespaceURI(),name.getLocalPart());
|
||||
}
|
||||
|
||||
public Name createAttributeName(String nsUri, String localName) {
|
||||
assert nsUri.intern()==nsUri;
|
||||
assert localName.intern()==localName;
|
||||
|
||||
if(nsUri.length()==0)
|
||||
return new Name(
|
||||
allocIndex(attributeQNameIndexMap,"",localName),
|
||||
-1,
|
||||
nsUri,
|
||||
allocIndex(localNameIndexMap,localName),
|
||||
localName,
|
||||
true);
|
||||
else {
|
||||
nonDefaultableNsUris.add(nsUri);
|
||||
return createName(nsUri,localName, true, attributeQNameIndexMap);
|
||||
}
|
||||
}
|
||||
|
||||
private Name createName(String nsUri, String localName, boolean isAttribute, QNameMap<Integer> map) {
|
||||
assert nsUri.intern()==nsUri;
|
||||
assert localName.intern()==localName;
|
||||
|
||||
return new Name(
|
||||
allocIndex(map,nsUri,localName),
|
||||
allocIndex(uriIndexMap,nsUri),
|
||||
nsUri,
|
||||
allocIndex(localNameIndexMap,localName),
|
||||
localName,
|
||||
isAttribute );
|
||||
}
|
||||
|
||||
private int allocIndex(Map<String,Integer> map, String str) {
|
||||
Integer i = map.get(str);
|
||||
if(i==null) {
|
||||
i = map.size();
|
||||
map.put(str,i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private int allocIndex(QNameMap<Integer> map, String nsUri, String localName) {
|
||||
Integer i = map.get(nsUri,localName);
|
||||
if(i==null) {
|
||||
i = map.size();
|
||||
map.put(nsUri,localName,i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps up everything and creates {@link NameList}.
|
||||
*/
|
||||
public NameList conclude() {
|
||||
boolean[] nsUriCannotBeDefaulted = new boolean[uriIndexMap.size()];
|
||||
for (Map.Entry<String,Integer> e : uriIndexMap.entrySet()) {
|
||||
nsUriCannotBeDefaulted[e.getValue()] = nonDefaultableNsUris.contains(e.getKey());
|
||||
}
|
||||
|
||||
NameList r = new NameList(
|
||||
list(uriIndexMap),
|
||||
nsUriCannotBeDefaulted,
|
||||
list(localNameIndexMap),
|
||||
elementQNameIndexMap.size(),
|
||||
attributeQNameIndexMap.size() );
|
||||
// delete them so that the create method can never be called again
|
||||
uriIndexMap = null;
|
||||
localNameIndexMap = null;
|
||||
return r;
|
||||
}
|
||||
|
||||
private String[] list(Map<String, Integer> map) {
|
||||
String[] r = new String[map.size()];
|
||||
for (Map.Entry<String, Integer> e : map.entrySet())
|
||||
r[e.getValue()] = e.getKey();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Namespace URIs and local names sorted by their indices.
|
||||
* Number of Names used for EIIs and AIIs
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class NameList {
|
||||
/**
|
||||
* Namespace URIs by their indices. No nulls in this array.
|
||||
* Read-only.
|
||||
*/
|
||||
public final String[] namespaceURIs;
|
||||
|
||||
/**
|
||||
* For each entry in {@link #namespaceURIs}, whether the namespace URI
|
||||
* can be declared as the default. If namespace URI is used in attributes,
|
||||
* we always need a prefix, so we can't.
|
||||
*
|
||||
* True if this URI has to have a prefix.
|
||||
*/
|
||||
public final boolean[] nsUriCannotBeDefaulted;
|
||||
|
||||
/**
|
||||
* Local names by their indices. No nulls in this array.
|
||||
* Read-only.
|
||||
*/
|
||||
public final String[] localNames;
|
||||
|
||||
/**
|
||||
* Number of Names for elements
|
||||
*/
|
||||
public final int numberOfElementNames;
|
||||
|
||||
/**
|
||||
* Number of Names for attributes
|
||||
*/
|
||||
public final int numberOfAttributeNames;
|
||||
|
||||
public NameList(String[] namespaceURIs, boolean[] nsUriCannotBeDefaulted, String[] localNames, int numberElementNames, int numberAttributeNames) {
|
||||
this.namespaceURIs = namespaceURIs;
|
||||
this.nsUriCannotBeDefaulted = nsUriCannotBeDefaulted;
|
||||
this.localNames = localNames;
|
||||
this.numberOfElementNames = numberElementNames;
|
||||
this.numberOfAttributeNames = numberAttributeNames;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.namespace.NamespaceContext;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
|
||||
/**
|
||||
* Maintains namespace<->prefix bindings.
|
||||
*
|
||||
* <p>
|
||||
* This interface extends {@link NamespaceContext} and provides
|
||||
* an additional functionality, which is necessary to declare
|
||||
* namespaced attributes on elements. The added method is for
|
||||
* self-consumption by the marshaller.
|
||||
*
|
||||
* This object is composed into a Serializer.
|
||||
*/
|
||||
public interface NamespaceContext2 extends NamespaceContext
|
||||
{
|
||||
/**
|
||||
* Declares a new namespace binding within the current context.
|
||||
*
|
||||
* <p>
|
||||
* The prefix is automatically assigned by MarshallingContext. If
|
||||
* a given namespace URI is already declared, nothing happens.
|
||||
*
|
||||
* <p>
|
||||
* It is <b>NOT</b> an error to declare the same namespace URI
|
||||
* more than once.
|
||||
*
|
||||
* <p>
|
||||
* For marshalling to work correctly, all namespace bindings
|
||||
* for an element must be declared between its startElement method and
|
||||
* its endAttributes event. Calling the same method with the same
|
||||
* parameter between the endAttributes and the endElement returns
|
||||
* the same prefix.
|
||||
*
|
||||
* @param requirePrefix
|
||||
* If this parameter is true, this method must assign a prefix
|
||||
* to this namespace, even if it's already bound to the default
|
||||
* namespace. IOW, this method will never return null if this
|
||||
* flag is true. This functionality is necessary to declare
|
||||
* namespace URI used for attribute names.
|
||||
* @param preferedPrefix
|
||||
* If the caller has any particular preference to the
|
||||
* prefix, pass that as a parameter. The callee will try
|
||||
* to honor it. Set null if there's no particular preference.
|
||||
*
|
||||
* @return
|
||||
* returns the assigned prefix. If the namespace is bound to
|
||||
* the default namespace, null is returned.
|
||||
*/
|
||||
String declareNamespace( String namespaceUri, String preferedPrefix, boolean requirePrefix );
|
||||
|
||||
/**
|
||||
* Forcibly make a namespace declaration in effect.
|
||||
*
|
||||
* If the (prefix,uri) binding is already in-scope, this method
|
||||
* simply returns the assigned prefix index. Otherwise a new
|
||||
* declaration will be put.
|
||||
*/
|
||||
int force(@NotNull String uri, @NotNull String prefix);
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class RuntimeUtil {
|
||||
/**
|
||||
* XmlAdapter for printing arbitrary object by using {@link Object#toString()}.
|
||||
*/
|
||||
public static final class ToStringAdapter extends XmlAdapter<String,Object> {
|
||||
public Object unmarshal(String s) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String marshal(Object o) {
|
||||
if(o==null) return null;
|
||||
return o.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map from {@link Class} objects representing primitive types
|
||||
* to {@link Class} objects representing their boxed types.
|
||||
* <p>
|
||||
* e.g., int -> Integer.
|
||||
*/
|
||||
public static final Map<Class,Class> boxToPrimitive;
|
||||
|
||||
/**
|
||||
* Reverse map of {@link #boxToPrimitive}.
|
||||
*/
|
||||
public static final Map<Class,Class> primitiveToBox;
|
||||
|
||||
static {
|
||||
Map<Class,Class> b = new HashMap<Class,Class>();
|
||||
b.put(Byte.TYPE,Byte.class);
|
||||
b.put(Short.TYPE,Short.class);
|
||||
b.put(Integer.TYPE,Integer.class);
|
||||
b.put(Long.TYPE,Long.class);
|
||||
b.put(Character.TYPE,Character.class);
|
||||
b.put(Boolean.TYPE,Boolean.class);
|
||||
b.put(Float.TYPE,Float.class);
|
||||
b.put(Double.TYPE,Double.class);
|
||||
b.put(Void.TYPE,Void.class);
|
||||
|
||||
primitiveToBox = Collections.unmodifiableMap(b);
|
||||
|
||||
Map<Class,Class> p = new HashMap<Class,Class>();
|
||||
for( Map.Entry<Class,Class> e : b.entrySet() )
|
||||
p.put(e.getValue(),e.getKey());
|
||||
|
||||
boxToPrimitive = Collections.unmodifiableMap(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a print conversion error while marshalling.
|
||||
*/
|
||||
/*
|
||||
public static void handlePrintConversionException(
|
||||
Object caller, Exception e, XMLSerializer serializer ) throws SAXException {
|
||||
|
||||
if( e instanceof SAXException )
|
||||
// assume this exception is not from application.
|
||||
// (e.g., when a marshaller aborts the processing, this exception
|
||||
// will be thrown)
|
||||
throw (SAXException)e;
|
||||
|
||||
ValidationEvent ve = new PrintConversionEventImpl(
|
||||
ValidationEvent.ERROR, e.getMessage(),
|
||||
new ValidationEventLocatorImpl(caller), e );
|
||||
serializer.reportError(ve);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reports that the type of an object in a property is unexpected.
|
||||
*/
|
||||
/*
|
||||
public static void handleTypeMismatchError( XMLSerializer serializer,
|
||||
Object parentObject, String fieldName, Object childObject ) throws SAXException {
|
||||
|
||||
ValidationEvent ve = new ValidationEventImpl(
|
||||
ValidationEvent.ERROR, // maybe it should be a fatal error.
|
||||
Messages.TYPE_MISMATCH.format(
|
||||
getTypeName(parentObject),
|
||||
fieldName,
|
||||
getTypeName(childObject) ),
|
||||
new ValidationEventLocatorExImpl(parentObject,fieldName) );
|
||||
|
||||
serializer.reportError(ve);
|
||||
}
|
||||
*/
|
||||
|
||||
private static String getTypeName( Object o ) {
|
||||
return o.getClass().getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.bind.annotation.XmlSchemaType;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Transducer} that signals the runtime that this datatype
|
||||
* is marshalled to a different XML Schema type.
|
||||
*
|
||||
* <p>
|
||||
* This transducer is used to implement the semantics of {@link XmlSchemaType} annotation.
|
||||
*
|
||||
*
|
||||
* @see XMLSerializer#schemaType
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class SchemaTypeTransducer<V> extends FilterTransducer<V> {
|
||||
private final QName schemaType;
|
||||
|
||||
public SchemaTypeTransducer(Transducer<V> core, QName schemaType) {
|
||||
super(core);
|
||||
this.schemaType = schemaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence print(V o) throws AccessorException {
|
||||
XMLSerializer w = XMLSerializer.getInstance();
|
||||
QName old = w.setSchemaType(schemaType);
|
||||
try {
|
||||
return core.print(o);
|
||||
} finally {
|
||||
w.setSchemaType(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeText(XMLSerializer w, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
QName old = w.setSchemaType(schemaType);
|
||||
try {
|
||||
core.writeText(w,o,fieldName);
|
||||
} finally {
|
||||
w.setSchemaType(old);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, V o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
|
||||
QName old = w.setSchemaType(schemaType);
|
||||
try {
|
||||
core.writeLeafElement(w, tagName, o, fieldName);
|
||||
} finally {
|
||||
w.setSchemaType(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.namespace.NamespaceContext;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
/**
|
||||
* Post-init action for {@link MarshallerImpl} that incorporate the in-scope namespace bindings
|
||||
* from a StAX writer.
|
||||
*
|
||||
* <p>
|
||||
* It's always used either with {@link XMLStreamWriter}, {@link XMLEventWriter}, or bare
|
||||
* {@link NamespaceContext},
|
||||
* but to reduce the # of classes in the runtime I wrote only one class that handles both.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class StAXPostInitAction implements Runnable {
|
||||
private final XMLStreamWriter xsw;
|
||||
private final XMLEventWriter xew;
|
||||
private final NamespaceContext nsc;
|
||||
private final XMLSerializer serializer;
|
||||
|
||||
StAXPostInitAction(XMLStreamWriter xsw,XMLSerializer serializer) {
|
||||
this.xsw = xsw;
|
||||
this.xew = null;
|
||||
this.nsc = null;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
StAXPostInitAction(XMLEventWriter xew,XMLSerializer serializer) {
|
||||
this.xsw = null;
|
||||
this.xew = xew;
|
||||
this.nsc = null;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
StAXPostInitAction(NamespaceContext nsc,XMLSerializer serializer) {
|
||||
this.xsw = null;
|
||||
this.xew = null;
|
||||
this.nsc = nsc;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
NamespaceContext ns = nsc;
|
||||
if(xsw!=null) ns = xsw.getNamespaceContext();
|
||||
if(xew!=null) ns = xew.getNamespaceContext();
|
||||
|
||||
// StAX javadoc isn't very clear on the behavior,
|
||||
// so work defensively in anticipation of broken implementations.
|
||||
if(ns==null)
|
||||
return;
|
||||
|
||||
// we can't enumerate all the in-scope namespace bindings in StAX,
|
||||
// so we only look for the known static namespace URIs.
|
||||
// this is less than ideal, but better than nothing.
|
||||
for( String nsUri : serializer.grammar.nameList.namespaceURIs ) {
|
||||
String p = ns.getPrefix(nsUri);
|
||||
if(p!=null)
|
||||
serializer.addInscopeBinding(nsUri,p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.activation.DataHandler;
|
||||
import javax.xml.bind.annotation.XmlAttachmentRef;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.bind.attachment.AttachmentUnmarshaller;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
|
||||
/**
|
||||
* {@link XmlAdapter} that binds the value as a SOAP attachment.
|
||||
*
|
||||
* <p>
|
||||
* On the user classes the SwA handling is done by using the {@link XmlAttachmentRef}
|
||||
* annotation, but internally we treat it as a {@link XmlJavaTypeAdapter} with this
|
||||
* adapter class. This is true with both XJC and the runtime.
|
||||
*
|
||||
* <p>
|
||||
* the model builder code and the code generator does the conversion and
|
||||
* shield the rest of the RI from this mess.
|
||||
* Also see @see <a href="http://webservices.xml.com/pub/a/ws/2003/09/16/wsbp.html?page=2">http://webservices.xml.com/pub/a/ws/2003/09/16/wsbp.html?page=2</a>.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class SwaRefAdapter extends XmlAdapter<String,DataHandler> {
|
||||
|
||||
public SwaRefAdapter() {
|
||||
}
|
||||
|
||||
public DataHandler unmarshal(String cid) {
|
||||
AttachmentUnmarshaller au = UnmarshallingContext.getInstance().parent.getAttachmentUnmarshaller();
|
||||
// TODO: error check
|
||||
return au.getAttachmentAsDataHandler(cid);
|
||||
}
|
||||
|
||||
public String marshal(DataHandler data) {
|
||||
if(data==null) return null;
|
||||
AttachmentMarshaller am = XMLSerializer.getInstance().attachmentMarshaller;
|
||||
// TODO: error check
|
||||
return am.addSwaRefAttachment(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.activation.DataHandler;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* Marker class used to identify swaref attachments and to generate appropriate annotations later.
|
||||
*/
|
||||
public class SwaRefAdapterMarker extends XmlAdapter<String, DataHandler> {
|
||||
|
||||
public DataHandler unmarshal(String v) throws Exception {
|
||||
throw new IllegalStateException("Not implemented");
|
||||
}
|
||||
|
||||
public String marshal(DataHandler v) throws Exception {
|
||||
throw new IllegalStateException("Not implemented");
|
||||
}
|
||||
}
|
||||
134
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Transducer.java
Normal file
134
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Transducer.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedTransducedAccessorFactory;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
||||
/**
|
||||
* Responsible for converting a Java object to a lexical representation
|
||||
* and vice versa.
|
||||
*
|
||||
* <p>
|
||||
* An implementation of this interface hides how this conversion happens.
|
||||
*
|
||||
* <p>
|
||||
* {@link Transducer}s are immutable.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
public interface Transducer<ValueT> {
|
||||
|
||||
/**
|
||||
* If this {@link Transducer} is the default transducer for the <code>ValueT</code>,
|
||||
* this method returns true.
|
||||
*
|
||||
* Used exclusively by {@link OptimizedTransducedAccessorFactory#get(RuntimePropertyInfo)}
|
||||
*/
|
||||
boolean isDefault();
|
||||
|
||||
/**
|
||||
* If true, this {@link Transducer} doesn't declare any namespace,
|
||||
* and therefore {@link #declareNamespace(Object, XMLSerializer)} is no-op.
|
||||
*
|
||||
* It also means that the {@link #parse(CharSequence)} method
|
||||
* won't use the context parameter.
|
||||
*/
|
||||
boolean useNamespace();
|
||||
|
||||
/**
|
||||
* Declares the namespace URIs used in the given value to {@code w}.
|
||||
*
|
||||
* @param o
|
||||
* never be null.
|
||||
* @param w
|
||||
* may be null if {@code !{@link #useNamespace()}}.
|
||||
*/
|
||||
void declareNamespace( ValueT o, XMLSerializer w ) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Converts the given value to its lexical representation.
|
||||
*
|
||||
* @param o
|
||||
* never be null.
|
||||
* @return
|
||||
* always non-null valid lexical representation.
|
||||
*/
|
||||
@NotNull CharSequence print(@NotNull ValueT o) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Converts the lexical representation to a value object.
|
||||
*
|
||||
* @param lexical
|
||||
* never be null.
|
||||
* @throws AccessorException
|
||||
* if the transducer is used to parse an user bean that uses {@link XmlValue},
|
||||
* then this exception may occur when it tries to set the leaf value to the bean.
|
||||
* @throws SAXException
|
||||
* if the lexical form is incorrect, the error should be reported
|
||||
* and SAXException may thrown (or it can return null to recover.)
|
||||
*/
|
||||
ValueT parse(CharSequence lexical) throws AccessorException, SAXException;
|
||||
|
||||
/**
|
||||
* Sends the result of the {@link #print(Object)} operation
|
||||
* to one of the {@link XMLSerializer#text(String, String)} method,
|
||||
* but with the best representation of the value, not necessarily String.
|
||||
*/
|
||||
void writeText(XMLSerializer w, ValueT o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException;
|
||||
|
||||
/**
|
||||
* Sends the result of the {@link #print(Object)} operation
|
||||
* to one of the {@link XMLSerializer#leafElement(Name, String, String)} method.
|
||||
* but with the best representation of the value, not necessarily String.
|
||||
*/
|
||||
void writeLeafElement(XMLSerializer w, Name tagName, @NotNull ValueT o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException;
|
||||
|
||||
/**
|
||||
* Transducers implicitly work against a single XML type,
|
||||
* but sometimes (most notably {@link XMLGregorianCalendar},
|
||||
* an instance may choose different XML types.
|
||||
*
|
||||
* @return
|
||||
* return non-null from this method allows transducers
|
||||
* to specify the type it wants to marshal to.
|
||||
* Most of the time this method returns null, in which case
|
||||
* the implicitly associated type will be used.
|
||||
*/
|
||||
QName getTypeName(@NotNull ValueT instance);
|
||||
}
|
||||
94
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Utils.java
Normal file
94
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/Utils.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, 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 com.sun.xml.internal.bind.v2.model.nav.Navigator;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utils class.
|
||||
*
|
||||
* WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
|
||||
*
|
||||
* Has *package private* access to avoid inappropriate usage.
|
||||
*/
|
||||
final class Utils {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Utils.class.getName());
|
||||
|
||||
/**
|
||||
* static ReflectionNavigator field to avoid usage of reflection every time we use it.
|
||||
*/
|
||||
static final Navigator<Type, Class, Field, Method> REFLECTION_NAVIGATOR;
|
||||
|
||||
static { // we statically initializing REFLECTION_NAVIGATOR property
|
||||
try {
|
||||
final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
|
||||
|
||||
// requires accessClassInPackage privilege
|
||||
final Method getInstance = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Method>() {
|
||||
@Override
|
||||
public Method run() {
|
||||
try {
|
||||
Method getInstance = refNav.getDeclaredMethod("getInstance");
|
||||
getInstance.setAccessible(true);
|
||||
return getInstance;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Can't find ReflectionNavigator class");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
|
||||
} catch (SecurityException e) {
|
||||
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor to avoid util class instantiating
|
||||
*/
|
||||
private Utils() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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 java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.helpers.ValidationEventImpl;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.FinalArrayList;
|
||||
import com.sun.xml.internal.bind.WhiteSpaceProcessor;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link JaxBeanInfo} implementation that binds T[] to a list of simple types.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ValueListBeanInfoImpl extends JaxBeanInfo {
|
||||
|
||||
private final Class itemType;
|
||||
private final Transducer xducer; // for items
|
||||
|
||||
public ValueListBeanInfoImpl(JAXBContextImpl owner, Class arrayType) throws JAXBException {
|
||||
super(owner, null, arrayType, false, true, false);
|
||||
this.itemType = jaxbType.getComponentType();
|
||||
this.xducer = owner.getBeanInfo(arrayType.getComponentType(),true).getTransducer();
|
||||
assert xducer!=null;
|
||||
}
|
||||
|
||||
private final Loader loader = new Loader(true) {
|
||||
@Override
|
||||
public void text(UnmarshallingContext.State state, CharSequence text) throws SAXException {
|
||||
List<Object> r = new FinalArrayList<Object>();
|
||||
|
||||
int idx = 0;
|
||||
int len = text.length();
|
||||
|
||||
while(true) {
|
||||
int p = idx;
|
||||
while( p<len && !WhiteSpaceProcessor.isWhiteSpace(text.charAt(p)) )
|
||||
p++;
|
||||
|
||||
CharSequence token = text.subSequence(idx,p);
|
||||
if (!token.equals(""))
|
||||
try {
|
||||
r.add(xducer.parse(token));
|
||||
} catch (AccessorException e) {
|
||||
handleGenericException(e,true);
|
||||
continue; // move on to next
|
||||
}
|
||||
|
||||
if(p==len) break; // done
|
||||
|
||||
while( p<len && WhiteSpaceProcessor.isWhiteSpace(text.charAt(p)) )
|
||||
p++;
|
||||
if(p==len) break; // done
|
||||
|
||||
idx = p;
|
||||
}
|
||||
|
||||
state.setTarget(toArray(r));
|
||||
}
|
||||
};
|
||||
|
||||
private Object toArray( List list ) {
|
||||
int len = list.size();
|
||||
Object array = Array.newInstance(itemType,len);
|
||||
for( int i=0; i<len; i++ )
|
||||
Array.set(array,i,list.get(i));
|
||||
return array;
|
||||
}
|
||||
|
||||
public void serializeBody(Object array, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
|
||||
int len = Array.getLength(array);
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Object item = Array.get(array,i);
|
||||
try {
|
||||
xducer.writeText(target,item,"arrayItem");
|
||||
} catch (AccessorException e) {
|
||||
target.reportError("arrayItem",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void serializeURIs(Object array, XMLSerializer target) throws SAXException {
|
||||
if(xducer.useNamespace()) {
|
||||
int len = Array.getLength(array);
|
||||
for( int i=0; i<len; i++ ) {
|
||||
Object item = Array.get(array,i);
|
||||
try {
|
||||
xducer.declareNamespace(item,target);
|
||||
} catch (AccessorException e) {
|
||||
target.reportError("arrayItem",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final String getElementNamespaceURI(Object array) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final String getElementLocalName(Object array) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final Object createInstance(UnmarshallingContext context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final boolean reset(Object array, UnmarshallingContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final String getId(Object array, XMLSerializer target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void serializeAttributes(Object array, XMLSerializer target) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public final void serializeRoot(Object array, XMLSerializer target) throws SAXException {
|
||||
target.reportError(
|
||||
new ValidationEventImpl(
|
||||
ValidationEvent.ERROR,
|
||||
Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(array.getClass().getName()),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
|
||||
public final Transducer getTransducer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
|
||||
// type substitution impossible
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
1077
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/XMLSerializer.java
Normal file
1077
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/runtime/XMLSerializer.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sun.xml.internal.bind.api.JAXBRIContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.istack.internal.FinalArrayList;
|
||||
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} that generates canonical XML.
|
||||
*
|
||||
* @see com.sun.xml.internal.bind.api.C14nSupport_ArchitectureDocument
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class C14nXmlOutput extends UTF8XmlOutput {
|
||||
public C14nXmlOutput(OutputStream out, Encoded[] localNames, boolean namedAttributesAreOrdered, CharacterEscapeHandler escapeHandler) {
|
||||
super(out, localNames, escapeHandler);
|
||||
this.namedAttributesAreOrdered = namedAttributesAreOrdered;
|
||||
|
||||
for( int i=0; i<staticAttributes.length; i++ )
|
||||
staticAttributes[i] = new StaticAttribute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hosts statically known attributes.
|
||||
*
|
||||
* {@link StaticAttribute} instances are reused.
|
||||
*/
|
||||
private StaticAttribute[] staticAttributes = new StaticAttribute[8];
|
||||
private int len = 0;
|
||||
|
||||
/**
|
||||
* Used to sort namespace declarations. Reused.
|
||||
*/
|
||||
private int[] nsBuf = new int[8];
|
||||
|
||||
/**
|
||||
* Hosts other attributes whose name are not statically known
|
||||
* (AKA attribute wildcard.)
|
||||
*
|
||||
* As long as this map is empty, there's no need for sorting.
|
||||
* see {@link com.sun.xml.internal.bind.api.C14nSupport_ArchitectureDocument} for more details.
|
||||
*/
|
||||
private final FinalArrayList<DynamicAttribute> otherAttributes = new FinalArrayList<DynamicAttribute>();
|
||||
|
||||
/**
|
||||
* True if {@link JAXBRIContext} is created with c14n support on,
|
||||
* in which case all named attributes are sorted by the marshaller
|
||||
* and we won't have to do it here.
|
||||
*/
|
||||
private final boolean namedAttributesAreOrdered;
|
||||
|
||||
final class StaticAttribute implements Comparable<StaticAttribute> {
|
||||
Name name;
|
||||
String value;
|
||||
|
||||
public void set(Name name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
void write() throws IOException {
|
||||
C14nXmlOutput.super.attribute(name,value);
|
||||
}
|
||||
|
||||
DynamicAttribute toDynamicAttribute() {
|
||||
int nsUriIndex = name.nsUriIndex;
|
||||
int prefix;
|
||||
if(nsUriIndex==-1)
|
||||
prefix = -1;
|
||||
else
|
||||
prefix = nsUriIndex2prefixIndex[nsUriIndex];
|
||||
return new DynamicAttribute(
|
||||
prefix, name.localName, value );
|
||||
}
|
||||
|
||||
public int compareTo(StaticAttribute that) {
|
||||
return this.name.compareTo(that.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class DynamicAttribute implements Comparable<DynamicAttribute> {
|
||||
final int prefix;
|
||||
final String localName;
|
||||
final String value;
|
||||
|
||||
public DynamicAttribute(int prefix, String localName, String value) {
|
||||
this.prefix = prefix;
|
||||
this.localName = localName;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private String getURI() {
|
||||
if(prefix==-1) return "";
|
||||
else return nsContext.getNamespaceURI(prefix);
|
||||
}
|
||||
|
||||
public int compareTo(DynamicAttribute that) {
|
||||
int r = this.getURI().compareTo(that.getURI());
|
||||
if(r!=0) return r;
|
||||
return this.localName.compareTo(that.localName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(Name name, String value) throws IOException {
|
||||
if(staticAttributes.length==len) {
|
||||
// reallocate
|
||||
int newLen = len*2;
|
||||
StaticAttribute[] newbuf = new StaticAttribute[newLen];
|
||||
System.arraycopy(staticAttributes,0,newbuf,0,len);
|
||||
for(int i=len;i<newLen;i++)
|
||||
staticAttributes[i] = new StaticAttribute();
|
||||
staticAttributes = newbuf;
|
||||
}
|
||||
|
||||
staticAttributes[len++].set(name,value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(int prefix, String localName, String value) throws IOException {
|
||||
otherAttributes.add(new DynamicAttribute(prefix,localName,value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endStartTag() throws IOException {
|
||||
if(otherAttributes.isEmpty()) {
|
||||
if(len!=0) {
|
||||
// sort is expensive even for size 0 array,
|
||||
// so it's worth checking len==0
|
||||
if(!namedAttributesAreOrdered)
|
||||
Arrays.sort(staticAttributes,0,len);
|
||||
// this is the common case
|
||||
for( int i=0; i<len; i++ )
|
||||
staticAttributes[i].write();
|
||||
len = 0;
|
||||
}
|
||||
} else {
|
||||
// this is the exceptional case
|
||||
|
||||
// sort all the attributes, not just the other attributes
|
||||
for( int i=0; i<len; i++ )
|
||||
otherAttributes.add(staticAttributes[i].toDynamicAttribute());
|
||||
len = 0;
|
||||
Collections.sort(otherAttributes);
|
||||
|
||||
// write them all
|
||||
int size = otherAttributes.size();
|
||||
for( int i=0; i<size; i++ ) {
|
||||
DynamicAttribute a = otherAttributes.get(i);
|
||||
super.attribute(a.prefix,a.localName,a.value);
|
||||
}
|
||||
otherAttributes.clear();
|
||||
}
|
||||
super.endStartTag();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write namespace declarations after sorting them.
|
||||
*/
|
||||
@Override
|
||||
protected void writeNsDecls(int base) throws IOException {
|
||||
int count = nsContext.getCurrent().count();
|
||||
|
||||
if(count==0)
|
||||
return; // quickly reject the most common case
|
||||
|
||||
if(count>nsBuf.length)
|
||||
nsBuf = new int[count];
|
||||
|
||||
for( int i=count-1; i>=0; i-- )
|
||||
nsBuf[i] = base+i;
|
||||
|
||||
// do a bubble sort. Hopefully # of ns decls are small enough to justify bubble sort.
|
||||
// faster algorithm is more compliated to implement
|
||||
for( int i=0; i<count; i++ ) {
|
||||
for( int j=i+1; j<count; j++ ) {
|
||||
String p = nsContext.getPrefix(nsBuf[i]);
|
||||
String q = nsContext.getPrefix(nsBuf[j]);
|
||||
if( p.compareTo(q) > 0 ) {
|
||||
// swap
|
||||
int t = nsBuf[j];
|
||||
nsBuf[j] = nsBuf[i];
|
||||
nsBuf[i] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write them out
|
||||
for( int i=0; i<count; i++ )
|
||||
writeNsDecl(nsBuf[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.AssociationMap;
|
||||
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} implementation that does associative marshalling to DOM.
|
||||
*
|
||||
* <p>
|
||||
* This is used for binder.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class DOMOutput extends SAXOutput {
|
||||
private final AssociationMap assoc;
|
||||
|
||||
public DOMOutput(Node node, AssociationMap assoc) {
|
||||
super(new SAX2DOMEx(node));
|
||||
this.assoc = assoc;
|
||||
assert assoc!=null;
|
||||
}
|
||||
|
||||
private SAX2DOMEx getBuilder() {
|
||||
return (SAX2DOMEx)out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endStartTag() throws SAXException {
|
||||
super.endStartTag();
|
||||
|
||||
Object op = nsContext.getCurrent().getOuterPeer();
|
||||
if(op!=null)
|
||||
assoc.addOuter( getBuilder().getCurrentElement(), op );
|
||||
|
||||
Object ip = nsContext.getCurrent().getInnerPeer();
|
||||
if(ip!=null)
|
||||
assoc.addInner( getBuilder().getCurrentElement(), ip );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Buffer for UTF-8 encoded string.
|
||||
*
|
||||
* See http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 for the UTF-8 encoding.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Encoded {
|
||||
public byte[] buf;
|
||||
|
||||
public int len;
|
||||
|
||||
public Encoded() {}
|
||||
|
||||
public Encoded(String text) {
|
||||
set(text);
|
||||
}
|
||||
|
||||
public void ensureSize(int size) {
|
||||
if(buf==null || buf.length<size)
|
||||
buf = new byte[size];
|
||||
}
|
||||
|
||||
public final void set( String text ) {
|
||||
int length = text.length();
|
||||
|
||||
ensureSize(length*3+1); // +1 for append
|
||||
|
||||
int ptr = 0;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
final char chr = text.charAt(i);
|
||||
if (chr > 0x7F) {
|
||||
if (chr > 0x7FF) {
|
||||
if(Character.MIN_HIGH_SURROGATE<=chr && chr<=Character.MAX_LOW_SURROGATE) {
|
||||
// surrogate
|
||||
int uc = (((chr & 0x3ff) << 10) | (text.charAt(++i) & 0x3ff)) + 0x10000;
|
||||
|
||||
buf[ptr++] = (byte)(0xF0 | ((uc >> 18)));
|
||||
buf[ptr++] = (byte)(0x80 | ((uc >> 12) & 0x3F));
|
||||
buf[ptr++] = (byte)(0x80 | ((uc >> 6) & 0x3F));
|
||||
buf[ptr++] = (byte)(0x80 + (uc & 0x3F));
|
||||
continue;
|
||||
}
|
||||
buf[ptr++] = (byte)(0xE0 + (chr >> 12));
|
||||
buf[ptr++] = (byte)(0x80 + ((chr >> 6) & 0x3F));
|
||||
} else {
|
||||
buf[ptr++] = (byte)(0xC0 + (chr >> 6));
|
||||
}
|
||||
buf[ptr++] = (byte)(0x80 + (chr & 0x3F));
|
||||
} else {
|
||||
buf[ptr++] = (byte)chr;
|
||||
}
|
||||
}
|
||||
|
||||
len = ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in the buffer by encoding the specified characters
|
||||
* while escaping characters like <
|
||||
*
|
||||
* @param isAttribute
|
||||
* if true, characters like \t, \r, and \n are also escaped.
|
||||
*/
|
||||
public final void setEscape(String text, boolean isAttribute) {
|
||||
int length = text.length();
|
||||
ensureSize(length*6+1); // in the worst case the text is like """""", so we need 6 bytes per char
|
||||
|
||||
int ptr = 0;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
final char chr = text.charAt(i);
|
||||
|
||||
int ptr1 = ptr;
|
||||
if (chr > 0x7F) {
|
||||
if (chr > 0x7FF) {
|
||||
if(Character.MIN_HIGH_SURROGATE<=chr && chr<=Character.MAX_LOW_SURROGATE) {
|
||||
// surrogate
|
||||
int uc = (((chr & 0x3ff) << 10) | (text.charAt(++i) & 0x3ff)) + 0x10000;
|
||||
|
||||
buf[ptr++] = (byte)(0xF0 | ((uc >> 18)));
|
||||
buf[ptr++] = (byte)(0x80 | ((uc >> 12) & 0x3F));
|
||||
buf[ptr++] = (byte)(0x80 | ((uc >> 6) & 0x3F));
|
||||
buf[ptr++] = (byte)(0x80 + (uc & 0x3F));
|
||||
continue;
|
||||
}
|
||||
buf[ptr1++] = (byte)(0xE0 + (chr >> 12));
|
||||
buf[ptr1++] = (byte)(0x80 + ((chr >> 6) & 0x3F));
|
||||
} else {
|
||||
buf[ptr1++] = (byte)(0xC0 + (chr >> 6));
|
||||
}
|
||||
buf[ptr1++] = (byte)(0x80 + (chr & 0x3F));
|
||||
} else {
|
||||
byte[] ent;
|
||||
|
||||
if((ent=attributeEntities[chr])!=null) {
|
||||
// the majority of the case is just printed as a char,
|
||||
// so it's very important to reject them as quickly as possible
|
||||
|
||||
// check again to see if this really needs to be escaped
|
||||
if(isAttribute || entities[chr]!=null)
|
||||
ptr1 = writeEntity(ent,ptr1);
|
||||
else
|
||||
buf[ptr1++] = (byte)chr;
|
||||
} else
|
||||
buf[ptr1++] = (byte)chr;
|
||||
}
|
||||
ptr = ptr1;
|
||||
}
|
||||
len = ptr;
|
||||
}
|
||||
|
||||
private int writeEntity( byte[] entity, int ptr ) {
|
||||
System.arraycopy(entity,0,buf,ptr,entity.length);
|
||||
return ptr+entity.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the encoded bytes to the given output stream.
|
||||
*/
|
||||
public final void write(UTF8XmlOutput out) throws IOException {
|
||||
out.write(buf,0,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a new character to the end of the buffer.
|
||||
* This assumes that you have enough space in the buffer.
|
||||
*/
|
||||
public void append(char b) {
|
||||
buf[len++] = (byte)b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocate the buffer to the exact size of the data
|
||||
* to reduce the memory footprint.
|
||||
*/
|
||||
public void compact() {
|
||||
byte[] b = new byte[len];
|
||||
System.arraycopy(buf,0,b,0,len);
|
||||
buf = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* UTF-8 encoded entities keyed by their character code.
|
||||
* e.g., entities['&'] == AMP_ENTITY.
|
||||
*
|
||||
* In attributes we need to encode more characters.
|
||||
*/
|
||||
private static final byte[][] entities = new byte[0x80][];
|
||||
private static final byte[][] attributeEntities = new byte[0x80][];
|
||||
|
||||
static {
|
||||
add('&',"&",false);
|
||||
add('<',"<",false);
|
||||
add('>',">",false);
|
||||
add('"',""",true);
|
||||
add('\t',"	",true);
|
||||
add('\r',"
",false);
|
||||
add('\n',"
",true);
|
||||
}
|
||||
|
||||
private static void add(char c, String s, boolean attOnly) {
|
||||
byte[] image = UTF8XmlOutput.toBytes(s);
|
||||
attributeEntities[c] = image;
|
||||
if(!attOnly)
|
||||
entities[c] = image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, 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.output;
|
||||
|
||||
import com.sun.xml.internal.bind.marshaller.NoEscapeHandler;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
|
||||
import com.sun.xml.internal.fastinfoset.EncodingConstants;
|
||||
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import com.sun.xml.internal.org.jvnet.fastinfoset.VocabularyApplicationData;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} for {@link LowLevelStAXDocumentSerializer}.
|
||||
* <p>
|
||||
* This class is responsible for managing the indexing of elements, attributes
|
||||
* and local names that are known to JAXB by way of the JAXBContext (generated
|
||||
* from JAXB beans or schema). The pre-encoded UTF-8 representations of known
|
||||
* local names are also utilized.
|
||||
* <p>
|
||||
* The lookup of elements, attributes and local names with respect to a context
|
||||
* is very efficient. It relies on an incrementing base line so that look up is
|
||||
* performed in O(1) time and only uses static memory. When the base line reaches
|
||||
* a point where integer overflow will occur the arrays and base line are reset
|
||||
* (such an event is rare and will have little impact on performance).
|
||||
* <p>
|
||||
* A weak map of JAXB contexts to optimized tables for attributes, elements and
|
||||
* local names is utilized and stored on the LowLevel StAX serializer. Thus,
|
||||
* optimized serializing can work other multiple serializing of JAXB beans using
|
||||
* the same LowLevel StAX serializer instance. This approach works best when JAXB
|
||||
* contexts are only created once per schema or JAXB beans (which is the recommended
|
||||
* practice as the creation JAXB contexts are expensive, they are thread safe and
|
||||
* can be reused).
|
||||
*
|
||||
* @author Paul.Sandoz@Sun.Com
|
||||
*/
|
||||
public final class FastInfosetStreamWriterOutput extends XMLStreamWriterOutput {
|
||||
private final StAXDocumentSerializer fiout;
|
||||
private final Encoded[] localNames;
|
||||
private final TablesPerJAXBContext tables;
|
||||
|
||||
/**
|
||||
* Holder for the optimzed element, attribute and
|
||||
* local name tables.
|
||||
*/
|
||||
final static class TablesPerJAXBContext {
|
||||
final int[] elementIndexes;
|
||||
final int[] elementIndexPrefixes;
|
||||
|
||||
final int[] attributeIndexes;
|
||||
final int[] localNameIndexes;
|
||||
|
||||
/**
|
||||
* The offset of the index
|
||||
*/
|
||||
int indexOffset;
|
||||
|
||||
/**
|
||||
* The the maximum known value of an index
|
||||
*/
|
||||
int maxIndex;
|
||||
|
||||
/**
|
||||
* True if the tables require clearing
|
||||
*/
|
||||
boolean requiresClear;
|
||||
|
||||
/**
|
||||
* Create a new set of tables for a JAXB context.
|
||||
* <p>
|
||||
* @param content the JAXB context.
|
||||
* @param initialIndexOffset the initial index offset to calculate
|
||||
* the maximum possible index
|
||||
*
|
||||
*/
|
||||
TablesPerJAXBContext(JAXBContextImpl context, int initialIndexOffset) {
|
||||
elementIndexes = new int[context.getNumberOfElementNames()];
|
||||
elementIndexPrefixes = new int[context.getNumberOfElementNames()];
|
||||
attributeIndexes = new int[context.getNumberOfAttributeNames()];
|
||||
localNameIndexes = new int[context.getNumberOfLocalNames()];
|
||||
|
||||
indexOffset = 1;
|
||||
maxIndex = initialIndexOffset + elementIndexes.length + attributeIndexes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require that tables are cleared.
|
||||
*/
|
||||
public void requireClearTables() {
|
||||
requiresClear = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear or reset the tables.
|
||||
* <p>
|
||||
* @param initialIndexOffset the initial index offset to calculate
|
||||
* the maximum possible index
|
||||
*/
|
||||
public void clearOrResetTables(int intialIndexOffset) {
|
||||
if (requiresClear) {
|
||||
requiresClear = false;
|
||||
|
||||
// Increment offset to new position
|
||||
indexOffset += maxIndex;
|
||||
// Reset the maximum known value of an index
|
||||
maxIndex = intialIndexOffset + elementIndexes.length + attributeIndexes.length;
|
||||
// Check if there is enough free space
|
||||
// If overflow
|
||||
if ((indexOffset + maxIndex) < 0) {
|
||||
clearAll();
|
||||
}
|
||||
} else {
|
||||
// Reset the maximum known value of an index
|
||||
maxIndex = intialIndexOffset + elementIndexes.length + attributeIndexes.length;
|
||||
// Check if there is enough free space
|
||||
// If overflow
|
||||
if ((indexOffset + maxIndex) < 0) {
|
||||
resetAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAll() {
|
||||
clear(elementIndexes);
|
||||
clear(attributeIndexes);
|
||||
clear(localNameIndexes);
|
||||
indexOffset = 1;
|
||||
}
|
||||
|
||||
private void clear(int[] array) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the maximum know index value
|
||||
* <p>
|
||||
* The indexes are preserved.
|
||||
*/
|
||||
public void incrementMaxIndexValue() {
|
||||
// Increment the maximum value of an index
|
||||
maxIndex++;
|
||||
// Check if there is enough free space
|
||||
// If overflow
|
||||
if ((indexOffset + maxIndex) < 0) {
|
||||
resetAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetAll() {
|
||||
clear(elementIndexes);
|
||||
clear(attributeIndexes);
|
||||
clear(localNameIndexes);
|
||||
indexOffset = 1;
|
||||
}
|
||||
|
||||
private void reset(int[] array) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] > indexOffset) {
|
||||
array[i] = array[i] - indexOffset + 1;
|
||||
} else {
|
||||
array[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Holder of JAXB contexts -> tables.
|
||||
* <p>
|
||||
* An instance will be registered with the
|
||||
* {@link LowLevelStAXDocumentSerializer}.
|
||||
*/
|
||||
final static class AppData implements VocabularyApplicationData {
|
||||
final Map<JAXBContext, TablesPerJAXBContext> contexts =
|
||||
new WeakHashMap<JAXBContext, TablesPerJAXBContext>();
|
||||
final Collection<TablesPerJAXBContext> collectionOfContexts = contexts.values();
|
||||
|
||||
/**
|
||||
* Clear all the tables.
|
||||
*/
|
||||
public void clear() {
|
||||
for(TablesPerJAXBContext c : collectionOfContexts)
|
||||
c.requireClearTables();
|
||||
}
|
||||
}
|
||||
|
||||
public FastInfosetStreamWriterOutput(StAXDocumentSerializer out,
|
||||
JAXBContextImpl context) {
|
||||
super(out, NoEscapeHandler.theInstance);
|
||||
|
||||
this.fiout = out;
|
||||
this.localNames = context.getUTF8NameTable();
|
||||
|
||||
final VocabularyApplicationData vocabAppData = fiout.getVocabularyApplicationData();
|
||||
AppData appData = null;
|
||||
if (vocabAppData == null || !(vocabAppData instanceof AppData)) {
|
||||
appData = new AppData();
|
||||
fiout.setVocabularyApplicationData(appData);
|
||||
} else {
|
||||
appData = (AppData)vocabAppData;
|
||||
}
|
||||
|
||||
final TablesPerJAXBContext tablesPerContext = appData.contexts.get(context);
|
||||
if (tablesPerContext != null) {
|
||||
tables = tablesPerContext;
|
||||
/**
|
||||
* Obtain the current local name index. Thus will be used to
|
||||
* calculate the maximum index value when serializing for this context
|
||||
*/
|
||||
tables.clearOrResetTables(out.getLocalNameIndex());
|
||||
} else {
|
||||
tables = new TablesPerJAXBContext(context, out.getLocalNameIndex());
|
||||
appData.contexts.put(context, tables);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment,
|
||||
int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext)
|
||||
throws IOException, SAXException, XMLStreamException {
|
||||
super.startDocument(serializer, fragment, nsUriIndex2prefixIndex, nsContext);
|
||||
|
||||
if (fragment)
|
||||
fiout.initiateLowLevelWriting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStartTag(Name name) throws IOException {
|
||||
fiout.writeLowLevelTerminationAndMark();
|
||||
|
||||
if (nsContext.getCurrent().count() == 0) {
|
||||
final int qNameIndex = tables.elementIndexes[name.qNameIndex] - tables.indexOffset;
|
||||
final int prefixIndex = nsUriIndex2prefixIndex[name.nsUriIndex];
|
||||
|
||||
if (qNameIndex >= 0 &&
|
||||
tables.elementIndexPrefixes[name.qNameIndex] == prefixIndex) {
|
||||
fiout.writeLowLevelStartElementIndexed(EncodingConstants.ELEMENT, qNameIndex);
|
||||
} else {
|
||||
tables.elementIndexes[name.qNameIndex] = fiout.getNextElementIndex() + tables.indexOffset;
|
||||
tables.elementIndexPrefixes[name.qNameIndex] = prefixIndex;
|
||||
writeLiteral(EncodingConstants.ELEMENT | EncodingConstants.ELEMENT_LITERAL_QNAME_FLAG,
|
||||
name,
|
||||
nsContext.getPrefix(prefixIndex),
|
||||
nsContext.getNamespaceURI(prefixIndex));
|
||||
}
|
||||
} else {
|
||||
beginStartTagWithNamespaces(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void beginStartTagWithNamespaces(Name name) throws IOException {
|
||||
final NamespaceContextImpl.Element nse = nsContext.getCurrent();
|
||||
|
||||
fiout.writeLowLevelStartNamespaces();
|
||||
for (int i = nse.count() - 1; i >= 0; i--) {
|
||||
final String uri = nse.getNsUri(i);
|
||||
if (uri.length() == 0 && nse.getBase() == 1)
|
||||
continue; // no point in definint xmlns='' on the root
|
||||
fiout.writeLowLevelNamespace(nse.getPrefix(i), uri);
|
||||
}
|
||||
fiout.writeLowLevelEndNamespaces();
|
||||
|
||||
final int qNameIndex = tables.elementIndexes[name.qNameIndex] - tables.indexOffset;
|
||||
final int prefixIndex = nsUriIndex2prefixIndex[name.nsUriIndex];
|
||||
|
||||
if (qNameIndex >= 0 &&
|
||||
tables.elementIndexPrefixes[name.qNameIndex] == prefixIndex) {
|
||||
fiout.writeLowLevelStartElementIndexed(0, qNameIndex);
|
||||
} else {
|
||||
tables.elementIndexes[name.qNameIndex] = fiout.getNextElementIndex() + tables.indexOffset;
|
||||
tables.elementIndexPrefixes[name.qNameIndex] = prefixIndex;
|
||||
writeLiteral(EncodingConstants.ELEMENT_LITERAL_QNAME_FLAG,
|
||||
name,
|
||||
nsContext.getPrefix(prefixIndex),
|
||||
nsContext.getNamespaceURI(prefixIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(Name name, String value) throws IOException {
|
||||
fiout.writeLowLevelStartAttributes();
|
||||
|
||||
final int qNameIndex = tables.attributeIndexes[name.qNameIndex] - tables.indexOffset;
|
||||
if (qNameIndex >= 0) {
|
||||
fiout.writeLowLevelAttributeIndexed(qNameIndex);
|
||||
} else {
|
||||
tables.attributeIndexes[name.qNameIndex] = fiout.getNextAttributeIndex() + tables.indexOffset;
|
||||
|
||||
final int namespaceURIId = name.nsUriIndex;
|
||||
if (namespaceURIId == -1) {
|
||||
writeLiteral(EncodingConstants.ATTRIBUTE_LITERAL_QNAME_FLAG,
|
||||
name,
|
||||
"",
|
||||
"");
|
||||
} else {
|
||||
final int prefix = nsUriIndex2prefixIndex[namespaceURIId];
|
||||
writeLiteral(EncodingConstants.ATTRIBUTE_LITERAL_QNAME_FLAG,
|
||||
name,
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix));
|
||||
}
|
||||
}
|
||||
|
||||
fiout.writeLowLevelAttributeValue(value);
|
||||
}
|
||||
|
||||
private void writeLiteral(int type, Name name, String prefix, String namespaceURI) throws IOException {
|
||||
final int localNameIndex = tables.localNameIndexes[name.localNameIndex] - tables.indexOffset;
|
||||
|
||||
if (localNameIndex < 0) {
|
||||
tables.localNameIndexes[name.localNameIndex] = fiout.getNextLocalNameIndex() + tables.indexOffset;
|
||||
|
||||
fiout.writeLowLevelStartNameLiteral(
|
||||
type,
|
||||
prefix,
|
||||
localNames[name.localNameIndex].buf,
|
||||
namespaceURI);
|
||||
} else {
|
||||
fiout.writeLowLevelStartNameLiteral(
|
||||
type,
|
||||
prefix,
|
||||
localNameIndex,
|
||||
namespaceURI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endStartTag() throws IOException {
|
||||
fiout.writeLowLevelEndStartElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(Name name) throws IOException {
|
||||
fiout.writeLowLevelEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(int prefix, String localName) throws IOException {
|
||||
fiout.writeLowLevelEndElement();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException {
|
||||
if (needsSeparatingWhitespace)
|
||||
fiout.writeLowLevelText(" ");
|
||||
|
||||
/*
|
||||
* Check if the CharSequence is from a base64Binary data type
|
||||
*/
|
||||
if (!(value instanceof Base64Data)) {
|
||||
final int len = value.length();
|
||||
if(len <buf.length) {
|
||||
value.writeTo(buf, 0);
|
||||
fiout.writeLowLevelText(buf, len);
|
||||
} else {
|
||||
fiout.writeLowLevelText(value.toString());
|
||||
}
|
||||
} else {
|
||||
final Base64Data dataValue = (Base64Data)value;
|
||||
// Write out the octets using the base64 encoding algorithm
|
||||
fiout.writeLowLevelOctets(dataValue.get(), dataValue.getDataLen());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void text(String value, boolean needsSeparatingWhitespace) throws IOException {
|
||||
if (needsSeparatingWhitespace)
|
||||
fiout.writeLowLevelText(" ");
|
||||
|
||||
fiout.writeLowLevelText(value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void beginStartTag(int prefix, String localName) throws IOException {
|
||||
fiout.writeLowLevelTerminationAndMark();
|
||||
|
||||
int type = EncodingConstants.ELEMENT;
|
||||
if (nsContext.getCurrent().count() > 0) {
|
||||
final NamespaceContextImpl.Element nse = nsContext.getCurrent();
|
||||
|
||||
fiout.writeLowLevelStartNamespaces();
|
||||
for (int i = nse.count() - 1; i >= 0; i--) {
|
||||
final String uri = nse.getNsUri(i);
|
||||
if (uri.length() == 0 && nse.getBase() == 1)
|
||||
continue; // no point in definint xmlns='' on the root
|
||||
fiout.writeLowLevelNamespace(nse.getPrefix(i), uri);
|
||||
}
|
||||
fiout.writeLowLevelEndNamespaces();
|
||||
|
||||
type= 0;
|
||||
}
|
||||
|
||||
final boolean isIndexed = fiout.writeLowLevelStartElement(
|
||||
type,
|
||||
nsContext.getPrefix(prefix),
|
||||
localName,
|
||||
nsContext.getNamespaceURI(prefix));
|
||||
|
||||
if (!isIndexed)
|
||||
tables.incrementMaxIndexValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(int prefix, String localName, String value) throws IOException {
|
||||
fiout.writeLowLevelStartAttributes();
|
||||
|
||||
boolean isIndexed;
|
||||
if (prefix == -1)
|
||||
isIndexed = fiout.writeLowLevelAttribute("", "", localName);
|
||||
else
|
||||
isIndexed = fiout.writeLowLevelAttribute(
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName);
|
||||
|
||||
if (!isIndexed)
|
||||
tables.incrementMaxIndexValue();
|
||||
|
||||
fiout.writeLowLevelAttributeValue(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} that writes to two {@link XmlOutput}s.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ForkXmlOutput extends XmlOutputAbstractImpl {
|
||||
private final XmlOutput lhs;
|
||||
private final XmlOutput rhs;
|
||||
|
||||
public ForkXmlOutput(XmlOutput lhs, XmlOutput rhs) {
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.startDocument(serializer, fragment, nsUriIndex2prefixIndex, nsContext);
|
||||
rhs.startDocument(serializer, fragment, nsUriIndex2prefixIndex, nsContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.endDocument(fragment);
|
||||
rhs.endDocument(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStartTag(Name name) throws IOException, XMLStreamException {
|
||||
lhs.beginStartTag(name);
|
||||
rhs.beginStartTag(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(Name name, String value) throws IOException, XMLStreamException {
|
||||
lhs.attribute(name, value);
|
||||
rhs.attribute(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(Name name) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.endTag(name);
|
||||
rhs.endTag(name);
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException {
|
||||
lhs.beginStartTag(prefix,localName);
|
||||
rhs.beginStartTag(prefix,localName);
|
||||
}
|
||||
|
||||
public void attribute(int prefix, String localName, String value) throws IOException, XMLStreamException {
|
||||
lhs.attribute(prefix,localName,value);
|
||||
rhs.attribute(prefix,localName,value);
|
||||
}
|
||||
|
||||
public void endStartTag() throws IOException, SAXException {
|
||||
lhs.endStartTag();
|
||||
rhs.endStartTag();
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.endTag(prefix,localName);
|
||||
rhs.endTag(prefix,localName);
|
||||
}
|
||||
|
||||
public void text(String value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.text(value,needsSeparatingWhitespace);
|
||||
rhs.text(value,needsSeparatingWhitespace);
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
lhs.text(value,needsSeparatingWhitespace);
|
||||
rhs.text(value,needsSeparatingWhitespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link UTF8XmlOutput} with indentation.
|
||||
*
|
||||
* TODO: not sure if it's a good idea to move the indenting functionality to another class.
|
||||
*
|
||||
* Doesn't have to be final, but it helps the JVM.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class IndentingUTF8XmlOutput extends UTF8XmlOutput {
|
||||
|
||||
/**
|
||||
* Null if the writer should perform no indentation.
|
||||
*
|
||||
* Otherwise this will keep the 8 copies of the string for indentation.
|
||||
* (so that we can write 8 indentation at once.)
|
||||
*/
|
||||
private final Encoded indent8;
|
||||
|
||||
/**
|
||||
* Length of one indentation.
|
||||
*/
|
||||
private final int unitLen;
|
||||
|
||||
private int depth = 0;
|
||||
|
||||
private boolean seenText = false;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param indentStr
|
||||
* set to null for no indentation and optimal performance.
|
||||
* otherwise the string is used for indentation.
|
||||
*/
|
||||
public IndentingUTF8XmlOutput(OutputStream out, String indentStr, Encoded[] localNames, CharacterEscapeHandler escapeHandler) {
|
||||
super(out, localNames, escapeHandler);
|
||||
|
||||
if(indentStr!=null) {
|
||||
Encoded e = new Encoded(indentStr);
|
||||
indent8 = new Encoded();
|
||||
indent8.ensureSize(e.len*8);
|
||||
unitLen = e.len;
|
||||
for( int i=0; i<8; i++ )
|
||||
System.arraycopy(e.buf, 0, indent8.buf, unitLen*i, unitLen);
|
||||
} else {
|
||||
this.indent8 = null;
|
||||
this.unitLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStartTag(int prefix, String localName) throws IOException {
|
||||
indentStartTag();
|
||||
super.beginStartTag(prefix, localName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStartTag(Name name) throws IOException {
|
||||
indentStartTag();
|
||||
super.beginStartTag(name);
|
||||
}
|
||||
|
||||
private void indentStartTag() throws IOException {
|
||||
closeStartTag();
|
||||
if(!seenText)
|
||||
printIndent();
|
||||
depth++;
|
||||
seenText = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(Name name) throws IOException {
|
||||
indentEndTag();
|
||||
super.endTag(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(int prefix, String localName) throws IOException {
|
||||
indentEndTag();
|
||||
super.endTag(prefix, localName);
|
||||
}
|
||||
|
||||
private void indentEndTag() throws IOException {
|
||||
depth--;
|
||||
if(!closeStartTagPending && !seenText)
|
||||
printIndent();
|
||||
seenText = false;
|
||||
}
|
||||
|
||||
private void printIndent() throws IOException {
|
||||
write('\n');
|
||||
int i = depth%8;
|
||||
|
||||
write( indent8.buf, 0, i*unitLen );
|
||||
|
||||
i>>=3; // really i /= 8;
|
||||
|
||||
for( ; i>0; i-- )
|
||||
indent8.write(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void text(String value, boolean needSP) throws IOException {
|
||||
seenText = true;
|
||||
super.text(value, needSP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void text(Pcdata value, boolean needSP) throws IOException {
|
||||
seenText = true;
|
||||
super.text(value, needSP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
write('\n');
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} decorator that supports MTOM.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class MTOMXmlOutput extends XmlOutputAbstractImpl {
|
||||
|
||||
private final XmlOutput next;
|
||||
|
||||
/**
|
||||
* Remembers the last namespace URI and local name so that we can pass them to
|
||||
* {@link AttachmentMarshaller}.
|
||||
*/
|
||||
private String nsUri,localName;
|
||||
|
||||
public MTOMXmlOutput(XmlOutput next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
super.startDocument(serializer,fragment,nsUriIndex2prefixIndex, nsContext);
|
||||
next.startDocument(serializer, fragment, nsUriIndex2prefixIndex, nsContext);
|
||||
}
|
||||
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
next.endDocument(fragment);
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
public void beginStartTag(Name name) throws IOException, XMLStreamException {
|
||||
next.beginStartTag(name);
|
||||
this.nsUri = name.nsUri;
|
||||
this.localName = name.localName;
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException {
|
||||
next.beginStartTag(prefix, localName);
|
||||
this.nsUri = nsContext.getNamespaceURI(prefix);
|
||||
this.localName = localName;
|
||||
}
|
||||
|
||||
public void attribute( Name name, String value ) throws IOException, XMLStreamException {
|
||||
next.attribute(name, value);
|
||||
}
|
||||
|
||||
public void attribute( int prefix, String localName, String value ) throws IOException, XMLStreamException {
|
||||
next.attribute(prefix, localName, value);
|
||||
}
|
||||
|
||||
public void endStartTag() throws IOException, SAXException {
|
||||
next.endStartTag();
|
||||
}
|
||||
|
||||
public void endTag(Name name) throws IOException, SAXException, XMLStreamException {
|
||||
next.endTag(name);
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException {
|
||||
next.endTag(prefix, localName);
|
||||
}
|
||||
|
||||
public void text( String value, boolean needsSeparatingWhitespace ) throws IOException, SAXException, XMLStreamException {
|
||||
next.text(value,needsSeparatingWhitespace);
|
||||
}
|
||||
|
||||
public void text( Pcdata value, boolean needsSeparatingWhitespace ) throws IOException, SAXException, XMLStreamException {
|
||||
if(value instanceof Base64Data && !serializer.getInlineBinaryFlag()) {
|
||||
Base64Data b64d = (Base64Data) value;
|
||||
String cid;
|
||||
if(b64d.hasData())
|
||||
cid = serializer.attachmentMarshaller.addMtomAttachment(
|
||||
b64d.get(),0,b64d.getDataLen(),b64d.getMimeType(),nsUri,localName);
|
||||
else
|
||||
cid = serializer.attachmentMarshaller.addMtomAttachment(
|
||||
b64d.getDataHandler(),nsUri,localName);
|
||||
|
||||
if(cid!=null) {
|
||||
nsContext.getCurrent().push();
|
||||
int prefix = nsContext.declareNsUri(WellKnownNamespace.XOP,"xop",false);
|
||||
beginStartTag(prefix,"Include");
|
||||
attribute(-1,"href",cid);
|
||||
endStartTag();
|
||||
endTag(prefix,"Include");
|
||||
nsContext.getCurrent().pop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
next.text(value, needsSeparatingWhitespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.NamespaceContext2;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Keeps track of in-scope namespace bindings for the marshaller.
|
||||
*
|
||||
* <p>
|
||||
* This class is also used to keep track of tag names for each element
|
||||
* for the marshaller (for the performance reason.)
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class NamespaceContextImpl implements NamespaceContext2 {
|
||||
private final XMLSerializer owner;
|
||||
|
||||
private String[] prefixes = new String[4];
|
||||
private String[] nsUris = new String[4];
|
||||
// /**
|
||||
// * True if the correponding namespace declaration is an authentic one that should be printed.
|
||||
// *
|
||||
// * False if it's a re-discovered in-scope namespace binding available at the ancestor elements
|
||||
// * outside this marhsalling. The false value is used to incorporate the in-scope namespace binding
|
||||
// * information from {@link #inscopeNamespaceContext}. When false, such a declaration does not need
|
||||
// * to be printed, as it's already available in ancestors.
|
||||
// */
|
||||
// private boolean[] visible = new boolean[4];
|
||||
//
|
||||
// /**
|
||||
// * {@link NamespaceContext} that informs this {@link XMLSerializer} about the
|
||||
// * in-scope namespace bindings of the ancestor elements outside this marshalling.
|
||||
// *
|
||||
// * <p>
|
||||
// * This is used when the marshaller is marshalling into a subtree that has ancestor
|
||||
// * elements created outside the JAXB marshaller.
|
||||
// *
|
||||
// * Its {@link NamespaceContext#getPrefix(String)} is used to discover in-scope namespace
|
||||
// * binding,
|
||||
// */
|
||||
// private final NamespaceContext inscopeNamespaceContext;
|
||||
|
||||
/**
|
||||
* Number of URIs declared. Identifies the valid portion of
|
||||
* the {@link #prefixes} and {@link #nsUris} arrays.
|
||||
*/
|
||||
private int size;
|
||||
|
||||
private Element current;
|
||||
|
||||
/**
|
||||
* This is the {@link Element} whose prev==null.
|
||||
* This element is used to hold the contextual namespace bindings
|
||||
* that are assumed to be outside of the document we are marshalling.
|
||||
* Specifically the xml prefix and any other user-specified bindings.
|
||||
*
|
||||
* @see NamespacePrefixMapper#getPreDeclaredNamespaceUris()
|
||||
*/
|
||||
private final Element top;
|
||||
|
||||
/**
|
||||
* Never null.
|
||||
*/
|
||||
private NamespacePrefixMapper prefixMapper = defaultNamespacePrefixMapper;
|
||||
|
||||
/**
|
||||
* True to allow new URIs to be declared. False otherwise.
|
||||
*/
|
||||
public boolean collectionMode;
|
||||
|
||||
|
||||
public NamespaceContextImpl(XMLSerializer owner) {
|
||||
this.owner = owner;
|
||||
|
||||
current = top = new Element(this,null);
|
||||
// register namespace URIs that are implicitly bound
|
||||
put(XMLConstants.XML_NS_URI,XMLConstants.XML_NS_PREFIX);
|
||||
}
|
||||
|
||||
public void setPrefixMapper( NamespacePrefixMapper mapper ) {
|
||||
if(mapper==null)
|
||||
mapper = defaultNamespacePrefixMapper;
|
||||
this.prefixMapper = mapper;
|
||||
}
|
||||
|
||||
public NamespacePrefixMapper getPrefixMapper() {
|
||||
return prefixMapper;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
current = top;
|
||||
size = 1;
|
||||
collectionMode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prefix index to the specified URI.
|
||||
* This method allocates a new URI if necessary.
|
||||
*/
|
||||
public int declareNsUri( String uri, String preferedPrefix, boolean requirePrefix ) {
|
||||
preferedPrefix = prefixMapper.getPreferredPrefix(uri,preferedPrefix,requirePrefix);
|
||||
|
||||
if(uri.length()==0) {
|
||||
for( int i=size-1; i>=0; i-- ) {
|
||||
if(nsUris[i].length()==0)
|
||||
return i; // already declared
|
||||
if(prefixes[i].length()==0) {
|
||||
// the default prefix is already taken.
|
||||
// move that URI to another prefix, then assign "" to the default prefix.
|
||||
assert current.defaultPrefixIndex==-1 && current.oldDefaultNamespaceUriIndex==-1;
|
||||
|
||||
String oldUri = nsUris[i];
|
||||
String[] knownURIs = owner.nameList.namespaceURIs;
|
||||
|
||||
if(current.baseIndex<=i) {
|
||||
// this default prefix is declared in this context. just reassign it
|
||||
|
||||
nsUris[i] = "";
|
||||
|
||||
int subst = put(oldUri,null);
|
||||
|
||||
// update uri->prefix table if necessary
|
||||
for( int j=knownURIs.length-1; j>=0; j-- ) {
|
||||
if(knownURIs[j].equals(oldUri)) {
|
||||
owner.knownUri2prefixIndexMap[j] = subst;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current.elementLocalName != null) {
|
||||
current.setTagName(subst, current.elementLocalName, current.getOuterPeer());
|
||||
}
|
||||
return i;
|
||||
} else {
|
||||
// first, if the previous URI assigned to "" is
|
||||
// a "known URI", remember what we've reallocated
|
||||
// so that we can fix it when this context pops.
|
||||
for( int j=knownURIs.length-1; j>=0; j-- ) {
|
||||
if(knownURIs[j].equals(oldUri)) {
|
||||
current.defaultPrefixIndex = i;
|
||||
current.oldDefaultNamespaceUriIndex = j;
|
||||
// assert commented out; too strict/not valid any more
|
||||
// assert owner.knownUri2prefixIndexMap[j]==current.defaultPrefixIndex;
|
||||
// update the table to point to the prefix we'll declare
|
||||
owner.knownUri2prefixIndexMap[j] = size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current.elementLocalName!=null) {
|
||||
current.setTagName(size, current.elementLocalName, current.getOuterPeer());
|
||||
}
|
||||
|
||||
put(nsUris[i],null);
|
||||
return put("", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "" isn't in use
|
||||
return put("", "");
|
||||
} else {
|
||||
// check for the existing binding
|
||||
for( int i=size-1; i>=0; i-- ) {
|
||||
String p = prefixes[i];
|
||||
if(nsUris[i].equals(uri)) {
|
||||
if (!requirePrefix || p.length()>0)
|
||||
return i;
|
||||
// declared but this URI is bound to empty. Look further
|
||||
}
|
||||
if(p.equals(preferedPrefix)) {
|
||||
// the suggested prefix is already taken. can't use it
|
||||
preferedPrefix = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(preferedPrefix==null && requirePrefix)
|
||||
// we know we can't bind to "", but we don't have any possible name at hand.
|
||||
// generate it here to avoid this namespace to be bound to "".
|
||||
preferedPrefix = makeUniquePrefix();
|
||||
|
||||
// haven't been declared. allocate a new one
|
||||
// if the preferred prefix is already in use, it should have been set to null by this time
|
||||
return put(uri, preferedPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
public int force(@NotNull String uri, @NotNull String prefix) {
|
||||
// check for the existing binding
|
||||
|
||||
for( int i=size-1; i>=0; i-- ) {
|
||||
if(prefixes[i].equals(prefix)) {
|
||||
if(nsUris[i].equals(uri))
|
||||
return i; // found duplicate
|
||||
else
|
||||
// the prefix is used for another namespace. we need to declare it
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return put(uri, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts this new binding into the declared prefixes list
|
||||
* without doing any duplicate check.
|
||||
*
|
||||
* This can be used to forcibly set namespace declarations.
|
||||
*
|
||||
* <p>
|
||||
* Most of the time {@link #declareNamespace(String, String, boolean)} shall be used.
|
||||
*
|
||||
* @return
|
||||
* the index of this new binding.
|
||||
*/
|
||||
public int put(@NotNull String uri, @Nullable String prefix) {
|
||||
if(size==nsUris.length) {
|
||||
// reallocate
|
||||
String[] u = new String[nsUris.length*2];
|
||||
String[] p = new String[prefixes.length*2];
|
||||
System.arraycopy(nsUris,0,u,0,nsUris.length);
|
||||
System.arraycopy(prefixes,0,p,0,prefixes.length);
|
||||
nsUris = u;
|
||||
prefixes = p;
|
||||
}
|
||||
if(prefix==null) {
|
||||
if(size==1)
|
||||
prefix = ""; // if this is the first user namespace URI we see, use "".
|
||||
else {
|
||||
// otherwise make up an unique name
|
||||
prefix = makeUniquePrefix();
|
||||
}
|
||||
}
|
||||
nsUris[size] = uri;
|
||||
prefixes[size] = prefix;
|
||||
|
||||
return size++;
|
||||
}
|
||||
|
||||
private String makeUniquePrefix() {
|
||||
String prefix;
|
||||
prefix = new StringBuilder(5).append("ns").append(size).toString();
|
||||
while(getNamespaceURI(prefix)!=null) {
|
||||
prefix += '_'; // under a rare circumstance there might be existing 'nsNNN', so rename them
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
public Element getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prefix index of the specified URI.
|
||||
* It is an error if the URI is not declared.
|
||||
*/
|
||||
public int getPrefixIndex( String uri ) {
|
||||
for( int i=size-1; i>=0; i-- ) {
|
||||
if(nsUris[i].equals(uri))
|
||||
return i;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix from a prefix index.
|
||||
*
|
||||
* The behavior is undefined if the index is out of range.
|
||||
*/
|
||||
public String getPrefix(int prefixIndex) {
|
||||
return prefixes[prefixIndex];
|
||||
}
|
||||
|
||||
public String getNamespaceURI(int prefixIndex) {
|
||||
return nsUris[prefixIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace URI that is bound to the specified prefix.
|
||||
*
|
||||
* @return null
|
||||
* if the prefix is unbound.
|
||||
*/
|
||||
public String getNamespaceURI(String prefix) {
|
||||
for( int i=size-1; i>=0; i-- )
|
||||
if(prefixes[i].equals(prefix))
|
||||
return nsUris[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prefix of the specified URI,
|
||||
* or null if none exists.
|
||||
*/
|
||||
public String getPrefix( String uri ) {
|
||||
if(collectionMode) {
|
||||
return declareNamespace(uri,null,false);
|
||||
} else {
|
||||
for( int i=size-1; i>=0; i-- )
|
||||
if(nsUris[i].equals(uri))
|
||||
return prefixes[i];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<String> getPrefixes(String uri) {
|
||||
String prefix = getPrefix(uri);
|
||||
if(prefix==null)
|
||||
return Collections.<String>emptySet().iterator();
|
||||
else
|
||||
return Collections.singleton(uri).iterator();
|
||||
}
|
||||
|
||||
public String declareNamespace(String namespaceUri, String preferedPrefix, boolean requirePrefix) {
|
||||
int idx = declareNsUri(namespaceUri,preferedPrefix,requirePrefix);
|
||||
return getPrefix(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of total bindings declared.
|
||||
*/
|
||||
public int count() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This model of namespace declarations maintain the following invariants.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If a non-empty prefix is declared, it will never be reassigned to different namespace URIs.
|
||||
* <li>
|
||||
*/
|
||||
public final class Element {
|
||||
|
||||
public final NamespaceContextImpl context;
|
||||
|
||||
/**
|
||||
* {@link Element}s form a doubly-linked list.
|
||||
*/
|
||||
private final Element prev;
|
||||
private Element next;
|
||||
|
||||
private int oldDefaultNamespaceUriIndex;
|
||||
private int defaultPrefixIndex;
|
||||
|
||||
|
||||
/**
|
||||
* The numbe of prefixes declared by ancestor {@link Element}s.
|
||||
*/
|
||||
private int baseIndex;
|
||||
|
||||
/**
|
||||
* The depth of the {@link Element}.
|
||||
*
|
||||
* This value is equivalent as the result of the following computation.
|
||||
*
|
||||
* <pre>
|
||||
* int depth() {
|
||||
* int i=-1;
|
||||
* for(Element e=this; e!=null;e=e.prev)
|
||||
* i++;
|
||||
* return i;
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
private final int depth;
|
||||
|
||||
|
||||
|
||||
private int elementNamePrefix;
|
||||
private String elementLocalName;
|
||||
|
||||
/**
|
||||
* Tag name of this element.
|
||||
* Either this field is used or the {@link #elementNamePrefix} and {@link #elementLocalName} pair.
|
||||
*/
|
||||
private Name elementName;
|
||||
|
||||
/**
|
||||
* Used for the binder. The JAXB object that corresponds to this element.
|
||||
*/
|
||||
private Object outerPeer;
|
||||
private Object innerPeer;
|
||||
|
||||
|
||||
private Element(NamespaceContextImpl context,Element prev) {
|
||||
this.context = context;
|
||||
this.prev = prev;
|
||||
this.depth = (prev==null) ? 0 : prev.depth+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this {@link Element} represents the root element that
|
||||
* we are marshalling.
|
||||
*/
|
||||
public boolean isRootElement() {
|
||||
return depth==1;
|
||||
}
|
||||
|
||||
public Element push() {
|
||||
if(next==null)
|
||||
next = new Element(context,this);
|
||||
next.onPushed();
|
||||
return next;
|
||||
}
|
||||
|
||||
public Element pop() {
|
||||
if(oldDefaultNamespaceUriIndex>=0) {
|
||||
// restore the old default namespace URI binding
|
||||
context.owner.knownUri2prefixIndexMap[oldDefaultNamespaceUriIndex] = defaultPrefixIndex;
|
||||
}
|
||||
context.size = baseIndex;
|
||||
context.current = prev;
|
||||
// release references to user objects
|
||||
outerPeer = innerPeer = null;
|
||||
return prev;
|
||||
}
|
||||
|
||||
private void onPushed() {
|
||||
oldDefaultNamespaceUriIndex = defaultPrefixIndex = -1;
|
||||
baseIndex = context.size;
|
||||
context.current = this;
|
||||
}
|
||||
|
||||
public void setTagName( int prefix, String localName, Object outerPeer ) {
|
||||
assert localName!=null;
|
||||
this.elementNamePrefix = prefix;
|
||||
this.elementLocalName = localName;
|
||||
this.elementName = null;
|
||||
this.outerPeer = outerPeer;
|
||||
}
|
||||
|
||||
public void setTagName( Name tagName, Object outerPeer ) {
|
||||
assert tagName!=null;
|
||||
this.elementName = tagName;
|
||||
this.outerPeer = outerPeer;
|
||||
}
|
||||
|
||||
public void startElement(XmlOutput out, Object innerPeer) throws IOException, XMLStreamException {
|
||||
this.innerPeer = innerPeer;
|
||||
if(elementName!=null) {
|
||||
out.beginStartTag(elementName);
|
||||
} else {
|
||||
out.beginStartTag(elementNamePrefix,elementLocalName);
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(XmlOutput out) throws IOException, SAXException, XMLStreamException {
|
||||
if(elementName!=null) {
|
||||
out.endTag(elementName);
|
||||
elementName = null;
|
||||
} else {
|
||||
out.endTag(elementNamePrefix,elementLocalName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of bindings declared on this element.
|
||||
*/
|
||||
public final int count() {
|
||||
return context.size-baseIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix declared in this context.
|
||||
*
|
||||
* @param idx
|
||||
* between 0 and {@link #count()}
|
||||
*/
|
||||
public final String getPrefix(int idx) {
|
||||
return context.prefixes[baseIndex+idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace URI declared in this context.
|
||||
*
|
||||
* @param idx
|
||||
* between 0 and {@link #count()}
|
||||
*/
|
||||
public final String getNsUri(int idx) {
|
||||
return context.nsUris[baseIndex+idx];
|
||||
}
|
||||
|
||||
public int getBase() {
|
||||
return baseIndex;
|
||||
}
|
||||
|
||||
public Object getOuterPeer() {
|
||||
return outerPeer;
|
||||
}
|
||||
|
||||
public Object getInnerPeer() {
|
||||
return innerPeer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parent {@link Element}.
|
||||
*/
|
||||
public Element getParent() {
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default {@link NamespacePrefixMapper} implementation used when
|
||||
* it is not specified by the user.
|
||||
*/
|
||||
private static final NamespacePrefixMapper defaultNamespacePrefixMapper = new NamespacePrefixMapper() {
|
||||
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
|
||||
if( namespaceUri.equals(WellKnownNamespace.XML_SCHEMA_INSTANCE) )
|
||||
return "xsi";
|
||||
if( namespaceUri.equals(WellKnownNamespace.XML_SCHEMA) )
|
||||
return "xs";
|
||||
if( namespaceUri.equals(WellKnownNamespace.XML_MIME_URI) )
|
||||
return "xmime";
|
||||
return suggestion;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Text data in XML.
|
||||
*
|
||||
* <p>
|
||||
* This class is used inside the marshaller/unmarshaller to
|
||||
* send/receive text data.
|
||||
*
|
||||
* <p>
|
||||
* On top of {@link CharSequence}, this class has an
|
||||
* ability to write itself to the {@link XmlOutput}. This allows
|
||||
* the implementation to choose the most efficient way possible
|
||||
* when writing to XML (for example, it can skip the escaping
|
||||
* of buffer copying.)
|
||||
*
|
||||
* TODO: visitor pattern support?
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class Pcdata implements CharSequence {
|
||||
|
||||
/**
|
||||
* Writes itself to {@link UTF8XmlOutput}.
|
||||
*
|
||||
* <p>
|
||||
* This is the most performance critical path for the marshaller,
|
||||
* so it warrants its own method.
|
||||
*/
|
||||
public abstract void writeTo(UTF8XmlOutput output) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes itself to the character array.
|
||||
*
|
||||
* <p>
|
||||
* This method is used by most other {@link XmlOutput}.
|
||||
* The default implementation involves in one extra char[] copying.
|
||||
*
|
||||
* <p>
|
||||
* The caller must provide a big enough buffer that can hold
|
||||
* enough characters returned by the {@link #length()} method.
|
||||
*/
|
||||
public void writeTo(char[] buf, int start) {
|
||||
toString().getChars(0,length(),buf,start);
|
||||
}
|
||||
|
||||
public abstract String toString();
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.util.AttributesImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} implementation that writes to SAX {@link ContentHandler}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class SAXOutput extends XmlOutputAbstractImpl {
|
||||
protected final ContentHandler out;
|
||||
|
||||
public SAXOutput(ContentHandler out) {
|
||||
this.out = out;
|
||||
out.setDocumentLocator(new LocatorImpl());
|
||||
}
|
||||
|
||||
private String elementNsUri,elementLocalName,elementQName;
|
||||
|
||||
private char[] buf = new char[256];
|
||||
|
||||
private final AttributesImpl atts = new AttributesImpl();
|
||||
|
||||
|
||||
// not called if we are generating fragments
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws SAXException, IOException, XMLStreamException {
|
||||
super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext);
|
||||
if(!fragment)
|
||||
out.startDocument();
|
||||
}
|
||||
|
||||
public void endDocument(boolean fragment) throws SAXException, IOException, XMLStreamException {
|
||||
if(!fragment)
|
||||
out.endDocument();
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) {
|
||||
elementNsUri = nsContext.getNamespaceURI(prefix);
|
||||
elementLocalName = localName;
|
||||
elementQName = getQName(prefix,localName);
|
||||
atts.clear();
|
||||
}
|
||||
|
||||
public void attribute(int prefix, String localName, String value) {
|
||||
String qname;
|
||||
String nsUri;
|
||||
if(prefix==-1) {
|
||||
nsUri = "";
|
||||
qname = localName;
|
||||
} else {
|
||||
nsUri = nsContext.getNamespaceURI(prefix);
|
||||
String p = nsContext.getPrefix(prefix);
|
||||
if(p.length()==0)
|
||||
// this is more likely a bug in the application code (NamespacePrefixMapper implementation)
|
||||
// this only happens when it tries to assign "" prefix to a non-"" URI,
|
||||
// which is by itself violation of namespace rec. But let's just be safe.
|
||||
// See http://forums.java.net/jive/thread.jspa?messageID=212598#212598
|
||||
qname = localName;
|
||||
else
|
||||
qname = p +':'+localName;
|
||||
}
|
||||
atts.addAttribute( nsUri, localName, qname, "CDATA", value );
|
||||
}
|
||||
|
||||
public void endStartTag() throws SAXException {
|
||||
NamespaceContextImpl.Element ns = nsContext.getCurrent();
|
||||
if(ns!=null) {
|
||||
int sz = ns.count();
|
||||
for( int i=0; i<sz; i++ ) {
|
||||
String p = ns.getPrefix(i);
|
||||
String uri = ns.getNsUri(i);
|
||||
if(uri.length()==0 && ns.getBase()==1)
|
||||
continue; // no point in defining xmlns='' on the root
|
||||
out.startPrefixMapping(p,uri);
|
||||
}
|
||||
}
|
||||
out.startElement(elementNsUri,elementLocalName,elementQName,atts);
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws SAXException {
|
||||
out.endElement(
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName,
|
||||
getQName(prefix, localName)
|
||||
);
|
||||
|
||||
NamespaceContextImpl.Element ns = nsContext.getCurrent();
|
||||
if(ns!=null) {
|
||||
int sz = ns.count();
|
||||
for( int i=sz-1; i>=0; i-- ) {
|
||||
String p = ns.getPrefix(i);
|
||||
String uri = ns.getNsUri(i);
|
||||
if(uri.length()==0 && ns.getBase()==1)
|
||||
continue; // no point in definint xmlns='' on the root
|
||||
out.endPrefixMapping(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getQName(int prefix, String localName) {
|
||||
String qname;
|
||||
String p = nsContext.getPrefix(prefix);
|
||||
if(p.length()==0)
|
||||
qname = localName;
|
||||
else
|
||||
qname = p+':'+localName;
|
||||
return qname;
|
||||
}
|
||||
|
||||
public void text(String value, boolean needsSP) throws IOException, SAXException, XMLStreamException {
|
||||
int vlen = value.length();
|
||||
if(buf.length<=vlen) {
|
||||
buf = new char[Math.max(buf.length*2,vlen+1)];
|
||||
}
|
||||
if(needsSP) {
|
||||
value.getChars(0,vlen,buf,1);
|
||||
buf[0] = ' ';
|
||||
} else {
|
||||
value.getChars(0,vlen,buf,0);
|
||||
}
|
||||
out.characters(buf,0,vlen+(needsSP?1:0));
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needsSP) throws IOException, SAXException, XMLStreamException {
|
||||
int vlen = value.length();
|
||||
if(buf.length<=vlen) {
|
||||
buf = new char[Math.max(buf.length*2,vlen+1)];
|
||||
}
|
||||
if(needsSP) {
|
||||
value.writeTo(buf,1);
|
||||
buf[0] = ' ';
|
||||
} else {
|
||||
value.writeTo(buf,0);
|
||||
}
|
||||
out.characters(buf,0,vlen+(needsSP?1:0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
/**
|
||||
* Class defined for safe calls of getClassLoader methods of any kind (context/system/class
|
||||
* classloader. This MUST be package private and defined in every package which
|
||||
* uses such invocations.
|
||||
* @author snajper
|
||||
*/
|
||||
class SecureLoader {
|
||||
|
||||
static ClassLoader getContextClassLoader() {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
} else {
|
||||
return (ClassLoader) java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public java.lang.Object run() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static ClassLoader getClassClassLoader(final Class c) {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return c.getClassLoader();
|
||||
} else {
|
||||
return (ClassLoader) java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public java.lang.Object run() {
|
||||
return c.getClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static ClassLoader getSystemClassLoader() {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
} else {
|
||||
return (ClassLoader) java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public java.lang.Object run() {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, 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.output;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.marshaller.NoEscapeHandler;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
|
||||
|
||||
import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} for {@link XMLStreamWriterEx}.
|
||||
*
|
||||
* @author Paul Sandoz.
|
||||
*/
|
||||
public final class StAXExStreamWriterOutput extends XMLStreamWriterOutput {
|
||||
private final XMLStreamWriterEx out;
|
||||
|
||||
public StAXExStreamWriterOutput(XMLStreamWriterEx out) {
|
||||
super(out, NoEscapeHandler.theInstance);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needsSeparatingWhitespace) throws XMLStreamException {
|
||||
if(needsSeparatingWhitespace) {
|
||||
out.writeCharacters(" ");
|
||||
}
|
||||
|
||||
if (!(value instanceof Base64Data)) {
|
||||
out.writeCharacters(value.toString());
|
||||
} else {
|
||||
Base64Data v = (Base64Data)value;
|
||||
out.writeBinary(v.getDataHandler());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.DatatypeConverterImpl;
|
||||
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.MarshallerImpl;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} implementation specialized for UTF-8.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Paul Sandoz
|
||||
*/
|
||||
public class UTF8XmlOutput extends XmlOutputAbstractImpl {
|
||||
protected final OutputStream out;
|
||||
|
||||
/** prefixes encoded. */
|
||||
private Encoded[] prefixes = new Encoded[8];
|
||||
|
||||
/**
|
||||
* Of the {@link #prefixes}, number of filled entries.
|
||||
* This is almost the same as {@link NamespaceContextImpl#count()},
|
||||
* except that it allows us to handle contextual in-scope namespace bindings correctly.
|
||||
*/
|
||||
private int prefixCount;
|
||||
|
||||
/** local names encoded in UTF-8. All entries are pre-filled. */
|
||||
private final Encoded[] localNames;
|
||||
|
||||
/** Temporary buffer used to encode text. */
|
||||
/*
|
||||
* TODO
|
||||
* The textBuffer could write directly to the _octetBuffer
|
||||
* when encoding a string if Encoder is modified.
|
||||
* This will avoid an additional memory copy.
|
||||
*/
|
||||
private final Encoded textBuffer = new Encoded();
|
||||
|
||||
/** Buffer of octets for writing. */
|
||||
// TODO: Obtain buffer size from property on the JAXB context
|
||||
protected final byte[] octetBuffer = new byte[1024];
|
||||
|
||||
/** Index in buffer to write to. */
|
||||
protected int octetBufferIndex;
|
||||
|
||||
/**
|
||||
* Set to true to indicate that we need to write '>'
|
||||
* to close a start tag. Deferring the write of this char
|
||||
* allows us to write "/>" for empty elements.
|
||||
*/
|
||||
protected boolean closeStartTagPending = false;
|
||||
|
||||
/**
|
||||
* @see MarshallerImpl#header
|
||||
*/
|
||||
private String header;
|
||||
|
||||
private CharacterEscapeHandler escapeHandler = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param localNames
|
||||
* local names encoded in UTF-8.
|
||||
*/
|
||||
public UTF8XmlOutput(OutputStream out, Encoded[] localNames, CharacterEscapeHandler escapeHandler) {
|
||||
this.out = out;
|
||||
this.localNames = localNames;
|
||||
for( int i=0; i<prefixes.length; i++ )
|
||||
prefixes[i] = new Encoded();
|
||||
this.escapeHandler = escapeHandler;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext);
|
||||
|
||||
octetBufferIndex = 0;
|
||||
if(!fragment) {
|
||||
write(XML_DECL);
|
||||
}
|
||||
if(header!=null) {
|
||||
textBuffer.set(header);
|
||||
textBuffer.write(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
flushBuffer();
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes '>' to close the start tag, if necessary.
|
||||
*/
|
||||
protected final void closeStartTag() throws IOException {
|
||||
if(closeStartTagPending) {
|
||||
write('>');
|
||||
closeStartTagPending = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException {
|
||||
closeStartTag();
|
||||
int base= pushNsDecls();
|
||||
write('<');
|
||||
writeName(prefix,localName);
|
||||
writeNsDecls(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStartTag(Name name) throws IOException {
|
||||
closeStartTag();
|
||||
int base = pushNsDecls();
|
||||
write('<');
|
||||
writeName(name);
|
||||
writeNsDecls(base);
|
||||
}
|
||||
|
||||
private int pushNsDecls() {
|
||||
int total = nsContext.count();
|
||||
NamespaceContextImpl.Element ns = nsContext.getCurrent();
|
||||
|
||||
if(total > prefixes.length) {
|
||||
// reallocate
|
||||
int m = Math.max(total,prefixes.length*2);
|
||||
Encoded[] buf = new Encoded[m];
|
||||
System.arraycopy(prefixes,0,buf,0,prefixes.length);
|
||||
for( int i=prefixes.length; i<buf.length; i++ )
|
||||
buf[i] = new Encoded();
|
||||
prefixes = buf;
|
||||
}
|
||||
|
||||
int base = Math.min(prefixCount,ns.getBase());
|
||||
int size = nsContext.count();
|
||||
for( int i=base; i<size; i++ ) {
|
||||
String p = nsContext.getPrefix(i);
|
||||
|
||||
Encoded e = prefixes[i];
|
||||
|
||||
if(p.length()==0) {
|
||||
e.buf = EMPTY_BYTE_ARRAY;
|
||||
e.len = 0;
|
||||
} else {
|
||||
e.set(p);
|
||||
e.append(':');
|
||||
}
|
||||
}
|
||||
prefixCount = size;
|
||||
return base;
|
||||
}
|
||||
|
||||
protected void writeNsDecls(int base) throws IOException {
|
||||
NamespaceContextImpl.Element ns = nsContext.getCurrent();
|
||||
int size = nsContext.count();
|
||||
|
||||
for( int i=ns.getBase(); i<size; i++ )
|
||||
writeNsDecl(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a single namespace declaration for the specified prefix.
|
||||
*/
|
||||
protected final void writeNsDecl(int prefixIndex) throws IOException {
|
||||
String p = nsContext.getPrefix(prefixIndex);
|
||||
|
||||
if(p.length()==0) {
|
||||
if(nsContext.getCurrent().isRootElement()
|
||||
&& nsContext.getNamespaceURI(prefixIndex).length()==0)
|
||||
return; // no point in declaring xmlns="" on the root element
|
||||
write(XMLNS_EQUALS);
|
||||
} else {
|
||||
Encoded e = prefixes[prefixIndex];
|
||||
write(XMLNS_COLON);
|
||||
write(e.buf,0,e.len-1); // skip the trailing ':'
|
||||
write(EQUALS);
|
||||
}
|
||||
doText(nsContext.getNamespaceURI(prefixIndex),true);
|
||||
write('\"');
|
||||
}
|
||||
|
||||
private void writePrefix(int prefix) throws IOException {
|
||||
prefixes[prefix].write(this);
|
||||
}
|
||||
|
||||
private void writeName(Name name) throws IOException {
|
||||
writePrefix(nsUriIndex2prefixIndex[name.nsUriIndex]);
|
||||
localNames[name.localNameIndex].write(this);
|
||||
}
|
||||
|
||||
private void writeName(int prefix, String localName) throws IOException {
|
||||
writePrefix(prefix);
|
||||
textBuffer.set(localName);
|
||||
textBuffer.write(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attribute(Name name, String value) throws IOException {
|
||||
write(' ');
|
||||
if(name.nsUriIndex==-1) {
|
||||
localNames[name.localNameIndex].write(this);
|
||||
} else
|
||||
writeName(name);
|
||||
write(EQUALS);
|
||||
doText(value,true);
|
||||
write('\"');
|
||||
}
|
||||
|
||||
public void attribute(int prefix, String localName, String value) throws IOException {
|
||||
write(' ');
|
||||
if(prefix==-1) {
|
||||
textBuffer.set(localName);
|
||||
textBuffer.write(this);
|
||||
} else
|
||||
writeName(prefix,localName);
|
||||
write(EQUALS);
|
||||
doText(value,true);
|
||||
write('\"');
|
||||
}
|
||||
|
||||
public void endStartTag() throws IOException {
|
||||
closeStartTagPending = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTag(Name name) throws IOException {
|
||||
if(closeStartTagPending) {
|
||||
write(EMPTY_TAG);
|
||||
closeStartTagPending = false;
|
||||
} else {
|
||||
write(CLOSE_TAG);
|
||||
writeName(name);
|
||||
write('>');
|
||||
}
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException {
|
||||
if(closeStartTagPending) {
|
||||
write(EMPTY_TAG);
|
||||
closeStartTagPending = false;
|
||||
} else {
|
||||
write(CLOSE_TAG);
|
||||
writeName(prefix,localName);
|
||||
write('>');
|
||||
}
|
||||
}
|
||||
|
||||
public void text(String value, boolean needSP) throws IOException {
|
||||
closeStartTag();
|
||||
if(needSP)
|
||||
write(' ');
|
||||
doText(value,false);
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needSP) throws IOException {
|
||||
closeStartTag();
|
||||
if(needSP)
|
||||
write(' ');
|
||||
value.writeTo(this);
|
||||
}
|
||||
|
||||
private void doText(String value,boolean isAttribute) throws IOException {
|
||||
if (escapeHandler != null) {
|
||||
StringWriter sw = new StringWriter();
|
||||
escapeHandler.escape(value.toCharArray(), 0, value.length(), isAttribute, sw);
|
||||
textBuffer.set(sw.toString());
|
||||
} else {
|
||||
textBuffer.setEscape(value, isAttribute);
|
||||
}
|
||||
textBuffer.write(this);
|
||||
}
|
||||
|
||||
public final void text(int value) throws IOException {
|
||||
closeStartTag();
|
||||
/*
|
||||
* TODO
|
||||
* Change to use the octet buffer directly
|
||||
*/
|
||||
|
||||
// max is -2147483648 and 11 digits
|
||||
boolean minus = (value<0);
|
||||
textBuffer.ensureSize(11);
|
||||
byte[] buf = textBuffer.buf;
|
||||
int idx = 11;
|
||||
|
||||
do {
|
||||
int r = value%10;
|
||||
if(r<0) r = -r;
|
||||
buf[--idx] = (byte)('0'|r); // really measn 0x30+r but 0<=r<10, so bit-OR would do.
|
||||
value /= 10;
|
||||
} while(value!=0);
|
||||
|
||||
if(minus) buf[--idx] = (byte)'-';
|
||||
|
||||
write(buf,idx,11-idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given byte[] as base64 encoded binary to the output.
|
||||
*
|
||||
* <p>
|
||||
* Being defined on this class allows this method to access the buffer directly,
|
||||
* which translates to a better performance.
|
||||
*/
|
||||
public void text(byte[] data, int dataLen) throws IOException {
|
||||
closeStartTag();
|
||||
|
||||
int start = 0;
|
||||
|
||||
while(dataLen>0) {
|
||||
// how many bytes (in data) can we write without overflowing the buffer?
|
||||
int batchSize = Math.min(((octetBuffer.length-octetBufferIndex)/4)*3,dataLen);
|
||||
|
||||
// write the batch
|
||||
octetBufferIndex = DatatypeConverterImpl._printBase64Binary(data,start,batchSize,octetBuffer,octetBufferIndex);
|
||||
|
||||
if(batchSize<dataLen)
|
||||
flushBuffer();
|
||||
|
||||
start += batchSize;
|
||||
dataLen -= batchSize;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// series of the write method that places bytes to the output
|
||||
// (by doing some buffering internal to this class)
|
||||
//
|
||||
|
||||
/**
|
||||
* Writes one byte directly into the buffer.
|
||||
*
|
||||
* <p>
|
||||
* This method can be used somewhat like the {@code text} method,
|
||||
* but it doesn't perform character escaping.
|
||||
*/
|
||||
public final void write(int i) throws IOException {
|
||||
if (octetBufferIndex < octetBuffer.length) {
|
||||
octetBuffer[octetBufferIndex++] = (byte)i;
|
||||
} else {
|
||||
out.write(octetBuffer);
|
||||
octetBufferIndex = 1;
|
||||
octetBuffer[0] = (byte)i;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void write(byte[] b) throws IOException {
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
protected final void write(byte[] b, int start, int length) throws IOException {
|
||||
if ((octetBufferIndex + length) < octetBuffer.length) {
|
||||
System.arraycopy(b, start, octetBuffer, octetBufferIndex, length);
|
||||
octetBufferIndex += length;
|
||||
} else {
|
||||
out.write(octetBuffer, 0, octetBufferIndex);
|
||||
out.write(b, start, length);
|
||||
octetBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void flushBuffer() throws IOException {
|
||||
out.write(octetBuffer, 0, octetBufferIndex);
|
||||
octetBufferIndex = 0;
|
||||
}
|
||||
|
||||
static byte[] toBytes(String s) {
|
||||
byte[] buf = new byte[s.length()];
|
||||
for( int i=s.length()-1; i>=0; i-- )
|
||||
buf[i] = (byte)s.charAt(i);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// per instance copy to prevent an attack where malicious OutputStream
|
||||
// rewrites the byte array.
|
||||
private final byte[] XMLNS_EQUALS = _XMLNS_EQUALS.clone();
|
||||
private final byte[] XMLNS_COLON = _XMLNS_COLON.clone();
|
||||
private final byte[] EQUALS = _EQUALS.clone();
|
||||
private final byte[] CLOSE_TAG = _CLOSE_TAG.clone();
|
||||
private final byte[] EMPTY_TAG = _EMPTY_TAG.clone();
|
||||
private final byte[] XML_DECL = _XML_DECL.clone();
|
||||
|
||||
// masters
|
||||
private static final byte[] _XMLNS_EQUALS = toBytes(" xmlns=\"");
|
||||
private static final byte[] _XMLNS_COLON = toBytes(" xmlns:");
|
||||
private static final byte[] _EQUALS = toBytes("=\"");
|
||||
private static final byte[] _CLOSE_TAG = toBytes("</");
|
||||
private static final byte[] _EMPTY_TAG = toBytes("/>");
|
||||
private static final byte[] _XML_DECL = toBytes("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
|
||||
|
||||
// no need to copy
|
||||
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLEventFactory;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.Characters;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} that writes to StAX {@link XMLEventWriter}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class XMLEventWriterOutput extends XmlOutputAbstractImpl {
|
||||
private final XMLEventWriter out;
|
||||
private final XMLEventFactory ef;
|
||||
|
||||
/** One whitespace. */
|
||||
private final Characters sp;
|
||||
|
||||
public XMLEventWriterOutput(XMLEventWriter out) {
|
||||
this.out = out;
|
||||
ef = XMLEventFactory.newInstance();
|
||||
sp = ef.createCharacters(" ");
|
||||
}
|
||||
|
||||
// not called if we are generating fragments
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext);
|
||||
if(!fragment)
|
||||
out.add(ef.createStartDocument());
|
||||
}
|
||||
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
if(!fragment) {
|
||||
out.add(ef.createEndDocument());
|
||||
out.flush();
|
||||
}
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException {
|
||||
out.add(
|
||||
ef.createStartElement(
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName));
|
||||
|
||||
NamespaceContextImpl.Element nse = nsContext.getCurrent();
|
||||
if(nse.count()>0) {
|
||||
for( int i=nse.count()-1; i>=0; i-- ) {
|
||||
String uri = nse.getNsUri(i);
|
||||
if(uri.length()==0 && nse.getBase()==1)
|
||||
continue; // no point in definint xmlns='' on the root
|
||||
out.add(ef.createNamespace(nse.getPrefix(i),uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void attribute(int prefix, String localName, String value) throws IOException, XMLStreamException {
|
||||
Attribute att;
|
||||
if(prefix==-1)
|
||||
att = ef.createAttribute(localName,value);
|
||||
else
|
||||
att = ef.createAttribute(
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName, value);
|
||||
|
||||
out.add(att);
|
||||
}
|
||||
|
||||
public void endStartTag() throws IOException, SAXException {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException {
|
||||
out.add(
|
||||
ef.createEndElement(
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName));
|
||||
}
|
||||
|
||||
public void text(String value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
if(needsSeparatingWhitespace)
|
||||
out.add(sp);
|
||||
out.add(ef.createCharacters(value));
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
text(value.toString(),needsSeparatingWhitespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
|
||||
import com.sun.xml.internal.bind.marshaller.NoEscapeHandler;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link XmlOutput} that writes to StAX {@link XMLStreamWriter}.
|
||||
* <p>
|
||||
* TODO:
|
||||
* Finding the optimized FI implementations is a bit hacky and not very
|
||||
* extensible. Can we use the service provider mechanism in general for
|
||||
* concrete implementations of XmlOutputAbstractImpl.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class XMLStreamWriterOutput extends XmlOutputAbstractImpl {
|
||||
|
||||
/**
|
||||
* Creates a new {@link XmlOutput} from a {@link XMLStreamWriter}.
|
||||
* This method recognizes an FI StAX writer.
|
||||
*/
|
||||
public static XmlOutput create(XMLStreamWriter out, JAXBContextImpl context, CharacterEscapeHandler escapeHandler) {
|
||||
// try optimized path
|
||||
final Class writerClass = out.getClass();
|
||||
if (writerClass==FI_STAX_WRITER_CLASS) {
|
||||
try {
|
||||
return FI_OUTPUT_CTOR.newInstance(out, context);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
if (STAXEX_WRITER_CLASS!=null && STAXEX_WRITER_CLASS.isAssignableFrom(writerClass)) {
|
||||
try {
|
||||
return STAXEX_OUTPUT_CTOR.newInstance(out);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
CharacterEscapeHandler xmlStreamEscapeHandler = escapeHandler != null ?
|
||||
escapeHandler : NoEscapeHandler.theInstance;
|
||||
|
||||
// otherwise the normal writer.
|
||||
return new XMLStreamWriterOutput(out, xmlStreamEscapeHandler);
|
||||
}
|
||||
|
||||
|
||||
private final XMLStreamWriter out;
|
||||
|
||||
private final CharacterEscapeHandler escapeHandler;
|
||||
|
||||
private final XmlStreamOutWriterAdapter writerWrapper;
|
||||
|
||||
protected final char[] buf = new char[256];
|
||||
|
||||
protected XMLStreamWriterOutput(XMLStreamWriter out, CharacterEscapeHandler escapeHandler) {
|
||||
this.out = out;
|
||||
this.escapeHandler = escapeHandler;
|
||||
this.writerWrapper = new XmlStreamOutWriterAdapter(out);
|
||||
}
|
||||
|
||||
// not called if we are generating fragments
|
||||
@Override
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
super.startDocument(serializer, fragment,nsUriIndex2prefixIndex,nsContext);
|
||||
if(!fragment)
|
||||
out.writeStartDocument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
if(!fragment) {
|
||||
out.writeEndDocument();
|
||||
out.flush();
|
||||
}
|
||||
super.endDocument(fragment);
|
||||
}
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException {
|
||||
out.writeStartElement(
|
||||
nsContext.getPrefix(prefix),
|
||||
localName,
|
||||
nsContext.getNamespaceURI(prefix));
|
||||
|
||||
NamespaceContextImpl.Element nse = nsContext.getCurrent();
|
||||
if(nse.count()>0) {
|
||||
for( int i=nse.count()-1; i>=0; i-- ) {
|
||||
String uri = nse.getNsUri(i);
|
||||
if(uri.length()==0 && nse.getBase()==1)
|
||||
continue; // no point in definint xmlns='' on the root
|
||||
out.writeNamespace(nse.getPrefix(i),uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void attribute(int prefix, String localName, String value) throws IOException, XMLStreamException {
|
||||
if(prefix==-1)
|
||||
out.writeAttribute(localName,value);
|
||||
else
|
||||
out.writeAttribute(
|
||||
nsContext.getPrefix(prefix),
|
||||
nsContext.getNamespaceURI(prefix),
|
||||
localName, value);
|
||||
}
|
||||
|
||||
public void endStartTag() throws IOException, SAXException {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException {
|
||||
out.writeEndElement();
|
||||
}
|
||||
|
||||
public void text(String value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
if(needsSeparatingWhitespace)
|
||||
out.writeCharacters(" ");
|
||||
escapeHandler.escape(value.toCharArray(), 0, value.length(), false, writerWrapper);
|
||||
}
|
||||
|
||||
public void text(Pcdata value, boolean needsSeparatingWhitespace) throws IOException, SAXException, XMLStreamException {
|
||||
if(needsSeparatingWhitespace)
|
||||
out.writeCharacters(" ");
|
||||
|
||||
int len = value.length();
|
||||
if(len <buf.length) {
|
||||
value.writeTo(buf,0);
|
||||
out.writeCharacters(buf,0,len);
|
||||
} else {
|
||||
out.writeCharacters(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference to FI's XMLStreamWriter class, if FI can be loaded.
|
||||
*/
|
||||
private static final Class FI_STAX_WRITER_CLASS = initFIStAXWriterClass();
|
||||
private static final Constructor<? extends XmlOutput> FI_OUTPUT_CTOR = initFastInfosetOutputClass();
|
||||
|
||||
private static Class initFIStAXWriterClass() {
|
||||
try {
|
||||
Class<?> llfisw = Class.forName("com.sun.xml.internal.org.jvnet.fastinfoset.stax.LowLevelFastInfosetStreamWriter");
|
||||
Class<?> sds = Class.forName("com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer");
|
||||
// Check if StAXDocumentSerializer implements LowLevelFastInfosetStreamWriter
|
||||
if (llfisw.isAssignableFrom(sds))
|
||||
return sds;
|
||||
else
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Constructor<? extends XmlOutput> initFastInfosetOutputClass() {
|
||||
try {
|
||||
if (FI_STAX_WRITER_CLASS == null)
|
||||
return null;
|
||||
Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.FastInfosetStreamWriterOutput");
|
||||
return c.getConstructor(FI_STAX_WRITER_CLASS, JAXBContextImpl.class);
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// StAX-ex
|
||||
//
|
||||
private static final Class STAXEX_WRITER_CLASS = initStAXExWriterClass();
|
||||
private static final Constructor<? extends XmlOutput> STAXEX_OUTPUT_CTOR = initStAXExOutputClass();
|
||||
|
||||
private static Class initStAXExWriterClass() {
|
||||
try {
|
||||
return Class.forName("com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx");
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Constructor<? extends XmlOutput> initStAXExOutputClass() {
|
||||
try {
|
||||
Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput");
|
||||
return c.getConstructor(STAXEX_WRITER_CLASS);
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class XmlStreamOutWriterAdapter extends Writer {
|
||||
|
||||
private final XMLStreamWriter writer;
|
||||
|
||||
private XmlStreamOutWriterAdapter(XMLStreamWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
try {
|
||||
writer.writeCharacters(cbuf, off, len);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IOException("Error writing XML stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeEntityRef(String entityReference) throws XMLStreamException {
|
||||
writer.writeEntityRef(entityReference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
try {
|
||||
writer.flush();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IOException("Error flushing XML stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IOException("Error closing XML stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.NameList;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Well-formed XML writer.
|
||||
*
|
||||
* <p>
|
||||
* Implementations of this interface is used to connect {@link XMLSerializer}
|
||||
* to the actual target. This allows {@link XMLSerializer} to be API agnostic.
|
||||
*
|
||||
*
|
||||
* <h2>Notes</h2>
|
||||
* <p>
|
||||
* {@link JAXBContext} assigns indices to URIs and local names
|
||||
* that are statically known by using {@link NameList}.
|
||||
* {@link XmlOutput} implementation can use these indices to improve
|
||||
* the performance. For example, those namespace URI indices can be
|
||||
* turned into prefixes quickly.
|
||||
*
|
||||
* <p>
|
||||
* {@link XmlOutput} still allows arbitrary namepsace URIs / local names
|
||||
* to be written.
|
||||
*
|
||||
* <p>
|
||||
* The {@link NamespaceContextImpl} object, which is shared between {@link XmlOutput} and
|
||||
* {@link XMLSerializer}, keeps track of the in-scope namespace bindings. By the time
|
||||
* the {@link #beginStartTag} method is called, all the namespace bindings for the new
|
||||
* element is already declared. Similarly, after the {@link #endTag} method is called,
|
||||
* in-scope bindings will be removed. This book keeping is all done outside {@link XmlOutput}.
|
||||
*
|
||||
* <p>
|
||||
* {@link XmlOutput} and {@link XMLSerializer} uses indices to
|
||||
* reference prefixes/URIs to be written. {@link NamespaceContextImpl} can
|
||||
* convert prefix indices to URIs and the string representations of prefixes.
|
||||
* Binding from indices to URIs and prefixes do not change while indices
|
||||
* are "in scope", so {@link XmlOutput} is again expected to take advantage of
|
||||
* this to improve the perofmrnace.
|
||||
*
|
||||
* <p>
|
||||
* prefix index 0 is reserved for "xml", and this binding is assumed to be always there.
|
||||
* {@link NamespaceContextImpl} can handle this index correctly, but this binding will never
|
||||
* be reported to {@link XmlOutput} through {@link #beginStartTag}.
|
||||
*
|
||||
* <p>
|
||||
* One pecurilar behavior of a {@link NamespaceContextImpl} object is that it tries
|
||||
* to define redundant xmlns="" on the root element. Implementations of {@link XmlOutput}
|
||||
* is encouraged to check for this and avoid generating redundant namespace declarations.
|
||||
*
|
||||
*
|
||||
*
|
||||
* <h2>Call Sequence</h2>
|
||||
* <p>
|
||||
* {@link XMLSerializer} calls the writer methods in the following order:
|
||||
*
|
||||
* <pre>
|
||||
* CALLSEQUENCE := {@link #startDocument startDocument} ELEMENT {@link #endDocument endDocument}
|
||||
* | ELEMENT // for fragment
|
||||
*
|
||||
* ELEMENT := {@link #beginStartTag beginStartTag} {@link #attribute attribute}* {@link #endStartTag endStartTag} CONTENTS {@link #endTag endTag}
|
||||
*
|
||||
* CONTENTS := (ELEMENT | {@link #text text})*
|
||||
* </pre>
|
||||
*
|
||||
* TODO: for FI, consider making attribute values from Strings to CharSequences.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface XmlOutput {
|
||||
//
|
||||
//
|
||||
// Contracts
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Called at the very beginning.
|
||||
*
|
||||
* @param serializer
|
||||
* the {@link XMLSerializer} that coordinates this whole marshalling episode.
|
||||
* @param fragment
|
||||
* true if we are marshalling a fragment.
|
||||
*/
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Called at the very end. This is the last method to be invoked.
|
||||
*
|
||||
* @param fragment
|
||||
* false if we are writing the whole document.
|
||||
*/
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Writes a start tag.
|
||||
*
|
||||
* <p>
|
||||
* At this point {@link NamespaceContextImpl} holds namespace declarations needed for this
|
||||
* new element.
|
||||
*
|
||||
* <p>
|
||||
* This method is used for writing tags that are indexed.
|
||||
*/
|
||||
public void beginStartTag(Name name) throws IOException, XMLStreamException;
|
||||
|
||||
public void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException;
|
||||
|
||||
public void attribute( Name name, String value ) throws IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* @param prefix
|
||||
* -1 if this attribute does not have a prefix
|
||||
* (this handling differs from that of elements.)
|
||||
*/
|
||||
public void attribute( int prefix, String localName, String value ) throws IOException, XMLStreamException;
|
||||
|
||||
public void endStartTag() throws IOException, SAXException;
|
||||
|
||||
public void endTag(Name name) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
public void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Writes XML text with character escaping, if necessary.
|
||||
*
|
||||
* @param value
|
||||
* this string can contain characters that might need escaping
|
||||
* (such as '&' or '>')
|
||||
* @param needsSeparatingWhitespace
|
||||
*/
|
||||
public void text( String value, boolean needsSeparatingWhitespace ) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Writes XML text with character escaping, if necessary.
|
||||
*
|
||||
* @param value
|
||||
* this string can contain characters that might need escaping
|
||||
* (such as '&' or '>')
|
||||
* @param needsSeparatingWhitespace
|
||||
*/
|
||||
public void text( Pcdata value, boolean needsSeparatingWhitespace ) throws IOException, SAXException, XMLStreamException;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.output;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link XmlOutput}
|
||||
*
|
||||
* Implements the optimal methods, where defer to
|
||||
* the non-optimal methods.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class XmlOutputAbstractImpl implements XmlOutput {
|
||||
//
|
||||
//
|
||||
// Contracts
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Called at the very beginning.
|
||||
*
|
||||
* @param serializer
|
||||
* the {@link XMLSerializer} that coordinates this whole marshalling episode.
|
||||
* @param fragment
|
||||
* true if we are marshalling a fragment.
|
||||
*/
|
||||
public void startDocument(XMLSerializer serializer, boolean fragment, int[] nsUriIndex2prefixIndex, NamespaceContextImpl nsContext) throws IOException, SAXException, XMLStreamException {
|
||||
this.nsUriIndex2prefixIndex = nsUriIndex2prefixIndex;
|
||||
this.nsContext = nsContext;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at the very end.
|
||||
*
|
||||
* @param fragment
|
||||
* false if we are writing the whole document.
|
||||
*/
|
||||
public void endDocument(boolean fragment) throws IOException, SAXException, XMLStreamException {
|
||||
serializer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a start tag.
|
||||
*
|
||||
* <p>
|
||||
* At this point {@link #nsContext} holds namespace declarations needed for this
|
||||
* new element.
|
||||
*
|
||||
* <p>
|
||||
* This method is used for writing tags that are indexed.
|
||||
*/
|
||||
public void beginStartTag(Name name) throws IOException, XMLStreamException {
|
||||
beginStartTag( nsUriIndex2prefixIndex[name.nsUriIndex], name.localName );
|
||||
}
|
||||
|
||||
public abstract void beginStartTag(int prefix, String localName) throws IOException, XMLStreamException;
|
||||
|
||||
public void attribute( Name name, String value ) throws IOException, XMLStreamException {
|
||||
short idx = name.nsUriIndex;
|
||||
if(idx==-1)
|
||||
attribute(-1,name.localName, value);
|
||||
else
|
||||
attribute( nsUriIndex2prefixIndex[idx], name.localName, value );
|
||||
}
|
||||
/**
|
||||
* @param prefix
|
||||
* -1 if this attribute does not have a prefix
|
||||
* (this handling differs from that of elements.)
|
||||
*/
|
||||
public abstract void attribute( int prefix, String localName, String value ) throws IOException, XMLStreamException;
|
||||
|
||||
public abstract void endStartTag() throws IOException, SAXException;
|
||||
|
||||
public void endTag(Name name) throws IOException, SAXException, XMLStreamException {
|
||||
endTag( nsUriIndex2prefixIndex[name.nsUriIndex], name.localName);
|
||||
}
|
||||
public abstract void endTag(int prefix, String localName) throws IOException, SAXException, XMLStreamException;
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Utilities for implementations
|
||||
//
|
||||
//
|
||||
/**
|
||||
* The conversion table from the namespace URI index to prefix index.
|
||||
*
|
||||
* This array is shared with {@link XMLSerializer} and
|
||||
* is updated by it automatically.
|
||||
*
|
||||
* This allows {@link Name#nsUriIndex} to be converted to prefix index
|
||||
* (for {@link NamespaceContextImpl}) quickly.
|
||||
*/
|
||||
protected int[] nsUriIndex2prefixIndex;
|
||||
|
||||
/**
|
||||
* Set by the marshaller before the start tag is written for the root element.
|
||||
*/
|
||||
protected NamespaceContextImpl nsContext;
|
||||
|
||||
protected XMLSerializer serializer;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Code that writes well-formed XML ({@link XmlOutput} and its implementations}.
|
||||
*/
|
||||
package com.sun.xml.internal.bind.v2.runtime.output;
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Commonality between {@link ArrayElementProperty} and {@link ArrayReferenceNodeProperty}.
|
||||
*
|
||||
* Mostly handles the unmarshalling of the wrapper element.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class ArrayERProperty<BeanT,ListT,ItemT> extends ArrayProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
/**
|
||||
* Wrapper tag name if any, or null.
|
||||
*/
|
||||
protected final Name wrapperTagName;
|
||||
|
||||
/**
|
||||
* True if the wrapper tag name is nillable.
|
||||
* Always false if {@link #wrapperTagName}==null.
|
||||
*/
|
||||
protected final boolean isWrapperNillable;
|
||||
|
||||
protected ArrayERProperty(JAXBContextImpl grammar, RuntimePropertyInfo prop, QName tagName, boolean isWrapperNillable) {
|
||||
super(grammar,prop);
|
||||
if(tagName==null)
|
||||
this.wrapperTagName = null;
|
||||
else
|
||||
this.wrapperTagName = grammar.nameBuilder.createElementName(tagName);
|
||||
this.isWrapperNillable = isWrapperNillable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to handle the collection wrapper element.
|
||||
*/
|
||||
private static final class ItemsLoader extends Loader {
|
||||
|
||||
private final Accessor acc;
|
||||
private final Lister lister;
|
||||
|
||||
public ItemsLoader(Accessor acc, Lister lister, QNameMap<ChildLoader> children) {
|
||||
super(false);
|
||||
this.acc = acc;
|
||||
this.lister = lister;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
UnmarshallingContext context = state.getContext();
|
||||
context.startScope(1);
|
||||
// inherit the target so that our children can access its target
|
||||
state.setTarget(state.getPrev().getTarget());
|
||||
|
||||
// start it now, so that even if there's no children we can still return empty collection
|
||||
context.getScope(0).start(acc,lister);
|
||||
}
|
||||
|
||||
private final QNameMap<ChildLoader> children;
|
||||
|
||||
@Override
|
||||
public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
ChildLoader child = children.get(ea.uri,ea.local);
|
||||
if (child == null) {
|
||||
child = children.get(CATCH_ALL);
|
||||
}
|
||||
if (child == null) {
|
||||
super.childElement(state,ea);
|
||||
return;
|
||||
}
|
||||
state.setLoader(child.loader);
|
||||
state.setReceiver(child.receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
state.getContext().endScope(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QName> getExpectedChildElements() {
|
||||
return children.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
public final void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
ListT list = acc.get(o);
|
||||
|
||||
if(list!=null) {
|
||||
if(wrapperTagName!=null) {
|
||||
w.startElement(wrapperTagName,null);
|
||||
w.endNamespaceDecls(list);
|
||||
w.endAttributes();
|
||||
}
|
||||
|
||||
serializeListBody(o,w,list);
|
||||
|
||||
if(wrapperTagName!=null)
|
||||
w.endElement();
|
||||
} else {
|
||||
// list is null
|
||||
if(isWrapperNillable) {
|
||||
w.startElement(wrapperTagName,null);
|
||||
w.writeXsiNilTrue();
|
||||
w.endElement();
|
||||
} // otherwise don't print the wrapper tag name
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the items of the list.
|
||||
* This method is invoked after the necessary wrapper tag is produced (if necessary.)
|
||||
*
|
||||
* @param list
|
||||
* always non-null.
|
||||
*/
|
||||
protected abstract void serializeListBody(BeanT o, XMLSerializer w, ListT list) throws IOException, XMLStreamException, SAXException, AccessorException;
|
||||
|
||||
/**
|
||||
* Creates the unmarshaler to unmarshal the body.
|
||||
*/
|
||||
protected abstract void createBodyUnmarshaller(UnmarshallerChain chain, QNameMap<ChildLoader> loaders);
|
||||
|
||||
|
||||
public final void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> loaders) {
|
||||
if(wrapperTagName!=null) {
|
||||
UnmarshallerChain c = new UnmarshallerChain(chain.context);
|
||||
QNameMap<ChildLoader> m = new QNameMap<ChildLoader>();
|
||||
createBodyUnmarshaller(c,m);
|
||||
Loader loader = new ItemsLoader(acc, lister, m);
|
||||
if(isWrapperNillable || chain.context.allNillable)
|
||||
loader = new XsiNilLoader(loader);
|
||||
loaders.put(wrapperTagName,new ChildLoader(loader,null));
|
||||
} else {
|
||||
createBodyUnmarshaller(chain,loaders);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Receiver} that puts the child object into the {@link Scope} object.
|
||||
*/
|
||||
protected final class ReceiverImpl implements Receiver {
|
||||
private final int offset;
|
||||
|
||||
protected ReceiverImpl(int offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public void receive(UnmarshallingContext.State state, Object o) throws SAXException {
|
||||
state.getContext().getScope(offset).add(acc,lister,o);
|
||||
}
|
||||
}}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Transducer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link ArrayProperty} that contains only one leaf type.
|
||||
*
|
||||
* <p>
|
||||
* This class is optimized for the case where there's only one kind of types
|
||||
* in the array and that type is a leaf type.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
final class ArrayElementLeafProperty<BeanT,ListT,ItemT> extends ArrayElementProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
private final Transducer<ItemT> xducer;
|
||||
|
||||
public ArrayElementLeafProperty(JAXBContextImpl p, RuntimeElementPropertyInfo prop) {
|
||||
super(p, prop);
|
||||
|
||||
// unless those are true, use the ArrayElementNodeProperty.
|
||||
assert prop.getTypes().size()==1;
|
||||
// assert prop.getTypes().get(0).getType().isLeaf(); // this assertion is incorrect in case it's IDREF
|
||||
|
||||
xducer = prop.getTypes().get(0).getTransducer();
|
||||
assert xducer!=null;
|
||||
}
|
||||
|
||||
public void serializeItem(JaxBeanInfo bi, ItemT item, XMLSerializer w) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
xducer.declareNamespace(item,w);
|
||||
w.endNamespaceDecls(item);
|
||||
w.endAttributes();
|
||||
// this is leaf, so by definition there's no type substitution
|
||||
// if there's, we'll be using ArrayElementNodeProperty
|
||||
xducer.writeText(w,item,fieldName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link ArrayProperty} that contains node values.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ArrayElementNodeProperty<BeanT,ListT,ItemT> extends ArrayElementProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
public ArrayElementNodeProperty(JAXBContextImpl p, RuntimeElementPropertyInfo prop) {
|
||||
super(p, prop);
|
||||
}
|
||||
|
||||
public void serializeItem(JaxBeanInfo expected, ItemT item, XMLSerializer w) throws SAXException, IOException, XMLStreamException {
|
||||
if(item==null) {
|
||||
w.writeXsiNilTrue();
|
||||
} else {
|
||||
w.childAsXsiType(item,fieldName,expected, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.core.TypeRef;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.RuntimeUtil;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Transducer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.ListIterator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.NullSafeAccessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TextLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Property} implementation for multi-value property that maps to an element.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class ArrayElementProperty<BeanT,ListT,ItemT> extends ArrayERProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
private final Map<Class,TagAndType> typeMap = new HashMap<Class,TagAndType>();
|
||||
/**
|
||||
* Set by the constructor and reset in the {@link #wrapUp()} method.
|
||||
*/
|
||||
private Map<TypeRef<Type,Class>,JaxBeanInfo> refs = new HashMap<TypeRef<Type, Class>, JaxBeanInfo>();
|
||||
/**
|
||||
* Set by the constructor and reset in the {@link #wrapUp()} method.
|
||||
*/
|
||||
protected RuntimeElementPropertyInfo prop;
|
||||
|
||||
/**
|
||||
* Tag name used when we see null in the collection. Can be null.
|
||||
*/
|
||||
private final Name nillableTagName;
|
||||
|
||||
protected ArrayElementProperty(JAXBContextImpl grammar, RuntimeElementPropertyInfo prop) {
|
||||
super(grammar, prop, prop.getXmlName(), prop.isCollectionNillable());
|
||||
this.prop = prop;
|
||||
|
||||
List<? extends RuntimeTypeRef> types = prop.getTypes();
|
||||
|
||||
Name n = null;
|
||||
|
||||
for (RuntimeTypeRef typeRef : types) {
|
||||
Class type = (Class)typeRef.getTarget().getType();
|
||||
if(type.isPrimitive())
|
||||
type = RuntimeUtil.primitiveToBox.get(type);
|
||||
|
||||
JaxBeanInfo beanInfo = grammar.getOrCreate(typeRef.getTarget());
|
||||
TagAndType tt = new TagAndType(
|
||||
grammar.nameBuilder.createElementName(typeRef.getTagName()),
|
||||
beanInfo);
|
||||
typeMap.put(type,tt);
|
||||
refs.put(typeRef,beanInfo);
|
||||
if(typeRef.isNillable() && n==null)
|
||||
n = tt.tagName;
|
||||
}
|
||||
|
||||
nillableTagName = n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapUp() {
|
||||
super.wrapUp();
|
||||
refs = null;
|
||||
prop = null; // avoid keeping model objects live
|
||||
}
|
||||
|
||||
protected void serializeListBody(BeanT beanT, XMLSerializer w, ListT list) throws IOException, XMLStreamException, SAXException, AccessorException {
|
||||
ListIterator<ItemT> itr = lister.iterator(list, w);
|
||||
|
||||
boolean isIdref = itr instanceof Lister.IDREFSIterator; // UGLY
|
||||
|
||||
while(itr.hasNext()) {
|
||||
try {
|
||||
ItemT item = itr.next();
|
||||
if (item != null) {
|
||||
Class itemType = item.getClass();
|
||||
if(isIdref)
|
||||
// This should be the only place where we need to be aware
|
||||
// that the iterator is iterating IDREFS.
|
||||
itemType = ((Lister.IDREFSIterator)itr).last().getClass();
|
||||
|
||||
// normally, this returns non-null
|
||||
TagAndType tt = typeMap.get(itemType);
|
||||
while(tt==null && itemType!=null) {
|
||||
// otherwise we'll just have to try the slow way
|
||||
itemType = itemType.getSuperclass();
|
||||
tt = typeMap.get(itemType);
|
||||
}
|
||||
|
||||
if(tt==null) {
|
||||
// item is not of the expected type.
|
||||
// w.reportError(new ValidationEventImpl(ValidationEvent.ERROR,
|
||||
// Messages.UNEXPECTED_JAVA_TYPE.format(
|
||||
// item.getClass().getName(),
|
||||
// getExpectedClassNameList()
|
||||
// ),
|
||||
// w.getCurrentLocation(fieldName)));
|
||||
// continue;
|
||||
|
||||
// see the similar code in SingleElementNodeProperty.
|
||||
// for the purpose of simple type substitution, make it a non-error
|
||||
|
||||
w.startElement(typeMap.values().iterator().next().tagName,null);
|
||||
w.childAsXsiType(item,fieldName,w.grammar.getBeanInfo(Object.class), false);
|
||||
} else {
|
||||
w.startElement(tt.tagName,null);
|
||||
serializeItem(tt.beanInfo,item,w);
|
||||
}
|
||||
|
||||
w.endElement();
|
||||
} else {
|
||||
if(nillableTagName!=null) {
|
||||
w.startElement(nillableTagName,null);
|
||||
w.writeXsiNilTrue();
|
||||
w.endElement();
|
||||
}
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(fieldName,e);
|
||||
// recover by ignoring this item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes one item of the property.
|
||||
*/
|
||||
protected abstract void serializeItem(JaxBeanInfo expected, ItemT item, XMLSerializer w) throws SAXException, AccessorException, IOException, XMLStreamException;
|
||||
|
||||
|
||||
public void createBodyUnmarshaller(UnmarshallerChain chain, QNameMap<ChildLoader> loaders) {
|
||||
|
||||
// all items go to the same lister,
|
||||
// so they should share the same offset.
|
||||
int offset = chain.allocateOffset();
|
||||
Receiver recv = new ReceiverImpl(offset);
|
||||
|
||||
for (RuntimeTypeRef typeRef : prop.getTypes()) {
|
||||
|
||||
Name tagName = chain.context.nameBuilder.createElementName(typeRef.getTagName());
|
||||
Loader item = createItemUnmarshaller(chain,typeRef);
|
||||
|
||||
if(typeRef.isNillable() || chain.context.allNillable)
|
||||
item = new XsiNilLoader.Array(item);
|
||||
if(typeRef.getDefaultValue()!=null)
|
||||
item = new DefaultValueLoaderDecorator(item,typeRef.getDefaultValue());
|
||||
|
||||
loaders.put(tagName,new ChildLoader(item,recv));
|
||||
}
|
||||
}
|
||||
|
||||
public final PropertyKind getKind() {
|
||||
return PropertyKind.ELEMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a loader handler that unmarshals the body of the item.
|
||||
*
|
||||
* <p>
|
||||
* This will be sandwiched into <item> ... </item>.
|
||||
*
|
||||
* <p>
|
||||
* When unmarshalling the body of item, the Pack of {@link Lister} is available
|
||||
* as the handler state.
|
||||
*
|
||||
* @param chain
|
||||
* @param typeRef
|
||||
*/
|
||||
private Loader createItemUnmarshaller(UnmarshallerChain chain, RuntimeTypeRef typeRef) {
|
||||
if(PropertyFactory.isLeaf(typeRef.getSource())) {
|
||||
final Transducer xducer = typeRef.getTransducer();
|
||||
return new TextLoader(xducer);
|
||||
} else {
|
||||
return refs.get(typeRef).getLoader(chain.context,true);
|
||||
}
|
||||
}
|
||||
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
if(wrapperTagName!=null) {
|
||||
if(wrapperTagName.equals(nsUri,localName))
|
||||
return acc;
|
||||
} else {
|
||||
for (TagAndType tt : typeMap.values()) {
|
||||
if(tt.tagName.equals(nsUri,localName))
|
||||
// when we can't distinguish null and empty list, JAX-WS doesn't want to see
|
||||
// null (just like any user apps), but since we are providing a raw accessor,
|
||||
// which just grabs the value from the field, we wrap it so that it won't return
|
||||
// null.
|
||||
return new NullSafeAccessor<BeanT,ListT,Object>(acc,lister);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
|
||||
|
||||
|
||||
/**
|
||||
* {@link Property} implementation for multi-value properties
|
||||
* (including arrays and collections.)
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
abstract class ArrayProperty<BeanT,ListT,ItemT> extends PropertyImpl<BeanT> {
|
||||
protected final Accessor<BeanT,ListT> acc;
|
||||
protected final Lister<BeanT,ListT,ItemT,Object> lister;
|
||||
|
||||
protected ArrayProperty(JAXBContextImpl context, RuntimePropertyInfo prop) {
|
||||
super(context,prop);
|
||||
|
||||
assert prop.isCollection();
|
||||
lister = Lister.create(
|
||||
Utils.REFLECTION_NAVIGATOR.erasure(prop.getRawType()),prop.id(),prop.getAdapter());
|
||||
assert lister!=null;
|
||||
acc = prop.getAccessor().optimize(context);
|
||||
assert acc!=null;
|
||||
}
|
||||
|
||||
public void reset(BeanT o) throws AccessorException {
|
||||
lister.reset(o,acc);
|
||||
}
|
||||
|
||||
public final String getIdValue(BeanT bean) {
|
||||
// mutli-value property can't be ID
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.annotation.DomHandler;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElement;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeReferencePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.ListIterator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.WildcardLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class ArrayReferenceNodeProperty<BeanT,ListT,ItemT> extends ArrayERProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
/**
|
||||
* Expected element names and what class to unmarshal.
|
||||
*/
|
||||
private final QNameMap<JaxBeanInfo> expectedElements = new QNameMap<JaxBeanInfo>();
|
||||
|
||||
private final boolean isMixed;
|
||||
|
||||
private final DomHandler domHandler;
|
||||
private final WildcardMode wcMode;
|
||||
|
||||
public ArrayReferenceNodeProperty(JAXBContextImpl p, RuntimeReferencePropertyInfo prop) {
|
||||
super(p, prop, prop.getXmlName(), prop.isCollectionNillable());
|
||||
|
||||
for (RuntimeElement e : prop.getElements()) {
|
||||
JaxBeanInfo bi = p.getOrCreate(e);
|
||||
expectedElements.put( e.getElementName().getNamespaceURI(),e.getElementName().getLocalPart(), bi );
|
||||
}
|
||||
|
||||
isMixed = prop.isMixed();
|
||||
|
||||
if(prop.getWildcard()!=null) {
|
||||
domHandler = (DomHandler) ClassFactory.create(prop.getDOMHandler());
|
||||
wcMode = prop.getWildcard();
|
||||
} else {
|
||||
domHandler = null;
|
||||
wcMode = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void serializeListBody(BeanT o, XMLSerializer w, ListT list) throws IOException, XMLStreamException, SAXException {
|
||||
ListIterator<ItemT> itr = lister.iterator(list, w);
|
||||
|
||||
while(itr.hasNext()) {
|
||||
try {
|
||||
ItemT item = itr.next();
|
||||
if (item != null) {
|
||||
if(isMixed && item.getClass()==String.class) {
|
||||
w.text((String)item,null);
|
||||
} else {
|
||||
JaxBeanInfo bi = w.grammar.getBeanInfo(item,true);
|
||||
if(bi.jaxbType==Object.class && domHandler!=null)
|
||||
// even if 'v' is a DOM node, it always derive from Object,
|
||||
// so the getBeanInfo returns BeanInfo for Object
|
||||
w.writeDom(item,domHandler,o,fieldName);
|
||||
else
|
||||
bi.serializeRoot(item,w);
|
||||
}
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(fieldName,e);
|
||||
// recover by ignoring this item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void createBodyUnmarshaller(UnmarshallerChain chain, QNameMap<ChildLoader> loaders) {
|
||||
final int offset = chain.allocateOffset();
|
||||
|
||||
Receiver recv = new ReceiverImpl(offset);
|
||||
|
||||
for( QNameMap.Entry<JaxBeanInfo> n : expectedElements.entrySet() ) {
|
||||
final JaxBeanInfo beanInfo = n.getValue();
|
||||
loaders.put(n.nsUri,n.localName,new ChildLoader(beanInfo.getLoader(chain.context,true),recv));
|
||||
}
|
||||
|
||||
if(isMixed) {
|
||||
// handler for processing mixed contents.
|
||||
loaders.put(TEXT_HANDLER,
|
||||
new ChildLoader(new MixedTextLoader(recv),null));
|
||||
}
|
||||
|
||||
if(domHandler!=null) {
|
||||
loaders.put(CATCH_ALL,
|
||||
new ChildLoader(new WildcardLoader(domHandler,wcMode),recv));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MixedTextLoader extends Loader {
|
||||
|
||||
private final Receiver recv;
|
||||
|
||||
public MixedTextLoader(Receiver recv) {
|
||||
super(true);
|
||||
this.recv = recv;
|
||||
}
|
||||
|
||||
public void text(UnmarshallingContext.State state, CharSequence text) throws SAXException {
|
||||
if(text.length()!=0) // length 0 text is pointless
|
||||
recv.receive(state,text.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
// TODO: unwrap JAXBElement
|
||||
if(wrapperTagName!=null) {
|
||||
if(wrapperTagName.equals(nsUri,localName))
|
||||
return acc;
|
||||
} else {
|
||||
if(expectedElements.containsKey(nsUri,localName))
|
||||
return acc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
import com.sun.xml.internal.bind.v2.model.core.AttributePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeAttributePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Property} implementation for {@link AttributePropertyInfo}.
|
||||
*
|
||||
* <p>
|
||||
* This one works for both leaves and nodes, scalars and arrays.
|
||||
*
|
||||
* <p>
|
||||
* Implements {@link Comparable} so that it can be sorted lexicographically.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
public final class AttributeProperty<BeanT> extends PropertyImpl<BeanT>
|
||||
implements Comparable<AttributeProperty> {
|
||||
|
||||
/**
|
||||
* Attribute name.
|
||||
*/
|
||||
public final Name attName;
|
||||
|
||||
/**
|
||||
* Heart of the conversion logic.
|
||||
*/
|
||||
public final TransducedAccessor<BeanT> xacc;
|
||||
|
||||
private final Accessor acc;
|
||||
|
||||
public AttributeProperty(JAXBContextImpl context, RuntimeAttributePropertyInfo prop) {
|
||||
super(context,prop);
|
||||
this.attName = context.nameBuilder.createAttributeName(prop.getXmlName());
|
||||
this.xacc = TransducedAccessor.get(context,prop);
|
||||
this.acc = prop.getAccessor(); // we only use this for binder, so don't waste memory by optimizing
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals one attribute.
|
||||
*
|
||||
* @see JaxBeanInfo#serializeAttributes(Object, XMLSerializer)
|
||||
*/
|
||||
public void serializeAttributes(BeanT o, XMLSerializer w) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
CharSequence value = xacc.print(o);
|
||||
if(value!=null)
|
||||
w.attribute(attName,value.toString());
|
||||
}
|
||||
|
||||
public void serializeURIs(BeanT o, XMLSerializer w) throws AccessorException, SAXException {
|
||||
xacc.declareNamespace(o,w);
|
||||
}
|
||||
|
||||
public boolean hasSerializeURIAction() {
|
||||
return xacc.useNamespace();
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chainElem, QNameMap<ChildLoader> handlers) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.ATTRIBUTE;
|
||||
}
|
||||
|
||||
public void reset(BeanT o) throws AccessorException {
|
||||
acc.set(o,null);
|
||||
}
|
||||
|
||||
public String getIdValue(BeanT bean) throws AccessorException, SAXException {
|
||||
return xacc.print(bean).toString();
|
||||
}
|
||||
|
||||
public int compareTo(AttributeProperty that) {
|
||||
return this.attName.compareTo(that.attName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Transducer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.ListTransducedAccessorImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Property} implementation for {@link ElementPropertyInfo} whose
|
||||
* {@link ElementPropertyInfo#isValueList()} is true.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ListElementProperty<BeanT,ListT,ItemT> extends ArrayProperty<BeanT,ListT,ItemT> {
|
||||
|
||||
private final Name tagName;
|
||||
private final String defaultValue;
|
||||
|
||||
/**
|
||||
* Converts all the values to a list and back.
|
||||
*/
|
||||
private final TransducedAccessor<BeanT> xacc;
|
||||
|
||||
public ListElementProperty(JAXBContextImpl grammar, RuntimeElementPropertyInfo prop) {
|
||||
super(grammar, prop);
|
||||
|
||||
assert prop.isValueList();
|
||||
assert prop.getTypes().size()==1; // required by the contract of isValueList
|
||||
RuntimeTypeRef ref = prop.getTypes().get(0);
|
||||
|
||||
tagName = grammar.nameBuilder.createElementName(ref.getTagName());
|
||||
defaultValue = ref.getDefaultValue();
|
||||
|
||||
// transducer for each item
|
||||
Transducer xducer = ref.getTransducer();
|
||||
// transduced accessor for the whole thing
|
||||
xacc = new ListTransducedAccessorImpl(xducer,acc,lister);
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.ELEMENT;
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
Loader l = new LeafPropertyLoader(xacc);
|
||||
l = new DefaultValueLoaderDecorator(l, defaultValue);
|
||||
handlers.put(tagName, new ChildLoader(l,null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
ListT list = acc.get(o);
|
||||
|
||||
if(list!=null) {
|
||||
if(xacc.useNamespace()) {
|
||||
w.startElement(tagName,null);
|
||||
xacc.declareNamespace(o,w);
|
||||
w.endNamespaceDecls(list);
|
||||
w.endAttributes();
|
||||
xacc.writeText(w,o,fieldName);
|
||||
w.endElement();
|
||||
} else {
|
||||
xacc.writeLeafElement(w, tagName, o, fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
if(tagName!=null) {
|
||||
if(tagName.equals(nsUri,localName))
|
||||
return acc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Message resources
|
||||
*/
|
||||
enum Messages {
|
||||
UNSUBSTITUTABLE_TYPE, // 3 args
|
||||
UNEXPECTED_JAVA_TYPE, // 2 args
|
||||
;
|
||||
|
||||
private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName());
|
||||
|
||||
public String toString() {
|
||||
return format();
|
||||
}
|
||||
|
||||
public String format( Object... args ) {
|
||||
return MessageFormat.format( rb.getString(name()), args );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* A JAXB property that constitutes a JAXB-bound bean.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public interface Property<BeanT> extends StructureLoaderBuilder {
|
||||
|
||||
// // is this method necessary? --> probably not
|
||||
// RuntimePropertyInfo owner();
|
||||
|
||||
/**
|
||||
* Resets the property value on the given object.
|
||||
*
|
||||
* <p>
|
||||
* ... for example by setting 0 or null.
|
||||
*/
|
||||
void reset( BeanT o ) throws AccessorException;
|
||||
|
||||
/**
|
||||
* @see JaxBeanInfo#serializeBody(Object, XMLSerializer)
|
||||
*
|
||||
* @param outerPeer
|
||||
* used when this property is expected to print out an element
|
||||
* and that should be associated with this outer peer. normally null.
|
||||
* this is only used for {@link JaxBeanInfo} for {@link JAXBElement}s.
|
||||
* @throws AccessorException
|
||||
* If thrown, caught by the caller and reported.
|
||||
*/
|
||||
public void serializeBody(BeanT beanT, XMLSerializer target, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* @see JaxBeanInfo#serializeURIs(Object, XMLSerializer)
|
||||
*/
|
||||
public void serializeURIs(BeanT beanT, XMLSerializer target) throws SAXException, AccessorException;
|
||||
|
||||
/**
|
||||
* Returns true if
|
||||
* {@link #serializeURIs(Object,XMLSerializer)} performs some meaningful action.
|
||||
*/
|
||||
public boolean hasSerializeURIAction();
|
||||
|
||||
// /**
|
||||
// * Builds the unmarshaller.
|
||||
// *
|
||||
// * @param grammar
|
||||
// * the context object to which this property ultimately belongs to.
|
||||
// * a property will only belong to one grammar, but to reduce the memory footprint
|
||||
// * we don't keep that information stored in {@link Property}, and instead we
|
||||
// * just pass the value as a parameter when needed.
|
||||
// */
|
||||
// Unmarshaller.Handler createUnmarshallerHandler(JAXBContextImpl grammar, Unmarshaller.Handler tail);
|
||||
|
||||
/**
|
||||
* Gets the value of the property.
|
||||
*
|
||||
* This method is only used when the corresponding {@link PropertyInfo#id()} is {@link ID#ID},
|
||||
* and therefore the return type is fixed to {@link String}.
|
||||
*/
|
||||
String getIdValue(BeanT bean) throws AccessorException, SAXException;
|
||||
|
||||
/**
|
||||
* Gets the Kind of property
|
||||
* @return
|
||||
* always non-null.
|
||||
*/
|
||||
PropertyKind getKind();
|
||||
|
||||
|
||||
// UGLY HACK to support JAX-WS
|
||||
// if other clients want to access those functionalities,
|
||||
// we should design a better model
|
||||
/**
|
||||
* If this property is mapped to the specified element,
|
||||
* return an accessor to it.
|
||||
*
|
||||
* @return
|
||||
* null if the property is not mapped to the specified element.
|
||||
*/
|
||||
Accessor getElementPropertyAccessor(String nsUri,String localName);
|
||||
|
||||
/**
|
||||
* Called at the end of the {@link JAXBContext} initialization phase
|
||||
* to clean up any unnecessary references.
|
||||
*/
|
||||
void wrapUp();
|
||||
|
||||
/**
|
||||
* Provides more {@link RuntimePropertyInfo} information on the property.
|
||||
*
|
||||
* @return
|
||||
* null if RETAIN_REFERENCE_TO_INFO property is not set on the {@link JAXBContext}
|
||||
*/
|
||||
public RuntimePropertyInfo getInfo();
|
||||
|
||||
public boolean isHiddenByOverride();
|
||||
|
||||
public void setHiddenByOverride(boolean hidden);
|
||||
|
||||
public String getFieldName();
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeAttributePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeNonElement;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeValuePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
|
||||
/**
|
||||
* Create {@link Property} objects.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
public abstract class PropertyFactory {
|
||||
private PropertyFactory() {}
|
||||
|
||||
|
||||
/**
|
||||
* Constructors of the {@link Property} implementation.
|
||||
*/
|
||||
private static final Constructor<? extends Property>[] propImpls;
|
||||
|
||||
static {
|
||||
Class<? extends Property>[] implClasses = new Class[] {
|
||||
SingleElementLeafProperty.class,
|
||||
null, // single reference leaf --- but there's no such thing as "reference leaf"
|
||||
null, // no such thing as "map leaf"
|
||||
|
||||
ArrayElementLeafProperty.class,
|
||||
null, // array reference leaf --- but there's no such thing as "reference leaf"
|
||||
null, // no such thing as "map leaf"
|
||||
|
||||
SingleElementNodeProperty.class,
|
||||
SingleReferenceNodeProperty.class,
|
||||
SingleMapNodeProperty.class,
|
||||
|
||||
ArrayElementNodeProperty.class,
|
||||
ArrayReferenceNodeProperty.class,
|
||||
null, // map is always a single property (Map doesn't implement Collection)
|
||||
};
|
||||
|
||||
propImpls = new Constructor[implClasses.length];
|
||||
for( int i=0; i<propImpls.length; i++ ) {
|
||||
if(implClasses[i]!=null)
|
||||
// this pointless casting necessary for Mustang
|
||||
propImpls[i] = (Constructor)implClasses[i].getConstructors()[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates/obtains a properly configured {@link Property}
|
||||
* object from the given description.
|
||||
*/
|
||||
public static Property create( JAXBContextImpl grammar, RuntimePropertyInfo info ) {
|
||||
|
||||
PropertyKind kind = info.kind();
|
||||
|
||||
switch(kind) {
|
||||
case ATTRIBUTE:
|
||||
return new AttributeProperty(grammar,(RuntimeAttributePropertyInfo)info);
|
||||
case VALUE:
|
||||
return new ValueProperty(grammar,(RuntimeValuePropertyInfo)info);
|
||||
case ELEMENT:
|
||||
if(((RuntimeElementPropertyInfo)info).isValueList())
|
||||
return new ListElementProperty(grammar,(RuntimeElementPropertyInfo) info);
|
||||
break;
|
||||
case REFERENCE:
|
||||
case MAP:
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
|
||||
boolean isCollection = info.isCollection();
|
||||
boolean isLeaf = isLeaf(info);
|
||||
|
||||
Constructor<? extends Property> c = propImpls[(isLeaf?0:6)+(isCollection?3:0)+kind.propertyIndex];
|
||||
try {
|
||||
return c.newInstance( grammar, info );
|
||||
} catch (InstantiationException e) {
|
||||
throw new InstantiationError(e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getCause();
|
||||
if(t instanceof Error)
|
||||
throw (Error)t;
|
||||
if(t instanceof RuntimeException)
|
||||
throw (RuntimeException)t;
|
||||
|
||||
throw new AssertionError(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for the case that can be optimized as a leaf,
|
||||
* which is a kind of type whose XML representation is just PCDATA.
|
||||
*/
|
||||
static boolean isLeaf(RuntimePropertyInfo info) {
|
||||
Collection<? extends RuntimeTypeInfo> types = info.ref();
|
||||
if(types.size()!=1) return false;
|
||||
|
||||
RuntimeTypeInfo rti = types.iterator().next();
|
||||
if(!(rti instanceof RuntimeNonElement)) return false;
|
||||
|
||||
if(info.id()==ID.IDREF)
|
||||
// IDREF is always handled as leaf -- Transducer maps IDREF String back to an object
|
||||
return true;
|
||||
|
||||
if(((RuntimeNonElement)rti).getTransducer()==null)
|
||||
// Transducer!=null means definitely binds to PCDATA.
|
||||
// even if transducer==null, a referene might be IDREF,
|
||||
// in which case it will still produce PCDATA in this reference.
|
||||
return false;
|
||||
|
||||
if(!info.getIndividualType().equals(rti.getType()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
abstract class PropertyImpl<BeanT> implements Property<BeanT> {
|
||||
/**
|
||||
* Name of this field.
|
||||
*/
|
||||
protected final String fieldName;
|
||||
private RuntimePropertyInfo propertyInfo = null;
|
||||
private boolean hiddenByOverride = false;
|
||||
|
||||
public PropertyImpl(JAXBContextImpl context, RuntimePropertyInfo prop) {
|
||||
fieldName = prop.getName();
|
||||
if (context.retainPropertyInfo) {
|
||||
propertyInfo = prop;
|
||||
}
|
||||
}
|
||||
|
||||
public RuntimePropertyInfo getInfo() {
|
||||
return propertyInfo;
|
||||
}
|
||||
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
}
|
||||
|
||||
public void serializeURIs(BeanT o, XMLSerializer w) throws SAXException, AccessorException {
|
||||
}
|
||||
|
||||
public boolean hasSerializeURIAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
// default implementation. should be overrided
|
||||
return null;
|
||||
}
|
||||
|
||||
public void wrapUp() {/*noop*/}
|
||||
|
||||
public boolean isHiddenByOverride() {
|
||||
return hiddenByOverride;
|
||||
}
|
||||
|
||||
public void setHiddenByOverride(boolean hidden) {
|
||||
this.hiddenByOverride = hidden;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
|
||||
import com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyXsiLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Property} that contains a leaf value.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
final class SingleElementLeafProperty<BeanT> extends PropertyImpl<BeanT> {
|
||||
|
||||
private final Name tagName;
|
||||
private final boolean nillable;
|
||||
private final Accessor acc;
|
||||
private final String defaultValue;
|
||||
private final TransducedAccessor<BeanT> xacc;
|
||||
private final boolean improvedXsiTypeHandling;
|
||||
private final boolean idRef;
|
||||
|
||||
public SingleElementLeafProperty(JAXBContextImpl context, RuntimeElementPropertyInfo prop) {
|
||||
super(context, prop);
|
||||
RuntimeTypeRef ref = prop.getTypes().get(0);
|
||||
tagName = context.nameBuilder.createElementName(ref.getTagName());
|
||||
assert tagName != null;
|
||||
nillable = ref.isNillable();
|
||||
defaultValue = ref.getDefaultValue();
|
||||
this.acc = prop.getAccessor().optimize(context);
|
||||
|
||||
xacc = TransducedAccessor.get(context, ref);
|
||||
assert xacc != null;
|
||||
|
||||
improvedXsiTypeHandling = context.improvedXsiTypeHandling;
|
||||
idRef = ref.getSource().id() == ID.IDREF;
|
||||
}
|
||||
|
||||
public void reset(BeanT o) throws AccessorException {
|
||||
acc.set(o, null);
|
||||
}
|
||||
|
||||
public String getIdValue(BeanT bean) throws AccessorException, SAXException {
|
||||
return xacc.print(bean).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
boolean hasValue = xacc.hasValue(o);
|
||||
|
||||
Object obj = null;
|
||||
|
||||
try {
|
||||
obj = acc.getUnadapted(o);
|
||||
} catch (AccessorException ae) {
|
||||
; // noop
|
||||
}
|
||||
|
||||
Class valueType = acc.getValueType();
|
||||
|
||||
// check for different type than expected. If found, add xsi:type declaration
|
||||
if (xsiTypeNeeded(o, w, obj, valueType)) {
|
||||
w.startElement(tagName, outerPeer);
|
||||
w.childAsXsiType(obj, fieldName, w.grammar.getBeanInfo(valueType), false);
|
||||
w.endElement();
|
||||
} else { // current type is expected
|
||||
if (hasValue) {
|
||||
xacc.writeLeafElement(w, tagName, o, fieldName);
|
||||
} else if (nillable) {
|
||||
w.startElement(tagName, null);
|
||||
w.writeXsiNilTrue();
|
||||
w.endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if xsi type needed to be specified
|
||||
*/
|
||||
private boolean xsiTypeNeeded(BeanT bean, XMLSerializer w, Object value, Class valueTypeClass) {
|
||||
if (!improvedXsiTypeHandling) // improved xsi type set
|
||||
return false;
|
||||
if (acc.isAdapted()) // accessor is not adapted
|
||||
return false;
|
||||
if (value == null) // value is not null
|
||||
return false;
|
||||
if (value.getClass().equals(valueTypeClass)) // value represented by different class
|
||||
return false;
|
||||
if (idRef) // IDREF
|
||||
return false;
|
||||
if (valueTypeClass.isPrimitive()) // is not primitive
|
||||
return false;
|
||||
return acc.isValueTypeAbstractable() || isNillableAbstract(bean, w.grammar, value, valueTypeClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if element is nillable and represented by abstract class.
|
||||
*/
|
||||
private boolean isNillableAbstract(BeanT bean, JAXBContextImpl context, Object value, Class valueTypeClass) {
|
||||
if (!nillable) // check if element is nillable
|
||||
return false;
|
||||
if (valueTypeClass != Object.class) // required type wasn't recognized
|
||||
return false;
|
||||
if (bean.getClass() != JAXBElement.class) // is JAXBElement
|
||||
return false;
|
||||
JAXBElement jaxbElement = (JAXBElement) bean;
|
||||
Class valueClass = value.getClass();
|
||||
Class declaredTypeClass = jaxbElement.getDeclaredType();
|
||||
if (declaredTypeClass.equals(valueClass)) // JAXBElement<class> is different from unadapted class)
|
||||
return false;
|
||||
if (!declaredTypeClass.isAssignableFrom(valueClass)) // and is subclass from it
|
||||
return false;
|
||||
if (!Modifier.isAbstract(declaredTypeClass.getModifiers())) // declared class is abstract
|
||||
return false;
|
||||
return acc.isAbstractable(declaredTypeClass); // and is not builtin type
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
Loader l = new LeafPropertyLoader(xacc);
|
||||
if (defaultValue != null)
|
||||
l = new DefaultValueLoaderDecorator(l, defaultValue);
|
||||
if (nillable || chain.context.allNillable)
|
||||
l = new XsiNilLoader.Single(l, acc);
|
||||
|
||||
// LeafPropertyXsiLoader doesn't work well with nillable elements
|
||||
if (improvedXsiTypeHandling)
|
||||
l = new LeafPropertyXsiLoader(l, xacc, acc);
|
||||
|
||||
handlers.put(tagName, new ChildLoader(l, null));
|
||||
}
|
||||
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
if (tagName.equals(nsUri, localName))
|
||||
return acc;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.core.TypeRef;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfo;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
final class SingleElementNodeProperty<BeanT,ValueT> extends PropertyImpl<BeanT> {
|
||||
|
||||
private final Accessor<BeanT,ValueT> acc;
|
||||
|
||||
private final boolean nillable;
|
||||
|
||||
private final QName[] acceptedElements;
|
||||
|
||||
private final Map<Class,TagAndType> typeNames = new HashMap<Class,TagAndType>();
|
||||
|
||||
private RuntimeElementPropertyInfo prop;
|
||||
|
||||
/**
|
||||
* The tag name used to produce xsi:nil. The first one in the list.
|
||||
*/
|
||||
private final Name nullTagName;
|
||||
|
||||
public SingleElementNodeProperty(JAXBContextImpl context, RuntimeElementPropertyInfo prop) {
|
||||
super(context,prop);
|
||||
acc = prop.getAccessor().optimize(context);
|
||||
this.prop = prop;
|
||||
|
||||
QName nt = null;
|
||||
boolean nil = false;
|
||||
|
||||
acceptedElements = new QName[prop.getTypes().size()];
|
||||
for( int i=0; i<acceptedElements.length; i++ )
|
||||
acceptedElements[i] = prop.getTypes().get(i).getTagName();
|
||||
|
||||
for (RuntimeTypeRef e : prop.getTypes()) {
|
||||
JaxBeanInfo beanInfo = context.getOrCreate(e.getTarget());
|
||||
if(nt==null) nt = e.getTagName();
|
||||
typeNames.put( beanInfo.jaxbType, new TagAndType(
|
||||
context.nameBuilder.createElementName(e.getTagName()),beanInfo) );
|
||||
nil |= e.isNillable();
|
||||
}
|
||||
|
||||
nullTagName = context.nameBuilder.createElementName(nt);
|
||||
|
||||
nillable = nil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapUp() {
|
||||
super.wrapUp();
|
||||
prop = null;
|
||||
}
|
||||
|
||||
public void reset(BeanT bean) throws AccessorException {
|
||||
acc.set(bean,null);
|
||||
}
|
||||
|
||||
public String getIdValue(BeanT beanT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
ValueT v = acc.get(o);
|
||||
if (v!=null) {
|
||||
Class vtype = v.getClass();
|
||||
TagAndType tt=typeNames.get(vtype); // quick way that usually works
|
||||
|
||||
if(tt==null) {// slow way that always works
|
||||
for (Map.Entry<Class,TagAndType> e : typeNames.entrySet()) {
|
||||
if(e.getKey().isAssignableFrom(vtype)) {
|
||||
tt = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean addNilDecl = (o instanceof JAXBElement) && ((JAXBElement)o).isNil();
|
||||
if(tt==null) {
|
||||
// actually this is an error, because the actual type was not a sub-type
|
||||
// of any of the types specified in the annotations,
|
||||
// but for the purpose of experimenting with simple type substitution,
|
||||
// it's convenient to marshal this anyway (for example so that classes
|
||||
// generated from simple types like String can be marshalled as expected.)
|
||||
w.startElement(typeNames.values().iterator().next().tagName,null);
|
||||
w.childAsXsiType(v,fieldName,w.grammar.getBeanInfo(Object.class), addNilDecl && nillable);
|
||||
} else {
|
||||
w.startElement(tt.tagName,null);
|
||||
w.childAsXsiType(v,fieldName,tt.beanInfo, addNilDecl && nillable);
|
||||
}
|
||||
w.endElement();
|
||||
} else if (nillable) {
|
||||
w.startElement(nullTagName,null);
|
||||
w.writeXsiNilTrue();
|
||||
w.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
JAXBContextImpl context = chain.context;
|
||||
|
||||
for (TypeRef<Type,Class> e : prop.getTypes()) {
|
||||
JaxBeanInfo bi = context.getOrCreate((RuntimeTypeInfo) e.getTarget());
|
||||
// if the expected Java type is already final, type substitution won't really work anyway.
|
||||
// this also traps cases like trying to substitute xsd:long element with xsi:type='xsd:int'
|
||||
Loader l = bi.getLoader(context,!Modifier.isFinal(bi.jaxbType.getModifiers()));
|
||||
if(e.getDefaultValue()!=null)
|
||||
l = new DefaultValueLoaderDecorator(l,e.getDefaultValue());
|
||||
if(nillable || chain.context.allNillable)
|
||||
l = new XsiNilLoader.Single(l,acc);
|
||||
handlers.put( e.getTagName(), new ChildLoader(l,acc));
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
for( QName n : acceptedElements) {
|
||||
if(n.getNamespaceURI().equals(nsUri) && n.getLocalPart().equals(localName))
|
||||
return acc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeMapPropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.State;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class SingleMapNodeProperty<BeanT,ValueT extends Map> extends PropertyImpl<BeanT> {
|
||||
|
||||
private final Accessor<BeanT,ValueT> acc;
|
||||
/**
|
||||
* The tag name that surrounds the whole property.
|
||||
*/
|
||||
private final Name tagName;
|
||||
/**
|
||||
* The tag name that corresponds to the 'entry' element.
|
||||
*/
|
||||
private final Name entryTag;
|
||||
private final Name keyTag;
|
||||
private final Name valueTag;
|
||||
|
||||
private final boolean nillable;
|
||||
|
||||
private JaxBeanInfo keyBeanInfo;
|
||||
private JaxBeanInfo valueBeanInfo;
|
||||
|
||||
/**
|
||||
* The implementation class for this property.
|
||||
* If the property is null, we create an instance of this class.
|
||||
*/
|
||||
private final Class<? extends ValueT> mapImplClass;
|
||||
|
||||
public SingleMapNodeProperty(JAXBContextImpl context, RuntimeMapPropertyInfo prop) {
|
||||
super(context, prop);
|
||||
acc = prop.getAccessor().optimize(context);
|
||||
this.tagName = context.nameBuilder.createElementName(prop.getXmlName());
|
||||
this.entryTag = context.nameBuilder.createElementName("","entry");
|
||||
this.keyTag = context.nameBuilder.createElementName("","key");
|
||||
this.valueTag = context.nameBuilder.createElementName("","value");
|
||||
this.nillable = prop.isCollectionNillable();
|
||||
this.keyBeanInfo = context.getOrCreate(prop.getKeyType());
|
||||
this.valueBeanInfo = context.getOrCreate(prop.getValueType());
|
||||
|
||||
// infer the implementation class
|
||||
//noinspection unchecked
|
||||
Class<ValueT> sig = (Class<ValueT>) Utils.REFLECTION_NAVIGATOR.erasure(prop.getRawType());
|
||||
mapImplClass = ClassFactory.inferImplClass(sig,knownImplClasses);
|
||||
// TODO: error check for mapImplClass==null
|
||||
// what is the error reporting path for this part of the code?
|
||||
}
|
||||
|
||||
private static final Class[] knownImplClasses = {
|
||||
HashMap.class, TreeMap.class, LinkedHashMap.class
|
||||
};
|
||||
|
||||
public void reset(BeanT bean) throws AccessorException {
|
||||
acc.set(bean,null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A Map property can never be ID.
|
||||
*/
|
||||
public String getIdValue(BeanT bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.MAP;
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
keyLoader = keyBeanInfo.getLoader(chain.context,true);
|
||||
valueLoader = valueBeanInfo.getLoader(chain.context,true);
|
||||
handlers.put(tagName,new ChildLoader(itemsLoader,null));
|
||||
}
|
||||
|
||||
private Loader keyLoader;
|
||||
private Loader valueLoader;
|
||||
|
||||
/**
|
||||
* Handles <items> and </items>.
|
||||
*
|
||||
* The target will be set to a {@link Map}.
|
||||
*/
|
||||
private final Loader itemsLoader = new Loader(false) {
|
||||
|
||||
private ThreadLocal<BeanT> target = new ThreadLocal<BeanT>();
|
||||
private ThreadLocal<ValueT> map = new ThreadLocal<ValueT>();
|
||||
private int depthCounter = 0; // needed to clean ThreadLocals
|
||||
|
||||
@Override
|
||||
public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
// create or obtain the Map object
|
||||
try {
|
||||
target.set((BeanT)state.getPrev().getTarget());
|
||||
map.set(acc.get(target.get()));
|
||||
depthCounter++;
|
||||
if(map.get() == null) {
|
||||
map.set(ClassFactory.create(mapImplClass));
|
||||
}
|
||||
map.get().clear();
|
||||
state.setTarget(map.get());
|
||||
} catch (AccessorException e) {
|
||||
// recover from error by setting a dummy Map that receives and discards the values
|
||||
handleGenericException(e,true);
|
||||
state.setTarget(new HashMap());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveElement(State state, TagName ea) throws SAXException {
|
||||
super.leaveElement(state, ea);
|
||||
try {
|
||||
acc.set(target.get(), map.get());
|
||||
if (--depthCounter == 0) {
|
||||
target.remove();
|
||||
map.remove();
|
||||
}
|
||||
} catch (AccessorException ex) {
|
||||
handleGenericException(ex,true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
if(ea.matches(entryTag)) {
|
||||
state.setLoader(entryLoader);
|
||||
} else {
|
||||
super.childElement(state,ea);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QName> getExpectedChildElements() {
|
||||
return Collections.singleton(entryTag.toQName());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles <entry> and </entry>.
|
||||
*
|
||||
* The target will be set to a {@link Map}.
|
||||
*/
|
||||
private final Loader entryLoader = new Loader(false) {
|
||||
@Override
|
||||
public void startElement(UnmarshallingContext.State state, TagName ea) {
|
||||
state.setTarget(new Object[2]); // this is inefficient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveElement(UnmarshallingContext.State state, TagName ea) {
|
||||
Object[] keyValue = (Object[])state.getTarget();
|
||||
Map map = (Map) state.getPrev().getTarget();
|
||||
map.put(keyValue[0],keyValue[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
|
||||
if(ea.matches(keyTag)) {
|
||||
state.setLoader(keyLoader);
|
||||
state.setReceiver(keyReceiver);
|
||||
return;
|
||||
}
|
||||
if(ea.matches(valueTag)) {
|
||||
state.setLoader(valueLoader);
|
||||
state.setReceiver(valueReceiver);
|
||||
return;
|
||||
}
|
||||
super.childElement(state,ea);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QName> getExpectedChildElements() {
|
||||
return Arrays.asList(keyTag.toQName(),valueTag.toQName());
|
||||
}
|
||||
};
|
||||
|
||||
private static final class ReceiverImpl implements Receiver {
|
||||
private final int index;
|
||||
public ReceiverImpl(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
public void receive(UnmarshallingContext.State state, Object o) {
|
||||
((Object[])state.getTarget())[index] = o;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Receiver keyReceiver = new ReceiverImpl(0);
|
||||
private static final Receiver valueReceiver = new ReceiverImpl(1);
|
||||
|
||||
@Override
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
ValueT v = acc.get(o);
|
||||
if(v!=null) {
|
||||
bareStartTag(w,tagName,v);
|
||||
for( Map.Entry e : (Set<Map.Entry>)v.entrySet() ) {
|
||||
bareStartTag(w,entryTag,null);
|
||||
|
||||
Object key = e.getKey();
|
||||
if(key!=null) {
|
||||
w.startElement(keyTag,key);
|
||||
w.childAsXsiType(key,fieldName,keyBeanInfo, false);
|
||||
w.endElement();
|
||||
}
|
||||
|
||||
Object value = e.getValue();
|
||||
if(value!=null) {
|
||||
w.startElement(valueTag,value);
|
||||
w.childAsXsiType(value,fieldName,valueBeanInfo, false);
|
||||
w.endElement();
|
||||
}
|
||||
|
||||
w.endElement();
|
||||
}
|
||||
w.endElement();
|
||||
} else
|
||||
if(nillable) {
|
||||
w.startElement(tagName,null);
|
||||
w.writeXsiNilTrue();
|
||||
w.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void bareStartTag(XMLSerializer w, Name tagName, Object peer) throws IOException, XMLStreamException, SAXException {
|
||||
w.startElement(tagName,peer);
|
||||
w.endNamespaceDecls(peer);
|
||||
w.endAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
if(tagName.equals(nsUri,localName))
|
||||
return acc;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.annotation.DomHandler;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElement;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeReferencePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.WildcardLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class SingleReferenceNodeProperty<BeanT,ValueT> extends PropertyImpl<BeanT> {
|
||||
|
||||
private final Accessor<BeanT,ValueT> acc;
|
||||
|
||||
private final QNameMap<JaxBeanInfo> expectedElements = new QNameMap<JaxBeanInfo>();
|
||||
|
||||
private final DomHandler domHandler;
|
||||
private final WildcardMode wcMode;
|
||||
|
||||
public SingleReferenceNodeProperty(JAXBContextImpl context, RuntimeReferencePropertyInfo prop) {
|
||||
super(context,prop);
|
||||
acc = prop.getAccessor().optimize(context);
|
||||
|
||||
for (RuntimeElement e : prop.getElements()) {
|
||||
expectedElements.put( e.getElementName(), context.getOrCreate(e) );
|
||||
}
|
||||
|
||||
if(prop.getWildcard()!=null) {
|
||||
domHandler = (DomHandler) ClassFactory.create(prop.getDOMHandler());
|
||||
wcMode = prop.getWildcard();
|
||||
} else {
|
||||
domHandler = null;
|
||||
wcMode = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(BeanT bean) throws AccessorException {
|
||||
acc.set(bean,null);
|
||||
}
|
||||
|
||||
public String getIdValue(BeanT beanT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
ValueT v = acc.get(o);
|
||||
if(v!=null) {
|
||||
try {
|
||||
JaxBeanInfo bi = w.grammar.getBeanInfo(v,true);
|
||||
if(bi.jaxbType==Object.class && domHandler!=null)
|
||||
// even if 'v' is a DOM node, it always derive from Object,
|
||||
// so the getBeanInfo returns BeanInfo for Object
|
||||
w.writeDom(v,domHandler,o,fieldName);
|
||||
else
|
||||
bi.serializeRoot(v,w);
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(fieldName,e);
|
||||
// recover by ignoring this property
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
|
||||
for (QNameMap.Entry<JaxBeanInfo> n : expectedElements.entrySet())
|
||||
handlers.put(n.nsUri,n.localName, new ChildLoader(n.getValue().getLoader(chain.context,true),acc));
|
||||
|
||||
if(domHandler!=null)
|
||||
handlers.put(CATCH_ALL,new ChildLoader(new WildcardLoader(domHandler,wcMode),acc));
|
||||
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor getElementPropertyAccessor(String nsUri, String localName) {
|
||||
JaxBeanInfo bi = expectedElements.get(nsUri, localName);
|
||||
if(bi!=null) {
|
||||
if(bi instanceof ElementBeanInfoImpl) {
|
||||
final ElementBeanInfoImpl ebi = (ElementBeanInfoImpl) bi;
|
||||
// a JAXBElement. We need to handle JAXBElement for JAX-WS
|
||||
return new Accessor<BeanT,Object>(ebi.expectedType) {
|
||||
public Object get(BeanT bean) throws AccessorException {
|
||||
ValueT r = acc.get(bean);
|
||||
if(r instanceof JAXBElement) {
|
||||
return ((JAXBElement)r).getValue();
|
||||
} else
|
||||
// this is sloppy programming, but hey...
|
||||
return r;
|
||||
}
|
||||
|
||||
public void set(BeanT bean, Object value) throws AccessorException {
|
||||
if(value!=null) {
|
||||
try {
|
||||
value = ebi.createInstanceFromValue(value);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AccessorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AccessorException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new AccessorException(e);
|
||||
}
|
||||
}
|
||||
acc.set(bean,(ValueT)value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// a custom element type, like @XmlRootElement class Foo { ... }
|
||||
return acc;
|
||||
}
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValuePropertyLoader;
|
||||
|
||||
/**
|
||||
* Component that contributes element unmarshallers into
|
||||
* {@link StructureLoader}.
|
||||
*
|
||||
* TODO: think of a better name.
|
||||
*
|
||||
* @author Bhakti Mehta
|
||||
*/
|
||||
public interface StructureLoaderBuilder {
|
||||
/**
|
||||
* Every Property class has an implementation of buildChildElementUnmarshallers
|
||||
* which will fill in the specified {@link QNameMap} by elements that are expected
|
||||
* by this property.
|
||||
*/
|
||||
void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers);
|
||||
|
||||
/**
|
||||
* Magic {@link QName} used to store a handler for the text.
|
||||
*
|
||||
* <p>
|
||||
* To support the mixed content model, {@link StructureLoader} can have
|
||||
* at most one {@link ValuePropertyLoader} for processing text
|
||||
* found amoung elements.
|
||||
*
|
||||
* This special text handler is put into the {@link QNameMap} parameter
|
||||
* of the {@link #buildChildElementUnmarshallers} method by using
|
||||
* this magic token as the key.
|
||||
*/
|
||||
public static final QName TEXT_HANDLER = new QName("\u0000","text");
|
||||
|
||||
/**
|
||||
* Magic {@link QName} used to store a handler for the rest of the elements.
|
||||
*
|
||||
* <p>
|
||||
* To support the wildcard, {@link StructureLoader} can have
|
||||
* at most one {@link Loader} for processing elements
|
||||
* that didn't match any of the named elements.
|
||||
*
|
||||
* This special text handler is put into the {@link QNameMap} parameter
|
||||
* of the {@link #buildChildElementUnmarshallers} method by using
|
||||
* this magic token as the key.
|
||||
*/
|
||||
public static final QName CATCH_ALL = new QName("\u0000","catchAll");
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
|
||||
/**
|
||||
* Pair of {@link QName} and {@link JaxBeanInfo}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class TagAndType {
|
||||
final Name tagName;
|
||||
final JaxBeanInfo beanInfo;
|
||||
TagAndType(Name tagName, JaxBeanInfo beanInfo) {
|
||||
this.tagName = tagName;
|
||||
this.beanInfo = beanInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope;
|
||||
|
||||
|
||||
/**
|
||||
* Pass around a 'ticket dispenser' when creating new
|
||||
* unmarshallers. This controls the index of the slot
|
||||
* allocated to the chain of handlers.
|
||||
|
||||
*
|
||||
* <p>
|
||||
* A ticket dispenser also maintains the offset for handlers
|
||||
* to access state slots. A handler records this value when it's created.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class UnmarshallerChain {
|
||||
/**
|
||||
* This offset allows child unmarshallers to have its own {@link Scope} without colliding with siblings.
|
||||
*/
|
||||
private int offset = 0;
|
||||
|
||||
public final JAXBContextImpl context;
|
||||
|
||||
public UnmarshallerChain(JAXBContextImpl context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new {@link Scope} offset.
|
||||
*/
|
||||
public int allocateOffset() {
|
||||
return offset++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of total scope offset allocated.
|
||||
*/
|
||||
public int getScopeSize() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, 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.property;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.nav.Navigator;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utils class.
|
||||
*
|
||||
* WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
|
||||
*
|
||||
* Has *package private* access to avoid inappropriate usage.
|
||||
*/
|
||||
final class Utils {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Utils.class.getName());
|
||||
|
||||
/**
|
||||
* static ReflectionNavigator field to avoid usage of reflection every time we use it.
|
||||
*/
|
||||
static final Navigator<Type, Class, Field, Method> REFLECTION_NAVIGATOR;
|
||||
|
||||
static { // we statically initializing REFLECTION_NAVIGATOR property
|
||||
try {
|
||||
final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
|
||||
|
||||
// requires accessClassInPackage privilege
|
||||
final Method getInstance = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Method>() {
|
||||
@Override
|
||||
public Method run() {
|
||||
try {
|
||||
Method getInstance = refNav.getDeclaredMethod("getInstance");
|
||||
getInstance.setAccessible(true);
|
||||
return getInstance;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Can't find ReflectionNavigator class");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
|
||||
} catch (SecurityException e) {
|
||||
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor to avoid util class instantiating
|
||||
*/
|
||||
private Utils() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.property;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeValuePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValuePropertyLoader;
|
||||
import com.sun.xml.internal.bind.v2.util.QNameMap;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Property} implementation for {@link XmlValue} properties.
|
||||
*
|
||||
* <p>
|
||||
* This one works for both leaves and nodes, scalars and arrays.
|
||||
*
|
||||
* @author Bhakti Mehta (bhakti.mehta@sun.com)
|
||||
*/
|
||||
public final class ValueProperty<BeanT> extends PropertyImpl<BeanT> {
|
||||
|
||||
/**
|
||||
* Heart of the conversion logic.
|
||||
*/
|
||||
private final TransducedAccessor<BeanT> xacc;
|
||||
private final Accessor<BeanT,?> acc;
|
||||
|
||||
|
||||
public ValueProperty(JAXBContextImpl context, RuntimeValuePropertyInfo prop) {
|
||||
super(context,prop);
|
||||
xacc = TransducedAccessor.get(context,prop);
|
||||
acc = prop.getAccessor(); // we only use this for binder, so don't waste memory by optimizing
|
||||
}
|
||||
|
||||
public final void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
if(xacc.hasValue(o))
|
||||
xacc.writeText(w,o,fieldName);
|
||||
}
|
||||
|
||||
public void serializeURIs(BeanT o, XMLSerializer w) throws SAXException, AccessorException {
|
||||
xacc.declareNamespace(o,w);
|
||||
}
|
||||
|
||||
public boolean hasSerializeURIAction() {
|
||||
return xacc.useNamespace();
|
||||
}
|
||||
|
||||
public void buildChildElementUnmarshallers(UnmarshallerChain chainElem, QNameMap<ChildLoader> handlers) {
|
||||
handlers.put(StructureLoaderBuilder.TEXT_HANDLER,
|
||||
new ChildLoader(new ValuePropertyLoader(xacc),null));
|
||||
}
|
||||
|
||||
public PropertyKind getKind() {
|
||||
return PropertyKind.VALUE;
|
||||
}
|
||||
|
||||
public void reset(BeanT o) throws AccessorException {
|
||||
acc.set(o,null);
|
||||
}
|
||||
|
||||
public String getIdValue(BeanT bean) throws AccessorException, SAXException {
|
||||
return xacc.print(bean).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, 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.reflect;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.bind.Util;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.api.JAXBRIContext;
|
||||
import com.sun.xml.internal.bind.v2.model.core.Adapter;
|
||||
import com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Accesses a particular property of a bean.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* This interface encapsulates the access to the actual data store.
|
||||
* The intention is to generate implementations for a particular bean
|
||||
* and a property to improve the performance.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Accessor can be used as a receiver. Upon receiving an object
|
||||
* it sets that to the field.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
* @see Accessor.FieldReflection
|
||||
* @see TransducedAccessor
|
||||
*/
|
||||
public abstract class Accessor<BeanT, ValueT> implements Receiver {
|
||||
|
||||
public final Class<ValueT> valueType;
|
||||
|
||||
public Class<ValueT> getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
protected Accessor(Class<ValueT> valueType) {
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the optimized version of the same accessor.
|
||||
*
|
||||
* @param context The {@link JAXBContextImpl} that owns the whole thing.
|
||||
* (See {@link RuntimeModelBuilder#context}.)
|
||||
* @return At least the implementation can return <tt>this</tt>.
|
||||
*/
|
||||
public Accessor<BeanT, ValueT> optimize(@Nullable JAXBContextImpl context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the property of the given bean object.
|
||||
*
|
||||
* @param bean must not be null.
|
||||
* @throws AccessorException if failed to set a value. For example, the getter method
|
||||
* may throw an exception.
|
||||
* @since 2.0 EA1
|
||||
*/
|
||||
public abstract ValueT get(BeanT bean) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Sets the value of the property of the given bean object.
|
||||
*
|
||||
* @param bean must not be null.
|
||||
* @param value the value to be set. Setting value to null means resetting
|
||||
* to the VM default value (even for primitive properties.)
|
||||
* @throws AccessorException if failed to set a value. For example, the setter method
|
||||
* may throw an exception.
|
||||
* @since 2.0 EA1
|
||||
*/
|
||||
public abstract void set(BeanT bean, ValueT value) throws AccessorException;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value without adapting the value.
|
||||
* <p/>
|
||||
* This ugly entry point is only used by JAX-WS.
|
||||
* See {@link JAXBRIContext#getElementPropertyAccessor}
|
||||
*/
|
||||
public Object getUnadapted(BeanT bean) throws AccessorException {
|
||||
return get(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this accessor wraps an adapter.
|
||||
* <p/>
|
||||
* This method needs to be used with care, but it helps some optimization.
|
||||
*/
|
||||
public boolean isAdapted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value without adapting the value.
|
||||
* <p/>
|
||||
* This ugly entry point is only used by JAX-WS.
|
||||
* See {@link JAXBRIContext#getElementPropertyAccessor}
|
||||
*/
|
||||
public void setUnadapted(BeanT bean, Object value) throws AccessorException {
|
||||
set(bean, (ValueT) value);
|
||||
}
|
||||
|
||||
public void receive(UnmarshallingContext.State state, Object o) throws SAXException {
|
||||
try {
|
||||
set((BeanT) state.getTarget(), (ValueT) o);
|
||||
} catch (AccessorException e) {
|
||||
Loader.handleGenericException(e, true);
|
||||
} catch (IllegalAccessError iae) {
|
||||
// throw UnmarshalException instead IllegalAccesssError | Issue 475
|
||||
Loader.handleGenericError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Class> nonAbstractableClasses = Arrays.asList(new Class[]{
|
||||
Object.class,
|
||||
java.util.Calendar.class,
|
||||
javax.xml.datatype.Duration.class,
|
||||
javax.xml.datatype.XMLGregorianCalendar.class,
|
||||
java.awt.Image.class,
|
||||
javax.activation.DataHandler.class,
|
||||
javax.xml.transform.Source.class,
|
||||
java.util.Date.class,
|
||||
java.io.File.class,
|
||||
java.net.URI.class,
|
||||
java.net.URL.class,
|
||||
Class.class,
|
||||
String.class,
|
||||
javax.xml.transform.Source.class}
|
||||
);
|
||||
|
||||
public boolean isValueTypeAbstractable() {
|
||||
return !nonAbstractableClasses.contains(getValueType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it is not builtin jaxb class
|
||||
* @param clazz to be checked
|
||||
* @return true if it is NOT builtin class
|
||||
*/
|
||||
public boolean isAbstractable(Class clazz) {
|
||||
return !nonAbstractableClasses.contains(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps this {@link Accessor} into another {@link Accessor}
|
||||
* and performs the type adaption as necessary.
|
||||
*/
|
||||
public final <T> Accessor<BeanT, T> adapt(Class<T> targetType, final Class<? extends XmlAdapter<T, ValueT>> adapter) {
|
||||
return new AdaptedAccessor<BeanT, ValueT, T>(targetType, this, adapter);
|
||||
}
|
||||
|
||||
public final <T> Accessor<BeanT, T> adapt(Adapter<Type, Class> adapter) {
|
||||
return new AdaptedAccessor<BeanT, ValueT, T>(
|
||||
(Class<T>) Utils.REFLECTION_NAVIGATOR.erasure(adapter.defaultType),
|
||||
this,
|
||||
adapter.adapterType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag that will be set to true after issueing a warning
|
||||
* about the lack of permission to access non-public fields.
|
||||
*/
|
||||
private static boolean accessWarned = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@link Accessor} that uses Java reflection to access a field.
|
||||
*/
|
||||
public static class FieldReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
|
||||
public final Field f;
|
||||
|
||||
private static final Logger logger = Util.getClassLogger();
|
||||
|
||||
public FieldReflection(Field f) {
|
||||
this(f, false);
|
||||
}
|
||||
|
||||
public FieldReflection(Field f, boolean supressAccessorWarnings) {
|
||||
super((Class<ValueT>) f.getType());
|
||||
this.f = f;
|
||||
|
||||
int mod = f.getModifiers();
|
||||
if (!Modifier.isPublic(mod) || Modifier.isFinal(mod) || !Modifier.isPublic(f.getDeclaringClass().getModifiers())) {
|
||||
try {
|
||||
// attempt to make it accessible, but do so in the security context of the calling application.
|
||||
// don't do this in the doPrivilege block, as that would create a security hole for anyone
|
||||
// to make any field accessible.
|
||||
f.setAccessible(true);
|
||||
} catch (SecurityException e) {
|
||||
if ((!accessWarned) && (!supressAccessorWarnings)) {
|
||||
// this happens when we don't have enough permission.
|
||||
logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
|
||||
f.getDeclaringClass().getName(),
|
||||
f.getName()),
|
||||
e);
|
||||
}
|
||||
accessWarned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ValueT get(BeanT bean) {
|
||||
try {
|
||||
return (ValueT) f.get(bean);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void set(BeanT bean, ValueT value) {
|
||||
try {
|
||||
if (value == null)
|
||||
value = (ValueT) uninitializedValues.get(valueType);
|
||||
f.set(bean, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
|
||||
if (context != null && context.fastBoot)
|
||||
// let's not waste time on doing this for the sake of faster boot.
|
||||
return this;
|
||||
Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(f);
|
||||
if (acc != null)
|
||||
return acc;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-only access to {@link Field}. Used to handle a static field.
|
||||
*/
|
||||
public static final class ReadOnlyFieldReflection<BeanT, ValueT> extends FieldReflection<BeanT, ValueT> {
|
||||
public ReadOnlyFieldReflection(Field f, boolean supressAccessorWarnings) {
|
||||
super(f, supressAccessorWarnings);
|
||||
}
|
||||
public ReadOnlyFieldReflection(Field f) {
|
||||
super(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(BeanT bean, ValueT value) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link Accessor} that uses Java reflection to access a getter and a setter.
|
||||
*/
|
||||
public static class GetterSetterReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
|
||||
public final Method getter;
|
||||
public final Method setter;
|
||||
|
||||
private static final Logger logger = Util.getClassLogger();
|
||||
|
||||
public GetterSetterReflection(Method getter, Method setter) {
|
||||
super(
|
||||
(Class<ValueT>) (getter != null ?
|
||||
getter.getReturnType() :
|
||||
setter.getParameterTypes()[0]));
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
|
||||
if (getter != null)
|
||||
makeAccessible(getter);
|
||||
if (setter != null)
|
||||
makeAccessible(setter);
|
||||
}
|
||||
|
||||
private void makeAccessible(Method m) {
|
||||
if (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
|
||||
try {
|
||||
m.setAccessible(true);
|
||||
} catch (SecurityException e) {
|
||||
if (!accessWarned)
|
||||
// this happens when we don't have enough permission.
|
||||
logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
|
||||
m.getDeclaringClass().getName(),
|
||||
m.getName()),
|
||||
e);
|
||||
accessWarned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ValueT get(BeanT bean) throws AccessorException {
|
||||
try {
|
||||
return (ValueT) getter.invoke(bean);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw handleInvocationTargetException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(BeanT bean, ValueT value) throws AccessorException {
|
||||
try {
|
||||
if (value == null)
|
||||
value = (ValueT) uninitializedValues.get(valueType);
|
||||
setter.invoke(bean, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw handleInvocationTargetException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private AccessorException handleInvocationTargetException(InvocationTargetException e) {
|
||||
// don't block a problem in the user code
|
||||
Throwable t = e.getTargetException();
|
||||
if (t instanceof RuntimeException)
|
||||
throw (RuntimeException) t;
|
||||
if (t instanceof Error)
|
||||
throw (Error) t;
|
||||
|
||||
// otherwise it's a checked exception.
|
||||
// I'm not sure how to handle this.
|
||||
// we can throw a checked exception from here,
|
||||
// but because get/set would be called from so many different places,
|
||||
// the handling would be tedious.
|
||||
return new AccessorException(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
|
||||
if (getter == null || setter == null)
|
||||
// if we aren't complete, OptimizedAccessor won't always work
|
||||
return this;
|
||||
if (context != null && context.fastBoot)
|
||||
// let's not waste time on doing this for the sake of faster boot.
|
||||
return this;
|
||||
|
||||
Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(getter, setter);
|
||||
if (acc != null)
|
||||
return acc;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of {@link GetterSetterReflection} that doesn't have any setter.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* This provides a user-friendly error message.
|
||||
*/
|
||||
public static class GetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
|
||||
public GetterOnlyReflection(Method getter) {
|
||||
super(getter, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(BeanT bean, ValueT value) throws AccessorException {
|
||||
throw new AccessorException(Messages.NO_SETTER.format(getter.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of {@link GetterSetterReflection} thaat doesn't have any getter.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* This provides a user-friendly error message.
|
||||
*/
|
||||
public static class SetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
|
||||
public SetterOnlyReflection(Method setter) {
|
||||
super(null, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueT get(BeanT bean) throws AccessorException {
|
||||
throw new AccessorException(Messages.NO_GETTER.format(setter.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the special {@link Accessor} used to recover from errors.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A, B> Accessor<A, B> getErrorInstance() {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
private static final Accessor ERROR = new Accessor<Object, Object>(Object.class) {
|
||||
public Object get(Object o) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void set(Object o, Object o1) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link Accessor} for {@link JAXBElement#getValue()}.
|
||||
*/
|
||||
public static final Accessor<JAXBElement, Object> JAXB_ELEMENT_VALUE = new Accessor<JAXBElement, Object>(Object.class) {
|
||||
public Object get(JAXBElement jaxbElement) {
|
||||
return jaxbElement.getValue();
|
||||
}
|
||||
|
||||
public void set(JAXBElement jaxbElement, Object o) {
|
||||
jaxbElement.setValue(o);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uninitialized map keyed by their classes.
|
||||
*/
|
||||
private static final Map<Class, Object> uninitializedValues = new HashMap<Class, Object>();
|
||||
|
||||
static {
|
||||
/*
|
||||
static byte default_value_byte = 0;
|
||||
static boolean default_value_boolean = false;
|
||||
static char default_value_char = 0;
|
||||
static float default_value_float = 0;
|
||||
static double default_value_double = 0;
|
||||
static int default_value_int = 0;
|
||||
static long default_value_long = 0;
|
||||
static short default_value_short = 0;
|
||||
*/
|
||||
uninitializedValues.put(byte.class, Byte.valueOf((byte) 0));
|
||||
uninitializedValues.put(boolean.class, false);
|
||||
uninitializedValues.put(char.class, Character.valueOf((char) 0));
|
||||
uninitializedValues.put(float.class, Float.valueOf(0));
|
||||
uninitializedValues.put(double.class, Double.valueOf(0));
|
||||
uninitializedValues.put(int.class, Integer.valueOf(0));
|
||||
uninitializedValues.put(long.class, Long.valueOf(0));
|
||||
uninitializedValues.put(short.class, Short.valueOf((short) 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.model.core.Adapter;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Coordinator;
|
||||
|
||||
/**
|
||||
* {@link Accessor} that adapts the value by using {@link Adapter}.
|
||||
*
|
||||
* @see Accessor#adapt
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class AdaptedAccessor<BeanT,InMemValueT,OnWireValueT> extends Accessor<BeanT,OnWireValueT> {
|
||||
private final Accessor<BeanT,InMemValueT> core;
|
||||
private final Class<? extends XmlAdapter<OnWireValueT,InMemValueT>> adapter;
|
||||
|
||||
/*pacakge*/ AdaptedAccessor(Class<OnWireValueT> targetType, Accessor<BeanT, InMemValueT> extThis, Class<? extends XmlAdapter<OnWireValueT, InMemValueT>> adapter) {
|
||||
super(targetType);
|
||||
this.core = extThis;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdapted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public OnWireValueT get(BeanT bean) throws AccessorException {
|
||||
InMemValueT v = core.get(bean);
|
||||
|
||||
XmlAdapter<OnWireValueT,InMemValueT> a = getAdapter();
|
||||
try {
|
||||
return a.marshal(v);
|
||||
} catch (Exception e) {
|
||||
throw new AccessorException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(BeanT bean, OnWireValueT o) throws AccessorException {
|
||||
XmlAdapter<OnWireValueT, InMemValueT> a = getAdapter();
|
||||
try {
|
||||
core.set(bean, (o == null ? null : a.unmarshal(o)));
|
||||
} catch (Exception e) {
|
||||
throw new AccessorException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getUnadapted(BeanT bean) throws AccessorException {
|
||||
return core.getUnadapted(bean);
|
||||
}
|
||||
|
||||
public void setUnadapted(BeanT bean, Object value) throws AccessorException {
|
||||
core.setUnadapted(bean,value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sometimes Adapters are used directly by JAX-WS outside any
|
||||
* {@link Coordinator}. Use this lazily-created cached
|
||||
* {@link XmlAdapter} in such cases.
|
||||
*/
|
||||
private XmlAdapter<OnWireValueT, InMemValueT> staticAdapter;
|
||||
|
||||
private XmlAdapter<OnWireValueT, InMemValueT> getAdapter() {
|
||||
Coordinator coordinator = Coordinator._getInstance();
|
||||
if(coordinator!=null)
|
||||
return coordinator.getAdapter(adapter);
|
||||
else {
|
||||
synchronized(this) {
|
||||
if(staticAdapter==null)
|
||||
staticAdapter = ClassFactory.create(adapter);
|
||||
}
|
||||
return staticAdapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.Coordinator;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Lister} that adapts individual item types.
|
||||
*/
|
||||
final class AdaptedLister<BeanT,PropT,InMemItemT,OnWireItemT,PackT> extends Lister<BeanT,PropT,OnWireItemT,PackT> {
|
||||
private final Lister<BeanT,PropT,InMemItemT,PackT> core;
|
||||
private final Class<? extends XmlAdapter<OnWireItemT,InMemItemT>> adapter;
|
||||
|
||||
/*package*/ AdaptedLister(
|
||||
Lister<BeanT,PropT,InMemItemT,PackT> core,
|
||||
Class<? extends XmlAdapter<OnWireItemT,InMemItemT>> adapter) {
|
||||
|
||||
this.core = core;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
private XmlAdapter<OnWireItemT,InMemItemT> getAdapter() {
|
||||
return Coordinator._getInstance().getAdapter(adapter);
|
||||
}
|
||||
|
||||
public ListIterator<OnWireItemT> iterator(PropT prop, XMLSerializer context) {
|
||||
return new ListIteratorImpl( core.iterator(prop,context), context );
|
||||
}
|
||||
|
||||
public PackT startPacking(BeanT bean, Accessor<BeanT, PropT> accessor) throws AccessorException {
|
||||
return core.startPacking(bean,accessor);
|
||||
}
|
||||
|
||||
public void addToPack(PackT pack, OnWireItemT item) throws AccessorException {
|
||||
InMemItemT r;
|
||||
try {
|
||||
r = getAdapter().unmarshal(item);
|
||||
} catch (Exception e) {
|
||||
throw new AccessorException(e);
|
||||
}
|
||||
core.addToPack(pack,r);
|
||||
}
|
||||
|
||||
public void endPacking(PackT pack, BeanT bean, Accessor<BeanT,PropT> accessor) throws AccessorException {
|
||||
core.endPacking(pack,bean,accessor);
|
||||
}
|
||||
|
||||
public void reset(BeanT bean, Accessor<BeanT, PropT> accessor) throws AccessorException {
|
||||
core.reset(bean,accessor);
|
||||
}
|
||||
|
||||
private final class ListIteratorImpl implements ListIterator<OnWireItemT> {
|
||||
private final ListIterator<InMemItemT> core;
|
||||
private final XMLSerializer serializer;
|
||||
|
||||
public ListIteratorImpl(ListIterator<InMemItemT> core,XMLSerializer serializer) {
|
||||
this.core = core;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return core.hasNext();
|
||||
}
|
||||
|
||||
public OnWireItemT next() throws SAXException, JAXBException {
|
||||
InMemItemT next = core.next();
|
||||
try {
|
||||
return getAdapter().marshal(next);
|
||||
} catch (Exception e) {
|
||||
serializer.reportError(null,e);
|
||||
return null; // recover this error by returning null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link TransducedAccessor} that prints to {@link String}.
|
||||
*
|
||||
* <p>
|
||||
* The print method that works for {@link String} determines the dispatching
|
||||
* of the {@link #writeText(XMLSerializer,Object,String)} and
|
||||
* {@link #writeLeafElement(XMLSerializer, Name, Object, String)} methods,
|
||||
* so those are implemented here.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class DefaultTransducedAccessor<T> extends TransducedAccessor<T> {
|
||||
|
||||
public abstract String print(T o) throws AccessorException, SAXException;
|
||||
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, T o, String fieldName) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
w.leafElement(tagName,print(o),fieldName);
|
||||
}
|
||||
|
||||
public void writeText(XMLSerializer w, T o, String fieldName) throws AccessorException, SAXException, IOException, XMLStreamException {
|
||||
w.text(print(o),fieldName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Almost like {@link Iterator} but can throw JAXB specific exceptions.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface ListIterator<E> {
|
||||
/**
|
||||
* Works like {@link Iterator#hasNext()}.
|
||||
*/
|
||||
boolean hasNext();
|
||||
|
||||
/**
|
||||
* Works like {@link Iterator#next()}.
|
||||
*
|
||||
* @throws SAXException
|
||||
* if an error is found, reported, and we were told to abort
|
||||
* @throws JAXBException
|
||||
* if an error is found, reported, and we were told to abort
|
||||
*/
|
||||
E next() throws SAXException, JAXBException;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.sun.xml.internal.bind.WhiteSpaceProcessor;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Transducer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link TransducedAccessor} for a list simple type.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ListTransducedAccessorImpl<BeanT,ListT,ItemT,PackT> extends DefaultTransducedAccessor<BeanT> {
|
||||
/**
|
||||
* {@link Transducer} for each item type.
|
||||
*/
|
||||
private final Transducer<ItemT> xducer;
|
||||
/**
|
||||
* {@link Lister} for handling list of tokens.
|
||||
*/
|
||||
private final Lister<BeanT,ListT,ItemT,PackT> lister;
|
||||
/**
|
||||
* {@link Accessor} to get/set the list.
|
||||
*/
|
||||
private final Accessor<BeanT,ListT> acc;
|
||||
|
||||
public ListTransducedAccessorImpl(Transducer<ItemT> xducer, Accessor<BeanT,ListT> acc, Lister<BeanT,ListT,ItemT,PackT> lister) {
|
||||
this.xducer = xducer;
|
||||
this.lister = lister;
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
public boolean useNamespace() {
|
||||
return xducer.useNamespace();
|
||||
}
|
||||
|
||||
public void declareNamespace(BeanT bean, XMLSerializer w) throws AccessorException, SAXException {
|
||||
ListT list = acc.get(bean);
|
||||
|
||||
if(list!=null) {
|
||||
ListIterator<ItemT> itr = lister.iterator(list, w);
|
||||
|
||||
while(itr.hasNext()) {
|
||||
try {
|
||||
ItemT item = itr.next();
|
||||
if (item != null) {
|
||||
xducer.declareNamespace(item,w);
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(null,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this is inefficient, consider a redesign
|
||||
// perhaps we should directly write to XMLSerializer,
|
||||
// or maybe add more methods like writeLeafElement.
|
||||
public String print(BeanT o) throws AccessorException, SAXException {
|
||||
ListT list = acc.get(o);
|
||||
|
||||
if(list==null)
|
||||
return null;
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
XMLSerializer w = XMLSerializer.getInstance();
|
||||
ListIterator<ItemT> itr = lister.iterator(list, w);
|
||||
|
||||
while(itr.hasNext()) {
|
||||
try {
|
||||
ItemT item = itr.next();
|
||||
if (item != null) {
|
||||
if(buf.length()>0) buf.append(' ');
|
||||
buf.append(xducer.print(item));
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(null,e);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void processValue(BeanT bean, CharSequence s) throws AccessorException, SAXException {
|
||||
PackT pack = lister.startPacking(bean,acc);
|
||||
|
||||
int idx = 0;
|
||||
int len = s.length();
|
||||
|
||||
while(true) {
|
||||
int p = idx;
|
||||
while( p<len && !WhiteSpaceProcessor.isWhiteSpace(s.charAt(p)) )
|
||||
p++;
|
||||
|
||||
CharSequence token = s.subSequence(idx,p);
|
||||
if (!token.equals(""))
|
||||
lister.addToPack(pack,xducer.parse(token));
|
||||
|
||||
if(p==len) break; // done
|
||||
|
||||
while( p<len && WhiteSpaceProcessor.isWhiteSpace(s.charAt(p)) )
|
||||
p++;
|
||||
if(p==len) break; // done
|
||||
|
||||
idx = p;
|
||||
}
|
||||
|
||||
lister.endPacking(pack,bean,acc);
|
||||
}
|
||||
|
||||
public void parse(BeanT bean, CharSequence lexical) throws AccessorException, SAXException {
|
||||
processValue(bean,lexical);
|
||||
}
|
||||
|
||||
public boolean hasValue(BeanT bean) throws AccessorException {
|
||||
return acc.get(bean)!=null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.reflect;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import com.sun.istack.internal.SAXException2;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.ClassFactory;
|
||||
import com.sun.xml.internal.bind.v2.TODO;
|
||||
import com.sun.xml.internal.bind.v2.model.core.Adapter;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Patcher;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Used to list individual values of a multi-value property, and
|
||||
* to pack individual values into a multi-value property.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
public abstract class Lister<BeanT,PropT,ItemT,PackT> {
|
||||
|
||||
protected Lister() {}
|
||||
|
||||
/**
|
||||
* Iterates values of a multi-value property.
|
||||
*
|
||||
* @param context
|
||||
* This parameter is used to support ID/IDREF handling.
|
||||
*/
|
||||
public abstract ListIterator<ItemT> iterator(PropT multiValueProp, XMLSerializer context);
|
||||
|
||||
/**
|
||||
* Setting values to a multi-value property starts by creating
|
||||
* a transient object called "pack" from the current field.
|
||||
*/
|
||||
public abstract PackT startPacking(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Once the {@link #startPacking} is called, you can
|
||||
* add values to the pack by using this method.
|
||||
*/
|
||||
public abstract void addToPack( PackT pack, ItemT newValue ) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Finally, call this method to
|
||||
* wraps up the {@code pack}. This method may update the field of
|
||||
* the given bean.
|
||||
*/
|
||||
public abstract void endPacking( PackT pack, BeanT bean, Accessor<BeanT,PropT> acc ) throws AccessorException;
|
||||
|
||||
/**
|
||||
* Clears the values of the property.
|
||||
*/
|
||||
public abstract void reset(BeanT o,Accessor<BeanT,PropT> acc) throws AccessorException;
|
||||
|
||||
|
||||
/**
|
||||
* Gets a reference to the appropriate {@link Lister} object
|
||||
* if the field is a multi-value field. Otherwise null.
|
||||
*
|
||||
* @param fieldType
|
||||
* the type of the field that stores the collection
|
||||
* @param idness
|
||||
* ID-ness of the property.
|
||||
* @param adapter
|
||||
* adapter to be used for individual items. can be null.
|
||||
*/
|
||||
public static <BeanT,PropT,ItemT,PackT>
|
||||
Lister<BeanT,PropT,ItemT,PackT> create(Type fieldType,ID idness, Adapter<Type,Class> adapter) {
|
||||
|
||||
Class rawType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(fieldType);
|
||||
Class itemType;
|
||||
|
||||
Lister l;
|
||||
if( rawType.isArray() ) {
|
||||
itemType = rawType.getComponentType();
|
||||
l = getArrayLister(itemType);
|
||||
} else
|
||||
if( Collection.class.isAssignableFrom(rawType) ) {
|
||||
Type bt = Utils.REFLECTION_NAVIGATOR.getBaseClass(fieldType,Collection.class);
|
||||
if(bt instanceof ParameterizedType)
|
||||
itemType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)bt).getActualTypeArguments()[0]);
|
||||
else
|
||||
itemType = Object.class;
|
||||
l = new CollectionLister(getImplClass(rawType));
|
||||
} else
|
||||
return null;
|
||||
|
||||
if(idness==ID.IDREF)
|
||||
l = new IDREFS(l,itemType);
|
||||
|
||||
if(adapter!=null)
|
||||
l = new AdaptedLister(l,adapter.adapterType);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
private static Class getImplClass(Class<?> fieldType) {
|
||||
return ClassFactory.inferImplClass(fieldType,COLLECTION_IMPL_CLASSES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache instances of {@link ArrayLister}s.
|
||||
*/
|
||||
private static final Map<Class,WeakReference<Lister>> arrayListerCache =
|
||||
Collections.synchronizedMap(new WeakHashMap<Class,WeakReference<Lister>>());
|
||||
|
||||
/**
|
||||
* Creates a lister for array type.
|
||||
*/
|
||||
private static Lister getArrayLister( Class componentType ) {
|
||||
Lister l=null;
|
||||
if(componentType.isPrimitive())
|
||||
l = primitiveArrayListers.get(componentType);
|
||||
else {
|
||||
WeakReference<Lister> wr = arrayListerCache.get(componentType);
|
||||
if(wr!=null)
|
||||
l = wr.get();
|
||||
if(l==null) {
|
||||
l = new ArrayLister(componentType);
|
||||
arrayListerCache.put(componentType,new WeakReference<Lister>(l));
|
||||
}
|
||||
}
|
||||
assert l!=null;
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Lister} for an array.
|
||||
*
|
||||
* <p>
|
||||
* Array packing is slower, but we expect this to be used less frequently than
|
||||
* the {@link CollectionLister}.
|
||||
*/
|
||||
private static final class ArrayLister<BeanT,ItemT> extends Lister<BeanT,ItemT[],ItemT,Pack<ItemT>> {
|
||||
|
||||
private final Class<ItemT> itemType;
|
||||
|
||||
public ArrayLister(Class<ItemT> itemType) {
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
public ListIterator<ItemT> iterator(final ItemT[] objects, XMLSerializer context) {
|
||||
return new ListIterator<ItemT>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public ItemT next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Pack startPacking(BeanT current, Accessor<BeanT, ItemT[]> acc) {
|
||||
return new Pack<ItemT>(itemType);
|
||||
}
|
||||
|
||||
public void addToPack(Pack<ItemT> objects, ItemT o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( Pack<ItemT> pack, BeanT bean, Accessor<BeanT,ItemT[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,ItemT[]> acc) throws AccessorException {
|
||||
acc.set(o,(ItemT[])Array.newInstance(itemType,0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final class Pack<ItemT> extends ArrayList<ItemT> {
|
||||
private final Class<ItemT> itemType;
|
||||
|
||||
public Pack(Class<ItemT> itemType) {
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
public ItemT[] build() {
|
||||
return super.toArray( (ItemT[])Array.newInstance(itemType,size()) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listers for the primitive type arrays, keyed by their primitive Class object.
|
||||
*/
|
||||
/*package*/ static final Map<Class,Lister> primitiveArrayListers = new HashMap<Class,Lister>();
|
||||
|
||||
static {
|
||||
// register primitive array listers
|
||||
PrimitiveArrayListerBoolean.register();
|
||||
PrimitiveArrayListerByte.register();
|
||||
PrimitiveArrayListerCharacter.register();
|
||||
PrimitiveArrayListerDouble.register();
|
||||
PrimitiveArrayListerFloat.register();
|
||||
PrimitiveArrayListerInteger.register();
|
||||
PrimitiveArrayListerLong.register();
|
||||
PrimitiveArrayListerShort.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Lister} for a collection
|
||||
*/
|
||||
public static final class CollectionLister<BeanT,T extends Collection> extends Lister<BeanT,T,Object,T> {
|
||||
|
||||
/**
|
||||
* Sometimes we need to create a new instance of a collection.
|
||||
* This is such an implementation class.
|
||||
*/
|
||||
private final Class<? extends T> implClass;
|
||||
|
||||
public CollectionLister(Class<? extends T> implClass) {
|
||||
this.implClass = implClass;
|
||||
}
|
||||
|
||||
public ListIterator iterator(T collection, XMLSerializer context) {
|
||||
final Iterator itr = collection.iterator();
|
||||
return new ListIterator() {
|
||||
public boolean hasNext() {
|
||||
return itr.hasNext();
|
||||
}
|
||||
public Object next() {
|
||||
return itr.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public T startPacking(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
|
||||
T collection = acc.get(bean);
|
||||
if(collection==null) {
|
||||
collection = ClassFactory.create(implClass);
|
||||
if(!acc.isAdapted())
|
||||
acc.set(bean,collection);
|
||||
}
|
||||
collection.clear();
|
||||
return collection;
|
||||
}
|
||||
|
||||
public void addToPack(T collection, Object o) {
|
||||
collection.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( T collection, BeanT bean, Accessor<BeanT,T> acc ) throws AccessorException {
|
||||
// this needs to be done in the endPacking, because
|
||||
// sometimes the accessor uses an adapter, and the adapter needs to see
|
||||
// the whole thing.
|
||||
|
||||
// but always doing so causes a problem when this collection property
|
||||
// is getter-only
|
||||
|
||||
// invoke set when possible (see Issue 488)
|
||||
try {
|
||||
if (acc.isAdapted()) {
|
||||
acc.set(bean,collection);
|
||||
}
|
||||
} catch (AccessorException ae) {
|
||||
if(acc.isAdapted()) throw ae;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
|
||||
T collection = acc.get(bean);
|
||||
if(collection == null) {
|
||||
return;
|
||||
}
|
||||
collection.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Lister} for IDREFS.
|
||||
*/
|
||||
private static final class IDREFS<BeanT,PropT> extends Lister<BeanT,PropT,String,IDREFS<BeanT,PropT>.Pack> {
|
||||
private final Lister<BeanT,PropT,Object,Object> core;
|
||||
/**
|
||||
* Expected type to which IDREF resolves to.
|
||||
*/
|
||||
private final Class itemType;
|
||||
|
||||
public IDREFS(Lister core, Class itemType) {
|
||||
this.core = core;
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
public ListIterator<String> iterator(PropT prop, XMLSerializer context) {
|
||||
final ListIterator i = core.iterator(prop,context);
|
||||
|
||||
return new IDREFSIterator(i, context);
|
||||
}
|
||||
|
||||
public Pack startPacking(BeanT bean, Accessor<BeanT, PropT> acc) {
|
||||
return new Pack(bean,acc);
|
||||
}
|
||||
|
||||
public void addToPack(Pack pack, String item) {
|
||||
pack.add(item);
|
||||
}
|
||||
|
||||
public void endPacking(Pack pack, BeanT bean, Accessor<BeanT, PropT> acc) {
|
||||
}
|
||||
|
||||
public void reset(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException {
|
||||
core.reset(bean,acc);
|
||||
}
|
||||
|
||||
/**
|
||||
* PackT for this lister.
|
||||
*/
|
||||
private class Pack implements Patcher {
|
||||
private final BeanT bean;
|
||||
private final List<String> idrefs = new ArrayList<String>();
|
||||
private final UnmarshallingContext context;
|
||||
private final Accessor<BeanT,PropT> acc;
|
||||
private final LocatorEx location;
|
||||
|
||||
public Pack(BeanT bean, Accessor<BeanT,PropT> acc) {
|
||||
this.bean = bean;
|
||||
this.acc = acc;
|
||||
this.context = UnmarshallingContext.getInstance();
|
||||
this.location = new LocatorEx.Snapshot(context.getLocator());
|
||||
context.addPatcher(this);
|
||||
}
|
||||
|
||||
public void add(String item) {
|
||||
idrefs.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves IDREFS and fill in the actual array.
|
||||
*/
|
||||
public void run() throws SAXException {
|
||||
try {
|
||||
Object pack = core.startPacking(bean,acc);
|
||||
|
||||
for( String id : idrefs ) {
|
||||
Callable callable = context.getObjectFromId(id,itemType);
|
||||
Object t;
|
||||
|
||||
try {
|
||||
t = (callable!=null) ? callable.call() : null;
|
||||
} catch (SAXException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new SAXException2(e);
|
||||
}
|
||||
|
||||
if(t==null) {
|
||||
context.errorUnresolvedIDREF(bean,id,location);
|
||||
} else {
|
||||
TODO.prototype(); // TODO: check if the type of t is proper.
|
||||
core.addToPack(pack,t);
|
||||
}
|
||||
}
|
||||
|
||||
core.endPacking(pack,bean,acc);
|
||||
} catch (AccessorException e) {
|
||||
context.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Iterator} for IDREFS lister.
|
||||
*
|
||||
* <p>
|
||||
* Only in ArrayElementProperty we need to get the actual
|
||||
* referenced object. This is a kind of ugly way to make that work.
|
||||
*/
|
||||
public static final class IDREFSIterator implements ListIterator<String> {
|
||||
private final ListIterator i;
|
||||
private final XMLSerializer context;
|
||||
private Object last;
|
||||
|
||||
private IDREFSIterator(ListIterator i, XMLSerializer context) {
|
||||
this.i = i;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return i.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last referenced object (not just its ID)
|
||||
*/
|
||||
public Object last() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public String next() throws SAXException, JAXBException {
|
||||
last = i.next();
|
||||
String id = context.grammar.getBeanInfo(last,true).getId(last,context);
|
||||
if(id==null) {
|
||||
context.errorMissingId(last);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the special {@link Lister} used to recover from an error.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A,B,C,D> Lister<A,B,C,D> getErrorInstance() {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
public static final Lister ERROR = new Lister() {
|
||||
public ListIterator iterator(Object o, XMLSerializer context) {
|
||||
return EMPTY_ITERATOR;
|
||||
}
|
||||
|
||||
public Object startPacking(Object o, Accessor accessor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addToPack(Object o, Object o1) {
|
||||
}
|
||||
|
||||
public void endPacking(Object o, Object o1, Accessor accessor) {
|
||||
}
|
||||
|
||||
public void reset(Object o, Accessor accessor) {
|
||||
}
|
||||
};
|
||||
|
||||
private static final ListIterator EMPTY_ITERATOR = new ListIterator() {
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
};
|
||||
|
||||
private static final Class[] COLLECTION_IMPL_CLASSES = new Class[] {
|
||||
ArrayList.class,
|
||||
LinkedList.class,
|
||||
HashSet.class,
|
||||
TreeSet.class,
|
||||
Stack.class
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Message resources
|
||||
*/
|
||||
enum Messages {
|
||||
// Accessor
|
||||
UNABLE_TO_ACCESS_NON_PUBLIC_FIELD, // 2 args
|
||||
UNASSIGNABLE_TYPE, // 2 args
|
||||
NO_SETTER, // 1 arg
|
||||
NO_GETTER, // 1 arg
|
||||
;
|
||||
|
||||
private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName());
|
||||
|
||||
public String toString() {
|
||||
return format();
|
||||
}
|
||||
|
||||
public String format( Object... args ) {
|
||||
return MessageFormat.format( rb.getString(name()), args );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
|
||||
/**
|
||||
* {@link Accessor} wrapper that replaces a null with an empty collection.
|
||||
*
|
||||
* <p>
|
||||
* This is so that JAX-WS property accessor will work like an ordinary getter.
|
||||
*
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class NullSafeAccessor<B,V,P> extends Accessor<B,V> {
|
||||
private final Accessor<B,V> core;
|
||||
private final Lister<B,V,?,P> lister;
|
||||
|
||||
public NullSafeAccessor(Accessor<B,V> core, Lister<B,V,?,P> lister) {
|
||||
super(core.getValueType());
|
||||
this.core = core;
|
||||
this.lister = lister;
|
||||
}
|
||||
|
||||
public V get(B bean) throws AccessorException {
|
||||
V v = core.get(bean);
|
||||
if(v==null) {
|
||||
// creates a new object
|
||||
P pack = lister.startPacking(bean,core);
|
||||
lister.endPacking(pack,bean,core);
|
||||
v = core.get(bean);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public void set(B bean, V value) throws AccessorException {
|
||||
core.set(bean,value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerBoolean<BeanT> extends Lister<BeanT,boolean[],Boolean,PrimitiveArrayListerBoolean.BooleanArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerBoolean() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Boolean.TYPE,new PrimitiveArrayListerBoolean());
|
||||
}
|
||||
|
||||
public ListIterator<Boolean> iterator(final boolean[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Boolean>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Boolean next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public BooleanArrayPack startPacking(BeanT current, Accessor<BeanT, boolean[]> acc) {
|
||||
return new BooleanArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(BooleanArrayPack objects, Boolean o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( BooleanArrayPack pack, BeanT bean, Accessor<BeanT,boolean[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,boolean[]> acc) throws AccessorException {
|
||||
acc.set(o,new boolean[0]);
|
||||
}
|
||||
|
||||
static final class BooleanArrayPack {
|
||||
boolean[] buf = new boolean[16];
|
||||
int size;
|
||||
|
||||
void add(Boolean b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
boolean[] nb = new boolean[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
boolean[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
boolean[] r = new boolean[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
*
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
*/
|
||||
final class PrimitiveArrayListerByte<BeanT> extends Lister<BeanT,byte[],Byte,PrimitiveArrayListerByte.ByteArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerByte() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Byte.TYPE,new PrimitiveArrayListerByte());
|
||||
}
|
||||
|
||||
public ListIterator<Byte> iterator(final byte[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Byte>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Byte next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ByteArrayPack startPacking(BeanT current, Accessor<BeanT, byte[]> acc) {
|
||||
return new ByteArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(ByteArrayPack objects, Byte o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( ByteArrayPack pack, BeanT bean, Accessor<BeanT,byte[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,byte[]> acc) throws AccessorException {
|
||||
acc.set(o,new byte[0]);
|
||||
}
|
||||
|
||||
static final class ByteArrayPack {
|
||||
byte[] buf = new byte[16];
|
||||
int size;
|
||||
|
||||
void add(Byte b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
byte[] nb = new byte[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
byte[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
byte[] r = new byte[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerCharacter<BeanT> extends Lister<BeanT,char[],Character,PrimitiveArrayListerCharacter.CharacterArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerCharacter() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Character.TYPE,new PrimitiveArrayListerCharacter());
|
||||
}
|
||||
|
||||
public ListIterator<Character> iterator(final char[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Character>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Character next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public CharacterArrayPack startPacking(BeanT current, Accessor<BeanT, char[]> acc) {
|
||||
return new CharacterArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(CharacterArrayPack objects, Character o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( CharacterArrayPack pack, BeanT bean, Accessor<BeanT,char[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,char[]> acc) throws AccessorException {
|
||||
acc.set(o,new char[0]);
|
||||
}
|
||||
|
||||
static final class CharacterArrayPack {
|
||||
char[] buf = new char[16];
|
||||
int size;
|
||||
|
||||
void add(Character b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
char[] nb = new char[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
char[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
char[] r = new char[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerDouble<BeanT> extends Lister<BeanT,double[],Double,PrimitiveArrayListerDouble.DoubleArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerDouble() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Double.TYPE,new PrimitiveArrayListerDouble());
|
||||
}
|
||||
|
||||
public ListIterator<Double> iterator(final double[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Double>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Double next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public DoubleArrayPack startPacking(BeanT current, Accessor<BeanT, double[]> acc) {
|
||||
return new DoubleArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(DoubleArrayPack objects, Double o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( DoubleArrayPack pack, BeanT bean, Accessor<BeanT,double[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,double[]> acc) throws AccessorException {
|
||||
acc.set(o,new double[0]);
|
||||
}
|
||||
|
||||
static final class DoubleArrayPack {
|
||||
double[] buf = new double[16];
|
||||
int size;
|
||||
|
||||
void add(Double b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
double[] nb = new double[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
double[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
double[] r = new double[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerFloat<BeanT> extends Lister<BeanT,float[],Float,PrimitiveArrayListerFloat.FloatArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerFloat() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Float.TYPE,new PrimitiveArrayListerFloat());
|
||||
}
|
||||
|
||||
public ListIterator<Float> iterator(final float[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Float>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Float next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public FloatArrayPack startPacking(BeanT current, Accessor<BeanT, float[]> acc) {
|
||||
return new FloatArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(FloatArrayPack objects, Float o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( FloatArrayPack pack, BeanT bean, Accessor<BeanT,float[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,float[]> acc) throws AccessorException {
|
||||
acc.set(o,new float[0]);
|
||||
}
|
||||
|
||||
static final class FloatArrayPack {
|
||||
float[] buf = new float[16];
|
||||
int size;
|
||||
|
||||
void add(Float b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
float[] nb = new float[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
float[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
float[] r = new float[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerInteger<BeanT> extends Lister<BeanT,int[],Integer,PrimitiveArrayListerInteger.IntegerArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerInteger() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Integer.TYPE,new PrimitiveArrayListerInteger());
|
||||
}
|
||||
|
||||
public ListIterator<Integer> iterator(final int[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Integer>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Integer next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IntegerArrayPack startPacking(BeanT current, Accessor<BeanT, int[]> acc) {
|
||||
return new IntegerArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(IntegerArrayPack objects, Integer o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( IntegerArrayPack pack, BeanT bean, Accessor<BeanT,int[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,int[]> acc) throws AccessorException {
|
||||
acc.set(o,new int[0]);
|
||||
}
|
||||
|
||||
static final class IntegerArrayPack {
|
||||
int[] buf = new int[16];
|
||||
int size;
|
||||
|
||||
void add(Integer b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
int[] nb = new int[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
int[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
int[] r = new int[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerLong<BeanT> extends Lister<BeanT,long[],Long,PrimitiveArrayListerLong.LongArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerLong() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Long.TYPE,new PrimitiveArrayListerLong());
|
||||
}
|
||||
|
||||
public ListIterator<Long> iterator(final long[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Long>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Long next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public LongArrayPack startPacking(BeanT current, Accessor<BeanT, long[]> acc) {
|
||||
return new LongArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(LongArrayPack objects, Long o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( LongArrayPack pack, BeanT bean, Accessor<BeanT,long[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,long[]> acc) throws AccessorException {
|
||||
acc.set(o,new long[0]);
|
||||
}
|
||||
|
||||
static final class LongArrayPack {
|
||||
long[] buf = new long[16];
|
||||
int size;
|
||||
|
||||
void add(Long b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
long[] nb = new long[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
long[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
long[] r = new long[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
|
||||
/**
|
||||
* {@link Lister} for primitive type arrays.
|
||||
* <p><b>
|
||||
* Auto-generated, do not edit.
|
||||
* </b></p>
|
||||
* <p>
|
||||
* B y t e ArrayLister is used as the master to generate the rest of the
|
||||
* lister classes. Do not modify the generated copies.
|
||||
* </p>
|
||||
*/
|
||||
final class PrimitiveArrayListerShort<BeanT> extends Lister<BeanT,short[],Short,PrimitiveArrayListerShort.ShortArrayPack> {
|
||||
|
||||
private PrimitiveArrayListerShort() {
|
||||
}
|
||||
|
||||
/*package*/ static void register() {
|
||||
Lister.primitiveArrayListers.put(Short.TYPE,new PrimitiveArrayListerShort());
|
||||
}
|
||||
|
||||
public ListIterator<Short> iterator(final short[] objects, XMLSerializer context) {
|
||||
return new ListIterator<Short>() {
|
||||
int idx=0;
|
||||
public boolean hasNext() {
|
||||
return idx<objects.length;
|
||||
}
|
||||
|
||||
public Short next() {
|
||||
return objects[idx++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ShortArrayPack startPacking(BeanT current, Accessor<BeanT, short[]> acc) {
|
||||
return new ShortArrayPack();
|
||||
}
|
||||
|
||||
public void addToPack(ShortArrayPack objects, Short o) {
|
||||
objects.add(o);
|
||||
}
|
||||
|
||||
public void endPacking( ShortArrayPack pack, BeanT bean, Accessor<BeanT,short[]> acc ) throws AccessorException {
|
||||
acc.set(bean,pack.build());
|
||||
}
|
||||
|
||||
public void reset(BeanT o,Accessor<BeanT,short[]> acc) throws AccessorException {
|
||||
acc.set(o,new short[0]);
|
||||
}
|
||||
|
||||
static final class ShortArrayPack {
|
||||
short[] buf = new short[16];
|
||||
int size;
|
||||
|
||||
void add(Short b) {
|
||||
if(buf.length==size) {
|
||||
// realloc
|
||||
short[] nb = new short[buf.length*2];
|
||||
System.arraycopy(buf,0,nb,0,buf.length);
|
||||
buf = nb;
|
||||
}
|
||||
if(b!=null)
|
||||
buf[size++] = b;
|
||||
}
|
||||
|
||||
short[] build() {
|
||||
if(buf.length==size)
|
||||
// if we are lucky enough
|
||||
return buf;
|
||||
|
||||
short[] r = new short[size];
|
||||
System.arraycopy(buf,0,r,0,size);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.istack.internal.SAXException2;
|
||||
import com.sun.xml.internal.bind.WhiteSpaceProcessor;
|
||||
import com.sun.xml.internal.bind.api.AccessorException;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimeNonElementRef;
|
||||
import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
import com.sun.xml.internal.bind.v2.runtime.Transducer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
|
||||
import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedTransducedAccessorFactory;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Patcher;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* {@link Accessor} and {@link Transducer} combined into one object.
|
||||
*
|
||||
* <p>
|
||||
* This allows efficient conversions between primitive values and
|
||||
* String without using boxing.
|
||||
*
|
||||
* <p>
|
||||
* This abstraction only works for a single-value property.
|
||||
*
|
||||
* <p>
|
||||
* An instance of {@link TransducedAccessor} implicitly holds a
|
||||
* field of the {@code BeanT} that the accessors access.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public abstract class TransducedAccessor<BeanT> {
|
||||
|
||||
/**
|
||||
* @see Transducer#useNamespace()
|
||||
*/
|
||||
public boolean useNamespace() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the value of the field and declares the namespace URIs used in
|
||||
* the value.
|
||||
*
|
||||
* @see Transducer#declareNamespace(Object, XMLSerializer)
|
||||
*/
|
||||
public void declareNamespace( BeanT o, XMLSerializer w ) throws AccessorException, SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the responsible field of the given bean to the writer.
|
||||
*
|
||||
* <p>
|
||||
* Use {@link XMLSerializer#getInstance()} to access to the namespace bindings
|
||||
*
|
||||
* @return
|
||||
* if the accessor didn't yield a value, return null.
|
||||
*/
|
||||
public abstract @Nullable CharSequence print(@NotNull BeanT o) throws AccessorException, SAXException;
|
||||
|
||||
/**
|
||||
* Parses the text value into the responsible field of the given bean.
|
||||
*
|
||||
* <p>
|
||||
* Use {@link UnmarshallingContext#getInstance()} to access to the namespace bindings
|
||||
*
|
||||
* @throws AccessorException
|
||||
* if the transducer is used to parse an user bean that uses {@link XmlValue},
|
||||
* then this exception may occur when it tries to set the leaf value to the bean.
|
||||
* @throws RuntimeException
|
||||
* if the lexical form is incorrect. The method may throw a RuntimeException,
|
||||
* but it shouldn't cause the entire unmarshalling to fail.
|
||||
* @throws SAXException
|
||||
* if the parse method found an error, the error is reported, and then
|
||||
* the processing is aborted.
|
||||
*/
|
||||
public abstract void parse(BeanT o, CharSequence lexical) throws AccessorException, SAXException;
|
||||
|
||||
/**
|
||||
* Checks if the field has a value.
|
||||
*/
|
||||
public abstract boolean hasValue(BeanT o) throws AccessorException;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@link TransducedAccessor} appropriately configured for
|
||||
* the given property.
|
||||
*
|
||||
* <p>
|
||||
* This allows the implementation to use an optimized code.
|
||||
*/
|
||||
public static <T> TransducedAccessor<T> get(JAXBContextImpl context, RuntimeNonElementRef ref) {
|
||||
Transducer xducer = RuntimeModelBuilder.createTransducer(ref);
|
||||
RuntimePropertyInfo prop = ref.getSource();
|
||||
|
||||
if(prop.isCollection()) {
|
||||
return new ListTransducedAccessorImpl(xducer,prop.getAccessor(),
|
||||
Lister.create(Utils.REFLECTION_NAVIGATOR.erasure(prop.getRawType()), prop.id(), prop.getAdapter()));
|
||||
}
|
||||
|
||||
if(prop.id()==ID.IDREF)
|
||||
return new IDREFTransducedAccessorImpl(prop.getAccessor());
|
||||
|
||||
if(xducer.isDefault() && context != null && !context.fastBoot) {
|
||||
TransducedAccessor xa = OptimizedTransducedAccessorFactory.get(prop);
|
||||
if(xa!=null) return xa;
|
||||
}
|
||||
|
||||
if(xducer.useNamespace())
|
||||
return new CompositeContextDependentTransducedAccessorImpl( context, xducer, prop.getAccessor() );
|
||||
else
|
||||
return new CompositeTransducedAccessorImpl( context, xducer, prop.getAccessor() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to write the value as a text inside an element
|
||||
* without any attributes.
|
||||
* Can be overridden for improved performance.
|
||||
*
|
||||
* <p>
|
||||
* The callee assumes that there's an associated value in the field.
|
||||
* No @xsi:type handling is expected.
|
||||
*/
|
||||
public abstract void writeLeafElement(XMLSerializer w, Name tagName, BeanT o, String fieldName) throws SAXException, AccessorException, IOException, XMLStreamException;
|
||||
|
||||
/**
|
||||
* Invokes one of the {@link XMLSerializer#text(String, String)} method
|
||||
* with the representation of data bested suited for this transduced accessor.
|
||||
*/
|
||||
public abstract void writeText(XMLSerializer w, BeanT o, String fieldName) throws AccessorException, SAXException, IOException, XMLStreamException;
|
||||
|
||||
static class CompositeContextDependentTransducedAccessorImpl<BeanT,ValueT> extends CompositeTransducedAccessorImpl<BeanT,ValueT> {
|
||||
public CompositeContextDependentTransducedAccessorImpl(JAXBContextImpl context,Transducer<ValueT> xducer, Accessor<BeanT,ValueT> acc) {
|
||||
super(context,xducer,acc);
|
||||
assert xducer.useNamespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useNamespace() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareNamespace(BeanT bean, XMLSerializer w) throws AccessorException {
|
||||
ValueT o = acc.get(bean);
|
||||
if(o!=null)
|
||||
xducer.declareNamespace(o,w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, BeanT o, String fieldName) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
w.startElement(tagName,null);
|
||||
declareNamespace(o,w);
|
||||
w.endNamespaceDecls(null);
|
||||
w.endAttributes();
|
||||
xducer.writeText(w,acc.get(o),fieldName);
|
||||
w.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link TransducedAccessor} that
|
||||
* simply combines a {@link Transducer} and {@link Accessor}.
|
||||
*/
|
||||
public static class CompositeTransducedAccessorImpl<BeanT,ValueT> extends TransducedAccessor<BeanT> {
|
||||
protected final Transducer<ValueT> xducer;
|
||||
protected final Accessor<BeanT,ValueT> acc;
|
||||
|
||||
public CompositeTransducedAccessorImpl(JAXBContextImpl context, Transducer<ValueT> xducer, Accessor<BeanT,ValueT> acc) {
|
||||
this.xducer = xducer;
|
||||
this.acc = acc.optimize(context);
|
||||
}
|
||||
|
||||
public CharSequence print(BeanT bean) throws AccessorException {
|
||||
ValueT o = acc.get(bean);
|
||||
if(o==null) return null;
|
||||
return xducer.print(o);
|
||||
}
|
||||
|
||||
public void parse(BeanT bean, CharSequence lexical) throws AccessorException, SAXException {
|
||||
acc.set(bean,xducer.parse(lexical));
|
||||
}
|
||||
|
||||
public boolean hasValue(BeanT bean) throws AccessorException {
|
||||
return acc.getUnadapted(bean)!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLeafElement(XMLSerializer w, Name tagName, BeanT o, String fieldName) throws SAXException, AccessorException, IOException, XMLStreamException {
|
||||
xducer.writeLeafElement(w,tagName,acc.get(o),fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeText(XMLSerializer w, BeanT o, String fieldName) throws AccessorException, SAXException, IOException, XMLStreamException {
|
||||
xducer.writeText(w,acc.get(o),fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TransducedAccessor} for IDREF.
|
||||
*
|
||||
* BeanT: the type of the bean that contains this the IDREF field.
|
||||
* TargetT: the type of the bean pointed by IDREF.
|
||||
*/
|
||||
private static final class IDREFTransducedAccessorImpl<BeanT,TargetT> extends DefaultTransducedAccessor<BeanT> {
|
||||
private final Accessor<BeanT,TargetT> acc;
|
||||
/**
|
||||
* The object that an IDREF resolves to should be
|
||||
* assignable to this type.
|
||||
*/
|
||||
private final Class<TargetT> targetType;
|
||||
|
||||
public IDREFTransducedAccessorImpl(Accessor<BeanT, TargetT> acc) {
|
||||
this.acc = acc;
|
||||
this.targetType = acc.getValueType();
|
||||
}
|
||||
|
||||
public String print(BeanT bean) throws AccessorException, SAXException {
|
||||
TargetT target = acc.get(bean);
|
||||
if(target==null) return null;
|
||||
|
||||
XMLSerializer w = XMLSerializer.getInstance();
|
||||
try {
|
||||
String id = w.grammar.getBeanInfo(target,true).getId(target,w);
|
||||
if(id==null)
|
||||
w.errorMissingId(target);
|
||||
return id;
|
||||
} catch (JAXBException e) {
|
||||
w.reportError(null,e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void assign( BeanT bean, TargetT t, UnmarshallingContext context ) throws AccessorException {
|
||||
if(!targetType.isInstance(t))
|
||||
context.handleError(Messages.UNASSIGNABLE_TYPE.format(targetType,t.getClass()));
|
||||
else
|
||||
acc.set(bean,t);
|
||||
}
|
||||
|
||||
public void parse(final BeanT bean, CharSequence lexical) throws AccessorException, SAXException {
|
||||
final String idref = WhiteSpaceProcessor.trim(lexical).toString();
|
||||
final UnmarshallingContext context = UnmarshallingContext.getInstance();
|
||||
|
||||
final Callable callable = context.getObjectFromId(idref,acc.valueType);
|
||||
if(callable==null) {
|
||||
// the IDResolver decided to abort it now
|
||||
context.errorUnresolvedIDREF(bean,idref,context.getLocator());
|
||||
return;
|
||||
}
|
||||
|
||||
TargetT t;
|
||||
try {
|
||||
t = (TargetT)callable.call();
|
||||
} catch (SAXException e) {// from callable.call
|
||||
throw e;
|
||||
} catch (RuntimeException e) {// from callable.call
|
||||
throw e;
|
||||
} catch (Exception e) {// from callable.call
|
||||
throw new SAXException2(e);
|
||||
}
|
||||
if(t!=null) {
|
||||
assign(bean,t,context);
|
||||
} else {
|
||||
// try again later
|
||||
final LocatorEx loc = new LocatorEx.Snapshot(context.getLocator());
|
||||
context.addPatcher(new Patcher() {
|
||||
public void run() throws SAXException {
|
||||
try {
|
||||
TargetT t = (TargetT)callable.call();
|
||||
if(t==null) {
|
||||
context.errorUnresolvedIDREF(bean,idref,loc);
|
||||
} else {
|
||||
assign(bean,t,context);
|
||||
}
|
||||
} catch (AccessorException e) {
|
||||
context.handleError(e);
|
||||
} catch (SAXException e) {// from callable.call
|
||||
throw e;
|
||||
} catch (RuntimeException e) {// from callable.call
|
||||
throw e;
|
||||
} catch (Exception e) {// from callable.call
|
||||
throw new SAXException2(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasValue(BeanT bean) throws AccessorException {
|
||||
return acc.get(bean)!=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, 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.reflect;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.model.nav.Navigator;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utils class.
|
||||
*
|
||||
* WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
|
||||
*
|
||||
* Has *package private* access to avoid inappropriate usage.
|
||||
*/
|
||||
final class Utils {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Utils.class.getName());
|
||||
|
||||
/**
|
||||
* static ReflectionNavigator field to avoid usage of reflection every time we use it.
|
||||
*/
|
||||
static final Navigator<Type, Class, Field, Method> REFLECTION_NAVIGATOR;
|
||||
|
||||
static { // we statically initializing REFLECTION_NAVIGATOR property
|
||||
try {
|
||||
final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
|
||||
|
||||
// requires accessClassInPackage privilege
|
||||
final Method getInstance = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Method>() {
|
||||
@Override
|
||||
public Method run() {
|
||||
try {
|
||||
Method getInstance = refNav.getDeclaredMethod("getInstance");
|
||||
getInstance.setAccessible(true);
|
||||
return getInstance;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Can't find ReflectionNavigator class");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
|
||||
} catch (SecurityException e) {
|
||||
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor to avoid util class instantiating
|
||||
*/
|
||||
private Utils() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.reflect.opt;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sun.xml.internal.bind.Util;
|
||||
import com.sun.xml.internal.bind.v2.bytecode.ClassTailor;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class AccessorInjector {
|
||||
|
||||
private static final Logger logger = Util.getClassLogger();
|
||||
|
||||
protected static final boolean noOptimize =
|
||||
Util.getSystemProperty(ClassTailor.class.getName()+".noOptimize")!=null;
|
||||
|
||||
static {
|
||||
if(noOptimize)
|
||||
logger.info("The optimized code generation is disabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the optimized class and returns it.
|
||||
*
|
||||
* @return null
|
||||
* if it fails for some reason.
|
||||
*/
|
||||
public static Class<?> prepare(
|
||||
Class beanClass, String templateClassName, String newClassName, String... replacements ) {
|
||||
|
||||
if(noOptimize)
|
||||
return null;
|
||||
|
||||
try {
|
||||
ClassLoader cl = SecureLoader.getClassClassLoader(beanClass);
|
||||
if(cl==null) return null; // how do I inject classes to this "null" class loader? for now, back off.
|
||||
|
||||
Class c = Injector.find(cl,newClassName);
|
||||
if (c==null) {
|
||||
byte[] image = tailor(templateClassName,newClassName,replacements);
|
||||
if (image==null) {
|
||||
return null;
|
||||
}
|
||||
c = Injector.inject(cl,newClassName,image);
|
||||
if (c == null) {
|
||||
Injector.find(cl, newClassName);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
} catch(SecurityException e) {
|
||||
// we don't have enough permission to do this
|
||||
logger.log(Level.INFO,"Unable to create an optimized TransducedAccessor ",e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Customizes a class file by replacing constant pools.
|
||||
*
|
||||
* @param templateClassName
|
||||
* The resource that contains the template class file.
|
||||
* @param replacements
|
||||
* A list of pair of strings that specify the substitution
|
||||
* {@code String[]{search_0, replace_0, search_1, replace_1, ..., search_n, replace_n }
|
||||
*
|
||||
* The search strings found in the constant pool will be replaced by the corresponding
|
||||
* replacement string.
|
||||
*/
|
||||
private static byte[] tailor( String templateClassName, String newClassName, String... replacements ) {
|
||||
InputStream resource;
|
||||
if(CLASS_LOADER!=null)
|
||||
resource = CLASS_LOADER.getResourceAsStream(templateClassName+".class");
|
||||
else
|
||||
resource = ClassLoader.getSystemResourceAsStream(templateClassName+".class");
|
||||
if(resource==null)
|
||||
return null;
|
||||
|
||||
return ClassTailor.tailor(resource,templateClassName,newClassName,replacements);
|
||||
}
|
||||
|
||||
private static final ClassLoader CLASS_LOADER = SecureLoader.getClassClassLoader(AccessorInjector.class);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.reflect.opt;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
|
||||
|
||||
/**
|
||||
* Used by {@link TransducedAccessor} templates.
|
||||
*
|
||||
* <p>
|
||||
* Fields needs to have a distinctive name.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class Bean {
|
||||
public boolean f_boolean;
|
||||
public char f_char;
|
||||
public byte f_byte;
|
||||
public short f_short;
|
||||
int f_int;
|
||||
public long f_long;
|
||||
public float f_float;
|
||||
public double f_double;
|
||||
/**
|
||||
* Field of a reference type.
|
||||
* We need a distinctive type so that it can be easily replaced.
|
||||
*/
|
||||
public Ref f_ref;
|
||||
|
||||
public boolean get_boolean() { throw new UnsupportedOperationException(); }
|
||||
public void set_boolean(boolean b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public char get_char() { throw new UnsupportedOperationException(); }
|
||||
public void set_char(char b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public byte get_byte() { throw new UnsupportedOperationException(); }
|
||||
public void set_byte(byte b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public short get_short() { throw new UnsupportedOperationException(); }
|
||||
public void set_short(short b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public int get_int() { throw new UnsupportedOperationException(); }
|
||||
public void set_int(int b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public long get_long() { throw new UnsupportedOperationException(); }
|
||||
public void set_long(long b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public float get_float() { throw new UnsupportedOperationException(); }
|
||||
public void set_float(float b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public double get_double() { throw new UnsupportedOperationException(); }
|
||||
public void set_double(double b) { throw new UnsupportedOperationException(); }
|
||||
|
||||
public Ref get_ref() { throw new UnsupportedOperationException(); }
|
||||
public void set_ref(Ref r) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user