Interface for admin command payloads--data carried
in the http request and response which flow between the admin client and the server.
This API also allows the requester to ask that the receiver remove a file,
presumably one that was transferred via an earlier request payload.
Motivation and Overview
The API is intended to be a simple abstraction of the
input and output streams in HTTP requests and responses,
inspired by the concepts from the mail API for
MIME body parts and multiparts.
A payload can contain zero or more parts.
If a payload contains only one part then only that part is sent or received
in the payload. If, on the other hand, the payload contains multiple parts
then the payload as a whole is a "multipart" payload which in turn contains
the individual parts.
Usage
Outbound
Code (on the client or the server) that needs to place data in the payload or
request that earlier-sent data be removed
would instantiate an implementation of
Payload.Outbound
. (The
PayloadImpl.Outbound
class is such an implementation.)
To this Payload.Outbound object the code can add parts using any of the
Payload.Outbound.addPart(java.lang.String, java.lang.String, java.util.Properties, java.lang.String)
methods or the
Payload.Outbound.attachFile(java.lang.String, java.net.URI, java.lang.String, java.io.File)
or
Payload.Outbound.requestFileRemoval(java.net.URI, java.lang.String, java.util.Properties)
convenience methods.
After the code has added all
the relevant parts to the payload it invokes the
Payload.Outbound.writeTo(java.io.OutputStream)
method to write
the outbound payload to an OutputStream. Typically the caller will pass the
output stream associated with the request (in the client case) or the response (in the
server case).
Inbound
Code that needs to read the payload from a request (as the server does) or
from a response (as the client does) will instantiate an implementation of
Payload.Inbound
. (The
PayloadImpl.Inbound
is such an implementation.
Payload.Inbound exposes the Payload.Inbound.parts()
method
which returns an Iterator<Part>. With each Payload.Part
available through the
iterator the caller can use Payload.Part.getContentType()
,
Payload.Part.getName()
, and Payload.Part.getInputStream()
.
Note that the caller should close the InputStream returned by getInputStream()
once it has read the data from the stream.
Part Properties
Each Part can carry with it Properties. The conventions as to what property
names are used and what they mean can vary from one admin command to the next.
For a file transfer these properties should be set:
- data-request-type=file-xfer
- data-request-name=(anything - typically the option name from the command to
help identify which part goes with which command argument)
- file-xfer-root=root path expression in the file system syntax of the system
where tranferred files will reside.
- last-modified=String representation of the long value recording the last-modified time of the original file
As an example as the server processes the "--retrieve xxx" option on the deploy and redeploy commands
it will specify file-xfer-root as xxx (in this example) to indicate where the
downloaded app client files should be stored on the
local system. Placing such information in the Part's properties helps to
decouple the admin client from the specifics of the command which triggered
the file transfer. That is, for example, the admin client does not need to
fetch the "--retrieve" option value to know where to store the transferred files
because the server placed this information with each part. The admin client
can therefore process this type of admin data request generically, without
regard to what command triggered the transfer.
The receiver of the file transfer request should return the
file-xfer-root value back to the requester without change so the local file path
syntax can be used correctly on the system where the file will exist.
Notes and Restrictions
In some implementations the caller must consume the contents of a
Part's input stream before advancing to the next Part. All callers should
follow this practice regardless of the underlying implementation used, in case
that implementation were to change in the future.