//
// Copyright (c) 2020, 2021 Contributors to the Eclipse Foundation
//

[appendix]
== Enhanced Binary Data Handling

=== Overview

Optimized transmission of binary data as
attachments is described by standards such as Soap [MTOM]/Xml-binary
Optimized Packaging[XOP] and WS-I Attachment Profile 1.0 [WSIAP]. To
optimally support these standards when JAXB databinding is used within a
message passing environment, <<jakarta-xml-bind-attachments>>
specifies an API that allows for an
integrated, cooperative implementation of these standards between a
MIME-based package processor and the Jakarta XML Binding unmarshal/marshal
processes. An enhanced binding of MIME content to Java representation is
specified in <<Binding MIME Binary Data>>.

=== Binding MIME Binary Data

==== Binary Data Schema Annotation

As specified in [MIME], the XML Schema
annotation attribute, `xmime:expectedContentTypes`, lists the expected
MIME content-type(s) for element content whose type derives from the xsd
binary datatypes, `xs:base64Binary` or `xs:hexBinary`.

Jakarta XML Binding databinding recognizes this schema
constraint to improve the binding of MIME type constrained binary data
to Java representation. The `xmime:expectedContentType` attribute is
allowed on type definitions deriving from binary datatypes and on
element declarations with types that derive from binary datatypes. For
Jakarta XML Binding binding purposes, the schema annotation,
`xmime:expectedContentTypes` is evaluated for binding purposes for all
cases EXCEPT when the annotation is on an element declaration with a
named complex type definition. For that case, the
`xmime:expectedContentTypes` annotation must be located directly within
the scope of the complex type definition in order to impact the binding
of the complex type definition’s simple binary content.

===== Binding Known Media Type

When `@xmime:expectedContentTypes` schema
annotation only refers to one MIME type, it is considered a known media
type for the binary data. [MIME] does not require an `xmime:contentType`
attribute to hold the dynamic mime type for the binary data for this
case. JAXB binding can achieve an optimal binding for this case. The
default MIME type to Java datatype are in <<a5119>>.

.Default Binding for Known Media Type
[[a5119]]
[cols=",",options="header",]
|===
| MIME Type | Java Type
| `image/gif` | `java.awt.Image`
| `image/jpeg` | `java.awt.Image`
| `text/xml` or `application/xml` | `javax.xml.transform.Source`
| `_any other MIME types_` | `jakarta.activation.DataHandler`
|===

A JAXB program annotation element,
`@XmlMimeType`, is generated to preserve the known media type for use
at marshal time.

.schema with a known media type
[source,xml,indent="2"]
----
<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:tns="http://example.com/know-type"
           xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
           targetNamespace="http://example.com/know-type">
  <xs:import namespace="http://www.w3.org/2005/05/xmlmime"
             schemaLocation="http://www.w3.org/2005/05/xmlmime"/>
  <xs:element name="JPEGPicture"
              type="xs:base64binary"
              xmime:expectedContentTypes="image/jpeg"/>
</xs:schema>
----

.Jakarta XML Binding binding of Example 8-1
[source,java,indent="4"]
----
import java.awt.Image;
@XmlRegistry
class ObjectFactory {
    @XmlElementDecl(...)
    @XmlMimeType("image/jpeg")
    JAXBELement<Image> createJPEGPicture(Image value);
}
----

The `@XmlMimeType` annotation provides the
MIME content type needed by Jakarta XML Binding Marshaller to specify the mime type
to set `DataHandler.setContentType(String)`.

.Schema for local element declaration annotated with known media type
[[a5140]]
[source,xml,indent="2"]
----
<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:tns="http://example.com/know-type"
           xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
           targetNamespace="http://example.com/know-type">
  <xs:import namespace="http://www.w3.org/2005/05/xmlmime"
             schemaLocation="http://www.w3.org/2005/05/xmlmime"/>
  <xs:complexType name="Item">
    <xs:sequence>
      <xs:element name="JPEGPicture"
                  type="xs:base64Binary"
                  xmime:expectedContentTypes="image/jpeg"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
----

.Java Binding of <<a5140>>
[source,java,indent="4"]
----
import java.awt.Image;
public class Item {
    @XmlMimeType("image/jpeg")
    Image getJPEGPicture();
    void setJPEGPicture(Image value);
}
----

