feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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&lt;->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&lt;->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;
}
}

View File

@@ -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();
}

View 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);
}
}

View File

@@ -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.
}
}
}

View File

@@ -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();
}
}

View 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();
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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";
}

View File

@@ -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 );
}
}

View File

@@ -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);
}
}
}

View 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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&lt;->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);
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View 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);
}

View 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() {
}
}

View File

@@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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]);
}
}

View File

@@ -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 );
}
}

View File

@@ -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 &lt;
*
* @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('&',"&amp;",false);
add('<',"&lt;",false);
add('>',"&gt;",false);
add('"',"&quot;",true);
add('\t',"&#x9;",true);
add('\r',"&#xD;",false);
add('\n',"&#xA;",true);
}
private static void add(char c, String s, boolean attOnly) {
byte[] image = UTF8XmlOutput.toBytes(s);
attributeEntities[c] = image;
if(!attOnly)
entities[c] = image;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
};
}

View File

@@ -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();
}

View File

@@ -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));
}
}

View File

@@ -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();
}
});
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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];
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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 '&amp;' 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 '&amp;' or '>')
* @param needsSeparatingWhitespace
*/
public void text( Pcdata value, boolean needsSeparatingWhitespace ) throws IOException, SAXException, XMLStreamException;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
}
}}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 &lt;items> and &lt;/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 &lt;entry> and &lt;/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;
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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.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() {
}
}

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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
};
}

View File

@@ -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 );
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View 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.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() {
}
}

View File

@@ -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);
}

View File

@@ -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