Class MultiPart.AbstractContentSource
- All Implemented Interfaces:
Closeable
,AutoCloseable
,Content.Source
- Direct Known Subclasses:
MultiPartByteRanges.ContentSource
,MultiPartFormData.ContentSource
- Enclosing class:
- MultiPart
An asynchronous Content.Source
where MultiPart.Part
s can
be added to it to form a multipart content.
When this Content.Source
is read, it will produce the
bytes (including boundary separators) in the multipart format.
Subclasses should override customizePartHeaders(Part)
to produce the right part headers depending on the specific
multipart subtype (for example, multipart/form-data
or
multipart/byteranges
, etc.).
Typical asynchronous usage is the following:
// Create a ContentSource subclass.
ContentSource source = ...;
// Add parts to the ContentSource.
source.addPart(new ByteBufferPart());
source.addPart(new PathPart());
// Close the ContentSource to signal
// that no more parts will be added.
source.close();
// The Sink where this ContentSource is written to.
Content.Sink sink = ...;
// Copy this ContentSource to the Sink.
Content.copy(source, sink, Callback.from(...));
Reading from ContentSource
may be performed at any time,
even if not all the parts have been added yet.
Adding parts and calling close()
may be done asynchronously
from other threads.
Eventually, reading from ContentSource
will produce a last
chunk when all the parts have been added and this ContentSource
has been closed.
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionboolean
addPart
(MultiPart.Part part) Adds, if possible, the givenMultiPart.Part
to thisContentSource
.void
close()
Closes thisContentSource
so that no more parts may be added.protected HttpFields
void
Demands to invoke the given demand callback parameter when a chunk of content is available.void
Fails this content source with alast
failure chunk
, failing and discarding accumulated content chunks that were not yet read.long
int
read()
Reads a chunk of content.void
setPartHeadersMaxLength
(int partHeadersMaxLength) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface org.eclipse.jetty.io.Content.Source
fail, rewind
-
Constructor Details
-
AbstractContentSource
-
-
Method Details
-
getBoundary
- Returns:
- the boundary string
-
getPartHeadersMaxLength
public int getPartHeadersMaxLength()- Returns:
- the max length of a
MultiPart.Part
headers, in bytes, or -1 for unlimited length
-
setPartHeadersMaxLength
public void setPartHeadersMaxLength(int partHeadersMaxLength) - Parameters:
partHeadersMaxLength
- the max length of aMultiPart.Part
headers, in bytes, or -1 for unlimited length
-
addPart
Adds, if possible, the given
MultiPart.Part
to thisContentSource
.Part
s may be added until thisContentSource
isclosed
.This method returns
true
if the part was added,false
if the part cannot be added because thisContentSource
is already closed, or because it has beenfailed
.- Parameters:
part
- theMultiPart.Part
to add- Returns:
- whether the part has been added
- See Also:
-
close
public void close()Closes this
ContentSource
so that no more parts may be added.Once this method is called, reading from this
ContentSource
will eventually produce a terminal multipart/form-data boundary, when all the part bytes have been read.- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceCloseable
-
getLength
public long getLength()- Specified by:
getLength
in interfaceContent.Source
- Returns:
- the content length, if known, or -1 if the content length is unknown
-
read
Description copied from interface:Content.Source
Reads a chunk of content.
See how to use this method idiomatically.
The returned chunk could be:
null
, to signal that there isn't a chunk of content available- an
Content.Chunk
instance with non nullContent.Chunk.getFailure()
, to signal that there was a failure trying to produce a chunk of content, or that the content production has beenfailed
externally - a
Content.Chunk
instance, containing the chunk of content.
Once a read returns an
Content.Chunk
instance with non-nullContent.Chunk.getFailure()
then if the failure islast
further reads will continue to return the same failure chunk instance, otherwise furtherread()
operations may return different non-failure chunks.Once a read returns a
last chunk
, further reads will continue to return a last chunk (although the instance may be different).The content reader code must ultimately arrange for a call to
Retainable.release()
on the returnedContent.Chunk
.Additionally, prior to the ultimate call to
Retainable.release()
, the reader code may make additional calls toRetainable.retain()
, that must ultimately be matched by a correspondent number of calls toRetainable.release()
.Concurrent reads from different threads are not recommended, as they are inherently in a race condition.
Reads performed outside the invocation context of a
demand callback
are allowed. However, reads performed with a pending demand are inherently in a race condition (the thread that reads with the thread that invokes the demand callback).- Specified by:
read
in interfaceContent.Source
- Returns:
- a chunk of content, possibly a failure instance, or
null
- See Also:
-
customizePartHeaders
-
demand
Description copied from interface:Content.Source
Demands to invoke the given demand callback parameter when a chunk of content is available.
See how to use this method idiomatically.
Implementations guarantee that calls to this method are safely reentrant so that stack overflows are avoided in the case of mutual recursion between the execution of the
Runnable
callback and a call to this method. Invocations of the passedRunnable
are serialized and a callback fordemand
call is not invoked until any previousdemand
callback has returned. Thus theRunnable
should not block waiting for a callback of a future demand call.The demand callback may be invoked spuriously: a subsequent call to
Content.Source.read()
may returnnull
.Calling this method establishes a pending demand, which is fulfilled when the demand callback is invoked.
Calling this method when there is already a pending demand results in an
IllegalStateException
to be thrown.If the invocation of the demand callback throws an exception, then
Content.Source.fail(Throwable)
is called.- Specified by:
demand
in interfaceContent.Source
- Parameters:
demandCallback
- the demand callback to invoke where there is a content chunk available- See Also:
-
fail
Description copied from interface:Content.Source
Fails this content source with a
last
failure chunk
, failing and discarding accumulated content chunks that were not yet read.The failure may be notified to the content reader at a later time, when the content reader reads a content chunk, via a
Content.Chunk
instance with a non nullContent.Chunk.getFailure()
.If
Content.Source.read()
has returned a last chunk, this is a no operation.Typical failure: the content being aborted by user code, or idle timeouts.
If this method has already been called, then it is a no operation.
- Specified by:
fail
in interfaceContent.Source
- Parameters:
failure
- the cause of the failure- See Also:
-