===== Binding Preferred Media Types

If there are more than one mime type listed
in `xmime:expectedContentTypes` or if there is one with a wildcard in
it, the annotation specifies the Preferred Media Types and recommends
that the binary data be simple content that has an attribute
`xmime:contentType` that specifies which of the
`xmime:expectedContentTypes` the binary data represents.

Given that the exact media type is not known
for this case, a Preferred Media Type binds to
`jakarta.activation.DataHandler`. `DataHandler` has a property
`get/setContentType` that should be kept synchronized with the value of
the JAXB binding for the `xmime:contentType` attribute.

==== Binding WS-I Attachment Profile `ref:swaRef`

An XML element or attribute with a type
definition of `ref:swaRef` is bound to a JAXB property with base type of
`jakarta.activation.DataHandler` and annotated with `@XmlAttachmentRef`.

=== jakarta.xml.bind.attachments

The abstract classes `AttachmentUnmarshaller`
and `AttachmentMarshaller` in package `jakarta.xml.bind.attachments` are
intended to be implemented by a MIME-based package processor, such as
Jakarta XML Web Services implementation, and are called during JAXB unmarshal/marshal.
The JAXB unmarshal/marshal processes the root part of a MIME-based
package, delegating knowledge of the overall package and its other parts
to the `Attachment*` class implementations.

==== AttachmentUnmarshaller

An implementation of this abstract class by a
MIME-based package processor provides access to package-level
information that is outside the scope of the JAXB unmarshal process. A
MIME-based package processor registers its processing context with a
Jakarta XML Binding processor using the method
`setAttachmentUnmarshaller(AttachmentUnmarshaller)` of
`jakarta.xml.bind.Unmarshaller`.

Interactions between the Unmarshaller and the
abstract class are summarized below. The javadoc specifies the details.

[source,java,indent="4"]
----
public abstract class AttachmentUnmarshaller {
public boolean isXOPPackage();
public abstract DataHandler getAttachmentAsDataHandler(String cid);
public abstract byte[] getAttachmentAsByteArray(String cid);
}
----

The JAXB unmarshal process communicates with
a MIME-based package processor via an instance of AttachmentUnmarshaller
registered with the unmarshaller.
<<opbin>> summarizes this
processing.

* MTOM/XOP processing during unmarshal: +
When `isXOPPackage()` returns true, the unmarshaller replaces each XOP
include element it encounters with MIME content returned by the
appropriate `getAttachment*()` method.
* WS-I AP processing: +
Each element or attribute of type definition `ref:swaRef`, a content-id
uri reference to binary data, is resolved by the unmarshal process by a
call to the appropriate `getAttachment*()` method.

==== AttachmentMarshaller

An `AttachmentMarshaller` instance is
registered with a `jakarta.xml.bind.Marshaller` instance using the method
`Marshaller.setAttachmentMarshaller()`.

Interactions between the Marshaller and the
abstract class is summarized below. See the javadoc for details.

[source,java,indent="4"]
----
public abstract class AttachmentMarshaller {
public boolean isXOPPackage();
public abstract String addMtomAttachment(
                    DataHandler data,
                    String elementNamespace,
                    String elementLocalName);
public abstract String addMtomAttachment(
                    byte[] data,
                    String elementNamespace,
                    String elementLocalName);
public abstract String addSwaRefAttachment(DataHandler data);
}
----

When an AttachmentMarshaller instance is
registered with the Marshaller, the following processing takes place.

* MTOM/XOP processing: +
When `isXOPPackage()` is true and a JAXB property representing binary
data is being marshalled, the method `addMtomAttachment(..)` is called
to provide the MIME-based package processor the opportunity to decide to
optimize or inline the binary data.
+
Note that the schema customization specified in
<<inlinebinarydata-declaration>> can be
used to declaratively disable XOP processing for binary data.
* WS-I AP processing: +
The `addSwaRefAttachment` method is called when marshalling content
represented by a `ref:swaRef` type definition.
 +
One can declaratively customize swaRef processing within a schema using
schema customization @attachmentRef of <jaxb:property>, specified in
<<usage-4>>.

.JAXB marshal/unmarshalling of optimized binary content.
[[opbin]]
image::images/xmlb-23.png[image]

