jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/000077500000000000000000000000001251656754200224505ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/.gitignore000066400000000000000000000002351251656754200244400ustar00rootroot00000000000000# use glob syntax. syntax: glob *.class *~ *.bak *.off *.old .DS_Store # building target # Eclipse .classpath .project .settings # IDEA *.iml *.ipr *.iws jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/README.md000066400000000000000000000201321251656754200237250ustar00rootroot00000000000000# Overview This projects contains [Jackson](http://wiki.fasterxml.com/JacksonHome) extension component for reading and writing [XML](http://en.wikipedia.org/wiki/Xml) encoded data. Further, the goal is to emulate how [JAXB](http://en.wikipedia.org/wiki/JAXB) data-binding works with "Code-first" approach (that is, no support is added for "Schema-first" approach). Support for JAXB annotations is provided by [JAXB annotation module](https://github.com/FasterXML/jackson-module-jaxb-annotations); this module provides low-level abstractions (`JsonParser`, `JsonGenerator`, `JsonFactory`) as well as small number of higher level overrides needed to make data-binding work. It is worth noting, however, that the goal is NOT to be full JAXB clone; or to be general purpose XML toolkit. Specifically: * While XML serialization should ideally be similar to JAXB output, deviations are not necessarily considered bugs -- we do "best-effort" matching * What should be guaranteed is that any XML written using this module must be readable using module as well: that is, we do aim for full XML serialization. * From above: there are XML constructs that module will not be able to handle; including some cases JAXB supports * This module may, however, also support constructs and use cases JAXB does not handle: specifically, rich type and object id support of Jackson are supported. [![Build Status](https://fasterxml.ci.cloudbees.com/job/jackson-dataformat-xml-master/badge/icon)](https://fasterxml.ci.cloudbees.com/job/jackson-dataformat-xml-master/) # Status As of version 2.3, module is fully functional and considered production ready. ## Maven dependency To use Jackson 2.x compatible version of this extension on Maven-based projects, use following dependency: ```xml com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.4.0 ``` (or whatever version is most up-to-date at the moment) Also: you usually also want to make sure that XML library in use is [Woodstox](http://wiki.fasterxml.com/WoodstoxHome) since it is not only faster than Stax implementation JDK provides, but also works better and avoids some known issues like adding unnecessary namespace prefixes. You can do this by adding this in your `pom.xml`: ```xml org.codehaus.woodstox woodstox-core-asl 4.1.4 ``` # Usage Although module implements low-level (`JsonFactory` / `JsonParser` / `JsonGenerator`) abstractions, most usage is through data-binding level. This because a small number of work-arounds have been added at data-binding level, to work around XML peculiarities: that is, stream of `JsonToken`s that parser produces has idiosyncracies that need special handling. Usually you either create `XmlMapper` simply by: ```java XmlMapper mapper = new XmlMapper(); ``` but in case you need to configure settings, you will want to do: ```java JacksonXmlModule module = new JacksonXmlModule(); // and then configure, for example: module.setDefaultUseWrapper(false); XmlMapper xmlMapper = new XmlMapper(module); // and you can also configure AnnotationIntrospectors etc here: ``` as many features that `XmlMapper` needs are provided by `JacksonXmlModule`; default `XmlMapper` simply constructs module with default settings. ## Serializing POJOs as XML Serialization is done very similar to JSON serialization: all that needs to change is `ObjectMapper` instance to use: ```java // Important: create XmlMapper; it will use proper factories, workarounds ObjectMapper xmlMapper = new XmlMapper(); String xml = xmlMapper.writeValueAsString(new Simple()); // or xmlMapper.writeValue(new File("/tmp/stuff.json"), new Simple()); ``` and with POJO like: ```java public class Simple { public int x = 1; public int y = 2; } ``` you would get something like: ```xml 1 2 ``` (except that by default output is not indented: you can enabled indentation using standard Jackson mechanisms) ## Deserializing POJOs from XML Similar to serialization, deserialization is not very different from JSON deserialization: ```java ObjectMapper xmlMapper = new XmlMapper(); Simple value = xmlMapper.readValue("12", Simple.class); ``` ## Incremental/partial reading/writing (2.4+) It is also possible to do incremental writes. This is done by creating Stax `XMLInputFactory` separately (similar to how with JSON you would create `JsonGenerator`), and then: ```java // First create Stax components we need XMLInputFactory f = XMLInputFactory.newFactory(); StringWriter out = new StringWriter(); XMLStreamWriter sw = f.createXMLStreamWriter(out); // then Jackson components XmlMapper mapper = new XmlMapper(f); sw.writeStartDocument(); sw.writeStartElement("root"); // Write whatever content POJOs... SomePojo value1 = ...; OtherPojo value2 = ...; mapper.writeValue(sw, value1); mapper.writeValue(sw, value2); // and/or regular Stax output sw.writeComment("Some insightful commentary here"); sw.writeEndElement(); sw.writeEndDocument(); ``` Similarly it is possible to read content, sub-tree by sub-tree; assuming similar XML content we would use ```java XMLOutputFactory f = XMLOutputFactory.newFactory(); File inputFile = ...; XMLStreamReader sr = f.createXMLStreamReader(new FileInputStream(inputFile)); XmlMapper mapper = new XmlMapper(); sr.next(); // to point to sr.next(); // to point to root-element under root SomePojo value1 = mapper.readValue(sr, SomePojo.class); // sr now points to matching END_ELEMENT, so move forward sr.next(); // should verify it's either closing root or new start, left as exercise OtherPojo value = mapper.readValue(sr, OtherPojo.class); // and more, as needed, then sr.close(); ``` ## Additional annotations In addition to standard [Jackson annotations](https://github.com/FasterXML/jackson-annotations) and optional JAXB (`javax.xml.bind.annotation`), this project also adds couple of its own annotations for convenience, to support XML-specific details: * `@JacksonXmlElementWrapper` allows specifying XML element to use for wrapping `List` and `Map` properties * `@JacksonXmlProperty` allows specifying XML namespace and local name for a property; as well as whether property is to be written as an XML element or attribute. * `@JacksonXmlRootElement` allows specifying XML element to use for wrapping the root element (default uses 'simple name' of the value class) * `@JacksonXmlText` allows specifying that value of one property is to be serialized as "unwrapped" text, and not in an element. * `@JacksonXmlCData` allows specifying that the value of a property is to be serialized within a CData tag. for longer description, check out [XML module annotations](https://github.com/FasterXML/jackson-dataformat-xml/wiki/Jackson-XML-annotations). ## Known Limitations Currently, following limitations exist beyond basic Jackson (JSON) limitations: * Root value should be a POJO; and specifically following types can be serialized as properties but not as root values: * Java arrays * `java.util.Collection` values (Lists, Sets) * `Enum`s (support for these may be added in future -- but not as of 2.4) * Lists and arrays are "wrapped" by default, when using Jackson annotations, but unwrapped when using JAXB annotations (if supported, see below) * Unwrapped List/array support was added in Jackson 2.1 (2.0 does NOT support them; arrays are always wrapped) * `@JacksonXmlElementWrapper.useWrapping` can be set to 'false' to disable wrapping * `JacksonXmlModule.setDefaultUseWrapper()` can be used to specify whether "wrapped" or "unwrapped" setting is the default * Tree Model is only supported in limited fashion: specifically, Java arrays and `Collection`s can be written, but can not be read, since it is not possible to distinguish Arrays and Objects without additional information. # See Also * XML module [wiki page](https://github.com/FasterXML/jackson-dataformat-xml/wiki) for more information * Using XML with [DropWizard](https://github.com/dropwizard/dropwizard)? Check out [this extension](https://github.com/yunspace/dropwizard-xml)! jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/pom.xml000066400000000000000000000146241251656754200237740ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson jackson-parent 2.5.1 com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.5.3 Jackson-dataformat-XML bundle Data format extension for Jackson (http://jackson.codehaus.org) to offer alternative support for serializing POJOs as XML and deserializing XML as pojos. Support implemented on top of Stax API (javax.xml.stream), by implementing core Jackson Streaming API types like JsonGenerator, JsonParser and JsonFactory. Some data-binding types overridden as well (ObjectMapper sub-classed as XmlMapper). http://wiki.fasterxml.com/JacksonExtensionXmlDataBinding scm:git:git@github.com:FasterXML/jackson-dataformat-xml.git scm:git:git@github.com:FasterXML/jackson-dataformat-xml.git http://github.com/FasterXML/jackson-dataformat-xml jackson-dataformat-xml-2.5.3 2.5.0 2.5.3 ${version.jackson.core} com/fasterxml/jackson/dataformat/xml ${project.groupId}.xml com.fasterxml.jackson.dataformat.xml ,com.fasterxml.jackson.dataformat.xml.annotation ,com.fasterxml.jackson.dataformat.xml.deser ,com.fasterxml.jackson.dataformat.xml.jaxb ,com.fasterxml.jackson.dataformat.xml.ser ,com.fasterxml.jackson.dataformat.xml.util javax.xml.bind.annotation, javax.xml.namespace, javax.xml.stream, javax.xml.transform ,org.codehaus.stax2, org.codehaus.stax2.io, org.codehaus.stax2.ri ,com.fasterxml.jackson.annotation ,com.fasterxml.jackson.core ,com.fasterxml.jackson.core.base, com.fasterxml.jackson.core.format, com.fasterxml.jackson.core.json ,com.fasterxml.jackson.core.io, com.fasterxml.jackson.core.type, com.fasterxml.jackson.core.util ,com.fasterxml.jackson.databind ,com.fasterxml.jackson.databind.cfg ,com.fasterxml.jackson.databind.deser ,com.fasterxml.jackson.databind.deser.std ,com.fasterxml.jackson.databind.introspect, com.fasterxml.jackson.databind.module ,com.fasterxml.jackson.databind.jsontype, com.fasterxml.jackson.databind.jsontype.impl ,com.fasterxml.jackson.databind.ser, com.fasterxml.jackson.databind.ser.impl, com.fasterxml.jackson.databind.ser.std ,com.fasterxml.jackson.databind.type, com.fasterxml.jackson.databind.util ,com.fasterxml.jackson.module.jaxb com.fasterxml.jackson.core jackson-core ${version.jackson.core} com.fasterxml.jackson.core jackson-annotations ${version.jackson.annotations} com.fasterxml.jackson.core jackson-databind ${version.jackson.core} com.fasterxml.jackson.module jackson-module-jaxb-annotations ${version.jackson.jaxb} javax.xml.stream stax-api 1.0-2 provided org.codehaus.woodstox stax2-api 3.1.4 org.codehaus.woodstox woodstox-core-asl 4.3.0 test com.google.code.maven-replacer-plugin replacer process-packageVersion generate-sources org.apache.maven.plugins maven-surefire-plugin ${version.plugin.surefire} com/fasterxml/jackson/dataformat/xml/failing/*.java **/Test*.java **/*Test.java force-release true true jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/release-notes/000077500000000000000000000000001251656754200252165ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/release-notes/CREDITS000066400000000000000000000012261251656754200262370ustar00rootroot00000000000000Here are people who have contributed to development of this project: (version numbers in brackets indicate release in which the problem was fixed) Tatu Saloranta, tatu.saloranta@iki.fi: author Sebastien Dionne: * Suggested Issue-23: Add @JacksonXmlText annotation (alias for JAXB @XmlValue), to support case of property values as 'unwrapped' text (2.0.1) Pascal Gelinas: * Reported and fixed #84: Problem with @JacksonXmlText when property output is suppressed (2.3.1) * Reported and fixed #83: Add support for @JsonUnwrapped (2.4.0) Dan Jasek: (oillio@github) * Contributed #126: Allow specifying properties that should be written as CData (2.5.0) jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/release-notes/VERSION000066400000000000000000000122341251656754200262700ustar00rootroot00000000000000Project: jackson-dataformat-xml ------------------------------------------------------------------------ = Releases ------------------------------------------------------------------------ 2.5.3 (24-Apr-2015) 2.5.2 (29-Mar-2015) No changes since 2.5.1 2.5.1 (06-Feb-2015) #133: Performance regression (2.4->2.5), 10% slower write via databind 2.5.0 (01-Jan-2015) #120: Encoding not taken in account (reported by Sébastien D, sdeleuze@github) #126: Allow specifying properties that should be written as CData (contributed by Dan J) #129: Unwrapped collection containing empty CDATA not deserialized correctly (reported by tjconsult@github) 2.4.6 (not yet released) - Improvement to `JsonParser.useDefaultPrettyPrinter()` override (wrt #136) 2.4.5 (13-Jan-2015) 2.4.4 (24-Nov-2014) 2.4.3 (04-Oct-2014) 2.4.2 (15-Aug-2014) No changes. 2.4.1 (17-Jun-2014) #117: @JsonAnyGetter + @JsonTypeInfo combination prevents serialization of properties as elements (reported by gawi@github) 2.4.0 (02-Jun-2014) #76: UnrecognizedPropertyException when containing object is a Collection (reported by pierre@github) #83: Add support for @JsonUnwrapped (contributed by Pascal G) #99: Problem with DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, Lists (reported by anton0xf@github) #108: Unwrapped list ignore attributes if 2 lists in sequence #111: Make vanilla `JaxbAnnotationIntrospector` work, without having to use `XmlJaxbAnnotationIntrospector` #115: Allow incremental reading/writing with existing `XMLStreamReader` and `XMLStreamWriter`. - Add `JsonFactory.canUseCharArrays()` introspection method 2.3.3 (10-Apr-2014) #101: Invalid index error when deserializing unwrapped list element with multiple attributes (reported by yunspace@github; fix suggested by escholz@github) 2.3.2 (01-Mar-2014) #81: Serialization of a polymorphic class As.Property with Identity info doesn't work (fixed by Pascal G) #91: @JsonPropertyOrder not working correctly with attributes (reported by thrykol@github) 2.3.1 (28-Dec-2013) #84: Problem with @JacksonXmlText when property output is suppressed (contributed by Pascal G) 2.3.0 (14-Nov-2013) #38: Support root-level Collection serialization #64: Problems deserializing unwrapped lists, with optional (and missing) attribute. #71: Fix issues with `XmlMapper.convertValue()` - Add support for `JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN` - Improved indentation 2.2.3 (22-Aug-2013): No functional changes. 2.2.2 (31-May-2013) #66: @JacksonXmlText should imply existence of property (without explicit marking) (suggested by ShijunK@github) 2.2.1 (03-May-2013) - Fixed problems with `XmlFactory.copy()` not calling underlying JsonFactory settings 2.2.0 (22-Apr-2013) #47: First attribute of list value elements ignored (reported by dewthefifth@github) #55: Problems deserializing wrapped lists (annotations not properly recognized) #56: Indenting disables @JacksonXmlText (reported by edrik@github) 2.1.3 (19-Jan-2013) * [JACKSON-879]: Missing OSGi import for 'com.fasterxml.jackson.databind.deser.std' causing error trying to load 'DelegatingDeserializer' base class. (reported by Martin S) * [Issue#45]: Indentation should not be added if element only has attributes * More fixes to [Issue#48], wrt thaw/unthaw 2.1.2 (04-Dec-2012) * [Issue#42]: Problems with custom serializers, `JsonGenerator.writeObjectField` (reported by matejj@github) * [Issue#44]: Problems with FilterProvider, serialization, annotations (reported by lalmeras@github) * [Issue#46]: Indentation not working for unwrapped Lists (reported by lalmeras@github) * [Issue#48]: 'XmlMapper.copy()' was missing copy of some fields in `XmlFactory` (reported by Sean B) 2.1.1 (12-Nov-2012) * [Issue#39]: Improve error reporting when trying to use non-Stax2 implementation, indentation * [Issue#41]: Custom (de)serializer registration not working with JacksonXmlModule (reported by matejj@github) 2.1.0 (08-Oct-2012) New minor version, with following changes: * [Issue#6]: Add support for "unwrapped lists"; now unwrapped is also default when using JAXB annotations (but not with Jackson annotations, for backwards compatibility). @JacksonXmlElementWrapper allows explicit per-property overrides * [Issue#30]: (from JAXB module, issue #11) Now `@XmlIDREF` forces use of id value for serialization of a reference property. * [Issue#33]: Ignore attributes of elements for "List" objects * [Issue#36]: Add 'JacksonXmlModule.setXMLTextElementName()' to allow matching 'value' text property of JAXB beans. 2.0.5 (27-Jul-2012) * [Issue-29]: Binary value not cleared, leading to duplicated binary data for POJOs. (reported by 'farfalena'@git) 2.0.4 (26-Jun-2012) no new fixes, dependencies to core components updated. 2.0.3 (15-Jun-2012) * [Issue#26]: Root element should use 'default namespace' 2.0.2 (14-May-2012) No fixes, updates dependencies. 2.0.1 (14-Apr-2012) * [Issue#23]: Add @JacksonXmlText annotation (alias for JAXB @XmlValue), to support case of text value with attributes (requested by Sebastian D) 2.0.0 (25-Mar-2012) * [Issue#19]: Strange behavior with namespace generation when using 'isAttribute = true' (reported by Morten-Olav H) [entries for version 1.x not retained) jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/000077500000000000000000000000001251656754200232375ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/000077500000000000000000000000001251656754200241635ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/000077500000000000000000000000001251656754200251045ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/000077500000000000000000000000001251656754200256625ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/000077500000000000000000000000001251656754200276675ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/000077500000000000000000000000001251656754200313175ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/000077500000000000000000000000001251656754200334415ustar00rootroot00000000000000000077500000000000000000000000001251656754200341625ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlJacksonXmlAnnotationIntrospector.java000066400000000000000000000145471251656754200435600ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.dataformat.xml.annotation.*; /** * Extension of {@link JacksonAnnotationIntrospector} that is needed to support * additional xml-specific annotation that Jackson provides. Note, however, that * there is no JAXB annotation support here; that is provided with * separate introspector (see * {@link com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector}). */ public class JacksonXmlAnnotationIntrospector extends JacksonAnnotationIntrospector implements XmlAnnotationIntrospector { private static final long serialVersionUID = 1L; /** * For backwards compatibility with 2.0, the default behavior is * to assume use of List wrapper if no annotations are used. */ public final static boolean DEFAULT_USE_WRAPPER = true; protected final boolean _cfgDefaultUseWrapper; public JacksonXmlAnnotationIntrospector() { this(DEFAULT_USE_WRAPPER); } public JacksonXmlAnnotationIntrospector(boolean defaultUseWrapper) { _cfgDefaultUseWrapper = defaultUseWrapper; } /* /********************************************************************** /* Overrides of JacksonAnnotationIntrospector impls /********************************************************************** */ @Override public PropertyName findWrapperName(Annotated ann) { JacksonXmlElementWrapper w = ann.getAnnotation(JacksonXmlElementWrapper.class); if (w != null) { // Special case: wrapping explicitly blocked? if (!w.useWrapping()) { return PropertyName.NO_NAME; } // also: need to ensure we use marker: String localName = w.localName(); if (localName == null || localName.length() == 0) { return PropertyName.USE_DEFAULT; } return PropertyName.construct(w.localName(), w.namespace()); } /* 09-Sep-2012, tatu: In absence of configurating we need to use our * default settings... */ if (_cfgDefaultUseWrapper) { return PropertyName.USE_DEFAULT; } return null; } @Override public PropertyName findRootName(AnnotatedClass ac) { JacksonXmlRootElement root = ac.getAnnotation(JacksonXmlRootElement.class); if (root != null) { String local = root.localName(); String ns = root.namespace(); if (local.length() == 0 && ns.length() == 0) { return PropertyName.USE_DEFAULT; } return new PropertyName(local, ns); } return super.findRootName(ac); } /* /********************************************************************** /* XmlAnnotationIntrospector, findXxx /********************************************************************** */ @Override public String findNamespace(Annotated ann) { JacksonXmlProperty prop = ann.getAnnotation(JacksonXmlProperty.class); if (prop != null) { return prop.namespace(); } return null; } /* /********************************************************************** /* XmlAnnotationIntrospector, isXxx methods /********************************************************************** */ @Override public Boolean isOutputAsAttribute(Annotated ann) { JacksonXmlProperty prop = ann.getAnnotation(JacksonXmlProperty.class); if (prop != null) { return prop.isAttribute() ? Boolean.TRUE : Boolean.FALSE; } return null; } @Override public Boolean isOutputAsText(Annotated ann) { JacksonXmlText prop = ann.getAnnotation(JacksonXmlText.class); if (prop != null) { return prop.value() ? Boolean.TRUE : Boolean.FALSE; } return null; } @Override public Boolean isOutputAsCData(Annotated ann) { JacksonXmlCData prop = ann.getAnnotation(JacksonXmlCData.class); if (prop != null) { return prop.value() ? Boolean.TRUE : Boolean.FALSE; } return null; } /* /********************************************************************** /* Overrides for name, property detection /********************************************************************** */ @Override public PropertyName findNameForSerialization(Annotated a) { PropertyName name = _findXmlName(a); if (name == null) { name = super.findNameForSerialization(a); if (name == null) { if (a.hasAnnotation(JacksonXmlText.class)) { return PropertyName.USE_DEFAULT; } } } return name; } @Override public PropertyName findNameForDeserialization(Annotated a) { PropertyName name = _findXmlName(a); if (name == null) { name = super.findNameForDeserialization(a); if (name == null) { if (a.hasAnnotation(JacksonXmlText.class)) { return PropertyName.USE_DEFAULT; } } } return name; } /* /********************************************************************** /* Overrides for non-public helper methods /********************************************************************** */ /** * We will override this method so that we can return instance * that cleans up type id property name to be a valid xml name. */ @Override protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() { return new XmlTypeResolverBuilder(); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected PropertyName _findXmlName(Annotated a) { JacksonXmlProperty pann = a.getAnnotation(JacksonXmlProperty.class); if (pann != null) { return PropertyName.construct(pann.localName(), pann.namespace()); } return null; } } JacksonXmlModule.java000066400000000000000000000113261251656754200402470ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser; import com.fasterxml.jackson.dataformat.xml.deser.XmlBeanDeserializerModifier; import com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerModifier; /** * Module that implements most functionality needed to support producing and * consuming XML instead of JSON. */ public class JacksonXmlModule extends SimpleModule implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Determination of whether indexed properties (arrays, Lists) that are not explicitly * annotated (with {@link com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper} * or equivalent) should default to using implicit wrapper (with same name as property) or not. * If enabled, wrapping is used by default; if false, it is not. *

