#7281 rewrite nextTransformedContent

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2021-12-20 12:38:40 +01:00
parent 1682265a00
commit 5cad97e134
1 changed files with 108 additions and 95 deletions

View File

@ -321,130 +321,143 @@ class AsyncContentProducer implements ContentProducer
{
if (LOG.isDebugEnabled())
LOG.debug("nextTransformedContent {}", this);
if (_rawContent == null)
while (true)
{
_rawContent = produceRawContent();
if (_rawContent == null)
return null;
}
if (_transformedContent != null && _transformedContent.isEmpty())
{
if (_transformedContent != _rawContent)
_transformedContent.succeeded();
if (LOG.isDebugEnabled())
LOG.debug("nulling depleted transformed content {}", this);
_transformedContent = null;
}
while (_transformedContent == null)
{
if (_interceptor != null)
if (_transformedContent != null && (_transformedContent.isSpecial() || !_transformedContent.isEmpty()))
{
if (LOG.isDebugEnabled())
LOG.debug("using interceptor to transform raw content {}", this);
_transformedContent = intercept();
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("null interceptor, transformed content = raw content {}", this);
_transformedContent = _rawContent;
}
if (_transformedContent != null)
{
if (_transformedContent.isSpecial())
if (_transformedContent.isSpecial() && !_error)
{
if (_transformedContent != _rawContent)
{
if (LOG.isDebugEnabled())
LOG.debug("making special transformed content the new raw content {}", this);
_rawContent.succeeded();
_rawContent = _transformedContent;
}
}
else if (_transformedContent.isEmpty())
{
if (_transformedContent != _rawContent)
_transformedContent.succeeded();
if (LOG.isDebugEnabled())
LOG.debug("nulling depleted transformed content {}", this);
_transformedContent = null;
}
}
if (_transformedContent == null)
{
if (_rawContent.isSpecial())
{
if (LOG.isDebugEnabled())
LOG.debug("checking if special raw content should be refreshed {}", this);
// In case the _rawContent was set by consumeAll(), check the httpChannel
// to see if it has a more precise error. Otherwise, the exact same
// special content will be returned by the httpChannel; do not do that
// if the _error flag was set, meaning the current error is definitive.
if (!_error)
{
HttpInput.Content refreshedRawContent = produceRawContent();
if (refreshedRawContent != null)
_rawContent = refreshedRawContent;
_error = _rawContent.getError() != null;
if (LOG.isDebugEnabled())
LOG.debug("refreshed raw content: {} {}", _rawContent, this);
}
HttpInput.Content refreshedRawContent = produceRawContent();
if (refreshedRawContent != null)
_rawContent = _transformedContent = refreshedRawContent;
_error = _rawContent.getError() != null;
if (LOG.isDebugEnabled())
LOG.debug("refreshed raw content: {} {}", _rawContent, this);
}
break;
}
else if (_rawContent.isEmpty())
{
if (LOG.isDebugEnabled())
LOG.debug("nulling depleted raw content {}", this);
_rawContent.succeeded();
_rawContent = null;
_rawContent = produceRawContent();
if (_rawContent == null)
{
if (LOG.isDebugEnabled())
LOG.debug("produced null raw content, returning null, {}", this);
break;
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("raw content is not empty {}", this);
}
if (LOG.isDebugEnabled())
LOG.debug("transformed content not yet depleted, returning it {}", this);
return _transformedContent;
}
else
if (_transformedContent != null && _transformedContent.isEmpty() && !_transformedContent.isSpecial())
{
if (LOG.isDebugEnabled())
LOG.debug("transformed content is not empty {}", this);
LOG.debug("current transformed content depleted {}", this);
_transformedContent.succeeded();
_transformedContent = null;
}
if (_rawContent == null)
{
if (LOG.isDebugEnabled())
LOG.debug("producing new raw content {}", this);
_rawContent = produceRawContent();
if (_rawContent == null)
{
if (LOG.isDebugEnabled())
LOG.debug("channel has no new raw content {}", this);
return null;
}
}
if (LOG.isDebugEnabled())
LOG.debug("transforming raw content {}", this);
transformRawContent();
}
}
private void transformRawContent()
{
if (_interceptor != null)
{
if (LOG.isDebugEnabled())
LOG.debug("intercepting raw content {}", this);
_transformedContent = intercept();
// If the interceptor generated a special content, _rawContent must become that special content.
if (_transformedContent != null && _transformedContent.isSpecial() && _transformedContent != _rawContent)
{
if (LOG.isDebugEnabled())
LOG.debug("interceptor generated a special content, _rawContent must become that special content {}", this);
_rawContent.succeeded();
_rawContent = _transformedContent;
return;
}
// If the interceptor generated a null content, recycle the raw content now if its empty.
if (_transformedContent == null && _rawContent.isEmpty() && !_rawContent.isSpecial())
{
if (LOG.isDebugEnabled())
LOG.debug("interceptor generated a null content, recycling the empty raw content now {}", this);
_rawContent.succeeded();
_rawContent = null;
return;
}
// If the interceptor returned the raw content, recycle the raw content now if its empty.
if (_transformedContent == _rawContent && _rawContent.isEmpty() && !_rawContent.isSpecial())
{
if (LOG.isDebugEnabled())
LOG.debug("interceptor returned the raw content, recycle the empty raw content now {}", this);
_rawContent.succeeded();
_rawContent = _transformedContent = null;
return;
}
}
else
{
// Recycle the raw content now if it is empty.
if (_rawContent.isEmpty() && !_rawContent.isSpecial())
{
if (LOG.isDebugEnabled())
LOG.debug("recycling the empty raw content now {}", this);
_rawContent.succeeded();
_rawContent = null;
}
if (LOG.isDebugEnabled())
LOG.debug("returning transformed content {}", this);
return _transformedContent;
if (LOG.isDebugEnabled())
LOG.debug("no interceptor, transformed content is raw content {}", this);
_transformedContent = _rawContent;
}
}
private HttpInput.Content intercept()
{
try
{
return _interceptor.readFrom(_rawContent);
HttpInput.Content content = _interceptor.readFrom(_rawContent);
if (content != null && content.isSpecial() && !_rawContent.isSpecial())
{
// Set the _error flag to mark the content as definitive, i.e.:
// do not try to produce new raw content to get a fresher error
// when the special content was generated by the interceptor.
_error = true;
if (LOG.isDebugEnabled())
LOG.debug("interceptor generated special content {}", this);
}
if (LOG.isDebugEnabled())
LOG.debug("intercepted raw content {}", this);
return content;
}
catch (Throwable x)
{
IOException failure = new IOException("Bad content", x);
failCurrentContent(failure);
// Set the _error flag to mark the error as definitive, i.e.:
// do not try to produce new raw content to get a fresher error.
// Set the _error flag to mark the content as definitive, i.e.:
// do not try to produce new raw content to get a fresher error
// when the special content was caused by the interceptor throwing.
_error = true;
Response response = _httpChannel.getResponse();
if (response.isCommitted())
_httpChannel.abort(failure);
if (LOG.isDebugEnabled())
LOG.debug("interceptor threw exception {}", this, x);
return _transformedContent;
}
}