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


Reply via email to