Hello devs,
I have been using flow to control my pipelines for some kind of cms. I
use flow to control the pipelines by invoking the PipelineUtil class to
execute pipelines to an outputstream, which I then send to the client
via another pipeline and a reader.
In some cases, the called pipelines are returning different mime-types.
With the methods offered by PipelineUtil, I have no possibility to
retrieve the mime-type set by the serializer.
What I did is implement a processToStreamEx function that returns me the
mimetype as a String. I tried around and encoutered the following pitfalls:
1) The members in PipelineUtil are private, which makes it difficult to
extend this class.
2) The SitemapSource class is final, too.
3) Using SitemapSource, the mimeType was not set. I had to add the
marked line to getInputStream()
/**
* Return an <code>InputStream</code> object to read from the source.
*/
public InputStream getInputStream()
throws IOException, SourceException {
if (this.needsRefresh) {
this.refresh();
}
// VG: Why exception is not thrown in constructor?
if (this.exception != null) {
throw new SourceException("Cannot get input stream for " +
getURI(), this.exception);
}
if (this.redirectSource != null) {
return this.redirectSource.getInputStream();
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
this.environment.setOutputStream(os);
CocoonComponentManager.enterEnvironment(this.environment,
this.manager,
this.pipelineProcessor);
try {
this.processingPipeline.process(this.environment);
} finally {
CocoonComponentManager.leaveEnvironment();
}
---> this.mimeType = this.environment.getContentType();
return new ByteArrayInputStream(os.toByteArray());
} catch (ResourceNotFoundException e) {
throw new SourceNotFoundException("Exception during
processing of " + this.systemId, e);
} catch (Exception e) {
throw new SourceException("Exception during processing of "
+ this.systemId, e);
} finally {
// Unhide wrapped environment output stream
this.environment.setOutputStream(null);
this.needsRefresh = true;
}
}
4) To retrieve the mimetype, I made my own PipelineUtil function that
returns the mimetype
public String processToStreamEx(String uri, Object viewData,
OutputStream output)
throws IOException {
checkSetup();
Map objectModel = ContextHelper.getObjectModel(this.context);
// Keep the previous view data, if any (is it really necessary?),
and set the new one
Object oldViewData = FlowHelper.getContextObject(objectModel);
FlowHelper.setContextObject(objectModel,
JavaScriptFlowHelper.unwrap(viewData));
Source src = null;
InputStream input = null;
---> String mimetype = null;
try {
src = this.resolver.resolveURI("cocoon:/" + uri);
input = src.getInputStream();
---> mimetype = src.getMimeType();
IOUtils.copy(input, output);
---> return mimetype;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException ignored) {}
}
// Restore the previous view data
FlowHelper.setContextObject(objectModel, oldViewData);
if (src != null) {
this.resolver.release(src);
}
}
}
I am not submitting any patch as the solution is only a workaround.
Maybe it would be better to add a processToOutput method that expects a
PipelineOutput instead of an Outputstream. The PipelineOutput would
expect an OutputStream in the constructor, but add a getMimeType()
function? I'm sure you have more ideas on that...
What do you think?
Nils