* Note that JAXB annotation introspector always assumes "do not wrap by default". * Jackson annotations have different default due to backwards compatibility. * * @since 2.1 */ protected boolean _cfgDefaultUseWrapper = JacksonXmlAnnotationIntrospector.DEFAULT_USE_WRAPPER; /** * Name used for pseudo-property used for returning XML Text value (which does * not have actual element name to use). Defaults to empty String, but * may be changed for interoperability reasons: JAXB, for example, uses * "value" as name. * * @since 2.1 */ protected String _cfgNameForTextElement = FromXmlParser.DEFAULT_UNNAMED_TEXT_PROPERTY; /* /********************************************************************** /* Life-cycle: construction /********************************************************************** */ public JacksonXmlModule() { super("JackxonXmlModule", PackageVersion.VERSION); } @Override public void setupModule(SetupContext context) { // Need to modify BeanDeserializer, BeanSerializer that are used context.addBeanSerializerModifier(new XmlBeanSerializerModifier()); context.addBeanDeserializerModifier(new XmlBeanDeserializerModifier(_cfgNameForTextElement)); // as well as AnnotationIntrospector context.insertAnnotationIntrospector(_constructIntrospector()); // and finally inform XmlFactory about overrides, if need be: if (_cfgNameForTextElement != FromXmlParser.DEFAULT_UNNAMED_TEXT_PROPERTY) { XmlMapper m = (XmlMapper) context.getOwner(); m.setXMLTextElementName(_cfgNameForTextElement); } /* Usually this would be the first call; but here anything added will * be stuff user may has added, so do it afterwards instead. */ super.setupModule(context); } /* /********************************************************************** /* Life-cycle: configuration /********************************************************************** */ /** * Method that can be used to define whether {@link AnnotationIntrospector} * we register will use wrapper for indexed (List, array) properties or not, * if there are no explicit annotations. * See {@link com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper} * for details. *

* Note that method MUST be called before registering the module; otherwise change * will not have any effect. * * @param state Whether to enable or disable "use wrapper for non-annotated List properties" * * @since 2.1 */ public void setDefaultUseWrapper(boolean state) { _cfgDefaultUseWrapper = state; } /** * Method that can be used to define alternate "virtual name" to use * for XML CDATA segments; that is, text values. Default name is empty String * (""); but some frameworks use other names: JAXB, for example, uses * "value". *

* Note that method MUST be called before registering the module; otherwise change * will not have any effect. * * @param name Virtual name to use when exposing XML character data sections * * @since 2.1 */ public void setXMLTextElementName(String name) { _cfgNameForTextElement = name; } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected AnnotationIntrospector _constructIntrospector() { return new JacksonXmlAnnotationIntrospector(_cfgDefaultUseWrapper); } } PackageVersion.java.in000066400000000000000000000011071251656754200403320ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage @package@; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.core.util.VersionUtil; /** * Automatically generated from PackageVersion.java.in during * packageVersion-generate execution of maven-replacer-plugin in * pom.xml. */ public final class PackageVersion implements Versioned { public final static Version VERSION = VersionUtil.parseVersion( "@projectversion@", "@projectgroupid@", "@projectartifactid@"); @Override public Version version() { return VERSION; } } XmlAnnotationIntrospector.java000066400000000000000000000136631251656754200422450ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; /** * Additional extension interface used above and beyond * {@link AnnotationIntrospector} to handle XML-specific configuration. */ public interface XmlAnnotationIntrospector { /** * Method that can be called to figure out generic namespace * property for an annotated object. * * @return Null if annotated thing does not define any * namespace information; non-null namespace (which may * be empty String) otherwise */ public String findNamespace(Annotated ann); /** * Method used to check whether given annotated element * (field, method, constructor parameter) has indicator that suggests * it be output as an XML attribute or not (as element) */ public Boolean isOutputAsAttribute(Annotated ann); /** * Method used to check whether given annotated element * (field, method, constructor parameter) has indicator that suggests * it should be serialized as text, without element wrapper. */ public Boolean isOutputAsText(Annotated ann); /** * Method used to check whether given annotated element * (field, method, constructor parameter) has indicator that suggests * it should be wrapped in a CDATA tag. */ public Boolean isOutputAsCData(Annotated ann); /* /********************************************************************** /* Replacement of 'AnnotationIntrospector.Pair' to use when combining /* (potential) XMLAnnotationIntrospector instance /********************************************************************** */ /** * Extension of AnnotationIntrospector.Pair that can * also dispatch 'XmlAnnotationIntrospector' methods. */ public static class Pair extends AnnotationIntrospectorPair implements XmlAnnotationIntrospector { private static final long serialVersionUID = 1L; protected final XmlAnnotationIntrospector _xmlPrimary; protected final XmlAnnotationIntrospector _xmlSecondary; public Pair(AnnotationIntrospector p, AnnotationIntrospector s) { super(p, s); if (p instanceof XmlAnnotationIntrospector) { _xmlPrimary = (XmlAnnotationIntrospector) p; } else if (p instanceof JaxbAnnotationIntrospector) { _xmlPrimary = new JaxbWrapper((JaxbAnnotationIntrospector) p); } else { _xmlPrimary = null; } if (s instanceof XmlAnnotationIntrospector) { _xmlSecondary = (XmlAnnotationIntrospector) s; } else if (s instanceof JaxbAnnotationIntrospector) { _xmlSecondary = new JaxbWrapper((JaxbAnnotationIntrospector) s); } else { _xmlSecondary = null; } } public static XmlAnnotationIntrospector.Pair instance(AnnotationIntrospector a1, AnnotationIntrospector a2) { return new XmlAnnotationIntrospector.Pair(a1, a2); } @Override public String findNamespace(Annotated ann) { String value = (_xmlPrimary == null) ? null : _xmlPrimary.findNamespace(ann); if (value == null && _xmlSecondary != null) { value = _xmlSecondary.findNamespace(ann); } return value; } @Override public Boolean isOutputAsAttribute(Annotated ann) { Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsAttribute(ann); if (value == null && _xmlSecondary != null) { value = _xmlSecondary.isOutputAsAttribute(ann); } return value; } @Override public Boolean isOutputAsText(Annotated ann) { Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsText(ann); if (value == null && _xmlSecondary != null) { value = _xmlSecondary.isOutputAsText(ann); } return value; } @Override public Boolean isOutputAsCData(Annotated ann) { Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsCData(ann); if (value == null && _xmlSecondary != null) { value = _xmlSecondary.isOutputAsCData(ann); } return value; } } /* /********************************************************************** /* Helper class used to adapt JaxbAnnoationIntrospector as /* XmlAnnotationIntrospector /********************************************************************** */ /** * Wrapper we need to adapt {@link JaxbAnnotationIntrospector} as * {@link XmlAnnotationIntrospector}: something we can not (alas!) * do in JAXB module because of dependency direction (JAXB module * has no knowledge of this module). */ static class JaxbWrapper implements XmlAnnotationIntrospector { protected final JaxbAnnotationIntrospector _intr; public JaxbWrapper(JaxbAnnotationIntrospector i) { _intr = i; } @Override public String findNamespace(Annotated ann) { return _intr.findNamespace(ann); } @Override public Boolean isOutputAsAttribute(Annotated ann) { return _intr.isOutputAsAttribute(ann); } @Override public Boolean isOutputAsText(Annotated ann) { return _intr.isOutputAsText(ann); } @Override public Boolean isOutputAsCData(Annotated ann) { //There is no CData annotation in JAXB return null; } } } XmlFactory.java000066400000000000000000000652201251656754200371220ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.io.*; import javax.xml.stream.*; import org.codehaus.stax2.io.Stax2ByteArraySource; import org.codehaus.stax2.io.Stax2CharArraySource; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.format.InputAccessor; import com.fasterxml.jackson.core.format.MatchStrength; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.util.VersionUtil; import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; import com.fasterxml.jackson.dataformat.xml.util.StaxUtil; /** * Factory used for constructing {@link FromXmlParser} and {@link ToXmlGenerator} * instances. *

* Implements {@link JsonFactory} since interface for constructing XML backed * parsers and generators is quite similar to dealing with JSON. * * @author Tatu Saloranta (tatu.saloranta@iki.fi) */ public class XmlFactory extends JsonFactory { // For 2.5: private static final long serialVersionUID = 1897624416641000209L; /** * Name used to identify XML format * (and returned by {@link #getFormatName()} */ public final static String FORMAT_NAME_XML = "XML"; /** * Bitfield (set of flags) of all parser features that are enabled * by default. */ final static int DEFAULT_XML_PARSER_FEATURE_FLAGS = FromXmlParser.Feature.collectDefaults(); /** * Bitfield (set of flags) of all generator features that are enabled * by default. */ final static int DEFAULT_XML_GENERATOR_FEATURE_FLAGS = ToXmlGenerator.Feature.collectDefaults(); /* /********************************************************** /* Configuration /********************************************************** */ protected int _xmlParserFeatures; protected int _xmlGeneratorFeatures; // non-final for setters (why are they needed again?) protected transient XMLInputFactory _xmlInputFactory; protected transient XMLOutputFactory _xmlOutputFactory; protected String _cfgNameForTextElement; /* /********************************************************** /* Factory construction, configuration /********************************************************** */ /** * Default constructor used to create factory instances. * Creation of a factory instance is a light-weight operation, * but it is still a good idea to reuse limited number of * factory instances (and quite often just a single instance): * factories are used as context for storing some reused * processing objects (such as symbol tables parsers use) * and this reuse only works within context of a single * factory instance. */ public XmlFactory() { this(null, null, null); } public XmlFactory(ObjectCodec oc) { this(oc, null, null); } public XmlFactory(XMLInputFactory xmlIn) { this(null, xmlIn, null); } public XmlFactory(XMLInputFactory xmlIn, XMLOutputFactory xmlOut) { this(null, xmlIn, xmlOut); } public XmlFactory(ObjectCodec oc, XMLInputFactory xmlIn, XMLOutputFactory xmlOut) { this(oc, DEFAULT_XML_PARSER_FEATURE_FLAGS, DEFAULT_XML_GENERATOR_FEATURE_FLAGS, xmlIn, xmlOut, null); } protected XmlFactory(ObjectCodec oc, int xpFeatures, int xgFeatures, XMLInputFactory xmlIn, XMLOutputFactory xmlOut, String nameForTextElem) { super(oc); _xmlParserFeatures = xpFeatures; _xmlGeneratorFeatures = xgFeatures; _cfgNameForTextElement = nameForTextElem; if (xmlIn == null) { xmlIn = XMLInputFactory.newInstance(); } if (xmlOut == null) { xmlOut = XMLOutputFactory.newInstance(); } _initFactories(xmlIn, xmlOut); _xmlInputFactory = xmlIn; _xmlOutputFactory = xmlOut; } /** * @since 2.2.1 */ protected XmlFactory(XmlFactory src, ObjectCodec oc) { super(src, oc); _xmlParserFeatures = src._xmlParserFeatures; _xmlGeneratorFeatures = src._xmlGeneratorFeatures; _cfgNameForTextElement = src._cfgNameForTextElement; _xmlInputFactory = src._xmlInputFactory; _xmlOutputFactory = src._xmlOutputFactory; } protected void _initFactories(XMLInputFactory xmlIn, XMLOutputFactory xmlOut) { // Better ensure namespaces get built properly, so: xmlOut.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); // and for parser, force coalescing as well (much simpler to use) xmlIn.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); } /** * Note: compared to base implementation by {@link JsonFactory}, * here the copy will actually share underlying XML input and * output factories, as there is no way to make copies of those. * * @since 2.1 */ @Override public XmlFactory copy() { _checkInvalidCopy(XmlFactory.class); return new XmlFactory(this, null); } @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************** /* Serializable overrides /********************************************************** */ /** * Hiding place for JDK-serialization unthawed factories... */ protected transient String _jdkXmlInFactory; /** * Hiding place for JDK-serialization unthawed factories... */ protected transient String _jdkXmlOutFactory; /** * Method that we need to override to actually make restoration go * through constructors etc. */ @Override // since JsonFactory already implemented it protected Object readResolve() { if (_jdkXmlInFactory == null) { throw new IllegalStateException("No XMLInputFactory class name read during JDK deserialization"); } if (_jdkXmlOutFactory == null) { throw new IllegalStateException("No XMLOutputFactory class name read during JDK deserialization"); } try { XMLInputFactory inf = (XMLInputFactory) Class.forName(_jdkXmlInFactory).newInstance(); XMLOutputFactory outf = (XMLOutputFactory) Class.forName(_jdkXmlOutFactory).newInstance(); return new XmlFactory(_objectCodec, _xmlParserFeatures, _xmlGeneratorFeatures, inf, outf, _cfgNameForTextElement); } catch (ClassNotFoundException e) { throw new IllegalArgumentException(e); } catch (InstantiationException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } /** * In addition to default serialization, which mostly works, need * to handle case of XML factories, hence override. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); _jdkXmlInFactory = in.readUTF(); _jdkXmlOutFactory = in.readUTF(); } /** * In addition to default serialization, which mostly works, need * to handle case of XML factories, hence override. */ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeUTF(_xmlInputFactory.getClass().getName()); out.writeUTF(_xmlOutputFactory.getClass().getName()); } /* /********************************************************** /* Configuration, XML-specific /********************************************************** */ /** * @since 2.1 */ public void setXMLTextElementName(String name) { _cfgNameForTextElement = name; } /** * @since 2.2 */ public String getXMLTextElementName() { return _cfgNameForTextElement; } /* /********************************************************** /* Configuration, XML, parser setting /********************************************************** */ /** * Method for enabling or disabling specified XML parser feature. */ public final XmlFactory configure(FromXmlParser.Feature f, boolean state) { if (state) { enable(f); } else { disable(f); } return this; } /** * Method for enabling specified XML parser feature. */ public XmlFactory enable(FromXmlParser.Feature f) { _xmlParserFeatures |= f.getMask(); return this; } /** * Method for disabling specified XML parser feature. */ public XmlFactory disable(FromXmlParser.Feature f) { _xmlParserFeatures &= ~f.getMask(); return this; } /** * Checked whether specified XML parser feature is enabled. */ public final boolean isEnabled(FromXmlParser.Feature f) { return (_xmlParserFeatures & f.getMask()) != 0; } /* /****************************************************** /* Configuration, XML, generator settings /****************************************************** */ /** * Method for enabling or disabling specified XML generator feature. */ public final XmlFactory configure(ToXmlGenerator.Feature f, boolean state) { if (state) { enable(f); } else { disable(f); } return this; } /** * Method for enabling specified XML generator feature. */ public XmlFactory enable(ToXmlGenerator.Feature f) { _xmlGeneratorFeatures |= f.getMask(); return this; } /** * Method for disabling specified XML generator feature. */ public XmlFactory disable(ToXmlGenerator.Feature f) { _xmlGeneratorFeatures &= ~f.getMask(); return this; } /** * Check whether specified XML generator feature is enabled. */ public final boolean isEnabled(ToXmlGenerator.Feature f) { return (_xmlGeneratorFeatures & f.getMask()) != 0; } /* /********************************************************** /* Additional configuration /********************************************************** */ /** @since 2.4 */ public XMLInputFactory getXMLInputFactory() { return _xmlInputFactory; } public void setXMLInputFactory(XMLInputFactory f) { _xmlInputFactory = f; } /** @since 2.4 */ public XMLOutputFactory getXMLOutputFactory() { return _xmlOutputFactory; } public void setXMLOutputFactory(XMLOutputFactory f) { _xmlOutputFactory = f; } /* /********************************************************** /* Format detection functionality /********************************************************** */ /** * Method that returns short textual id identifying format * this factory supports. *

* Note: sub-classes should override this method; default * implementation will return null for all sub-classes */ @Override public String getFormatName() { return FORMAT_NAME_XML; } @Override public MatchStrength hasFormat(InputAccessor acc) throws IOException { return hasXMLFormat(acc); } /** * XML format does require support from custom {@link ObjectCodec} * (that is, {@link XmlMapper}), so need to return true here. * * @return True since XML format does require support from codec */ @Override public boolean requiresCustomCodec() { return true; } /* /********************************************************** /* Capability overrides /********************************************************** */ /** * As of 2.4, we do have actual capability for passing char arrays * efficiently, but unfortunately * have no working mechanism for recycling buffers. So we have to * admit that can not make efficient use. */ @Override public boolean canUseCharArrays() { return false; } /* /********************************************************** /* Overrides of public methods: parsing /********************************************************** */ /** * Overridden just to prevent trying to optimize access via char array; * while nice idea, problem is that we don't have proper hooks to ensure * that temporary buffer gets recycled; so let's just use StringReader. */ @SuppressWarnings("resource") @Override public JsonParser createParser(String content) throws IOException { Reader r = new StringReader(content); IOContext ctxt = _createContext(r, true); if (_inputDecorator != null) { r = _inputDecorator.decorate(ctxt, r); } return _createParser(r, ctxt); } /* /********************************************************** /* Overrides of public methods: generation /********************************************************** */ @Override public ToXmlGenerator createGenerator(OutputStream out) throws IOException { return createGenerator(out, JsonEncoding.UTF8); } @Override public ToXmlGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException { // false -> we won't manage the stream unless explicitly directed to IOContext ctxt = _createContext(out, false); ctxt.setEncoding(enc); return new ToXmlGenerator(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, _createXmlWriter(out)); } @Override public ToXmlGenerator createGenerator(Writer out) throws IOException { return new ToXmlGenerator(_createContext(out, false), _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, _createXmlWriter(out)); } @SuppressWarnings("resource") @Override public ToXmlGenerator createGenerator(File f, JsonEncoding enc) throws IOException { OutputStream out = new FileOutputStream(f); // true -> yes, we have to manage the stream since we created it IOContext ctxt = _createContext(out, true); ctxt.setEncoding(enc); return new ToXmlGenerator(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, _createXmlWriter(out)); } /* /********************************************************** /* Extended public API, mostly for XmlMapper /********************************************************** */ /** * Factory method that wraps given {@link XMLStreamReader}, usually to allow * partial data-binding. * * @since 2.4 */ public FromXmlParser createParser(XMLStreamReader sr) throws IOException { // note: should NOT move parser if already pointing to START_ELEMENT if (sr.getEventType() != XMLStreamConstants.START_ELEMENT) { try { sr = _initializeXmlReader(sr); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } } // false -> not managed FromXmlParser xp = new FromXmlParser(_createContext(sr, false), _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sr); if (_cfgNameForTextElement != null) { xp.setXMLTextElementName(_cfgNameForTextElement); } return xp; } /** * Factory method that wraps given {@link XMLStreamWriter}, usually to allow * incremental serialization to compose large output by serializing a sequence * of individual objects. * * @since 2.4 */ public ToXmlGenerator createGenerator(XMLStreamWriter sw) throws IOException { try { sw = _initializeXmlWriter(sw); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } IOContext ctxt = _createContext(sw, false); return new ToXmlGenerator(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sw); } /* /********************************************************** /* Internal factory method overrides /********************************************************** */ @Override protected FromXmlParser _createParser(InputStream in, IOContext ctxt) throws IOException { XMLStreamReader sr; try { sr = _xmlInputFactory.createXMLStreamReader(in); sr = _initializeXmlReader(sr); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } FromXmlParser xp = new FromXmlParser(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sr); if (_cfgNameForTextElement != null) { xp.setXMLTextElementName(_cfgNameForTextElement); } return xp; } @Override protected FromXmlParser _createParser(Reader r, IOContext ctxt) throws IOException { XMLStreamReader sr; try { sr = _xmlInputFactory.createXMLStreamReader(r); sr = _initializeXmlReader(sr); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } FromXmlParser xp = new FromXmlParser(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sr); if (_cfgNameForTextElement != null) { xp.setXMLTextElementName(_cfgNameForTextElement); } return xp; } @Override protected FromXmlParser _createParser(char[] data, int offset, int len, IOContext ctxt, boolean recycleBuffer) throws IOException { // !!! TODO: add proper handling of 'recycleBuffer'; currently its handling // is always same as if 'false' was passed XMLStreamReader sr; try { sr = _xmlInputFactory.createXMLStreamReader(new Stax2CharArraySource(data, offset, len)); sr = _initializeXmlReader(sr); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } FromXmlParser xp = new FromXmlParser(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sr); if (_cfgNameForTextElement != null) { xp.setXMLTextElementName(_cfgNameForTextElement); } return xp; } @Override protected FromXmlParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException { XMLStreamReader sr; try { sr = _xmlInputFactory.createXMLStreamReader(new Stax2ByteArraySource(data, offset, len)); sr = _initializeXmlReader(sr); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } FromXmlParser xp = new FromXmlParser(ctxt, _generatorFeatures, _xmlGeneratorFeatures, _objectCodec, sr); if (_cfgNameForTextElement != null) { xp.setXMLTextElementName(_cfgNameForTextElement); } return xp; } @Override protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException { // this method should never get called here, so: VersionUtil.throwInternal(); return null; } /* /********************************************************************** /* Internal factory methods, XML-specific /********************************************************************** */ protected XMLStreamWriter _createXmlWriter(OutputStream out) throws IOException { try { return _initializeXmlWriter(_xmlOutputFactory.createXMLStreamWriter(out, "UTF-8")); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } } protected XMLStreamWriter _createXmlWriter(Writer w) throws IOException { try { return _initializeXmlWriter(_xmlOutputFactory.createXMLStreamWriter(w)); } catch (XMLStreamException e) { return StaxUtil.throwXmlAsIOException(e); } } protected final XMLStreamWriter _initializeXmlWriter(XMLStreamWriter sw) throws IOException, XMLStreamException { // And just for Sun Stax parser (JDK default), seems that we better define default namespace // (Woodstox doesn't care) -- otherwise it'll add unnecessary odd declaration sw.setDefaultNamespace(""); return sw; } protected final XMLStreamReader _initializeXmlReader(XMLStreamReader sr) throws IOException, XMLStreamException { // for now, nothing to do... except let's find the root element while (sr.next() != XMLStreamConstants.START_ELEMENT) { ; } return sr; } /* /********************************************************************** /* Internal methods, format auto-detection /********************************************************************** */ private final static byte UTF8_BOM_1 = (byte) 0xEF; private final static byte UTF8_BOM_2 = (byte) 0xBB; private final static byte UTF8_BOM_3 = (byte) 0xBF; private final static byte BYTE_x = (byte) 'x'; private final static byte BYTE_m = (byte) 'm'; private final static byte BYTE_l = (byte) 'l'; private final static byte BYTE_D = (byte) 'D'; private final static byte BYTE_LT = (byte) '<'; private final static byte BYTE_QMARK = (byte) '?'; private final static byte BYTE_EXCL = (byte) '!'; private final static byte BYTE_HYPHEN = (byte) '-'; /** * Method that tries to figure out if content seems to be in some kind * of XML format. * Note that implementation here is not nearly as robust as what underlying * Stax parser will do; the idea is to first support common encodings, * then expand as needed (for example, it is not all that hard to support * UTF-16; but it is some work and not needed quite yet) */ public static MatchStrength hasXMLFormat(InputAccessor acc) throws IOException { /* Basically we just need to find " or , since * can NOT come outside of root */ if (!acc.hasMoreBytes()) { return MatchStrength.INCONCLUSIVE; } b = acc.nextByte(); if (b == BYTE_HYPHEN) { if (!acc.hasMoreBytes()) { return MatchStrength.INCONCLUSIVE; } if (acc.nextByte() == BYTE_HYPHEN) { return MatchStrength.SOLID_MATCH; } } else if (b == BYTE_D) { return tryMatch(acc, "OCTYPE", MatchStrength.SOLID_MATCH); } } else { // maybe root element? Just needs to match first char. if (validXmlNameStartChar(acc, b)) { return MatchStrength.SOLID_MATCH; } } return MatchStrength.NO_MATCH; } private final static boolean validXmlNameStartChar(InputAccessor acc, byte b) throws IOException { /* Can make it actual real XML check in future; for now we do just crude * check for ASCII range */ int ch = (int) b & 0xFF; if (ch >= 'A') { // in theory, colon could be; in practice it should never be valid (wrt namespace) // This is where we'd check for multi-byte UTF-8 chars (or whatever encoding is in use)... return true; } return false; } private final static MatchStrength tryMatch(InputAccessor acc, String matchStr, MatchStrength fullMatchStrength) throws IOException { for (int i = 0, len = matchStr.length(); i < len; ++i) { if (!acc.hasMoreBytes()) { return MatchStrength.INCONCLUSIVE; } if (acc.nextByte() != matchStr.charAt(i)) { return MatchStrength.NO_MATCH; } } return fullMatchStrength; } private final static int skipSpace(InputAccessor acc, byte b) throws IOException { while (true) { int ch = (int) b & 0xFF; if (!(ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t')) { return ch; } if (!acc.hasMoreBytes()) { return -1; } b = acc.nextByte(); ch = (int) b & 0xFF; } } } XmlMapper.java000066400000000000000000000161311251656754200367340ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.io.IOException; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; import com.fasterxml.jackson.dataformat.xml.ser.XmlSerializerProvider; import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter; import com.fasterxml.jackson.dataformat.xml.util.XmlRootNameLookup; /** * Customized {@link ObjectMapper} that will read and write XML instead of JSON, * using XML-backed {@link com.fasterxml.jackson.core.JsonFactory} * implementation ({@link XmlFactory}). *

* Mapper itself overrides some aspects of functionality to try to handle * data binding aspects as similar to JAXB as possible. */ public class XmlMapper extends ObjectMapper { // as of 2.5 private static final long serialVersionUID = -1212805483143619605L; protected final static JacksonXmlModule DEFAULT_XML_MODULE = new JacksonXmlModule(); // need to hold on to module instance just in case copy() is used protected final JacksonXmlModule _xmlModule; /* /********************************************************** /* Life-cycle: construction, configuration /********************************************************** */ public XmlMapper() { this(new XmlFactory()); } /** @since 2.4 */ public XmlMapper(XMLInputFactory inputF, XMLOutputFactory outF) { this(new XmlFactory(inputF, outF)); } /** @since 2.4 */ public XmlMapper(XMLInputFactory inputF) { this(new XmlFactory(inputF)); } public XmlMapper(XmlFactory xmlFactory) { this(xmlFactory, DEFAULT_XML_MODULE); } public XmlMapper(JacksonXmlModule module) { this(new XmlFactory(), module); } public XmlMapper(XmlFactory xmlFactory, JacksonXmlModule module) { /* Need to override serializer provider (due to root name handling); * deserializer provider fine as is */ super(xmlFactory, new XmlSerializerProvider(new XmlRootNameLookup()), null); _xmlModule = module; // but all the rest is done via Module interface! if (module != null) { registerModule(module); } } // @since 2.1 @Override public XmlMapper copy() { _checkInvalidCopy(XmlMapper.class); return new XmlMapper((XmlFactory) _jsonFactory.copy(), _xmlModule); } @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************** /* Additional XML-specific configurations /********************************************************** */ /** * Method called by {@link JacksonXmlModule} to pass configuration * information to {@link XmlFactory}, during registration. * * @since 2.1 */ protected void setXMLTextElementName(String name) { ((XmlFactory) _jsonFactory).setXMLTextElementName(name); } /* /********************************************************** /* Access to configuration settings /********************************************************** */ /** * @deprecated Since 2.1, use {@link #getFactory} instead */ @Override @Deprecated public XmlFactory getJsonFactory() { return (XmlFactory) _jsonFactory; } @Override public XmlFactory getFactory() { return (XmlFactory) _jsonFactory; } public ObjectMapper configure(ToXmlGenerator.Feature f, boolean state) { ((XmlFactory)_jsonFactory).configure(f, state); return this; } public ObjectMapper configure(FromXmlParser.Feature f, boolean state) { ((XmlFactory)_jsonFactory).configure(f, state); return this; } public ObjectMapper enable(ToXmlGenerator.Feature f) { ((XmlFactory)_jsonFactory).enable(f); return this; } public ObjectMapper enable(FromXmlParser.Feature f) { ((XmlFactory)_jsonFactory).enable(f); return this; } public ObjectMapper disable(ToXmlGenerator.Feature f) { ((XmlFactory)_jsonFactory).disable(f); return this; } public ObjectMapper disable(FromXmlParser.Feature f) { ((XmlFactory)_jsonFactory).disable(f); return this; } /* /********************************************************** /* XML-specific access /********************************************************** */ /** * Method for reading a single XML value from given XML-specific input * source; useful for incremental data-binding, combining traversal using * basic Stax {@link XMLStreamReader} with data-binding by Jackson. * * @since 2.4 */ public T readValue(XMLStreamReader r, Class valueType) throws IOException { return readValue(r, _typeFactory.constructType(valueType)); } /** * Method for reading a single XML value from given XML-specific input * source; useful for incremental data-binding, combining traversal using * basic Stax {@link XMLStreamReader} with data-binding by Jackson. * * @since 2.4 */ public T readValue(XMLStreamReader r, TypeReference valueTypeRef) throws IOException { return readValue(r, _typeFactory.constructType(valueTypeRef)); } /** * Method for reading a single XML value from given XML-specific input * source; useful for incremental data-binding, combining traversal using * basic Stax {@link XMLStreamReader} with data-binding by Jackson. * * @since 2.4 */ @SuppressWarnings("resource") public T readValue(XMLStreamReader r, JavaType valueType) throws IOException { FromXmlParser p = getFactory().createParser(r); return super.readValue(p, valueType); } /** * Method for serializing given value using specific {@link XMLStreamReader}: * useful when building large XML files by binding individual items, one at * a time. * * @since 2.4 */ public void writeValue(XMLStreamWriter w0, Object value) throws IOException { @SuppressWarnings("resource") ToXmlGenerator g = getFactory().createGenerator(w0); super.writeValue(g, value); /* NOTE: above call should do flush(); and we should NOT close here. * Finally, 'g' has no buffers to release. */ } /* /********************************************************** /* Overridden methods /********************************************************** */ /** * XML indentation differs from JSON indentation, thereby * need to change default pretty-printer */ @Override protected PrettyPrinter _defaultPrettyPrinter() { return new DefaultXmlPrettyPrinter(); } } XmlPrettyPrinter.java000066400000000000000000000053521251656754200403460ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.math.BigDecimal; import java.math.BigInteger; import javax.xml.stream.XMLStreamException; import org.codehaus.stax2.XMLStreamWriter2; import com.fasterxml.jackson.core.PrettyPrinter; /** * There are some XML-specific quirks that need extra TLC when * indenting: so we will use a refinement of general purpose one. */ public interface XmlPrettyPrinter extends PrettyPrinter { /** * Method for forcibly writing a start element, without going * through Jackson generator (and thus, without updating currently * active element stack) * * @since 2.1 */ public void writeStartElement(XMLStreamWriter2 sw, String nsURI, String localName) throws XMLStreamException; /** * Method for forcibly writing an end element, without going * through Jackson generator (and thus, without updating currently * active element stack) * * @since 2.1 */ public void writeEndElement(XMLStreamWriter2 sw, int nrOfEntries) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, String text, boolean isCData) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, char[] buffer, int offset, int len, boolean isCData) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, boolean value) throws XMLStreamException; // Lots of numbers... public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, int value) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, long value) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, double value) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, float value) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, BigInteger value) throws XMLStreamException; public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, BigDecimal value) throws XMLStreamException; // binary element public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, byte[] data, int offset, int len) throws XMLStreamException; // empty element to represent null public void writeLeafNullElement(XMLStreamWriter2 sw, String nsURI, String localName) throws XMLStreamException; } XmlTypeResolverBuilder.java000066400000000000000000000126031251656754200414620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.MinimalClassNameIdResolver; import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.util.StaxUtil; /** * Custom specialization of {@link StdTypeResolverBuilder}; needed so that * type id property name can be modified as necessary to make it legal * XML element or attribute name. */ public class XmlTypeResolverBuilder extends StdTypeResolverBuilder { @Override public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) { super.init(idType, idRes); if (_typeProperty != null) { _typeProperty = StaxUtil.sanitizeXmlTypeName(_typeProperty); } return this; } @Override public StdTypeResolverBuilder typeProperty(String typeIdPropName) { // ok to have null/empty; will restore to use defaults if (typeIdPropName == null || typeIdPropName.length() == 0) { typeIdPropName = _idType.getDefaultPropertyName(); } _typeProperty = StaxUtil.sanitizeXmlTypeName(typeIdPropName); return this; } @Override protected TypeIdResolver idResolver(MapperConfig config, JavaType baseType, Collection subtypes, boolean forSer, boolean forDeser) { if (_customIdResolver != null) { return _customIdResolver; } // Only override handlings of class, minimal class; name is good as is switch (_idType) { case CLASS: return new XmlClassNameIdResolver(baseType, config.getTypeFactory()); case MINIMAL_CLASS: return new XmlMinimalClassNameIdResolver(baseType, config.getTypeFactory()); default: return super.idResolver(config, baseType, subtypes, forSer, forDeser); } } /* /********************************************************************** /* Internal helper methods /********************************************************************** */ /** * Helper method for encoding regular Java class name in form that * can be used as XML element name. */ protected static String encodeXmlClassName(String className) { /* For now, let's just replace '$'s with double dots... * Perhaps make configurable in future? */ int ix = className.lastIndexOf('$'); if (ix >= 0) { StringBuilder sb = new StringBuilder(className); do { sb.replace(ix, ix+1, ".."); ix = className.lastIndexOf('$', ix-1); } while (ix >= 0); className = sb.toString(); } return className; } /** * Helper method for decoding "XML safe" Java class name back into * actual class name */ protected static String decodeXmlClassName(String className) { int ix = className.lastIndexOf(".."); if (ix >= 0) { StringBuilder sb = new StringBuilder(className); do { sb.replace(ix, ix+2, "$"); ix = className.lastIndexOf("..", ix-1); } while (ix >= 0); className = sb.toString(); } return className; } /* /********************************************************************** /* Customized class name handlers /********************************************************************** */ protected static class XmlClassNameIdResolver extends ClassNameIdResolver { public XmlClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) { super(baseType, typeFactory); } @Override public String idFromValue(Object value) { return encodeXmlClassName(super.idFromValue(value)); } @SuppressWarnings("deprecation") @Override public JavaType typeFromId(String id) { return super.typeFromId(decodeXmlClassName(id)); } @Override public JavaType typeFromId(DatabindContext context, String id) { return super.typeFromId(context, decodeXmlClassName(id)); } } protected static class XmlMinimalClassNameIdResolver extends MinimalClassNameIdResolver { public XmlMinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) { super(baseType, typeFactory); } @Override public String idFromValue(Object value) { return encodeXmlClassName(super.idFromValue(value)); } @SuppressWarnings("deprecation") @Override public JavaType typeFromId(String id) { return super.typeFromId(decodeXmlClassName(id)); } @Override public JavaType typeFromId(DatabindContext context, String id) { return super.typeFromId(context, decodeXmlClassName(id)); } } } 000077500000000000000000000000001251656754200363345ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationJacksonXmlCData.java000066400000000000000000000012551251656754200421500ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationpackage com.fasterxml.jackson.dataformat.xml.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Adding this annotation will result in value of the property to be serialized * within a CData tag. Only use on String properties and String collections. */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) public @interface JacksonXmlCData { /** * Whether the property text should always be within a CData block * when serialized. */ public boolean value() default true; } JacksonXmlElementWrapper.java000066400000000000000000000024441251656754200441270ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationpackage com.fasterxml.jackson.dataformat.xml.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation that is similar to JAXB javax.xml.bind.annotation.XmlElementWrapper, * to indicate wrapper element to use (if any) for Collection types (arrays, * java.util.Collection). If defined, a separate container (wrapper) element * is used; if not, entries are written without wrapping. */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface JacksonXmlElementWrapper { /** * Marker value (empty String) that denotes that the underlying property * name should also be used as the wrapper name, effectively "doubling" * start and end elements. * * @since 2.1 */ public final static String USE_PROPERTY_NAME = ""; String namespace() default USE_PROPERTY_NAME; String localName() default USE_PROPERTY_NAME; /** * Optional property that can be used to explicitly disable wrapping, * usually via mix-ins, or when using AnnotationIntrospector * pairs. * * @since 2.1 */ boolean useWrapping() default true; } JacksonXmlProperty.java000066400000000000000000000013141251656754200430140ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationpackage com.fasterxml.jackson.dataformat.xml.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation that can be used to provide XML-specific configuration * for properties, above and beyond what * {@link com.fasterxml.jackson.annotation.JsonProperty} contains. * It is an alternative to using JAXB annotations. */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface JacksonXmlProperty { boolean isAttribute() default false; String namespace() default ""; String localName() default ""; } JacksonXmlRootElement.java000066400000000000000000000011531251656754200434260ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationpackage com.fasterxml.jackson.dataformat.xml.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation that can be used to define name of root element used * for the root-level object when serialized, which normally uses * name of the type (class). It is similar to JAXB XmlRootElement. */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface JacksonXmlRootElement { String namespace() default ""; String localName() default ""; } JacksonXmlText.java000066400000000000000000000016261251656754200421220ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotationpackage com.fasterxml.jackson.dataformat.xml.annotation; import java.lang.annotation.*; /** * Interface that is loosely similar to {@link javax.xml.bind.annotation.XmlValue} * in that it can be used on one (and only one!) property of a POJO. * It will result in value of the property be serialized without element wrapper, * as long as there are no element-wrapped other properties (attribute-valued * properties are acceptable). * It is also similar to core Jackson JsonValue annotation; but * has to be separate as JsonValue does not allow any other * properties. */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface JacksonXmlText { /** * Whether serialization of the property should always be done as basic * XML text or not; if true, will be, if false, not. */ public boolean value() default true; } package-info.java000066400000000000000000000003171251656754200415240ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/annotation/** * Package that contains additional annotations that can be * used to configure XML-specific aspects of serialization * and deserialization */ package com.fasterxml.jackson.dataformat.xml.annotation; 000077500000000000000000000000001251656754200352645ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserElementWrapper.java000066400000000000000000000053301251656754200410620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; /** * Helper class needed to keep track of virtual wrapper elements * added in the logical XML token stream. */ class ElementWrapper { protected final ElementWrapper _parent; protected final String _wrapperName; protected final String _wrapperNamespace; /* /********************************************************** /* Life-cycle /********************************************************** */ private ElementWrapper(ElementWrapper parent) { _parent = parent; _wrapperName = null; _wrapperNamespace = ""; } private ElementWrapper(ElementWrapper parent, String wrapperLocalName, String wrapperNamespace) { _parent = parent; _wrapperName = wrapperLocalName; _wrapperNamespace = (wrapperNamespace == null) ? "" : wrapperNamespace; } /** * Factory method called to construct a new "matching" wrapper element, * at level where virtual wrapping is needed. */ public static ElementWrapper matchingWrapper(ElementWrapper parent, String wrapperLocalName, String wrapperNamespace) { return new ElementWrapper(parent, wrapperLocalName, wrapperNamespace); } /** * Factory method used for creating intermediate wrapper level, which * is only used for purpose of keeping track of physical element * nesting. */ public ElementWrapper intermediateWrapper() { return new ElementWrapper(this, null, null); } /* /********************************************************** /* API /********************************************************** */ public boolean isMatching() { return _wrapperName != null; } public String getWrapperLocalName() { return _wrapperName; } public String getWrapperNamespace() { return _wrapperNamespace; } public ElementWrapper getParent() { return _parent; } public boolean matchesWrapper(String localName, String ns) { // null means "anything goes", so: if (_wrapperName == null) { return true; } if (ns == null) { ns = ""; } return _wrapperName.equals(localName) && _wrapperNamespace.equals(ns); } /* /********************************************************** /* Overrides /********************************************************** */ @Override public String toString() { if (_parent == null) { return "Wrapper: ROOT, matching: "+_wrapperName; } if (_wrapperName == null) { return "Wrapper: empty"; } return "Wrapper: branch, matching: "+_wrapperName; } } FromXmlParser.java000066400000000000000000000735771251656754200407130ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Set; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserMinimalBase; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.dataformat.xml.PackageVersion; import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** * {@link JsonParser} implementation that exposes XML structure as * set of JSON events that can be used for data binding. */ public class FromXmlParser extends ParserMinimalBase { /** * The default name placeholder for XML text segments is empty * String (""). */ public final static String DEFAULT_UNNAMED_TEXT_PROPERTY = ""; /** * Enumeration that defines all togglable features for XML parsers */ public enum Feature { ; final boolean _defaultState; final int _mask; /** * Method that calculates bit set (flags) of all features that * are enabled by default. */ public static int collectDefaults() { int flags = 0; for (Feature f : values()) { if (f.enabledByDefault()) { flags |= f.getMask(); } } return flags; } private Feature(boolean defaultState) { _defaultState = defaultState; _mask = (1 << ordinal()); } public boolean enabledByDefault() { return _defaultState; } public int getMask() { return _mask; } } /** * In cases where a start element has both attributes and non-empty textual * value, we have to create a bogus property; we will use this as * the property name. *

* Name used for pseudo-property used for returning XML Text value (which does * not have actual element name to use). Defaults to empty String, but * may be changed for interoperability reasons: JAXB, for example, uses * "value" as name. * * @since 2.1 */ protected String _cfgNameForTextElement = DEFAULT_UNNAMED_TEXT_PROPERTY; /* /********************************************************** /* Configuration /********************************************************** */ /** * Bit flag composed of bits that indicate which * {@link FromXmlParser.Feature}s * are enabled. */ protected int _xmlFeatures; protected ObjectCodec _objectCodec; /* /********************************************************** /* I/O state /********************************************************** */ /** * Flag that indicates whether parser is closed or not. Gets * set when parser is either closed by explicit call * ({@link #close}) or when end-of-input is reached. */ protected boolean _closed; final protected IOContext _ioContext; /* /********************************************************** /* Parsing state /********************************************************** */ /** * Information about parser context, context in which * the next token is to be parsed (root, array, object). */ protected XmlReadContext _parsingContext; protected final XmlTokenStream _xmlTokens; /** * * We need special handling to keep track of whether a value * may be exposed as simple leaf value. */ protected boolean _mayBeLeaf; protected JsonToken _nextToken; protected String _currText; protected Set _namesToWrap; /* /********************************************************** /* Parsing state, parsed values /********************************************************** */ /** * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so, * we better reuse it for remainder of content. */ protected ByteArrayBuilder _byteArrayBuilder = null; /** * We will hold on to decoded binary data, for duration of * current event, so that multiple calls to * {@link #getBinaryValue} will not need to decode data more * than once. */ protected byte[] _binaryValue; /* /********************************************************** /* Life-cycle /********************************************************** */ public FromXmlParser(IOContext ctxt, int genericParserFeatures, int xmlFeatures, ObjectCodec codec, XMLStreamReader xmlReader) { super(genericParserFeatures); _xmlFeatures = xmlFeatures; _ioContext = ctxt; _objectCodec = codec; _parsingContext = XmlReadContext.createRootContext(-1, -1); // and thereby start a scope _nextToken = JsonToken.START_OBJECT; _xmlTokens = new XmlTokenStream(xmlReader, ctxt.getSourceReference()); } @Override public Version version() { return PackageVersion.VERSION; } @Override public ObjectCodec getCodec() { return _objectCodec; } @Override public void setCodec(ObjectCodec c) { _objectCodec = c; } /** * @since 2.1 */ public void setXMLTextElementName(String name) { _cfgNameForTextElement = name; } /** * XML format does require support from custom {@link ObjectCodec} * (that is, {@link XmlMapper}), so need to return true here. * * @return True since XML format does require support from codec */ @Override public boolean requiresCustomCodec() { return false; } /* /********************************************************** /* Extended API, configuration /********************************************************** */ public FromXmlParser enable(Feature f) { _xmlFeatures |= f.getMask(); return this; } public FromXmlParser disable(Feature f) { _xmlFeatures &= ~f.getMask(); return this; } public final boolean isEnabled(Feature f) { return (_xmlFeatures & f.getMask()) != 0; } public FromXmlParser configure(Feature f, boolean state) { if (state) { enable(f); } else { disable(f); } return this; } /* /********************************************************** /* Extended API, access to some internal components /********************************************************** */ /** * Method that allows application direct access to underlying * Stax {@link XMLStreamWriter}. Note that use of writer is * discouraged, and may interfere with processing of this writer; * however, occasionally it may be necessary. *

* Note: writer instance will always be of type * {@link org.codehaus.stax2.XMLStreamWriter2} (including * Typed Access API) so upcasts are safe. */ public XMLStreamReader getStaxReader() { return _xmlTokens.getXmlReader(); } /* /********************************************************** /* Internal API /********************************************************** */ /** * Method that may be called to indicate that specified names * (only local parts retained currently: this may be changed in * future) should be considered "auto-wrapping", meaning that * they will be doubled to contain two opening elements, two * matching closing elements. This is needed for supporting * handling of so-called "unwrapped" array types, something * XML mappings like JAXB often use. *

* NOTE: this method is considered part of internal implementation * interface, and it is NOT guaranteed to remain unchanged * between minor versions (it is however expected not to change in * patch versions). So if you have to use it, be prepared for * possible additional work. * * @since 2.1 */ public void addVirtualWrapping(Set namesToWrap) { /* 17-Sep-2012, tatu: Not 100% sure why, but this is necessary to avoid * problems with Lists-in-Lists properties */ String name = _xmlTokens.getLocalName(); if (name != null && namesToWrap.contains(name)) { _xmlTokens.repeatStartElement(); } _namesToWrap = namesToWrap; _parsingContext.setNamesToWrap(namesToWrap); } /* /********************************************************** /* JsonParser impl /********************************************************** */ /** * Method that can be called to get the name associated with * the current event. */ @Override public String getCurrentName() throws IOException, JsonParseException { // [JACKSON-395]: start markers require information from parent String name; if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { XmlReadContext parent = _parsingContext.getParent(); name = parent.getCurrentName(); } else { name = _parsingContext.getCurrentName(); } // sanity check if (name == null) { throw new IllegalStateException("Missing name, in state: "+_currToken); } return name; } @Override public void overrideCurrentName(String name) { // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: XmlReadContext ctxt = _parsingContext; if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { ctxt = ctxt.getParent(); } ctxt.setCurrentName(name); } @Override public void close() throws IOException { if (!_closed) { _closed = true; try { if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { _xmlTokens.closeCompletely(); } else { _xmlTokens.close(); } } finally { // as per [JACKSON-324], do in finally block // Also, internal buffer(s) can now be released as well _releaseBuffers(); } } } @Override public boolean isClosed() { return _closed; } @Override public XmlReadContext getParsingContext() { return _parsingContext; } /** * Method that return the starting location of the current * token; that is, position of the first character from input * that starts the current token. */ @Override public JsonLocation getTokenLocation() { return _xmlTokens.getTokenLocation(); } /** * Method that returns location of the last processed character; * usually for error reporting purposes */ @Override public JsonLocation getCurrentLocation() { return _xmlTokens.getCurrentLocation(); } /** * Since xml representation can not really distinguish between array * and object starts (both are represented with elements), this method * is overridden and taken to mean that expecation is that the current * start element is to mean 'start array', instead of default of * 'start object'. */ @Override public boolean isExpectedStartArrayToken() { JsonToken t = _currToken; if (t == JsonToken.START_OBJECT) { _currToken = JsonToken.START_ARRAY; // Ok: must replace current context with array as well _parsingContext.convertToArray(); //System.out.println(" isExpectedArrayStart: OBJ->Array, wraps now: "+_parsingContext.getNamesToWrap()); // And just in case a field name was to be returned, wipe it _nextToken = null; // and last thing, [Issue#33], better ignore attributes _xmlTokens.skipAttributes(); return true; } //System.out.println(" isExpectedArrayStart?: t="+t); return (t == JsonToken.START_ARRAY); } // DEBUGGING /* @Override public JsonToken nextToken() throws IOException, JsonParseException { JsonToken t = nextToken0(); if (t != null) { switch (t) { case FIELD_NAME: System.out.println("JsonToken: FIELD_NAME '"+_parsingContext.getCurrentName()+"'"); break; case VALUE_STRING: System.out.println("JsonToken: VALUE_STRING '"+getText()+"'"); break; default: System.out.println("JsonToken: "+t); } } return t; } */ @Override public JsonToken nextToken() throws IOException { _binaryValue = null; // to fix [Issue-29] if (_nextToken != null) { JsonToken t = _nextToken; _currToken = t; _nextToken = null; switch (t) { case START_OBJECT: _parsingContext = _parsingContext.createChildObjectContext(-1, -1); break; case START_ARRAY: _parsingContext = _parsingContext.createChildArrayContext(-1, -1); break; case END_OBJECT: case END_ARRAY: _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); break; case FIELD_NAME: _parsingContext.setCurrentName(_xmlTokens.getLocalName()); break; default: // VALUE_STRING, VALUE_NULL // should be fine as is? } return t; } int token = _xmlTokens.next(); /* Need to have a loop just because we may have to eat/convert * a start-element that indicates an array element. */ while (token == XmlTokenStream.XML_START_ELEMENT) { // If we thought we might get leaf, no such luck if (_mayBeLeaf) { // leave _mayBeLeaf set, as we start a new context _nextToken = JsonToken.FIELD_NAME; _parsingContext = _parsingContext.createChildObjectContext(-1, -1); return (_currToken = JsonToken.START_OBJECT); } if (_parsingContext.inArray()) { /* Yup: in array, so this element could be verified; but it won't be reported * anyway, and we need to process following event. */ token = _xmlTokens.next(); _mayBeLeaf = true; continue; } String name = _xmlTokens.getLocalName(); _parsingContext.setCurrentName(name); /* Ok: virtual wrapping can be done by simply repeating * current START_ELEMENT. Couple of ways to do it; but * start by making _xmlTokens replay the thing... */ if (_namesToWrap != null && _namesToWrap.contains(name)) { _xmlTokens.repeatStartElement(); } _mayBeLeaf = true; /* Ok: in array context we need to skip reporting field names. But what's the best way * to find next token? */ return (_currToken = JsonToken.FIELD_NAME); } // Ok; beyond start element, what do we get? switch (token) { case XmlTokenStream.XML_END_ELEMENT: // Simple, except that if this is a leaf, need to suppress end: if (_mayBeLeaf) { _mayBeLeaf = false; return (_currToken = JsonToken.VALUE_NULL); } _currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT; _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); return _currToken; case XmlTokenStream.XML_ATTRIBUTE_NAME: // If there was a chance of leaf node, no more... if (_mayBeLeaf) { _mayBeLeaf = false; _nextToken = JsonToken.FIELD_NAME; _currText = _xmlTokens.getText(); _parsingContext = _parsingContext.createChildObjectContext(-1, -1); return (_currToken = JsonToken.START_OBJECT); } _parsingContext.setCurrentName(_xmlTokens.getLocalName()); return (_currToken = JsonToken.FIELD_NAME); case XmlTokenStream.XML_ATTRIBUTE_VALUE: _currText = _xmlTokens.getText(); return (_currToken = JsonToken.VALUE_STRING); case XmlTokenStream.XML_TEXT: _currText = _xmlTokens.getText(); if (_mayBeLeaf) { _mayBeLeaf = false; // Also: must skip following END_ELEMENT _xmlTokens.skipEndElement(); /* One more refinement (pronunced like "hack") is that if * we had an empty String (or all white space), and we are * deserializing an array, we better just hide the text * altogether. */ if (_parsingContext.inArray()) { if (_isEmpty(_currText)) { _currToken = JsonToken.END_ARRAY; _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); return _currToken; } } return (_currToken = JsonToken.VALUE_STRING); } // If not a leaf, need to transform into property... _parsingContext.setCurrentName(_cfgNameForTextElement); _nextToken = JsonToken.VALUE_STRING; return (_currToken = JsonToken.FIELD_NAME); case XmlTokenStream.XML_END: return (_currToken = null); } // should never get here _throwInternal(); return null; } /* /********************************************************** /* Overrides of specialized nextXxx() methods /********************************************************** */ /** * Method overridden to support more reliable deserialization of * String collections. */ @Override public String nextTextValue() throws IOException { _binaryValue = null; if (_nextToken != null) { JsonToken t = _nextToken; _currToken = t; _nextToken = null; // expected case; yes, got a String if (t == JsonToken.VALUE_STRING) { return _currText; } _updateState(t); return null; } int token = _xmlTokens.next(); // mostly copied from 'nextToken()' while (token == XmlTokenStream.XML_START_ELEMENT) { if (_mayBeLeaf) { _nextToken = JsonToken.FIELD_NAME; _parsingContext = _parsingContext.createChildObjectContext(-1, -1); _currToken = JsonToken.START_OBJECT; return null; } if (_parsingContext.inArray()) { token = _xmlTokens.next(); _mayBeLeaf = true; continue; } String name = _xmlTokens.getLocalName(); _parsingContext.setCurrentName(name); if (_namesToWrap != null && _namesToWrap.contains(name)) { _xmlTokens.repeatStartElement(); } _mayBeLeaf = true; _currToken = JsonToken.FIELD_NAME; return null; } // Ok; beyond start element, what do we get? switch (token) { case XmlTokenStream.XML_END_ELEMENT: if (_mayBeLeaf) { // NOTE: this is different from nextToken() -- produce "", NOT null _mayBeLeaf = false; _currToken = JsonToken.VALUE_STRING; return (_currText = ""); } _currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT; _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); break; case XmlTokenStream.XML_ATTRIBUTE_NAME: // If there was a chance of leaf node, no more... if (_mayBeLeaf) { _mayBeLeaf = false; _nextToken = JsonToken.FIELD_NAME; _currText = _xmlTokens.getText(); _parsingContext = _parsingContext.createChildObjectContext(-1, -1); _currToken = JsonToken.START_OBJECT; } else { _parsingContext.setCurrentName(_xmlTokens.getLocalName()); _currToken = JsonToken.FIELD_NAME; } break; case XmlTokenStream.XML_ATTRIBUTE_VALUE: _currText = _xmlTokens.getText(); _currToken = JsonToken.VALUE_STRING; break; case XmlTokenStream.XML_TEXT: _currText = _xmlTokens.getText(); if (_mayBeLeaf) { _mayBeLeaf = false; // Also: must skip following END_ELEMENT _xmlTokens.skipEndElement(); // NOTE: this is different from nextToken() -- NO work-around // for otherwise empty List/array _currToken = JsonToken.VALUE_STRING; return _currText; } // If not a leaf, need to transform into property... _parsingContext.setCurrentName(_cfgNameForTextElement); _nextToken = JsonToken.VALUE_STRING; _currToken = JsonToken.FIELD_NAME; break; case XmlTokenStream.XML_END: _currToken = null; } return null; } private void _updateState(JsonToken t) { switch (t) { case START_OBJECT: _parsingContext = _parsingContext.createChildObjectContext(-1, -1); break; case START_ARRAY: _parsingContext = _parsingContext.createChildArrayContext(-1, -1); break; case END_OBJECT: case END_ARRAY: _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); break; case FIELD_NAME: _parsingContext.setCurrentName(_xmlTokens.getLocalName()); break; default: } } /* /********************************************************** /* Public API, access to token information, text /********************************************************** */ @Override public String getText() throws IOException, JsonParseException { if (_currToken == null) { return null; } switch (_currToken) { case FIELD_NAME: return getCurrentName(); case VALUE_STRING: return _currText; default: return _currToken.asString(); } } // @since 2.1 @Override public final String getValueAsString() throws IOException, JsonParseException { return getValueAsString(null); } @Override public String getValueAsString(String defValue) throws IOException, JsonParseException { JsonToken t = _currToken; if (t == null) { return null; } switch (t) { case FIELD_NAME: return getCurrentName(); case VALUE_STRING: return _currText; case START_OBJECT: // the interesting case; may be able to convert certain kinds of // elements (specifically, ones with attributes, CDATA only content) // into VALUE_STRING { String str = _xmlTokens.convertToString(); if (str != null) { // need to convert token, as well as "undo" START_OBJECT // note: Should NOT update context, because we will still be getting // matching END_OBJECT, which will undo contexts properly _parsingContext = _parsingContext.getParent(); _namesToWrap = _parsingContext.getNamesToWrap(); _currToken = JsonToken.VALUE_STRING; _nextToken = null; /* One more thing: must explicitly skip the END_OBJECT that * would follow. */ _xmlTokens.skipEndElement(); return (_currText = str); } } return null; default: if (_currToken.isScalarValue()) { return _currToken.asString(); } } return defValue; } @Override public char[] getTextCharacters() throws IOException, JsonParseException { String text = getText(); return (text == null) ? null : text.toCharArray(); } @Override public int getTextLength() throws IOException, JsonParseException { String text = getText(); return (text == null) ? 0 : text.length(); } @Override public int getTextOffset() throws IOException, JsonParseException { return 0; } /** * XML input actually would offer access to character arrays; but since * we must coalesce things it cannot really be exposed. */ @Override public boolean hasTextCharacters() { return false; } /* /********************************************************** /* Public API, access to token information, binary /********************************************************** */ @Override public Object getEmbeddedObject() throws IOException, JsonParseException { // no way to embed POJOs for now... return null; } @Override public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { if (_currToken != JsonToken.VALUE_STRING && (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT || _binaryValue == null)) { _reportError("Current token ("+_currToken+") not VALUE_STRING or VALUE_EMBEDDED_OBJECT, can not access as binary"); } /* To ensure that we won't see inconsistent data, better clear up * state... */ if (_binaryValue == null) { try { _binaryValue = _decodeBase64(b64variant); } catch (IllegalArgumentException iae) { throw _constructError("Failed to decode VALUE_STRING as base64 ("+b64variant+"): "+iae.getMessage()); } } return _binaryValue; } protected byte[] _decodeBase64(Base64Variant b64variant) throws IOException { ByteArrayBuilder builder = _getByteArrayBuilder(); final String str = getText(); _decodeBase64(str, builder, b64variant); return builder.toByteArray(); } /* /********************************************************** /* Numeric accessors /********************************************************** */ @Override public BigInteger getBigIntegerValue() throws IOException { // TODO Auto-generated method stub return null; } @Override public BigDecimal getDecimalValue() throws IOException { // TODO Auto-generated method stub return null; } @Override public double getDoubleValue() throws IOException { // TODO Auto-generated method stub return 0; } @Override public float getFloatValue() throws IOException { // TODO Auto-generated method stub return 0; } @Override public int getIntValue() throws IOException { // TODO Auto-generated method stub return 0; } @Override public long getLongValue() throws IOException { // TODO Auto-generated method stub return 0; } @Override public NumberType getNumberType() throws IOException { // TODO Auto-generated method stub return null; } @Override public Number getNumberValue() throws IOException { // TODO Auto-generated method stub return null; } /* /********************************************************** /* Abstract method impls for stuff from JsonParser /********************************************************** */ /** * Method called when an EOF is encountered between tokens. * If so, it may be a legitimate EOF, but only iff there * is no open non-root context. */ @Override protected void _handleEOF() throws JsonParseException { if (!_parsingContext.inRoot()) { _reportInvalidEOF(": expected close marker for "+_parsingContext.getTypeDesc()+" (from "+_parsingContext.getStartLocation(_ioContext.getSourceReference())+")"); } } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Method called to release internal buffers owned by the base * parser. */ protected void _releaseBuffers() throws IOException { // anything we can/must release? Underlying parser should do all of it, for now? } protected ByteArrayBuilder _getByteArrayBuilder() { if (_byteArrayBuilder == null) { _byteArrayBuilder = new ByteArrayBuilder(); } else { _byteArrayBuilder.reset(); } return _byteArrayBuilder; } protected boolean _isEmpty(String str) { int len = (str == null) ? 0 : str.length(); if (len > 0) { for (int i = 0; i < len; ++i) { if (str.charAt(i) > ' ') { return false; } } } return true; } } WrapperHandlingDeserializer.java000066400000000000000000000137351251656754200435700ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.dataformat.xml.util.TypeUtil; /** * Delegating deserializer whose only function is to handle case of * "unwrapped" List/array deserialization from XML. */ public class WrapperHandlingDeserializer extends DelegatingDeserializer { private static final long serialVersionUID = 1L; /** * (Simple) Names of properties, for which virtual wrapping is needed * to compensate: these are so-called 'unwrapped' XML lists where property * name is used for elements, and not as List markers. */ protected final Set _namesToWrap; protected final JavaType _type; /* /********************************************************************** /* Construction /********************************************************************** */ public WrapperHandlingDeserializer(BeanDeserializerBase delegate) { this(delegate, null); } public WrapperHandlingDeserializer(BeanDeserializerBase delegate, Set namesToWrap) { super(delegate); _namesToWrap = namesToWrap; _type = delegate.getValueType(); } /* /********************************************************************** /* Abstract method implementations /********************************************************************** */ @Override protected JsonDeserializer newDelegatingInstance(JsonDeserializer newDelegatee0) { // default not enough, as we may need to create a new wrapping deserializer // even if delegatee does not change throw new IllegalStateException("Internal error: should never get called"); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // !!! 16-Jan-2015, tatu: TODO: change to be like so in 2.6.0 -- leaving // out for 2.5 just to increase compatibility slightly with 2.4 databind /* JavaType vt = _type; if (vt == null) { vt = ctxt.constructType(_delegatee.handledType()); } JsonDeserializer del = ctxt.handleSecondaryContextualization(_delegatee, property, vt); */ JsonDeserializer del = ctxt.handleSecondaryContextualization(_delegatee, property); BeanDeserializerBase newDelegatee = _verifyDeserType(del); // Let's go through the properties now... Iterator it = newDelegatee.properties(); HashSet unwrappedNames = null; while (it.hasNext()) { SettableBeanProperty prop = it.next(); /* First things first: only consider array/Collection types * (not perfect check, but simplest reasonable check) */ JavaType type = prop.getType(); if (!TypeUtil.isIndexedType(type)) { continue; } PropertyName wrapperName = prop.getWrapperName(); // skip anything with wrapper (should work as is) if (wrapperName != null && wrapperName != PropertyName.NO_NAME) { continue; } if (unwrappedNames == null) { unwrappedNames = new HashSet(); } // not optimal; should be able to use PropertyName... unwrappedNames.add(prop.getName()); } // Ok: if nothing to take care of, just return the delegatee... if (unwrappedNames == null) { return newDelegatee; } // Otherwise, create the thing that can deal with virtual wrapping return new WrapperHandlingDeserializer(newDelegatee, unwrappedNames); } /* /********************************************************************** /* Overridden deserialization methods /********************************************************************** */ @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { _configureParser(jp); return _delegatee.deserialize(jp, ctxt); } @SuppressWarnings("unchecked") @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt, Object intoValue) throws IOException { _configureParser(jp); return ((JsonDeserializer)_delegatee).deserialize(jp, ctxt, intoValue); } @Override public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { _configureParser(jp); return _delegatee.deserializeWithType(jp, ctxt, typeDeserializer); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected final void _configureParser(JsonParser jp) throws IOException { /* 19-Aug-2013, tatu: Although we should not usually get called with * parser of other types, there are some cases where this may happen: * specifically, during structural value conversions. */ if (jp instanceof FromXmlParser) { ((FromXmlParser) jp).addVirtualWrapping(_namesToWrap); } } protected BeanDeserializerBase _verifyDeserType(JsonDeserializer deser) { if (!(deser instanceof BeanDeserializerBase)) { throw new IllegalArgumentException("Can not change delegate to be of type " +deser.getClass().getName()); } return (BeanDeserializerBase) deser; } } XmlBeanDeserializerModifier.java000066400000000000000000000124501251656754200435010ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil; /** * The main reason for a modifier is to support handling of * 'wrapped' Collection types. */ public class XmlBeanDeserializerModifier extends BeanDeserializerModifier implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * Virtual name used for text segments. */ protected String _cfgNameForTextValue = ""; public XmlBeanDeserializerModifier(String nameForTextValue) { _cfgNameForTextValue = nameForTextValue; } @Override public List updateProperties(DeserializationConfig config, BeanDescription beanDesc, List propDefs) { final AnnotationIntrospector intr = config.getAnnotationIntrospector(); int changed = 0; for (int i = 0, propCount = propDefs.size(); i < propCount; ++i) { BeanPropertyDefinition prop = propDefs.get(i); AnnotatedMember acc = prop.getPrimaryMember(); // should not be null, but just in case: if (acc == null) { continue; } /* First: handle "as text"? Such properties * are exposed as values of 'unnamed' fields; so one way to * map them is to rename property to have name ""... (and * hope this does not break other parts...) */ Boolean b = AnnotationUtil.findIsTextAnnotation(intr, acc); if (b != null && b.booleanValue()) { // unwrapped properties will appear as 'unnamed' (empty String) BeanPropertyDefinition newProp = prop.withSimpleName(_cfgNameForTextValue); if (newProp != prop) { propDefs.set(i, newProp); } continue; } // second: do we need to handle wrapping (for Lists)? PropertyName wrapperName = prop.getWrapperName(); if (wrapperName != null && wrapperName != PropertyName.NO_NAME) { String localName = wrapperName.getSimpleName(); if ((localName != null && localName.length() > 0) && !localName.equals(prop.getName())) { // make copy-on-write as necessary if (changed == 0) { propDefs = new ArrayList(propDefs); } ++changed; propDefs.set(i, prop.withSimpleName(localName)); continue; } // otherwise unwrapped; needs handling but later on } } return propDefs; } @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deser0) { if (!(deser0 instanceof BeanDeserializerBase)) { return deser0; } /* 17-Aug-2013, tatu: One important special case first: if we have one "XML Text" * property, it may be exposed as VALUE_STRING token (depending on whether any attribute * values are exposed): and to deserialize from that, we need special handling unless POJO * has appropriate single-string creator method. */ BeanDeserializerBase deser = (BeanDeserializerBase) deser0; // Heuristics are bit tricky; but for now let's assume that if POJO // can already work with VALUE_STRING, it's ok and doesn't need extra support if (!deser.getValueInstantiator().canCreateFromString()) { SettableBeanProperty textProp = _findSoleTextProp(config, deser.properties()); if (textProp != null) { return new XmlTextDeserializer(deser, textProp); } } return new WrapperHandlingDeserializer(deser); } private SettableBeanProperty _findSoleTextProp(DeserializationConfig config, Iterator propIt) { final AnnotationIntrospector ai = config.getAnnotationIntrospector(); SettableBeanProperty textProp = null; while (propIt.hasNext()) { SettableBeanProperty prop = propIt.next(); AnnotatedMember m = prop.getMember(); if (m != null) { // Ok, let's use a simple check: we should have renamed it earlier so: PropertyName n = prop.getFullName(); if (_cfgNameForTextValue.equals(n.getSimpleName())) { // should we verify we only got one? textProp = prop; continue; } // as-attribute are ok as well Boolean b = AnnotationUtil.findIsAttributeAnnotation(ai, m); if (b != null && b.booleanValue()) { continue; } } // Otherwise, it's something else; no go return null; } return textProp; } } XmlReadContext.java000066400000000000000000000125631251656754200410370ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.util.Set; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharTypes; /** * Extension of {@link JsonStreamContext}, which implements * core methods needed, and adds small amount of additional * state data we need. *

* Almost same as standard JsonReaderContext, but * custom version needed to be able to keep track of names * of properties that need wrapping; this is needed to * support wrapped/unwrapped Collection/array values. */ public final class XmlReadContext extends JsonStreamContext { // // // Configuration protected final XmlReadContext _parent; // // // Location information (minus source reference) protected int _lineNr; protected int _columnNr; protected String _currentName; protected Set _namesToWrap; /** * Name of property that requires wrapping */ protected String _wrappedName; /* /********************************************************** /* Simple instance reuse slots; speeds up things /* a bit (10-15%) for docs with lots of small /* arrays/objects (for which allocation was /* visible in profile stack frames) /********************************************************** */ protected XmlReadContext _child = null; /* /********************************************************** /* Instance construction, reuse /********************************************************** */ public XmlReadContext(XmlReadContext parent, int type, int lineNr, int colNr) { super(); _type = type; _parent = parent; _lineNr = lineNr; _columnNr = colNr; _index = -1; } protected final void reset(int type, int lineNr, int colNr) { _type = type; _index = -1; _lineNr = lineNr; _columnNr = colNr; _currentName = null; _namesToWrap = null; } // // // Factory methods public static XmlReadContext createRootContext(int lineNr, int colNr) { return new XmlReadContext(null, TYPE_ROOT, lineNr, colNr); } public static XmlReadContext createRootContext() { return new XmlReadContext(null, TYPE_ROOT, 1, 0); } public final XmlReadContext createChildArrayContext(int lineNr, int colNr) { XmlReadContext ctxt = _child; if (ctxt == null) { _child = ctxt = new XmlReadContext(this, TYPE_ARRAY, lineNr, colNr); return ctxt; } ctxt.reset(TYPE_ARRAY, lineNr, colNr); return ctxt; } public final XmlReadContext createChildObjectContext(int lineNr, int colNr) { XmlReadContext ctxt = _child; if (ctxt == null) { _child = ctxt = new XmlReadContext(this, TYPE_OBJECT, lineNr, colNr); return ctxt; } ctxt.reset(TYPE_OBJECT, lineNr, colNr); return ctxt; } /* /********************************************************** /* Abstract method implementation /********************************************************** */ @Override public final String getCurrentName() { return _currentName; } @Override public final XmlReadContext getParent() { return _parent; } /* /********************************************************** /* State changes /********************************************************** */ public final boolean expectComma() { throw new UnsupportedOperationException(); } public void setCurrentName(String name) { _currentName = name; } /* /********************************************************** /* Extended API /********************************************************** */ /** * @return Location pointing to the point where the context * start marker was found */ public final JsonLocation getStartLocation(Object srcRef) { // We don't keep track of offsets at this level (only reader does) long totalChars = -1L; return new JsonLocation(srcRef, totalChars, _lineNr, _columnNr); } public void setNamesToWrap(Set namesToWrap) { _namesToWrap = namesToWrap; } public Set getNamesToWrap() { return _namesToWrap; } protected void convertToArray() { _type = TYPE_ARRAY; } /* /********************************************************** /* Overridden standard methods /********************************************************** */ /** * Overridden to provide developer readable "JsonPath" representation * of the context. */ @Override public final String toString() { StringBuilder sb = new StringBuilder(64); switch (_type) { case TYPE_ROOT: sb.append("/"); break; case TYPE_ARRAY: sb.append('['); sb.append(getCurrentIndex()); sb.append(']'); break; case TYPE_OBJECT: sb.append('{'); if (_currentName != null) { sb.append('"'); CharTypes.appendQuoted(sb, _currentName); sb.append('"'); } else { sb.append('?'); } sb.append('}'); break; } return sb.toString(); } } XmlTextDeserializer.java000066400000000000000000000113331251656754200421000ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** * Delegating deserializer that is used in the special cases where * we may sometimes see a "plain" String value but need to map it * as if it was a property of POJO. The impedance is introduced by * heuristic conversion from XML events into rough JSON equivalents; * and this is one work-around that can only be done after the fact. */ public class XmlTextDeserializer extends DelegatingDeserializer { private static final long serialVersionUID = 1L; /** * Property index of the "XML text property"; needed for finding actual * property instance after resolution and contextualization: instance * may change, but index will remain constant. */ protected final int _xmlTextPropertyIndex; /** * Actual property that is indicated to be of type "XML Text" (and * is the only element-valued property) */ protected final SettableBeanProperty _xmlTextProperty; protected final ValueInstantiator _valueInstantiator; /* /********************************************************************** /* Construction /********************************************************************** */ public XmlTextDeserializer(BeanDeserializerBase delegate, SettableBeanProperty prop) { super(delegate); _xmlTextProperty = prop; _xmlTextPropertyIndex = prop.getPropertyIndex(); _valueInstantiator = delegate.getValueInstantiator(); } public XmlTextDeserializer(BeanDeserializerBase delegate, int textPropIndex) { super(delegate); _xmlTextPropertyIndex = textPropIndex; _valueInstantiator = delegate.getValueInstantiator(); _xmlTextProperty = delegate.findProperty(textPropIndex); } /* /********************************************************************** /* Abstract method implementations /********************************************************************** */ @Override protected JsonDeserializer newDelegatingInstance(JsonDeserializer newDelegatee0) { // default not enough, as we need to create a new wrapping deserializer // even if delegatee does not change throw new IllegalStateException("Internal error: should never get called"); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { return new XmlTextDeserializer(_verifyDeserType(_delegatee), _xmlTextPropertyIndex); } /* /********************************************************************** /* Overridden deserialization methods /********************************************************************** */ @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { Object bean = _valueInstantiator.createUsingDefault(ctxt); _xmlTextProperty.deserializeAndSet(jp, ctxt, bean); return bean; } return _delegatee.deserialize(jp, ctxt); } @SuppressWarnings("unchecked") @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt, Object bean) throws IOException, JsonProcessingException { if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { _xmlTextProperty.deserializeAndSet(jp, ctxt, bean); return bean; } return ((JsonDeserializer)_delegatee).deserialize(jp, ctxt, bean); } @Override public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException, JsonProcessingException { return _delegatee.deserializeWithType(jp, ctxt, typeDeserializer); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected BeanDeserializerBase _verifyDeserType(JsonDeserializer deser) { if (!(deser instanceof BeanDeserializerBase)) { throw new IllegalArgumentException("Can not change delegate to be of type " +deser.getClass().getName()); } return (BeanDeserializerBase) deser; } } XmlTokenStream.java000066400000000000000000000444611251656754200410550ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.io.IOException; import javax.xml.stream.*; import org.codehaus.stax2.XMLStreamLocation2; import org.codehaus.stax2.XMLStreamReader2; import org.codehaus.stax2.ri.Stax2ReaderAdapter; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.dataformat.xml.util.StaxUtil; /** * Simple helper class used on top of STAX {@link XMLStreamReader} to further * abstract out all irrelevant details, and to expose equivalent of flat token * stream with no "fluff" tokens (comments, processing instructions, mixed * content) all of which is just to simplify * actual higher-level conversion to JSON tokens */ public class XmlTokenStream { // // // main token states: public final static int XML_START_ELEMENT = 1; public final static int XML_END_ELEMENT = 2; public final static int XML_ATTRIBUTE_NAME = 3; public final static int XML_ATTRIBUTE_VALUE = 4; public final static int XML_TEXT = 5; public final static int XML_END = 6; // // // token replay states private final static int REPLAY_START_DUP = 1; private final static int REPLAY_END = 2; private final static int REPLAY_START_DELAYED = 3; /* /********************************************************************** /* Configuration /********************************************************************** */ final protected XMLStreamReader2 _xmlReader; final protected Object _sourceReference; /* /********************************************************************** /* Parsing state /********************************************************************** */ protected int _currentState; protected int _attributeCount; /** * Index of the next attribute of the current START_ELEMENT * to return (as field name and value pair), if any; -1 * when no attributes to return */ protected int _nextAttributeIndex = 0; protected String _localName; protected String _namespaceURI; protected String _textValue; /* /********************************************************************** /* State for handling virtual wrapping /********************************************************************** */ /** * Flag used to indicate that given element should be "replayed". */ protected int _repeatElement; /** * Wrapping state, if any active (null if none) */ protected ElementWrapper _currentWrapper; /** * In cases where we need to 'inject' a virtual END_ELEMENT, we may also * need to restore START_ELEMENT afterwards; if so, this is where names * are held. */ protected String _nextLocalName; protected String _nextNamespaceURI; /* /********************************************************************** /* Life-cycle /********************************************************************** */ public XmlTokenStream(XMLStreamReader xmlReader, Object sourceRef) { _sourceReference = sourceRef; // Let's ensure we point to START_ELEMENT... if (xmlReader.getEventType() != XMLStreamConstants.START_ELEMENT) { throw new IllegalArgumentException("Invalid XMLStreamReader passed: should be pointing to START_ELEMENT (" +XMLStreamConstants.START_ELEMENT+"), instead got "+xmlReader.getEventType()); } _xmlReader = Stax2ReaderAdapter.wrapIfNecessary(xmlReader); _currentState = XML_START_ELEMENT; _localName = _xmlReader.getLocalName(); _namespaceURI = _xmlReader.getNamespaceURI(); _attributeCount = _xmlReader.getAttributeCount(); } public XMLStreamReader2 getXmlReader() { return _xmlReader; } /* /********************************************************************** /* Public API /********************************************************************** */ // DEBUGGING /* public int next() throws IOException { int n = next0(); switch (n) { case XML_START_ELEMENT: System.out.println(" XML-token: XML_START_ELEMENT '"+_localName+"'"); break; case XML_END_ELEMENT: System.out.println(" XML-token: XML_END_ELEMENT '"+_localName+"'"); break; case XML_ATTRIBUTE_NAME: System.out.println(" XML-token: XML_ATTRIBUTE_NAME '"+_localName+"'"); break; case XML_ATTRIBUTE_VALUE: System.out.println(" XML-token: XML_ATTRIBUTE_VALUE '"+_textValue+"'"); break; case XML_TEXT: System.out.println(" XML-token: XML_TEXT '"+_textValue+"'"); break; case XML_END: System.out.println(" XML-token: XML_END"); break; default: throw new IllegalStateException(); } return n; } */ public int next() throws IOException { if (_repeatElement != 0) { return (_currentState = _handleRepeatElement()); } try { return _next(); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); return -1; } } public void skipEndElement() throws IOException { int type = next(); if (type != XML_END_ELEMENT) { throw new IOException("Expected END_ELEMENT, got event of type "+type); } } public int getCurrentToken() { return _currentState; } public String getText() { return _textValue; } public String getLocalName() { return _localName; } public String getNamespaceURI() { return _namespaceURI; } public boolean hasAttributes() { return (_currentState == XML_START_ELEMENT) && (_attributeCount > 0); } public void closeCompletely() throws IOException { try { _xmlReader.closeCompletely(); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } public void close() throws IOException { try { _xmlReader.close(); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } public JsonLocation getCurrentLocation() { return _extractLocation(_xmlReader.getLocationInfo().getCurrentLocation()); } public JsonLocation getTokenLocation() { return _extractLocation(_xmlReader.getLocationInfo().getStartLocation()); } /* /********************************************************************** /* Internal API: more esoteric methods /********************************************************************** */ /** * Method used to add virtual wrapping, which just duplicates START_ELEMENT * stream points to, and its matching closing element. * * @since 2.1 */ protected void repeatStartElement() { //System.out.println(" -> repeatStartElement for "+_localName); // sanity check: can only be used when just returned START_ELEMENT: if (_currentState != XML_START_ELEMENT) { throw new IllegalStateException("Current state not XML_START_ELEMENT (" +XML_START_ELEMENT+") but "+_currentState); } // Important: add wrapper, to keep track... if (_currentWrapper == null) { _currentWrapper = ElementWrapper.matchingWrapper(_currentWrapper, _localName, _namespaceURI); } else { _currentWrapper = ElementWrapper.matchingWrapper(_currentWrapper.getParent(), _localName, _namespaceURI); } _repeatElement = REPLAY_START_DUP; } /** * Method called to skip any attributes current START_ELEMENT may have, * so that they are not returned as token. * * @since 2.1 */ protected void skipAttributes() { if (_currentState == XML_ATTRIBUTE_NAME) { _attributeCount = 0; _currentState = XML_START_ELEMENT; } else if (_currentState == XML_START_ELEMENT) { /* 06-Jan-2012, tatu: As per [#47] it looks like we should NOT do anything * in this particular case, because it occurs when original element had * no attributes and we now point to the first child element. */ // _attributeCount = 0; } else if (_currentState == XML_TEXT) { ; // nothing to do... is it even legal? } else { throw new IllegalStateException("Current state not XML_START_ELEMENT or XML_ATTRIBUTE_NAME (" +XML_START_ELEMENT+") but "+_currentState); } } protected String convertToString() throws IOException { // only applicable to cases where START_OBJECT was induced by attributes if (_currentState != XML_ATTRIBUTE_NAME || _nextAttributeIndex != 0) { return null; } try { String text = _collectUntilTag(); if (text != null && _xmlReader.getEventType() == XMLStreamReader.END_ELEMENT) { if (_currentWrapper != null) { _currentWrapper = _currentWrapper.getParent(); } // just for diagnostics, reset to element name (from first attribute name) _localName = _xmlReader.getLocalName(); _namespaceURI = _xmlReader.getNamespaceURI(); _attributeCount = 0; _currentState = XML_TEXT; _textValue = text; return text; } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } // Anything to do in failed case? Roll back whatever we found or.. ? return null; } /* /********************************************************************** /* Internal methods, parsing /********************************************************************** */ private final int _next() throws XMLStreamException { switch (_currentState) { case XML_ATTRIBUTE_VALUE: ++_nextAttributeIndex; // fall through case XML_START_ELEMENT: // attributes to return? if (_nextAttributeIndex < _attributeCount) { _localName = _xmlReader.getAttributeLocalName(_nextAttributeIndex); _namespaceURI = _xmlReader.getAttributeNamespace(_nextAttributeIndex); _textValue = _xmlReader.getAttributeValue(_nextAttributeIndex); return (_currentState = XML_ATTRIBUTE_NAME); } // otherwise need to find START/END_ELEMENT or text String text = _collectUntilTag(); // If it's START_ELEMENT, ignore any text if (_xmlReader.getEventType() == XMLStreamReader.START_ELEMENT) { return _initStartElement(); } // For END_ELEMENT we will return text, if any if (text != null) { _textValue = text; return (_currentState = XML_TEXT); } return _handleEndElement(); case XML_ATTRIBUTE_NAME: // if we just returned name, will need to just send value next return (_currentState = XML_ATTRIBUTE_VALUE); case XML_TEXT: // text is always followed by END_ELEMENT return _handleEndElement(); case XML_END: return XML_END; // throw new IllegalStateException("No more XML tokens available (end of input)"); } // Ok: must be END_ELEMENT; see what tag we get (or end) switch (_skipUntilTag()) { case XMLStreamConstants.END_DOCUMENT: return (_currentState = XML_END); case XMLStreamConstants.END_ELEMENT: return _handleEndElement(); } // START_ELEMENT... return _initStartElement(); } private final String _collectUntilTag() throws XMLStreamException { String text = null; while (true) { switch (_xmlReader.next()) { case XMLStreamConstants.START_ELEMENT: case XMLStreamConstants.END_ELEMENT: case XMLStreamConstants.END_DOCUMENT: return text; // note: SPACE is ignorable (and seldom seen), not to be included case XMLStreamConstants.CHARACTERS: case XMLStreamConstants.CDATA: if (text == null) { text = _xmlReader.getText(); } else { // can be optimized in future, if need be: text += _xmlReader.getText(); } break; default: // any other type (proc instr, comment etc) is just ignored } } } private final int _skipUntilTag() throws XMLStreamException { while (_xmlReader.hasNext()) { int type; switch (type = _xmlReader.next()) { case XMLStreamConstants.START_ELEMENT: case XMLStreamConstants.END_ELEMENT: case XMLStreamConstants.END_DOCUMENT: return type; default: // any other type (proc instr, comment etc) is just ignored } } throw new IllegalStateException("Expected to find a tag, instead reached end of input"); } /* /********************************************************************** /* Internal methods, other /********************************************************************** */ private final int _initStartElement() throws XMLStreamException { final String ns = _xmlReader.getNamespaceURI(); final String localName = _xmlReader.getLocalName(); _attributeCount = _xmlReader.getAttributeCount(); _nextAttributeIndex = 0; /* Support for virtual wrapping: in wrapping, may either * create a new wrapper scope (if in sub-tree, or matches * wrapper element itself), or implicitly close existing * scope. */ if (_currentWrapper != null) { if (_currentWrapper.matchesWrapper(localName, ns)) { _currentWrapper = _currentWrapper.intermediateWrapper(); } else { // implicit end is more interesting: _localName = _currentWrapper.getWrapperLocalName(); _namespaceURI = _currentWrapper.getWrapperNamespace(); _currentWrapper = _currentWrapper.getParent(); //System.out.println(" START_ELEMENT ("+localName+") not matching '"+_localName+"'; add extra XML-END-ELEMENT!"); // Important! We also need to restore the START_ELEMENT, so: _nextLocalName = localName; _nextNamespaceURI = ns; _repeatElement = REPLAY_START_DELAYED; return (_currentState = XML_END_ELEMENT); } } _localName = localName; _namespaceURI = ns; return (_currentState = XML_START_ELEMENT); } /** * Method called to handle details of repeating "virtual" * start/end elements, needed for handling 'unwrapped' lists. */ protected int _handleRepeatElement() throws IOException { int type = _repeatElement; _repeatElement = 0; if (type == REPLAY_START_DUP) { //System.out.println("handleRepeat for START_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")"); // important: add the virtual element second time, but not with name to match _currentWrapper = _currentWrapper.intermediateWrapper(); return XML_START_ELEMENT; } if (type == REPLAY_END) { //System.out.println("handleRepeat for END_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")"); _localName = _xmlReader.getLocalName(); _namespaceURI = _xmlReader.getNamespaceURI(); if (_currentWrapper != null) { _currentWrapper = _currentWrapper.getParent(); } return XML_END_ELEMENT; } if (type == REPLAY_START_DELAYED) { if (_currentWrapper != null) { _currentWrapper = _currentWrapper.intermediateWrapper(); } _localName = _nextLocalName; _namespaceURI = _nextNamespaceURI; _nextLocalName = null; _nextNamespaceURI = null; //System.out.println("handleRepeat for START_DELAYED: "+_localName+" ("+_xmlReader.getLocalName()+")"); return XML_START_ELEMENT; } throw new IllegalStateException("Unrecognized type to repeat: "+type); } private final int _handleEndElement() { if (_currentWrapper != null) { ElementWrapper w = _currentWrapper; // important: if we close the scope, must duplicate END_ELEMENT as well if (w.isMatching()) { _repeatElement = REPLAY_END; _localName = w.getWrapperLocalName(); _namespaceURI = w.getWrapperNamespace(); _currentWrapper = _currentWrapper.getParent(); //System.out.println(" IMPLICIT requestRepeat of END_ELEMENT '"+_localName); } else { _currentWrapper = _currentWrapper.getParent(); } } return (_currentState = XML_END_ELEMENT); } private JsonLocation _extractLocation(XMLStreamLocation2 location) { if (location == null) { // just for impls that might pass null... return new JsonLocation(_sourceReference, -1, -1, -1); } return new JsonLocation(_sourceReference, location.getCharacterOffset(), location.getLineNumber(), location.getColumnNumber()); } // for DEBUGGING @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("(Token stream:"); sb.append(" state=").append(_currentState); sb.append(" attr#=").append(_attributeCount); sb.append(" nextAttr#=").append(_nextAttributeIndex); sb.append(" name=").append(_localName); sb.append(" text=").append(_textValue); sb.append(" repeat?=").append(_repeatElement); sb.append(" wrapper=[").append(_currentWrapper); sb.append("] repeatElement=").append(_repeatElement); sb.append(" nextName=").append(_nextLocalName); sb.append(")"); return sb.toString(); } } 000077500000000000000000000000001251656754200351065ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/jaxbXmlJaxbAnnotationIntrospector.java000066400000000000000000000106701251656754200437710ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/jaxbpackage com.fasterxml.jackson.dataformat.xml.jaxb; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Member; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; /** * Alternative {@link com.fasterxml.jackson.databind.AnnotationIntrospector} * implementation that * builds on {@link JaxbAnnotationIntrospector}. *

* NOTE: since version 2.4, it should NOT be necessary to use this class; * instead, plain {@link JaxbAnnotationIntrospector} should fully work. * With previous versions some aspects were not fully working and this * class was necessary. */ public class XmlJaxbAnnotationIntrospector extends JaxbAnnotationIntrospector implements XmlAnnotationIntrospector { private static final long serialVersionUID = 6477843393758275877L; @Deprecated public XmlJaxbAnnotationIntrospector() { super(); } public XmlJaxbAnnotationIntrospector(TypeFactory typeFactory) { super(typeFactory); } /* /********************************************************************** /* XmlAnnotationIntrospector overrides /********************************************************************** */ // Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate @Override public String findNamespace(Annotated ann) { return super.findNamespace(ann); } // Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate @Override public Boolean isOutputAsAttribute(Annotated ann) { return super.isOutputAsAttribute(ann); } // Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate @Override public Boolean isOutputAsText(Annotated ann) { return super.isOutputAsText(ann); } @Override public Boolean isOutputAsCData(Annotated ann) { //There is no CData annotation in JAXB return null; } /* /********************************************************************** /* Helper methods /********************************************************************** */ /* private String handleJaxbDefault(String value) { return MARKER_FOR_DEFAULT.equals(value) ? "" : value; } */ @Deprecated // since 2.4; not used by this module protected A findAnnotation(Class annotationClass, Annotated annotated, boolean includePackage, boolean includeClass, boolean includeSuperclasses) { A annotation = annotated.getAnnotation(annotationClass); if (annotation != null) { return annotation; } Class memberClass = null; if (annotated instanceof AnnotatedParameter) { memberClass = ((AnnotatedParameter) annotated).getDeclaringClass(); } else { AnnotatedElement annType = annotated.getAnnotated(); if (annType instanceof Member) { memberClass = ((Member) annType).getDeclaringClass(); if (includeClass) { annotation = (A) memberClass.getAnnotation(annotationClass); if (annotation != null) { return annotation; } } } else if (annType instanceof Class) { memberClass = (Class) annType; } else { throw new IllegalStateException("Unsupported annotated member: " + annotated.getClass().getName()); } } if (memberClass != null) { if (includeSuperclasses) { Class superclass = memberClass.getSuperclass(); while (superclass != null && superclass != Object.class) { annotation = (A) superclass.getAnnotation(annotationClass); if (annotation != null) { return annotation; } superclass = superclass.getSuperclass(); } } if (includePackage) { Package pkg = memberClass.getPackage(); if (pkg != null) { return memberClass.getPackage().getAnnotation(annotationClass); } } } return null; } } package-info.java000066400000000000000000000004141251656754200373500ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/** * Package that contains XML-based backends which can serialize POJOs * to and deserialize from XML, using Stax XML parsers and generators * for XML processing and mostly standard Jackson data binding otherwise. */ package com.fasterxml.jackson.dataformat.xml; 000077500000000000000000000000001251656754200347535ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serToXmlGenerator.java000066400000000000000000001112651251656754200405360ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.codehaus.stax2.XMLStreamWriter2; import org.codehaus.stax2.ri.Stax2WriterAdapter; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.json.JsonWriteContext; import com.fasterxml.jackson.dataformat.xml.XmlPrettyPrinter; import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter; import com.fasterxml.jackson.dataformat.xml.util.StaxUtil; /** * {@link JsonGenerator} that outputs JAXB-style XML output instead of JSON content. * Operation requires calling code (usually either standard Jackson serializers, * or in some cases (like BeanSerializer) customised ones) to do * additional configuration calls beyond regular {@link JsonGenerator} API, * mostly to pass namespace information. */ public final class ToXmlGenerator extends GeneratorBase { /** * If we support optional definition of element names, this is the element * name to use... */ protected final static String DEFAULT_UNKNOWN_ELEMENT = "unknown"; /** * Enumeration that defines all togglable extra XML-specific features */ public enum Feature { /** * Feature that controls whether XML declaration should be written before * when generator is initialized (true) or not (false) */ WRITE_XML_DECLARATION(false), /** * Feature that controls whether output should be done as XML 1.1; if so, * certain aspects may differ from default (1.0) processing: for example, * XML declaration will be automatically added (regardless of setting * WRITE_XML_DECLARATION) as this is required for reader to * know to use 1.1 compliant handling. XML 1.1 can be used to allow quoted * control characters (Ascii codes 0 through 31) as well as additional linefeeds * and name characters. */ WRITE_XML_1_1(false) ; final boolean _defaultState; final int _mask; /** * Method that calculates bit set (flags) of all features that * are enabled by default. */ public static int collectDefaults() { int flags = 0; for (Feature f : values()) { if (f.enabledByDefault()) { flags |= f.getMask(); } } return flags; } private Feature(boolean defaultState) { _defaultState = defaultState; _mask = (1 << ordinal()); } public boolean enabledByDefault() { return _defaultState; } public int getMask() { return _mask; } } /* /********************************************************** /* Configuration /********************************************************** */ final protected XMLStreamWriter2 _xmlWriter; final protected XMLStreamWriter _originalXmlWriter; /** * Marker flag set if the underlying stream writer has to emulate * Stax2 API: this is problematic if trying to use {@link #writeRaw} calls. */ final protected boolean _stax2Emulation; final protected IOContext _ioContext; /** * Bit flag composed of bits that indicate which * {@link ToXmlGenerator.Feature}s * are enabled. */ protected int _xmlFeatures; /** * We may need to use XML-specific indentation as well */ protected XmlPrettyPrinter _xmlPrettyPrinter; /* /********************************************************** /* XML Output state /********************************************************** */ /** * Marker set when {@link #initGenerator()} has been called or not. * * @since 2.2 */ protected boolean _initialized; /** * Element or attribute name to use for next output call. * Assigned by either code that initiates serialization * or bean serializer. */ protected QName _nextName = null; /** * Marker flag that indicates whether next name to write * implies an attribute (true) or element (false) */ protected boolean _nextIsAttribute = false; /** * Marker flag used to indicate that the next write of a (property) * value should be done without using surrounding start/end * elements. Flag is to be cleared once unwrapping has been triggered * once. */ protected boolean _nextIsUnwrapped = false; /** * Marker flag used to indicate that the next write of a (property) * value should be as CData */ protected boolean _nextIsCData = false; /** * To support proper serialization of arrays it is necessary to keep * stack of element names, so that we can "revert" to earlier */ protected LinkedList _elementNameStack = new LinkedList(); /* /********************************************************** /* Life-cycle /********************************************************** */ public ToXmlGenerator(IOContext ctxt, int genericGeneratorFeatures, int xmlFeatures, ObjectCodec codec, XMLStreamWriter sw) { super(genericGeneratorFeatures, codec); _xmlFeatures = xmlFeatures; _ioContext = ctxt; _originalXmlWriter = sw; _xmlWriter = Stax2WriterAdapter.wrapIfNecessary(sw); _stax2Emulation = (_xmlWriter != sw); _xmlPrettyPrinter = (_cfgPrettyPrinter instanceof XmlPrettyPrinter) ? (XmlPrettyPrinter) _cfgPrettyPrinter : null; } /** * Method called before writing any other output, to optionally * output XML declaration. */ public void initGenerator() throws IOException, JsonGenerationException { if (_initialized) { return; } _initialized = true; try { if ((_xmlFeatures & Feature.WRITE_XML_1_1.getMask()) != 0) { _xmlWriter.writeStartDocument("UTF-8", "1.1"); } else if ((_xmlFeatures & Feature.WRITE_XML_DECLARATION.getMask()) != 0) { _xmlWriter.writeStartDocument("UTF-8", "1.0"); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } /* /********************************************************** /* Extended API, configuration /********************************************************** */ public ToXmlGenerator enable(Feature f) { _xmlFeatures |= f.getMask(); return this; } public ToXmlGenerator disable(Feature f) { _xmlFeatures &= ~f.getMask(); return this; } public final boolean isEnabled(Feature f) { return (_xmlFeatures & f.getMask()) != 0; } public ToXmlGenerator configure(Feature f, boolean state) { if (state) { enable(f); } else { disable(f); } return this; } /* /********************************************************** /* Extended API, access to some internal components /********************************************************** */ /** * Method that allows application direct access to underlying * Stax {@link XMLStreamWriter}. Note that use of writer is * discouraged, and may interfere with processing of this writer; * however, occasionally it may be necessary. *

* Note: writer instance will always be of type * {@link org.codehaus.stax2.XMLStreamWriter2} (including * Typed Access API) so upcasts are safe. */ public XMLStreamWriter getStaxWriter() { return _xmlWriter; } /* /********************************************************** /* Extended API, passing XML specific settings /********************************************************** */ public void setNextIsAttribute(boolean isAttribute) { _nextIsAttribute = isAttribute; } public void setNextIsUnwrapped(boolean isUnwrapped) { _nextIsUnwrapped = isUnwrapped; } public void setNextIsCData(boolean isCData) { _nextIsCData = isCData; } public final void setNextName(QName name) { _nextName = name; } /** * Method that does same as {@link #setNextName}, unless * a name has already been set. * * @since 2.1.2 */ public final boolean setNextNameIfMissing(QName name) { if (_nextName == null) { _nextName = name; return true; } return false; } /** * Methdod called when a structured (collection, array, map) is being * output. * * @param wrapperName Element used as wrapper around elements, if any (null if none) * @param wrappedName Element used around individual content items (can not * be null) */ public void startWrappedValue(QName wrapperName, QName wrappedName) throws IOException, JsonGenerationException { if (wrapperName != null) { try { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeStartElement(_xmlWriter, wrapperName.getNamespaceURI(), wrapperName.getLocalPart()); } else { _xmlWriter.writeStartElement(wrapperName.getNamespaceURI(), wrapperName.getLocalPart()); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } this.setNextName(wrappedName); } /** * Method called after a structured collection output has completed */ public void finishWrappedValue(QName wrapperName, QName wrappedName) throws IOException, JsonGenerationException { // First: wrapper to close? if (wrapperName != null) { try { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeEndElement(_xmlWriter, _writeContext.getEntryCount()); } else { _xmlWriter.writeEndElement(); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } } /** * Trivial helper method called when to add a replicated wrapper name * * @since 2.2 */ public void writeRepeatedFieldName() throws IOException, JsonGenerationException { if (_writeContext.writeFieldName(_nextName.getLocalPart()) == JsonWriteContext.STATUS_EXPECT_VALUE) { _reportError("Can not write a field name, expecting a value"); } } /* /********************************************************** /* JsonGenerator method overrides /********************************************************** */ /* Most overrides in this section are just to make methods final, * to allow better inlining... */ @Override public final void writeFieldName(String name) throws IOException, JsonGenerationException { if (_writeContext.writeFieldName(name) == JsonWriteContext.STATUS_EXPECT_VALUE) { _reportError("Can not write a field name, expecting a value"); } // Should this ever get called? String ns = (_nextName == null) ? "" : _nextName.getNamespaceURI(); setNextName(new QName(ns, name)); } @Override public final void writeStringField(String fieldName, String value) throws IOException, JsonGenerationException { writeFieldName(fieldName); writeString(value); } /* /********************************************************** /* JsonGenerator output method implementations, structural /********************************************************** */ @Override public final void writeStartArray() throws IOException, JsonGenerationException { _verifyValueWrite("start an array"); _writeContext = _writeContext.createChildArrayContext(); if (_cfgPrettyPrinter != null) { _cfgPrettyPrinter.writeStartArray(this); } else { // nothing to do here; no-operation } } @Override public final void writeEndArray() throws IOException, JsonGenerationException { if (!_writeContext.inArray()) { _reportError("Current context not an ARRAY but "+_writeContext.getTypeDesc()); } if (_cfgPrettyPrinter != null) { _cfgPrettyPrinter.writeEndArray(this, _writeContext.getEntryCount()); } else { // nothing to do here; no-operation } _writeContext = _writeContext.getParent(); } @Override public final void writeStartObject() throws IOException, JsonGenerationException { _verifyValueWrite("start an object"); _writeContext = _writeContext.createChildObjectContext(); if (_cfgPrettyPrinter != null) { _cfgPrettyPrinter.writeStartObject(this); } else { _handleStartObject(); } } @Override public final void writeEndObject() throws IOException, JsonGenerationException { if (!_writeContext.inObject()) { _reportError("Current context not an object but "+_writeContext.getTypeDesc()); } _writeContext = _writeContext.getParent(); if (_cfgPrettyPrinter != null) { // as per [Issue#45], need to suppress indentation if only attributes written: int count = _nextIsAttribute ? 0 : _writeContext.getEntryCount(); _cfgPrettyPrinter.writeEndObject(this, count); } else { _handleEndObject(); } } // note: public just because pretty printer needs to make a callback public final void _handleStartObject() throws IOException, JsonGenerationException { if (_nextName == null) { handleMissingName(); } // Need to keep track of names to make Lists work correctly _elementNameStack.addLast(_nextName); try { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } // note: public just because pretty printer needs to make a callback public final void _handleEndObject() throws IOException, JsonGenerationException { // We may want to repeat same element, so: if (_elementNameStack.isEmpty()) { throw new JsonGenerationException("Can not write END_ELEMENT without open START_ELEMENT"); } _nextName = _elementNameStack.removeLast(); try { // note: since attributes don't nest, can only have one attribute active, so: _nextIsAttribute = false; _xmlWriter.writeEndElement(); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } /* /********************************************************** /* Output method implementations, textual /********************************************************** */ @Override public void writeFieldName(SerializableString name) throws IOException, JsonGenerationException { writeFieldName(name.getValue()); } @Override public void writeString(String text) throws IOException,JsonGenerationException { _verifyValueWrite("write String value"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { // must write attribute name and value with one call _xmlWriter.writeAttribute(_nextName.getNamespaceURI(), _nextName.getLocalPart(), text); } else if (checkNextIsUnwrapped()) { // [Issue#56] Should figure out how to prevent indentation for end element // but for now, let's just make sure structure is correct //if (_xmlPrettyPrinter != null) { ... } if(_nextIsCData) { _xmlWriter.writeCData(text); } else { _xmlWriter.writeCharacters(text); } } else if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), text, _nextIsCData); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); if(_nextIsCData) { _xmlWriter.writeCData(text); } else { _xmlWriter.writeCharacters(text); } _xmlWriter.writeEndElement(); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeString(char[] text, int offset, int len) throws IOException, JsonGenerationException { _verifyValueWrite("write String value"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeAttribute(_nextName.getNamespaceURI(), _nextName.getLocalPart(), new String(text, offset, len)); } else if (checkNextIsUnwrapped()) { // should we consider pretty-printing or not? if(_nextIsCData) { _xmlWriter.writeCData(text, offset, len); } else { _xmlWriter.writeCharacters(text, offset, len); } } else if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), text, offset, len, _nextIsCData); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); if(_nextIsCData) { _xmlWriter.writeCData(text, offset, len); } else { _xmlWriter.writeCharacters(text, offset, len); } _xmlWriter.writeEndElement(); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeString(SerializableString text) throws IOException, JsonGenerationException { writeString(text.getValue()); } @Override public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException, JsonGenerationException { // could add support for this case if we really want it (and can make Stax2 support it) _reportUnsupportedOperation(); } @Override public void writeUTF8String(byte[] text, int offset, int length) throws IOException, JsonGenerationException { // could add support for this case if we really want it (and can make Stax2 support it) _reportUnsupportedOperation(); } /* /********************************************************** /* Output method implementations, unprocessed ("raw") /********************************************************** */ @Override public void writeRaw(String text) throws IOException, JsonGenerationException { // [Issue#39] if (_stax2Emulation) { _reportUnimplementedStax2("writeRaw"); } try { _xmlWriter.writeRaw(text); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeRaw(String text, int offset, int len) throws IOException, JsonGenerationException { // [Issue#39] if (_stax2Emulation) { _reportUnimplementedStax2("writeRaw"); } try { _xmlWriter.writeRaw(text, offset, len); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeRaw(char[] text, int offset, int len) throws IOException, JsonGenerationException { // [Issue#39] if (_stax2Emulation) { _reportUnimplementedStax2("writeRaw"); } try { _xmlWriter.writeRaw(text, offset, len); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeRaw(char c) throws IOException, JsonGenerationException { writeRaw(String.valueOf(c)); } /* /********************************************************** /* Output method implementations, base64-encoded binary /********************************************************** */ @Override public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException, JsonGenerationException { if (data == null) { writeNull(); return; } _verifyValueWrite("write Binary value"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { // Stax2 API only has 'full buffer' write method: byte[] fullBuffer = toFullBuffer(data, offset, len); _xmlWriter.writeBinaryAttribute("", _nextName.getNamespaceURI(), _nextName.getLocalPart(), fullBuffer); } else if (checkNextIsUnwrapped()) { // should we consider pretty-printing or not? _xmlWriter.writeBinary(data, offset, len); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), data, offset, len); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeBinary(data, offset, len); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } private byte[] toFullBuffer(byte[] data, int offset, int len) { // might already be ok: if (offset == 0 && len == data.length) { return data; } byte[] result = new byte[len]; if (len > 0) { System.arraycopy(data, offset, result, 0, len); } return result; } /* /********************************************************** /* Output method implementations, primitive /********************************************************** */ @Override public void writeBoolean(boolean value) throws IOException, JsonGenerationException { _verifyValueWrite("write boolean value"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeBooleanAttribute(null, _nextName.getNamespaceURI(), _nextName.getLocalPart(), value); } else if (checkNextIsUnwrapped()) { // should we consider pretty-printing or not? _xmlWriter.writeBoolean(value); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), value); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeBoolean(value); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNull() throws IOException, JsonGenerationException { _verifyValueWrite("write null value"); if (_nextName == null) { handleMissingName(); } // !!! TODO: proper use of 'xsd:isNil' ? try { if (_nextIsAttribute) { /* With attributes, best just leave it out, right? (since there's no way * to use 'xsi:nil') */ } else if (checkNextIsUnwrapped()) { // as with above, best left unwritten? } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafNullElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart()); } else { _xmlWriter.writeEmptyElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(int i) throws IOException, JsonGenerationException { _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeIntAttribute(null, _nextName.getNamespaceURI(), _nextName.getLocalPart(), i); } else if (checkNextIsUnwrapped()) { // should we consider pretty-printing or not? _xmlWriter.writeInt(i); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), i); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeInt(i); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(long l) throws IOException, JsonGenerationException { _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeLongAttribute(null, _nextName.getNamespaceURI(), _nextName.getLocalPart(), l); } else if (checkNextIsUnwrapped()) { _xmlWriter.writeLong(l); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), l); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeLong(l); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(double d) throws IOException, JsonGenerationException { _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeDoubleAttribute(null, _nextName.getNamespaceURI(), _nextName.getLocalPart(), d); } else if (checkNextIsUnwrapped()) { _xmlWriter.writeDouble(d); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), d); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeDouble(d); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(float f) throws IOException, JsonGenerationException { _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeFloatAttribute(null, _nextName.getNamespaceURI(), _nextName.getLocalPart(), f); } else if (checkNextIsUnwrapped()) { _xmlWriter.writeFloat(f); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), f); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeFloat(f); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(BigDecimal dec) throws IOException, JsonGenerationException { if (dec == null) { writeNull(); return; } _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } boolean usePlain = isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); try { if (_nextIsAttribute) { if (usePlain) { _xmlWriter.writeAttribute("", _nextName.getNamespaceURI(), _nextName.getLocalPart(), dec.toPlainString()); } else { _xmlWriter.writeDecimalAttribute("", _nextName.getNamespaceURI(), _nextName.getLocalPart(), dec); } } else if (checkNextIsUnwrapped()) { if (usePlain) { _xmlWriter.writeCharacters(dec.toPlainString()); } else { _xmlWriter.writeDecimal(dec); } } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), dec); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); if (usePlain) { _xmlWriter.writeDecimal(dec); } else { _xmlWriter.writeCharacters(dec.toPlainString()); } _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(BigInteger value) throws IOException, JsonGenerationException { if (value == null) { writeNull(); return; } _verifyValueWrite("write number"); if (_nextName == null) { handleMissingName(); } try { if (_nextIsAttribute) { _xmlWriter.writeIntegerAttribute("", _nextName.getNamespaceURI(), _nextName.getLocalPart(), value); } else if (checkNextIsUnwrapped()) { _xmlWriter.writeInteger(value); } else { if (_xmlPrettyPrinter != null) { _xmlPrettyPrinter.writeLeafElement(_xmlWriter, _nextName.getNamespaceURI(), _nextName.getLocalPart(), value); } else { _xmlWriter.writeStartElement(_nextName.getNamespaceURI(), _nextName.getLocalPart()); _xmlWriter.writeInteger(value); _xmlWriter.writeEndElement(); } } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override public void writeNumber(String encodedValue) throws IOException,JsonGenerationException, UnsupportedOperationException { writeString(encodedValue); } /* /********************************************************** /* Implementations, overrides for other methods /********************************************************** */ @Override protected final void _verifyValueWrite(String typeMsg) throws IOException, JsonGenerationException { int status = _writeContext.writeValue(); if (status == JsonWriteContext.STATUS_EXPECT_NAME) { _reportError("Can not "+typeMsg+", expecting field name"); } } /** * Standard JSON indenter does not work well with XML, use * default XML indenter instead. */ @Override public final JsonGenerator useDefaultPrettyPrinter() { // related to [dataformat-xml#136], need to verify: if (_cfgPrettyPrinter != null) { return this; } return setPrettyPrinter(new DefaultXmlPrettyPrinter()); } @Override public JsonGenerator setPrettyPrinter(PrettyPrinter pp) { _cfgPrettyPrinter = pp; _xmlPrettyPrinter = (pp instanceof XmlPrettyPrinter) ? (XmlPrettyPrinter) pp : null; return this; } /* /********************************************************** /* Low-level output handling /********************************************************** */ @Override public final void flush() throws IOException { if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) { try { _xmlWriter.flush(); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } } @Override public void close() throws IOException { // boolean wasClosed = _closed; super.close(); /* 05-Dec-2008, tatu: To add [JACKSON-27], need to close open * scopes. */ // First: let's see that we still have buffers... if (isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)) { try { while (true) { JsonStreamContext ctxt = getOutputContext(); if (ctxt.inArray()) { writeEndArray(); } else if (ctxt.inObject()) { writeEndObject(); } else { break; } } } catch (ArrayIndexOutOfBoundsException e) { /* 29-Nov-2010, tatu: Stupid, stupid SJSXP doesn't do array checks, so we get * hit by this as a collateral problem in some cases. Yuck. */ throw new JsonGenerationException(e); } } try { if (_ioContext.isResourceManaged() || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) { _xmlWriter.closeCompletely(); } else { _xmlWriter.close(); } } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } @Override protected void _releaseBuffers() { // Nothing to do here, as we have no buffers } /* /********************************************************** /* Internal methods /********************************************************** */ /** * Method called to see if unwrapping is required; and if so, * clear the flag (so further calls will return 'false' unless * state is re-set) */ protected boolean checkNextIsUnwrapped() { if (_nextIsUnwrapped) { _nextIsUnwrapped = false; return true; } return false; } protected void handleMissingName() { throw new IllegalStateException("No element/attribute name specified when trying to output element"); } /** * Method called */ protected void _reportUnimplementedStax2(String missingMethod) throws IOException { throw new JsonGenerationException("Underlying Stax XMLStreamWriter (of type " +_originalXmlWriter.getClass().getName() +") does not implement Stax2 API natively and is missing method '" +missingMethod+"': this breaks functionality such as indentation that relies on it. " +"You need to upgrade to using compliant Stax implementation like Woodstox or Aalto"); } } UnwrappingXmlBeanSerializer.java000066400000000000000000000105401251656754200432510ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Copy of {@link UnwrappingBeanSerializer} required to extend * {@link XmlBeanSerializerBase} for XML-specific handling. * * @author Pascal Gélinas * */ public class UnwrappingXmlBeanSerializer extends XmlBeanSerializerBase { private static final long serialVersionUID = 1L; /** * Transformer used to add prefix and/or suffix for properties of unwrapped * POJO. */ protected final NameTransformer _nameTransformer; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ /** * Constructor used for creating unwrapping instance of a standard * BeanSerializer */ public UnwrappingXmlBeanSerializer(XmlBeanSerializerBase src, NameTransformer transformer) { super(src, transformer); _nameTransformer = transformer; } public UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); _nameTransformer = src._nameTransformer; } public UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); _nameTransformer = src._nameTransformer; } protected UnwrappingXmlBeanSerializer(UnwrappingXmlBeanSerializer src, String[] toIgnore) { super(src, toIgnore); _nameTransformer = src._nameTransformer; } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ @Override public JsonSerializer unwrappingSerializer(NameTransformer transformer) { // !!! 23-Jan-2012, tatu: Should we chain transformers? return new UnwrappingXmlBeanSerializer(this, transformer); } @Override public boolean isUnwrappingSerializer() { return true; // sure is } @Override public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) { return new UnwrappingXmlBeanSerializer(this, objectIdWriter); } @Override protected BeanSerializerBase withFilterId(Object filterId) { return new UnwrappingXmlBeanSerializer(this, _objectIdWriter, filterId); } @Override protected BeanSerializerBase withIgnorals(String[] toIgnore) { return new UnwrappingXmlBeanSerializer(this, toIgnore); } /** * JSON Array output can not be done if unwrapping operation is requested; * so implementation will simply return 'this'. */ @Override protected BeanSerializerBase asArraySerializer() { return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ /** * Main serialization method that will delegate actual output to configured * {@link BeanPropertyWriter} instances. */ @Override public final void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { if (_objectIdWriter != null) { _serializeWithObjectId(bean, jgen, provider, false); return; } if (_propertyFilterId != null) { serializeFieldsFiltered(bean, jgen, provider); } else { serializeFields(bean, jgen, provider); } } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "UnwrappingXmlBeanSerializer for " + handledType().getName(); } } XmlBeanPropertyWriter.java000066400000000000000000000121201251656754200421020ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import javax.xml.namespace.QName; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; /** * Property writer sub-class used for handling element wrapping needed for serializing * collection (array, Collection; possibly Map) types. */ public class XmlBeanPropertyWriter extends BeanPropertyWriter { /* /********************************************************** /* Config settings /********************************************************** */ /** * Element name used as wrapper for collection. */ protected final QName _wrapperQName; /** * Element name used for items in the collection */ protected final QName _wrappedQName; /* /********************************************************** /* Life-cycle: construction, configuration /********************************************************** */ public XmlBeanPropertyWriter(BeanPropertyWriter wrapped, PropertyName wrapperName, PropertyName wrappedName) { this(wrapped, wrapperName, wrappedName, null); } public XmlBeanPropertyWriter(BeanPropertyWriter wrapped, PropertyName wrapperName, PropertyName wrappedName, JsonSerializer serializer) { super(wrapped); _wrapperQName = _qname(wrapperName); _wrappedQName = _qname(wrappedName); if (serializer != null) { assignSerializer(serializer); } } private QName _qname(PropertyName n) { String ns = n.getNamespace(); if (ns == null) { ns = ""; } return new QName(ns, n.getSimpleName()); } /* /********************************************************** /* Overridden methods /********************************************************** */ /** * Overridden version so that we can wrap output within wrapper element if * and as necessary. */ @Override public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception { Object value = get(bean); /* 13-Feb-2014, tatu: As per [#103], default handling does not really * work here. Rather, we need just a wrapping and should NOT call * null handler, as it does not know what to do... * * Question, however, is what should it be serialized as. We have two main * choices; equivalent empty List, and "nothing" (missing). Let's start with * empty List? But producing missing entry is non-trivial... */ if (value == null) { // if (_nullSerializer != null) { ... } // For Empty List, we'd do this: /* @SuppressWarnings("resource") final ToXmlGenerator xmlGen = (jgen instanceof ToXmlGenerator) ? (ToXmlGenerator) jgen : null; if (xmlGen != null) { xmlGen.startWrappedValue(_wrapperQName, _wrappedQName); xmlGen.finishWrappedValue(_wrapperQName, _wrappedQName); } */ // but for missing thing, well, just output nothing return; } // then find serializer to use JsonSerializer ser = _serializer; if (ser == null) { Class cls = value.getClass(); PropertySerializerMap map = _dynamicSerializers; ser = map.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(map, cls, prov); } } // and then see if we must suppress certain values (default, empty) if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { return; } } else if (_suppressableValue.equals(value)) { return; } } // For non-nulls: simple check for direct cycles if (value == bean) { // NOTE: method signature here change 2.3->2.4 if (_handleSelfReference(bean, jgen, prov, ser)) { return; } } @SuppressWarnings("resource") final ToXmlGenerator xmlGen = (jgen instanceof ToXmlGenerator) ? (ToXmlGenerator) jgen : null; // Ok then; addition we want to do is to add wrapper element, and that's what happens here // 19-Aug-2013, tatu: ... except for those nasty 'convertValue()' calls... if (xmlGen != null) { xmlGen.startWrappedValue(_wrapperQName, _wrappedQName); } jgen.writeFieldName(_name); if (_typeSerializer == null) { ser.serialize(value, jgen, prov); } else { ser.serializeWithType(value, jgen, prov, _typeSerializer); } if (xmlGen != null) { xmlGen.finishWrappedValue(_wrapperQName, _wrappedQName); } } } XmlBeanSerializer.java000066400000000000000000000101721251656754200411770ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.BeanSerializer; import com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Variant of {@link BeanSerializer} for XML handling. * * @author Pascal Gélinas */ public class XmlBeanSerializer extends XmlBeanSerializerBase { private static final long serialVersionUID = 1L; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ public XmlBeanSerializer(BeanSerializerBase src) { super(src); } public XmlBeanSerializer(XmlBeanSerializerBase src, ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); } public XmlBeanSerializer(XmlBeanSerializerBase src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); } public XmlBeanSerializer(XmlBeanSerializerBase src, String[] toIgnore) { super(src, toIgnore); } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ @Override public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) { return new UnwrappingXmlBeanSerializer(this, unwrapper); } @Override public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) { return new XmlBeanSerializer(this, objectIdWriter, _propertyFilterId); } @Override protected BeanSerializerBase withFilterId(Object filterId) { return new XmlBeanSerializer(this, _objectIdWriter, filterId); } @Override protected BeanSerializerBase withIgnorals(String[] toIgnore) { return new XmlBeanSerializer(this, toIgnore); } /** * Implementation has to check whether as-array serialization * is possible reliably; if (and only if) so, will construct * a {@link BeanAsArraySerializer}, otherwise will return this * serializer as is. */ @Override protected BeanSerializerBase asArraySerializer() { /* Can not: * * - have Object Id (may be allowed in future) * - have any getter * */ if ((_objectIdWriter == null) && (_anyGetterWriter == null) && (_propertyFilterId == null) ) { return new BeanAsArraySerializer(this); } // already is one, so: return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ /** * Main serialization method that will delegate actual output to configured * {@link BeanPropertyWriter} instances. */ @Override public void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (_objectIdWriter != null) { _serializeWithObjectId(bean, jgen, provider, true); return; } jgen.writeStartObject(); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, jgen, provider); } else { serializeFields(bean, jgen, provider); } jgen.writeEndObject(); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "XmlBeanSerializer for " + handledType().getName(); } } XmlBeanSerializerBase.java000066400000000000000000000363171251656754200420030ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import java.util.BitSet; import javax.xml.namespace.QName; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; import com.fasterxml.jackson.dataformat.xml.util.XmlInfo; /** * Specific sub-class of {@link BeanSerializerBase} needed to take care * of some xml-specific aspects, such as distinction between attributes * and elements. */ @SuppressWarnings("serial") public abstract class XmlBeanSerializerBase extends BeanSerializerBase { /** * Marker used for storing associated internal data with {@link BeanPropertyWriter} * instances; to mark instances that are to be written out as attributes. * Created as separate non-interned String to ensure there are no collisions. */ public final static String KEY_XML_INFO = new String("xmlInfo"); /** * Number of attributes to write; these will have been ordered to be the first * properties to write. */ protected final int _attributeCount; /** * Index of "text value" property we have, if any; can have at most * one such property. */ protected final int _textPropertyIndex; /** * Array that contains namespace URIs associated with properties, if any; * null if no namespace definitions have been assigned */ protected final QName[] _xmlNames; /** * Optional set of indexes of properties that should be serialized as CDATA, * instead of regular XML text segment. Left as null in cases where none of * element values are to be written in such a way. */ protected final BitSet _cdata; public XmlBeanSerializerBase(BeanSerializerBase src) { super(src); /* Then make sure attributes are sorted before elements, keep track * of how many there are altogether */ int attrCount = 0; for (BeanPropertyWriter bpw : _props) { if (_isAttribute(bpw)) { // Yup: let's build re-ordered list then attrCount = _orderAttributesFirst(_props, _filteredProps); break; } } _attributeCount = attrCount; // also: pre-compute need, if any, for CDATA handling: BitSet cdata = null; for (int i = 0, len = _props.length; i < len; ++i) { BeanPropertyWriter bpw = _props[i]; if (_isCData(bpw)) { if (cdata == null) { cdata = new BitSet(len); } cdata.set(i); } } _cdata = cdata; // And then collect namespace information _xmlNames = new QName[_props.length]; int textIndex = -1; for (int i = 0, len = _props.length; i < len; ++i) { BeanPropertyWriter bpw = _props[i]; XmlInfo info = (XmlInfo) bpw.getInternalSetting(KEY_XML_INFO); String ns = null; if (info != null) { ns = info.getNamespace(); if (textIndex < 0 && info.isText()) { textIndex = i; } } _xmlNames[i] = new QName((ns == null) ? "" : ns, bpw.getName()); } _textPropertyIndex = textIndex; } protected XmlBeanSerializerBase(XmlBeanSerializerBase src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); _attributeCount = src._attributeCount; _textPropertyIndex = src._textPropertyIndex; _xmlNames = src._xmlNames; _cdata = src._cdata; } protected XmlBeanSerializerBase(XmlBeanSerializerBase src, ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); _attributeCount = src._attributeCount; _textPropertyIndex = src._textPropertyIndex; _xmlNames = src._xmlNames; _cdata = src._cdata; } protected XmlBeanSerializerBase(XmlBeanSerializerBase src, String[] toIgnore) { super(src, toIgnore); _attributeCount = src._attributeCount; _textPropertyIndex = src._textPropertyIndex; _xmlNames = src._xmlNames; _cdata = src._cdata; } public XmlBeanSerializerBase(XmlBeanSerializerBase src, NameTransformer transformer) { super(src, transformer); _attributeCount = src._attributeCount; _textPropertyIndex = src._textPropertyIndex; _xmlNames = src._xmlNames; _cdata = src._cdata; } /* /********************************************************** /* Overridden serialization methods /********************************************************** */ /** * Main serialization method needs to be overridden to allow XML-specific * extra handling, such as indication of whether to write attributes or * elements. */ @Override protected void serializeFields(Object bean, JsonGenerator gen0, SerializerProvider provider) throws IOException { // 19-Aug-2013, tatu: During 'convertValue()', need to skip if (!(gen0 instanceof ToXmlGenerator)) { super.serializeFields(bean, gen0, provider); return; } final ToXmlGenerator xgen = (ToXmlGenerator) gen0; final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } final int attrCount = _attributeCount; final boolean isAttribute = xgen._nextIsAttribute; if (attrCount > 0) { xgen.setNextIsAttribute(true); } final int textIndex = _textPropertyIndex; final QName[] xmlNames = _xmlNames; int i = 0; final BitSet cdata = _cdata; try { for (final int len = props.length; i < len; ++i) { // 28-jan-2014, pascal: we don't want to reset the attribute flag if we are an unwrapping serializer // that started with nextIsAttribute to true because all properties should be unwrapped as attributes too. if (i == attrCount && !(isAttribute && isUnwrappingSerializer())) { xgen.setNextIsAttribute(false); } // also: if this is property to write as text ("unwrap"), need to: if (i == textIndex) { xgen.setNextIsUnwrapped(true); } xgen.setNextName(xmlNames[i]); BeanPropertyWriter prop = props[i]; if (prop != null) { // can have nulls in filtered list if ((cdata != null) && cdata.get(i)) { xgen.setNextIsCData(true); prop.serializeAsField(bean, xgen, provider); xgen.setNextIsCData(false); } else { prop.serializeAsField(bean, xgen, provider); } } // Reset to avoid next value being written as unwrapped, // for example when property is suppressed if (i == textIndex) { xgen.setNextIsUnwrapped(false); } } if (_anyGetterWriter != null) { // For [#117]: not a clean fix, but with @JsonTypeInfo, we'll end up // with accidental attributes otherwise xgen.setNextIsAttribute(false); _anyGetterWriter.getAndSerialize(bean, xgen, provider); } } catch (Exception e) { String name = (i == props.length) ? "[anySetter]" : props[i].getName(); wrapAndThrow(provider, e, bean, name); } catch (StackOverflowError e) { // Bit tricky, can't do more calls as stack is full; so: JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)"); String name = (i == props.length) ? "[anySetter]" : props[i].getName(); mapE.prependPath(new JsonMappingException.Reference(bean, name)); throw mapE; } } @Override protected void serializeFieldsFiltered(Object bean, JsonGenerator gen0, SerializerProvider provider) throws IOException { // 19-Aug-2013, tatu: During 'convertValue()', need to skip if (!(gen0 instanceof ToXmlGenerator)) { super.serializeFieldsFiltered(bean, gen0, provider); return; } final ToXmlGenerator xgen = (ToXmlGenerator) gen0; final BeanPropertyWriter[] props; if (_filteredProps != null && provider.getActiveView() != null) { props = _filteredProps; } else { props = _props; } final PropertyFilter filter = findPropertyFilter(provider, _propertyFilterId, bean); // better also allow missing filter actually.. if (filter == null) { serializeFields(bean, gen0, provider); return; } final boolean isAttribute = xgen._nextIsAttribute; final int attrCount = _attributeCount; if (attrCount > 0) { xgen.setNextIsAttribute(true); } final int textIndex = _textPropertyIndex; final QName[] xmlNames = _xmlNames; final BitSet cdata = _cdata; int i = 0; try { for (final int len = props.length; i < len; ++i) { // 28-jan-2014, pascal: we don't want to reset the attribute flag if we are an unwrapping serializer // that started with nextIsAttribute to true because all properties should be unwrapped as attributes too. if (i == attrCount && !(isAttribute && isUnwrappingSerializer())) { xgen.setNextIsAttribute(false); } // also: if this is property to write as text ("unwrap"), need to: if (i == textIndex) { xgen.setNextIsUnwrapped(true); } xgen.setNextName(xmlNames[i]); BeanPropertyWriter prop = props[i]; if (prop != null) { // can have nulls in filtered list if ((cdata != null) && cdata.get(i)) { xgen.setNextIsCData(true); filter.serializeAsField(bean, xgen, provider, prop); xgen.setNextIsCData(false); } else { filter.serializeAsField(bean, xgen, provider, prop); } } } if (_anyGetterWriter != null) { // For [#117]: not a clean fix, but with @JsonTypeInfo, we'll end up // with accidental attributes otherwise xgen.setNextIsAttribute(false); _anyGetterWriter.getAndSerialize(bean, xgen, provider); } } catch (Exception e) { String name = (i == props.length) ? "[anySetter]" : props[i].getName(); wrapAndThrow(provider, e, bean, name); } catch (StackOverflowError e) { JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e); String name = (i == props.length) ? "[anySetter]" : props[i].getName(); mapE.prependPath(new JsonMappingException.Reference(bean, name)); throw mapE; } } @Override public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException { if (_objectIdWriter != null) { _serializeWithObjectId(bean, gen, provider, typeSer); return; } /* Ok: let's serialize type id as attribute, but if (and only if!) * we are using AS_PROPERTY */ if (typeSer.getTypeInclusion() == JsonTypeInfo.As.PROPERTY) { ToXmlGenerator xgen = (ToXmlGenerator)gen; xgen.setNextIsAttribute(true); super.serializeWithType(bean, gen, provider, typeSer); if (_attributeCount == 0) { // if no attributes, need to reset xgen.setNextIsAttribute(false); } } else { super.serializeWithType(bean, gen, provider, typeSer); } } @Override protected void _serializeObjectId(Object bean, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer, WritableObjectId objectId) throws IOException { // Ok: let's serialize type id as attribute, but if (and only if!) we are using AS_PROPERTY if (typeSer.getTypeInclusion() == JsonTypeInfo.As.PROPERTY) { ToXmlGenerator xgen = (ToXmlGenerator)gen; xgen.setNextIsAttribute(true); super._serializeObjectId(bean, gen, provider, typeSer, objectId); if (_attributeCount == 0) { // if no attributes, need to reset xgen.setNextIsAttribute(false); } } else { super._serializeObjectId(bean, gen, provider, typeSer, objectId); } } /* /********************************************************** /* Helper methods /********************************************************** */ protected static boolean _isAttribute(BeanPropertyWriter bpw) { XmlInfo info = (XmlInfo) bpw.getInternalSetting(KEY_XML_INFO); return (info != null) && info.isAttribute(); } protected static boolean _isCData(BeanPropertyWriter bpw) { XmlInfo info = (XmlInfo) bpw.getInternalSetting(KEY_XML_INFO); return (info != null) && info.isCData(); } /** * Method for re-sorting lists of bean properties such that attributes are strictly * written before elements. */ protected static int _orderAttributesFirst(BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { int attrCount = 0; for (int i = 0, len = properties.length; i < len; ++i) { BeanPropertyWriter bpw = properties[i]; if (!_isAttribute(bpw)) { continue; } // Move attribute a few places down as necessary int moveBy = i - attrCount; if (moveBy > 0) { System.arraycopy(properties, attrCount, properties, attrCount + 1, moveBy); properties[attrCount] = bpw; if (filteredProperties != null) { BeanPropertyWriter fbpw = filteredProperties[i]; System.arraycopy(filteredProperties, attrCount, filteredProperties, attrCount+1, moveBy); filteredProperties[attrCount] = fbpw; } } ++attrCount; } return attrCount; } } XmlBeanSerializerModifier.java000066400000000000000000000071541251656754200426640ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.util.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.ser.*; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil; import com.fasterxml.jackson.dataformat.xml.util.TypeUtil; import com.fasterxml.jackson.dataformat.xml.util.XmlInfo; /** * We need a {@link BeanSerializerModifier} to replace default BeanSerializer * with XML-specific one; mostly to ensure that attribute properties are output * before element properties. */ public class XmlBeanSerializerModifier extends BeanSerializerModifier implements java.io.Serializable { private static final long serialVersionUID = 1L; public XmlBeanSerializerModifier() { } /* /********************************************************** /* Overridden methods /********************************************************** */ /** * First thing to do is to find annotations regarding XML serialization, * and wrap collection serializers. */ @Override public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { final AnnotationIntrospector intr = config.getAnnotationIntrospector(); for (int i = 0, len = beanProperties.size(); i < len; ++i) { BeanPropertyWriter bpw = beanProperties.get(i); final AnnotatedMember member = bpw.getMember(); String ns = AnnotationUtil.findNamespaceAnnotation(intr, member); Boolean isAttribute = AnnotationUtil.findIsAttributeAnnotation(intr, member); Boolean isText = AnnotationUtil.findIsTextAnnotation(intr, member); Boolean isCData = AnnotationUtil.findIsCDataAnnotation(intr, member); bpw.setInternalSetting(XmlBeanSerializerBase.KEY_XML_INFO, new XmlInfo(isAttribute, ns, isText, isCData)); // Actually: if we have a Collection type, easiest place to add wrapping would be here... // or: let's also allow wrapping of "untyped" (Object): assuming it is a dynamically // typed Collection... if (!TypeUtil.isIndexedType(bpw.getType())) { continue; } PropertyName wrappedName = PropertyName.construct(bpw.getName(), ns); PropertyName wrapperName = bpw.getWrapperName(); // first things first: no wrapping? if (wrapperName == null || wrapperName == PropertyName.NO_NAME) { continue; } // no local name? Just double the wrapped name for wrapper String localName = wrapperName.getSimpleName(); if (localName == null || localName.length() == 0) { wrapperName = wrappedName; } beanProperties.set(i, new XmlBeanPropertyWriter(bpw, wrapperName, wrappedName)); } return beanProperties; } @Override public JsonSerializer modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer serializer) { /* First things first: we can only handle real BeanSerializers; question * is, what to do if it's not one: throw exception or bail out? * For now let's do latter. */ if (!(serializer instanceof BeanSerializerBase)) { return serializer; } return new XmlBeanSerializer((BeanSerializerBase) serializer); } } XmlSerializerProvider.java000066400000000000000000000220331251656754200421230ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.ser.SerializerFactory; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import com.fasterxml.jackson.databind.util.TokenBuffer; import com.fasterxml.jackson.dataformat.xml.util.StaxUtil; import com.fasterxml.jackson.dataformat.xml.util.TypeUtil; import com.fasterxml.jackson.dataformat.xml.util.XmlRootNameLookup; /** * We need to override some parts of * {@link com.fasterxml.jackson.databind.SerializerProvider} * implementation to handle oddities of XML output, like "extra" root element. */ public class XmlSerializerProvider extends DefaultSerializerProvider { // As of 2.5 private static final long serialVersionUID = -4138605166320336475L; /** * If all we get to serialize is a null, there's no way to figure out * expected root name; so let's just default to something like "<null>"... */ protected final static QName ROOT_NAME_FOR_NULL = new QName("null"); protected final XmlRootNameLookup _rootNameLookup; public XmlSerializerProvider(XmlRootNameLookup rootNames) { super(); _rootNameLookup = rootNames; } public XmlSerializerProvider(XmlSerializerProvider src, SerializationConfig config, SerializerFactory f) { super(src, config, f); _rootNameLookup = src._rootNameLookup; } /* /********************************************************************** /* Overridden methods /********************************************************************** */ @Override public DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) { return new XmlSerializerProvider(this, config, jsf); } @SuppressWarnings("resource") @Override public void serializeValue(JsonGenerator jgen, Object value) throws IOException { if (value == null) { _serializeXmlNull(jgen); return; } final Class cls = value.getClass(); final boolean asArray; final ToXmlGenerator xgen = _asXmlGenerator(jgen); if (xgen == null) { // called by convertValue() asArray = false; } else { QName rootName = _rootNameFromConfig(); if (rootName == null) { rootName = _rootNameLookup.findRootName(cls, _config); } _initWithRootName(xgen, rootName); asArray = TypeUtil.isIndexedType(cls); if (asArray) { _startRootArray(xgen, rootName); } } // From super-class implementation final JsonSerializer ser = findTypedValueSerializer(cls, true, null); try { ser.serialize(value, jgen, this); } catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is throw ioe; } catch (Exception e) { // but wrap RuntimeExceptions, to get path information String msg = e.getMessage(); if (msg == null) { msg = "[no message for "+e.getClass().getName()+"]"; } throw new JsonMappingException(msg, e); } // end of super-class implementation if (asArray) { jgen.writeEndObject(); } } @SuppressWarnings("resource") @Override public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType) throws IOException { if (value == null) { _serializeXmlNull(jgen); return; } final boolean asArray; final ToXmlGenerator xgen = _asXmlGenerator(jgen); if (xgen == null) { // called by convertValue() asArray = false; } else { QName rootName = _rootNameFromConfig(); if (rootName == null) { rootName = _rootNameLookup.findRootName(rootType, _config); } _initWithRootName(xgen, rootName); asArray = TypeUtil.isIndexedType(rootType); if (asArray) { _startRootArray(xgen, rootName); } } final JsonSerializer ser = findTypedValueSerializer(rootType, true, null); // From super-class implementation try { ser.serialize(value, jgen, this); } catch (IOException ioe) { // no wrapping for IO (and derived) throw ioe; } catch (Exception e) { // but others do need to be, to get path etc String msg = e.getMessage(); if (msg == null) { msg = "[no message for "+e.getClass().getName()+"]"; } throw new JsonMappingException(msg, e); } // end of super-class implementation if (asArray) { jgen.writeEndObject(); } } // @since 2.1 @SuppressWarnings("resource") @Override public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType, JsonSerializer ser) throws IOException { if (value == null) { _serializeXmlNull(jgen); return; } final boolean asArray; final ToXmlGenerator xgen = _asXmlGenerator(jgen); if (xgen == null) { // called by convertValue() asArray = false; } else { QName rootName = _rootNameFromConfig(); if (rootName == null) { rootName = _rootNameLookup.findRootName(rootType, _config); } _initWithRootName(xgen, rootName); asArray = TypeUtil.isIndexedType(rootType); if (asArray) { _startRootArray(xgen, rootName); } } if (ser == null) { ser = findTypedValueSerializer(rootType, true, null); } // From super-class implementation try { ser.serialize(value, jgen, this); } catch (IOException ioe) { // no wrapping for IO (and derived) throw ioe; } catch (Exception e) { // but others do need to be, to get path etc String msg = e.getMessage(); if (msg == null) { msg = "[no message for "+e.getClass().getName()+"]"; } throw new JsonMappingException(msg, e); } // end of super-class implementation if (asArray) { jgen.writeEndObject(); } } protected void _serializeXmlNull(JsonGenerator jgen) throws IOException { if (jgen instanceof ToXmlGenerator) _initWithRootName((ToXmlGenerator) jgen, ROOT_NAME_FOR_NULL); super.serializeValue(jgen, null); } protected void _startRootArray(ToXmlGenerator xgen, QName rootName) throws IOException { xgen.writeStartObject(); // Could repeat root name, but what's the point? How to customize? xgen.writeFieldName("item"); } protected void _initWithRootName(ToXmlGenerator xgen, QName rootName) throws IOException { /* 28-Nov-2012, tatu: We should only initialize the root * name if no name has been set, as per [Issue#42], * to allow for custom serializers to work. */ if (!xgen.setNextNameIfMissing(rootName)) { // however, if we are root, we... insist if (xgen.getOutputContext().inRoot()) { xgen.setNextName(rootName); } } xgen.initGenerator(); String ns = rootName.getNamespaceURI(); /* [Issue#26] If we just try writing root element with namespace, * we will get an explicit prefix. But we'd rather use the default * namespace, so let's try to force that. */ if (ns != null && ns.length() > 0) { try { xgen.getStaxWriter().setDefaultNamespace(ns); } catch (XMLStreamException e) { StaxUtil.throwXmlAsIOException(e); } } } protected QName _rootNameFromConfig() { String name = _config.getRootName(); return (name == null) ? null : new QName(name); } protected ToXmlGenerator _asXmlGenerator(JsonGenerator jgen) throws JsonMappingException { // [Issue#71]: When converting, we actually get TokenBuffer, which is fine if (!(jgen instanceof ToXmlGenerator)) { // but verify if (!(jgen instanceof TokenBuffer)) { throw new JsonMappingException("XmlMapper does not with generators of type other than ToXmlGenerator; got: " +jgen.getClass().getName()); } return null; } return (ToXmlGenerator) jgen; } } 000077500000000000000000000000001251656754200351375ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilAnnotationUtil.java000066400000000000000000000056221251656754200407570ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; public class AnnotationUtil { public static String findNamespaceAnnotation(AnnotationIntrospector ai, AnnotatedMember prop) { for (AnnotationIntrospector intr : ai.allIntrospectors()) { if (intr instanceof XmlAnnotationIntrospector) { String ns = ((XmlAnnotationIntrospector) intr).findNamespace(prop); if (ns != null) { return ns; } } else if (intr instanceof JaxbAnnotationIntrospector) { String ns = ((JaxbAnnotationIntrospector) intr).findNamespace(prop); if (ns != null) { return ns; } } } return null; } public static Boolean findIsAttributeAnnotation(AnnotationIntrospector ai, AnnotatedMember prop) { for (AnnotationIntrospector intr : ai.allIntrospectors()) { if (intr instanceof XmlAnnotationIntrospector) { Boolean b = ((XmlAnnotationIntrospector) intr).isOutputAsAttribute(prop); if (b != null) { return b; } } else if (intr instanceof JaxbAnnotationIntrospector) { Boolean b = ((JaxbAnnotationIntrospector) intr).isOutputAsAttribute(prop); if (b != null) { return b; } } } return null; } public static Boolean findIsTextAnnotation(AnnotationIntrospector ai, AnnotatedMember prop) { for (AnnotationIntrospector intr : ai.allIntrospectors()) { if (intr instanceof XmlAnnotationIntrospector) { Boolean b = ((XmlAnnotationIntrospector) intr).isOutputAsText(prop); if (b != null) { return b; } } else if (intr instanceof JaxbAnnotationIntrospector) { Boolean b = ((JaxbAnnotationIntrospector) intr).isOutputAsText(prop); if (b != null) { return b; } } } return null; } public static Boolean findIsCDataAnnotation(AnnotationIntrospector ai, AnnotatedMember prop) { for (AnnotationIntrospector intr : ai.allIntrospectors()) { if (intr instanceof XmlAnnotationIntrospector) { Boolean b = ((XmlAnnotationIntrospector) intr).isOutputAsCData(prop); if (b != null) { return b; } } } return null; } } DefaultXmlPrettyPrinter.java000066400000000000000000000375431251656754200426370ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; import javax.xml.stream.XMLStreamException; import org.codehaus.stax2.XMLStreamWriter2; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.Instantiatable; import com.fasterxml.jackson.dataformat.xml.XmlPrettyPrinter; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; /** * Indentation to use with XML is different from JSON, because JSON * requires use of separator characters and XML just basic whitespace. *

* Note that only a subset of methods of {@link PrettyPrinter} actually * get called by {@link ToXmlGenerator}; because of this, implementation * is bit briefer (and uglier...). */ public class DefaultXmlPrettyPrinter implements XmlPrettyPrinter, Instantiatable, java.io.Serializable { private static final long serialVersionUID = -1811120944652457526L; /** * Interface that defines objects that can produce indentation used * to separate object entries and array values. Indentation in this * context just means insertion of white space, independent of whether * linefeeds are output. */ public interface Indenter { public void writeIndentation(JsonGenerator jg, int level) throws IOException, JsonGenerationException; public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException; /** * @return True if indenter is considered inline (does not add linefeeds), * false otherwise */ public boolean isInline(); } /* /********************************************************** /* Configuration /********************************************************** */ /** * By default, let's use only spaces to separate array values. */ protected Indenter _arrayIndenter = new FixedSpaceIndenter(); /** * By default, let's use linefeed-adding indenter for separate * object entries. We'll further configure indenter to use * system-specific linefeeds, and 2 spaces per level (as opposed to, * say, single tabs) */ protected Indenter _objectIndenter = new Lf2SpacesIndenter(); // // // Config, other white space configuration /** * By default we will add spaces around colons used to * separate object fields and values. * If disabled, will not use spaces around colon. */ protected boolean _spacesInObjectEntries = true; /* /********************************************************** /* State /********************************************************** */ /** * Number of open levels of nesting. Used to determine amount of * indentation to use. */ protected transient int _nesting = 0; /** * Marker flag set on start element, and cleared if an end element * is encountered. Used for suppressing indentation to allow empty * elements. * * @since 2.3.0 */ protected transient boolean _justHadStartElement; /* /********************************************************** /* Life-cycle (construct, configure) /********************************************************** */ public DefaultXmlPrettyPrinter() { } public void indentArraysWith(Indenter i) { _arrayIndenter = (i == null) ? new NopIndenter() : i; } public void indentObjectsWith(Indenter i) { _objectIndenter = (i == null) ? new NopIndenter() : i; } public void spacesInObjectEntries(boolean b) { _spacesInObjectEntries = b; } /* /********************************************************** /* Instantiatable impl /********************************************************** */ @Override public DefaultXmlPrettyPrinter createInstance() { return new DefaultXmlPrettyPrinter(); } /* /********************************************************** /* PrettyPrinter impl /********************************************************** */ @Override public void writeRootValueSeparator(JsonGenerator jgen) throws IOException, JsonGenerationException { // Not sure if this should ever be applicable; but if multiple roots were allowed, we'd use linefeed jgen.writeRaw('\n'); } /* /********************************************************** /* Array values /********************************************************** */ @Override public void beforeArrayValues(JsonGenerator jgen) throws IOException, JsonGenerationException { // never called for ToXmlGenerator } @Override public void writeStartArray(JsonGenerator jgen) throws IOException, JsonGenerationException { // anything to do here? } @Override public void writeArrayValueSeparator(JsonGenerator jgen) throws IOException, JsonGenerationException { // never called for ToXmlGenerator } @Override public void writeEndArray(JsonGenerator jgen, int nrOfValues) throws IOException, JsonGenerationException { // anything to do here? } /* /********************************************************** /* Object values /********************************************************** */ @Override public void beforeObjectEntries(JsonGenerator jgen) throws IOException, JsonGenerationException { // never called for ToXmlGenerator } @Override public void writeStartObject(JsonGenerator jgen) throws IOException, JsonGenerationException { if (!_objectIndenter.isInline()) { if (_nesting > 0) { _objectIndenter.writeIndentation(jgen, _nesting); } ++_nesting; } _justHadStartElement = true; ((ToXmlGenerator) jgen)._handleStartObject(); } @Override public void writeObjectEntrySeparator(JsonGenerator jgen) throws IOException, JsonGenerationException { // never called for ToXmlGenerator } @Override public void writeObjectFieldValueSeparator(JsonGenerator jgen) throws IOException, JsonGenerationException { // never called for ToXmlGenerator } @Override public void writeEndObject(JsonGenerator jgen, int nrOfEntries) throws IOException, JsonGenerationException { if (!_objectIndenter.isInline()) { --_nesting; } // for empty elements, no need for linefeeds etc: if (_justHadStartElement) { _justHadStartElement = false; } else { _objectIndenter.writeIndentation(jgen, _nesting); } ((ToXmlGenerator) jgen)._handleEndObject(); } /* /********************************************************** /* XML-specific additions /********************************************************** */ @Override public void writeStartElement(XMLStreamWriter2 sw, String nsURI, String localName) throws XMLStreamException { if (!_objectIndenter.isInline()) { if (_justHadStartElement) { _justHadStartElement = false; } else { _objectIndenter.writeIndentation(sw, _nesting); } ++_nesting; } sw.writeStartElement(nsURI, localName); _justHadStartElement = true; } @Override public void writeEndElement(XMLStreamWriter2 sw, int nrOfEntries) throws XMLStreamException { if (!_objectIndenter.isInline()) { --_nesting; } // for empty elements, no need for linefeeds etc: if (_justHadStartElement) { _justHadStartElement = false; } else { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeEndElement(); } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, String text, boolean isCData) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); if(isCData) { sw.writeCData(text); } else { sw.writeCharacters(text); } sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, char[] buffer, int offset, int len, boolean isCData) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); if(isCData) { sw.writeCData(buffer, offset, len); } else { sw.writeCharacters(buffer, offset, len); } sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, boolean value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeBoolean(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, int value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeInt(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, long value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeLong(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, double value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeDouble(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, float value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeFloat(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, BigInteger value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeInteger(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, BigDecimal value) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeDecimal(value); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafElement(XMLStreamWriter2 sw, String nsURI, String localName, byte[] data, int offset, int len) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeStartElement(nsURI, localName); sw.writeBinary(data, offset, len); sw.writeEndElement(); _justHadStartElement = false; } @Override public void writeLeafNullElement(XMLStreamWriter2 sw, String nsURI, String localName) throws XMLStreamException { if (!_objectIndenter.isInline()) { _objectIndenter.writeIndentation(sw, _nesting); } sw.writeEmptyElement(nsURI, localName); _justHadStartElement = false; } /* /********************************************************** /* Helper classes /* (note: copied from jackson-core to avoid dependency; /* allow local changes) /********************************************************** */ /** * Dummy implementation that adds no indentation whatsoever */ protected static class NopIndenter implements Indenter { public NopIndenter() { } @Override public void writeIndentation(JsonGenerator jg, int level) { } @Override public boolean isInline() { return true; } @Override public void writeIndentation(XMLStreamWriter2 sw, int level) { } } /** * This is a very simple indenter that only every adds a * single space for indentation. It is used as the default * indenter for array values. */ protected static class FixedSpaceIndenter implements Indenter { public FixedSpaceIndenter() { } @Override public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException { sw.writeRaw(" "); } @Override public void writeIndentation(JsonGenerator jg, int level) throws IOException, JsonGenerationException { jg.writeRaw(' '); } @Override public boolean isInline() { return true; } } /** * Default linefeed-based indenter uses system-specific linefeeds and * 2 spaces for indentation per level. */ protected static class Lf2SpacesIndenter implements Indenter { final static String SYSTEM_LINE_SEPARATOR; static { String lf = null; try { lf = System.getProperty("line.separator"); } catch (Throwable t) { } // access exception? SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf; } final static int SPACE_COUNT = 64; final static char[] SPACES = new char[SPACE_COUNT]; static { Arrays.fill(SPACES, ' '); } public Lf2SpacesIndenter() { } @Override public boolean isInline() { return false; } @Override public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException { sw.writeRaw(SYSTEM_LINE_SEPARATOR); level += level; // 2 spaces per level while (level > SPACE_COUNT) { // should never happen but... sw.writeRaw(SPACES, 0, SPACE_COUNT); level -= SPACES.length; } sw.writeRaw(SPACES, 0, level); } @Override public void writeIndentation(JsonGenerator jg, int level) throws IOException, JsonGenerationException { jg.writeRaw(SYSTEM_LINE_SEPARATOR); level += level; // 2 spaces per level while (level > SPACE_COUNT) { // should never happen but... jg.writeRaw(SPACES, 0, SPACE_COUNT); level -= SPACES.length; } jg.writeRaw(SPACES, 0, level); } } } StaxUtil.java000066400000000000000000000044121251656754200375600ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; import java.io.IOException; import javax.xml.stream.*; public class StaxUtil { /** * Adapter method used when only IOExceptions are declared to be thrown, but * a {@link XMLStreamException} was caught. *

* Note: dummy type variable is used for convenience, to allow caller to claim * that this method returns result of any necessary type. */ public static T throwXmlAsIOException(XMLStreamException e) throws IOException { Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } if (t instanceof Error) throw (Error) t; if (t instanceof RuntimeException) throw (RuntimeException) t; throw new IOException(t); } /** * Since XML names can not contain all characters JSON names can, we may * need to replace characters. Let's start with trivial replacement of * ASCII characters that can not be included. */ public static String sanitizeXmlTypeName(String name) { StringBuilder sb; int changes = 0; // First things first: remove array types' trailing[]... if (name.endsWith("[]")) { do { name = name.substring(0, name.length() - 2); ++changes; } while (name.endsWith("[]")); sb = new StringBuilder(name); // do trivial pluralization attempt if (name.endsWith("s")) { sb.append("es"); } else { sb.append('s'); } } else { sb = new StringBuilder(name); } for (int i = 0, len = name.length(); i < len; ++i) { char c = name.charAt(i); if (c > 127) continue; if (c >= 'a' && c <= 'z') continue; if (c >= 'A' && c <= 'Z') continue; if (c >= '0' && c <= '9') continue; if (c == '_' || c == '.' || c == '-') continue; // Ok, need to replace ++changes; if (c == '$') { sb.setCharAt(i, '.'); } else { sb.setCharAt(i, '_'); } } if (changes == 0) { return name; } return sb.toString(); } } TypeUtil.java000066400000000000000000000022621251656754200375630ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; import java.util.Collection; import java.util.Map; import com.fasterxml.jackson.databind.JavaType; public class TypeUtil { /** * Helper method used for figuring out if given raw type is a collection ("indexed") type; * in which case a wrapper element is typically added. */ public static boolean isIndexedType(JavaType type) { if (type.isContainerType()) { Class cls = type.getRawClass(); // One special case; byte[] will be serialized as base64-encoded String, not real array, so: // (actually, ditto for char[]; thought to be a String) if (cls == byte[].class || cls == char[].class) { return false; } // issue#5: also, should not add wrapping for Maps if (Map.class.isAssignableFrom(cls)) { return false; } return true; } return false; } public static boolean isIndexedType(Class cls) { return (cls.isArray() && cls != byte[].class && cls != char[].class) || Collection.class.isAssignableFrom(cls); } } XmlInfo.java000066400000000000000000000016621251656754200373630ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; /** * Helper container class used to contain XML specific information * we need to retain to construct proper bean serializer */ public class XmlInfo { protected final String _namespace; protected final boolean _isAttribute; protected final boolean _isText; protected final boolean _isCData; public XmlInfo(Boolean isAttribute, String ns, Boolean isText, Boolean isCData) { _isAttribute = (isAttribute == null) ? false : isAttribute.booleanValue(); _namespace = (ns == null) ? "" : ns; _isText = (isText == null) ? false : isText.booleanValue(); _isCData = (isCData == null) ? false : isCData.booleanValue(); } public String getNamespace() { return _namespace; } public boolean isAttribute() { return _isAttribute; } public boolean isText() { return _isText; } public boolean isCData() { return _isCData; } } XmlRootNameLookup.java000066400000000000000000000066211251656754200414060ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/java/com/fasterxml/jackson/dataformat/xml/utilpackage com.fasterxml.jackson.dataformat.xml.util; import javax.xml.namespace.QName; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.type.ClassKey; import com.fasterxml.jackson.databind.util.LRUMap; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; /** * Helper class used for efficiently finding root element name used with * XML serializations. */ public class XmlRootNameLookup implements java.io.Serializable { private static final long serialVersionUID = 1L; /** * For efficient operation, let's try to minimize number of times we * need to introspect root element name to use. *

* Note: changed to transient for 2.3; no point in serializing such * state */ protected final transient LRUMap _rootNames = new LRUMap(40, 200); public XmlRootNameLookup() { } protected Object readResolve() { // just need to make 100% sure it gets set to non-null, that's all if (_rootNames == null) { return new XmlRootNameLookup(); } return this; } public QName findRootName(JavaType rootType, MapperConfig config) { return findRootName(rootType.getRawClass(), config); } public QName findRootName(Class rootType, MapperConfig config) { ClassKey key = new ClassKey(rootType); QName name; synchronized (_rootNames) { name = _rootNames.get(key); } if (name != null) { return name; } BeanDescription beanDesc = config.introspectClassAnnotations(rootType); AnnotationIntrospector intr = config.getAnnotationIntrospector(); AnnotatedClass ac = beanDesc.getClassInfo(); String localName = null; String ns = null; PropertyName root = intr.findRootName(ac); if (root != null) { localName = root.getSimpleName(); ns = root.getNamespace(); } // No answer so far? Let's just default to using simple class name if (localName == null || localName.length() == 0) { // Should we strip out enclosing class tho? For now, nope: // one caveat: array simple names end with "[]"; also, "$" needs replacing localName = StaxUtil.sanitizeXmlTypeName(rootType.getSimpleName()); name = new QName("", localName); } else { // Otherwise let's see if there's namespace, too (if we are missing it) if (ns == null || ns.length() == 0) { ns = findNamespace(intr, ac); } } if (ns == null) { // some QName impls barf on nulls... ns = ""; } name = new QName(ns, localName); synchronized (_rootNames) { _rootNames.put(key, name); } return name; } private String findNamespace(AnnotationIntrospector ai, AnnotatedClass ann) { for (AnnotationIntrospector intr : ai.allIntrospectors()) { if (intr instanceof XmlAnnotationIntrospector) { String ns = ((XmlAnnotationIntrospector) intr).findNamespace(ann); if (ns != null) { return ns; } } } return null; } } jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/000077500000000000000000000000001251656754200261755ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/000077500000000000000000000000001251656754200273355ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/LICENSE000066400000000000000000000005011251656754200303360ustar00rootroot00000000000000This copy of Jackson JSON processor databind module is licensed under the Apache (Software) License, version 2.0 ("the License"). See the License for details about distribution rights, and the specific rights regarding derivate works. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/NOTICE000066400000000000000000000014711251656754200302440ustar00rootroot00000000000000# Jackson JSON processor Jackson is a high-performance, Free/Open Source JSON processing library. It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has been in development since 2007. It is currently developed by a community of developers, as well as supported commercially by FasterXML.com. ## Licensing Jackson core and extension components may be licensed under different licenses. To find the details that apply to this artifact see the accompanying LICENSE file. For more information, including possible other licensing options, contact FasterXML.com (http://fasterxml.com). ## Credits A list of contributors may be found from CREDITS file, which is included in some artifacts (usually source distributions); but is always available from the source code management (SCM) system project uses. jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/services/000077500000000000000000000000001251656754200311605ustar00rootroot00000000000000com.fasterxml.jackson.core.JsonFactory000066400000000000000000000000601251656754200404200ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/servicescom.fasterxml.jackson.dataformat.xml.XmlFactory com.fasterxml.jackson.core.ObjectCodec000066400000000000000000000000571251656754200403310ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/main/resources/META-INF/servicescom.fasterxml.jackson.dataformat.xml.XmlMapper jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/000077500000000000000000000000001251656754200242165ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/000077500000000000000000000000001251656754200251375ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/000077500000000000000000000000001251656754200257155ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/000077500000000000000000000000001251656754200277225ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/000077500000000000000000000000001251656754200313525ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/000077500000000000000000000000001251656754200334745ustar00rootroot00000000000000000077500000000000000000000000001251656754200342155ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xmlMediaItem.java000066400000000000000000000075411251656754200367250ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({"content", "images"}) class MediaItem { public enum Player { JAVA, FLASH; } public enum Size { SMALL, LARGE; } private List _photos; private Content _content; public MediaItem() { } public MediaItem(Content c) { _content = c; } public void addPhoto(Photo p) { if (_photos == null) { _photos = new ArrayList(); } _photos.add(p); } public List getImages() { return _photos; } public void setImages(List p) { _photos = p; } public Content getContent() { return _content; } public void setContent(Content c) { _content = c; } /* /********************************************************** /* Helper types /********************************************************** */ @JsonPropertyOrder({"uri","title","width","height","size"}) public static class Photo { private String _uri; private String _title; private int _width; private int _height; private Size _size; public Photo() {} public Photo(String uri, String title, int w, int h, Size s) { _uri = uri; _title = title; _width = w; _height = h; _size = s; } public String getUri() { return _uri; } public String getTitle() { return _title; } public int getWidth() { return _width; } public int getHeight() { return _height; } public Size getSize() { return _size; } public void setUri(String u) { _uri = u; } public void setTitle(String t) { _title = t; } public void setWidth(int w) { _width = w; } public void setHeight(int h) { _height = h; } public void setSize(Size s) { _size = s; } } @JsonPropertyOrder({"uri","title","width","height","format","duration","size","bitrate","persons","player","copyright"}) public static class Content { private Player _player; private String _uri; private String _title; private int _width; private int _height; private String _format; private long _duration; private long _size; private int _bitrate; private List _persons; private String _copyright; public Content() { } public void addPerson(String p) { if (_persons == null) { _persons = new ArrayList(); } _persons.add(p); } public Player getPlayer() { return _player; } public String getUri() { return _uri; } public String getTitle() { return _title; } public int getWidth() { return _width; } public int getHeight() { return _height; } public String getFormat() { return _format; } public long getDuration() { return _duration; } public long getSize() { return _size; } public int getBitrate() { return _bitrate; } public List getPersons() { return _persons; } public String getCopyright() { return _copyright; } public void setPlayer(Player p) { _player = p; } public void setUri(String u) { _uri = u; } public void setTitle(String t) { _title = t; } public void setWidth(int w) { _width = w; } public void setHeight(int h) { _height = h; } public void setFormat(String f) { _format = f; } public void setDuration(long d) { _duration = d; } public void setSize(long s) { _size = s; } public void setBitrate(int b) { _bitrate = b; } public void setPersons(List p) { _persons = p; } public void setCopyright(String c) { _copyright = c; } } } RoundtripContentTest.java000066400000000000000000000024551251656754200412470ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectWriter; public class RoundtripContentTest extends XmlTestBase { public void testRoundtrip() throws Exception { final XmlMapper MAPPER = new XmlMapper(); MediaItem.Content content = new MediaItem.Content(); content.setTitle("content"); content.addPerson("William"); content.addPerson("Robert"); MediaItem input = new MediaItem(content); input.addPhoto(new MediaItem.Photo("http://a", "title1", 200, 100, MediaItem.Size.LARGE)); input.addPhoto(new MediaItem.Photo("http://b", "title2", 640, 480, MediaItem.Size.SMALL)); ObjectWriter w = MAPPER.writerFor(MediaItem.class); /* StringWriter sw = new StringWriter(); try { w.writeValue(sw, input); } finally { System.err.println("So far -> ["+sw+"]"); } */ String xml = w.writeValueAsString(input); //System.err.println("DEBUG: Xml == "+xml); ObjectReader r = MAPPER.reader(MediaItem.class); MediaItem result = r.readValue(xml); assertNotNull(result); assertEquals(content.getTitle(), result.getContent().getTitle()); } } VersionInfoTest.java000066400000000000000000000051511251656754200401630ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.io.*; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.dataformat.xml.PackageVersion; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; public class VersionInfoTest extends XmlTestBase { public void testMapperVersions() { assertVersion(new XmlMapper()); assertVersion(new XmlFactory()); } // @since 2.1 // [Issue#48]: ObjectMapper.copy() public void testMapperCopy() { XmlMapper mapper1 = new XmlMapper(); mapper1.setXMLTextElementName("foo"); mapper1.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); XmlMapper mapper2 = mapper1.copy(); assertNotSame(mapper1, mapper2); XmlFactory xf1 = mapper1.getFactory(); XmlFactory xf2 = mapper2.getFactory(); assertNotSame(xf1, xf2); assertEquals(XmlFactory.class, xf2.getClass()); // and [Issue#48] as well, incomplete copy... assertEquals(xf1.getXMLTextElementName(), xf2.getXMLTextElementName()); assertEquals(xf1._xmlGeneratorFeatures, xf2._xmlGeneratorFeatures); assertEquals(xf1._xmlParserFeatures, xf2._xmlParserFeatures); } // Another test for [Issue#48] public void testMapperSerialization() throws Exception { XmlMapper mapper1 = new XmlMapper(); mapper1.setXMLTextElementName("foo"); assertEquals("foo", mapper1.getFactory().getXMLTextElementName()); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ObjectOutputStream objectStream = new ObjectOutputStream(bytes); objectStream.writeObject(mapper1); objectStream.close(); ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray())); XmlMapper mapper2 = (XmlMapper) input.readObject(); input.close(); assertEquals("foo", mapper2.getFactory().getXMLTextElementName()); } /* /********************************************************** /* Helper methods /********************************************************** */ private void assertVersion(Versioned vers) { final Version v = vers.version(); assertFalse("Should find version information (got "+v+")", v.isUknownVersion()); Version exp = PackageVersion.VERSION; assertEquals(exp.toFullString(), v.toFullString()); assertEquals(exp, v); } } XmlTestBase.java000066400000000000000000000232101251656754200372510ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xmlpackage com.fasterxml.jackson.dataformat.xml; import java.io.*; import java.util.Arrays; import junit.framework.TestCase; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public abstract class XmlTestBase extends TestCase { @JsonPropertyOrder({ "first", "last", "id" }) protected static class NameBean { @JacksonXmlProperty(isAttribute=true) public int age; public String last, first; public NameBean() { } public NameBean(int age, String f, String l) { this.age = age; first = f; last = l; } } /** * Sample class from Jackson tutorial ("JacksonInFiveMinutes") */ public static class FiveMinuteUser { public enum Gender { MALE, FEMALE }; public static class Name { private String _first, _last; public Name() { } public Name(String f, String l) { _first = f; _last = l; } public String getFirst() { return _first; } public String getLast() { return _last; } public void setFirst(String s) { _first = s; } public void setLast(String s) { _last = s; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; Name other = (Name) o; return _first.equals(other._first) && _last.equals(other._last); } } private Gender _gender; private Name _name; private boolean _isVerified; private byte[] _userImage; public FiveMinuteUser() { } public FiveMinuteUser(String first, String last, boolean verified, Gender g, byte[] data) { _name = new Name(first, last); _isVerified = verified; _gender = g; _userImage = data; } public Name getName() { return _name; } public boolean isVerified() { return _isVerified; } public Gender getGender() { return _gender; } public byte[] getUserImage() { return _userImage; } public void setName(Name n) { _name = n; } public void setVerified(boolean b) { _isVerified = b; } public void setGender(Gender g) { _gender = g; } public void setUserImage(byte[] b) { _userImage = b; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; FiveMinuteUser other = (FiveMinuteUser) o; if (_isVerified != other._isVerified) return false; if (_gender != other._gender) return false; if (!_name.equals(other._name)) return false; byte[] otherImage = other._userImage; if (otherImage.length != _userImage.length) return false; for (int i = 0, len = _userImage.length; i < len; ++i) { if (_userImage[i] != otherImage[i]) { return false; } } return true; } } protected static class StringBean { public String text; public StringBean() { this("foobar"); } public StringBean(String s) { text = s; } @Override public String toString() { if (text == null) return "NULL"; return "\""+text+"\""; } } /** * Simple wrapper around String type, usually to test value * conversions or wrapping */ protected static class StringWrapper { public String str; public StringWrapper() { } public StringWrapper(String value) { str = value; } } protected static class IntWrapper { public int i; public IntWrapper() { } public IntWrapper(int value) { i = value; } } /* /********************************************************** /* Some sample documents: /********************************************************** */ protected final static int SAMPLE_SPEC_VALUE_WIDTH = 800; protected final static int SAMPLE_SPEC_VALUE_HEIGHT = 600; protected final static String SAMPLE_SPEC_VALUE_TITLE = "View from 15th Floor"; protected final static String SAMPLE_SPEC_VALUE_TN_URL = "http://www.example.com/image/481989943"; protected final static int SAMPLE_SPEC_VALUE_TN_HEIGHT = 125; protected final static String SAMPLE_SPEC_VALUE_TN_WIDTH = "100"; protected final static int SAMPLE_SPEC_VALUE_TN_ID1 = 116; protected final static int SAMPLE_SPEC_VALUE_TN_ID2 = 943; protected final static int SAMPLE_SPEC_VALUE_TN_ID3 = 234; protected final static int SAMPLE_SPEC_VALUE_TN_ID4 = 38793; protected final static String SAMPLE_DOC_JSON_SPEC = "{\n" +" \"Image\" : {\n" +" \"Width\" : "+SAMPLE_SPEC_VALUE_WIDTH+",\n" +" \"Height\" : "+SAMPLE_SPEC_VALUE_HEIGHT+"," +"\"Title\" : \""+SAMPLE_SPEC_VALUE_TITLE+"\",\n" +" \"Thumbnail\" : {\n" +" \"Url\" : \""+SAMPLE_SPEC_VALUE_TN_URL+"\",\n" +"\"Height\" : "+SAMPLE_SPEC_VALUE_TN_HEIGHT+",\n" +" \"Width\" : \""+SAMPLE_SPEC_VALUE_TN_WIDTH+"\"\n" +" },\n" +" \"IDs\" : ["+SAMPLE_SPEC_VALUE_TN_ID1+","+SAMPLE_SPEC_VALUE_TN_ID2+","+SAMPLE_SPEC_VALUE_TN_ID3+","+SAMPLE_SPEC_VALUE_TN_ID4+"]\n" +" }" +"}" ; /* /********************************************************** /* Construction, factory methods /********************************************************** */ protected XmlTestBase() { super(); } protected XmlMapper xmlMapper(boolean useListWrapping) { JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(useListWrapping); return new XmlMapper(module); } /* /********************************************************** /* Additional assertion methods /********************************************************** */ protected void assertToken(JsonToken expToken, JsonToken actToken) { if (actToken != expToken) { fail("Expected token "+expToken+", current token "+actToken); } } protected void assertToken(JsonToken expToken, JsonParser jp) { assertToken(expToken, jp.getCurrentToken()); } /** * Method that gets textual contents of the current token using * available methods, and ensures results are consistent, before * returning them */ protected String getAndVerifyText(JsonParser jp) throws IOException, JsonParseException { // Ok, let's verify other accessors int actLen = jp.getTextLength(); char[] ch = jp.getTextCharacters(); String str2 = new String(ch, jp.getTextOffset(), actLen); String str = jp.getText(); if (str.length() != actLen) { fail("Internal problem (jp.token == "+jp.getCurrentToken()+"): jp.getText().length() ['"+str+"'] == "+str.length()+"; jp.getTextLength() == "+actLen); } assertEquals("String access via getText(), getTextXxx() must be the same", str, str2); return str; } protected void verifyFieldName(JsonParser jp, String expName) throws IOException { assertEquals(expName, jp.getText()); assertEquals(expName, jp.getCurrentName()); } protected void verifyException(Throwable e, String... matches) { String msg = e.getMessage(); String lmsg = (msg == null) ? "" : msg.toLowerCase(); for (String match : matches) { String lmatch = match.toLowerCase(); if (lmsg.indexOf(lmatch) >= 0) { return; } } fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\""); } /* /********************************************************** /* Helper methods, other /********************************************************** */ protected byte[] utf8Bytes(String str) { try { return str.getBytes("UTF-8"); } catch (IOException e) { throw new IllegalArgumentException(e); } } /** * Helper method that tries to remove unnecessary namespace * declaration that default JDK XML parser (SJSXP) sees fit * to add. */ protected static String removeSjsxpNamespace(String xml) { final String match = " xmlns=\"\""; int ix = xml.indexOf(match); if (ix > 0) { xml = xml.substring(0, ix) + xml.substring(ix+match.length()); } return xml; } protected String readAll(File f) throws IOException { StringBuilder sb = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8")); String line; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } br.close(); return sb.toString(); } public String jaxbSerialized(Object ob, Class... classes) throws Exception { StringWriter sw = new StringWriter(); if (classes.length == 0) { javax.xml.bind.JAXB.marshal(ob, sw); } else { javax.xml.bind.JAXBContext.newInstance(classes).createMarshaller().marshal(ob, sw); } sw.close(); return sw.toString(); } } 000077500000000000000000000000001251656754200360205ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/adaptersTestIssue47Attribute.java000066400000000000000000000017661251656754200426640ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/adapterspackage com.fasterxml.jackson.dataformat.xml.adapters; import java.util.List; import com.fasterxml.jackson.dataformat.xml.*; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class TestIssue47Attribute extends XmlTestBase { public static class Response { @JacksonXmlProperty(localName = "wrapper") public List items; } public static class Item { public String id; public String a; public String b; } public void testEmptyStringFromElemAndAttr() throws Exception { final XmlMapper MAPPER = new XmlMapper(); String xml = "xyyx"; Response res = MAPPER.readValue(xml, Response.class); //System.out.println(MAPPER.writeValueAsString(res)); assertNotNull(res.items); assertNotNull(res.items.get(0)); assertNotNull(res.items.get(0).id); } } 000077500000000000000000000000001251656754200353175ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserTestBinaryData.java000066400000000000000000000030751251656754200410450ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class TestBinaryData extends XmlTestBase { public static class Data { public byte[] bytes; } public static class TwoData { public Data data1; public Data data2; } /* /********************************************************** /* Unit tests /********************************************************** */ // private final XmlMapper MAPPER = new XmlMapper(); // for [https://github.com/FasterXML/jackson-dataformat-xml/issues/29] public void testTwoBinaryProps() throws Exception { /* Hmmh. Looks like XmlMapper has some issues with convertValue: * should investigate at some point. But not now... */ final ObjectMapper jsonMapper = new ObjectMapper(); String BIN1 = jsonMapper.convertValue("Hello".getBytes("UTF-8"), String.class); String BIN2 = jsonMapper.convertValue("world!!".getBytes("UTF-8"), String.class); String xml = "" + "" + BIN1 + "" + "" + BIN2 + "" + ""; TwoData two = new XmlMapper().readValue(xml, TwoData.class); assertEquals("Hello", new String(two.data1.bytes, "UTF-8")); assertEquals("world!!", new String(two.data2.bytes, "UTF-8")); } } TestDeserialization.java000066400000000000000000000054251251656754200421560ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.util.*; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; public class TestDeserialization extends XmlTestBase { static class AttributeBean { @JacksonXmlProperty(isAttribute=true, localName="attr") public String text = "?"; } static class Optional { @JacksonXmlText public String number = "NOT SET"; public String type = "NOT SET"; } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); /** * Unit test to ensure that we can successfully also round trip * example Bean used in Jackson tutorial */ public void testRoundTripWithJacksonExample() throws Exception { FiveMinuteUser user = new FiveMinuteUser("Joe", "Sixpack", true, FiveMinuteUser.Gender.MALE, new byte[] { 1, 2, 3 , 4, 5 }); String xml = MAPPER.writeValueAsString(user); FiveMinuteUser result = MAPPER.readValue(xml, FiveMinuteUser.class); assertEquals(user, result); } public void testFromAttribute() throws Exception { AttributeBean bean = MAPPER.readValue("", AttributeBean.class); assertNotNull(bean); assertEquals("abc", bean.text); } // [Issue#14] public void testMapWithAttr() throws Exception { final String xml = "John Smith"; Map map = MAPPER.readValue(xml, Map.class); // Will result in equivalent of: // { "person" : { // "lang" : "en", // "" : "John Smith" // } // } // // which may or may not be what we want. Without attribute // we would just have '{ "person" : "John Smith" }' assertNotNull(map); } // // Tests for [Issue#64] public void testOptionalAttr() throws Exception { Optional ob = MAPPER.readValue("123-456-7890", Optional.class); assertNotNull(ob); assertEquals("123-456-7890", ob.number); assertEquals("work", ob.type); } public void testMissingOptionalAttr() throws Exception { Optional ob = MAPPER.readValue("123-456-7890", Optional.class); assertNotNull(ob); assertEquals("123-456-7890", ob.number); assertEquals("NOT SET", ob.type); } } TestEnums.java000066400000000000000000000015021251656754200401070ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import com.fasterxml.jackson.dataformat.xml.*; public class TestEnums extends XmlTestBase { static enum TestEnum { A, B, C; } static class EnumBean { public TestEnum value; public EnumBean() { } public EnumBean(TestEnum v) { value = v; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testEnum() throws Exception { String xml = MAPPER.writeValueAsString(new EnumBean(TestEnum.B)); EnumBean result = MAPPER.readValue(xml, EnumBean.class); assertNotNull(result); assertEquals(TestEnum.B, result.value); } } TestStringValues.java000066400000000000000000000061111251656754200414470ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class TestStringValues extends XmlTestBase { protected static class Bean2 { public String a, b; @Override public String toString() { return "[a="+a+",b="+b+"]"; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testSimpleStringElement() throws Exception { // first, simple one to verify baseline StringBean bean = MAPPER.readValue("text!", StringBean.class); assertNotNull(bean); assertEquals("text!", bean.text); } public void testEmptyStringElement() throws Exception { // then with empty element StringBean bean = MAPPER.readValue("", StringBean.class); assertNotNull(bean); // empty String or null? // 22-Sep-2012, tatu: Seems to be 'null', but should probably be fixed to "" // assertEquals("", bean.text); assertNull(bean.text); } public void testMissingString() throws Exception { StringBean baseline = new StringBean(); // then missing StringBean bean = MAPPER.readValue("", StringBean.class); assertNotNull(bean); assertEquals(baseline.text, bean.text); } public void testStringWithAttribute() throws Exception { // and then the money shot: with 'standard' attribute... StringBean bean = MAPPER.readValue("Pulla", StringBean.class); assertNotNull(bean); assertEquals("Pulla", bean.text); } public void testStringsWithAttribute() throws Exception { Bean2 bean = MAPPER.readValue( "\n" +"abc" +"def" // +"abcdef" +"\n", Bean2.class); assertNotNull(bean); assertEquals("abc", bean.a); assertEquals("def", bean.b); } public void testStringArrayWithAttribute() throws Exception { // should even work for arrays of those StringBean[] beans = MAPPER.readValue( "\n" +"Pulla" +"Bulla" +"Good stuff" +"", StringBean[].class); assertNotNull(beans); assertEquals(3, beans.length); assertEquals("Pulla", beans[0].text); assertEquals("Bulla", beans[1].text); assertEquals("Good stuff", beans[2].text); } } TestViews.java000066400000000000000000000073711251656754200401270ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/deserpackage com.fasterxml.jackson.dataformat.xml.deser; import java.io.IOException; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; /* * Tests for ('JSON') Views, other filtering. */ public class TestViews extends XmlTestBase { static class RestrictedView { }; static class Foo { @JsonView(RestrictedView.class) @JsonProperty public String restrictedFooProperty; @JsonView(RestrictedView.class) @JsonProperty public Bar[] bars; } static class Bar { @JsonView(RestrictedView.class) @JsonProperty public int restrictedBarProperty; } @JsonInclude(JsonInclude.Include.NON_NULL) static class NonNullBean { public String nullName = null; public String name = "Bob"; } @JsonFilter("filter44") public class Issue44Bean { @JacksonXmlProperty(isAttribute=true) protected String first = "abc"; public int second = 13; } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ public void testIssue7() throws Exception { Foo foo = new Foo(); foo.restrictedFooProperty = "test"; Bar bar1 = new Bar(); bar1.restrictedBarProperty = 10; Bar bar2 = new Bar(); bar2.restrictedBarProperty = 11; foo.bars = new Bar[] { bar1, bar2 }; ObjectMapper xmlMapper = new XmlMapper(); xmlMapper.configure(MapperFeature.AUTO_DETECT_FIELDS, false ); xmlMapper.configure(MapperFeature.AUTO_DETECT_GETTERS, false ); xmlMapper.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false ); xmlMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false ); String xml = xmlMapper.writerWithView(RestrictedView.class).writeValueAsString(foo); // views not used for deserialization Foo result = xmlMapper.readValue(xml, Foo.class); assertEquals("test", result.restrictedFooProperty); assertNotNull(result.bars); assertEquals(2, result.bars.length); assertEquals(10, result.bars[0].restrictedBarProperty); assertEquals(11, result.bars[1].restrictedBarProperty); } public void testNullSuppression() throws Exception { String xml = _xmlMapper.writeValueAsString(new NonNullBean()); assertEquals("Bob", xml); } public void testIssue44() throws IOException { String exp = "13"; Issue44Bean bean = new Issue44Bean(); FilterProvider prov = new SimpleFilterProvider().addFilter("filter44", SimpleBeanPropertyFilter.serializeAllExcept("filterMe")); ObjectWriter writer = _xmlMapper.writer(prov); // as well as with proper filter assertEquals(exp, writer.writeValueAsString(bean)); } } 000077500000000000000000000000001251656754200356265ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingIssue37AdapterTest.java000066400000000000000000000140441251656754200420770ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import java.io.UnsupportedEncodingException; import java.net.*; import java.util.*; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.*; import com.fasterxml.jackson.dataformat.xml.jaxb.XmlJaxbAnnotationIntrospector; public class Issue37AdapterTest extends XmlTestBase { @XmlJavaTypeAdapter(URLEncoderMapDataAdapter.class) public static class MapData { public String key; public String value; public MapData() { } public MapData(String key, String value) { super(); this.key = key; this.value = value; } } public static class URLEncoderMapDataAdapter extends XmlAdapter> { public URLEncoderMapDataAdapter() { } @Override public MapData[] marshal(Map arg0) throws Exception { MapData[] mapElements = new MapData[arg0.size()]; int i = 0; for (Map.Entry entry : arg0.entrySet()) { mapElements[i++] = new MapData(encodeKey(entry.getKey()), entry.getValue()); } return mapElements; } @Override public Map unmarshal(MapData[] arg0) throws Exception { Map r = new HashMap(); for (MapData mapelement : arg0) { r.put(decodeKey(mapelement.key), mapelement.value); } return r; } private final static String ENCODING = "UTF-8"; private String encodeKey(String key) throws UnsupportedEncodingException { return URLEncoder.encode(key, ENCODING); } private String decodeKey(String key) throws UnsupportedEncodingException { return URLDecoder.decode(key, ENCODING); } } @XmlRootElement(name = "DocWithMapData") public static class DocWithMapData { @XmlJavaTypeAdapter(value = URLEncoderMapDataAdapter.class) // type = MapData[].class) public Map mapDatas; } @XmlRootElement(name = "DocWithMapDataSimpleAnnotation") public static class DocWithMapDataSimpleAnnotation { @XmlJavaTypeAdapter(URLEncoderMapDataAdapter.class) public Map mapDatas; } private Map simpleMapData = singletonMap("key", "value"); private Map needEncodingMapData = singletonMap("my/key", "my/value"); private Map singletonMap(String a, String b) { Map map = new HashMap(); map.put(a,b); return map; } /* /********************************************************************** /* Set up /*********************************************************************** */ protected XmlMapper _jaxbMapper; protected XmlMapper _nonJaxbMapper; @Override public void setUp() throws Exception { super.setUp(); _jaxbMapper = new XmlMapper(); _nonJaxbMapper = new XmlMapper(); // Use JAXB-then-Jackson annotation introspector AnnotationIntrospector intr = XmlAnnotationIntrospector.Pair.instance(new XmlJaxbAnnotationIntrospector(TypeFactory.defaultInstance()), new JacksonAnnotationIntrospector()); _jaxbMapper.setAnnotationIntrospector(intr); } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testSimpleKeyMap() throws Exception { DocWithMapData bean = new DocWithMapData(); bean.mapDatas = simpleMapData; assertEquals("value", _jaxbMapper.writeValueAsString(bean)); } public void testNeedEncodingKeyMap() throws Exception { DocWithMapData bean = new DocWithMapData(); bean.mapDatas = needEncodingMapData; String xml = _jaxbMapper.writeValueAsString(bean); assertEquals("my/value", xml); } public void testSimpleKeyMapSimpleAnnotation() throws Exception { DocWithMapDataSimpleAnnotation bean = new DocWithMapDataSimpleAnnotation(); bean.mapDatas = simpleMapData; assertEquals( "value", _jaxbMapper.writeValueAsString(bean)); } public void testNeedEncodingKeyMapSimpleAnnotation() throws Exception { DocWithMapDataSimpleAnnotation bean = new DocWithMapDataSimpleAnnotation(); bean.mapDatas = needEncodingMapData; assertEquals( "my/value", _jaxbMapper.writeValueAsString(bean)); } public void testNeedEncodingKeyMap_nonJaxb() throws Exception { DocWithMapData bean = new DocWithMapData(); bean.mapDatas = needEncodingMapData; assertEquals( "my/value", _nonJaxbMapper.writeValueAsString(bean)); } public void testNeedEncodingKeyMapSimpleAnnotation_nonJaxb() throws Exception { DocWithMapDataSimpleAnnotation bean = new DocWithMapDataSimpleAnnotation(); bean.mapDatas = needEncodingMapData; assertEquals( "my/value", _nonJaxbMapper.writeValueAsString(bean)); } } TestConflictingGetters.java000066400000000000000000000037311251656754200431320ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; public class TestConflictingGetters extends XmlTestBase { @JacksonXmlRootElement(localName = "output") static class Bean { public BeanInfo[] beanInfo; public BeanInfo[] beanOther; @JacksonXmlElementWrapper(localName = "beanInfo") @JacksonXmlProperty(localName = "item") public BeanInfo[] getBeanInfo() { return beanInfo; } public void setBeanInfo(BeanInfo[] beanInfo) { this.beanInfo = beanInfo; } @JacksonXmlElementWrapper(localName = "beanOther") @JacksonXmlProperty(localName = "item") public BeanInfo[] getBeanOther() { return beanOther; } public void setBeanOther(BeanInfo[] beanOther) { this.beanOther = beanOther; } } static class BeanInfo { public String name; public BeanInfo() { } public BeanInfo(String n) { name = n; } } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testIssue27() throws Exception { XmlMapper mapper = new XmlMapper(); Bean bean = new Bean(); BeanInfo beanInfo = new BeanInfo("name"); BeanInfo beanOther = new BeanInfo("name"); bean.setBeanInfo(new BeanInfo[] { beanInfo }); bean.setBeanOther(new BeanInfo[] { beanOther }); String json = mapper.writeValueAsString(bean); assertNotNull(json); // System.out.println(output); } } TestDeserialization.java000066400000000000000000000015021251656754200424550ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class TestDeserialization extends XmlTestBase { private static class EmptyStrings { @JacksonXmlProperty(isAttribute=true) public String a = "NOT SET"; public String b = "NOT SET"; } private final XmlMapper MAPPER = new XmlMapper(); // [Issue#25] public void testEmptyStringFromElemAndAttr() throws Exception { EmptyStrings ob = MAPPER.readValue("", EmptyStrings.class); assertNotNull(ob); assertEquals("", ob.a); assertEquals("", ob.b); } } TestEmptyContent.java000066400000000000000000000013271251656754200417650ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; /** * Test case(s) to see that we can map "empty" content into null, for convenience. * Currently Stax parser will throw an exception; we could either use buffering, * or catch the EOFException and take that as a hint. */ public class TestEmptyContent extends XmlTestBase { static class EmptyBean { } /** * [Issue#60]: should be able to detect "no content", ideally. */ public void testNoContent() throws Exception { XmlMapper mapper = new XmlMapper(); assertNull(mapper.readValue("", EmptyBean.class)); } } TestEnums.java000066400000000000000000000035131251656754200404220ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class TestEnums extends XmlTestBase { static enum TestEnum { A, B, C; } static class UntypedEnumBean { @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="__type") // this would actually work: // @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) public Object value; public UntypedEnumBean() { } public UntypedEnumBean(TestEnum v) { value = v; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testUntypedEnum() throws Exception { ObjectMapper mapper = new XmlMapper(); String xml = mapper.writeValueAsString(new UntypedEnumBean(TestEnum.B)); UntypedEnumBean result = mapper.readValue(xml, UntypedEnumBean.class); assertNotNull(result); assertNotNull(result.value); Object ob = result.value; if (TestEnum.class != ob.getClass()) { fail("Failed to deserialize TestEnum (got "+ob.getClass()+getName()+") from: "+xml); } assertEquals(TestEnum.B, result.value); } // [dataformat-xml#121] public void testRootEnumIssue121() throws Exception { String xml = MAPPER.writeValueAsString(TestEnum.B); TestEnum result = MAPPER.readValue(xml, TestEnum.class); assertNotNull(result); assertEquals(TestEnum.B, result); } } TestPolymorphic.java000066400000000000000000000066601251656754200416460ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class TestPolymorphic extends XmlTestBase { /* /********************************************************** /* Helper types /********************************************************** */ @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) static class BaseTypeWithClassProperty { } static class SubTypeWithClassProperty extends BaseTypeWithClassProperty { public String name; public SubTypeWithClassProperty() { } public SubTypeWithClassProperty(String s) { name = s; } } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) static class BaseTypeWithClassArray { } static class SubTypeWithClassArray extends BaseTypeWithClassArray { public String name; public SubTypeWithClassArray() { } public SubTypeWithClassArray(String s) { name = s; } } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) static class BaseTypeWithClassObject { } static class SubTypeWithClassObject extends BaseTypeWithClassObject { public String name; public SubTypeWithClassObject() { } public SubTypeWithClassObject(String s) { name = s; } } /** * If not used as root element, need to use a wrapper */ static class ClassArrayWrapper { public BaseTypeWithClassArray wrapped; public ClassArrayWrapper() { } public ClassArrayWrapper(String s) { wrapped = new SubTypeWithClassArray(s); } } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ /* 19-Dec-2010, tatu: Let's hold off these tests, due to issues with inclusions. */ // Does not work since array wrapping is not explicitly forced (unlike with collection // property of a bean public void testAsClassArray() throws Exception { String xml = _xmlMapper.writeValueAsString(new SubTypeWithClassArray("Foobar")); Object result = _xmlMapper.readValue(xml, BaseTypeWithClassArray.class); assertNotNull(result); assertEquals(SubTypeWithClassArray.class, result.getClass()); assertEquals("Foobar", ((SubTypeWithClassArray) result).name); } // Hmmh. Does not yet quite work either, since we do not properly force // array context when writing... public void testAsWrappedClassArray() throws Exception { String xml = _xmlMapper.writeValueAsString(new ClassArrayWrapper("Foobar")); ClassArrayWrapper result = _xmlMapper.readValue(xml, ClassArrayWrapper.class); assertNotNull(result); assertEquals(SubTypeWithClassArray.class, result.wrapped.getClass()); assertEquals("Foobar", ((SubTypeWithClassArray) result.wrapped).name); } } TestUntypedListSerialization.java000066400000000000000000000031401251656754200443510ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; public class TestUntypedListSerialization extends XmlTestBase { @JacksonXmlRootElement(localName="L") static class UntypedListBean { public final Object list; public UntypedListBean() { ArrayList l= new ArrayList(); l.add("first"); l.add("second"); list = l; } } @JacksonXmlRootElement(localName="L") static class TypedListBean { public final List list; public TypedListBean() { ArrayList l= new ArrayList(); l.add("first"); l.add("second"); list = l; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); /* * For [Issue#8] -- Will not use wrapping, if type is not statically known * to be a Collection */ public void testListAsObject() throws IOException { String xmlForUntyped = MAPPER.writeValueAsString(new UntypedListBean()); String xmlForTyped = MAPPER.writeValueAsString(new TypedListBean()); assertEquals(xmlForTyped, xmlForUntyped); } } TestUnwrappedDeserIssue86.java000066400000000000000000000052161251656754200434540ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/failingpackage com.fasterxml.jackson.dataformat.xml.failing; import java.util.Arrays; import java.util.List; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; public class TestUnwrappedDeserIssue86 extends XmlTestBase { @JacksonXmlRootElement(localName = "test") public static class Issue86 { @JacksonXmlProperty(localName = "id", isAttribute = true) private String id; @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "test") private List children; public Issue86() {} public Issue86(final String id, final List children) { this.id = id; this.children = children; } @Override public boolean equals(final Object other) { if (other == null) { return false; } if (other == this) { return true; } if (!(other instanceof Issue86)) { return false; } final Issue86 otherIssue86 = (Issue86) other; return otherIssue86.id.equals(id) && otherIssue86.children.equals(children); } } /* /********************************************************************** /* Test methods /*********************************************************************** */ @Test public void deserializeUnwrappedListWhenLocalNameForRootElementAndXmlPropertyMatch() throws Exception { final String source = "" + "" + "" + "" + "" + "" + "" + "" + ""; final Issue86 before = new Issue86("0", Arrays.asList(new Issue86("0.1", Arrays.asList(new Issue86("0.1.1", null))), new Issue86("0.2", null), new Issue86("0.3", Arrays.asList( new Issue86("0.3.1", null))))); final XmlMapper mapper = new XmlMapper(); mapper.setSerializationInclusion(Include.NON_NULL); final String xml = mapper.writeValueAsString(before); assertEquals(source, xml); final Issue86 after = mapper.readValue(xml, Issue86.class); assertEquals(before, after); } } 000077500000000000000000000000001251656754200351505ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/incrIncrementalWritingTest.java000066400000000000000000000021231251656754200424560ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/incrpackage com.fasterxml.jackson.dataformat.xml.incr; import java.io.*; import javax.xml.stream.XMLStreamWriter; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class IncrementalWritingTest extends XmlTestBase { private final XmlMapper MAPPER = xmlMapper(true); public void testSimple() throws Exception { StringWriter strw = new StringWriter(); XMLStreamWriter sw = MAPPER.getFactory().getXMLOutputFactory().createXMLStreamWriter(strw); sw.writeStartElement("root"); MAPPER.writeValue(sw, new NameBean(13, "Grizabella", "Glamour")); MAPPER.writeValue(sw, new NameBean(17, "Growl", "Tiger")); sw.writeEndElement(); sw.writeEndDocument(); sw.close(); String xml = strw.toString().trim(); assertEquals("" +"GrizabellaGlamour" +"GrowlTiger", xml); } } PartialReadTest.java000066400000000000000000000035141251656754200410460ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/incrpackage com.fasterxml.jackson.dataformat.xml.incr; import java.io.*; import javax.xml.stream.*; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class PartialReadTest extends XmlTestBase { private final XmlMapper MAPPER = xmlMapper(true); public void testSimpleRead() throws Exception { final String XML = "" +"GrizabellaGlamour" +"GrowlTiger"; XMLStreamReader sr = MAPPER.getFactory().getXMLInputFactory().createXMLStreamReader( new StringReader(XML)); assertEquals(sr.next(), XMLStreamConstants.START_ELEMENT); assertEquals("root", sr.getLocalName()); /* 30-May-2014, tatu: This is bit tricky... need to ensure that currently * pointed to START_ELEMENT is sort of re-read. */ assertEquals(sr.next(), XMLStreamConstants.START_ELEMENT); assertEquals("NameBean", sr.getLocalName()); NameBean bean1 = MAPPER.readValue(sr, NameBean.class); assertNotNull(bean1); assertEquals(sr.getEventType(), XMLStreamConstants.END_ELEMENT); assertEquals("NameBean", sr.getLocalName()); assertEquals(sr.next(), XMLStreamConstants.START_ELEMENT); assertEquals("NameBean", sr.getLocalName()); NameBean bean2 = MAPPER.readValue(sr, NameBean.class); assertNotNull(bean2); assertEquals(sr.getEventType(), XMLStreamConstants.END_ELEMENT); assertEquals("NameBean", sr.getLocalName()); assertEquals(sr.next(), XMLStreamConstants.END_ELEMENT); assertEquals("root", sr.getLocalName()); sr.close(); } } 000077500000000000000000000000001251656754200351415ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/jaxbAttributesWithJAXBTest.java000066400000000000000000000037651251656754200423060ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/jaxbpackage com.fasterxml.jackson.dataformat.xml.jaxb; import java.io.IOException; import javax.xml.bind.annotation.*; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; public class AttributesWithJAXBTest extends XmlTestBase { @XmlAccessorType(value = XmlAccessType.FIELD) public class Jurisdiction { @XmlAttribute(name="name",required=true) protected String name = "Foo"; @XmlAttribute(name="value",required=true) protected int value = 13; } @XmlRootElement(name="problem") public static class Problem { @XmlAttribute(name="id") public String id; public String description; public Problem() { } public Problem(String id, String description) { this.id = id; this.description = description; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testTwoAttributes() throws IOException { XmlMapper mapper = new XmlMapper(); // mapper.setAnnotationIntrospector(new XmlJaxbAnnotationIntrospector(TypeFactory.defaultInstance())); mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(TypeFactory.defaultInstance())); String xml = mapper.writeValueAsString(new Jurisdiction()); assertEquals("", xml); } public void testAttributeAndElement() throws IOException { XmlMapper mapper = new XmlMapper(); mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(TypeFactory.defaultInstance())); String xml = mapper.writeValueAsString(new Problem("x", "Stuff")); assertEquals("Stuff", xml); } } ElementWrapperTest.java000066400000000000000000000054731251656754200416070ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/jaxbpackage com.fasterxml.jackson.dataformat.xml.jaxb; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class ElementWrapperTest extends XmlTestBase { @XmlRootElement(name = "Individual") static class MyPerson { public String name; @XmlElementWrapper(name = "offspring") @XmlElement(name = "kid") public List children = new ArrayList(); } @XmlRootElement(name="p") static class MyPerson2 { public String name; public List child = new ArrayList(); } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testElementWrapper() throws Exception { XmlMapper _jaxbMapper = new XmlMapper(); // Use JAXB-then-Jackson annotation introspector AnnotationIntrospector intr = XmlAnnotationIntrospector.Pair.instance (new XmlJaxbAnnotationIntrospector(TypeFactory.defaultInstance()), new JacksonAnnotationIntrospector()); _jaxbMapper.setAnnotationIntrospector(intr); MyPerson person = new MyPerson(); person.name = "Jay"; MyPerson child = new MyPerson(); child.name = "Junior"; person.children.add(child); String xml = _jaxbMapper.writer().writeValueAsString(person); String expected = "Jay" + "Junior"; assertEquals(expected, xml); } // And with JAXB, default should be "no wrapper" public void testNoElementWrapper() throws Exception { XmlMapper jaxbMapper = new XmlMapper(); jaxbMapper.setAnnotationIntrospector(new XmlJaxbAnnotationIntrospector(TypeFactory.defaultInstance())); MyPerson2 person = new MyPerson2(); person.name = "Jay"; MyPerson2 child = new MyPerson2(); child.name = "Junior"; person.child.add(child); String xml = jaxbMapper.writeValueAsString(person); String expected = "

JayJunior

"; assertEquals(expected, xml); } } WithJAXBAnnotationsTest.java000066400000000000000000000124041251656754200424430ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/jaxbpackage com.fasterxml.jackson.dataformat.xml.jaxb; import java.io.IOException; import javax.xml.bind.annotation.*; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.jaxb.XmlJaxbAnnotationIntrospector; /** * Although XML-backed data binding does not rely (or directly build) on JAXB * annotations, it should be possible to use them similar to how they are used * with default Jackson JSON data binding. Let's verify this is the case. */ public class WithJAXBAnnotationsTest extends XmlTestBase { /* /********************************************************************** /* Helper types /********************************************************************** */ @XmlRootElement(name="bean") public static class RootBean { public String value = "text"; } public static class AttrBean { @XmlAttribute public String attr = "3"; } @javax.xml.bind.annotation.XmlRootElement(name="Simple") static class WithXmlValue { @javax.xml.bind.annotation.XmlAttribute public int a = 13; @javax.xml.bind.annotation.XmlValue public String text = "something"; } @XmlRootElement(name = "Individual") static class MyPerson { @XmlAttribute(name = "identifier") public Long id; @XmlElement(name = "givenName") public String firstName; @XmlElement(name = "surName") public String lastName; public Long getId() { return id; } public void setId(final Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } } /* /********************************************************************** /* Set up /********************************************************************** */ protected XmlMapper _jaxbMapper; protected XmlMapper _nonJaxbMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _jaxbMapper = new XmlMapper(); _nonJaxbMapper = new XmlMapper(); // Use JAXB-then-Jackson annotation introspector AnnotationIntrospector intr = XmlAnnotationIntrospector.Pair.instance (new XmlJaxbAnnotationIntrospector(TypeFactory.defaultInstance()), new JacksonAnnotationIntrospector()); _jaxbMapper.setAnnotationIntrospector(intr); } /* /********************************************************************** /* Unit tests /********************************************************************** */ /** * Unit test for verifying that root element name can be overridden * with {@link XmlRootElement} annotation. */ public void testRootName() throws Exception { RootBean bean = new RootBean(); // without JAXB annotations will use class simple name: assertEquals("text", _nonJaxbMapper.writeValueAsString(bean)); assertEquals("text", _jaxbMapper.writeValueAsString(bean)); } /** * Unit test for verifying that a property defaults to being written as * element, but can be redefined with {@link XmlAttribute} annotation. */ public void testSerializeAsAttr() throws Exception { AttrBean bean = new AttrBean(); assertEquals("3", _nonJaxbMapper.writeValueAsString(bean)); assertEquals("", _jaxbMapper.writeValueAsString(bean)); } /** * Unit test for verifying correct handling of * {@link XmlValue} annotation. */ public void testAsTextWithJAXB() throws IOException { // first: serialize String xml = _jaxbMapper.writeValueAsString(new WithXmlValue()); assertEquals("something", xml); // and then deserialize back... WithXmlValue result = _jaxbMapper.readValue("else", WithXmlValue.class); assertEquals(99, result.a); assertEquals("else", result.text); } public void testPersonAsXml() throws Exception { MyPerson person = new MyPerson(); person.id = Long.valueOf(1L); person.firstName = "Jay"; person.lastName = "Unit"; String json = _jaxbMapper.writeValueAsString(person); // System.out.println("Person: " + json); String expected = "Jay" +"Unit"; assertEquals(expected, json); } } 000077500000000000000000000000001251656754200353535ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listsIssue101UnwrappedListAttributesTest.java000066400000000000000000000063161251656754200451670ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.*; // Failing unit test(s) wrt [Issue#64] public class Issue101UnwrappedListAttributesTest extends XmlTestBase { static class Optional { @JacksonXmlText public String number = "NOT SET"; @JacksonXmlProperty(isAttribute=true) public String type = "NOT SET"; public Optional() { } // uncommenting this ALSO works: // public Optional(String n) { number = n; } } static class Optionals { @JacksonXmlElementWrapper(useWrapping = false) public List optional; } // For [Issue#101] @JacksonXmlRootElement(localName = "root") @JsonPropertyOrder({ "unwrapped", "name" }) static class Root { @JacksonXmlProperty(localName = "unwrapped") @JacksonXmlElementWrapper(useWrapping = false) public List unwrapped; public String name; } static class UnwrappedElement { public UnwrappedElement () {} public UnwrappedElement (String id, String type) { this.id = id; this.type = type; } @JacksonXmlProperty(isAttribute = true) public String id; @JacksonXmlProperty(isAttribute = true) public String type; } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); // // [Issue#64] public void testOptionalsWithMissingType() throws Exception { // Optionals ob = MAPPER.readValue("123-456-7890", Optionals ob = MAPPER.readValue("123-456-7890", Optionals.class); assertNotNull(ob); assertNotNull(ob.optional); assertEquals(1, ob.optional.size()); // System.err.println("ob: " + ob); // works fine Optional opt = ob.optional.get(0); assertEquals("123-456-7890", opt.number); assertEquals("NOT SET", opt.type); } // [Issue#101] public void testWithTwoAttributes() throws Exception { final String EXP = "" +"" +"" +"test" +""; Root rootOb = new Root(); rootOb.unwrapped = Arrays.asList( new UnwrappedElement("1", "string"), new UnwrappedElement("2", "string") ); rootOb.name = "test"; // First, serialize, which works String xml = MAPPER.writeValueAsString(rootOb); assertEquals(EXP, xml); // then try deserialize Root result = MAPPER.readValue(xml, Root.class); assertNotNull(result); assertEquals(rootOb.name, result.name); } } ListAnnotationSharingTest.java000066400000000000000000000027661251656754200433530ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; // for [Issue#55] public class ListAnnotationSharingTest extends XmlTestBase { static class Wrapper { @JacksonXmlElementWrapper(localName = "Points", useWrapping = true) @JsonProperty("Point") List points = new ArrayList(); public List getPoints() { return points; } } static class Point { public int x, y; public Point() { } public Point(int x, int y) { this.x = x; this.y = y; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testAnnotationSharing() throws Exception { Wrapper input = new Wrapper(); input.points.add(new Point(1, 2)); String xml = MAPPER.writeValueAsString(input); assertEquals("12", xml); // and then back Wrapper result = MAPPER.readValue(xml, Wrapper.class); assertEquals(1, result.points.size()); } } ListAsObjectTest.java000066400000000000000000000044261251656754200414120ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @SuppressWarnings("serial") public class ListAsObjectTest extends XmlTestBase { static final class Value { @XmlElement(name = "v") public String v; public String getV() { return v; } public void setV(final String v) { this.v = v; } } @JsonFormat(shape=JsonFormat.Shape.OBJECT) static final class Values extends LinkedList { @XmlAttribute(name = "type") private String type; @JacksonXmlElementWrapper(localName = "value", useWrapping = false) @JacksonXmlProperty(localName = "value") List values = new ArrayList(); String getType() { return type; } void setType(final String type) { this.type = type; } List getValues() { return values; } void setValues(final List values) { this.values = values; } } public void testCollection() throws Exception { final Values values = new XmlMapper().readValue("" + " c" + " d" + "", Values.class); assertEquals(2, values.getValues().size(), 2); assertEquals("c", values.getValues().get(0).getV()); assertEquals("d", values.getValues().get(1).getV()); assertEquals("array", values.getType()); // Passes with 2.1.2 /* assertEquals(2, values.size()); assertEquals("c", values.get(0).getV()); assertEquals("d", values.get(1).getV()); */ } } ListDeserializationTest.java000066400000000000000000000130041251656754200430360ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.*; public class ListDeserializationTest extends XmlTestBase { /* /********************************************************** /* Helper types /********************************************************** */ @JacksonXmlRootElement(localName = "person", namespace ="http://example.org/person" ) public static class Person { @JacksonXmlProperty( isAttribute = true ) public String id; public String name; public int age; @JacksonXmlElementWrapper(localName = "notes") @JacksonXmlProperty(localName = "note" ) public List notes = new ArrayList(); public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } } public static class PersonWithGetters { @JacksonXmlProperty( isAttribute = true ) public String id; protected List _notes = new ArrayList(); public PersonWithGetters() { } public PersonWithGetters(String id) { this.id = id; } @JacksonXmlElementWrapper(localName = "notes") @JacksonXmlProperty( localName = "note" ) public List getStuff() { return _notes; } public void setStuff(List n) { _notes = n; } } static class ListBeanWrapped { @JacksonXmlElementWrapper public List values; } static class ListBeanUnwrapped { @JacksonXmlElementWrapper(useWrapping=false) public List values; } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); { // easier for eye: MAPPER.enable(SerializationFeature.INDENT_OUTPUT); } /* Issue#17 [https://github.com/FasterXML/jackson-dataformat-xml/issues/17] * * Problems deserializing otherwise properly wrapped lists */ public void testWrappedList() throws Exception { Person p = new Person( "Name", 30 ); p.notes.add("note 1"); p.notes.add("note 2"); String xml = MAPPER.writeValueAsString( p ); Person result = MAPPER.readValue(xml, Person.class); assertNotNull(result); assertEquals("Name", result.name); assertEquals(30, result.age); assertEquals(2, result.notes.size()); assertEquals("note 1", result.notes.get(0)); assertEquals("note 2", result.notes.get(1)); } public void testWrappedListWithGetters() throws Exception { PersonWithGetters p = new PersonWithGetters("abc"); p._notes.add("note 1"); p._notes.add("note 2"); String xml = MAPPER.writeValueAsString( p ); PersonWithGetters result = MAPPER.readValue(xml, PersonWithGetters.class); assertNotNull(result); assertEquals("abc", result.id); assertEquals(2, result._notes.size()); assertEquals("note 1", result._notes.get(0)); assertEquals("note 2", result._notes.get(1)); } public void testWrappedListBeanDeser() throws Exception { ListBeanWrapped bean = MAPPER.readValue( "123", ListBeanWrapped.class); assertNotNull(bean); assertNotNull(bean.values); assertEquals(3, bean.values.size()); assertEquals(Integer.valueOf(1), bean.values.get(0)); assertEquals(Integer.valueOf(2), bean.values.get(1)); assertEquals(Integer.valueOf(3), bean.values.get(2)); } // for [Issue#33] public void testWrappedListWithAttribute() throws Exception { ListBeanWrapped bean = MAPPER.readValue( "12", ListBeanWrapped.class); assertNotNull(bean); assertNotNull(bean.values); if (bean.values.size() < 2) { // preliminary check fail("List should have 2 entries, had "+bean.values.size()); } assertEquals(Integer.valueOf(1), bean.values.get(0)); assertEquals(Integer.valueOf(2), bean.values.get(1)); assertEquals(2, bean.values.size()); } public void testUnwrappedListBeanDeser() throws Exception { /* ListBeanUnwrapped foo = new ListBeanUnwrapped(); foo.values = new ArrayList(); foo.values.add(1); foo.values.add(2); foo.values.add(3); System.out.println("List -> "+MAPPER.writeValueAsString(foo)); */ ListBeanUnwrapped bean = MAPPER.readValue( "123", ListBeanUnwrapped.class); assertNotNull(bean); assertNotNull(bean.values); assertEquals(3, bean.values.size()); assertEquals(Integer.valueOf(1), bean.values.get(0)); assertEquals(Integer.valueOf(2), bean.values.get(1)); assertEquals(Integer.valueOf(3), bean.values.get(2)); } } ListRoundtripTest.java000066400000000000000000000127711251656754200417100ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.*; public class ListRoundtripTest extends XmlTestBase { @JacksonXmlRootElement(localName="parents") public static class Parents { @JacksonXmlElementWrapper(useWrapping=false) public List parent = new ArrayList(); } @JsonPropertyOrder({ "name", "desc", "prop" }) public static class Parent { @JacksonXmlProperty(isAttribute=true) public String name; public String description; @JacksonXmlElementWrapper(useWrapping=false) public List prop = new ArrayList(); public Parent() { } public Parent(String name, String desc) { this.name = name; description = desc; } } static class Prop { @JacksonXmlProperty(isAttribute=true) public String name; public String value; public Prop() { } public Prop(String name, String value) { this.name = name; this.value = value; } } // For [Issue#58] @JacksonXmlRootElement(localName = "point") static class Point { @JacksonXmlProperty(localName = "x", isAttribute = true) int x; @JacksonXmlProperty(localName = "y", isAttribute = true) int y; public Point() { } public Point(int x, int y) { this.x = x; this.y = y; } } @JacksonXmlRootElement(localName = "Points") static class PointContainer { @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "point") public List points; } // For [Issue#64] static class Optional { @JacksonXmlText public String number = "NOT SET"; @JacksonXmlProperty(isAttribute=true) public String type = "NOT SET"; } static class Optionals { @JacksonXmlElementWrapper(useWrapping = false) public List optional; } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); { // easier for eye, uncomment for testing // MAPPER.enable(SerializationFeature.INDENT_OUTPUT); } public void testParentListRoundtrip() throws Exception { Parents root = new Parents(); Parent parent1 = new Parent("a", "First"); root.parent.add(parent1); parent1.prop.add(new Prop("width", "13")); parent1.prop.add(new Prop("height", "10")); Parent parent2 = new Parent("b", "Second"); parent2.prop.add(new Prop("x", "1")); parent2.prop.add(new Prop("y", "2")); root.parent.add(parent2); String xml = MAPPER.writeValueAsString(root); assertNotNull(xml); // then bring it back Parents result = MAPPER.readValue(xml, Parents.class); assertNotNull(result.parent); assertEquals(2, result.parent.size()); Parent p2 = result.parent.get(1); assertNotNull(p2); assertEquals("b", p2.name); assertEquals("Second", p2.description); assertEquals(2, p2.prop.size()); Prop prop2 = p2.prop.get(1); assertNotNull(prop2); assertEquals("2", prop2.value); } public void testListWithAttrOnlyValues() throws Exception { PointContainer obj = new PointContainer(); obj.points = new ArrayList(); obj.points.add(new Point(1, 2)); obj.points.add(new Point(3, 4)); obj.points.add(new Point(5, 6)); String xml = MAPPER.writeValueAsString(obj); PointContainer converted = MAPPER.readValue(xml, PointContainer.class); assertEquals(3, converted.points.size()); assertNotNull(converted.points.get(0)); assertNotNull(converted.points.get(1)); assertNotNull(converted.points.get(2)); assertEquals(2, converted.points.get(0).y); assertEquals(4, converted.points.get(1).y); assertEquals(6, converted.points.get(2).y); } // // [Issue#64] public void testOptionals() throws Exception { Optionals ob = MAPPER.readValue("123-456-7890", Optionals.class); assertNotNull(ob); assertNotNull(ob.optional); assertEquals(1, ob.optional.size()); // System.err.println("ob: " + ob); // works fine Optional opt = ob.optional.get(0); assertEquals("123-456-7890", opt.number); assertEquals("work", opt.type); } /*// comment out for release public void testOptionalsWithMissingType() throws Exception { // Optionals ob = MAPPER.readValue("123-456-7890", Optionals ob = MAPPER.readValue("123-456-7890", Optionals.class); assertNotNull(ob); assertNotNull(ob.optional); assertEquals(1, ob.optional.size()); // System.err.println("ob: " + ob); // works fine Optional opt = ob.optional.get(0); assertEquals("123-456-7890", opt.number); assertEquals("NOT SET", opt.type); } */ }ListSerializationTest.java000066400000000000000000000050771251656754200425400ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; public class ListSerializationTest extends XmlTestBase { /* /********************************************************** /* Helper types /********************************************************** */ static class ListBean { public final List values = new ArrayList(); public ListBean() { } public ListBean(int... ints) { for (int i : ints) { values.add(Integer.valueOf(i)); } } } static class StringListBean { // to see what JAXB gives, uncomment: //@javax.xml.bind.annotation.XmlElementWrapper(name="stringList") @JacksonXmlElementWrapper(localName="stringList") public List strings; public StringListBean() { strings = new ArrayList(); } public StringListBean(String... texts) { strings = new ArrayList(); for (String text : texts) { strings.add(new StringBean(text)); } } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testSimpleWrappedList() throws IOException { String xml = MAPPER.writeValueAsString(new ListBean(1, 2, 3)); xml = removeSjsxpNamespace(xml); // 06-Dec-2010, tatu: Not completely ok; should default to not using wrapper... assertEquals("123", xml); } public void testStringList() throws IOException { StringListBean list = new StringListBean("a", "b", "c"); String xml = MAPPER.writeValueAsString(list); xml = removeSjsxpNamespace(xml); // 06-Dec-2010, tatu: Not completely ok; should default to not using wrapper... but it's what we have now assertEquals("" +"a" +"b" +"c" +"", xml); } } ListWithAttributes.java000066400000000000000000000063761251656754200420500ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.dataformat.xml.*; import com.fasterxml.jackson.dataformat.xml.annotation.*; public class ListWithAttributes extends XmlTestBase { // [Issue#43] static class Name { @JacksonXmlProperty(isAttribute=true) public String language; @JacksonXmlText public String text; // public String data; public Name() { } } static class RoomName { @JacksonXmlElementWrapper(localName = "names", useWrapping=true) @JsonProperty("name") public List names; } // [Issue#99]: allow skipping unknown properties static class Root { @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "value") public List values; } public static class Value { @JacksonXmlProperty(isAttribute = true) public int id; } // [Issue#108]: unwrapped lists, more than one entry, id attributes static class Foo { @JacksonXmlElementWrapper(useWrapping = false) public List firstBar = new ArrayList(); @JacksonXmlElementWrapper(useWrapping = false) public List secondBar = new ArrayList(); } static class Bar { public String value; @JacksonXmlProperty(isAttribute = true) public int id; } /* /********************************************************** /* Test methods /********************************************************** */ // [Issue#43] public void testIssue43() throws Exception { String xmlData = "" +"SPECIAL" +""; XmlMapper xmlMapper = new XmlMapper(); RoomName roomName = xmlMapper.readValue(xmlData, RoomName.class); assertEquals(1, roomName.names.size()); assertEquals("SPECIAL", roomName.names.get(0).text); } // [Issue#99]: allow skipping unknown properties public void testListWithAttributes() throws Exception { String source = "" + " " + " " + ""; ObjectMapper mapper = new XmlMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); Root root = mapper.readValue(source, Root.class); assertNotNull(root.values); assertEquals(1, root.values.size()); } // [Issue#108]: unwrapped lists, more than one entry, id attributes public void testIdsFromAttributes() throws Exception { XmlMapper xmlMapper = new XmlMapper(); Foo foo = new Foo(); Bar bar1 = new Bar(); bar1.id = 1; bar1.value = "FIRST"; foo.firstBar.add(bar1); Bar bar2 = new Bar(); bar2.value = "SECOND"; bar2.id = 2; foo.secondBar.add(bar2); String string = xmlMapper.writeValueAsString(foo); Foo fooRead = xmlMapper.readValue(string, Foo.class); assertEquals(foo.secondBar.get(0).id, fooRead.secondBar.get(0).id); } } NestedUnwrappedListsTest.java000066400000000000000000000164151251656754200432140ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.List; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class NestedUnwrappedListsTest extends XmlTestBase { // // // Test static class ServiceDelivery { public String responseTimestamp; public List vehicleMonitoringDelivery; } static class VehicleMonitoringDelivery { public String responseTimestamp; public String validUntil; public List vehicleActivity; } static class VehicleActivity { public String recordedAtTime; } /* /********************************************************************** /* Set up /********************************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(false); _xmlMapper = new XmlMapper(module); _xmlMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy()); _xmlMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testNested1_2() throws Exception { final String XML = "\n" +" 2012-09-12T09:28:17.213-04:00\n" +" \n" +" 2012-09-12T09:28:17.213-04:00\n" +" 2012-09-12T09:29:17.213-04:00\n" +" \n" +" 2012-09-12T09:28:07.536-04:00\n" +" \n" +" \n" +" 2013-09-12T09:29:07.536-04:00\n" +" \n" +" \n" +"\n" ; ServiceDelivery svc = _xmlMapper.readValue(XML, ServiceDelivery.class); assertNotNull(svc); assertNotNull(svc.vehicleMonitoringDelivery); assertEquals(1, svc.vehicleMonitoringDelivery.size()); VehicleMonitoringDelivery del = svc.vehicleMonitoringDelivery.get(0); assertEquals("2012-09-12T09:28:17.213-04:00", del.responseTimestamp); assertNotNull(del); assertNotNull(del.vehicleActivity); assertEquals(2, del.vehicleActivity.size()); VehicleActivity act = del.vehicleActivity.get(1); assertNotNull(act); assertEquals("2013-09-12T09:29:07.536-04:00", act.recordedAtTime); } public void testNestedWithEmpty() throws Exception { final String XML = "\n" +" 2012-09-12T09:28:17.213-04:00\n" +" \n" +" \n" +"\n" ; ServiceDelivery svc = _xmlMapper.readValue(XML, ServiceDelivery.class); assertNotNull(svc); assertNotNull(svc.vehicleMonitoringDelivery); assertEquals(0, svc.vehicleMonitoringDelivery.size()); } public void testNestedWithEmpty2() throws Exception { final String XML = "\n" +" 2012-09-12T09:28:17.213-04:00\n" +" \n" +" \n" +" \n" +" \n" +"\n" ; ServiceDelivery svc = _xmlMapper.readValue(XML, ServiceDelivery.class); assertNotNull(svc); assertNotNull(svc.vehicleMonitoringDelivery); assertEquals(1, svc.vehicleMonitoringDelivery.size()); VehicleMonitoringDelivery del = svc.vehicleMonitoringDelivery.get(0); assertNotNull(del.vehicleActivity); assertEquals(0, del.vehicleActivity.size()); } public void testNested1_2b() throws Exception { final String XML = "\n" +" 2012-09-12T09:28:17.213-04:00\n" +" \n" +" \n" +" 2012-09-12T09:28:07.536-04:00\n" +" \n" +" \n" +" 2013-09-12T09:29:07.536-04:00\n" +" \n" +" 2012-09-12T09:28:17.213-04:00\n" +" 2012-09-12T09:29:17.213-04:00\n" +" \n" +"\n" ; ServiceDelivery svc = _xmlMapper.readValue(XML, ServiceDelivery.class); assertNotNull(svc); assertEquals("2012-09-12T09:28:17.213-04:00", svc.responseTimestamp); assertNotNull(svc.vehicleMonitoringDelivery); assertEquals(1, svc.vehicleMonitoringDelivery.size()); VehicleMonitoringDelivery del = svc.vehicleMonitoringDelivery.get(0); assertEquals("2012-09-12T09:29:17.213-04:00", del.validUntil); assertNotNull(del); assertNotNull(del.vehicleActivity); assertEquals(2, del.vehicleActivity.size()); VehicleActivity act = del.vehicleActivity.get(1); assertNotNull(act); assertEquals("2013-09-12T09:29:07.536-04:00", act.recordedAtTime); } public void testNested2_1() throws Exception { final String XML = "\n" +" 2012-09-12T09:28:17.213-04:00\n" +" \n" +" 2012-09-12T09:28:17.213-04:00\n" +" 2012-09-12T09:29:17.213-04:00\n" +" \n" +" 2012-09-12T09:28:07.536-04:00\n" +" \n" +" \n" +" \n" +" 2012-09-12T09:28:17.213-04:00\n" +" 2012-09-12T09:29:17.213-04:00\n" +" \n" +" 2012-09-12T09:28:07.536-04:00\n" +" \n" +" \n" +"\n" ; ServiceDelivery svc = _xmlMapper.readValue(XML, ServiceDelivery.class); assertNotNull(svc); assertEquals("2012-09-12T09:28:17.213-04:00", svc.responseTimestamp); assertNotNull(svc.vehicleMonitoringDelivery); assertEquals(2, svc.vehicleMonitoringDelivery.size()); VehicleMonitoringDelivery del = svc.vehicleMonitoringDelivery.get(1); assertNotNull(del); assertNotNull(del.vehicleActivity); assertEquals(1, del.vehicleActivity.size()); assertEquals("2012-09-12T09:28:07.536-04:00", del.vehicleActivity.get(0).recordedAtTime); } } RootListHandlingTest.java000066400000000000000000000146031251656754200423060ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** * Tests for verifying that Lists (and arrays) can be serialized even * when they are root values. */ public class RootListHandlingTest extends XmlTestBase { @JacksonXmlRootElement(localName="SR") @JsonPropertyOrder({ "id", "name", "description" }) public static class SampleResource { private Long id; private String name; private String description; public SampleResource() { } public SampleResource(long id, String n, String d) { this.id = id; name = n; description = d; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } } /* /********************************************************** /* Unit tests /********************************************************** */ // Test for ensuring that we can use ".withRootName()" to override // default name AND annotation public void testRenamedRootItem() throws Exception { XmlMapper xmlMapper = new XmlMapper(); String xml = xmlMapper .writer() .withRootName("Shazam") .writeValueAsString(new SampleResource(123, "Foo", "Barfy!")) .trim(); xml = removeSjsxpNamespace(xml); assertEquals("123FooBarfy!", xml); } // for [Issue#38] -- root-level Collections not supported public void testListSerialization() throws Exception { _testListSerialization(true); _testListSerialization(false); } private void _testListSerialization(boolean useWrapping) throws Exception { JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(useWrapping); XmlMapper xmlMapper = new XmlMapper(module); AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); xmlMapper.setAnnotationIntrospector(introspector); SampleResource r1 = new SampleResource(); r1.setId(123L); r1.setName("Albert"); r1.setDescription("desc"); SampleResource r2 = new SampleResource(); r2.setId(123L); r2.setName("William"); r2.setDescription("desc2"); List l = new ArrayList(); l.add(r1); l.add(r2); // to see what JAXB might do, uncomment: //System.out.println("By JAXB: "+jaxbSerialized(l)); // ArrayList.class, SampleResource.class)); String xml = xmlMapper .writerWithDefaultPrettyPrinter() .writeValueAsString(l) .trim(); // first trivial sanity checks assertNotNull(xml); if (xml.indexOf("") < 0) { fail("Unexpected output: should have as root element, got: "+xml); } // and then try reading back JavaType resListType = xmlMapper.getTypeFactory() .constructCollectionType(List.class, SampleResource.class); Object ob = xmlMapper.reader(resListType).readValue(xml); assertNotNull(ob); // System.err.println("XML -> "+xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(ob)); assertTrue(ob instanceof List); List resultList = (List) ob; assertEquals(2, resultList.size()); assertEquals(SampleResource.class, resultList.get(0).getClass()); assertEquals(SampleResource.class, resultList.get(1).getClass()); SampleResource rr = (SampleResource) resultList.get(1); assertEquals("William", rr.getName()); } // Related to #38 as well public void testArraySerialization() throws Exception { _testArraySerialization(true); _testArraySerialization(false); } private void _testArraySerialization(boolean useWrapping) throws Exception { JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(useWrapping); XmlMapper xmlMapper = new XmlMapper(module); AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); xmlMapper.setAnnotationIntrospector(introspector); SampleResource r1 = new SampleResource(); r1.setId(123L); r1.setName("Albert"); r1.setDescription("desc"); SampleResource r2 = new SampleResource(); r2.setId(123L); r2.setName("William"); r2.setDescription("desc2"); SampleResource[] input = new SampleResource[] { r1, r2 }; // to see what JAXB might do, uncomment: //System.out.println("By JAXB: "+jaxbSerialized(input)); String xml = xmlMapper .writerWithDefaultPrettyPrinter() .writeValueAsString(input) .trim(); // first trivial sanity checks assertNotNull(xml); // Is this good name? If not, what should be used instead? if (xml.indexOf("") < 0) { fail("Unexpected output: should have as root element, got: "+xml); } // and then try reading back SampleResource[] result = xmlMapper.reader(SampleResource[].class).readValue(xml); assertNotNull(result); // System.err.println("XML -> "+xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(ob)); assertEquals(2, result.length); SampleResource rr = result[1]; assertEquals("desc2", rr.getDescription()); } } UnwrappedListWithEmptyCData129Test.java000066400000000000000000000031351251656754200446650ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.List; import javax.xml.bind.annotation.XmlElement; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; public class UnwrappedListWithEmptyCData129Test extends XmlTestBase { static class ListValues { @XmlElement(name = "value", required = true) @JacksonXmlElementWrapper(useWrapping=false) public List value; } private final XmlMapper MAPPER = new XmlMapper(); { // easier for eye: MAPPER.enable(SerializationFeature.INDENT_OUTPUT); } // for [#129] public void testListWithEmptyCData() throws Exception { _testListWithEmptyCData(" "); _testListWithEmptyCData(""); } private void _testListWithEmptyCData(String cdata) throws Exception { ListValues result = MAPPER.readValue("\n" + "A\n" // + "\n" + ""+cdata+"\n" + "C\n" + "", ListValues.class); List values = result.value; assertEquals(3, values.size()); // expecting 3 values, getting only 1 assertEquals("A", values.get(0)); assertEquals(cdata, values.get(1)); // expecting empty string in second position assertEquals("C", values.get(2)); } } UnwrappedListsTest.java000066400000000000000000000140231251656754200420420ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.List; import javax.xml.bind.annotation.*; import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.*; public class UnwrappedListsTest extends XmlTestBase { static class Value { public String v; public Value() { } public Value(String str) { v = str; } } @XmlRootElement(name="list") @JsonRootName("list") static class WrappedList { @XmlElementWrapper(name="WRAP") @JacksonXmlElementWrapper(localName = "WRAP") public Value[] value; } @XmlRootElement(name="list") @JsonRootName("list") static class UnwrappedList { @JacksonXmlElementWrapper(useWrapping=false) public Value[] value; } static class DefaultList { public Value[] value; } // [Issue#64] static class Optionals { @JacksonXmlElementWrapper(useWrapping = false) public List optional; } static class Optional { @JacksonXmlText public String number = "NOT SET"; @JacksonXmlProperty(isAttribute=true) public String type = "NOT SET"; public Optional() { } } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testWrappedLists() throws Exception { XmlMapper mapper = new XmlMapper(); WrappedList list = new WrappedList(); list.value = new Value[] { new Value("a"), new Value("b") }; // First, serialize: String json = mapper.writeValueAsString(list); // withJAXB(list); assertEquals("ab", json); // then deserialize back WrappedList output = mapper.readValue(json, WrappedList.class); assertNotNull(output); assertNotNull(output.value); assertEquals(2, output.value.length); } public void testUnwrappedLists() throws Exception { XmlMapper mapper = new XmlMapper(); UnwrappedList list = new UnwrappedList(); list.value = new Value[] { new Value("c"), new Value("d") }; String json = mapper.writeValueAsString(list); // System.out.println("Unwrapped == "+json); // withJAXB(list); assertEquals("cd", json); // then deserialize back UnwrappedList output = mapper.readValue(json, UnwrappedList.class); assertNotNull(output); assertNotNull(output.value); assertEquals(2, output.value.length); } /** * Test to verify that default wrapping setting is used */ public void testDefaultWrapping() throws Exception { // by default, should be using wrapping, so: XmlMapper mapper = new XmlMapper(); DefaultList input = new DefaultList(); input.value = new Value[] { new Value("a"), new Value("b") }; String json = mapper.writeValueAsString(input); assertEquals("ab", json); DefaultList output = mapper.readValue(json, DefaultList.class); assertNotNull(output.value); assertEquals(2, output.value.length); // but can be changed not to use wrapping by default JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(false); mapper = new XmlMapper(module); json = mapper.writeValueAsString(input); assertEquals("ab", json); output = mapper.readValue(json, DefaultList.class); assertNotNull(output.value); assertEquals(2, output.value.length); } public void testDefaultWrappingWithEmptyLists() throws Exception { // by default, should be using wrapping, so: XmlMapper mapper = new XmlMapper(); String json = ""; DefaultList output = mapper.readValue(json, DefaultList.class); assertNotNull(output.value); assertEquals(1, output.value.length); // but without, should work as well JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(false); mapper = new XmlMapper(module); json = ""; output = mapper.readValue(json, DefaultList.class); assertNotNull(output.value); assertEquals(1, output.value.length); } // // [Issue#64] public void testOptionalsWithMissingType() throws Exception { XmlMapper mapper = new XmlMapper(); // Optionals ob = MAPPER.readValue("123-456-7890", Optionals ob = mapper.readValue("123-456-7890", Optionals.class); assertNotNull(ob); assertNotNull(ob.optional); assertEquals(1, ob.optional.size()); // System.err.println("ob: " + ob); // works fine Optional opt = ob.optional.get(0); assertEquals("123-456-7890", opt.number); assertEquals("NOT SET", opt.type); } /* void withJAXB(Object ob) throws Exception { JAXBContext jc = JAXBContext.newInstance(ob.getClass()); Marshaller m = jc.createMarshaller(); System.out.print("JAXB -> "); StringWriter sw = new StringWriter(); m.marshal(ob, sw); String xml = sw.toString(); if (xml.indexOf("")+2); } System.out.println(xml); } */ } WrappedListsTest.java000066400000000000000000000023271251656754200415030ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/listspackage com.fasterxml.jackson.dataformat.xml.lists; import java.util.*; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class WrappedListsTest extends XmlTestBase { static class Order { @JacksonXmlElementWrapper(localName = "line_items") @JacksonXmlProperty(localName = "item") private List line_items; // new ArrayList(); } static class ListItem { public int id; public ListItem(int id) { this.id = id; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = xmlMapper(true); // For [Issue#103] public void testEmptyList() throws Exception { String xml = MAPPER.writeValueAsString(new Order()); assertEquals("", xml); // If we expected Empty list, it'd be: // assertEquals("", xml); } } 000077500000000000000000000000001251656754200351505ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscArrayConversionsTest.java000066400000000000000000000231221251656754200421620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import java.util.*; import java.lang.reflect.Array; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; /* NOTE: copied from jackson-databind (with some pruning) */ /** * Conversion tests to ensure that standard ObjectMapper conversions * work despite XmlMapper having to add XML-specific work-arounds. */ public class ArrayConversionsTest extends XmlTestBase { static class IntListWrapper { public List values; } static class IntArrayWrapper { public int[] values; public IntArrayWrapper() { } public IntArrayWrapper(int[] v) { values = v; } } /* /******************************************************** /* Test methods /******************************************************** */ public void testNullXform() throws Exception { _testNullXform(xmlMapper(true)); _testNullXform(xmlMapper(false)); } private void _testNullXform(ObjectMapper mapper) throws Exception { // when given null, null should be returned without conversion (Java null has no type) assertNull(mapper.convertValue(null, Integer.class)); assertNull(mapper.convertValue(null, String.class)); assertNull(mapper.convertValue(null, byte[].class)); } /** * Tests to verify that primitive number arrays round-trip * correctly, i.e. type -> type gives equal (although * not necessarily same) output */ public void testArrayIdentityTransforms() throws Exception { _testArrayIdentityTransforms(xmlMapper(true)); _testArrayIdentityTransforms(xmlMapper(false)); } private void _testArrayIdentityTransforms(ObjectMapper mapper) throws Exception { // first integral types // (note: byte[] is ok, even if it goes to base64 and back) verifyByteArrayConversion(mapper, bytes(), byte[].class); verifyShortArrayConversion(mapper, shorts(), short[].class); verifyIntArrayConversion(mapper, ints(), int[].class); verifyLongArrayConversion(mapper, longs(), long[].class); // then primitive decimal types verifyFloatArrayConversion(mapper, floats(), float[].class); verifyDoubleArrayConversion(mapper, doubles(), float[].class); } public void testByteArrayFrom() throws Exception { _testByteArrayFrom(xmlMapper(true)); _testByteArrayFrom(xmlMapper(false)); } private void _testByteArrayFrom(ObjectMapper mapper) throws Exception { /* Note: byte arrays are tricky, since they are considered * binary data primarily, not as array of numbers. Hence * output will be base64 encoded... */ byte[] data = _convert(mapper, "c3VyZS4=", byte[].class); byte[] exp = "sure.".getBytes("Ascii"); verifyIntegralArrays(exp, data, exp.length); } public void testShortArrayToX() throws Exception { final XmlMapper mapper = new XmlMapper(); short[] data = shorts(); verifyShortArrayConversion(mapper, data, byte[].class); verifyShortArrayConversion(mapper, data, int[].class); verifyShortArrayConversion(mapper, data, long[].class); } public void testIntArrayToX() throws Exception { final XmlMapper mapper = new XmlMapper(); int[] data = ints(); verifyIntArrayConversion(mapper, data, byte[].class); verifyIntArrayConversion(mapper, data, short[].class); verifyIntArrayConversion(mapper, data, long[].class); List expNums = _numberList(data, data.length); // Alas, due to type erasure, need to use TypeRef, not just class List actNums = mapper.convertValue(data, new TypeReference>() {}); assertEquals(expNums, actNums); } public void testLongArrayToX() throws Exception { final XmlMapper mapper = new XmlMapper(); long[] data = longs(); verifyLongArrayConversion(mapper, data, byte[].class); verifyLongArrayConversion(mapper, data, short[].class); verifyLongArrayConversion(mapper, data, int[].class); List expNums = _numberList(data, data.length); List actNums = mapper.convertValue(data, new TypeReference>() {}); assertEquals(expNums, actNums); } public void testListToIntArray() throws Exception { _testListToIntArray(true); _testListToIntArray(false); } private void _testListToIntArray(boolean wrap) throws Exception { final XmlMapper mapper = xmlMapper(wrap); List in = new ArrayList(); in.add(1); in.add(2); in.add(3); int[] out = mapper.convertValue(in, int[].class); assertEquals(3, out.length); for (int i = 0; i < out.length; ++i) { assertEquals(i+1, out[i]); } } public void testListAsProperty() throws Exception { _testListAsProperty(true); _testListAsProperty(false); } private void _testListAsProperty(boolean wrap) throws Exception { final XmlMapper mapper = xmlMapper(wrap); IntListWrapper mid = mapper.convertValue(new IntArrayWrapper(new int[] { 1, 2, 3}), IntListWrapper.class); assertNotNull(mid); assertNotNull(mid.values); assertEquals(3, mid.values.size()); IntArrayWrapper output = mapper.convertValue(mid, IntArrayWrapper.class); assertEquals(3, output.values.length); assertEquals(3, output.values[2]); } /* /******************************************************** /* Helper methods /******************************************************** */ // note: all value need to be within byte range private byte[] bytes() { return new byte[] { 1, -1, 0, 98, 127 }; } private short[] shorts() { return new short[] { 1, -1, 0, 98, 127 }; } private int[] ints() { return new int[] { 1, -1, 0, 98, 127 }; } private long[] longs() { return new long[] { 1, -1, 0, 98, 127 }; } // note: use values that are exact in binary private double[] doubles() { return new double[] { 0.0, 0.25, -0.125, 10.5, 9875.0 }; } private float[] floats() { return new float[] { 0.0f, 0.25f, -0.125f, 10.5f, 9875.0f }; } private void verifyByteArrayConversion(ObjectMapper mapper, byte[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyShortArrayConversion(ObjectMapper mapper, short[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyIntArrayConversion(ObjectMapper mapper, int[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyLongArrayConversion(ObjectMapper mapper, long[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyIntegralArrays(data, result, data.length); } private void verifyFloatArrayConversion(ObjectMapper mapper, float[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyDoubleArrays(data, result, data.length); } private void verifyDoubleArrayConversion(ObjectMapper mapper, double[] data, Class arrayType) { T result = _convert(mapper, data, arrayType); verifyDoubleArrays(data, result, data.length); } private T _convert(ObjectMapper mapper, Object input, Class outputType) { // must be a primitive array, like "int[].class" if (!outputType.isArray()) throw new IllegalArgumentException(); if (!outputType.getComponentType().isPrimitive()) throw new IllegalArgumentException(); T result = mapper.convertValue(input, outputType); // sanity check first: assertNotNull(result); assertEquals(outputType, result.getClass()); return result; } private List _numberList(Object numberArray, int size) { ArrayList result = new ArrayList(size); for (int i = 0; i < size; ++i) { result.add((Number) Array.get(numberArray, i)); } return result; } /** * Helper method for checking that given collections contain integral Numbers * that essentially contain same values in same order */ private void verifyIntegralArrays(Object inputArray, Object outputArray, int size) { for (int i = 0; i < size; ++i) { Number n1 = (Number) Array.get(inputArray, i); Number n2 = (Number) Array.get(outputArray, i); double value1 = ((Number) n1).longValue(); double value2 = ((Number) n2).longValue(); assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); } } private void verifyDoubleArrays(Object inputArray, Object outputArray, int size) { for (int i = 0; i < size; ++i) { Number n1 = (Number) Array.get(inputArray, i); Number n2 = (Number) Array.get(outputArray, i); double value1 = ((Number) n1).doubleValue(); double value2 = ((Number) n2).doubleValue(); assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); } } } NodeTest.java000066400000000000000000000012361251656754200375420ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class NodeTest extends XmlTestBase { public void testMixed() throws Exception { final XmlMapper xmlMapper = new XmlMapper(); final ObjectMapper jsonMapper = new ObjectMapper(); JsonNode root = xmlMapper.readTree("first4second"); String json = jsonMapper.writeValueAsString(root); System.out.println("-> "+json); } } ObjectId104Test.java000066400000000000000000000031141251656754200405620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; /** * Unit test to showcase issue #104, based on TestObjectIdDeserialization unit test in databind package. */ public class ObjectId104Test extends XmlTestBase { // // Classes for external id from property annotations: static class IdWrapper { @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id") public ValueNode node; public IdWrapper() { } public IdWrapper(int v) { node = new ValueNode(v); } } static class ValueNode { public List value= new ArrayList(); public IdWrapper next; public ValueNode() { this(0); } public ValueNode(int v) { value.add(v); } } private final XmlMapper MAPPER = new XmlMapper(); // Another test to ensure ordering is not required (i.e. can do front references) public void testSimpleCollectionDeserWithForwardRefs() throws Exception { IdWrapper result = MAPPER.readValue("711" ,IdWrapper.class); assertEquals(7, (int)result.node.value.get(0)); assertSame(result.node, result.node.next.node); } } PolymorphicTypesTest.java000066400000000000000000000113041251656754200422040ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; public class PolymorphicTypesTest extends XmlTestBase { /* /********************************************************** /* Helper types /********************************************************** */ @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) static class BaseTypeWithClassProperty { } static class SubTypeWithClassProperty extends BaseTypeWithClassProperty { public String name; public SubTypeWithClassProperty() { } public SubTypeWithClassProperty(String s) { name = s; } } @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) protected static class BaseTypeWithClassObject { } protected static class SubTypeWithClassObject extends BaseTypeWithClassObject { public String name; public SubTypeWithClassObject() { } public SubTypeWithClassObject(String s) { name = s; } } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") protected static class TypeWithClassPropertyAndObjectId { public String id; public TypeWithClassPropertyAndObjectId() {} public TypeWithClassPropertyAndObjectId(String id) { this.id = id; } } protected static class Wrapper { public List data; public Wrapper(){} public Wrapper(List data) { this.data = data; } } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ public void testAsClassProperty() throws Exception { String xml = _xmlMapper.writeValueAsString(new SubTypeWithClassProperty("Foobar")); // Type info should be written as an attribute, so: /* 13-Jan-2010, tatu: With Jackson 1.7.1, it is possible to override type information * inclusion, which allows use of attribute over element, so: */ final String exp = "" //"<_class>com.fasterxml.jackson.xml.types.TestPolymorphic..SubTypeWithClassProperty" +"Foobar" ; assertEquals(exp, xml); Object result = _xmlMapper.readValue(xml, BaseTypeWithClassProperty.class); assertNotNull(result); assertEquals(SubTypeWithClassProperty.class, result.getClass()); assertEquals("Foobar", ((SubTypeWithClassProperty) result).name); } public void testAsClassObject() throws Exception { String xml = _xmlMapper.writeValueAsString(new SubTypeWithClassObject("Foobar")); Object result = _xmlMapper.readValue(xml, BaseTypeWithClassObject.class); assertNotNull(result); assertEquals(SubTypeWithClassObject.class, result.getClass()); assertEquals("Foobar", ((SubTypeWithClassObject) result).name); } /** * Test for issue 81 */ public void testAsPropertyWithObjectId() throws Exception { List data = new ArrayList(); TypeWithClassPropertyAndObjectId object = new TypeWithClassPropertyAndObjectId("Foobar"); data.add(object); // This will be written as an id reference instead of object; as such, no type info will be written. data.add(object); String xml = _xmlMapper.writeValueAsString(new Wrapper(data)); Wrapper result = _xmlMapper.readValue(xml, Wrapper.class); assertNotNull(result); assertSame(result.data.get(0), result.data.get(1)); assertEquals("Foobar", result.data.get(0).id); } } TextValueTest.java000066400000000000000000000127641251656754200406060ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.*; public class TextValueTest extends XmlTestBase { static class Simple { @JacksonXmlProperty(isAttribute=true) // same as: @javax.xml.bind.annotation.XmlAttribute public int a = 13; @JacksonXmlText // about same as: @javax.xml.bind.annotation.XmlValue public String text = "something"; } // [Issue#24] static class Main { @JsonProperty("com.test.stack") public Stack stack; } static class Stack { public String name; @JsonProperty("com.test.stack.slot") public Slot slot; } static class Slot { @JsonProperty("name") public String name; @JsonProperty("id") public String id; @JsonProperty("height") public String height; @JsonProperty("width") public String width; @JacksonXmlText public String value; } static class JAXBStyle { public String value; } // [Issue#66] static class Issue66Bean { @JacksonXmlProperty(isAttribute = true) protected String id; @JacksonXmlText protected String textValue; } // [Issue#72] static class TextOnlyBean { @JacksonXmlText protected String textValue; public TextOnlyBean() { } public TextOnlyBean(String str, boolean foo) { textValue = str; } } @JsonPropertyOrder({ "a", "b" }) static class TextOnlyWrapper { public TextOnlyBean a, b; public TextOnlyWrapper() { } public TextOnlyWrapper(String a, String b) { this.a = new TextOnlyBean(a, true); this.b = new TextOnlyBean(b, true); } } /* /********************************************************** /* Unit tests /********************************************************** */ private final XmlMapper MAPPER = new XmlMapper(); public void testSerializeAsText() throws IOException { String xml = MAPPER.writeValueAsString(new Simple()); assertEquals("something", xml); // [Issue#56]: should work with indentation as well xml = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(new Simple()); assertEquals("something", xml); } public void testDeserializeAsText() throws IOException { Simple result = MAPPER.readValue("else", Simple.class); assertEquals(99, result.a); assertEquals("else", result.text); } public void testIssue24() throws Exception { final String TEXT = "+/null/this is a long string"; final String XML = "
\n" +"\n" +"" +TEXT +"\n" +"\n" +"
"; Main main = MAPPER.readValue(XML, Main.class); assertNotNull(main.stack); assertNotNull(main.stack.slot); assertEquals(TEXT, main.stack.slot.value); } // for [Issue#36] public void testAlternateTextElementName() throws IOException { final String XML = "foo"; // first: verify that without change, POJO would not match: try { MAPPER.readValue(XML, JAXBStyle.class); fail("Should have failed"); } catch (JsonProcessingException e) { verifyException(e, "Unrecognized"); } JacksonXmlModule module = new JacksonXmlModule(); module.setXMLTextElementName("value"); XmlMapper mapper = new XmlMapper(module); JAXBStyle pojo = mapper.readValue(XML, JAXBStyle.class); assertEquals("foo", pojo.value); } // [Issue#66], implicit property from "XmlText" public void testIssue66() throws Exception { JacksonXmlModule module = new JacksonXmlModule(); module.setDefaultUseWrapper(false); XmlMapper mapper = new XmlMapper(module); final String XML = "text"; // let's start with deserialization Issue66Bean node = mapper.readValue(XML, Issue66Bean.class); assertEquals("id", node.id); assertEquals("text", node.textValue); // Let's serialize too String json = mapper.writeValueAsString(node); assertEquals(XML, json); } // [Issue#72] public void testTextOnlyPojo() throws Exception { XmlMapper mapper = xmlMapper(true); TextOnlyWrapper input = new TextOnlyWrapper("foo", "bar"); // serialization should work fine String xml = mapper.writeValueAsString(input); assertEquals("foobar", xml); // but how about deser? TextOnlyWrapper result = mapper.readValue(xml, TextOnlyWrapper.class); assertNotNull(result); assertEquals("foo", result.a.textValue); assertEquals("bar", result.b.textValue); } } UnwrappingWithXMLTest.java000066400000000000000000000106221251656754200422230ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; // for #12 public class UnwrappingWithXMLTest extends XmlTestBase { @JsonPropertyOrder({"x", "y"}) final static class Location { public int x; public int y; public Location() { } public Location(int x, int y) { this.x = x; this.y = y; } } // IMPORTANT: ordering DOES matter here @JsonPropertyOrder({ "name", "location" }) static class Unwrapping { public String name; @JsonUnwrapped(prefix="loc.") public Location location; public Unwrapping() { } public Unwrapping(String str, int x, int y) { name = str; location = new Location(x, y); } } static class UnwrappingWithAttributes{ @JacksonXmlProperty(isAttribute=true) public String name; @JacksonXmlProperty(isAttribute=true) @JsonUnwrapped(prefix="loc.") public Location location; public UnwrappingWithAttributes() { } public UnwrappingWithAttributes(String str, int x, int y) { name = str; location = new Location(x, y); } } static class UnwrappingSubWithAttributes{ @JacksonXmlProperty(isAttribute=true) public String name; @JsonUnwrapped(prefix="loc.") public LocationWithAttributes location; public UnwrappingSubWithAttributes() { } public UnwrappingSubWithAttributes(String str, int x, int y) { name = str; location = new LocationWithAttributes(x, y); } } @JsonPropertyOrder({"x", "y"}) final static class LocationWithAttributes { @JacksonXmlProperty(isAttribute=true) public int x; public int y; public LocationWithAttributes() { } public LocationWithAttributes(int x, int y) { this.x = x; this.y = y; } } /* /********************************************************** /* Tests /********************************************************** */ /** * Simple test to verify that explicit schema mapping works fine * with unwrapped entities */ public void testSimpleUnwrappingRoundtrip() throws Exception { final String XML = "Joe1527"; ObjectMapper mapper = xmlMapper(false); Unwrapping wrapper = mapper.reader(Unwrapping.class).readValue(XML); assertNotNull(wrapper); assertNotNull(wrapper.location); assertEquals(15, wrapper.location.x); assertEquals(27, wrapper.location.y); // should also write out the same way assertEquals(XML, mapper.writerFor(Unwrapping.class).writeValueAsString(wrapper)); } public void testUnwrappingWithAttribute() throws Exception { final String XML = ""; ObjectMapper mapper = xmlMapper(false); UnwrappingWithAttributes wrapper = mapper.reader(UnwrappingWithAttributes.class).readValue(XML); assertNotNull(wrapper); assertNotNull(wrapper.location); assertEquals(15, wrapper.location.x); assertEquals(27, wrapper.location.y); // should also write out the same way assertEquals(XML, mapper.writerFor(UnwrappingWithAttributes.class).writeValueAsString(wrapper)); } public void testUnwrappingSubWithAttribute() throws Exception { final String XML = "27"; ObjectMapper mapper = xmlMapper(false); UnwrappingSubWithAttributes wrapper = mapper.reader(UnwrappingSubWithAttributes.class).readValue(XML); assertNotNull(wrapper); assertNotNull(wrapper.location); assertEquals(15, wrapper.location.x); assertEquals(27, wrapper.location.y); // should also write out the same way assertEquals(XML, mapper.writerFor(UnwrappingSubWithAttributes.class).writeValueAsString(wrapper)); } } XmlTextTest.java000066400000000000000000000020321251656754200402550ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/miscpackage com.fasterxml.jackson.dataformat.xml.misc; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; public class XmlTextTest extends XmlTestBase { @JsonPropertyOrder({"first","second"}) class Data{ @JacksonXmlText public String first; public String second; public Data(String first, String second) { this.first = first; this.second = second; } } public void testXmlTextWithSuppressedValue() throws Exception { final XmlMapper mapper = new XmlMapper(); mapper.setSerializationInclusion(Include.NON_EMPTY); String xml = mapper.writeValueAsString(new Data("","second")); String expectedXml = "second"; assertEquals(expectedXml, xml); } } 000077500000000000000000000000001251656754200350065ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serTestIndentation.java000066400000000000000000000107531251656754200407730ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.util.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class TestIndentation extends XmlTestBase { /* /********************************************************** /* Helper types /********************************************************** */ static class StringWrapperBean { public StringWrapper string; public StringWrapperBean() { } public StringWrapperBean(String s) { string = new StringWrapper(s); } } static class IntWrapperBean { public IntWrapper wrapped; public IntWrapperBean() { } public IntWrapperBean(int i) { wrapped = new IntWrapper(i); } } // [Issue#45] static class AttrBean { @JacksonXmlProperty(isAttribute=true) public int count = 3; } static class AttrBean2 { @JacksonXmlProperty(isAttribute=true) public int count = 3; public int value = 14; } public class PojoFor123 { @JacksonXmlProperty(isAttribute = true) public String name; @JsonInclude(JsonInclude.Include.NON_EMPTY) public String property; public PojoFor123(String name) { this.name = name; } } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); _xmlMapper.configure(SerializationFeature.INDENT_OUTPUT, true); } /* /********************************************************** /* Unit tests /********************************************************** */ // Verify [JACKSON-444], Issue #1 public void testSimpleStringBean() throws Exception { String xml = _xmlMapper.writeValueAsString(new StringWrapperBean("abc")); // should have at least one linefeed, space... if (xml.indexOf('\n') < 0 || xml.indexOf(' ') < 0) { fail("No indentation: XML == "+xml); } // Let's verify we get similar stuff back, first: StringWrapperBean result = _xmlMapper.readValue(xml, StringWrapperBean.class); assertNotNull(result); assertEquals("abc", result.string.str); } public void testSimpleIntBean() throws Exception { String xml = _xmlMapper.writeValueAsString(new IntWrapperBean(42)); // should have at least one linefeed, space... if (xml.indexOf('\n') < 0 || xml.indexOf(' ') < 0) { fail("No indentation: XML == "+xml); } // Let's verify we get similar stuff back, first: IntWrapperBean result = _xmlMapper.readValue(xml, IntWrapperBean.class); assertNotNull(result); assertEquals(42, result.wrapped.i); } public void testSimpleMap() throws Exception { Map map = new HashMap(); map.put("a", "b"); String xml = _xmlMapper.writeValueAsString(map); // should have at least one linefeed, space... if (xml.indexOf('\n') < 0 || xml.indexOf(' ') < 0) { fail("No indentation: XML == "+xml); } // Let's verify we get similar stuff back, first: Map result = _xmlMapper.readValue(xml, Map.class); assertNotNull(result); assertEquals(1, result.size()); assertEquals("b", map.get("a")); } // [Issue#45]: Use of attributes should not force linefeed for empty elements public void testWithAttr() throws Exception { String xml = _xmlMapper.writeValueAsString(new AttrBean()); assertEquals("", xml); String xml2 = _xmlMapper.writeValueAsString(new AttrBean2()); assertEquals("\n 14\n", xml2); } public void testEmptyElem() throws Exception { PojoFor123 simple = new PojoFor123("foobar"); String xml = _xmlMapper.writeValueAsString(simple); assertEquals("", xml); } }TestJDKSerializability.java000066400000000000000000000076071251656754200422140ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.*; import javax.xml.namespace.QName; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; /** * Unit test related to core [Issue#31] (https://github.com/FasterXML/jackson-core/issues/31) * as it relates to XmlFactory. */ public class TestJDKSerializability extends XmlTestBase { @JacksonXmlRootElement(localName="MyPojo") static class MyPojo { public int x; int y; public MyPojo() { } public MyPojo(int x0, int y0) { x = x0; y = y0; } public int getY() { return y; } public void setY(int y) { this.y = y; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testXmlFactory() throws Exception { XmlFactory f = new XmlFactory(); String origXml = "text"; assertEquals(origXml, _writeXml(f, false)); // Ok: freeze dry factory, thaw, and try to use again: byte[] frozen = jdkSerialize(f); XmlFactory f2 = jdkDeserialize(frozen); assertNotNull(f2); assertEquals(origXml, _writeXml(f2, false)); // Let's also try byte-based variant, for fun... assertEquals(origXml, _writeXml(f2, true)); } public void testMapper() throws IOException { XmlMapper mapper = new XmlMapper(); final String EXP = "23"; final MyPojo p = new MyPojo(2, 3); assertEquals(EXP, mapper.writeValueAsString(p)); byte[] bytes = jdkSerialize(mapper); XmlMapper mapper2 = jdkDeserialize(bytes); assertEquals(EXP, mapper2.writeValueAsString(p)); MyPojo p2 = mapper2.readValue(EXP, MyPojo.class); assertEquals(p.x, p2.x); assertEquals(p.y, p2.y); } /* /********************************************************** /* Helper methods /********************************************************** */ protected byte[] jdkSerialize(Object o) throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000); ObjectOutputStream obOut = new ObjectOutputStream(bytes); obOut.writeObject(o); obOut.close(); return bytes.toByteArray(); } @SuppressWarnings("unchecked") protected T jdkDeserialize(byte[] raw) throws IOException { ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(raw)); try { return (T) objIn.readObject(); } catch (ClassNotFoundException e) { fail("Missing class: "+e.getMessage()); return null; } finally { objIn.close(); } } @SuppressWarnings("resource") protected String _writeXml(XmlFactory f, boolean useBytes) throws IOException { if (useBytes) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ToXmlGenerator jg = f.createGenerator(bytes); _write(f, jg); return bytes.toString("UTF-8"); } StringWriter sw = new StringWriter(); ToXmlGenerator jg = f.createGenerator(sw); _write(f, jg); return sw.toString(); } protected void _write(JsonFactory f, ToXmlGenerator jg) throws IOException { jg.setNextName(new QName("root")); jg.writeStartObject(); jg.writeFieldName("a"); jg.writeString("text"); jg.writeEndObject(); jg.close(); } } TestNamespaces.java000066400000000000000000000026271251656754200405770ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; public class TestNamespaces extends XmlTestBase { @JacksonXmlRootElement(localName="person", namespace="http://example.org/person" ) static class Person { private String name; @JacksonXmlProperty(namespace = "http://example.org/person") public String getName() { return name; } public void setName(String name) { this.name = name; } } /* /********************************************************** /* Unit tests /********************************************************** */ // [Issue-26]: should prefer the "default namespace" public void testRootNamespace() throws Exception { Person person = new Person(); person.setName( "hello" ); XmlMapper xmlMapper = new XmlMapper(); String xml = xmlMapper.writeValueAsString(person); // should use "the default namespace"... final String PREFIX = " { public T value; public WrapperBean() { } public WrapperBean(T v) { value = v; } } static class MapBean { public Map map; public MapBean() { } public MapBean(Map v) { map = v; } } static class NsElemBean { @JacksonXmlProperty(namespace="http://foo") public String text = "blah"; } @JacksonXmlRootElement(localName="root") static class RootBean { public String value = "123"; } @JacksonXmlRootElement(localName="nsRoot", namespace="http://foo") static class NsRootBean { public String value = "abc"; } static class CDataStringBean { @JacksonXmlCData public String value = " { public CustomSerializer() { super(String.class); } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeString("custom:"+value); } } static class CustomMap extends LinkedHashMap { } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ // Unit test to verify that root name is properly set public void testRootName() throws IOException { String xml = _xmlMapper.writeValueAsString(new StringBean()); // Hmmh. Looks like JDK Stax may adds bogus ns declaration. As such, // let's just check that name starts ok... if (!xml.startsWith("123", xml); // and namespace one too xml = _xmlMapper.writeValueAsString(new NsRootBean()); if (xml.indexOf("nsRoot") < 0) { // verify localName fail("Expected root name of 'nsRoot'; but XML document is ["+xml+"]"); } // and NS declaration if (xml.indexOf("http://foo") < 0) { fail("Expected NS declaration for 'http://foo', not found, XML document is ["+xml+"]"); } } public void testSimpleAttribute() throws IOException { String xml = _xmlMapper.writeValueAsString(new AttributeBean()); xml = removeSjsxpNamespace(xml); assertEquals("", xml); } public void testSimpleAttrAndElem() throws IOException { String xml = _xmlMapper.writeValueAsString(new AttrAndElem()); xml = removeSjsxpNamespace(xml); assertEquals("whatever", xml); } public void testSimpleNsElem() throws IOException { String xml = _xmlMapper.writeValueAsString(new NsElemBean()); xml = removeSjsxpNamespace(xml); // here we assume woodstox automatic prefixes, not very robust but: assertEquals("blah", xml); } @SuppressWarnings("boxing") public void testMap() throws IOException { // First, map in a general wrapper LinkedHashMap map = new LinkedHashMap(); map.put("a", 1); map.put("b", 2); String xml; xml = _xmlMapper.writeValueAsString(new WrapperBean>(map)); assertEquals("" +"1" +"2" +"", xml); // then as strongly typed xml = _xmlMapper.writeValueAsString(new MapBean(map)); assertEquals("" +"1" +"2" +"", xml); } public void testNakedMap() throws IOException { CustomMap input = new CustomMap(); input.put("a", 123); input.put("b", 456); String xml = _xmlMapper.writeValueAsString(input); // System.err.println("XML = "+xml); CustomMap result = _xmlMapper.readValue(xml, CustomMap.class); assertEquals(2, result.size()); assertEquals(Integer.valueOf(456), result.get("b")); } public void testCDataString() throws IOException { String xml = _xmlMapper.writeValueAsString(new CDataStringBean()); xml = removeSjsxpNamespace(xml); assertEquals("", xml); } public void testCDataStringArray() throws IOException { String xml = _xmlMapper.writeValueAsString(new CDataStringArrayBean()); xml = removeSjsxpNamespace(xml); assertEquals("", xml); } // for [Issue#41] public void testCustomSerializer() throws Exception { JacksonXmlModule module = new JacksonXmlModule(); module.addSerializer(String.class, new CustomSerializer()); XmlMapper xml = new XmlMapper(module); assertEquals("custom:foo", xml.writeValueAsString("foo")); } // manual 'test' to see "what would JAXB do?" /* public void testJAXB() throws Exception { StringWriter sw = new StringWriter(); javax.xml.bind.JAXB.marshal(new StringListBean("a", "b", "c"), sw); System.out.println("JAXB -> "+sw); } */ } TestSerializationAttr.java000066400000000000000000000100461251656754200421620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; public class TestSerializationAttr extends XmlTestBase { static class NsAttrBean { @JacksonXmlProperty(namespace="http://foo", isAttribute=true) public String attr = "3"; } @JacksonXmlRootElement(localName="test", namespace="http://root") static class Issue19Bean { @JsonProperty @JacksonXmlProperty(namespace = "http://my.ns") public boolean booleanA = true; @JsonProperty @JacksonXmlProperty(isAttribute=true) public String id = "abc"; } public class Jurisdiction { @JacksonXmlProperty(isAttribute=true) protected String name = "Foo"; @JacksonXmlProperty(isAttribute=true) protected int value = 13; } @JacksonXmlRootElement(localName = "dynaBean", namespace = "") @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "class", include = JsonTypeInfo.As.PROPERTY) public class DynaBean { private final Map _properties = new TreeMap(); public DynaBean(Map values) { _properties.putAll(values); } @JsonAnyGetter @JacksonXmlProperty(isAttribute = false) public Map getProperties() { return _properties; } } /* /********************************************************** /* Set up /********************************************************** */ protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimpleNsAttr() throws IOException { String xml = _xmlMapper.writeValueAsString(new NsAttrBean()); xml = removeSjsxpNamespace(xml); // here we assume woodstox automatic prefixes, not very robust but: assertEquals("", xml); } public void testIssue19() throws IOException { String xml = _xmlMapper.writeValueAsString(new Issue19Bean()); xml = removeSjsxpNamespace(xml); xml = xml.replaceAll("\"", "'"); // as with above, assumes exact NS allocation strategy, not optimal: assertEquals("" +"true", xml); } public void testIssue6() throws IOException { assertEquals("", _xmlMapper.writeValueAsString(new Jurisdiction())); } public void testIssue117AnySetterAttrs() throws IOException { Map values = new HashMap(); values.put("prop1", "val1"); String xml = _xmlMapper.writeValueAsString(new DynaBean(values)); assertEquals("val1", removeSjsxpNamespace(xml)); } /* /********************************************************** /* Helper methods /********************************************************** */ // manual 'test' to see "what would JAXB do?" /* public void testJAXB() throws Exception { StringWriter sw = new StringWriter(); javax.xml.bind.JAXB.marshal(new StringListBean("a", "b", "c"), sw); System.out.println("JAXB -> "+sw); } */ } TestSerializationManual.java000066400000000000000000000034101251656754200424620ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.StringWriter; import java.util.ArrayList; import javax.xml.namespace.QName; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; public class TestSerializationManual extends XmlTestBase { public static class Value { public int num; public Value(int n) { num = n; } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testIssue54() throws Exception { XmlMapper xmlMapper = new XmlMapper(); xmlMapper.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION); StringWriter sw = new StringWriter(); ToXmlGenerator generator = (ToXmlGenerator) xmlMapper.getFactory().createGenerator(sw); generator.initGenerator(); generator.setNextName(new QName("items")); generator.writeStartObject(); ArrayList values = new ArrayList(); values.add(new Value(13)); values.add(new Value(456)); for (Value value : values) { generator.writeFieldName("foo"); generator.setNextName(new QName("item")); generator.writeObject(value); } generator.writeEndObject(); generator.close(); String xml = sw.toString(); // Remove XML declaration assertTrue(xml.startsWith(""); xml = xml.substring(ix+2).trim(); assertEquals("13456", xml); } } TestSerializationOrdering.java000066400000000000000000000015631251656754200430250ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.dataformat.xml.*; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class TestSerializationOrdering extends XmlTestBase { @JsonPropertyOrder({"a", "c" }) static class Bean91 { public String a; @JacksonXmlProperty(isAttribute = true) public String b; public String c; public Bean91(String a, String b, String c) { this.a = a; this.b = b; this.c = c; } } public void testOrdering() throws Exception { XmlMapper xmlMapper = new XmlMapper(); String xml = xmlMapper.writeValueAsString(new Bean91("1", "2", "3")); assertEquals("13", xml); } } TestSerializerCustom.java000066400000000000000000000057031251656754200420220ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import java.io.IOException; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; /** * Unit test(s) for [Issue#42], problems with custom (de)serializer. */ @SuppressWarnings("serial") public class TestSerializerCustom extends XmlTestBase { @JsonPropertyOrder({ "name", "obj" }) static class Item { public String name; public Foo obj; public Item(String name, Foo obj) { this.name = name; this.obj = obj; } } static class Foo { public String name; protected Foo() { } public Foo(String name) { this.name = name; } } static class ItemDeserializer extends StdDeserializer { public ItemDeserializer() { super(Item.class); } @Override public Item deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { ObjectCodec oc = jp.getCodec(); JsonNode json = oc.readTree(jp); JsonNode foo = json.get("obj"); if (foo == null) { throw new IllegalStateException("missing foo property"); } return new Item(json.path("name").asText(), oc.treeToValue(foo, Foo.class)); } } public class ItemSerializer extends StdSerializer { public ItemSerializer() { super(Item.class); } @Override public void serialize(Item value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeStartObject(); jgen.writeObjectField("obj", value.obj); jgen.writeStringField("name", value.name); jgen.writeEndObject(); } } /* /********************************************************** /* Unit tests /********************************************************** */ public void testIssue42() throws Exception { XmlMapper xmlMapper = new XmlMapper(); SimpleModule m = new SimpleModule("module", new Version(1,0,0,null,null,null)); m.addSerializer(Item.class, new ItemSerializer()); m.addDeserializer(Item.class, new ItemDeserializer()); xmlMapper.registerModule(m); Item value = new Item("itemName", new Foo("fooName")); String xml = xmlMapper.writeValueAsString(value); Item result = xmlMapper.readValue(xml, Item.class); assertNotNull(result); assertEquals("itemName", result.name); assertNotNull(result.obj); assertEquals("fooName", result.obj.name); } } TestXmlDeclaration.java000066400000000000000000000022501251656754200414160ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/serpackage com.fasterxml.jackson.dataformat.xml.ser; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; public class TestXmlDeclaration extends XmlTestBase { /* /********************************************************** /* Unit tests /********************************************************** */ public void testXml10Declaration() throws Exception { XmlMapper mapper = new XmlMapper(); mapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); String xml = mapper.writeValueAsString(new StringBean("123")); assertEquals(xml, "123"); } public void testXml11Declaration() throws Exception { XmlMapper mapper = new XmlMapper(); mapper.configure(ToXmlGenerator.Feature.WRITE_XML_1_1, true); String xml = mapper.writeValueAsString(new StringBean("abcd")); assertEquals(xml, "abcd"); } } 000077500000000000000000000000001251656754200355105ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/streamFormatDetectionTest.java000066400000000000000000000150471251656754200423110ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/streampackage com.fasterxml.jackson.dataformat.xml.stream; import java.io.ByteArrayInputStream; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.format.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; public class FormatDetectionTest extends XmlTestBase { static class POJO { public int x, y; public POJO() { } public POJO(int x, int y) { this.x = x; this.y = y; } } static class ListPOJO { @JacksonXmlElementWrapper(localName="list") public List v = new ArrayList(); } /* /********************************************************** /* Test methods, success /********************************************************** */ public void testSimpleValidXmlDecl() throws Exception { XmlFactory f = new XmlFactory(); DataFormatDetector detector = new DataFormatDetector(f); String XML = ""; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(XML.getBytes("UTF-8"))); assertTrue(matcher.hasMatch()); assertEquals("XML", matcher.getMatchedFormatName()); assertSame(f, matcher.getMatch()); assertEquals(MatchStrength.FULL_MATCH, matcher.getMatchStrength()); // ensure we could build a parser... JsonParser jp = matcher.createParserWithMatch(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); jp.close(); } public void testSimpleValidRoot() throws Exception { XmlFactory f = new XmlFactory(); DataFormatDetector detector = new DataFormatDetector(f); String XML = ""; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(XML.getBytes("UTF-8"))); assertTrue(matcher.hasMatch()); assertEquals("XML", matcher.getMatchedFormatName()); assertSame(f, matcher.getMatch()); assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); // ensure we could build a parser... JsonParser jp = matcher.createParserWithMatch(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); jp.close(); } public void testSimpleValidDoctype() throws Exception { XmlFactory f = new XmlFactory(); DataFormatDetector detector = new DataFormatDetector(f); String XML = " "; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(XML.getBytes("UTF-8"))); assertTrue(matcher.hasMatch()); assertEquals("XML", matcher.getMatchedFormatName()); assertSame(f, matcher.getMatch()); assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); // ensure we could build a parser... JsonParser jp = matcher.createParserWithMatch(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); jp.close(); } public void testSimpleValidComment() throws Exception { XmlFactory f = new XmlFactory(); DataFormatDetector detector = new DataFormatDetector(f); String XML = " "; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(XML.getBytes("UTF-8"))); assertTrue(matcher.hasMatch()); assertEquals("XML", matcher.getMatchedFormatName()); assertSame(f, matcher.getMatch()); assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); // ensure we could build a parser... JsonParser jp = matcher.createParserWithMatch(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); jp.close(); } public void testSimpleValidPI() throws Exception { XmlFactory f = new XmlFactory(); DataFormatDetector detector = new DataFormatDetector(f); String XML = ""; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(XML.getBytes("UTF-8"))); assertTrue(matcher.hasMatch()); assertEquals("XML", matcher.getMatchedFormatName()); assertSame(f, matcher.getMatch()); assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); // ensure we could build a parser... JsonParser jp = matcher.createParserWithMatch(); assertToken(JsonToken.START_OBJECT, jp.nextToken()); jp.close(); } public void testSimpleViaObjectReader() throws Exception { ObjectMapper mapper = new ObjectMapper(); XmlMapper xmlMapper = new XmlMapper(); ObjectReader detecting = mapper.reader(POJO.class); detecting = detecting .withFormatDetection(detecting, xmlMapper.reader(POJO.class)); POJO pojo = detecting.readValue(utf8Bytes("31")); assertNotNull(pojo); assertEquals(1, pojo.x); assertEquals(3, pojo.y); } public void testListViaObjectReader() throws Exception { ObjectMapper mapper = new ObjectMapper(); XmlMapper xmlMapper = new XmlMapper(); ListPOJO list = new ListPOJO(); list.v.add(new POJO(1, 2)); list.v.add(new POJO(3, 4)); String xml = xmlMapper.writeValueAsString(list); ObjectReader detecting = mapper.reader(ListPOJO.class); ListPOJO resultList = detecting .withFormatDetection(detecting, xmlMapper.reader(ListPOJO.class)) .readValue(utf8Bytes(xml)); assertNotNull(resultList); assertEquals(2, resultList.v.size()); } /* /********************************************************** /* Test methods, error handling /********************************************************** */ public void testSimpleInvalid() throws Exception { DataFormatDetector detector = new DataFormatDetector(new XmlFactory()); final String NON_XML = "{\"foo\":\"bar\"}"; DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(NON_XML.getBytes("UTF-8"))); // should not have match assertFalse(matcher.hasMatch()); // and thus: assertEquals(MatchStrength.INCONCLUSIVE, matcher.getMatchStrength()); // also: assertNull(matcher.createParserWithMatch()); } } XmlGeneratorTest.java000066400000000000000000000074171251656754200416330ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/streampackage com.fasterxml.jackson.dataformat.xml.stream; import java.io.*; import javax.xml.namespace.QName; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; public class XmlGeneratorTest extends XmlTestBase { public void testSimpleElement() throws Exception { XmlFactory f = new XmlFactory(); StringWriter out = new StringWriter(); ToXmlGenerator gen = f.createGenerator(out); // root name is special, need to be fed first: gen.setNextName(new QName("root")); gen.writeStartObject(); gen.writeFieldName("elem"); gen.writeString("value"); gen.writeEndObject(); gen.close(); String xml = out.toString(); // one more thing: remove that annoying 'xmlns' decl, if it's there: xml = removeSjsxpNamespace(xml); assertEquals("value", xml); } public void testSimpleAttribute() throws Exception { XmlFactory f = new XmlFactory(); StringWriter out = new StringWriter(); ToXmlGenerator gen = f.createGenerator(out); // root name is special, need to be fed first: gen.setNextName(new QName("root")); gen.writeStartObject(); // and also need to force attribute gen.setNextIsAttribute(true); gen.writeFieldName("attr"); gen.writeString("value"); gen.writeEndObject(); gen.close(); String xml = out.toString(); // one more thing: remove that annoying 'xmlns' decl, if it's there: xml = removeSjsxpNamespace(xml); assertEquals("", xml); } public void testSecondLevelAttribute() throws Exception { XmlFactory f = new XmlFactory(); StringWriter out = new StringWriter(); ToXmlGenerator gen = f.createGenerator(out); gen.setNextName(new QName("root")); gen.writeStartObject(); gen.writeFieldName("elem"); gen.writeStartObject(); // and also need to force attribute gen.setNextIsAttribute(true); gen.writeFieldName("attr"); gen.writeString("value"); gen.writeEndObject(); gen.writeEndObject(); gen.close(); String xml = out.toString(); // one more thing: remove that annoying 'xmlns' decl, if it's there: xml = removeSjsxpNamespace(xml); assertEquals("", xml); } public void testAttrAndElem() throws Exception { XmlFactory f = new XmlFactory(); StringWriter out = new StringWriter(); ToXmlGenerator gen = f.createGenerator(out); gen.setNextName(new QName("root")); gen.writeStartObject(); // and also need to force attribute gen.writeFieldName("attr"); gen.setNextIsAttribute(true); gen.writeNumber(-3); // Also let's add child element as well gen.setNextIsAttribute(false); gen.writeFieldName("elem"); gen.writeNumber(13); gen.writeEndObject(); gen.close(); String xml = removeSjsxpNamespace(out.toString()); assertEquals("13", xml); } // [Issue#6], missing overrides for File-backed generator public void testWriteToFile() throws Exception { ObjectMapper mapper = new XmlMapper(); File f = File.createTempFile("test", ".tst"); mapper.writeValue(f, new IntWrapper(42)); String xml = readAll(f).trim(); assertEquals("42", xml); f.delete(); } } XmlParserTest.java000066400000000000000000000253641251656754200411420ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/streampackage com.fasterxml.jackson.dataformat.xml.stream; import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser; public class XmlParserTest extends XmlTestBase { /* /********************************************************** /* Set up /********************************************************** */ protected JsonFactory _jsonFactory; protected XmlFactory _xmlFactory; protected XmlMapper _xmlMapper; // let's actually reuse XmlMapper to make things bit faster @Override public void setUp() throws Exception { super.setUp(); _jsonFactory = new JsonFactory(); _xmlFactory = new XmlFactory(); _xmlMapper = new XmlMapper(); } /* /********************************************************** /* Unit tests /********************************************************** */ public void testSimplest() throws Exception { assertEquals("{\"leaf\":\"abc\"}", _readXmlWriteJson("abc")); } public void testSimpleWithEmpty() throws Exception { assertEquals("{\"leaf\":null}", _readXmlWriteJson("")); } public void testSimpleNested() throws Exception { assertEquals("{\"a\":{\"b\":{\"c\":\"xyz\"}}}", _readXmlWriteJson("xyz")); } /** * Unit test that verifies that we can write sample document from JSON * specification as XML, and read it back in "as JSON", with * expected transformation. */ public void testRoundTripWithSample() throws Exception { // First: let's convert from sample JSON doc to default xml output JsonNode root = new ObjectMapper().readTree(SAMPLE_DOC_JSON_SPEC); String xml = _xmlMapper.writeValueAsString(root); // Here we would ideally use base class test method. Alas, it won't // work due to couple of problems; // (a) All values are reported as Strings (not ints, for example // (b) XML mangles arrays, so all we see are objects. // Former could be worked around; latter less so at this point. // So, for now, let's just do sort of minimal verification, manually JsonParser jp = _xmlMapper.getFactory().createParser(xml); assertToken(JsonToken.START_OBJECT, jp.nextToken()); // main object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image' verifyFieldName(jp, "Image"); assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' verifyFieldName(jp, "Width"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_WIDTH), jp.getText()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' verifyFieldName(jp, "Height"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_HEIGHT), jp.getText()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title' verifyFieldName(jp, "Title"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail' verifyFieldName(jp, "Thumbnail"); assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url' verifyFieldName(jp, "Url"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' verifyFieldName(jp, "Height"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_TN_HEIGHT), jp.getText()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' verifyFieldName(jp, "Width"); // Width value is actually a String in the example assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp)); assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object // Note: arrays are "eaten"; wrapping is done using BeanPropertyWriter, so: //assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs' //verifyFieldName(jp, "IDs"); //assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'ids' array assertToken(JsonToken.FIELD_NAME, jp.nextToken()); verifyFieldName(jp, "IDs"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_TN_ID1), getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); verifyFieldName(jp, "IDs"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_TN_ID2), getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); verifyFieldName(jp, "IDs"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_TN_ID3), getAndVerifyText(jp)); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); verifyFieldName(jp, "IDs"); assertToken(JsonToken.VALUE_STRING, jp.nextToken()); assertEquals(String.valueOf(SAMPLE_SPEC_VALUE_TN_ID4), getAndVerifyText(jp)); // no matching entry for array: //assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'ids' array assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object jp.close(); } /** * Test to ensure functionality used to force an element to be reported * as "JSON" Array, instead of default Object. */ public void testForceElementAsArray() throws Exception { final String XML = "value1231"; FromXmlParser xp = (FromXmlParser) _xmlFactory.createParser(new StringReader(XML)); // First: verify handling without forcing array handling: assertToken(JsonToken.START_OBJECT, xp.nextToken()); // assertToken(JsonToken.FIELD_NAME, xp.nextToken()); // assertEquals("elem", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("value", xp.getText()); assertToken(JsonToken.FIELD_NAME, xp.nextToken()); // assertEquals("elem", xp.getCurrentName()); assertToken(JsonToken.START_OBJECT, xp.nextToken()); // assertToken(JsonToken.FIELD_NAME, xp.nextToken()); assertEquals("property", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("123", xp.getText()); assertToken(JsonToken.END_OBJECT, xp.nextToken()); // assertToken(JsonToken.FIELD_NAME, xp.nextToken()); // assertEquals("elem", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("1", xp.getText()); assertToken(JsonToken.END_OBJECT, xp.nextToken()); // xp.close(); // And then with array handling: xp = (FromXmlParser) _xmlFactory.createParser(new StringReader(XML)); assertTrue(xp.getParsingContext().inRoot()); assertToken(JsonToken.START_OBJECT, xp.nextToken()); // assertTrue(xp.getParsingContext().inObject()); // true until we do following: // must request 'as-array' handling, which will "convert" current token: assertTrue("Should 'convert' START_OBJECT to START_ARRAY", xp.isExpectedStartArrayToken()); assertToken(JsonToken.START_ARRAY, xp.getCurrentToken()); // assertTrue(xp.getParsingContext().inArray()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertTrue(xp.getParsingContext().inArray()); assertEquals("value", xp.getText()); assertToken(JsonToken.START_OBJECT, xp.nextToken()); // assertTrue(xp.getParsingContext().inObject()); assertToken(JsonToken.FIELD_NAME, xp.nextToken()); assertEquals("property", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("123", xp.getText()); assertTrue(xp.getParsingContext().inObject()); assertToken(JsonToken.END_OBJECT, xp.nextToken()); // assertTrue(xp.getParsingContext().inArray()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertTrue(xp.getParsingContext().inArray()); assertEquals("1", xp.getText()); assertToken(JsonToken.END_ARRAY, xp.nextToken()); // assertTrue(xp.getParsingContext().inRoot()); xp.close(); } /* /********************************************************** /* Helper methods /********************************************************** */ public void testXmlAttributes() throws Exception { final String XML = ""; FromXmlParser xp = (FromXmlParser) _xmlFactory.createParser(new StringReader(XML)); // First: verify handling without forcing array handling: assertToken(JsonToken.START_OBJECT, xp.nextToken()); // assertToken(JsonToken.FIELD_NAME, xp.nextToken()); // assertEquals("max", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("7", xp.getText()); assertToken(JsonToken.FIELD_NAME, xp.nextToken()); // assertEquals("offset", xp.getCurrentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("9", xp.getText()); assertToken(JsonToken.END_OBJECT, xp.nextToken()); // xp.close(); } private String _readXmlWriteJson(String xml) throws IOException { StringWriter w = new StringWriter(); JsonParser jp = _xmlFactory.createParser(xml); JsonGenerator jg = _jsonFactory.createGenerator(w); while (jp.nextToken() != null) { jg.copyCurrentEvent(jp); } jp.close(); jg.close(); return w.toString(); } } XmlTokenStreamTest.java000066400000000000000000000103751251656754200421360ustar00rootroot00000000000000jackson-dataformat-xml-jackson-dataformat-xml-2.5.3/src/test/java/com/fasterxml/jackson/dataformat/xml/streampackage com.fasterxml.jackson.dataformat.xml.stream; import java.io.*; import javax.xml.stream.*; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.deser.XmlTokenStream; public class XmlTokenStreamTest extends XmlTestBase { public void testSimple() throws Exception { String XML = "abc"; XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(XML)); // must point to START_ELEMENT, so: sr.nextTag(); XmlTokenStream tokens = new XmlTokenStream(sr, XML); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.getCurrentToken()); assertEquals("root", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next()); assertEquals("leaf", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_ATTRIBUTE_NAME, tokens.next()); assertEquals("id", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_ATTRIBUTE_VALUE, tokens.next()); assertEquals("123", tokens.getText()); assertEquals(XmlTokenStream.XML_TEXT, tokens.next()); assertEquals("abc", tokens.getText()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END, tokens.next()); } public void testRootAttributes() throws Exception { String XML = ""; XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(XML)); // must point to START_ELEMENT, so: sr.nextTag(); XmlTokenStream tokens = new XmlTokenStream(sr, XML); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.getCurrentToken()); assertEquals("root", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_ATTRIBUTE_NAME, tokens.next()); assertEquals("id", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_ATTRIBUTE_VALUE, tokens.next()); assertEquals("x", tokens.getText()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END, tokens.next()); } public void testEmptyTags() throws Exception { String XML = ""; XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(XML)); // must point to START_ELEMENT, so: sr.nextTag(); XmlTokenStream tokens = new XmlTokenStream(sr, XML); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.getCurrentToken()); assertEquals("root", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next()); assertEquals("leaf", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END, tokens.next()); } public void testNested() throws Exception { String XML = "abc"; XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(XML)); sr.nextTag(); XmlTokenStream tokens = new XmlTokenStream(sr, XML); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.getCurrentToken()); assertEquals("root", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next()); assertEquals("a", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next()); assertEquals("b", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next()); assertEquals("c", tokens.getLocalName()); assertEquals(XmlTokenStream.XML_TEXT, tokens.next()); assertEquals("abc", tokens.getText()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next()); assertEquals(XmlTokenStream.XML_END, tokens.next()); } }